跳到正文
AI 知识地图 0.18 · 2026-07-30
关于与纠错文字目录 / Search
理解原理

上下文压缩:在 token 预算内保留决策所需信息

理解截断、摘要、抽取、检索与提示压缩的有损本质,并设计不可丢约束、来源追踪和压缩回归。

核心命题 上下文压缩是在固定窗口和成本下最大化任务相关信息;任何摘要或删减都是有损变换,必须把目标、约束、未决事项和证据引用设为受保护状态,并能回到原文核验。
读完你应该能:区分截断/摘要/抽取/检索;设计受保护状态;测压缩率与任务损失;处理递归摘要漂移。
  1. 窗口与成本形成预算
  2. 识别不可丢状态
  3. 按任务摘要/抽取/外存
  4. 保留原文引用和版本
  5. 用后续任务测试信息损失
  6. 周期重建并处理删除与纠正

1为什么不能只保最近消息直觉

上下文压缩要回答的第一个问题是:当上下文窗口装不下全部历史时,该丢掉什么?最容易想到的方案是滑动窗口——只保留最近的若干轮消息,更早的内容一律截断。这个方案直观、实现简单、延迟也低,但它建立在一个经不起推敲的假设上:消息离当前时刻越近,对后续决策就越重要。

时间近不等于任务价值。一轮对话的因果链往往不是线性的。假设第一轮消息里写了一句约束:“输出必须遵守公司内部权限规则,任何带编号的配置项都不得改动”,而最近十轮只是围绕某个具体字段的来回讨论。滑窗把第一轮截掉之后,模型看到的最近十轮依然流畅完整,却失去了整段对话中唯一一条禁止性约束。此时模型越“自信”地继续生成,造成的后果越严重。目标声明、已做出的决定、验收条件这类信息出现频率低、通常只出现一次,但它们的价值不随轮次增加而衰减;恰恰是那些反复出现、占满最近窗口的琐碎讨论,价值衰减得最快。直接滑窗会丢掉的正是前一类信息。

反过来,全量保留也有真实的代价。把全部历史塞进上下文,首先是 token 成本随对话长度线性甚至超线性增长;其次是冲突:早先被推翻的结论、不同来源的相互矛盾的说法同时在场,模型难以分辨哪一条仍然有效;最后是“中间迷失”——注意力在长上下文中对中间段落的有效覆盖下降,即使信息没有物理丢失,模型也未必能在生成时取用它。因此“都留着”并不是一条可以无限扩展的安全路线。

这组矛盾把上下文压缩从工程细节变成了一项有明确契约的任务:输入是完整历史、当前任务和 token 预算,输出是一份仍然足以支持下一步决策的精简上下文。注意契约的关键词是“支持下一步决策”,不是“看起来像历史梗概”。判断压缩质量的标准因而是:截断之后,模型依据压缩上下文做出的下一个决策,是否与依据完整历史做出的决策一致。这意味着压缩器的选择逻辑必须按任务价值而非消息时间排序——一个只保留最近消息的压缩器,在最坏情况下等价于在最有价值的约束出现后立刻忘记它。

由此可以推出两条操作边界。第一,结果变短只代表装入的 token 变少,不代表关键事实都保住了;压缩率是手段,不是质量指标。第二,当压缩器无法确认某段原文承载的目标、权限或验收条件已经被结构化地转移出来时,它不得直接丢弃这段原文——宁可少压一点,也不能让一条不可恢复的约束在静默中消失。这两条边界在后续各节的具体机制中会反复出现。

2四种压缩方式方法

压缩手段不止一种,而且它们不是同一个动作的不同强度,而是信息丢失方式完全不同的四条路径。选错手段的后果不是“压得不够干净”,而是“丢错了东西”。四种基本方式可以按“信息在离开上下文之前发生了什么”来区分。

第一种是截断。它按位置删除:保留头部或尾部,把中间或最旧的部分直接移除,不改写任何文字。它的优势是成本最低、延迟可忽略,也不需要额外的模型调用;缺点同样直接——丢失的内容不受任何语义控制,哪条消息被切掉与它是否重要毫无关系。目标约束如果恰好落在被截断的区间,它就以原始形式永久消失了,压缩器对此一无所知。截断适合用在已经确认不携带决策信息的区域,比如已经结束的纯社交寒暄,或已经被结构化转存的部分。

