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:
Mason Daugherty
2025-12-08 09:44:43 -05:00
committed by GitHub
parent b5efafe80c
commit 9875ffbabc
2 changed files with 243 additions and 10 deletions

View File

@@ -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)

View File

@@ -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"
)