diff --git a/README.md b/README.md index 9ad879a1..3a9678e7 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ TradingAgentsX 支援業界領先的多家 LLM 提供商,並為每個模型配 | 提供商 | 支援模型 | Base URL | 是否支援自訂端點 | | ------------------ | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ---------------- | | **OpenAI** | GPT-5.1, GPT-5 Mini/Nano, GPT-4.1 Mini/Nano, o4-mini | `https://api.openai.com/v1` | ✅ 是 | -| **Anthropic** | Claude Haiku 4.5, Claude Sonnet 4.5/4.0, Claude 3.5 Haiku, Claude 3 Haiku | `https://api.anthropic.com` | ✅ 是 | +| **Anthropic** | Claude Haiku 4.5, Claude Sonnet 4.5/4.0, Claude 3.5 Haiku, Claude 3 Haiku | `https://api.anthropic.com/v1` | ✅ 是 | | **Gemini** | Gemini 2.5 Pro, Gemini 2.5 Flash, Gemini 2.5 Flash Lite, Gemini 2.0 Flash, Gemini 2.0 Flash Lite | `https://generativelanguage.googleapis.com/v1beta/openai` | ✅ 是 | | **Grok (xAI)** | Grok-4.1 Fast, Grok-4 Fast, Grok-4, Grok-3, Grok-3 Mini | `https://api.x.ai/v1` | ✅ 是 | | **DeepSeek** | DeepSeek Reasoner, DeepSeek Chat | `https://api.deepseek.com/v1` | ✅ 是 | @@ -481,7 +481,7 @@ docker compose down -v 快速思維 API Key: sk-your-openai-key 深層思維模型: claude-sonnet-4-5 - 深層思維 Base URL: https://api.anthropic.com + 深層思維 Base URL: https://api.anthropic.com/v1 深層思維 API Key: sk-ant-your-claude-key 嵌入模型 Base URL: 自訂 → https://api.your-embedding-service.com/v1 @@ -569,7 +569,7 @@ curl -X POST http://localhost:8000/api/analyze \ "quick_think_llm": "gpt-5-mini-2025-08-07", "analysts": ["market", "sentiment", "news", "fundamental"], "quick_think_base_url": "https://api.openai.com/v1", - "deep_think_base_url": "https://api.anthropic.com", + "deep_think_base_url": "https://api.anthropic.com/v1", "embedding_base_url": "https://api.openai.com/v1", "quick_think_api_key": "sk-your-openai-key", "deep_think_api_key": "sk-ant-your-claude-key", diff --git a/cli/utils.py b/cli/utils.py index df4af437..36d0bf1d 100644 --- a/cli/utils.py +++ b/cli/utils.py @@ -430,7 +430,7 @@ def select_llm_provider() -> tuple[str, str]: # 定義 LLM 供應商及其 API 基礎 URL BASE_URLS = [ ("OpenAI", "https://api.openai.com/v1"), - ("Anthropic", "https://api.anthropic.com"), + ("Anthropic", "https://api.anthropic.com/v1"), ("Google", "https://generativelanguage.googleapis.com/v1beta/openai"), ("Grok", "https://api.x.ai/v1"), ("DeepSeek", "https://api.deepseek.com/v1"), diff --git a/frontend/lib/api-helpers.ts b/frontend/lib/api-helpers.ts index fee532a4..0ad5c341 100644 --- a/frontend/lib/api-helpers.ts +++ b/frontend/lib/api-helpers.ts @@ -9,12 +9,7 @@ import { ApiSettings } from "./storage"; * If custom_base_url is set, it takes precedence */ export function getBaseUrlForModel(model: string, customBaseUrl?: string): string { - // If custom base URL is provided, use it - if (customBaseUrl && customBaseUrl.trim() !== "") { - return customBaseUrl; - } - - // OpenAI models + // OpenAI models - always use OpenAI API if ( model.startsWith("gpt-") || model.startsWith("o4-") || @@ -23,31 +18,36 @@ export function getBaseUrlForModel(model: string, customBaseUrl?: string): strin return "https://api.openai.com/v1"; } - // Anthropic models + // Anthropic models - always use Anthropic API if (model.startsWith("claude-")) { - return "https://api.anthropic.com"; + return "https://api.anthropic.com/v1"; } - // Google models + // Google models - always use Google API if (model.startsWith("gemini-")) { return "https://generativelanguage.googleapis.com/v1beta/openai"; } - // Grok models + // Grok models - always use Grok API if (model.startsWith("grok-")) { return "https://api.x.ai/v1"; } - // DeepSeek models + // DeepSeek models - always use DeepSeek API if (model.startsWith("deepseek-")) { return "https://api.deepseek.com/v1"; } - // Qwen models + // Qwen models - always use Qwen API if (model.startsWith("qwen")) { return "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"; } + // For "custom" or unknown models, use custom_base_url if provided + if (customBaseUrl && customBaseUrl.trim() !== "") { + return customBaseUrl; + } + // Default to OpenAI return "https://api.openai.com/v1"; } @@ -60,14 +60,7 @@ export function getApiKeyForModel( model: string, settings: ApiSettings ): string { - // If custom base URL is configured and has a key, use the custom key - if (settings.custom_base_url && settings.custom_base_url.trim() !== "") { - if (settings.custom_api_key && settings.custom_api_key.trim() !== "") { - return settings.custom_api_key; - } - } - - // OpenAI models + // OpenAI models - always use OpenAI API key if ( model.startsWith("gpt-") || model.startsWith("o4-") || @@ -76,31 +69,36 @@ export function getApiKeyForModel( return settings.openai_api_key; } - // Anthropic models + // Anthropic models - always use Anthropic API key if (model.startsWith("claude-")) { return settings.anthropic_api_key || ""; } - // Google models + // Google models - always use Google API key if (model.startsWith("gemini-")) { return settings.google_api_key || ""; } - // Grok models + // Grok models - always use Grok API key if (model.startsWith("grok-")) { return settings.grok_api_key || ""; } - // DeepSeek models + // DeepSeek models - always use DeepSeek API key if (model.startsWith("deepseek-")) { return settings.deepseek_api_key || ""; } - // Qwen models + // Qwen models - always use Qwen API key if (model.startsWith("qwen")) { return settings.qwen_api_key || ""; } + // For "custom" or unknown models, use custom_api_key if provided + if (settings.custom_api_key && settings.custom_api_key.trim() !== "") { + return settings.custom_api_key; + } + // Default to OpenAI return settings.openai_api_key; }