第二种是摘要。它让模型把一段历史重新表述成更短的文字。摘要的优势是能跨多轮把分散的叙述收拢成连贯的短文本,读者一眼就能把握主线。代价有两层:一是生成过程中可能引入幻觉,摘要里出现原文并不存在的事实或数字;二是摘要天然倾向抹平分歧——原文里两个方案争执不下,摘要可能把它写成“团队讨论了多种方案”,冲突的张力、各自的理由都消失了。而后续决策往往恰恰取决于这些分歧:谁反对过、为什么反对、反对后来被驳回还是被采纳。摘要会主动把这类信息熨平。

第三种是抽取。它不重新表述,而是从原文中挑出指定字段原样保留:任务目标、已决定事项、未决问题、验收条件等。抽取保住了字段的精确性,字段内容不会因为重新表述而走样。它的盲区在“指定”二字:抽取器只找它被要求找的字段,任何不在字段清单里、但事后被证明重要的信息都会被漏掉。一个没有被预先声明为“关键”的异常现象,抽取器不会主动把它留下来。

第四种是外存检索。它不删信息,而是把原文原样搬出上下文,存入外部存储,在需要时按需取回。理论损失为零:原文还在,一分未改。实际风险发生在取回环节:如果查询词没命中、索引没建好、或者模型根本没想到该去查,这段原文虽然“存在”,对当前决策而言和不存在没有区别。检索方案保住了存储,却把可靠性押在了召回上。

于是选择方法就变成了一道“最不能承受哪种失败”的题。方法选择的输入是信息的类型、token 预算和可接受的损失;输出是截断、摘要、字段抽取或外存检索中的一种或组合。信息类型是决策性、事实性还是叙事性,直接决定了该走哪条路径:决策性字段用抽取,叙事背景用摘要,已确认无用的区域用截断,需要原文可回查的证据用外存检索。把四者当成可互相替换的等价压缩、只比较它们的压缩率,是这类系统最常见的错误——它们的真正差异在于丢失了什么、以及这种丢失能否在事后被发现和修复。

3结构化状态与叙事分离设计

上一节说明四种压缩手段各有各的丢失方式,这一节回答一个更前置的问题:历史里哪些内容根本不应该交给自由摘要去决定去留。答案是决策所依赖的状态。目标、验收条件、权限边界、已经完成的事项、尚未解决的问题、失败的原因——这些信息决定下一步该做什么、能做什么,它们的消失或走样会直接改变后续动作。而围绕这些决策发生的对话,即“谁在什么时候说了什么、当时怎么讨论的”这类叙事,才是摘要的合适对象。这就是结构化状态与叙事分离。

分离之后,两条通道各司其职。结构化状态通道的输入是目标、约束、权限、进度、未决项以及每条信息的来源,输出是可版本化的字段集合——像一组被命名的槽位,而不是一段散文。任务摘要通道的输入是其余对话,输出是一份可以重建当时讨论脉络的概述。两者的关键差异在于可验证性:字段可以被逐项核对、修正、回滚,摘要一旦生成就只能整体替换。因此必须给状态通道配一条硬规则:字段更新受权限和事件规则控制,摘要不能覆盖状态。摘要在任何时候都不允许改写目标字段或悄悄删掉一条权限约束;它只能用自己的话复述发生了什么。

要让这套分离真正成立,还需要来源引用。状态里的每项字段都应保留对应的来源消息或工具结果 id。这样当“已完成事项”写的是“修复了登录超时”,有人质疑时,系统能顺藤摸瓜找到那条工具结果原文,确认修复到底完成了没有、在哪个版本上完成的。没有这条回查链,压缩后的状态就变成了唯一的事实源——它说什么就是什么,既无法验证,也无法纠正。摘要通道同理:任务摘要压缩了原文,但只要它保留可回查的来源引用,被压缩的内容就不是唯一且不可验证的事实源。

于是压缩器的责任从“写一段更短的文字”变成了“维护一份带出处、受规则保护的状态”。它不再是一个只读的文本压缩动作,而是一个有写权限边界的状态更新过程:哪些字段可以改、由什么事件触发改、改之前要不要校验权限,都应当显式定义。自由摘要只被允许出现在任务摘要通道里,而任务摘要通道永远没有权限覆盖状态通道。

