Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions litellm/llms/moonshot/chat/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,11 @@ def _add_tool_choice_required_message(

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
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,34 @@ def test_tool_choice_required_preserves_other_params(self):
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()
Expand Down
Loading