Files
TradingAgents/tradingagents/llm_clients/factory.py
T
Yijia-Xiao 20d3b0782f feat(llm): unify OpenAI-compatible providers behind a registry + generic endpoint
The OpenAI-compatible family (openai, xAI, DeepSeek, Qwen, GLM, MiniMax,
OpenRouter, Ollama) all speak the same Chat Completions API and differ only by
base_url, key, and two narrow wire-format quirks already isolated in subclasses.
Replace the scattered base-URL dict, key handling, and client-class branches with
one ProviderSpec registry that get_llm and the factory drive off; provider quirks
stay in their subclasses. Add a generic "openai_compatible" provider for any
OpenAI-compatible server (vLLM, LM Studio, llama.cpp, relays) via backend_url +
optional key — adding a provider is now one registry row. Native Anthropic/Google
keep their own clients (genuinely different APIs). Also fixes the env backend URL
being ignored when the provider was chosen interactively (#978).
2026-06-14 03:22:24 +00:00

51 lines
1.7 KiB
Python

from typing import Optional
from .base_client import BaseLLMClient
def create_llm_client(
provider: str,
model: str,
base_url: Optional[str] = None,
**kwargs,
) -> BaseLLMClient:
"""Create an LLM client for the specified provider.
Provider modules are imported lazily so that simply importing this
factory (e.g. during test collection) does not pull in heavy LLM SDKs
or fail when their API keys are absent.
Args:
provider: LLM provider name
model: Model name/identifier
base_url: Optional base URL for API endpoint
**kwargs: Additional provider-specific arguments
Returns:
Configured BaseLLMClient instance
Raises:
ValueError: If provider is not supported
"""
provider_lower = provider.lower()
# Native (non-OpenAI) APIs are matched first so their string check doesn't
# import the OpenAI client. Everything else is OpenAI-compatible and routes
# through the provider registry (single source of truth).
if provider_lower == "anthropic":
from .anthropic_client import AnthropicClient
return AnthropicClient(model, base_url, **kwargs)
if provider_lower == "google":
from .google_client import GoogleClient
return GoogleClient(model, base_url, **kwargs)
if provider_lower == "azure":
from .azure_client import AzureOpenAIClient
return AzureOpenAIClient(model, base_url, **kwargs)
from .openai_client import OpenAIClient, is_openai_compatible
if is_openai_compatible(provider_lower):
return OpenAIClient(model, base_url, provider=provider_lower, **kwargs)
raise ValueError(f"Unsupported LLM provider: {provider}")