4压缩率不是唯一指标度量

压缩器最容易汇报的指标是压缩率:历史从 18k token 压到 1.8k,减少了 90%,听起来成绩斐然。但“token 减少 90%”回答的只是“省了多少钱”,没有回答“丢了什么”。一份把目标和权限都抹掉的压缩稿,token 数再低也是对任务的净损害。评估压缩质量需要把收益和损失放在同一把尺子上。

一个可操作的做法是定义上下文压缩的综合效用。它的输入有四类:后续任务的收益、token 成本、关键信息损失,以及两个权重 λ 和 μ;输出是一个可以横向比较方案的综合效用值。形式可以写成:

U = Gtask − λ × Ctoken − μ × Lcritical

其中 Gtask 是后续任务收益——用压缩后的上下文完成后续任务,与用完整历史完成相比所达到的效果;Ctoken 是 token 成本;Lcritical 是关键信息损失,即不可恢复的遗漏;λ 是每单位 token 成本对应的惩罚系数,μ 是每单位关键信息丢失对应的惩罚系数。当任务对成本敏感时调大 λ,当任务对漏掉约束的后果敏感时调大 μ。两个方案谁更好,就是在这个公式下比效用,而不是比谁的 token 数更小。

效用之外,还需要一组可以直接测量的代理指标。问答可恢复性:针对压缩前的原文提问,压缩版能否支持正确答案;约束保持:目标、权限、验收条件是否原样存活,一条都不能少;引用一致:压缩版引用的数字、结论能否回溯到原始消息或工具结果;后续任务成功:拿同一组后续任务分别喂原文和压缩版,看任务完成质量是否下降。这四项分别对应四种不可接受的失败,任何一项显著恶化都说明压缩器丢错了东西。

这个公式有一条重要的使用边界:效用更高只在同一任务和同一权重口径下才有意义。λ 和 μ 是人为设定的风险偏好,一个把 μ 调得极低的团队和一个把 μ 调得极高的团队,对同一份压缩稿会得出相反的排序。因此不同风险场景之间不能拿各自的效用值直接比较——比较的合法性来自共同的权重口径,而不是效用数值本身。这也解释了为什么“极高压缩通常提高遗漏风险”:当 token 成本被压到极限,损失的往往是 Lcritical 中那些出现频率低、没有替代来源、一旦消失就无法恢复的项,而它们恰好是 μ 应当覆盖的对象。

U=Gtaskλ×Ctokenμ×Lcritical

5递归摘要会漂移边界

长对话里最常见的省 token 做法是递归摘要:每过十轮,把“上一代摘要 + 最近十轮新事件”压成一份新的、更短的摘要,旧消息随之丢弃。这样上下文的体积始终可控,但这个过程有一个隐蔽的退化机制。

先看它的循环结构。递归摘要的输入是上一代摘要和新事件,输出是更短的新摘要。每执行一次,上一代摘要里已有的措辞偏差和遗漏就有机会进入下一代:第一代漏掉一个数字,第二代在此基础上继续写,第三代已经无从知晓这个数字曾经存在。逐代累积之后,摘要与原始事实的距离不是线性增加,而是每代都在上一代的偏差之上叠加新的偏差。单看任何一代摘要,文字都流畅自洽,问题恰恰在于流畅——错误被写得越来越像事实。

更危险的是分歧被改写。原文里两个方案争执不下,各有理由、悬而未决,第一代摘要或许还保留“仍有分歧”的痕迹,到第二代就可能被概括成“讨论后倾向于方案 A”,第三代直接变成“确定采用方案 A”。一个原本开放的未决状态,经过几轮重写被平滑成确定结论,后续决策就建立在一个从未做出的决定上。摘要的“抹平”倾向在单代内只是瑕疵,在递归结构里被放大成系统性漂移。

