Files
agent_management/plans/search_agent_问题诊断报告.md
zhanggangyong 647f9e6e31 feat: 更新 agent 模板支持 MODEL_NAME 环境变量
- 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 模板端口和镜像映射
- 清理冗余文件和备份文件
2026-01-17 09:12:11 +00:00

12 KiB
Raw Permalink Blame History

Search Agent 问题诊断报告

Pod 信息

  • Pod 名称: search-agent-bd115e1f-fc89c0
  • 命名空间: agent-search-agent-bd115e1f-fc89c0
  • 状态: Running

一、发现的问题

问题 0:为什么 Agent 还能返回内容?(即使 LiteLLM 返回 401)

现象

虽然 LiteLLM 返回 401 错误,但 Agent 仍然返回了内容,例如:

{
    "query": "什么是人工智能",
    "answer": "关于「什么是人工智能」,以下是搜索到的相关信息:\n### 来源 [1]: 人工智能 (AI)\n..."
}

原因:降级策略(Fallback Mechanism)

Agent 有一个降级策略,当 LLM 调用失败时,会直接从搜索结果中提取内容:

  1. 正常流程(LLM 成功时):

    搜索 → 提取内容 → 重排序 → LLM 生成答案 → 返回
    
  2. 降级流程(LLM 失败时):

    搜索 → 提取内容 → 重排序 → LLM 失败 → 使用 _fallback_answer() → 返回
    
  3. 降级答案生成逻辑(answer_generator.py:125-150):

    def _fallback_answer(self, query: str, documents: List[RankedDocument]) -> Answer:
        """后备答案生成(LLM失败时)"""
        # 简单汇总文档内容
        content_parts = [f"关于「{query}」,以下是搜索到的相关信息:\n"]
    
        for i, doc in enumerate(documents[:5], 1):
            content_parts.append(f"### 来源 [{i}]: {doc.title}\n")
            content_parts.append(f"{doc.content[:500]}...\n\n")
    
        return Answer(
            content="".join(content_parts),
            sources=sources,
            confidence="low"  # 注意:置信度是 low
        )
    
  4. 日志证据:

    2026-01-16 12:37:00.009 | ERROR | modules.answer_generator:generate:114 - 答案生成失败: LLM API请求失败: 401
    2026-01-16 12:37:00.009 | INFO  | agent.search_agent:search:131 - 答案生成完成: confidence=low
    

    注意:虽然 LLM 失败了,但答案生成"完成"了,只是 confidence=low。

这意味着什么?

  • ✅ 搜索功能正常:Serper 搜索和 Jina 内容提取都成功了
  • ✅ 内容提取正常:从网页提取了内容并进行了重排序
  • ❌ LLM 生成失败:无法使用 LLM 生成高质量答案
  • ⚠️ 返回降级答案:直接返回搜索结果的简单汇总,质量较低

所以 Agent 返回的内容是降级答案,不是 LLM 生成的,质量会明显下降。


问题 1:API Key 未正确使用(导致 LiteLLM 回调失败)

现象

日志显示 LiteLLM 收到的 API Key 是 placeholder,而不是用户传入的真实 API Key:

LLM API错误: 401 - {"error":{"message":"Authentication Error, LiteLLM Virtual Key expected. Received=placeholder, expected to start with 'sk-'.","type":"auth_error"}}

原因分析

  1. 代码逻辑:search_agent_main.py 第 276-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
        search_agent = SearchAgent(config)  # 重新初始化
    
  2. 问题:日志中没有看到 "使用请求中的 LLM API Key" 这条日志,说明:

    • 要么 request.llm_api_key 为空/None
    • 要么请求中的字段名不是 llm_api_key
  3. SearchAgent 初始化时机:

    • 各个模块(QueryAnalyzer, AnswerGenerator 等)在 __init__ 时创建了 LLMClient
    • 即使重新初始化 SearchAgent,如果模块内部已经缓存了旧的 LLMClient,仍会使用 placeholder

验证方法

检查最近的请求日志,看是否有 "使用请求中的 LLM API Key" 这条日志:

kubectl logs -n agent-search-agent-bd115e1f-fc89c0 search-agent-bd115e1f-fc89c0 --tail=1000 | grep "使用请求中的"

如果没有这条日志,说明 API Key 没有被正确传入或处理。


问题 2:Agent 回调 URL 无法解析(Agent Manager 回调失败)

现象

日志显示回调请求失败,无法解析 mcp-server 主机名:

