feat(#875): LLM Router shadow mode + consolidate litellm master key

This commit is contained in:
QihuAI Design committed 2026-08-04 13:16:30 +08:00
1 parent 037c965c26
commit 180409d317
3 files changed
+390 -5

No files matched your search

+22 -4
View File
@@ -31,6 +31,13 @@ from sqlalchemy.orm import Session
from ..capability_registry import resolve_auto_model
from ..models import AIModel, ModelProvider, TokenUsageLog, gen_uuid
from app.core.observability import get_trace_id
# #875 LLM Router:统一模型路由层(影子模式先行,收敛 litellm 主密钥硬编码)
from ..core.llm_router import (
route as _llm_route,
set_route_ctx as _set_route_ctx,
SHADOW as _LLM_ROUTER_SHADOW,
resolve_api_key as _llm_resolve_api_key,
)
logger = logging.getLogger(__name__)
@@ -212,6 +219,19 @@ def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im
).order_by(AIModel.is_default.desc()).all()
_fallbacks = [m for m in _fallbacks if _is_text_only(m)]
_try_models.extend([m for m in _fallbacks[:4] if m not in _try_models])
# ===== LLM Router(#875 影子模式)=====
# 计算决策并打 claw_type 标签 metrics;影子模式下仅观测,不改流量。
# 切主路径:LLM_ROUTER_SHADOW=0 时改用 Router 候选链(已含文本过滤,等同此处逻辑)。
try:
_set_route_ctx(tenant_id=getattr(user, "tenant_id", "") or "", claw_type="im_wechat")
_rm = _llm_route("text", db=db, legacy_primary=_try_models[0].name if _try_models else None)
if not _LLM_ROUTER_SHADOW and _rm.models:
_try_models = _rm.models
_debug_log(f"ROUTER_LIVE models={[m.name for m in _try_models]}")
except Exception as _e:
logger.warning(f"[im_llm] LLM Router 观测失败(降级忽略): {_e}")
_debug_log(f"TRY_MODELS user={user_id} count={len(_try_models)} names={[m.name for m in _try_models]}")
if not _try_models:
@@ -268,10 +288,8 @@ def _call_real_llm(db: Session, user=None, prompt: str = "", platform: str = "im
provider = db.query(ModelProvider).filter(ModelProvider.id == ai_model.provider_id).first()
api_key = ai_model.api_key or (provider.api_key if provider else None)
api_url = ai_model.endpoint
# 2026-07-30: LiteLLM 端点统一用 master key(与 chat_service.py 对齐)
if api_url and "qihu-aiflow-litellm" in api_url:
_litellm_key = os.environ.get("LITELLM_MASTER_KEY") or "sk-litellm-master-key-aiflow-2026"
api_key = _litellm_key
# 2026-07-30: LiteLLM 端点统一用 master key(收敛进 LLM Router,两端唯一来源)
api_key = _llm_resolve_api_key(api_url, api_key, provider.api_key if provider else None)
if not api_url and provider and provider.api_base_url:
api_url = f"{provider.api_base_url.rstrip('/')}/v1/chat/completions"
if not (api_key and api_url):