init
This commit is contained in:
130
vw-agentic-rag/docs/topics/MULTI_ROUND_TOKEN_OPTIMIZATION.md
Normal file
130
vw-agentic-rag/docs/topics/MULTI_ROUND_TOKEN_OPTIMIZATION.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# 多轮工具调用 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 使用,同时保持对话的连续性和完整性。
|
||||
Reference in New Issue
Block a user