# 多轮工具调用 Token 优化实现 ## 概述 本文档描述了为减少多轮工具调用中 token 占用而实现的优化策略。 ## 问题描述 在多轮工具调用场景中,每一轮的工具调用结果(ToolMessage)都包含大量的检索数据,这些数据在进入下一轮时仍然被包含在 LLM 的输入中,导致: 1. **Token 消耗激增**:前面轮次的 ToolMessage 包含大量 JSON 格式的搜索结果 2. **上下文长度超限**:可能超过 LLM 的最大上下文长度限制 3. **效率降低**:旧的工具结果对新一轮的工具调用决策帮助不大 ## 解决方案 ### 1. 多轮工具调用优化算法 在 `ConversationTrimmer` 类中实现了 `_optimize_multi_round_tool_calls` 方法: **策略**: - 保留系统消息(包含重要指令) - 保留用户的原始查询 - 只保留最近一轮的 AI-Tool 消息对(维持上下文连续性) - 移除较早轮次的 ToolMessage(它们占用最多 token) **算法流程**: 1. 识别消息序列中的工具调用轮次 2. 检测多轮工具调用模式 3. 构建优化后的消息列表: - 保留所有 SystemMessage - 保留第一个 HumanMessage(原始查询) - 只保留最新一轮的工具调用及结果 ### 2. 工具轮次识别 实现了 `_identify_tool_rounds` 方法来识别工具调用轮次: - 识别 AIMessage(包含 tool_calls) - 识别随后的 ToolMessage 序列 - 返回每个工具轮次的起始和结束位置 ### 3. 智能修剪策略 修改了 `trim_conversation_history` 方法的流程: 1. **优先应用多轮优化**:首先尝试多轮工具调用优化 2. **检查是否足够**:如果优化后仍在限制范围内,直接返回 3. **备用修剪**:如果仍超出限制,使用 LangChain 的标准修剪策略 ## 实现细节 ### 代码位置 - 文件:`service/graph/message_trimmer.py` - 主要方法: - `_optimize_multi_round_tool_calls()` - `_identify_tool_rounds()` - 修改的 `trim_conversation_history()` ### 配置参数 ```yaml parameters: max_context_length: 96000 # 默认 96k tokens # 历史消息限制:85% = 81,600 tokens # 响应生成预留:15% = 14,400 tokens ``` ## 测试结果 ### 模拟测试结果 在测试脚本中创建了包含 3 轮工具调用的对话: - **原始对话**: 11 条消息,约 14,142 tokens - **优化后**: 5 条消息,约 4,737 tokens (保留 33.5%) - **节省**: 9,405 tokens (减少 66.5%) ### 实际运行结果 在真实的多轮工具调用场景中: - **第一次优化**: 15 → 4 条消息(移除 2 个旧工具轮次) - **第二次优化**: 17 → 4 条消息(移除 3 个旧工具轮次) ## 优势 1. **大幅减少 Token 使用**:在多轮场景中减少 60-70% 的 token 消耗 2. **保持上下文连续性**:保留最新轮次的结果用于最终合成 3. **智能优先级**:优先移除占用最多 token 的旧工具结果 4. **向后兼容**:不影响单轮或简单对话场景 5. **渐进式优化**:先尝试多轮优化,必要时再应用标准修剪 ## 适用场景 - 多轮自主工具调用 - 大量工具结果数据的场景 - 需要保持对话完整性的长对话 - Token 成本敏感的应用 ## 未来优化方向 1. **智能摘要**:对旧轮次的结果进行摘要而非完全删除 2. **内容重要性评估**:基于内容相关性保留重要信息 3. **动态阈值**:根据工具结果大小动态调整保留策略 4. **分层保留**:为不同类型的工具结果设置不同的保留策略 ## 配置建议 对于不同的使用场景,建议的配置: ```yaml # 高频多轮场景 parameters: max_context_length: 50000 # 平衡场景 parameters: max_context_length: 96000 # 大型对话场景 parameters: max_context_length: 128000 ``` ## 监控指标 建议监控以下指标来评估优化效果: 1. 优化触发频率 2. Token 节省量 3. 消息减少数量 4. 对话质量保持情况 通过这些改进,系统现在能够在多轮工具调用场景中显著减少 token 使用,同时保持对话的连续性和完整性。