From 11e4ec00f7c2efd55f9d1d352af08fc0916d5590 Mon Sep 17 00:00:00 2001 From: Chesars Date: Sun, 22 Mar 2026 01:37:18 -0300 Subject: [PATCH] fix: resolve file refs in nested lists, only flag truly multimodal nested inputs --- .../batch_embed_content_handler.py | 28 ++++++++++++------- .../batch_embed_content_transformation.py | 8 ++++-- ...test_batch_embed_content_transformation.py | 5 ++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py index efd77f5916c..75923fb38e8 100644 --- a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py +++ b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py @@ -215,18 +215,22 @@ class GoogleBatchEmbeddings(VertexLLM): ) else: input_list = [input] if isinstance(input, str) else input - has_file_refs = any( - _is_file_reference(e) for e in input_list if isinstance(e, str) - ) + flat_elements = [ + e + for item in input_list + for e in (item if isinstance(item, list) else [item]) + if isinstance(e, str) + ] + has_file_refs = any(_is_file_reference(e) for e in flat_elements) if has_file_refs and not api_key: raise ValueError( "An API key is required to resolve Gemini file references (files/...). " "Pass api_key= or set GEMINI_API_KEY." ) resolved_files = {} - if api_key and _is_multimodal_input(input): + if api_key and has_file_refs: resolved_files = self._resolve_file_references( - input=input, api_key=api_key, sync_handler=sync_handler + input=flat_elements, api_key=api_key, sync_handler=sync_handler ) request_data = transform_openai_input_gemini_content( input=input, @@ -320,18 +324,22 @@ class GoogleBatchEmbeddings(VertexLLM): ) else: input_list = [input] if isinstance(input, str) else input - has_file_refs = any( - _is_file_reference(e) for e in input_list if isinstance(e, str) - ) + flat_elements = [ + e + for item in input_list + for e in (item if isinstance(item, list) else [item]) + if isinstance(e, str) + ] + has_file_refs = any(_is_file_reference(e) for e in flat_elements) if has_file_refs and not api_key: raise ValueError( "An API key is required to resolve Gemini file references (files/...). " "Pass api_key= or set GEMINI_API_KEY." ) resolved_files = {} - if api_key and _is_multimodal_input(input): + if api_key and has_file_refs: resolved_files = await self._async_resolve_file_references( - input=input, api_key=api_key, async_handler=async_handler + input=flat_elements, api_key=api_key, async_handler=async_handler ) data = transform_openai_input_gemini_content( input=input, diff --git a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py index 60b6a1a33ef..6e47915b862 100644 --- a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py +++ b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py @@ -130,8 +130,9 @@ def _is_multimodal_input(input: EmbeddingInput) -> bool: for element in input: if isinstance(element, list): - return True - if isinstance(element, str) and _is_multimodal_element(element): + if any(_is_multimodal_element(sub) for sub in element if isinstance(sub, str)): + return True + elif isinstance(element, str) and _is_multimodal_element(element): return True return False @@ -350,7 +351,8 @@ def process_response( model_response.data = openai_embeddings model_response.model = model - if _is_multimodal_input(input): + has_nested = isinstance(input, list) and any(isinstance(e, list) for e in input) + if _is_multimodal_input(input) or has_nested: input_list = input if isinstance(input, list) else [input] text_elements = [] for e in input_list: diff --git a/tests/test_litellm/llms/vertex_ai/gemini_embeddings/test_batch_embed_content_transformation.py b/tests/test_litellm/llms/vertex_ai/gemini_embeddings/test_batch_embed_content_transformation.py index 9ba6e04744a..ec27824e2ba 100644 --- a/tests/test_litellm/llms/vertex_ai/gemini_embeddings/test_batch_embed_content_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/gemini_embeddings/test_batch_embed_content_transformation.py @@ -44,8 +44,9 @@ class TestIsMultimodalInput: def test_mixed_text_and_image(self): assert _is_multimodal_input(["hello", IMAGE_DATA_URI]) is True - def test_nested_list_is_multimodal(self): - assert _is_multimodal_input([["text_a", "text_b"]]) is True + def test_nested_text_only_is_not_multimodal(self): + """Nested list with only text is not multimodal.""" + assert _is_multimodal_input([["text_a", "text_b"]]) is False def test_nested_list_with_image_is_multimodal(self): assert _is_multimodal_input([["a red shoe", IMAGE_DATA_URI]]) is True