- search_agent: 支持 MODEL_NAME 环境变量配置模型名称 - a2a_litellm_agent: 支持 MODEL_NAME 或 LITELLM_MODEL 环境变量 - mysql_agent/postgresql_agent: 新增数据库查询 agent - echo_agent: 新增回显测试 agent - jina_search_agent: 新增 Jina 搜索 agent - 更新 callback_utils 默认回调 URL - 优化 k8s_manager 模板端口和镜像映射 - 清理冗余文件和备份文件
9.9 KiB
Search Agent LiteLLM 问题分析报告
一、Search Agent 模型和密钥部署方式分析
1.1 配置来源
Search Agent 的模型和密钥配置通过以下方式部署:
环境变量配置(主要方式)
从 agent_templates/agents/search_agent/search_agent/config.py 和 search_agent_main.py 可以看到:
# 必须的环境变量
LLM_BASE_URL: str # LLM API基础URL(如:https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/)
LLM_API_KEY: str # LLM API密钥(可选,可在请求中传入)
LLM_MODEL: str # 模型名称(默认:gpt-4o-mini,实际使用:taiji/gpt-4o-mini)
SERPER_API_KEY: str # Serper 搜索 API 密钥
JINA_API_KEY: str # Jina Reader API 密钥
部署配置示例
从 k8s-test-deployment.yaml 可以看到实际部署配置:
env:
- name: LLM_BASE_URL
value: "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/"
- name: LLM_MODEL
value: "taiji/gpt-4o-mini"
- name: LLM_API_KEY
valueFrom:
secretKeyRef:
name: search-agent-secrets
key: LLM_API_KEY
1.2 密钥使用流程
-
初始化阶段:
- Agent 启动时从环境变量读取
LLM_BASE_URL和LLM_MODEL LLM_API_KEY可以为空(使用占位符),等待请求时传入
- Agent 启动时从环境变量读取
-
请求处理阶段(
search_agent_main.py:233-282):# 临时更新API key - 重要:在搜索前设置 if config and request.llm_api_key: logger.info(f"使用请求中的 LLM API Key: {request.llm_api_key[:10]}...") config.llm_api_key = request.llm_api_key # 重新初始化整个 SearchAgent 以使用新的 API key search_agent = SearchAgent(config) -
LLM 调用(
llm_client.py:49-89):# Azure OpenAI 风格的URL url = f"{self.base_url}/chat/completions?api-version={self.API_VERSION}" # Azure OpenAI 使用 api-key 头 headers = { "api-key": self.api_key, # 使用传入的 API Key "Content-Type": "application/json" }
1.3 关键发现
- 模型名称:使用的是
taiji/gpt-4o-mini,这是一个模型别名(model alias),不是原始模型名 - API Key 传递方式:
- 通过 HTTP Header
api-key传递(Azure OpenAI 风格) - 支持在请求中动态传入,覆盖环境变量
- 通过 HTTP Header
- LiteLLM Proxy 地址:
https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/
二、LiteLLM 回调报错原因分析
2.1 错误现象
根据提供的日志信息:
"call_type": "/chat/completions",
"model": "taiji/gpt-4o-mini",
"status": "failure",
"response_time": 0.00039 # 极短的响应时间,说明在鉴权阶段就被拒绝
异常位置:
ProxyException
File ".../auth_checks.py", line 1756
can_team_access_model(model=_model, team_model_aliases=...)
2.2 根本原因
LiteLLM Proxy 在鉴权阶段无法将当前请求使用的 API Key 映射到任何租户(tenant/team),因此直接拒绝了模型调用。
问题链路:
-
请求到达 LiteLLM Proxy
- Search Agent 发送请求到
https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/chat/completions - Header:
api-key: <用户提供的API Key> - Model:
taiji/gpt-4o-mini
- Search Agent 发送请求到
-
LiteLLM 鉴权流程
LiteLLM Proxy 收到请求 ↓ 查找 API Key 对应的 team/tenant ↓ 检查该 team/tenant 是否有权限访问 "taiji/gpt-4o-mini" ↓ ❌ 失败:无法找到 API Key 对应的租户,或租户没有该模型的访问权限 ↓ 抛出 ProxyException,拒绝请求 -
为什么 Agent 还有回复?
- 可能的原因:
- Agent 使用了备用 API Key(环境变量中的默认值)
- 或者 LiteLLM Proxy 配置了降级策略(fallback)
- 或者请求被重试,使用了不同的 API Key
- 可能的原因:
2.3 具体问题点
问题 1:API Key 未正确映射到租户
LiteLLM Proxy 需要知道:
- 哪个 API Key 属于哪个 team/tenant
- 该 team/tenant 可以访问哪些模型
可能的原因:
- API Key 未在 LiteLLM 的数据库中注册
- API Key 没有关联
team_id或tenant_id - API Key 的
auth_metadata中缺少租户信息
问题 2:模型别名权限配置缺失
模型 taiji/gpt-4o-mini 是一个别名,需要:
- 在 LiteLLM 中配置该别名映射到实际模型
- 配置哪些 team/tenant 可以访问该别名
可能的原因:
- 模型别名
taiji/gpt-4o-mini未在 LiteLLM 中配置 - 或者配置了,但当前租户没有访问权限
问题 3:回调时缺少租户信息
从回调文档可以看到,LiteLLM 回调需要包含租户信息:
{
"metadata": {
"user_api_key_auth_metadata": {
"tenant_id": "tenant-123",
"channel_id": "channel-456"
}
}
}
如果回调中缺少这些信息,计费系统无法识别租户,导致计费失败。
三、修复方案
3.1 立即修复(LiteLLM Proxy 配置)
方案 A:在 LiteLLM 中正确配置 API Key 和租户映射
-
检查 LiteLLM 数据库中的 API Key 配置
确保每个 API Key 都有:
# LiteLLM config.yaml 或数据库记录 api_keys: - sk-xxx: team_id: "team-123" metadata: tenant_id: "tenant-123" channel_id: "channel-456" -
配置模型别名和团队访问权限
# LiteLLM config.yaml model_list: - model_name: taiji/gpt-4o-mini litellm_params: model: gpt-4o-mini api_key: os.environ/OPENAI_API_KEY # 团队模型访问配置 team_settings: team-123: team_model_aliases: - taiji/gpt-4o-mini
方案 B:在请求中添加租户信息(如果 LiteLLM 支持)
如果 LiteLLM Proxy 支持通过 Header 传递租户信息:
# 在 llm_client.py 中修改
headers = {
"api-key": self.api_key,
"Content-Type": "application/json",
"x-tenant-id": tenant_id, # 如果 LiteLLM 支持
"x-team-id": team_id # 如果 LiteLLM 支持
}
3.2 代码层面修复(Search Agent)
修复 1:在 LLM 调用时传递租户信息
修改 search_agent/utils/llm_client.py,在请求中包含租户信息:
class LLMClient:
def __init__(
self,
base_url: str,
api_key: str,
model: str = "xchat52",
timeout: int = 60,
tenant_id: Optional[str] = None, # 新增
team_id: Optional[str] = None # 新增
):
self.base_url = base_url.rstrip("/")
self.api_key = api_key
self.model = model
self.timeout = timeout
self.tenant_id = tenant_id
self.team_id = team_id
async def chat(self, ...):
headers = {
"api-key": self.api_key,
"Content-Type": "application/json"
}
# 如果 LiteLLM 支持通过 Header 传递租户信息
if self.tenant_id:
headers["x-tenant-id"] = self.tenant_id
if self.team_id:
headers["x-team-id"] = self.team_id
# ... 其余代码
修复 2:从请求中提取并传递租户信息
修改 search_agent_main.py,在搜索请求中包含租户信息:
class SearchRequest(BaseModel):
query: str
llm_api_key: str
user_id: Optional[str] = None
tenant_id: Optional[str] = None # 新增
team_id: Optional[str] = None # 新增
# 在初始化 SearchAgent 时传递租户信息
config = Config(
...
tenant_id=request.tenant_id, # 传递租户信息
team_id=request.team_id
)
3.3 LiteLLM Proxy 配置检查清单
-
✅ API Key 配置
- 所有使用的 API Key 都在 LiteLLM 数据库中
- 每个 API Key 都关联了
team_id或tenant_id - API Key 的
auth_metadata包含租户信息
-
✅ 模型别名配置
taiji/gpt-4o-mini在model_list中定义- 模型别名正确映射到实际模型
-
✅ 团队/租户访问权限
- 每个 team/tenant 的
team_model_aliases包含taiji/gpt-4o-mini - 或者使用通配符允许所有模型
- 每个 team/tenant 的
-
✅ 回调配置
- LiteLLM 的
webhook_url指向正确的回调地址 - 回调中包含
metadata.user_api_key_auth_metadata信息
- LiteLLM 的
3.4 验证步骤
-
测试 API Key 映射
# 使用 curl 测试 curl -X POST https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/chat/completions \ -H "api-key: <your-api-key>" \ -H "Content-Type: application/json" \ -d '{ "model": "taiji/gpt-4o-mini", "messages": [{"role": "user", "content": "test"}] }' -
检查 LiteLLM 日志
- 查看 LiteLLM Proxy 的日志,确认 API Key 是否被正确识别
- 检查是否有
can_team_access_model相关的错误
-
验证回调数据
- 检查回调请求中的
metadata字段 - 确认包含
user_api_key_auth_metadata.tenant_id
- 检查回调请求中的
四、总结
核心问题
LiteLLM Proxy 的多租户鉴权机制无法将 API Key 映射到租户,导致模型调用被拒绝。
修复优先级
-
高优先级:修复 LiteLLM Proxy 配置
- 确保 API Key 正确映射到租户
- 配置模型别名和访问权限
-
中优先级:代码层面改进
- 在请求中传递租户信息(如果 LiteLLM 支持)
- 改进错误处理和日志记录
-
低优先级:长期优化
- 统一租户信息管理
- 添加更详细的监控和告警
为什么 Agent 还有回复?
可能的原因:
- Agent 使用了环境变量中的备用 API Key(有权限的)
- LiteLLM Proxy 配置了降级策略
- 请求被重试,使用了不同的 API Key
建议:检查 LiteLLM Proxy 的日志,确认实际使用的 API Key 和租户信息。