From bee41c19610cd35c5663e176e0fe1459e6bd80f3 Mon Sep 17 00:00:00 2001 From: Cole McIntosh Date: Thu, 12 Jun 2025 11:17:48 -0600 Subject: [PATCH] Update Mistral documentation and enhance reasoning prompt handling - Revised the reasoning support indicators in the Mistral model documentation for clarity. - Improved the `_add_reasoning_system_prompt_if_needed` method to handle both string and list content types for system messages, ensuring the reasoning prompt is correctly prepended. - Added a new test case to verify the functionality of adding the reasoning system prompt when the existing content is a list. --- docs/my-website/docs/providers/mistral.md | 28 +++++++-------- .../mistral/mistral_chat_transformation.py | 16 ++++++++- .../test_mistral_chat_transformation.py | 36 +++++++++++++++++++ 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/docs/my-website/docs/providers/mistral.md b/docs/my-website/docs/providers/mistral.md index b14206a711..d9e12e4bcf 100644 --- a/docs/my-website/docs/providers/mistral.md +++ b/docs/my-website/docs/providers/mistral.md @@ -146,20 +146,20 @@ All models listed here https://docs.mistral.ai/platform/endpoints are supported. | Model Name | Function Call | Reasoning Support | |----------------|--------------------------------------------------------------|-------------------| -| Mistral Small | `completion(model="mistral/mistral-small-latest", messages)` | ❌ | -| Mistral Medium | `completion(model="mistral/mistral-medium-latest", messages)`| ❌ | -| Mistral Large 2 | `completion(model="mistral/mistral-large-2407", messages)` | ❌ | -| Mistral Large Latest | `completion(model="mistral/mistral-large-latest", messages)` | ❌ | -| **Magistral Small** | `completion(model="mistral/magistral-small-2506", messages)` | ✅ | -| **Magistral Medium** | `completion(model="mistral/magistral-medium-2506", messages)`| ✅ | -| Mistral 7B | `completion(model="mistral/open-mistral-7b", messages)` | ❌ | -| Mixtral 8x7B | `completion(model="mistral/open-mixtral-8x7b", messages)` | ❌ | -| Mixtral 8x22B | `completion(model="mistral/open-mixtral-8x22b", messages)` | ❌ | -| Codestral | `completion(model="mistral/codestral-latest", messages)` | ❌ | -| Mistral NeMo | `completion(model="mistral/open-mistral-nemo", messages)` | ❌ | -| Mistral NeMo 2407 | `completion(model="mistral/open-mistral-nemo-2407", messages)` | ❌ | -| Codestral Mamba | `completion(model="mistral/open-codestral-mamba", messages)` | ❌ | -| Codestral Mamba | `completion(model="mistral/codestral-mamba-latest"", messages)` | ❌ | +| Mistral Small | `completion(model="mistral/mistral-small-latest", messages)` | No | +| Mistral Medium | `completion(model="mistral/mistral-medium-latest", messages)`| No | +| Mistral Large 2 | `completion(model="mistral/mistral-large-2407", messages)` | No | +| Mistral Large Latest | `completion(model="mistral/mistral-large-latest", messages)` | No | +| **Magistral Small** | `completion(model="mistral/magistral-small-2506", messages)` | Yes | +| **Magistral Medium** | `completion(model="mistral/magistral-medium-2506", messages)`| Yes | +| Mistral 7B | `completion(model="mistral/open-mistral-7b", messages)` | No | +| Mixtral 8x7B | `completion(model="mistral/open-mixtral-8x7b", messages)` | No | +| Mixtral 8x22B | `completion(model="mistral/open-mixtral-8x22b", messages)` | No | +| Codestral | `completion(model="mistral/codestral-latest", messages)` | No | +| Mistral NeMo | `completion(model="mistral/open-mistral-nemo", messages)` | No | +| Mistral NeMo 2407 | `completion(model="mistral/open-mistral-nemo-2407", messages)` | No | +| Codestral Mamba | `completion(model="mistral/open-codestral-mamba", messages)` | No | +| Codestral Mamba | `completion(model="mistral/codestral-mamba-latest"", messages)` | No | ## Function Calling diff --git a/litellm/llms/mistral/mistral_chat_transformation.py b/litellm/llms/mistral/mistral_chat_transformation.py index b886e3cc96..8fc8b93c79 100644 --- a/litellm/llms/mistral/mistral_chat_transformation.py +++ b/litellm/llms/mistral/mistral_chat_transformation.py @@ -251,9 +251,23 @@ Then provide a clear, concise answer based on your reasoning.""" if msg.get("role") == "system": existing_content = msg.get("content", "") reasoning_prompt = self._get_mistral_reasoning_system_prompt() + + # Handle both string and list content + if isinstance(existing_content, str): + # String content - prepend reasoning prompt + new_content = f"{reasoning_prompt}\n\n{existing_content}" + elif isinstance(existing_content, list): + # List content - prepend reasoning prompt as text block + new_content = [ + {"type": "text", "text": reasoning_prompt + "\n\n"} + ] + existing_content + else: + # Fallback for any other type - convert to string + new_content = f"{reasoning_prompt}\n\n{str(existing_content)}" + messages[i] = cast(AllMessageValues, { **msg, - "content": f"{reasoning_prompt}\n\n{existing_content}" + "content": new_content }) break else: diff --git a/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py b/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py index 96a5671cb3..390de07d73 100644 --- a/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py +++ b/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py @@ -145,6 +145,42 @@ class TestMistralReasoningSupport: # Should remove the internal flag assert "_add_reasoning_prompt" not in optional_params + def test_add_reasoning_system_prompt_with_existing_list_content(self): + """Test adding reasoning system prompt when system message has list content.""" + mistral_config = MistralConfig() + + messages = [ + { + "role": "system", + "content": [ + {"type": "text", "text": "You are a helpful assistant."}, + {"type": "text", "text": "You always provide detailed explanations."} + ] + }, + {"role": "user", "content": "What is 2+2?"} + ] + optional_params = {"_add_reasoning_prompt": True} + + result = mistral_config._add_reasoning_system_prompt_if_needed(messages, optional_params) + + # Should modify existing system message with list content + assert len(result) == 2 + assert result[0]["role"] == "system" + assert isinstance(result[0]["content"], list) + + # First item should be the reasoning prompt + assert result[0]["content"][0]["type"] == "text" + assert "" in result[0]["content"][0]["text"] + + # Original content should be preserved + assert "You are a helpful assistant." in result[0]["content"][1]["text"] + assert "You always provide detailed explanations." in result[0]["content"][2]["text"] + + assert result[1]["role"] == "user" + + # Should remove the internal flag + assert "_add_reasoning_prompt" not in optional_params + def test_add_reasoning_system_prompt_no_flag(self): """Test that no modification happens when _add_reasoning_prompt flag is not set.""" mistral_config = MistralConfig()