From 7829b722b1570c8e47a5cdf3bb730d965c673afe Mon Sep 17 00:00:00 2001 From: Nhan Nguyen Date: Fri, 12 Dec 2025 13:18:56 -0500 Subject: [PATCH] fix(mistralai): handle null content in tool call responses (#34268) --- .../langchain_mistralai/chat_models.py | 3 +- .../tests/unit_tests/test_chat_models.py | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/libs/partners/mistralai/langchain_mistralai/chat_models.py b/libs/partners/mistralai/langchain_mistralai/chat_models.py index 3a2681d7bc1..a5f8b3a60ce 100644 --- a/libs/partners/mistralai/langchain_mistralai/chat_models.py +++ b/libs/partners/mistralai/langchain_mistralai/chat_models.py @@ -148,7 +148,8 @@ def _convert_mistral_chat_message_to_message( if role != "assistant": msg = f"Expected role to be 'assistant', got {role}" raise ValueError(msg) - content = cast("str", _message["content"]) + # Mistral returns None for tool invocations + content = _message.get("content", "") or "" additional_kwargs: dict = {} tool_calls = [] diff --git a/libs/partners/mistralai/tests/unit_tests/test_chat_models.py b/libs/partners/mistralai/tests/unit_tests/test_chat_models.py index d3c2754449b..a28bccab8f0 100644 --- a/libs/partners/mistralai/tests/unit_tests/test_chat_models.py +++ b/libs/partners/mistralai/tests/unit_tests/test_chat_models.py @@ -238,6 +238,58 @@ def test__convert_dict_to_message_tool_call() -> None: assert _convert_message_to_mistral_chat_message(expected_output) == message +def test__convert_dict_to_message_tool_call_with_null_content() -> None: + raw_tool_call = { + "id": "ssAbar4Dr", + "function": { + "arguments": '{"name": "Sally", "hair_color": "green"}', + "name": "GenerateUsername", + }, + } + message = {"role": "assistant", "content": None, "tool_calls": [raw_tool_call]} + result = _convert_mistral_chat_message_to_message(message) + expected_output = AIMessage( + content="", + additional_kwargs={"tool_calls": [raw_tool_call]}, + tool_calls=[ + ToolCall( + name="GenerateUsername", + args={"name": "Sally", "hair_color": "green"}, + id="ssAbar4Dr", + type="tool_call", + ) + ], + response_metadata={"model_provider": "mistralai"}, + ) + assert result == expected_output + + +def test__convert_dict_to_message_with_missing_content() -> None: + raw_tool_call = { + "id": "ssAbar4Dr", + "function": { + "arguments": '{"query": "test search"}', + "name": "search", + }, + } + message = {"role": "assistant", "tool_calls": [raw_tool_call]} + result = _convert_mistral_chat_message_to_message(message) + expected_output = AIMessage( + content="", + additional_kwargs={"tool_calls": [raw_tool_call]}, + tool_calls=[ + ToolCall( + name="search", + args={"query": "test search"}, + id="ssAbar4Dr", + type="tool_call", + ) + ], + response_metadata={"model_provider": "mistralai"}, + ) + assert result == expected_output + + def test_custom_token_counting() -> None: def token_encoder(text: str) -> list[int]: return [1, 2, 3]