This commit is contained in:
Zang Peiyu 2026-08-27 16:58:34 -05:00 committed by GitHub
commit 08bb968d71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 1 deletions

View file

@ -253,6 +253,8 @@ class MistralConfig(OpenAIGPTConfig):
m = strip_none_values_from_message(m) # prevents 'extra_forbidden' error
new_messages.append(m)
new_messages = self._strip_extra_fields(new_messages)
if is_async:
return super()._transform_messages(new_messages, model, True)
else:
@ -266,7 +268,7 @@ class MistralConfig(OpenAIGPTConfig):
# and then apply Mistral-specific handling for files
messages = await super()._transform_messages(messages, model, True)
messages = self._handle_message_with_file(messages)
return messages
return self._strip_extra_fields(messages)
def _transform_messages_sync(self, messages: list[AllMessageValues], model: str) -> list[AllMessageValues]:
"""Handle modification of messages for Mistral API in a sync context."""
@ -275,6 +277,17 @@ class MistralConfig(OpenAIGPTConfig):
# This is the sync version of the async method above
messages = super()._transform_messages(messages, model, False)
messages = self._handle_message_with_file(messages)
return self._strip_extra_fields(messages)
@staticmethod
def _strip_extra_fields(messages: list[AllMessageValues]) -> list[AllMessageValues]:
for m in messages:
if isinstance(m, dict) and m.get("role") == "assistant":
m.pop("metadata", None)
m.pop("provider_specific_fields", None)
m.pop("thinking_blocks", None)
m.pop("cache_control", None)
m.pop("reasoning_content", None)
return messages
def _handle_message_with_file(self, messages: list[AllMessageValues]) -> list[AllMessageValues]:

View file

@ -245,6 +245,53 @@ class TestMistralReasoningSupport:
assert result == messages
assert len(result) == 1
def test_transform_messages_strips_extra_fields(self):
"""GH#30882: extra fields like metadata should be stripped
from messages before sending to Mistral API."""
mistral_config = MistralConfig()
messages: List[AllMessageValues] = [
cast(
AllMessageValues,
{
"role": "assistant",
"content": "hello",
"metadata": {
"tool_outputs_trimmed": True,
"trimmed_by": "async_context_compression",
},
"provider_specific_fields": {"foo": "bar"},
"thinking_blocks": [],
"cache_control": {"type": "ephemeral"},
"reasoning_content": "some thinking",
},
)
]
result = mistral_config._transform_messages(messages, "mistral/mistral-large-latest")
assert len(result) == 1
msg = cast(dict, result[0])
assert msg["role"] == "assistant"
assert msg["content"] == "hello"
assert "metadata" not in msg
assert "provider_specific_fields" not in msg
assert "thinking_blocks" not in msg
assert "cache_control" not in msg
assert "reasoning_content" not in msg
def test_user_message_extra_fields_are_preserved(self):
"""GH#30882: user messages should not be stripped of extra fields."""
mistral_config = MistralConfig()
messages: List[AllMessageValues] = [
cast(
AllMessageValues,
{"role": "user", "content": "Question?", "reasoning_content": "noise"},
)
]
result = mistral_config._transform_messages(messages, "mistral/mistral-large-latest")
assert len(result) == 1
msg = cast(dict, result[0])
assert msg["role"] == "user"
assert msg["reasoning_content"] == "noise"
def test_transform_request_magistral_with_reasoning(self):
"""Test transform_request method for magistral model with reasoning."""
mistral_config = MistralConfig()