Failed to send callback: HTTPConnectionPool(host='mcp-server', port=8002): Max retries exceeded with url: /api/v1/billing/agent-callback 
(Caused by NameResolutionError("HTTPConnection(host='mcp-server', port=8002): Failed to resolve 'mcp-server' ([Errno -2] Name or service not known)"))

回调 URL 信息

  • 当前配置的 URL: http://mcp-server:8002/api/v1/billing/agent-callback
  • 来源: agent_callback_utils.py 第 33-35 行
    self.callback_url = callback_url or os.getenv(
        "AGENT_CALLBACK_URL", 
        "http://mcp-server:8002/api/v1/billing/agent-callback"
    )
    

原因分析

  1. 服务发现问题:

    • mcp-server 服务在 taiji-ai 命名空间中
    • 当前 Pod 在 agent-search-agent-bd115e1f-fc89c0 命名空间中
    • 跨命名空间访问需要使用完整的服务名:mcp-server.taiji-ai.svc.cluster.local
  2. 端口问题:

    • mcp-server 服务实际端口是 8000(不是 8002)
    • 代码中默认使用的是 8002 端口
  3. 正确的回调 URL 应该是:

    http://mcp-server.taiji-ai.svc.cluster.local:8000/api/v1/billing/agent-callback
    

    或者(如果 mcp-server 在同一个集群中):

    http://mcp-server.taiji-ai:8000/api/v1/billing/agent-callback
    

    注意:端口是 8000,不是 8002!

回调请求详情

从日志中可以看到回调请求的 payload:

{
  "agentName": "search-agent-bd115e1f-fc89c0",
  "userId": "bd115e1f-e2de-4bd2-a641-1ed74ac1a34a",
  "podRunningTimeSeconds": 22,
  "toolsUsed": ["web_search", "content_reader"],
  "startTime": "2026-01-16T12:02:39.355978+00:00",
  "endTime": "2026-01-16T12:03:01.701388+00:00",
  "requestId": "search-1768564959"
}

问题 3:LiteLLM 回调失败(但直接测试密钥正常)

现象

  • 用户使用 sk-rxegkFOciNmQLhOHr3qP3A 直接测试模型回调正常
  • 但通过 search_agent 调用时,LiteLLM 回调报错

原因分析

  1. API Key 传递问题:

    • Agent 使用的是 placeholder,不是真实的 sk-rxegkFOciNmQLhOHr3qP3A
    • LiteLLM 无法识别 placeholder,导致鉴权失败
    • 鉴权失败后,LiteLLM 的回调也会失败(因为无法识别租户)
  2. 为什么直接测试正常:

    • 直接测试时使用的是真实的 API Key sk-rxegkFOciNmQLhOHr3qP3A
    • 该 API Key 在 LiteLLM 中正确配置了租户信息
    • 所以回调正常
  3. 为什么 Agent 调用失败:

    • Agent 实际使用的是 placeholder
    • LiteLLM 无法识别 placeholder,返回 401 错误
    • 回调时也无法识别租户,导致回调失败

二、问题根源总结

核心问题链

用户传入 llm_api_key: "sk-rxegkFOciNmQLhOHr3qP3A"
  ↓
代码应该更新 config.llm_api_key 并重新初始化 SearchAgent
  ↓
❌ 但日志显示没有执行更新逻辑(没有 "使用请求中的 LLM API Key" 日志)
  ↓
SearchAgent 继续使用 placeholder
  ↓
LLMClient 使用 placeholder 调用 LiteLLM
  ↓
LiteLLM 返回 401: "Received=placeholder, expected to start with 'sk-'"
  ↓
LiteLLM 回调失败(无法识别租户)

三、验证步骤

1. 验证 API Key 是否被传入

检查最近的请求日志:

kubectl logs -n agent-search-agent-bd115e1f-fc89c0 search-agent-bd115e1f-fc89c0 --tail=1000 | grep -E "使用请求中的|llm_api_key|POST /search"

2. 验证回调 URL 配置

检查 Pod 的环境变量:

kubectl exec -n agent-search-agent-bd115e1f-fc89c0 search-agent-bd115e1f-fc89c0 -- env | grep -i "CALLBACK\|MCP"

3. 验证 mcp-server 服务

确认 mcp-server 服务的完整地址:

kubectl get svc -n taiji-ai mcp-server
kubectl get endpoints -n taiji-ai mcp-server

4. 测试回调 URL 连通性

从 Pod 内部测试回调 URL:

# 测试健康检查接口(端口 8000)
kubectl exec -n agent-search-agent-bd115e1f-fc89c0 search-agent-bd115e1f-fc89c0 -- curl -v http://mcp-server.taiji-ai.svc.cluster.local:8000/api/v1/billing/agent-callback/health

# 测试 DNS 解析
kubectl exec -n agent-search-agent-bd115e1f-fc89c0 search-agent-bd115e1f-fc89c0 -- nslookup mcp-server.taiji-ai.svc.cluster.local

四、修复建议(不改代码)

修复 1:配置正确的回调 URL

通过环境变量或 ConfigMap 设置正确的回调 URL:

env:
  - name: AGENT_CALLBACK_URL
    value: "http://mcp-server.taiji-ai.svc.cluster.local:8000/api/v1/billing/agent-callback"

或者如果 mcp-server 在同一个集群中:

env:
  - name: AGENT_CALLBACK_URL
    value: "http://mcp-server.taiji-ai:8000/api/v1/billing/agent-callback"

重要:

  • 服务名:mcp-server.taiji-ai.svc.cluster.local(跨命名空间访问)
  • 端口:8000(不是 8002)
  • 路径:/api/v1/billing/agent-callback

修复 2:确认 API Key 传递方式

检查请求格式是否正确:

{
  "query": "什么是人工智能",
  "llm_api_key": "sk-rxegkFOciNmQLhOHr3qP3A",
  "user_id": "bd115e1f-e2de-4bd2-a641-1ed74ac1a34a"
}

注意:字段名必须是 llm_api_key(不是 LLM_API_KEY 或其他)。

修复 3:检查 LiteLLM 配置

确认 LiteLLM Proxy 中 sk-rxegkFOciNmQLhOHr3qP3A 的配置:

  • API Key 是否正确注册
  • 是否关联了 team_id 或 tenant_id
  • 是否有权限访问 taiji/gpt-4o-mini 模型

五、关键日志位置

Agent 回调日志

Sending callback: {'agentName': '...', 'userId': '...', ...}
Failed to send callback: HTTPConnectionPool(host='mcp-server', port=8002): ...

LiteLLM 调用日志

LLM API错误: 401 - {"error":{"message":"Authentication Error, LiteLLM Virtual Key expected. Received=placeholder, ..."}}

API Key 更新日志(应该出现但没出现)

使用请求中的 LLM API Key: sk-rxegkFO...
SearchAgent 已使用新的 API Key 重新初始化

六、Agent 执行流程说明

完整执行流程

1. 接收请求(POST /search)
   ↓
2. 查询分析(QueryAnalyzer)→ ❌ LLM 失败,使用默认 intent
   ↓
3. 搜索规划(SearchPlanner)→ ✅ 成功
   ↓
4. 执行搜索(SearchExecutor + Serper)→ ✅ 成功,获取 10 条结果
   ↓
5. 提取内容(ContentExtractor + Jina Reader)→ ✅ 成功,提取 10 个文档
   ↓
6. 结果处理(ResultProcessor + Jina Reranker)→ ✅ 成功,排序后返回 5 个
   ↓
7. 生成答案(AnswerGenerator + LLM)→ ❌ LLM 失败(401)
   ↓
8. 降级处理(_fallback_answer)→ ✅ 从文档中提取内容,生成简单答案
   ↓
9. 质量评估(Reflector + LLM)→ ❌ LLM 失败(401),跳过评估
   ↓
10. 返回结果 → ✅ 返回降级答案(confidence=low)

为什么还能返回内容?

  • 搜索和内容提取不依赖 LLM:使用 Serper API 和 Jina Reader API,这些服务都有独立的 API Key
  • 降级策略:当 LLM 失败时,直接从搜索结果中提取内容并格式化返回
  • 质量下降:降级答案只是简单汇总,没有 LLM 的智能整合和结构化

如何判断返回的是降级答案?

  1. 检查 confidence:降级答案的 confidence 是 "low"
  2. 检查答案格式:降级答案通常以 "关于「xxx」,以下是搜索到的相关信息:" 开头
  3. 检查日志:日志中会有 "答案生成失败" 和 "confidence=low" 的记录

七、下一步行动

  1. 立即检查:确认请求中是否真的传入了 llm_api_key 字段
  2. 修复回调 URL:通过环境变量设置正确的 AGENT_CALLBACK_URL
  3. 验证修复:重新发送请求,检查日志中是否出现 "使用请求中的 LLM API Key"
  4. 监控回调:确认 Agent 回调和 LiteLLM 回调都成功
  5. 验证答案质量:修复后,答案的 confidence 应该是 "high" 或 "medium",而不是 "low"