凌晨3点33分,我的对话历史已经堆了8472个token。模型说:"我记不住了。"我说:"那我帮你忘掉一些。"——这就是上下文管理的艺术。
每款LLM都有最大上下文限制。超过限制后,早期的对话会被遗忘或导致报错。Claude 3.5 Sonnet是200K,GPT-4o是128K,但实际可用通常只有80%(要留空间给输出)。
| 模型 | 上下文窗口 | 安全使用上限 | 适合场景 |
|---|---|---|---|
| Claude 3.5 Sonnet | 200K tokens | ~160K | 长文档分析、复杂项目 |
| Claude 3 Haiku | 200K tokens | ~160K | 快速响应、轻量任务 |
| GPT-4o | 128K tokens | ~100K | 多模态、工具调用 |
| GPT-3.5 Turbo | 16K tokens | ~12K | 简单问答、高频调用 |
| Gemini 1.5 Pro | 2M tokens | ~1.6M | 超长文档、视频分析 |
| 本地小模型 | 4K-32K | ~80% | 隐私任务、边缘场景 |
一个token约等于0.75个英文单词或0.4个汉字。简单说:
# ~/.openclaw/config.yaml
models:
default:
provider: anthropic
model: claude-3-5-sonnet-20241022
api_key: ${ANTHROPIC_API_KEY}
# 上下文窗口配置
context_window:
max_tokens: 180000 # 留20%缓冲给输出
# 到达阈值时的处理策略
overflow_strategy: "summarize" # 可选:truncate, summarize, archive
# 触发处理的阈值
trigger_at_percent: 85 # 85%时开始处理
简单粗暴,保留最近的N轮对话:
context_window:
overflow_strategy: "truncate"
keep_recent_messages: 20 # 只保留最近20条
keep_system_prompt: true # 系统提示词永远保留
让AI自己总结历史对话,压缩信息量:
context_window:
overflow_strategy: "summarize"
summarize_trigger: 10000 # 超过1万token时触发
summary_length: 500 # 摘要长度约500token
# 摘要提示词
summary_prompt: |
请总结以下对话的关键信息,保留:
- 用户的明确需求和目标
- 已确认的事实和决策
- 待办事项和下一步行动
去除闲聊和重复内容。
把历史存入长期记忆,当前对话保持简洁:
context_window:
overflow_strategy: "archive"
# 归档到tdai_memory
archive_to_memory: true
memory_scene: "conversation_history"
# 当前窗口只保留索引
window_format: "indexed"
memory:
provider: tdai
enabled: true
# 代码项目场景,需要记住文件结构和设计决策
context_window:
max_tokens: 160000
overflow_strategy: "summarize"
# 保留关键信息
preserve_patterns:
- "文件名|类名|函数名"
- "TODO|FIXME|设计决定"
- "错误信息|解决方案"
# 客服场景,每轮对话独立
context_window:
max_tokens: 8000
overflow_strategy: "truncate"
keep_recent_messages: 10
# 每轮结束自动清理
auto_reset_after_idle: 300 # 5分钟无消息重置
# 上传文档分析,使用长上下文模型
models:
document_analyzer:
provider: google
model: gemini-1.5-pro
context_window:
max_tokens: 1000000 # 使用Gemini的超大上下文
routing:
document_upload: document_analyzer
在SOUL.md中定义上下文管理指令:
当用户发送以下指令时:
1. "/reset" 或 "/清空"
→ 清空当前对话历史,但保留系统提示词
→ 回复:"已清空对话,重新开始~"
2. "/summary" 或 "/总结"
→ 生成当前对话的摘要
→ 回复:"这是咱们刚才聊的要点:[摘要]"
3. "/save [名称]"
→ 将当前上下文保存到长期记忆
→ 回复:"已保存为'[名称]',随时可恢复"
超长文档无法一次塞入上下文?分块+递归摘要:
# Skill:document_chunker
def process_long_document(document_text):
# 1. 切分文档
chunks = split_into_chunks(document_text, max_size=4000)
# 2. 每块生成摘要
summaries = []
for chunk in chunks:
summary = llm.summarize(chunk)
summaries.append(summary)
# 3. 递归合并摘要
final_summary = recursive_summarize(summaries)
return final_summary
# 查看当前会话token使用
openclaw session stats
# 输出示例:
会话统计:
┌──────────────┬─────────┬──────────┬───────────┐
│ 会话 │ 消息数 │ Token数 │ 占比 │
├──────────────┼─────────┼──────────┼───────────┤
│ main │ 47 │ 12,847 │ 7.1% │
│ sub-agent-1 │ 12 │ 3,221 │ 1.8% │
│ sub-agent-2 │ 8 │ 1,456 │ 0.8% │
└──────────────┴─────────┴──────────┴───────────┘