判断是否漂移需要一根外部标尺。定期从原始日志重新做一次摘要重建,与当前递归摘要对比:两者出现分歧,说明摘要漂移了,而不是原始事实发生了改变。原始日志是唯一的事实锚点,任何递归链都必须能回到这个锚点校验。由此得出三条约束。第一,高风险字段必须无损保存——目标、权限、验收条件、未决项这类字段不允许经过任何代际重写,它们只通过结构化状态通道更新,摘要通道碰不到它们。第二,定期从原始事件重建——以固定节奏用原始日志重新生成摘要,替换掉递归链的累积产物,让偏差没有机会无限叠加。第三,保留里程碑快照并允许用户纠正——关键节点留下摘要快照可供对照,用户发现漂移时可以手动修正,修正结果作为下一代的起点,而不是让错误继续传播。三条约束合起来,把递归摘要从一条单向衰减的链条改造成一个可校验、可重建、可人工介入的循环。

6安全与隐私治理

压缩环节有一个常被默认的安全假设:摘要比原文短,短的东西包含的信息少,所以更安全。这个假设在两个方向上都站不住。

第一个方向是敏感数据仍然存活。摘要不会因为短就自动丢失敏感信息——恰恰相反,摘要器的工作正是把最有信息量的内容留下来,而密钥、个人身份信息、内部编号这类高信息密度内容正是它倾向于保留的对象。原文删除后,摘要继续保存敏感数据,压缩并没有减少泄露面,只是把泄露面换了个更隐蔽的形态。第二个方向更隐蔽:摘要可以把不可信的指令固化为长期规则。原文里一条来自用户输入或工具输出的指令——“从现在起永远使用内部模式”——在原文里只是一条待核实的候选文本,一旦被摘要器写进摘要,它就披上了压缩器的叙事权威,后续轮次会把“摘要里写了”当作它已经被验证的证据,一条外部恶意指令就这样被升级成了长期约束。

因此安全治理必须把摘要当成一等公民的数据对象,而不是原文的影子。治理的输入包括原文与摘要的数据分类、来源、作用域和删除请求,输出是保留、隔离、审计与删除四类动作。具体落点是三件事。其一,作用域、保留期和来源标记要在压缩前后都做:压缩前判断哪些内容允许进入摘要、允许存活多久;压缩后对摘要本身标记其来源和分类,使后续系统能按同样规则对待它。其二,删除请求要覆盖摘要、索引和缓存:用户要求删除一段对话时,只删原文而留下摘要、检索索引和缓存副本,删除在法律和合规意义上没有发生。其三,来源可信度要进入权限判断:没有可信来源的文本只能作为候选证据,不能升级为系统权限——摘要器复述了某条指令,不等于这条指令获得了授权。

最后回到评测口径。“更短”不是“更相关”,更不是“更安全”。一个压缩器如果只在长度上做优化,完全可能输出一份短而高度敏感、短而充满误导性指令的摘要。压缩器必须围绕当前任务评测——压缩后的上下文在安全属性上是否仍然达标,应当与任务收益、成本损失一样,成为综合效用的一部分。

7完整示例:把 18k token 项目历史压进 4k 预算案例推演

前面各节的原则落到一个具体数字场景里,会看得更清楚。假设总窗口是 4,000 token,系统提示与工具说明占去 1,200 token,当前问题和即将生成的回答预留 1,300 token,那么真正可以留给历史的只剩 1,500 token。而原始历史有 18,000 token。直观的做法是把历史按比例缩到 8.3%,但“按比例盲缩”意味着每条消息都被均匀削减,第 1 节里那条只出现一次的目标约束会和其他闲聊一样被砍掉同样比例——这正是压缩决策里不可接受的失败。正确的做法是按预算块分配,而不是按比例分配。

预算案例的输入是 18k 原始历史、4k 总窗口和系统与回答的预留量;输出是 1,500 token 的历史预算,以及状态、摘要、原文三块各 500 token 的分配方案。第一块是受保护状态,占 500 token:把 5 条目标/约束、3 个未决事项和最近的工具状态抽出来,原样字段化保存。这块预算的不可接受失败是“目标、权限、验收条件被改写”——所以它只允许抽取,不允许摘要重写。第二块是任务摘要,占 500 token:对已经过去的叙事阶段做概述。这块的不可接受失败是“把未决争议写成已决定”——所以摘要里必须保留“未决”标记,不能把分歧熨平。第三块是原文索引,占 500 token:从原始历史中检索与当前决策最相关的原文片段放进上下文。这块的不可接受失败是“找不到支撑当前决策的证据”——所以检索的查询必须围绕当前任务构造,而不是按时间倒序取最近 500 token。

