diff --git a/litellm/llms/cohere/chat/v2_transformation.py b/litellm/llms/cohere/chat/v2_transformation.py index c499dea2456..bbf2787244b 100644 --- a/litellm/llms/cohere/chat/v2_transformation.py +++ b/litellm/llms/cohere/chat/v2_transformation.py @@ -182,14 +182,14 @@ class CohereV2ChatConfig(OpenAIGPTConfig): sanitized: List[AllMessageValues] = [] for message in data.get("messages", []): if hasattr(message, "model_dump"): - message = message.model_dump(exclude_none=True) + message = message.model_dump(exclude_unset=True) if isinstance(message, dict): role = message.get("role") if role == "assistant" and message.get("tool_calls"): cleaned_tool_calls = [ {k: v for k, v in tc.items() if k != "index"} if isinstance(tc, dict) - else {k: v for k, v in tc.model_dump(exclude_none=True).items() if k != "index"} + else {k: v for k, v in tc.model_dump(exclude_unset=True).items() if k != "index"} for tc in message["tool_calls"] ] message = {**message, "tool_calls": cleaned_tool_calls} diff --git a/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py b/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py index 70826fe4a58..78960f41090 100644 --- a/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py +++ b/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py @@ -8,6 +8,7 @@ sys.path.insert( from litellm.llms.cohere.chat.transformation import CohereChatConfig from litellm.llms.cohere.chat.v2_transformation import CohereV2ChatConfig +from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig class TestCohereTransform: @@ -59,7 +60,7 @@ class TestCohereV2Transform: def _make_transform_request(self, messages): with patch.object( - self.config.__class__.__bases__[0], + OpenAIGPTConfig, "transform_request", return_value={"model": self.model, "messages": messages}, ): @@ -110,6 +111,29 @@ class TestCohereV2Transform: assert tool_msg["tool_call_id"] == "call_abc" assert tool_msg["content"] == "12:00" + def test_strips_index_from_pydantic_tool_calls(self): + """Pydantic model tool call objects also have index stripped.""" + from litellm.types.utils import ChatCompletionMessageToolCall, Function + + tool_call_obj = ChatCompletionMessageToolCall( + index=0, + id="call_abc", + type="function", + function=Function(name="get_time", arguments="{}"), + ) + messages = [ + {"role": "user", "content": "What time is it?"}, + { + "role": "assistant", + "content": None, + "tool_calls": [tool_call_obj], + }, + ] + result = self._make_transform_request(messages) + assistant_msg = result["messages"][1] + assert "index" not in assistant_msg["tool_calls"][0] + assert assistant_msg["tool_calls"][0]["id"] == "call_abc" + def test_preserves_messages_without_offending_fields(self): """Messages that don't have index or name are passed through unchanged.""" messages = [