Files
TradingAgents/tradingagents/llm_clients/api_key_env.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

49 lines
1.9 KiB
Python

"""Canonical provider -> API-key env-var mapping.
A single source of truth for which environment variable holds the API
key for each supported LLM provider. Used by the CLI's interactive key
prompt (cli/utils.ensure_api_key) and by anything else that needs to
ask "does this provider require a key, and which env var is it?".
When adding a new provider, register its env var here so the CLI flow
prompts for it automatically instead of failing on first API call.
"""
from __future__ import annotations
from typing import Optional
PROVIDER_API_KEY_ENV: dict[str, Optional[str]] = {
"openai": "OPENAI_API_KEY",
"anthropic": "ANTHROPIC_API_KEY",
"google": "GOOGLE_API_KEY",
"azure": "AZURE_OPENAI_API_KEY",
"xai": "XAI_API_KEY",
"deepseek": "DEEPSEEK_API_KEY",
# Dual-region providers each carry their own account; keys are not
# interchangeable between the international and China endpoints.
"qwen": "DASHSCOPE_API_KEY",
"qwen-cn": "DASHSCOPE_CN_API_KEY",
"glm": "ZHIPU_API_KEY",
"glm-cn": "ZHIPU_CN_API_KEY",
"minimax": "MINIMAX_API_KEY",
"minimax-cn": "MINIMAX_CN_API_KEY",
"openrouter": "OPENROUTER_API_KEY",
# Local runtimes do not authenticate.
"ollama": None,
# Generic OpenAI-compatible endpoint: the client reads this when set (keyed
# relays), but it is marked key-optional in the provider registry so the CLI
# never forces a prompt and keyless local servers still work.
"openai_compatible": "OPENAI_COMPATIBLE_API_KEY",
}
def get_api_key_env(provider: str) -> Optional[str]:
"""Return the env var name for `provider`'s API key, or None if not applicable.
Unknown providers also return None — callers should treat that as
"no key check possible" rather than as "no key required".
"""
return PROVIDER_API_KEY_ENV.get(provider.lower())