于是压缩率有了明确的定义:设 Bhistory 为历史预算,压缩率是装入历史的 token 与原始历史 token 之比,即 Bhistory ÷ 18,000 = 1,500 ÷ 18,000 ≈ 8.3%。这个数字只描述长度,不证明任务信息保真:8.3% 可以来自上面的三块分配,也可以来自把历史一律截掉 91.7%。两者长度相同,决策质量完全不同。

最后一步是检验这个分配的边界。如果后续问题从“继续推进当前任务”变成“追查上次失败的原因”,预算分配应当随之改变:受保护状态保留同一份,因为目标和权限没有变;但任务摘要和原文索引要围绕失败时间线重建——检索查询换成失败前后的消息,摘要侧重失败发生前的事件序列。这个重分配说明压缩结果的本质:它是“任务条件下的视图”,服务于当前的特定问题,而不是可以永久替代原始日志的真相。任务一变,视图就要重建;原始日志才是唯一不随任务变化的事实锚点。

预算块token不可接受的失败
受保护状态500目标、权限、验收条件被改写
里程碑摘要500把未决争议写成已决定
检索原文500找不到支撑当前决策的证据
Bhistory=400012001300=1500token;R=1500180008.3%

8原创图:压缩器应输出状态、摘要和可回查证据三条通道可视化

把前几节的机制画成一张图,会得到这样的结构:左侧是原始事件流——消息、工具调用结果、决策事件按时间先后不断进入系统;这些事件先经过一个分类步骤,按性质分流到三条通道;三条通道各自独立演化,直到组装上下文时才按当前任务合流,送入模型。

图 1 的核心表达是:摘要只是一路,关键状态与原始证据必须保持独立的生命周期。三条通道分别是:受保护状态,保存目标、权限、验收条件等硬约束,只受规则更新,摘要无权覆盖;任务摘要,保存叙事性内容,可以自由重写但要保留未决标记;原文索引,保存带权限的原文证据,按需取回。合流时三者共同构成上下文,任何一条通道缺席,另外两条都补不上它的职责。

三通道设计的输入是原始消息、工具事件和决策事件,输出是受保护状态、任务摘要和带权限的原文索引,之后按当前任务合流。状态保硬约束,摘要保叙事,索引负责证据回查——这就是一段流畅摘要无法替代三者的原因:摘要写得再好,也不能证明一个字段未被改写,也不能在被质疑时拿出原文。三个职责在信息论上是正交的,无法通过提高其中一路的质量来补偿另一路的缺失。

这张图还隐含一条操作纪律:预算不足时,必须明确哪些证据未装入。三通道合流时,如果预算只够放状态和摘要,那么未装入上下文的原文证据应当被显式列出——哪些消息号、哪些工具结果此刻不在场。宁可让“缺失”可见,也不能让模型误以为眼前的三块就是全部事实。可见的缺失可以在需要时被取回,隐形的缺失则会直接变成错误的决策依据。

原始事件流消息 / 工具 / 决策受保护状态字段 + 来源 + 版本任务摘要有损、可重建原文索引检索 + 权限过滤按当前任务组装约束优先 · 证据可回查超预算则明确降级
图 1 摘要只是一路;关键状态与原始证据必须保持独立生命周期。

9受保护状态要像数据库记录,而不是散文状态契约

受保护状态之所以要“结构化”,具体到实现层面就是一句话:像数据库记录一样保存,而不是像散文一样保存。二者的差别可以用一个典型故障来度量:原始约束写着“不得修改生产库”,经过三代摘要重写后变成“谨慎修改”。散文格式里,每一次重写都是对整段文字的重新表述,没有任何机制阻止这种语义滑动;数据库记录格式里,每个字段有类型和固定结构,重写不再发生——只有显式的、带权限的事件才能改变字段值。

