diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index 9acbc9c459c..f27593dc94e 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -2743,10 +2743,10 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): chunk_indices = support.get("groundingChunkIndices", []) if start_index is not None and end_index is not None and chunk_indices: - # Use the first chunk's URL for the annotation - first_chunk_idx = chunk_indices[0] - if first_chunk_idx in chunk_to_uri_map: - uri_info = chunk_to_uri_map[first_chunk_idx] + for chunk_index in chunk_indices: + if chunk_index not in chunk_to_uri_map: + continue + uri_info = chunk_to_uri_map[chunk_index] url_citation: ChatCompletionAnnotationURLCitation = { "start_index": start_index, diff --git a/tests/unit/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py b/tests/unit/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py index 065d894e658..1546d1e9fe0 100644 --- a/tests/unit/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py +++ b/tests/unit/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py @@ -10655,3 +10655,34 @@ async def test_gemini_sends_a_boolean_for_a_gateway_default_written_as_text_or_n sent: Final = await _sent_thinking_config("gemini-3.8-flash", {"reasoning_effort": "high"}) assert sent["includeThoughts"] is expected + + +@pytest.mark.parametrize("chunk_indices", [[0, 1], [2, 1, 0]]) +def test_grounding_support_preserves_every_web_source(chunk_indices: list[int]) -> None: + metadata: Final = { + "groundingChunks": [ + {"web": {"uri": "https://example.com/a", "title": "A"}}, + {"web": {"uri": "https://example.com/b", "title": "B"}}, + {"retrievedContext": {"uri": "gs://document"}}, + ], + "groundingSupports": [ + {"segment": {"startIndex": 0, "endIndex": 5}, "groundingChunkIndices": chunk_indices}, + {"segment": {"startIndex": 6, "endIndex": 11}, "groundingChunkIndices": [1]}, + ], + } + + annotations: Final = VertexGeminiConfig._convert_grounding_metadata_to_annotations([metadata], "First claim") + + expected_sources: Final = [(index, 0, 5) for index in chunk_indices if index in (0, 1)] + [(1, 6, 11)] + assert annotations == [ + { + "type": "url_citation", + "url_citation": { + "start_index": start, + "end_index": end, + "url": metadata["groundingChunks"][index]["web"]["uri"], + "title": metadata["groundingChunks"][index]["web"]["title"], + }, + } + for index, start, end in expected_sources + ]