Agent 完成一个任务,可能连续读 5 个文件、跑 3 次搜索、执行测试——一个 turn 产出 50K+ token 的工具输出很常见。即使 1M 窗口的模型,复杂任务跑十几轮、每轮几十次工具调用,上下文也会逼近上限。窗口越大只是推迟问题,不能消除。
四个问题:怎么砍、砍哪里、什么时候砍、砍完怎么恢复。
全景架构
三道防线,各管一层:
| 防线 | 位置 | 管什么 |
|---|---|---|
| L1 实时截断 | 工具输出写入时 | 单次输出别太大 |
| Pre-Turn 压缩 | 新 turn 开始前 | 历史别累积太多 |
| Mid-Turn 压缩 | turn 执行中途 | 长任务别中断 |
一、工具输出截断
一次cat就能返回 100K token。不实时截断就写入历史的话,等需要做压缩时,光是把历史作为输入发给模型做摘要,这个输入本身就可能超过模型窗口。
保头保尾砍中间
工具输出的信息分布不均匀:
| 位置 | 通常是什么 | 保留价值 |
|---|---|---|
| 头部 | schema / header / 命令回显 | 高——结构信息 |
| 中间 | 大量数据行、重复内容 | 低——冗余 |
| 尾部 | result / error / summary | 高——结论 |
对命令输出和日志类内容,两端信息密度通常最高。不过对纯 JSON 数组类输出,头尾不一定比中间更重要——可以按工具类型配置不同截断策略。
两层截断
| 层级 | 时机 | 做法 | 目的 |
|---|---|---|---|
| L1 | 工具输出录入时 | 中间截断到上限(推荐 10K token) | 日常控速 |
| L2 | 压缩前仍超窗口 | 整段替换为一句话 | 紧急腾空间 |
L2 是 L1 的兜底。正常情况 L1 够用,工具连续返回大输出时才触发 L2。
只截输出不截输入:tool arguments 是模型生成的,一般几百 bytes;tool output 是外部系统返回的,可能 100K+。截断只作用于不可控的外部返回。
二、压缩触发——双阈值
两种失败模式需要两道防线
上下文超限有两种撞墙方式:
| 失败模式 | 现象 | 对应阈值 |
|---|---|---|
| 增速过快 | 一个 turn 内连续大量工具调用 | Scoped(推荐窗口 × 90%) |
| 逼近硬顶 | 多次小增量悄悄累积 | Full Window(推荐窗口 × 95%) |
只有一个阈值会怎样?
- 只有 Scoped → 多次"刚好不超"的小增量悄悄累积到窗口顶,没人兜底
- 只有 Full Window → 如果固定前缀没控制好(比如超过 10K token),用户没聊几句就触发(因为总量包含了固定开销)
两个阈值任一命中即触发压缩。Scoped 管日常节奏,Full Window 做绝对兜底。
什么算"增长"——BodyAfterPrefix
关键问题:系统指令算不算增长?
这里说的"系统提示词"不只是 system role 那一条消息。实际中,固定上下文通常由 system message + 构造的 user/assistant 对组成——把记忆、环境信息、few-shot 示例等以对话形式注入。这个固定前缀整体不参与压缩,但会占用窗口空间。
好的设计应该保持固定前缀精简——只放核心角色定义和行为约束,详细内容通过工具按需动态载入。即便如此,一个合理的固定前缀也有 3-5K token,如果把这部分也当成"增长"去计算,等于对话空间被白白吃掉一块。
解法:记录一个 prefill 基线,只统计基线之上的增长。
prefill 基线 = 压缩后(或会话开始时)的初始 token 总量
净增长 = 当前总 token − prefill 基线
净增长超过 Scoped 阈值 → 触发压缩
每次压缩后基线更新(因为摘要变了),新窗口从零计算净增长。
阈值跟随模型窗口
阈值按模型窗口的固定比例自动算,切换模型不用改配置。防止配出一个超过窗口的阈值。
三、触发时机——Pre-Turn vs Mid-Turn
| 时机 | 场景 | 动态上下文怎么处理 |
|---|---|---|
| Pre-Turn | 上轮结束后已超限 | 不注入,下轮自然带入 |
| Mid-Turn | turn 中途超限,还得继续 | 立即注入,放在最后用户消息前 |
这里说的动态上下文是指系统服务在对话过程中注入历史的运行时信息——当前文件状态、环境变量、会话配置等。它和固定前缀不同:固定前缀不参与压缩,动态上下文在历史中会被一起压掉。
Mid-Turn 为什么重要
只有 Pre-Turn 的话,Agent 只能在 turn 边界(两条用户消息之间)压缩。但一个 turn 可能包含 20+ 次工具调用——一个任务读 5 个文件 + 搜索 3 次 + 跑测试,全在一个 turn 里。
Mid-Turn 是在执行循环里插入检查点:超限了就暂停 → 压缩 → 恢复,用户无感。
四、摘要怎么写——两条路线
在讲具体怎么生成摘要之前,先说两条路线:
| 维度 | 交接式 | 结构化 |
|---|---|---|
| 思路 | 压缩 = 交接给另一个模型 | 压缩 = 拍快照存档 |
| Prompt | “为接手者写交接” | “按模板填字段” |
| 优势 | 信息完整——接手者视角不遗漏 | 格式统一——下游易解析 |
| 劣势 | 格式不可控 | 模板没覆盖的就丢了 |
| 适用 | 聊天场景、创造性任务 | 固定流程、需要结构化记忆 |
两者可以组合:交接式保内容完整,结构化模板约束输出格式。
交接式摘要
普通摘要 prompt 的问题:“请总结上面的对话”——模型会省略它认为"显而易见"的信息。
包装成交接给另一个模型。
你正在执行 CONTEXT CHECKPOINT。为即将接手任务的另一个 LLM 写交接摘要。必须包含:- 当前进展和已做出的关键决策- 重要约束和用户偏好- 明确的下一步行动- 继续工作所需的关键数据和引用接收方看到的 prefix:
另一个模型已开始处理这个问题并产出了思考摘要。你可以访问它使用过的工具状态。利用这些信息继续工作,避免重复劳动。为什么交接框架比"请总结"好?因为模型在"交接"心态下,会假设接收方什么都不知道——不会省略隐含约束,会列 next steps,会区分已完成和待完成。
压缩本身放不进窗口怎么办
渐进降级:先尝试用全量历史做压缩 → 如果超窗口,就丢掉最早的一条历史项 → 重试 → 直到 prompt 能塞进去。不是一次性失败,而是逐步妥协。
五、历史替换——摘要生成后怎么拼回去
摘要生成后,需要用它替换原始历史。注意:系统指令(system prompt)始终作为固定前缀发送,不进入对话历史,不参与压缩。被压缩的是对话历史中的用户消息、assistant 消息、工具调用/输出,以及动态注入的上下文(如当前文件状态、环境信息)。
90K → 12K,约 7:1 压缩比(系统指令不计入,它始终在)。
为什么这样拼?三个设计考量:
1. 保留原始用户消息——摘要会丢失措辞和隐含意图
从后往前扫描用户消息,在预算(推荐 20K token)内保留尽可能多的原文。超出预算的消息截断而非丢弃——部分保留好过完全丢失。
2. 丢弃工具调用和输出——信息已被摘要吸收
模型继续工作需要的是"做了什么、结果如何"的结论,不是原始 JSON 和完整命令输出。
注意:大部分 provider 要求 tool_use 和 tool_result 必须成对出现。丢弃时要整对丢,只删一端会导致 API 报错。
3. 重新注入动态上下文——压缩会把它一起压掉
动态上下文(文件状态、环境信息等)是系统服务在对话过程中注入历史的,压缩后丢失。需要重新注入当前版本,确保 Agent 拿到最新环境状态。
注入位置:
| 位置 | 场景 |
|---|---|
| 最后用户消息之前 | Mid-Turn——模型接着处理当前请求 |
| 摘要之后 | Pre-Turn——下轮自然注入 |
六、压缩的副作用
压缩不是免费的。做方案设计时需要考虑这些代价:
KV Cache 部分失效
压缩后对话历史被重组了。固定前缀(系统指令)保持不变能继续命中 cache,但前缀之后的内容全变了——这部分的 KV Cache 作废,需要重新 prefill。
对缓存命中率的影响:正常对话中,每轮请求只新增少量 token,前面的历史都能命中缓存,命中率通常在 90%+。压缩后,除了固定前缀外全部是新内容,命中率瞬间跌到只有前缀那部分(可能只有 10-20%)。后续几轮对话随着新的前缀逐步稳定,命中率才会恢复。
应对:保持压缩后新历史的结构稳定(固定前缀 + 摘要格式固定),让后续请求尽快重建缓存前缀。避免频繁压缩——每次压缩都是一次缓存命中率的"重置"。
Token 成本
一次压缩 = 一次完整模型调用。输入是接近满窗的历史 + 摘要 prompt,输出是 2-4K 的摘要。如果压缩频率高,额外成本可观(视场景和模型而定)。
应对:用小模型做摘要(适合事实性任务);复杂推理链的摘要可能仍需强模型,否则关键逻辑会丢失。也可以用 provider 的专用压缩端点(如果有的话,成本通常更低)。
失败路径记忆丢失
压缩丢弃了工具调用历史。工具定义和参数格式在系统指令里不会丢,但"哪条路径已经走过、哪个方案已经失败"这类试错记忆会丢失。模型可能重新尝试已经证明走不通的方案。
应对:在摘要中显式包含"尝试过什么、为什么失败、哪些路径已经排除"。
Token 计数精度
阈值判断依赖 token 计数。准确计数需要跑 tokenizer(有延迟),近似计数(按字节估算)有误差。如果估偏了:
- 估低了 → 该压缩时没压缩,下一次模型调用直接报 context length exceeded
- 估高了 → 过早压缩,浪费成本和丢失信息
应对:近似计数留安全余量(这也是为什么 Full Window 设 95% 而非 100%),关键判断点用精确 tokenizer 校验。
七、窗口管理
压缩链
每次压缩递增窗口编号:
| 窗口 | prefill 基线 | 状态 |
|---|---|---|
| Window 0 | 5K(系统指令+动态上下文) | 首次对话 |
| Window 1 | 7K(+摘要) | 第一次压缩后 |
| Window 2 | 8K(+新摘要) | 第二次压缩后 |
每个窗口独立追踪 prefill 基线。BodyAfterPrefix 只计算该窗口内的净增长。
Token Budget Reminder
临近阈值时注入一条提醒,告知 Agent 快没空间了。每个窗口只发一次。Agent 可以据此决定:收尾当前步骤、简化后续操作、或主动请求压缩。
Hooks
| Hook | 时机 | 用途 |
|---|---|---|
| Pre-Compact | 压缩前 | 保存状态到外部系统、决定是否跳过 |
| Post-Compact | 压缩后 | 记忆持久化、通知监控、校验质量 |
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~