# 智能深度研究系统 - 执行过程详细分析 **基于**: `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工具 #### 输出 ```json { "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 #### 输出 ```json { "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读取两个文件 #### 输出 ```json { "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`): ```python 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. **查询策略**: 基础概念 + 最佳实践 + 实现细节 #### 输出 ```json { "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. 可以总结并返回结果 #### 输出 ```json { "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`: ```python 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写入,已合并) ✅ ``` --- ## 执行流程图 ```mermaid 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`