From 92af9423448197b0d083073234fac5e9af40c2ad Mon Sep 17 00:00:00 2001 From: Hugo Sqr Date: Tue, 17 Mar 2026 13:32:35 +0700 Subject: [PATCH] feat: integrate OpenRouter as a fallback LLM option; update configuration and client handling --- .env.example | 20 +++++++++++++------ backend/app/config.py | 17 +++++++++++----- .../app/services/oasis_profile_generator.py | 15 +++++++++++--- .../services/simulation_config_generator.py | 15 +++++++++++--- backend/app/utils/llm_client.py | 15 +++++++++++--- 5 files changed, 62 insertions(+), 20 deletions(-) diff --git a/.env.example b/.env.example index 78a3b72c..bc4b66fd 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,17 @@ -# LLM API配置(支持 OpenAI SDK 格式的任意 LLM API) -# 推荐使用阿里百炼平台qwen-plus模型:https://bailian.console.aliyun.com/ -# 注意消耗较大,可先进行小于40轮的模拟尝试 -LLM_API_KEY=your_api_key_here -LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 -LLM_MODEL_NAME=qwen-plus +# ===== OpenRouter 配置(后备 LLM,未设置 LLM_API_KEY 时自动使用)===== +# OpenRouter 聚合了数百种模型,注册获取API Key:https://openrouter.ai/ +OPENROUTER_API_KEY=sk-or-v1-your_openrouter_key_here +OPENROUTER_MODEL_NAME=anthropic/claude-sonnet-4 +# OPENROUTER_BASE_URL=https://openrouter.ai/api/v1 # 默认值,一般无需修改 +# OPENROUTER_REFERER=https://github.com/MiroFish # 默认值,一般无需修改 +# OPENROUTER_TITLE=MiroFish # 默认值,一般无需修改 + +# ===== LLM API 配置(可选,优先级高于 OpenRouter)===== +# 支持 OpenAI SDK 格式的任意 LLM API(如阿里百炼平台) +# 如果设置了以下配置,将覆盖 OpenRouter 配置 +# LLM_API_KEY=your_api_key_here +# LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 +# LLM_MODEL_NAME=qwen-plus # ===== ZEP记忆图谱配置 ===== # 每月免费额度即可支撑简单使用:https://app.getzep.com/ diff --git a/backend/app/config.py b/backend/app/config.py index 953dfa50..7cbbf192 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -27,10 +27,17 @@ class Config: # JSON配置 - 禁用ASCII转义,让中文直接显示(而不是 \uXXXX 格式) JSON_AS_ASCII = False - # LLM配置(统一使用OpenAI格式) - LLM_API_KEY = os.environ.get('LLM_API_KEY') - LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1') - LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini') + # OpenRouter配置(作为LLM的后备方案) + OPENROUTER_API_KEY = os.environ.get('OPENROUTER_API_KEY') + OPENROUTER_BASE_URL = os.environ.get('OPENROUTER_BASE_URL', 'https://openrouter.ai/api/v1') + OPENROUTER_MODEL_NAME = os.environ.get('OPENROUTER_MODEL_NAME', 'anthropic/claude-sonnet-4') + OPENROUTER_REFERER = os.environ.get('OPENROUTER_REFERER', 'https://github.com/MiroFish') + OPENROUTER_TITLE = os.environ.get('OPENROUTER_TITLE', 'MiroFish') + + # LLM配置(优先使用LLM_*,未设置则回退到OpenRouter) + LLM_API_KEY = os.environ.get('LLM_API_KEY') or OPENROUTER_API_KEY + LLM_BASE_URL = os.environ.get('LLM_BASE_URL') or OPENROUTER_BASE_URL + LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME') or OPENROUTER_MODEL_NAME # Zep配置 ZEP_API_KEY = os.environ.get('ZEP_API_KEY') @@ -68,7 +75,7 @@ class Config: """验证必要配置""" errors = [] if not cls.LLM_API_KEY: - errors.append("LLM_API_KEY 未配置") + errors.append("LLM_API_KEY 或 OPENROUTER_API_KEY 未配置") if not cls.ZEP_API_KEY: errors.append("ZEP_API_KEY 未配置") return errors diff --git a/backend/app/services/oasis_profile_generator.py b/backend/app/services/oasis_profile_generator.py index 57836c53..0203d450 100644 --- a/backend/app/services/oasis_profile_generator.py +++ b/backend/app/services/oasis_profile_generator.py @@ -188,13 +188,22 @@ class OasisProfileGenerator: self.api_key = api_key or Config.LLM_API_KEY self.base_url = base_url or Config.LLM_BASE_URL self.model_name = model_name or Config.LLM_MODEL_NAME - + if not self.api_key: raise ValueError("LLM_API_KEY 未配置") - + + # OpenRouter兼容:自动检测并添加推荐的额外请求头 + extra_kwargs = {} + if self.base_url and 'openrouter.ai' in self.base_url: + extra_kwargs['default_headers'] = { + 'HTTP-Referer': Config.OPENROUTER_REFERER, + 'X-Title': Config.OPENROUTER_TITLE, + } + self.client = OpenAI( api_key=self.api_key, - base_url=self.base_url + base_url=self.base_url, + **extra_kwargs ) # Zep客户端用于检索丰富上下文 diff --git a/backend/app/services/simulation_config_generator.py b/backend/app/services/simulation_config_generator.py index cc362508..8b3eb6b7 100644 --- a/backend/app/services/simulation_config_generator.py +++ b/backend/app/services/simulation_config_generator.py @@ -230,13 +230,22 @@ class SimulationConfigGenerator: self.api_key = api_key or Config.LLM_API_KEY self.base_url = base_url or Config.LLM_BASE_URL self.model_name = model_name or Config.LLM_MODEL_NAME - + if not self.api_key: raise ValueError("LLM_API_KEY 未配置") - + + # OpenRouter兼容:自动检测并添加推荐的额外请求头 + extra_kwargs = {} + if self.base_url and 'openrouter.ai' in self.base_url: + extra_kwargs['default_headers'] = { + 'HTTP-Referer': Config.OPENROUTER_REFERER, + 'X-Title': Config.OPENROUTER_TITLE, + } + self.client = OpenAI( api_key=self.api_key, - base_url=self.base_url + base_url=self.base_url, + **extra_kwargs ) def generate_config( diff --git a/backend/app/utils/llm_client.py b/backend/app/utils/llm_client.py index 6c1a81f4..fcd139ec 100644 --- a/backend/app/utils/llm_client.py +++ b/backend/app/utils/llm_client.py @@ -23,13 +23,22 @@ class LLMClient: self.api_key = api_key or Config.LLM_API_KEY self.base_url = base_url or Config.LLM_BASE_URL self.model = model or Config.LLM_MODEL_NAME - + if not self.api_key: raise ValueError("LLM_API_KEY 未配置") - + + # OpenRouter兼容:自动检测并添加推荐的额外请求头 + extra_kwargs = {} + if self.base_url and 'openrouter.ai' in self.base_url: + extra_kwargs['default_headers'] = { + 'HTTP-Referer': Config.OPENROUTER_REFERER, + 'X-Title': Config.OPENROUTER_TITLE, + } + self.client = OpenAI( api_key=self.api_key, - base_url=self.base_url + base_url=self.base_url, + **extra_kwargs ) def chat(