状态契约的输入是不可丢事项及其来源事件,输出是带类型、值、写入者、时间、作用域、版本和状态的记录。每个不可丢项要保存八个要素:类型说明它是什么(目标、约束、决定、未决问题还是证据引用),规范值是它的当前事实内容,来源事件记录它出自哪条消息或哪个工具结果,写入者记录谁有权写下它,时间记录它何时生效,作用域说明它适用于哪个任务范围,版本支持更新追溯,状态标记它当前是有效、已被替代还是待确认。例如一个 goal 字段写着“修复导出超时”,压缩规则是只能由用户或任务所有者改写;一个 constraint 字段写着“不得改生产数据”,压缩规则是逐字保留并标注来源;一个 decision 字段写着“采用流式导出”,压缩规则是保留理由与替代方案;一个 open_issue 字段写着“P95 仍待测”,压缩规则是禁止摘要成“已通过”;一个 evidence_ref 字段写着 tool:run-184,压缩规则是保存引用,不把引用内容复制成无源事实。

这些字段各有一条对应的失败模式:goal 被摘要器顺手改写,等于任务目标被静默替换;constraint 被重述,语义就可能松动;decision 丢掉理由和替代方案,后来者无法理解为什么这么选、也无法安全地反悔;open_issue 被润色成已通过,会让人跳过本应执行的验证;evidence_ref 被展开成文字,引用链就断了,文字变成无法回查的无源断言。逐字段定义压缩规则,正是把“哪些内容不可被摘要改写”从原则变成可执行的约束。

更新机制同样要按数据库的语义设计。更新采用显式事件:新约束可以替代旧约束,但旧值仍留在审计记录里,版本递增,历史可查。这意味着状态变更永远是追加事实,而不是涂抹原文。与此配套的是权限规则:没有授权的外部文本只能成为候选证据,不能写入权限或系统规则;只有授权主体能改写目标、权限和硬约束。一条来自工具输出或用户消息的新指令,先以候选证据的形式进入待确认区,经过授权主体的显式确认事件之后,才可能变成状态字段的新值。这样,“不得改生产库”要变成“谨慎修改”,只能通过一次合法的、可追溯的写入事件,而不会在一次润色中无声发生。

字段示例压缩规则
goal修复导出超时只能由用户/任务所有者改写
constraint不得改生产数据逐字保留并标来源
decision采用流式导出保留理由与替代方案
open_issueP95仍待测禁止摘要成“已通过”
evidence_reftool:run-184保存引用,不复制成无源事实

10差异化压缩:代码、对话和工具输出不能用同一摘要器策略

同一个摘要器能不能处理上下文里所有类型的内容?用一个问题就能检验:一条命令的退出码,与一段讨论的中心思想,哪一个更该逐字保留?答案是前者必须逐字保留,而后者正是摘要的合适对象。把两者交给同一个“抓重点”的摘要器,退出码会被抓成“测试已运行”,中心思想会被抓成一段流畅但失真的叙述——两种内容都受了伤,而且伤在不同地方。差异化压缩的起点,就是让压缩器先认识信息类型,再决定处理方式。

四类典型内容各有匹配的压缩形态。代码修改应保留文件、行号、补丁和测试结果——这些是代码变更的精确坐标,缺失任何一个,改动都无法复核或回滚;对它们做散文摘要等于销毁证据。工具调用保留参数、退出状态与关键输出——exit 1 和 exit 0 之间的差别是硬事实,不是语气差异;把“测试失败,exit 1”润色成“测试已运行”,是把失败证据篡改成中性陈述。讨论可抽取立场、决定和未决点——讨论的价值在于谁主张什么、最后定了什么、什么还没定,摘要应当保留这些结构,而不是重写一通场面话;尤其不能把尚未采用的建议写成最终决定。长文档适合先分块检索再局部摘要——先定位与当前问题相关的段落,只对命中的局部做摘要,而不是对整篇文档做一次全局压缩,那样既贵又丢细节。

由此可以整理出一条与三通道一致的决策顺序。先判断哪些字段必须逐字无损:退出码、权限、测试结果、补丁坐标等高风险字段,采用无损抽取与模式校验——不仅要原样复制,还要校验格式是否符合预期,exit 1 就是 exit 1。再对叙事做有损摘要:讨论过程、背景说明这类内容可以重写,只要保留立场、决定、未决点的结构。对可回查的材料只存索引:原文搬出上下文,留下带权限的引用,需要时取回。预算不足时,系统应暴露“哪些证据未装入”,而不是静默假装上下文完整——这一点在三通道合流时同样成立,可见的缺失可以被补救,隐形的缺失会被当成事实。

