diff --git a/lib/crewai/src/crewai/llms/providers/gemini/completion.py b/lib/crewai/src/crewai/llms/providers/gemini/completion.py index 98edc1238..68fc9d4d7 100644 --- a/lib/crewai/src/crewai/llms/providers/gemini/completion.py +++ b/lib/crewai/src/crewai/llms/providers/gemini/completion.py @@ -599,6 +599,14 @@ class GeminiCompletion(BaseLLM): mime_type=inline["mimeType"], ) ) + elif "fileData" in item: + file_data = item["fileData"] + parts.append( + types.Part.from_uri( + file_uri=file_data["fileUri"], + mime_type=file_data["mimeType"], + ) + ) else: parts.append(types.Part.from_text(text=str(item))) else: diff --git a/lib/crewai/tests/llms/google/test_google.py b/lib/crewai/tests/llms/google/test_google.py index 48c9f3224..17b0b2700 100644 --- a/lib/crewai/tests/llms/google/test_google.py +++ b/lib/crewai/tests/llms/google/test_google.py @@ -500,6 +500,71 @@ def test_gemini_message_formatting(): assert formatted_contents[1].role == "model" +@pytest.mark.parametrize( + "file_uri", + [ + "https://storage.googleapis.com/example/image.jpg", + "gs://example-bucket/image.jpg", + ], +) +def test_gemini_message_formatting_preserves_file_data(file_uri): + """Test that Gemini file references are preserved in their original order.""" + llm = LLM(model="google/gemini-2.0-flash-001") + + formatted_contents, _ = llm._format_messages_for_gemini( + [ + { + "role": "user", + "content": [ + {"text": "Before"}, + { + "fileData": { + "fileUri": file_uri, + "mimeType": "image/jpeg", + } + }, + {"text": "After"}, + ], + } + ] + ) + + parts = formatted_contents[0].parts + assert parts[0].text == "Before" + assert parts[1].file_data is not None + assert parts[1].file_data.file_uri == file_uri + assert parts[1].file_data.mime_type == "image/jpeg" + assert parts[2].text == "After" + + +def test_gemini_message_formatting_preserves_file_data_without_text(): + """Test that a message containing only a file reference is preserved.""" + llm = LLM(model="google/gemini-2.0-flash-001") + file_uri = "gs://example-bucket/image.jpg" + + formatted_contents, _ = llm._format_messages_for_gemini( + [ + { + "role": "user", + "content": [ + { + "fileData": { + "fileUri": file_uri, + "mimeType": "image/jpeg", + } + } + ], + } + ] + ) + + parts = formatted_contents[0].parts + assert len(parts) == 1 + assert parts[0].file_data is not None + assert parts[0].file_data.file_uri == file_uri + assert parts[0].file_data.mime_type == "image/jpeg" + + def test_gemini_message_formatting_appends_user_turn_after_trailing_model_turn(): """ Gemini's generateContent API rejects a request whose history ends on a