diff --git a/litellm/llms/ollama/chat/transformation.py b/litellm/llms/ollama/chat/transformation.py index f9e7071db41..c36ce925eab 100644 --- a/litellm/llms/ollama/chat/transformation.py +++ b/litellm/llms/ollama/chat/transformation.py @@ -164,8 +164,8 @@ class OllamaChatConfig(BaseConfig): optional_params["top_p"] = value if param == "frequency_penalty": optional_params["repeat_penalty"] = value - if param == "stop": - optional_params["stop"] = value + if param == "stop" and value != "": + optional_params["stop"] = [value] if isinstance(value, str) else value if param == "response_format" and isinstance(value, dict) and value.get("type") == "json_object": optional_params["format"] = "json" if param == "response_format" and isinstance(value, dict) and value.get("type") == "json_schema": diff --git a/litellm/llms/ollama/completion/transformation.py b/litellm/llms/ollama/completion/transformation.py index 239b4e32645..76af839bb00 100644 --- a/litellm/llms/ollama/completion/transformation.py +++ b/litellm/llms/ollama/completion/transformation.py @@ -246,8 +246,8 @@ class OllamaConfig(BaseConfig): optional_params["top_p"] = value elif param == "frequency_penalty": optional_params["frequency_penalty"] = value - elif param == "stop": - optional_params["stop"] = value + elif param == "stop" and value != "": + optional_params["stop"] = [value] if isinstance(value, str) else value elif param == "reasoning_effort" and value is not None: if model.startswith("gpt-oss"): optional_params["think"] = value diff --git a/tests/unit/llms/ollama/test_ollama_chat_transformation.py b/tests/unit/llms/ollama/test_ollama_chat_transformation.py index df9f5fd9d14..6f132947d9a 100644 --- a/tests/unit/llms/ollama/test_ollama_chat_transformation.py +++ b/tests/unit/llms/ollama/test_ollama_chat_transformation.py @@ -27,6 +27,26 @@ from litellm.types.utils import Choices, EmbeddingResponse, Message, ModelRespon from unittest import mock +@pytest.mark.parametrize( + "stop, expected", + [ + ("END", ["END"]), + ("", None), + (["END", "STOP"], ["END", "STOP"]), + ([""], [""]), + ([], []), + ], +) +def test_stop_is_sent_as_an_array(stop: str | list[str], expected: list[str] | None) -> None: + optional_params: Final = get_optional_params( + model="test-model", custom_llm_provider="ollama_chat", stop=stop + ) + if expected is None: + assert "stop" not in optional_params + else: + assert optional_params["stop"] == expected + + class TestEvent(BaseModel): name: str value: int diff --git a/tests/unit/llms/ollama/test_ollama_completion_transformation.py b/tests/unit/llms/ollama/test_ollama_completion_transformation.py index 248e745ebff..400921dfda3 100644 --- a/tests/unit/llms/ollama/test_ollama_completion_transformation.py +++ b/tests/unit/llms/ollama/test_ollama_completion_transformation.py @@ -19,6 +19,26 @@ from litellm.llms.ollama.completion.transformation import ( from litellm.types.utils import Message, ModelResponse, ModelResponseStream +@pytest.mark.parametrize( + "stop, expected", + [ + ("END", ["END"]), + ("", None), + (["END", "STOP"], ["END", "STOP"]), + ([""], [""]), + ([], []), + ], +) +def test_stop_is_sent_as_an_array(stop: str | list[str], expected: list[str] | None) -> None: + optional_params: Final = litellm.utils.get_optional_params( + model="test-model", custom_llm_provider="ollama", stop=stop + ) + if expected is None: + assert "stop" not in optional_params + else: + assert optional_params["stop"] == expected + + class TestOllamaConfig: def test_transform_response_standard(self): # Initialize config