3.2 KiB
3.2 KiB
并行工具调用优化实施报告
📋 问题描述
用户指出了一个重要问题:虽然在 agent_system_prompt 中提到了"parallel tool calling",但实际的系统代码仍然是串行执行工具调用。这意味着:
- 当LLM决定调用多个工具时,它们会一个接一个地执行
- 如果每个工具调用需要1秒,3个工具调用就需要3秒总时间
- 这与提示词中承诺的"并行执行"不符
🔧 技术实现
修改前 (串行执行)
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)
修改后 (并行执行)
# 定义单个工具执行函数
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
)
关键改进点
- 真正的并行执行: 使用
asyncio.gather()实现真正的并发执行 - 错误隔离:
return_exceptions=True确保一个工具失败不会影响其他工具 - 结果聚合: 正确收集和处理所有工具的执行结果
- 流式事件: 保持对流式事件的支持(tool_start, tool_result等)
- 性能监控: 添加日志跟踪并行执行的完成情况
📊 性能验证
通过测试脚本验证:
📈 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倍性能提升
- 确认并发执行行为
🚀 部署建议
- 立即部署: 这是一个纯性能优化,不会影响功能
- 监控: 观察生产环境中的工具调用延迟
- 日志: 检查并行执行的完成日志
- 用户反馈: 收集用户对响应速度改善的反馈
📝 总结
这个修复解决了提示词与实际实现不一致的问题,将真正的并行工具调用能力带到了系统中。用户现在将体验到:
- ✅ 更快的多工具查询响应
- ✅ 提示词承诺与实际行为的一致性
- ✅ 更高效的系统资源利用
- ✅ 为未来更复杂的工具调用场景奠定基础
影响: 直接提升用户体验,特别是在需要多源信息检索的复杂查询场景中。