279 lines
8.5 KiB
Markdown
279 lines
8.5 KiB
Markdown
---
|
||
name: context-optimization-reference
|
||
description: 上下文优化技术参考文档
|
||
metadata:
|
||
type: reference
|
||
---
|
||
|
||
# 上下文优化参考
|
||
|
||
本文档提供了关于上下文优化技术与策略的详细技术参考。
|
||
|
||
## 压缩策略
|
||
|
||
### 基于摘要的压缩
|
||
|
||
基于摘要的压缩用简洁的摘要替代冗长的内容,同时保留关键信息。该方法通过识别可压缩的部分、生成捕捉要点的摘要,以及用摘要替换完整内容来实现。
|
||
|
||
压缩的有效性取决于保留哪些信息。关键决策、用户偏好以及当前任务状态绝不能压缩。中间结果和支持性证据可以更积极地摘要化。样板内容、重复信息以及探索性推理通常可以直接移除。
|
||
|
||
### Token 预算分配
|
||
|
||
有效的上下文预算管理需要了解不同上下文组件如何消耗 token,并进行策略性分配:
|
||
|
||
| 组件 | 典型范围 | 说明 |
|
||
|-----------|---------------|-------|
|
||
| 系统提示词 | 500–2000 tokens | 整个会话期间保持稳定 |
|
||
| 工具定义 | 每个工具 100–500 | 随工具数量增长 |
|
||
| 检索到的文档 | 不固定 | 通常是最大消耗者 |
|
||
| 消息历史 | 不固定 | 随对话增长 |
|
||
| 工具输出 | 不固定 | 可能占据绝大部分上下文 |
|
||
|
||
### 压缩阈值
|
||
|
||
在适当的阈值触发压缩,以维持性能:
|
||
|
||
- 达到有效上下文限制 70% 时发出警告阈值
|
||
- 达到有效上下文限制 80% 时触发压缩
|
||
- 达到有效上下文限制 90% 时进行激进压缩
|
||
|
||
具体阈值取决于模型行为与任务特征。部分模型会呈现渐进式退化,而另一些模型则表现出明显的性能悬崖。
|
||
|
||
## 观测屏蔽模式
|
||
|
||
### 选择性屏蔽
|
||
|
||
并非所有观测结果都应同等屏蔽。应考虑屏蔽那些已完成使命、不再需要用于活跃推理的观测结果。保留当前任务的核心观测结果。保留最近一轮的观测结果。保留可能被再次引用的观测结果。
|
||
|
||
### 屏蔽实现
|
||
|
||
```python
|
||
def selective_mask(observations: List[Dict], current_task: Dict) -> List[Dict]:
|
||
"""
|
||
根据相关性选择性屏蔽观测结果。
|
||
|
||
返回带有 mask 字段的观测结果,指示已屏蔽的内容。
|
||
"""
|
||
masked = []
|
||
|
||
for obs in observations:
|
||
relevance = calculate_relevance(obs, current_task)
|
||
|
||
if relevance < 0.3 and obs["age"] > 3:
|
||
# 低相关性且陈旧——屏蔽
|
||
masked.append({
|
||
**obs,
|
||
"masked": True,
|
||
"reference": store_for_reference(obs["content"]),
|
||
"summary": summarize_content(obs["content"])
|
||
})
|
||
else:
|
||
masked.append({
|
||
**obs,
|
||
"masked": False
|
||
})
|
||
|
||
return masked
|
||
```
|
||
|
||
## KV 缓存优化
|
||
|
||
### 前缀稳定性
|
||
|
||
KV 缓存的命中率取决于前缀的稳定性。稳定的前缀支持跨请求复用缓存。动态前缀会使缓存失效并强制重新计算。
|
||
|
||
应保持稳定的元素包括:系统提示词、工具定义以及常用模板。可能变化的元素包括:时间戳、会话标识符以及查询相关的内容。
|
||
|
||
### 缓存友好的设计
|
||
|
||
设计提示词以最大化缓存命中率:
|
||
|
||
1. 将稳定内容放在开头
|
||
2. 跨请求使用一致的格式
|
||
3. 尽可能避免在提示词中使用动态内容
|
||
4. 对动态内容使用占位符
|
||
|
||
```python
|
||
# 不利于缓存:提示词中包含动态时间戳
|
||
system_prompt = f"""
|
||
Current time: {datetime.now().isoformat()}
|
||
You are a helpful assistant.
|
||
"""
|
||
|
||
# 有利于缓存:提示词稳定,动态时间作为变量
|
||
system_prompt = """
|
||
You are a helpful assistant.
|
||
Current time is provided separately when relevant.
|
||
"""
|
||
```
|
||
|
||
## 上下文分区策略
|
||
|
||
### 子代理隔离
|
||
|
||
将工作分配到多个子代理中,以防止任何一个上下文增长过大。每个子代理使用干净的上下文,专注于其子任务。
|
||
|
||
### 分区规划
|
||
|
||
```python
|
||
def plan_partitioning(task: Dict, context_limit: int) -> Dict:
|
||
"""
|
||
根据上下文限制规划如何对任务进行分区。
|
||
|
||
返回分区策略与子任务定义。
|
||
"""
|
||
estimated_context = estimate_task_context(task)
|
||
|
||
if estimated_context <= context_limit:
|
||
return {
|
||
"strategy": "single_agent",
|
||
"subtasks": [task]
|
||
}
|
||
|
||
# 规划多代理方案
|
||
subtasks = decompose_task(task)
|
||
|
||
return {
|
||
"strategy": "multi_agent",
|
||
"subtasks": subtasks,
|
||
"coordination": "hierarchical"
|
||
}
|
||
```
|
||
|
||
## 优化决策框架
|
||
|
||
### 何时进行优化
|
||
|
||
在以下情况考虑上下文优化:上下文利用率超过 70%,回复质量随对话延长而下降,长上下文导致成本上升,或对话长度增加导致延迟升高。
|
||
|
||
### 应用何种优化
|
||
|
||
根据上下文构成选择优化策略:
|
||
|
||
如果工具输出占据上下文主导地位,应用观测屏蔽。如果检索到的文档占据主导地位,应用摘要化或分区。如果消息历史占据主导地位,应用带摘要的压缩。如果多个组件共同贡献,则组合多种策略。
|
||
|
||
### 优化效果评估
|
||
|
||
应用优化后,评估效果:
|
||
|
||
- 衡量 token 减少量
|
||
- 衡量质量保留程度(输出质量不应下降)
|
||
- 衡量延迟改善情况
|
||
- 衡量成本降低情况
|
||
|
||
根据评估结果迭代优化策略。
|
||
|
||
## 常见陷阱
|
||
|
||
### 过度激进的压缩
|
||
|
||
压缩过于激进可能会移除关键信息。务必保留任务目标、用户偏好以及最近的对话上下文。逐步增加压缩强度进行测试,以找到最佳平衡点。
|
||
|
||
### 屏蔽关键观测结果
|
||
|
||
屏蔽仍在使用的观测结果可能导致错误。跟踪观测结果的使用情况,仅屏蔽不再被引用的内容。考虑保留已屏蔽内容的引用,以便在需要时检索。
|
||
|
||
### 忽略注意力分布
|
||
|
||
中间丢失现象意味着信息放置位置至关重要。将关键信息放在注意力有利的位置(上下文的开头和结尾)。使用显式标记突出重要内容。
|
||
|
||
### 过早优化
|
||
|
||
并非所有上下文都需要优化。添加优化机制本身有开销。仅在上下文限制确实制约了代理性能时进行优化。
|
||
|
||
## 监控与告警
|
||
|
||
### 关键指标
|
||
|
||
跟踪以下指标以了解优化需求:
|
||
|
||
- 上下文 token 数量随时间变化
|
||
- 重复模式的缓存命中率
|
||
- 按上下文大小划分的回复质量指标
|
||
- 按上下文长度划分的每次对话成本
|
||
- 按上下文大小划分的延迟
|
||
|
||
### 告警阈值
|
||
|
||
针对以下情况设置告警:
|
||
|
||
- 上下文利用率超过 80%
|
||
- 缓存命中率低于 50%
|
||
- 质量分数下降超过 10%
|
||
- 成本超过基线上升
|
||
|
||
## 集成模式
|
||
|
||
### 与代理框架集成
|
||
|
||
将优化集成到代理工作流中:
|
||
|
||
```python
|
||
class OptimizingAgent:
|
||
def __init__(self, context_limit: int = 80000):
|
||
self.context_limit = context_limit
|
||
self.optimizer = ContextOptimizer()
|
||
|
||
def process(self, user_input: str, context: Dict) -> Dict:
|
||
# 检查是否需要优化
|
||
if self.optimizer.should_compact(context):
|
||
context = self.optimizer.compact(context)
|
||
|
||
# 使用优化后的上下文进行处理
|
||
response = self._call_model(user_input, context)
|
||
|
||
# 跟踪指标
|
||
self.optimizer.record_metrics(context, response)
|
||
|
||
return response
|
||
```
|
||
|
||
### 与记忆系统集成
|
||
|
||
将优化与记忆系统对接:
|
||
|
||
```python
|
||
class MemoryAwareOptimizer:
|
||
def __init__(self, memory_system, context_limit: int):
|
||
self.memory = memory_system
|
||
self.limit = context_limit
|
||
|
||
def optimize_context(self, current_context: Dict, task: str) -> Dict:
|
||
# 检查信息是否已在记忆中
|
||
relevant_memories = self.memory.retrieve(task)
|
||
|
||
# 将不需要留在上下文中的信息移至记忆
|
||
for mem in relevant_memories:
|
||
if mem["importance"] < threshold:
|
||
current_context = remove_from_context(current_context, mem)
|
||
# 保留引用,以便需要时从记忆检索
|
||
|
||
return current_context
|
||
```
|
||
|
||
## 性能基准
|
||
|
||
### 压缩性能
|
||
|
||
压缩应在保留质量的同时减少 token 数量。目标:
|
||
|
||
- 激进压缩实现 50–70% 的 token 减少
|
||
- 压缩带来的质量退化低于 5%
|
||
- 压缩开销导致的延迟增加低于 10%
|
||
|
||
### 屏蔽性能
|
||
|
||
观测屏蔽应显著减少 token 数量:
|
||
|
||
- 被屏蔽的观测结果减少 60–80%
|
||
- 屏蔽带来的质量影响低于 2%
|
||
- 延迟开销接近为零
|
||
|
||
### 缓存性能
|
||
|
||
KV 缓存优化应改善成本与延迟:
|
||
|
||
- 稳定工作负载下缓存命中率达 70% 以上
|
||
- 缓存命中实现 50% 以上的成本降低
|
||
- 缓存命中实现 40% 以上的延迟降低
|