From 9ce5dede2c040a88af56b009e618a347df9818fb Mon Sep 17 00:00:00 2001 From: Praising Harris Ratnam Date: Sat, 17 Oct 2026 12:48:23 +0530 Subject: [PATCH] fix(cohere): map string stop parameter to list of strings for stop_sequences Fixes #46977: Cohere chat API reference expects stop_sequences to be a list of strings. Convert string stop parameter to a single-element list for CohereChatConfig and CohereV2ChatConfig while preserving lists. --- litellm/llms/cohere/chat/transformation.py | 2 +- litellm/llms/cohere/chat/v2_transformation.py | 2 +- .../cohere/chat/test_cohere_transformation.py | 40 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/litellm/llms/cohere/chat/transformation.py b/litellm/llms/cohere/chat/transformation.py index fdf44d5333e..ca32dc2989d 100644 --- a/litellm/llms/cohere/chat/transformation.py +++ b/litellm/llms/cohere/chat/transformation.py @@ -205,7 +205,7 @@ class CohereChatConfig(BaseConfig): if param == "presence_penalty": optional_params["presence_penalty"] = value if param == "stop": - optional_params["stop_sequences"] = value + optional_params["stop_sequences"] = [value] if isinstance(value, str) else value if param == "tools": optional_params["tools"] = value if param == "seed": diff --git a/litellm/llms/cohere/chat/v2_transformation.py b/litellm/llms/cohere/chat/v2_transformation.py index 41b1569bc4a..cf033e10b41 100644 --- a/litellm/llms/cohere/chat/v2_transformation.py +++ b/litellm/llms/cohere/chat/v2_transformation.py @@ -159,7 +159,7 @@ class CohereV2ChatConfig(OpenAIGPTConfig): if param == "presence_penalty": optional_params["presence_penalty"] = value if param == "stop": - optional_params["stop_sequences"] = value + optional_params["stop_sequences"] = [value] if isinstance(value, str) else value if param == "tools": optional_params["tools"] = value if param == "seed": diff --git a/tests/unit/llms/cohere/chat/test_cohere_transformation.py b/tests/unit/llms/cohere/chat/test_cohere_transformation.py index 087a5254ae0..8d39c301029 100644 --- a/tests/unit/llms/cohere/chat/test_cohere_transformation.py +++ b/tests/unit/llms/cohere/chat/test_cohere_transformation.py @@ -77,6 +77,26 @@ class TestCohereTransform: # The function should properly map max_tokens if max_completion_tokens is not provided assert result == {"temperature": 0.7, "max_tokens": 200} + def test_cohere_stop_string_to_list(self): + """Test that a string stop parameter is converted to a list of strings for stop_sequences""" + result = self.config.map_openai_params( + non_default_params={"stop": "END"}, + optional_params={}, + model=self.model, + drop_params=False, + ) + assert result == {"stop_sequences": ["END"]} + + def test_cohere_stop_list_preserved(self): + """Test that a list stop parameter is preserved as a list for stop_sequences""" + result = self.config.map_openai_params( + non_default_params={"stop": ["END", "STOP"]}, + optional_params={}, + model=self.model, + drop_params=False, + ) + assert result == {"stop_sequences": ["END", "STOP"]} + class TestCohereV2Transform: def setup_method(self): @@ -141,6 +161,26 @@ class TestCohereV2Transform: assert optional_params["max_tokens"] == 256 + def test_v2_stop_string_to_list(self): + """Test that a string stop parameter is converted to a list of strings for stop_sequences in v2""" + result = self.config.map_openai_params( + non_default_params={"stop": "END"}, + optional_params={}, + model=self.model, + drop_params=False, + ) + assert result == {"stop_sequences": ["END"]} + + def test_v2_stop_list_preserved(self): + """Test that a list stop parameter is preserved as a list for stop_sequences in v2""" + result = self.config.map_openai_params( + non_default_params={"stop": ["END", "STOP"]}, + optional_params={}, + model=self.model, + drop_params=False, + ) + assert result == {"stop_sequences": ["END", "STOP"]} + @pytest.mark.asyncio async def test_cohere_request_body_with_allowed_params():