Files
deepagents----/tests/EXECUTION_ANALYSIS.md
2025-11-02 18:06:38 +08:00

16 KiB
Raw Blame History

智能深度研究系统 - 执行过程详细分析

基于: llm_calls_20251031_150543.json 测试问题: "Python asyncio最佳实践" 深度模式: quick 总LLM调用次数: 5次 总耗时: 49.49秒


整体架构回顾

┌─────────────────────────────────────────────────────────────┐
│                    LangGraph 执行引擎                        │
│  (持续调用Agent直到任务完成或无工具调用)                     │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│            ResearchCoordinator (主Agent)                    │
│  - 协调整个研究流程                                          │
│  - 通过虚拟文件系统管理状态                                  │
│  - 使用task工具调用SubAgent                                 │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│                   虚拟文件系统 (State)                       │
│  - /question.txt                                            │
│  - /config.json                                             │
│  - /search_queries.json                                     │
│  - /iteration_N/*.json                                      │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│                 6个SubAgent (通过task调用)                   │
│  1. intent-analyzer       4. content-analyzer               │
│  2. search-orchestrator   5. confidence-evaluator           │
│  3. source-validator      6. report-generator               │
└─────────────────────────────────────────────────────────────┘

详细执行流程分析

🔵 LLM调用 #1 - 主Agent初始化 (步骤1)

时间: 15:04:53 → 15:05:01 (8秒) 执行者: ResearchCoordinator (主Agent) Token消耗: 输入5,920 + 输出103 = 6,023 tokens

输入

[SystemMessage] 完整的系统提示词
  - 研究问题: "Python asyncio最佳实践"
  - 7步执行流程说明
  - 重要提示: write_file和task不能在同一个响应中调用

[HumanMessage] "请开始研究这个问题Python asyncio最佳实践"

主Agent的思考过程

根据系统提示词主Agent理解到

  1. 需要先执行步骤1初始化虚拟文件系统
  2. 写入/question.txt/config.json
  3. 不能在同一响应中调用task工具

输出

{
  "tool_calls": [
    {
      "name": "write_file",
      "file_path": "/question.txt",
      "content": "Python asyncio最佳实践"
    },
    {
      "name": "write_file",
      "file_path": "/config.json",
      "content": "{\"depth_mode\": \"quick\", \"report_format\": \"technical\", ...}"
    }
  ]
}

关键点

  • 主Agent 调用了write_file没有调用task
  • 两个文件被并行写入
  • 🔄 LangGraph看到有工具调用会继续执行下一轮

State更新

虚拟文件系统:
├── /question.txt ✅ (新增)
└── /config.json ✅ (新增)

🔵 LLM调用 #2 - 主Agent启动SubAgent (步骤2)

时间: 15:05:01 → 15:05:06 (4.5秒) 执行者: ResearchCoordinator (主Agent) Token消耗: 输入6,046 + 输出69 = 6,115 tokens

输入

[SystemMessage] 完整的系统提示词 (相同)

[HumanMessage] "请开始研究这个问题Python asyncio最佳实践"

[AIMessage] 之前的响应 (write_file × 2)

[ToolMessage] "Updated file /question.txt" ✅
[ToolMessage] "Updated file /config.json" ✅

主Agent的思考过程

主Agent看到

  1. 两个文件已成功写入ToolMessage确认
  2. 步骤1已完成应该进入步骤2
  3. 现在可以调用task工具启动intent-analyzer

输出

{
  "content": "已将研究问题和配置写入虚拟文件系统。现在,我将调用 `intent-analyzer` SubAgent 来分析研究问题并生成搜索查询。",
  "tool_calls": [
    {
      "name": "task",
      "args": {
        "description": "分析研究问题并生成搜索查询",
        "subagent_type": "intent-analyzer"
      }
    }
  ]
}

关键点

  • 主Agent在独立的响应中调用task
  • 此时虚拟文件系统已包含两个文件
  • 🚀 task工具触发SubAgent创建和执行

🔵 LLM调用 #3 - SubAgent读取文件

时间: 15:05:06 → 15:05:08 (2.7秒) 执行者: intent-analyzer (SubAgent) Token消耗: 输入2,724 + 输出49 = 2,773 tokens

输入

[SystemMessage] intent-analyzer的专用系统提示词
  - 任务: 分析问题并生成搜索查询
  - 需要读取: /question.txt, /config.json
  - 需要输出: /search_queries.json

[HumanMessage] "分析研究问题并生成搜索查询"

SubAgent的思考过程

SubAgent按照提示词

  1. 需要先读取输入文件
  2. 使用ls查看文件系统结构
  3. 使用read_file读取两个文件

输出

{
  "tool_calls": [
    {"name": "ls"},
    {"name": "read_file", "file_path": "/question.txt"},
    {"name": "read_file", "file_path": "/config.json"}
  ]
}

关键机制解析

🔑 核心问题SubAgent如何访问主Agent写入的文件

根据DeepAgents源码 (deepagents/middleware/subagents.py:332):

def _validate_and_prepare_state(subagent_type, description, runtime):
    # 创建SubAgent的state从主Agent的state复制
    subagent_state = {
        k: v for k, v in runtime.state.items()
        if k not in ("messages", "todos")  # 排除这两个键
    }
    subagent_state["messages"] = [HumanMessage(content=description)]
    return subagent, subagent_state

执行时序:

1. 主Agent调用 #1: write_file × 2
   → 返回 Command(update={"files": {...}})

2. LangGraph应用State更新
   → runtime.state["files"] = {
        "/question.txt": {...},
        "/config.json": {...}
      }

3. 主Agent调用 #2: task(...)
   → task工具内部调用 _validate_and_prepare_state()
   → 复制 runtime.state (包括files) 给SubAgent

4. SubAgent启动时state中已包含这两个文件 ✅

这就是为什么必须分两个响应

  • 如果在同一响应中调用write_file和task两个工具会并行执行
  • 当task开始复制state时write_file的更新还没被应用
  • 分两个响应后第二次调用时state已包含更新

🔵 LLM调用 #4 - SubAgent分析并生成查询

时间: 15:05:08 → 15:05:28 (19.4秒) 执行者: intent-analyzer (SubAgent) Token消耗: 输入2,861 + 输出404 = 3,265 tokens

输入

[SystemMessage] intent-analyzer的系统提示词

[HumanMessage] "分析研究问题并生成搜索查询"

[AIMessage] 之前的工具调用 (ls, read_file × 2)

[ToolMessage] "[\"/question.txt\", \"/config.json\"]" ✅

[ToolMessage] "     1\tPython asyncio最佳实践" ✅

[ToolMessage] "     1\t{\"depth_mode\": \"quick\", ...}" ✅

SubAgent的思考过程

SubAgent成功读取到文件内容

  1. 问题: "Python asyncio最佳实践"
  2. 配置: quick模式 → 生成3个查询
  3. 领域分析: 技术(编程)
  4. 查询策略: 基础概念 + 最佳实践 + 实现细节

输出

{
  "content": "已经读取了原始研究问题和配置文件。研究问题是关于...",
  "tool_calls": [
    {
      "name": "write_file",
      "file_path": "/search_queries.json",
      "content": "{\n    \"original_question\": \"Python asyncio最佳实践\",\n    \"queries\": [\n        {\"query\": \"What is Python asyncio and how does it work?\", ...},\n        {\"query\": \"Best practices for using Python asyncio\", ...},\n        {\"query\": \"How to implement best practices with Python asyncio in real projects\", ...}\n    ]\n}"
    }
  ]
}

生成的3个搜索查询

  1. 基础概念: "What is Python asyncio and how does it work?"
  2. 最佳实践: "Best practices for using Python asyncio"
  3. 实现细节: "How to implement best practices with Python asyncio in real projects"

State更新

虚拟文件系统:
├── /question.txt
├── /config.json
└── /search_queries.json ✅ (新增SubAgent写入)

🔵 LLM调用 #5 - SubAgent完成并返回

时间: 15:05:28 → 15:05:43 (14.6秒) 执行者: intent-analyzer (SubAgent) Token消耗: 输入3,278 + 输出241 = 3,519 tokens

输入

[SystemMessage] intent-analyzer的系统提示词

[HumanMessage] "分析研究问题并生成搜索查询"

[之前的所有消息和工具调用...]

[ToolMessage] "Updated file /search_queries.json" ✅

SubAgent的思考过程

SubAgent看到

  1. 文件已成功写入
  2. 任务已完成生成了3个查询
  3. 可以总结并返回结果

输出

{
  "content": "搜索查询已成功生成并写入`/search_queries.json`文件中。以下是生成的搜索查询:\n\n- **原始问题**: Python asyncio最佳实践\n- **领域**: 技术(编程)\n...",
  "tool_calls": []  // ← 空数组,没有更多工具调用
}

关键点

  • SubAgent没有工具调用tool_calls为空
  • 🔄 LangGraph检测到SubAgent完成返回结果给主Agent
  • 📦 SubAgent的state更新包括/search_queries.json合并回主Agent

SubAgent返回机制

根据deepagents/middleware/subagents.py:316-323:

def _return_command_with_state_update(result, tool_call_id):
    # 排除messages和todos其他state都返回给主Agent
    state_update = {
        k: v for k, v in result.items()
        if k not in ("messages", "todos")
    }
    return Command(update={
        **state_update,  # files会被合并
        "messages": [ToolMessage(result["messages"][-1].text, tool_call_id)]
    })

最终State

虚拟文件系统 (主Agent):
├── /question.txt         (主Agent写入)
├── /config.json          (主Agent写入)
└── /search_queries.json  (SubAgent写入已合并) ✅

执行流程图

sequenceDiagram
    participant User
    participant LangGraph
    participant 主Agent
    participant State as 虚拟文件系统
    participant SubAgent as intent-analyzer

    User->>LangGraph: "研究: Python asyncio最佳实践"

    Note over LangGraph,主Agent: 🔵 LLM调用 #1 (8秒)
    LangGraph->>主Agent: SystemMessage + HumanMessage
    主Agent->>主Agent: 理解: 需执行步骤1 - 初始化
    主Agent->>State: write_file(/question.txt)
    主Agent->>State: write_file(/config.json)
    State-->>主Agent: ToolMessage × 2

    Note over LangGraph,State: State更新: files包含2个文件

    Note over LangGraph,主Agent: 🔵 LLM调用 #2 (4.5秒)
    LangGraph->>主Agent: 之前的消息 + ToolMessage
    主Agent->>主Agent: 理解: 步骤1完成进入步骤2
    主Agent->>LangGraph: task(intent-analyzer)

    Note over LangGraph,SubAgent: task工具复制state给SubAgent
    LangGraph->>SubAgent: 创建SubAgent (state包含2个文件)

    Note over LangGraph,SubAgent: 🔵 LLM调用 #3 (2.7秒)
    LangGraph->>SubAgent: SystemMessage + HumanMessage
    SubAgent->>SubAgent: 理解: 需读取输入文件
    SubAgent->>State: ls()
    SubAgent->>State: read_file(/question.txt)
    SubAgent->>State: read_file(/config.json)
    State-->>SubAgent: ToolMessage × 3 ✅ 文件存在!

    Note over LangGraph,SubAgent: 🔵 LLM调用 #4 (19.4秒)
    LangGraph->>SubAgent: 之前的消息 + ToolMessage
    SubAgent->>SubAgent: 分析问题生成3个查询
    SubAgent->>State: write_file(/search_queries.json)
    State-->>SubAgent: ToolMessage

    Note over LangGraph,SubAgent: 🔵 LLM调用 #5 (14.6秒)
    LangGraph->>SubAgent: 之前的消息 + ToolMessage
    SubAgent->>SubAgent: 理解: 任务完成
    SubAgent-->>LangGraph: 无工具调用 (完成)

    Note over LangGraph,State: SubAgent state合并回主Agent
    LangGraph->>主Agent: ToolMessage (SubAgent结果)

    Note over 主Agent: 继续步骤3...
    主Agent-->>User: (测试在此停止)

Token消耗分析

调用 执行者 输入Token 输出Token 总计 占比
#1 主Agent 5,920 103 6,023 31.2%
#2 主Agent 6,046 69 6,115 31.7%
#3 SubAgent 2,724 49 2,773 14.4%
#4 SubAgent 2,861 404 3,265 16.9%
#5 SubAgent 3,278 241 3,519 18.2%
总计 20,829 866 19,295 100%

关键观察:

  • 主Agent的Token消耗主要在系统提示词非常详细
  • SubAgent的输入Token较少专用提示词更简洁
  • 输出Token主要用于JSON生成调用#4

关键技术要点总结

成功解决的问题

  1. 虚拟文件系统共享

    • SubAgent能成功读取主Agent写入的文件
    • 通过state复制机制实现
  2. 工具调用顺序

    • write_file在第一个响应
    • task在第二个响应
    • 确保state更新已应用
  3. SubAgent生命周期

    • 创建 → 接收任务描述
    • 执行 → 读取文件、处理、写入结果
    • 返回 → state合并回主Agent

🎯 设计亮点

  1. 声明式流程控制

    • 通过系统提示词定义流程
    • 不使用Python while循环
    • LLM自主决策下一步
  2. 文件驱动的状态管理

    • 所有状态通过虚拟文件系统
    • 跨Agent通信通过文件
    • 易于调试和追踪
  3. 降级运行策略

    • 部分失败不影响整体
    • 提示词中明确说明

后续步骤预测

如果测试继续运行,预期流程:

✅ 步骤1: 初始化 (已完成)
✅ 步骤2: 意图分析 (已完成)
⏭️  步骤3.1: 并行搜索
   - 主Agent调用search-orchestrator
   - 使用Tavily API搜索3个查询
   - 写入/iteration_1/search_results.json

⏭️  步骤3.2: 来源验证
   - 主Agent调用source-validator
   - Tier 1-4分级
   - 写入/iteration_1/sources.json

⏭️  步骤3.3: 内容分析
   - 主Agent调用content-analyzer
   - 提取信息,交叉验证
   - 写入/iteration_1/findings.json

⏭️  步骤3.4: 置信度评估
   - 主Agent调用confidence-evaluator
   - 计算置信度 (50%+30%+20%)
   - 写入/iteration_decision.json
   - 决策: FINISH 或 CONTINUE

⏭️  步骤7: 报告生成
   - 主Agent调用report-generator
   - 读取所有iteration数据
   - 写入/final_report.md

性能优化建议

基于当前执行情况:

  1. 系统提示词优化

    • 主Agent的提示词非常长5,920 tokens
    • 可以精简部分重复说明
    • 预期节省 ~20% Token
  2. 并行SubAgent调用

    • 当前是串行步骤3.1 → 3.2 → 3.3
    • 某些步骤可以并行(如果依赖允许)
    • 预期减少 30-40% 时间
  3. 缓存机制

    • 相同问题的搜索结果可缓存
    • 减少API调用次数

总结

测试成功证明:

  • 虚拟文件系统在主Agent和SubAgent之间正确共享
  • 工具调用顺序控制有效
  • 基于提示词的流程控制可行

🎯 下一步工作:

  1. 完成剩余SubAgent的测试
  2. 实现完整的端到端流程
  3. 添加错误处理和降级策略
  4. 性能优化

📊 当前进度: 2/7步 (28.6%)

  • 步骤1: 初始化
  • 步骤2: 意图分析
  • 步骤3-7: 待实现

生成时间: 2025-10-31 测试数据: llm_calls_20251031_150543.json