mirror of
https://github.com/hwchase17/langchain.git
synced 2026-06-09 10:17:00 +00:00
fix(ollama): exclude None parameters from options dictionary (#33208)
This commit is contained in:
@@ -741,26 +741,30 @@ class ChatOllama(BaseChatModel):
|
|||||||
if self.stop is not None:
|
if self.stop is not None:
|
||||||
stop = self.stop
|
stop = self.stop
|
||||||
|
|
||||||
options_dict = kwargs.pop(
|
options_dict = kwargs.pop("options", None)
|
||||||
"options",
|
if options_dict is None:
|
||||||
{
|
# Only include parameters that are explicitly set (not None)
|
||||||
"mirostat": self.mirostat,
|
options_dict = {
|
||||||
"mirostat_eta": self.mirostat_eta,
|
k: v
|
||||||
"mirostat_tau": self.mirostat_tau,
|
for k, v in {
|
||||||
"num_ctx": self.num_ctx,
|
"mirostat": self.mirostat,
|
||||||
"num_gpu": self.num_gpu,
|
"mirostat_eta": self.mirostat_eta,
|
||||||
"num_thread": self.num_thread,
|
"mirostat_tau": self.mirostat_tau,
|
||||||
"num_predict": self.num_predict,
|
"num_ctx": self.num_ctx,
|
||||||
"repeat_last_n": self.repeat_last_n,
|
"num_gpu": self.num_gpu,
|
||||||
"repeat_penalty": self.repeat_penalty,
|
"num_thread": self.num_thread,
|
||||||
"temperature": self.temperature,
|
"num_predict": self.num_predict,
|
||||||
"seed": self.seed,
|
"repeat_last_n": self.repeat_last_n,
|
||||||
"stop": self.stop if stop is None else stop,
|
"repeat_penalty": self.repeat_penalty,
|
||||||
"tfs_z": self.tfs_z,
|
"temperature": self.temperature,
|
||||||
"top_k": self.top_k,
|
"seed": self.seed,
|
||||||
"top_p": self.top_p,
|
"stop": self.stop if stop is None else stop,
|
||||||
},
|
"tfs_z": self.tfs_z,
|
||||||
)
|
"top_k": self.top_k,
|
||||||
|
"top_p": self.top_p,
|
||||||
|
}.items()
|
||||||
|
if v is not None
|
||||||
|
}
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"messages": ollama_messages,
|
"messages": ollama_messages,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ MODEL_NAME = "llama3.1"
|
|||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mock_httpx_client_stream(
|
def _mock_httpx_client_stream(
|
||||||
*args: Any, **kwargs: Any
|
*_args: Any, **_kwargs: Any
|
||||||
) -> Generator[Response, Any, Any]:
|
) -> Generator[Response, Any, Any]:
|
||||||
yield Response(
|
yield Response(
|
||||||
status_code=200,
|
status_code=200,
|
||||||
@@ -310,3 +310,103 @@ def test_load_response_with_actual_content_is_not_skipped(
|
|||||||
assert result.content == "This is actual content"
|
assert result.content == "This is actual content"
|
||||||
assert result.response_metadata.get("done_reason") == "load"
|
assert result.response_metadata.get("done_reason") == "load"
|
||||||
assert not caplog.text
|
assert not caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_none_parameters_excluded_from_options() -> None:
|
||||||
|
"""Test that None parameters are excluded from the options dict sent to Ollama."""
|
||||||
|
response = [
|
||||||
|
{
|
||||||
|
"model": "test-model",
|
||||||
|
"created_at": "2025-01-01T00:00:00.000000000Z",
|
||||||
|
"done": True,
|
||||||
|
"done_reason": "stop",
|
||||||
|
"message": {"role": "assistant", "content": "Hello!"},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch("langchain_ollama.chat_models.Client") as mock_client_class:
|
||||||
|
mock_client = MagicMock()
|
||||||
|
mock_client_class.return_value = mock_client
|
||||||
|
mock_client.chat.return_value = response
|
||||||
|
|
||||||
|
# Create ChatOllama with only num_ctx set
|
||||||
|
llm = ChatOllama(model="test-model", num_ctx=4096)
|
||||||
|
llm.invoke([HumanMessage("Hello")])
|
||||||
|
|
||||||
|
# Verify that chat was called
|
||||||
|
assert mock_client.chat.called
|
||||||
|
|
||||||
|
# Get the options dict that was passed to chat
|
||||||
|
call_kwargs = mock_client.chat.call_args[1]
|
||||||
|
options = call_kwargs.get("options", {})
|
||||||
|
|
||||||
|
# Only num_ctx should be in options, not None parameters
|
||||||
|
assert "num_ctx" in options
|
||||||
|
assert options["num_ctx"] == 4096
|
||||||
|
|
||||||
|
# These parameters should NOT be in options since they were None
|
||||||
|
assert "mirostat" not in options
|
||||||
|
assert "mirostat_eta" not in options
|
||||||
|
assert "mirostat_tau" not in options
|
||||||
|
assert "tfs_z" not in options
|
||||||
|
|
||||||
|
|
||||||
|
def test_all_none_parameters_results_in_empty_options() -> None:
|
||||||
|
"""Test that when all parameters are None, options dict is empty."""
|
||||||
|
response = [
|
||||||
|
{
|
||||||
|
"model": "test-model",
|
||||||
|
"created_at": "2025-01-01T00:00:00.000000000Z",
|
||||||
|
"done": True,
|
||||||
|
"done_reason": "stop",
|
||||||
|
"message": {"role": "assistant", "content": "Hello!"},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch("langchain_ollama.chat_models.Client") as mock_client_class:
|
||||||
|
mock_client = MagicMock()
|
||||||
|
mock_client_class.return_value = mock_client
|
||||||
|
mock_client.chat.return_value = response
|
||||||
|
|
||||||
|
# Create ChatOllama with no parameters set
|
||||||
|
llm = ChatOllama(model="test-model")
|
||||||
|
llm.invoke([HumanMessage("Hello")])
|
||||||
|
|
||||||
|
# Get the options dict that was passed to chat
|
||||||
|
call_kwargs = mock_client.chat.call_args[1]
|
||||||
|
options = call_kwargs.get("options", {})
|
||||||
|
|
||||||
|
# Options should be empty when no parameters are set
|
||||||
|
assert options == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_explicit_options_dict_preserved() -> None:
|
||||||
|
"""Test that explicitly provided options dict is preserved and not filtered."""
|
||||||
|
response = [
|
||||||
|
{
|
||||||
|
"model": "test-model",
|
||||||
|
"created_at": "2025-01-01T00:00:00.000000000Z",
|
||||||
|
"done": True,
|
||||||
|
"done_reason": "stop",
|
||||||
|
"message": {"role": "assistant", "content": "Hello!"},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch("langchain_ollama.chat_models.Client") as mock_client_class:
|
||||||
|
mock_client = MagicMock()
|
||||||
|
mock_client_class.return_value = mock_client
|
||||||
|
mock_client.chat.return_value = response
|
||||||
|
|
||||||
|
llm = ChatOllama(model="test-model")
|
||||||
|
# Pass explicit options dict, including None values
|
||||||
|
llm.invoke(
|
||||||
|
[HumanMessage("Hello")],
|
||||||
|
options={"temperature": 0.5, "custom_param": None},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the options dict that was passed to chat
|
||||||
|
call_kwargs = mock_client.chat.call_args[1]
|
||||||
|
options = call_kwargs.get("options", {})
|
||||||
|
|
||||||
|
# Explicit options should be preserved as-is
|
||||||
|
assert options == {"temperature": 0.5, "custom_param": None}
|
||||||
|
|||||||
Reference in New Issue
Block a user