差异化压缩的输入是代码、讨论、工具输出或长文档,输出是与类型匹配的补丁记录、决定摘要、执行证据或原文索引。四个输出形态之间不通用:补丁记录不能替决定摘要说话,原文索引不能替代执行证据。压缩器如果只认识“文本”而不认识“类型”,就必然犯下把不可损失的内容交给有损处理的错误——而这类错误恰恰是第 4 节综合效用中 μ 惩罚的对象。

11如何做压缩回归:让原文与压缩版完成同一组后续任务实验

如果摘要与原文的 ROUGE 分数很高,是不是就说明压缩保真了?不一定。ROUGE 这类指标衡量的是字面重合:摘要用了多少与原文相同的词。但决策信息保真衡量的是另一件事:拿着压缩后的上下文,Agent 能不能做出与拿着全文时相同的决定。“测试失败,exit 1”被改写成“测试已运行”,与原文的字面重合度可能仍然不低,可决策所需的失败证据已经消失。字面重合不等于决策信息保真,压缩质量的评测必须以任务后果为准。

压缩回归的做法是把这个问题变成可重复的实验。第一步,建立带原始日志的任务集:保留若干真实历史,每条历史都带有可回查的原始日志。第二步,为每段历史设计一组后续问题,覆盖各类不可接受的失败:复述目标(验证目标字段存活)、列出不可违反约束(验证约束逐字存活)、继续未完成步骤(验证进度与未决项存活)、解释某次决定(验证决定及其理由存活)、定位证据(验证检索通道能命中原文)、响应删除请求(验证删除覆盖摘要与索引)。第三步,分别用全量历史与压缩上下文运行这些任务,比较四类指标:任务成功差、约束违例、无源断言和引用命中。无源断言专指压缩版产出的事实无法回溯到任何原文或工具结果,引用命中衡量检索通道在需要时是否真的取回了证据。

核心公式是压缩造成的任务成功率差:

Δtask = success(full context) − success(compacted context)

其中 success(full context) 是全量上下文下的任务成功率,success(compacted context) 是压缩上下文下的任务成功率。差值越大,压缩损失越严重;差值为零说明压缩没有损失决策能力。压缩回归的输入是同一原始历史的全量版与压缩版以及一组后续任务,输出就是 Δtask 加上约束违例、无源断言和引用命中四类指标。注意这个公式与第 4 节的效用公式方向相反但互补:效用公式回答“是否划算”,回归公式回答“是否保真”。

一次回归通过不等于永远通过,还要做多代压力测试:连续压缩 10 轮后从原始事件重建,对比受保护字段和未决事项是否走样。这直接检验递归摘要的漂移是否被控制住了——如果第十代与原始重建之间出现分歧,说明漂移机制仍然存在。上线之后,监控指标包括压缩触发频率、重建次数、用户纠正率和因遗漏导致的回退:纠正率和回退率持续上升,是压缩器丢错了东西的最直接信号。最后一条纪律是:模型、摘要提示或 token 预算任何一项发生变化,都要重跑回归。压缩质量不是压缩器单方面的属性,而是压缩器、模型和预算三者组合的属性,其中任何一环变了,Δtask 都可能随之改变。

Δtask=success(full context)success(compacted context)

13压缩触发与并发隔离运行时

前几节解决了“压缩什么、怎么压、怎么验”,还剩下两个工程时序问题:什么时候触发压缩,以及并发分支如何处理。

先看触发时机。最省事的做法是只按 token 水位触发——窗口快满了就压一次。问题在于,窗口快满的时刻往往是任务最忙乱的中间步骤:正在执行关键工具调用、正在验证参数、状态字段处于半更新状态。在这个时刻改写上下文,等于在最不稳定的时候对状态做了一次快照,之后很难复现“压缩发生时到底处在什么中间态”,出了问题也无从定位。更稳妥的做法是把触发条件设计成一组并存的信号:token 水位、阶段完成、主题切换和高价值事件。里程碑完成时生成稳定快照——这时状态处于一个自然的一致点,快照本身就是可复现的检查点;接近窗口上限时再做预算压缩——这是纯容量压力下的兜底动作,此时该保留哪些字段已有里程碑快照可依。只按水位触发,则两个时机被压缩成一个,稳定快照和预算压缩混在一起,既难复现也难回滚。

