怎么考「上下文快满了:滑动窗口 / 摘要压缩 / 重要性过滤怎么选?压缩丢了关键决定怎么办?」
谁在问:二面追问重灾区;做过长会话或长任务 Agent 的面试官会一路追到「压缩丢了约束怎么办」
开场怎么问
跑长了上下文放不下,你们怎么处理?
换个问法
- 摘要压缩听起来挺好,它会丢什么?丢了你怎么知道?
- 压缩之后模型忘了用户一开始说的预算上限,这种事怎么防?
五层追问链
左边照着问,右边对着听。最后一层是压力面,不必每个候选人都问到。
具体说说你的分层方案,阈值怎么定?
- 期望
- 能给出一个可落地的结构:系统提示 + 任务状态(约束、slot、已执行动作)常驻不压 → 最近 3–5 轮原样保留(模型对最近上下文最敏感)→ 更早的对话进摘要区 → 大体量的工具结果和文档从一开始就外部化成句柄。阈值上按占用比例触发而不是按轮数(因为单轮体量差异极大),并且给压缩留出余量,别压到刚好塞下。加分:不同区块分开放置,把稳定部分放前面以利用 prompt 缓存,易变部分放后面。
- 信号
- 给得出分区 + 比例触发 + 缓存友好布局的,实现过;只答「保留最近 N 轮,其余摘要」的,是通用方案,没针对 Agent 的状态特性设计。
压缩之后模型忘了用户早前说的预算上限,导致推荐了超预算方案。怎么防?
- 期望
- 根本不该靠记忆来守约束。 三层防线:① 约束在识别到的那一刻就提取进结构化状态,不参与压缩,每次重建上下文原样注入;② 关键动作执行前用代码校验(金额超限直接拦,不问模型);③ 输出层校验(推荐结果里的价格与状态里的预算比对,不合规就重生成或拒答)。核心表达:模型可以忘,系统不能忘——凡是不能忘的,就不能只存在于自然语言历史里。
- 信号
- 把约束从对话搬进状态、并且强调用代码校验的,是工程思维;答「摘要提示词里强调要保留约束」的,还在靠模型自觉,这题就答废了。
会话很长,摘要要做很多次。反复对摘要再摘要会怎样?
- 期望
- 会出现复印机效应——每一代摘要都在上一代的有损结果上再有损,细节逐代漂移甚至变形,最后模型手里的"事实"可能和原始对话对不上,而且没人会发现。三个应对:① 摘要基于归档的原文重新生成,而不是在上一份摘要上叠加;② 限制摘要代数,到一定代数就做一次"重建"而不是"追加";③ 关键结论一旦被结构化提取出来,就以结构化形式保存,不再进入后续的自由文本摘要循环。加分:定期做一致性抽检——拿状态里的关键槽位和原文核对。
- 信号
- 能命名这个累积失真现象并提出"基于原文重建"的,遇到过;答「多摘要几次没什么问题」的,没跑过真正的长会话。
什么时候触发压缩?窗口满了再压有什么问题?成本上有什么坑?
- 期望
- 等满了再压有两个问题——这之前的若干轮已经在长上下文的低质量区做决策了;而且满的那一刻往往正处在任务中途,被迫在坏边界上切。所以要阈值触发 + 边界对齐。成本上的坑是 prompt 缓存:压缩重写前缀会让缓存全部失效,短期成本反而上升,因此"少次大压"优于"频繁小压"。还有一个隐性成本是摘要调用本身的延迟,会在用户体感上表现为某一轮突然变慢——可以做异步预压缩(在用户思考的间隙提前压)来缓解。
- 信号
- 主动提 prompt 缓存击穿并给出"少次大压"结论的,算过账;只答「快满了就压」的,及格但没有区分度。
客服 Agent 在长会话里压缩之后,反复向用户索要已经提供过的手机号和订单号,用户投诉体验差。怎么止血、怎么根治?
- 期望
- 先分清两种成因:是压缩把信息丢了,还是提取器压根没把它抽进状态?看 trace 里的状态快照就能分清——如果状态里有但模型仍然问,那是注入位置或提示词问题;如果状态里就没有,是提取环节漏了。这两种修法完全不同,不分清就会改错地方。 止血(当天):把已收集的信息做成结构化 slot 表常驻上下文、不参与压缩;更关键的是在提问前加一道代码层的检查——slot 已填就不允许再问,把这个判断从模型手里拿走。两条一起上,投诉能立刻停住。 根治:把"已确认信息"从对话历史彻底迁移到任务状态,历史只承担叙事作用;提取器覆盖所有必填 slot 并加单测;评测集里加一条专门指标——重复索取率,作为长会话的健康度看板。 体验兜底:如果确实必须再问一次(比如识别到的号码置信度低),要说明原因("我这边记录的是尾号 1234,麻烦确认一下"),而不是干巴巴地重问——用户讨厌的是"你根本没在听",而不是被问第二次。 对外沟通:给影响范围、已止血、结构性修复三段,结论落在"关键信息迁出对话历史"这个架构调整上。
- 信号
- 先分"丢了"还是"没抽到"、把提问的判断权从模型移交给代码、并且给出重复索取率这个可监控指标的,处理过真投诉;只答「优化摘要提示词让它保留用户信息」的,治标且下次还会犯。
危险信号
听到这些话,基本可以判定是背题而不是做过。
评分卡
- 三种策略的机制与各自代价说得清(尤其滑动窗口丢开头目标)
- 明确压缩目的是保决策质量,不只是省 token
- 给得出分层方案:锚定区 + 近窗 + 摘要区 + 外部化
- 列得出必须保真的信息类别(含"已失败路径"这类易漏项)
- 核心判断:关键约束应活在结构化状态里,而非对话历史里
- 关键动作执行前用代码校验约束,不依赖模型记忆
- 阈值触发 + 自然边界压缩,而不是等窗口满
- 加分:知道压缩击穿 prompt 缓存,"少次大压"优于"频繁小压"
- 加分:摘要基于原文重建,避免多代累积失真
- 加分:压缩有损但可恢复(原文归档 + 句柄回取)
参考答案与考察意图面试中途别看这一段
考察意图
这是第 3 章追问最凶的一题,因为它有一个几乎所有人都会踩的坑:把压缩当成省 token 的手段。面试官在验四层:
- 知不知道压缩的目的是保决策质量。 就算窗口塞得下,长上下文本身也会让模型变笨(context rot),所以压缩不是等窗口满了才做的事。
- 说不说得出每种策略丢的是什么。 三个方案的名字谁都会背,能讲清"滑动窗口丢的恰好是用户最初的目标"才算想过。
- 有没有"该保真的东西不该活在对话历史里"这个认知。 这是本题的分水岭。
- 算不算得清压缩本身的成本。 压缩会重写上下文前缀,直接击穿 prompt 缓存——压得太勤反而更贵。
参考答案
60 分答案(及格线)
三种策略各有取舍:
| 策略 | 怎么做 | 代价 / 丢什么 |
|---|---|---|
| 滑动窗口 / 截断 | 只保留最近 N 轮 | 最便宜、零额外调用;但丢掉的恰好是最开始的用户目标和约束——那通常是整个任务里最重要的一条消息 |
| 摘要压缩 | 把旧对话交给模型压成一段摘要 | 保住语义主干;代价是多一次调用与延迟,而且有损且不可控——具体丢了什么你不知道 |
| 重要性过滤 / 结构化提取 | 按类型抽取该留的(目标、约束、已确认参数、已执行动作、待办),其余丢弃 | 可控性最好;代价是要设计 schema 和提取器,实现最复杂 |
实际生产里三者是混用的分层结构:锚定区(系统提示、用户原始目标与约束,永不压缩)+ 近窗(最近若干轮原样保留)+ 中间区(摘要或结构化提取)+ 外部化(大块内容落盘,上下文里只留一个引用句柄)。
90 分答案(有生产经验的回答)
补四层。
1. 压缩的目标不是最大压缩率,是"保住决策所需的最小充分信息"。 判断一次压缩好不好,唯一标准是:压完之后模型还能不能做出同样正确的下一步决策。所以我会先定义必须保真的五类信息,它们不参与任何有损压缩:
- 用户的原始目标与硬约束(预算上限、截止时间、不能用某方案)
- 已经确认过的参数与决定(是 3 月不是 4 月,选的是方案 B)
- 已执行的写操作清单(不然会重复下单、重复发邮件)
- 尚未解决的待办项
- 已经失败过的路径(漏了这条,模型会兴致勃勃地把刚试过的错误方案再试一遍——这是最容易被忽略的一类)
2. 一句分水岭级的判断:这五类信息不该活在对话历史里,应该活在状态里。 把它们放进一份结构化的任务状态(slot 表 / 约束清单),每次重建上下文时原样注入,压缩只作用于对话历史那一部分。指望"摘要的时候记得把预算带上"是靠运气;把预算放进状态、并且在动作执行前用代码校验,才是工程。
3. 触发时机和边界很关键。 不要等窗口满了才压——那时模型已经在低质量区跑了一阵了。按预算阈值主动压(经验上到窗口的六七成就该动手,具体看模型,需自测)。压缩点要选在自然边界:一个子任务结束后、工具结果消化完之后,而不是在一段推理链中间切一刀。
4. 压缩的成本坑:prompt 缓存。 压缩重写了上下文前缀,缓存直接失效,之后几轮都要按未命中计费。所以压得太频繁可能比不压还贵——正确姿势是"少次、大幅、在自然边界压",而不是每轮修修补补。这一条能答出来,基本可以确认是真在长会话上算过账的。
5. 有损但可恢复。 压缩前把原文归档,摘要里保留指向原文的句柄,模型需要细节时能取回来(这正好对上 MCP 2026-07 无状态化之后"工具返回显式 handle"的范式,截至 2026-08)。这样压缩从"不可逆丢失"变成"降精度 + 可回取",风险大幅下降。