长会话生存指南
你可能遇到过这种情况
你开了一个长会话,AI 帮你做了很多事。到第 50 轮对话的时候,你发现:
- AI 开始问你之前已经回答过的问题
- 它重新提了一个已经被否决的方案
- 它的代码质量明显下降——少了错误处理、类型定义
- 有时候它甚至开始“幻觉“——编造不存在的函数和文件
最极端的情况:AI 直接报错了——“上下文窗口超出限制”(context window exceeded),整个会话崩溃。
💡 这就是“上下文膨胀“问题:AI 的“工作记忆“有容量上限,装太多东西就会溢出。
问题的根源
AI 的上下文窗口是一个固定大小的“工作台“:
上下文窗口(例如 128K tokens)
┌──────────────────────────────────────┐
│ 系统提示(System Prompt) ≈ 5K │
│ 工具定义(Tools) ≈ 8K │
│ 记忆注入(Memory) ≈ 2K │
│ ───────────────────────────── │
│ 对话历史(前 50 轮) ≈ 80K │ ← 膨胀的主要来源
│ 工具返回结果 ≈ 30K │ ← 工具返回的内容可能很大
│ ───────────────────────────── │
│ 剩余可用空间 ≈ 3K │ ← 快满了!
└──────────────────────────────────────┘
问题在于:
- 对话历史只增不减:每轮对话都往上下文里加内容,从不删除
- 工具返回结果可能巨大:
read一个 1000 行的文件可能就占 5K tokens - 重复信息累积:AI 多次读取同一个文件,每次都占空间
两件工具:Smart Compact 和 Context Manager
你可能会问:这两个包都要装吗?答案是:推荐都装,它们解决不同层面的问题:
| 维度 | pi-smart-compact | pi-context-manager |
|---|---|---|
| 做什么 | 压缩历史对话 | 诊断 token 消耗 + 压缩工具返回 |
| 主动/被动 | 全自动触发 | 诊断需你叫 AI 跑,distill 自动 |
| 解决什么 | “历史对话太长” | “工具返回太多” + “为什么这么慢” |
| 能互相替代吗 | ❌ 不能 | ❌ 不能 |
💡 一句话总结:context-manager 帮你发现问题(token 都花哪了),smart-compact 帮你自动解决问题(压缩历史)。两个配合使用效果最佳。
pi-smart-compact — 智能压缩
Smart Compact 在上下文快满的时候自动“压缩“历史对话:
压缩前(80K tokens 的对话历史):
┌─────────────────────────────────┐
│ 用户:帮我看看 auth.ts │
│ AI:我读取了 auth.ts...(500字) │
│ 用户:加个空值检查 │
│ AI:好的,我修改了...(300字) │
│ 用户:测试一下 │
│ AI:测试结果...(200字) │
│ ... 重复 50 轮 ... │
└─────────────────────────────────┘
压缩后(15K tokens 的摘要):
┌─────────────────────────────────┐
│ 摘要: │
│ - 在 auth.ts 中添加了空值检查 │
│ - 修改了对应的测试文件 │
│ - 所有测试通过 │
│ - 使用了 JWT 认证方案 │
│ ... 关键信息保留 ... │
└─────────────────────────────────┘
两阶段压缩策略:
| 阶段 | 方法 | 说明 |
|---|---|---|
| Phase 1 | 提取关键信息(如决策、文件修改、结论) | 遍历对话,生成结构化意图摘要 |
| Phase 2 | 丢弃低价值信息(如重复的文件读取、中间调试输出) | 让 LLM 逐批判断工具结果去留 |
pi-context-manager — 诊断工具
pi-context-manager 提供了 payload_analyze 工具,帮你看清 token 到底花在哪了:
📊 Token 预算分析
System Prompt: 4,200 tokens ( 3.2%)
Tool Definitions: 8,100 tokens ( 6.2%)
Memory Injection: 2,300 tokens ( 1.8%)
Conversation: 52,400 tokens (40.0%)
Tool Results: 64,800 tokens (49.5%) ← 大头在这!
──────────────────────────────────────
Total: 131,800 / 128,000 ← 超了!
Top 3 最贵的工具调用:
1. read(src/database/schema.ts) — 8,200 tokens
2. code_graph_module_overview — 6,400 tokens
3. grep("TODO|FIXME") — 4,100 tokens
实际案例:诊断上下文崩溃
真实场景回顾
有一次,一个会话在上下文使用率只有 34.8% 的时候就崩溃了。看起来不应该——才用了三分之一啊?
用 pi-context-manager 的 budget 模式分析后发现:
问题根因:
工具返回结果中有 34.8% 是 error 输出
→ 大量重复的 "Command not found" 错误信息
→ 每次错误都消耗了 token 但没有有价值的信息
→ 累积导致上下文提前耗尽
解决方案:在 shepherd 规则中加入 after_bash 钩子,失败命令的错误输出自动截断,避免无意义的 token 消耗。
用 growth 模式看趋势
📈 上下文增长趋势
请求 #1: 15K ████
请求 #5: 28K ███████
请求 #10: 45K ████████████
请求 #15: 72K ████████████████████
请求 #20: 98K ██████████████████████████ ← 接近上限
请求 #23: 💥 崩溃!
关键发现:第 10-15 轮之间增长最快,因为那个阶段做了大量的文件搜索。
优化:用 compact 模式的 code_graph_semantic_code_search(只返回签名和位置)替代 grep(返回完整匹配行),token 消耗减少 70%。
配置 Smart Compact
通过 settings.json 安装:
{
"packages": ["pi-smart-compact"]
}
安装后默认为 手动模式(enabled: false),只在用户执行 /smart-compact 时触发。
用 /smart-compact-config auto 可开启自动接管模式。
可选的高级配置
在 .pi/smart-compact.json 中:
{
"enabled": true
}
enabled: true:自动触发(pi 触发 compact 时接管)enabled: false:手动模式(默认,只响应/smart-compact命令)
手动触发:在对话中输入 /smart-compact。
配置查看:输入 /smart-compact-config。
Payload Analyzer 的常用命令
| 命令 | 用途 | 何时用 |
|---|---|---|
budget | Token 预算分析(system/tools/history 构成) | “token 都花哪了” |
growth | 上下文增长趋势(token 随请求变化曲线) | “为什么越来越慢” |
expensive | 最贵的工具调用(Top N 排序) | “哪个工具最吃 token” |
overview | 逐消息详细分析(含 distill 事件) | “精确诊断某个时间点” |
messages | 按索引/范围/关键词定位消息 | “看看第 10 条消息说了什么” |
chain | 跨 payload 追踪同一个工具调用 | “这个调用后来怎么样了” |
chain-tcid | 跨 payload 追踪同一个 toolCallId | “验证 distill 是否压缩了这条调用” |
chain-tcid | 跨 payload 追踪同一个 toolCallId | “验证 distill 行为” |
diff | 对比两个 payload 的差异 | “这两次请求有什么不同” |
stats | 聚合统计 distill/processor 命中率 | “压缩效率如何” |
single | 分析单个 payload 文件 | “深入看一个录制文件” |
list | 列出所有录制文件 | “有哪些可以分析的” |
💡 诊断流程:先用
list看有哪些录制文件 →budget看整体分布 →expensive找大户 →messages精确定位。
Context Manager 的 Aging 和 Processor
除了 Distill,pi-context-manager 还提供了两个辅助机制:
Aging(老化淘汰)
自动淘汰长期未被引用的旧工具输出。通过 /aging-config 设置淘汰轮数。
特殊豁免:技能文件(SKILL.md)内容不会被 aging 淘汰,确保 AI 始终能看到当前加载的技能。
Tool Result Processor(后处理器)
对特定类型的工具输出做格式化精简(如 code-graph 的 AST 搜索结果、MCP JSON 输出)。通过 /processor-config 设置阈值。
/context TUI 面板
输入 /context 可以打开可视化面板,分类浏览上下文内容,手动标记不需要的内容进行删除。
最佳实践
✅ 保持长会话健康的习惯
- 用 compact 模式搜索:
code_graph_semantic_code_search(compact: true)比grep省 70% token - 及时压缩:不要等到崩溃才处理,上下文接近上限时就应该触发压缩
- 避免重复读取:用记忆记住文件内容,不要反复
read同一个文件 - 大文件分块读:用
offset/limit只读需要的部分,而不是整个文件 - 合理配置 aging:设置 8-12 轮淘汰,自动清理过时内容
- 定期用 payload_analyze 体检:长会话中途跑一次
budget,提前发现问题
✅ 诊断的优先级
上下文出问题时:
1. payload_analyze budget → 看总量分布
2. payload_analyze expensive → 找最贵的调用
3. payload_analyze growth → 看增长趋势
4. 针对性优化(换工具、加过滤、调整策略)
❌ 常见误区
- “上下文还有 50% 空间,不用担心” → 错,工具返回结果可能突然膨胀
- “压缩会丢失重要信息” → Smart Compact 优先保留决策和结论
- “重启会话就好了” → 治标不治本,下次还会遇到同样的问题
下一步
现在 AI 有了记忆、规划、规矩、复盘和压缩——它已经是一个相当能干的助手了。但它还是“被动“的——你问它才做。
能不能让 AI 主动工作?比如每天自动检查代码质量,或者自动跑一轮研究分析?
下一章,我们来看如何让 AI 自动化工作。