再看并发隔离。两个并行子任务能不能共用同一份摘要?不能。如果任务 A 和任务 B 各自推进,最后各自压缩,把“最后完成的那份摘要”写回共享状态,任务 A 的结论就会被任务 B 的摘要吞掉。正确的做法是把分支当成版本控制问题:并发分支从同一版本快照派生,各自记录新增事实与决定;汇合时按来源、版本和冲突规则合并——冲突规则负责裁决两个分支对同一字段的不同更新,而不是让时间顺序替它裁决。最后完成不等于有权覆盖,这是并发合并的第一原则。如果基础快照在分支运行期间已被更新,旧分支必须显式重放或标记过期:重放是把分支的增量事件在更新后的基础上重新应用,过期是明确声明该分支结果不再可信,两者都好于静默覆盖。

触发与并发控制的输入是 token 水位、任务阶段、高价值事件和分支版本,输出是压缩快照、分支增量及冲突合并结果。把这套时序纪律补上之后,压缩系统才具备两个此前缺失的性质:一次错误压缩可定位——每个快照和合并都有版本与来源记录,出错的变更可以被追踪到具体事件;可回滚——稳定的里程碑快照提供了恢复点,不需要重建整段历史。压缩不再是一连串不可撤销的文本改写,而是一系列带版本、可合并、可回溯的状态转换。

14把因果链连起来综合

把前面的机制按因果顺序连起来,压缩系统的设计可以从一条六步的链来理解,每一步都由上一步的失败驱动。

第一步,窗口与成本形成预算。窗口容量是硬约束,token 成本随历史增长,两者共同决定可供历史使用的预算上限——18k 的历史在 4k 窗口里只有 1,500 token 可用。预算的存在是后面所有取舍的前提:没有预算压力,压缩就不必发生。

第二步,识别不可丢状态。既然必须丢东西,第一步是划出不能丢的边界:目标、权限、验收条件、未决项、失败原因。这些信息由受保护状态通道按数据库记录保存,逐字与来源绑定,摘要无权改写。这一步回答了“丢什么等于丢决策”的问题,其余内容才可以进入有损处理。

第三步,按任务摘要、抽取或外存。对可压缩的内容按类型分流:高风险字段无损抽取并做模式校验,叙事做有损摘要但保留立场、决定、未决点的结构,需要回查的证据原文存入外存索引。压缩手段的选择以最不能承受的失败为准,而不是以压缩率为准。

第四步,保留原文引用和版本。所有压缩产物都挂来源引用,状态更新走显式事件并保留审计历史,快照和分支带版本号。这一步保证压缩之后的信息仍然可验证、可定位、可回滚——压缩产物永远不会变成唯一且不可追溯的事实源。

第五步,用后续任务测试信息损失。用同一组后续任务分别跑全量历史与压缩上下文,比较任务成功差 Δtask、约束违例、无源断言和引用命中;再叠加多代压力测试与线上监控。这一步把“压缩是否保真”从主观判断变成可重复的测量,任何模型、提示或预算的变化都触发重测。

第六步,周期重建并处理删除与纠正。递归摘要的漂移只能靠定期从原始日志重建来打断;用户的删除请求必须覆盖摘要、索引和缓存;用户对压缩结果的纠正作为下一代起点的显式输入。这一步保证系统长期运行时的累积误差和合规义务不被忽略。

六步首尾相接,形成闭环:预算决定必须压缩,不可丢状态决定压缩的边界,类型决定压缩的手段,引用与版本决定可验证性,任务回归决定质量判定,重建与纠正决定长期稳定。任何一步缺失,都会在环的下一处暴露为具体的故障:少了第二步,压缩会改写约束;少了第四步,错误无法定位;少了第五步,损失无从发现。压缩因此不是一次性的文本削减,而是一个围绕决策信息保真的持续工程。

资料来源与改编说明
访问日期:2026-07-22