mirror of
https://github.com/hwchase17/langchain.git
synced 2026-07-13 20:47:15 +00:00
feat(core): support google maps grounding in genai block translator (#34244)
https://github.com/langchain-ai/langchain-google/pull/1330 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -76,21 +76,36 @@ def translate_grounding_metadata_to_citations(
|
||||
for chunk_index in chunk_indices:
|
||||
if chunk_index < len(grounding_chunks):
|
||||
chunk = grounding_chunks[chunk_index]
|
||||
web_info = chunk.get("web", {})
|
||||
|
||||
# Handle web and maps grounding
|
||||
web_info = chunk.get("web") or {}
|
||||
maps_info = chunk.get("maps") or {}
|
||||
|
||||
# Extract citation info depending on source
|
||||
url = maps_info.get("uri") or web_info.get("uri")
|
||||
title = maps_info.get("title") or web_info.get("title")
|
||||
|
||||
# Note: confidence_scores is a legacy field from Gemini 2.0 and earlier
|
||||
# that indicated confidence (0.0-1.0) for each grounding chunk.
|
||||
#
|
||||
# In Gemini 2.5+, this field is always None/empty and should be ignored.
|
||||
extras_metadata = {
|
||||
"web_search_queries": web_search_queries,
|
||||
"grounding_chunk_index": chunk_index,
|
||||
"confidence_scores": support.get("confidence_scores") or [],
|
||||
}
|
||||
|
||||
# Add maps-specific metadata if present
|
||||
if maps_info.get("placeId"):
|
||||
extras_metadata["place_id"] = maps_info["placeId"]
|
||||
|
||||
citation = create_citation(
|
||||
url=web_info.get("uri"),
|
||||
title=web_info.get("title"),
|
||||
url=url,
|
||||
title=title,
|
||||
start_index=start_index,
|
||||
end_index=end_index,
|
||||
cited_text=cited_text,
|
||||
extras={
|
||||
"google_ai_metadata": {
|
||||
"web_search_queries": web_search_queries,
|
||||
"grounding_chunk_index": chunk_index,
|
||||
"confidence_scores": support.get("confidence_scores", []),
|
||||
}
|
||||
},
|
||||
google_ai_metadata=extras_metadata,
|
||||
)
|
||||
citations.append(citation)
|
||||
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
"""Tests for Google GenAI block translator."""
|
||||
|
||||
from langchain_core.messages.block_translators.google_genai import (
|
||||
translate_grounding_metadata_to_citations,
|
||||
)
|
||||
|
||||
|
||||
def test_translate_grounding_metadata_web() -> None:
|
||||
"""Test translation of web grounding metadata to citations."""
|
||||
grounding_metadata = {
|
||||
"grounding_chunks": [
|
||||
{
|
||||
"web": {
|
||||
"uri": "https://example.com",
|
||||
"title": "Example Site",
|
||||
},
|
||||
"maps": None,
|
||||
}
|
||||
],
|
||||
"grounding_supports": [
|
||||
{
|
||||
"segment": {
|
||||
"start_index": 0,
|
||||
"end_index": 13,
|
||||
"text": "Test response",
|
||||
},
|
||||
"grounding_chunk_indices": [0],
|
||||
"confidence_scores": [],
|
||||
}
|
||||
],
|
||||
"web_search_queries": ["test query"],
|
||||
}
|
||||
|
||||
citations = translate_grounding_metadata_to_citations(grounding_metadata)
|
||||
|
||||
assert len(citations) == 1
|
||||
citation = citations[0]
|
||||
assert citation["type"] == "citation"
|
||||
assert citation.get("url") == "https://example.com"
|
||||
assert citation.get("title") == "Example Site"
|
||||
assert citation.get("start_index") == 0
|
||||
assert citation.get("end_index") == 13
|
||||
assert citation.get("cited_text") == "Test response"
|
||||
|
||||
extras = citation.get("extras", {})["google_ai_metadata"]
|
||||
assert extras["web_search_queries"] == ["test query"]
|
||||
assert extras["grounding_chunk_index"] == 0
|
||||
assert "place_id" not in extras
|
||||
|
||||
|
||||
def test_translate_grounding_metadata_maps() -> None:
|
||||
"""Test translation of maps grounding metadata to citations."""
|
||||
grounding_metadata = {
|
||||
"grounding_chunks": [
|
||||
{
|
||||
"web": None,
|
||||
"maps": {
|
||||
"uri": "https://maps.google.com/?cid=13100894621228039586",
|
||||
"title": "Heaven on 7th Marketplace",
|
||||
"placeId": "places/ChIJ0-zA1vBZwokRon0fGj-6z7U",
|
||||
},
|
||||
}
|
||||
],
|
||||
"grounding_supports": [
|
||||
{
|
||||
"segment": {
|
||||
"start_index": 0,
|
||||
"end_index": 25,
|
||||
"text": "Great Italian restaurant",
|
||||
},
|
||||
"grounding_chunk_indices": [0],
|
||||
"confidence_scores": [0.95],
|
||||
}
|
||||
],
|
||||
"web_search_queries": [],
|
||||
}
|
||||
|
||||
citations = translate_grounding_metadata_to_citations(grounding_metadata)
|
||||
|
||||
assert len(citations) == 1
|
||||
citation = citations[0]
|
||||
assert citation["type"] == "citation"
|
||||
assert citation.get("url") == "https://maps.google.com/?cid=13100894621228039586"
|
||||
assert citation.get("title") == "Heaven on 7th Marketplace"
|
||||
assert citation.get("start_index") == 0
|
||||
assert citation.get("end_index") == 25
|
||||
assert citation.get("cited_text") == "Great Italian restaurant"
|
||||
|
||||
extras = citation.get("extras", {})["google_ai_metadata"]
|
||||
assert extras["web_search_queries"] == []
|
||||
assert extras["grounding_chunk_index"] == 0
|
||||
assert extras["confidence_scores"] == [0.95]
|
||||
assert extras["place_id"] == "places/ChIJ0-zA1vBZwokRon0fGj-6z7U"
|
||||
|
||||
|
||||
def test_translate_grounding_metadata_none() -> None:
|
||||
"""Test translation when both web and maps are None."""
|
||||
grounding_metadata = {
|
||||
"grounding_chunks": [
|
||||
{
|
||||
"web": None,
|
||||
"maps": None,
|
||||
}
|
||||
],
|
||||
"grounding_supports": [
|
||||
{
|
||||
"segment": {
|
||||
"start_index": 0,
|
||||
"end_index": 10,
|
||||
"text": "test text",
|
||||
},
|
||||
"grounding_chunk_indices": [0],
|
||||
"confidence_scores": [],
|
||||
}
|
||||
],
|
||||
"web_search_queries": [],
|
||||
}
|
||||
|
||||
citations = translate_grounding_metadata_to_citations(grounding_metadata)
|
||||
|
||||
# Should still create citation but without url/title fields when None
|
||||
assert len(citations) == 1
|
||||
citation = citations[0]
|
||||
assert citation["type"] == "citation"
|
||||
# url and title are omitted when None
|
||||
assert "url" not in citation
|
||||
assert "title" not in citation
|
||||
assert citation.get("start_index") == 0
|
||||
assert citation.get("end_index") == 10
|
||||
assert citation.get("cited_text") == "test text"
|
||||
|
||||
|
||||
def test_translate_grounding_metadata_confidence_scores_none() -> None:
|
||||
"""Test translation when confidence_scores is None (API returns this)."""
|
||||
grounding_metadata = {
|
||||
"grounding_chunks": [
|
||||
{
|
||||
"web": None,
|
||||
"maps": {
|
||||
"uri": "https://maps.google.com/?cid=123",
|
||||
"title": "Test Restaurant",
|
||||
"placeId": "places/ChIJ123",
|
||||
},
|
||||
}
|
||||
],
|
||||
"grounding_supports": [
|
||||
{
|
||||
"segment": {
|
||||
"start_index": 0,
|
||||
"end_index": 10,
|
||||
"text": "test text",
|
||||
},
|
||||
"grounding_chunk_indices": [0],
|
||||
"confidence_scores": None, # API returns None, not []
|
||||
}
|
||||
],
|
||||
"web_search_queries": ["test query"],
|
||||
}
|
||||
|
||||
citations = translate_grounding_metadata_to_citations(grounding_metadata)
|
||||
|
||||
assert len(citations) == 1
|
||||
extras = citations[0].get("extras", {})["google_ai_metadata"]
|
||||
# Should convert None to empty list
|
||||
assert extras["confidence_scores"] == []
|
||||
assert isinstance(extras["confidence_scores"], list)
|
||||
|
||||
|
||||
def test_translate_grounding_metadata_multiple_chunks() -> None:
|
||||
"""Test translation with multiple grounding chunks."""
|
||||
grounding_metadata = {
|
||||
"grounding_chunks": [
|
||||
{
|
||||
"web": {
|
||||
"uri": "https://example1.com",
|
||||
"title": "Example 1",
|
||||
},
|
||||
"maps": None,
|
||||
},
|
||||
{
|
||||
"web": None,
|
||||
"maps": {
|
||||
"uri": "https://maps.google.com/?cid=123",
|
||||
"title": "Place 1",
|
||||
"placeId": "places/123",
|
||||
},
|
||||
},
|
||||
],
|
||||
"grounding_supports": [
|
||||
{
|
||||
"segment": {
|
||||
"start_index": 0,
|
||||
"end_index": 10,
|
||||
"text": "First part",
|
||||
},
|
||||
"grounding_chunk_indices": [0, 1],
|
||||
"confidence_scores": [],
|
||||
}
|
||||
],
|
||||
"web_search_queries": [],
|
||||
}
|
||||
|
||||
citations = translate_grounding_metadata_to_citations(grounding_metadata)
|
||||
|
||||
# Should create two citations, one for each chunk
|
||||
assert len(citations) == 2
|
||||
|
||||
# First citation from web chunk
|
||||
assert citations[0].get("url") == "https://example1.com"
|
||||
assert citations[0].get("title") == "Example 1"
|
||||
assert "place_id" not in citations[0].get("extras", {})["google_ai_metadata"]
|
||||
|
||||
# Second citation from maps chunk
|
||||
assert citations[1].get("url") == "https://maps.google.com/?cid=123"
|
||||
assert citations[1].get("title") == "Place 1"
|
||||
assert (
|
||||
citations[1].get("extras", {})["google_ai_metadata"]["place_id"] == "places/123"
|
||||
)
|
||||
Reference in New Issue
Block a user