diff --git a/libs/core/langchain_core/messages/block_translators/openai.py b/libs/core/langchain_core/messages/block_translators/openai.py index 86c201dcc405b..7f0b7ba799377 100644 --- a/libs/core/langchain_core/messages/block_translators/openai.py +++ b/libs/core/langchain_core/messages/block_translators/openai.py @@ -94,6 +94,15 @@ def convert_to_openai_data_block( if block.get("source_type") == "base64" or "base64" in block: # Handle v0 format (Base64CB): {"source_type": "base64", "data": "...", ...} # Handle v1 format (IDCB): {"base64": "...", ...} + if ( + api == "chat/completions" + and block.get("mime_type") != "application/pdf" + ): + error_msg = ( + "OpenAI Chat Completions only supports application/pdf for " + "file data blocks. Use Responses API for other file MIME types." + ) + raise ValueError(error_msg) base64_data = block["data"] if "source_type" in block else block["base64"] file = {"file_data": f"data:{block['mime_type']};base64,{base64_data}"} if filename := block.get("filename"): @@ -548,7 +557,7 @@ def _extract_extras( filename = block["file"].get("filename") return types.create_file_block( base64=parsed["data"], - mime_type="application/pdf", + mime_type=parsed["mime_type"], filename=filename, **all_extras, ) diff --git a/libs/core/tests/unit_tests/messages/block_translators/test_openai.py b/libs/core/tests/unit_tests/messages/block_translators/test_openai.py index b39b768993cda..f1ab7e79d2ed3 100644 --- a/libs/core/tests/unit_tests/messages/block_translators/test_openai.py +++ b/libs/core/tests/unit_tests/messages/block_translators/test_openai.py @@ -490,6 +490,16 @@ def test_convert_to_openai_data_block() -> None: result = convert_to_openai_data_block(block) assert result == expected + # File / base64 with non-PDF MIME (chat/completions) + block = { + "type": "file", + "base64": "", + "mime_type": "text/csv", + "filename": "test.csv", + } + with pytest.raises(ValueError, match="only supports application/pdf"): + convert_to_openai_data_block(block) + # Image / base64 block = { "type": "image", @@ -603,3 +613,39 @@ def test_convert_to_openai_data_block() -> None: expected = {"type": "input_file", "file_id": "file-abc123"} result = convert_to_openai_data_block(block, api="responses") assert result == expected + + +def test_convert_to_v1_file_block_preserves_non_pdf_mime_type() -> None: + message = HumanMessage( + content=[ + { + "type": "file", + "file": { + "filename": "sheet.csv", + "file_data": "data:text/csv;base64,aGVsbG8=", + }, + }, + { + "type": "file", + "file": { + "file_data": "data:text/plain;base64,aGVsbG8=", + }, + }, + ] + ) + + expected: list[types.ContentBlock] = [ + { + "type": "file", + "base64": "aGVsbG8=", + "mime_type": "text/csv", + "extras": {"filename": "sheet.csv"}, + }, + { + "type": "file", + "base64": "aGVsbG8=", + "mime_type": "text/plain", + }, + ] + + assert _content_blocks_equal_ignore_id(message.content_blocks, expected)