mirror of
https://github.com/TauricResearch/TradingAgents.git
synced 2026-09-19 11:15:24 +03:00
fix(llm): suppress object-form tool_choice for Ollama (#1062)
- Ollama takes the local-compatible client, like the generic endpoint
This commit is contained in:
@@ -197,3 +197,28 @@ def test_ollama_offers_custom_model_id():
|
|||||||
assert "custom" in values, f"Ollama {mode!r} missing 'custom' option: {entries}"
|
assert "custom" in values, f"Ollama {mode!r} missing 'custom' option: {entries}"
|
||||||
# Custom option is last so it doesn't push the curated defaults off-screen
|
# Custom option is last so it doesn't push the curated defaults off-screen
|
||||||
assert values[-1] == "custom", f"'custom' should be last entry: {values}"
|
assert values[-1] == "custom", f"'custom' should be last entry: {values}"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_structured_output_suppresses_object_tool_choice(monkeypatch):
|
||||||
|
"""Ollama rejects the object-form tool_choice like other local servers
|
||||||
|
(#1062), and a local model ID has no capability entry saying otherwise, so
|
||||||
|
it takes the same client as the generic local endpoint."""
|
||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from tradingagents.llm_clients import create_llm_client
|
||||||
|
|
||||||
|
class Schema(BaseModel):
|
||||||
|
x: int
|
||||||
|
|
||||||
|
captured = {}
|
||||||
|
monkeypatch.setattr(
|
||||||
|
ChatOpenAI,
|
||||||
|
"with_structured_output",
|
||||||
|
lambda self, schema, method=None, **kw: captured.update({"method": method, **kw}) or "BOUND",
|
||||||
|
)
|
||||||
|
|
||||||
|
create_llm_client(provider="ollama", model="qwen3:30b").get_llm().with_structured_output(Schema)
|
||||||
|
|
||||||
|
assert captured["tool_choice"] is None
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import pytest
|
|||||||
from tradingagents.llm_clients.openai_client import (
|
from tradingagents.llm_clients.openai_client import (
|
||||||
OPENAI_COMPATIBLE_PROVIDERS,
|
OPENAI_COMPATIBLE_PROVIDERS,
|
||||||
DeepSeekChatOpenAI,
|
DeepSeekChatOpenAI,
|
||||||
|
LocalCompatibleChatOpenAI,
|
||||||
MinimaxChatOpenAI,
|
MinimaxChatOpenAI,
|
||||||
NormalizedChatOpenAI,
|
NormalizedChatOpenAI,
|
||||||
is_openai_compatible,
|
is_openai_compatible,
|
||||||
@@ -39,7 +40,7 @@ def test_registry_membership():
|
|||||||
("kimi", "https://api.moonshot.ai/v1", NormalizedChatOpenAI, False),
|
("kimi", "https://api.moonshot.ai/v1", NormalizedChatOpenAI, False),
|
||||||
("groq", "https://api.groq.com/openai/v1", NormalizedChatOpenAI, False),
|
("groq", "https://api.groq.com/openai/v1", NormalizedChatOpenAI, False),
|
||||||
("nvidia", "https://integrate.api.nvidia.com/v1", NormalizedChatOpenAI, False),
|
("nvidia", "https://integrate.api.nvidia.com/v1", NormalizedChatOpenAI, False),
|
||||||
("ollama", "http://localhost:11434/v1", NormalizedChatOpenAI, False),
|
("ollama", "http://localhost:11434/v1", LocalCompatibleChatOpenAI, False),
|
||||||
])
|
])
|
||||||
def test_registry_spec(provider, base_url, chat_class, responses):
|
def test_registry_spec(provider, base_url, chat_class, responses):
|
||||||
spec = OPENAI_COMPATIBLE_PROVIDERS[provider]
|
spec = OPENAI_COMPATIBLE_PROVIDERS[provider]
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ OPENAI_COMPATIBLE_PROVIDERS: dict[str, ProviderSpec] = {
|
|||||||
"groq": ProviderSpec(base_url="https://api.groq.com/openai/v1"),
|
"groq": ProviderSpec(base_url="https://api.groq.com/openai/v1"),
|
||||||
"nvidia": ProviderSpec(base_url="https://integrate.api.nvidia.com/v1"),
|
"nvidia": ProviderSpec(base_url="https://integrate.api.nvidia.com/v1"),
|
||||||
"ollama": ProviderSpec(base_url="http://localhost:11434/v1", base_url_env="OLLAMA_BASE_URL",
|
"ollama": ProviderSpec(base_url="http://localhost:11434/v1", base_url_env="OLLAMA_BASE_URL",
|
||||||
key_optional=True, placeholder_key="ollama"),
|
key_optional=True, placeholder_key="ollama",
|
||||||
|
chat_class=LocalCompatibleChatOpenAI),
|
||||||
# Generic endpoint: user supplies base_url; key optional (keyless local).
|
# Generic endpoint: user supplies base_url; key optional (keyless local).
|
||||||
"openai_compatible": ProviderSpec(
|
"openai_compatible": ProviderSpec(
|
||||||
require_base_url=True, key_optional=True, chat_class=LocalCompatibleChatOpenAI
|
require_base_url=True, key_optional=True, chat_class=LocalCompatibleChatOpenAI
|
||||||
|
|||||||
Reference in New Issue
Block a user