一、先回答:为什么不能写死固定阈值?

举个例子,固定 80%:

  • 模型上下文窗口 128k,80% 就是 102.4k。
  • 场景 A:当前对话里关键信息多,频繁压缩,重要细节被摘要丢掉,Agent 幻觉、跑偏;
  • 场景 B:当前都是无意义闲聊,明明可以多存一点历史,还是触发压缩,白白浪费算力;
  • 还有一个致命问题:震荡。压缩之后 token 降到 78%,刚压缩完,加一条消息又到 81%,立刻再次压缩,反复循环,也就是 “抖动”。

一句话总结:固定阈值忽略了任务重要性、当前消息类型、模型本身开销,还容易出现压缩抖动,不适合生产环境。

二、上下文压缩阈值,要参考哪些因素?

我们最终的阈值,是综合下面几项算出来的:

  1. 模型最大上下文窗口上限 这是天花板,比如 128k、32k,绝对不能超过窗口,否则直接报错。我们要预留一部分 token 给:系统提示词、工具返回结果、Agent 思考输出、函数调用、最终回复。 预留池是硬性开销,不能拿来存对话历史。
  2. 当前任务类型权重
    • 推理、规划、代码、复杂 RAG 任务:调高阈值,尽量少压缩,保留完整信息;
    • 简单问答、闲聊、一次性查询:阈值压低,及时压缩,节省 token;
  3. 历史消息的重要性评分 给每一条历史消息打分:关键决策、工具返回、用户核心指令是高分;普通闲聊、已经过期的中间草稿是低分。 同样 token 占用下,重要信息多,我们可以容忍更高的占用;垃圾信息多,更早触发压缩。
  4. 压缩本身的成本 压缩本身也要调用大模型做摘要,消耗 token 和耗时。如果模型延迟很高,我们要避免频繁触发压缩,阈值适当放宽。
  5. SLA、延迟指标要求 面向 C 端低延迟场景,压缩次数要少;后台离线 Agent,对延迟不敏感,可以更激进压缩。

三、核心方案:动态阈值 + 滞回(Hysteresis)机制(面试重点)

这是工业界最主流的实现方式。

1. 两个阈值,而不是一个
  • 上阈值(触发压缩线):token 占用达到这个值,启动压缩;
  • 下阈值(压缩停止线):压缩到 token 低于这个值,停止压缩。

举例:窗口 128k,预留 16k 给系统提示 + 工具输出,可用 112k。 上阈值:85%(95.2k),下阈值:65%(72.8k) 当 token 涨到 95.2k → 开始压缩;压缩到 72.8k 就停。 两个阈值拉开间隙,解决反复抖动震荡问题。这个间隙就是滞回区间。

2. 阈值动态调整逻辑

基础阈值 = 基础比例 × 可用 token 然后根据上面的因子做修正: 任务复杂、高重要性 → 上调上阈值; 简单任务、消息价值低 → 下调上阈值; 当检测到最近多次压缩都丢失关键信息,自动降低压缩激进程度,抬高下阈值。

3. 压缩策略配套(阈值只是开关,还要配压缩方式)

阈值只是决定 “什么时候压”,还要搭配不同压缩手段:

  • 摘要式压缩:把多轮对话浓缩成简短摘要;
  • 丢弃式压缩:直接丢弃分数最低、过期的历史消息;
  • 检索式压缩:把久远历史写入向量库,不放在上下文,需要的时候再召回;
  • 结构化精简:去掉冗余换行、重复内容,保留关键 JSON、参数。

四、工程上的踩坑点

  1. 不要忘记系统 prompt、工具返回、模型输出本身也要占 token,很多人只算用户历史,算错总量;
  2. 滞回区间不能太小,上下阈值差小于 10%,依然容易抖动;
  3. 压缩不是一劳永逸:压缩之后要做校验,检查摘要有没有丢失关键约束;
  4. 阈值策略要可观测:打点记录每次触发压缩的 token 数量、压缩前后 token、丢失信息情况,持续调参;
  5. 兜底策略:哪怕动态阈值,也要设置绝对硬上限,无论什么情况,不能逼近模型窗口极限,防止溢出。

五、面试一句话总结版

上下文压缩阈值不能固定,要基于模型窗口、预留 token 开销、任务类型、消息重要性、压缩开销动态计算;同时引入滞回双阈值,区分触发线和停止线,避免压缩抖动。阈值只是触发开关,还要搭配摘要、丢弃、外部检索等压缩手段,并且做好监控和兜底上限。

面试追问

Q:滞回区间设置多大合适? A:一般推荐上下阈值差距 10%~20%,根据业务对延迟、信息完整性的要求调整,信息敏感的业务拉大滞回区间。

Q:动态阈值会不会增加系统复杂度? A:会,简单 Demo 可以用固定阈值;生产级 Agent,尤其是长上下文多轮 Agent,必须动态 + 滞回,否则稳定性很难保障。

Logo

更多推荐