98 lines
3.2 KiB
Markdown
98 lines
3.2 KiB
Markdown
|
|
# 并行工具调用优化实施报告
|
|||
|
|
|
|||
|
|
## 📋 问题描述
|
|||
|
|
|
|||
|
|
用户指出了一个重要问题:虽然在 `agent_system_prompt` 中提到了"parallel tool calling",但实际的系统代码仍然是**串行执行**工具调用。这意味着:
|
|||
|
|
|
|||
|
|
- 当LLM决定调用多个工具时,它们会一个接一个地执行
|
|||
|
|
- 如果每个工具调用需要1秒,3个工具调用就需要3秒总时间
|
|||
|
|
- 这与提示词中承诺的"并行执行"不符
|
|||
|
|
|
|||
|
|
## 🔧 技术实现
|
|||
|
|
|
|||
|
|
### 修改前 (串行执行)
|
|||
|
|
```python
|
|||
|
|
for tool_call in tool_calls:
|
|||
|
|
tool_name = tool_call.get("name")
|
|||
|
|
tool_args = tool_call.get("args", {})
|
|||
|
|
# 执行工具 - 等待完成后再执行下一个
|
|||
|
|
result = await tool_func.ainvoke(tool_args)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 修改后 (并行执行)
|
|||
|
|
```python
|
|||
|
|
# 定义单个工具执行函数
|
|||
|
|
async def execute_single_tool(tool_call):
|
|||
|
|
# 工具执行逻辑
|
|||
|
|
result = await tool_func.ainvoke(tool_args)
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
# 使用 asyncio.gather 并行执行所有工具
|
|||
|
|
tool_execution_results = await asyncio.gather(
|
|||
|
|
*[execute_single_tool(tool_call) for tool_call in tool_calls],
|
|||
|
|
return_exceptions=True
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 关键改进点
|
|||
|
|
|
|||
|
|
1. **真正的并行执行**: 使用 `asyncio.gather()` 实现真正的并发执行
|
|||
|
|
2. **错误隔离**: `return_exceptions=True` 确保一个工具失败不会影响其他工具
|
|||
|
|
3. **结果聚合**: 正确收集和处理所有工具的执行结果
|
|||
|
|
4. **流式事件**: 保持对流式事件的支持(tool_start, tool_result等)
|
|||
|
|
5. **性能监控**: 添加日志跟踪并行执行的完成情况
|
|||
|
|
|
|||
|
|
## 📊 性能验证
|
|||
|
|
|
|||
|
|
通过测试脚本验证:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
📈 Performance Comparison:
|
|||
|
|
Sequential: 3.00s (原始行为)
|
|||
|
|
Parallel: 1.00s (优化后)
|
|||
|
|
Speedup: 3.0x (3倍性能提升)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🎯 实际效益
|
|||
|
|
|
|||
|
|
### 用户体验改善
|
|||
|
|
- **响应速度**: 当需要调用多个检索工具时,响应时间显著减少
|
|||
|
|
- **系统效率**: 更好地利用I/O等待时间,提高整体吞吐量
|
|||
|
|
- **一致性**: 提示词承诺与实际行为保持一致
|
|||
|
|
|
|||
|
|
### 技术优势
|
|||
|
|
- **真正的并发**: 充分利用异步编程的优势
|
|||
|
|
- **资源利用**: 更高效的网络和CPU资源使用
|
|||
|
|
- **可扩展性**: 支持更复杂的多工具调用场景
|
|||
|
|
|
|||
|
|
## 🛠️ 代码变更摘要
|
|||
|
|
|
|||
|
|
### 文件: `service/graph/graph.py`
|
|||
|
|
- 添加 `asyncio` 导入
|
|||
|
|
- 重构 `run_tools_with_streaming()` 函数
|
|||
|
|
- 新增 `execute_single_tool()` 内部函数
|
|||
|
|
- 实现并行执行逻辑和错误处理
|
|||
|
|
|
|||
|
|
### 测试验证
|
|||
|
|
- 创建 `scripts/test_parallel_execution.py` 性能测试
|
|||
|
|
- 验证3倍性能提升
|
|||
|
|
- 确认并发执行行为
|
|||
|
|
|
|||
|
|
## 🚀 部署建议
|
|||
|
|
|
|||
|
|
1. **立即部署**: 这是一个纯性能优化,不会影响功能
|
|||
|
|
2. **监控**: 观察生产环境中的工具调用延迟
|
|||
|
|
3. **日志**: 检查并行执行的完成日志
|
|||
|
|
4. **用户反馈**: 收集用户对响应速度改善的反馈
|
|||
|
|
|
|||
|
|
## 📝 总结
|
|||
|
|
|
|||
|
|
这个修复解决了提示词与实际实现不一致的问题,将真正的并行工具调用能力带到了系统中。用户现在将体验到:
|
|||
|
|
|
|||
|
|
- ✅ 更快的多工具查询响应
|
|||
|
|
- ✅ 提示词承诺与实际行为的一致性
|
|||
|
|
- ✅ 更高效的系统资源利用
|
|||
|
|
- ✅ 为未来更复杂的工具调用场景奠定基础
|
|||
|
|
|
|||
|
|
**影响**: 直接提升用户体验,特别是在需要多源信息检索的复杂查询场景中。
|