mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(moonshot): stop mutating caller messages on tool_choice='required' (#31060)
_add_tool_choice_required_message appended the "select a tool" prompt to the caller's messages list in place, so transform_request corrupted the caller's conversation history and appended a duplicate prompt on every retry. Build and return a new list instead so the call stays idempotent. Adds a regression test asserting the input messages list is unchanged across repeated transform_request calls. Co-authored-by: Wassbdr <wassim.badraoui07@gmail.com>
This commit is contained in:
parent
6893df16fb
commit
e71d6ef8ba
2 changed files with 33 additions and 5 deletions
|
|
@ -238,11 +238,11 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
|
||||
https://platform.moonshot.ai/docs/guide/migrating-from-openai-to-kimi#about-tool_choice
|
||||
"""
|
||||
messages.append(
|
||||
optional_params.pop("tool_choice")
|
||||
return [
|
||||
*messages,
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Please select a tool to handle the current issue.", # Usually, the Kimi large language model understands the intention to invoke a tool and selects one for invocation
|
||||
}
|
||||
)
|
||||
optional_params.pop("tool_choice")
|
||||
return messages
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -305,6 +305,34 @@ class TestMoonshotConfig:
|
|||
assert len(result["messages"]) == 2
|
||||
assert result["messages"][1]["content"] == "Please select a tool to handle the current issue."
|
||||
|
||||
def test_tool_choice_required_does_not_mutate_input_messages(self):
|
||||
"""tool_choice='required' must not mutate the caller's messages list.
|
||||
|
||||
The handling appends a "select a tool" user message; building it in
|
||||
place corrupts the caller's conversation history and makes
|
||||
transform_request non-idempotent across retries.
|
||||
"""
|
||||
config = MoonshotChatConfig()
|
||||
|
||||
messages = [{"role": "user", "content": "What's the weather like?"}]
|
||||
|
||||
for _ in range(2):
|
||||
optional_params = {
|
||||
"tool_choice": "required",
|
||||
"tools": [{"type": "function", "function": {"name": "get_weather"}}],
|
||||
}
|
||||
result = config.transform_request(
|
||||
model="moonshot-v1-8k",
|
||||
messages=messages,
|
||||
optional_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
# The returned request carries the extra message.
|
||||
assert len(result["messages"]) == 2
|
||||
# The caller's list is untouched, so repeated calls stay idempotent.
|
||||
assert messages == [{"role": "user", "content": "What's the weather like?"}]
|
||||
|
||||
def test_tool_choice_non_required_preserved(self):
|
||||
"""Test that non-'required' tool_choice values are preserved"""
|
||||
config = MoonshotChatConfig()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue