上下文管理基础
Q:上下文窗口不够用,对话太长了怎么办?
来源:Agent 岗面试高频题 / 字节 Agent 实习二面 【小红书 Agent 岗一面追问:两层压缩、LLM 保留判定与大结果落盘】
新手答:“截断早期消息,只保留最近几轮。”
高手答:
截断是最粗暴的做法,会丢失关键上下文。我们的处理分四层:
- 早期对话压缩成摘要:不是直接丢掉,而是每隔一段对话,让模型把已完成的部分压缩成结构化摘要(“用户需求是什么、已确认的参数、当前进展”),只保留摘要,释放原始 token
- 大任务拆子任务:一个 30 步的复杂任务,不要在一个上下文里硬撑。拆成 5 个子任务,每个子任务用独立对话完成,中间结果通过数据库传递,而不是全靠上下文承载
- 中间结果落库:工具调用的返回值、中间计算结果,不要全留在对话里。提取关键字段存数据库,需要时再查回来,上下文里只保留一句“已完成 XX,结果存储在 task_123”
- 按需回溯而非全量携带:不是每轮都把所有历史带上。建一个索引,标记每段对话的主题和关键实体,需要时按主题精准召回,而不是全量塞回去
核心思路是:先用工程手段省 token,实在不够再考虑模型层面的压缩。
差距在哪:新手的”截断”是单一策略,且会造成信息丢失。高手的四层方案各有分工——摘要保留语义、拆任务降低单次复杂度、落库减少冗余、按需召回精准补充。面试官考的是”你有没有在生产环境里处理过长对话的工程经验”,这不是模型能力问题,是系统设计问题。
追问:智能客服场景下,Agent 的上下文压缩机制有哪些?各自优劣?
来源:币安 AI大模型实习一面
智能客服比通用 Agent 更复杂——用户可能聊了 50 轮还没解决问题,且中间夹杂大量无效信息(寒暄、重复、情绪表达)。压缩机制需要在保留关键信息和释放 token 空间之间取舍:
| 机制 | 原理 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|---|
| 滑动窗口截断 | 只保留最近 N 轮 | 简单、零额外成本 | 丢失早期关键信息(如订单号、投诉原因) | 简单咨询,无需长记忆 |
| 摘要压缩 | LLM 定期把历史压缩成摘要 | 保留语义、释放 70%+ token | 摘要可能丢细节、额外 LLM 调用成本 | 多轮复杂咨询 |
| 关键信息外置 | 提取实体/约束存独立 state,每轮注入 | 关键信息不丢、最可靠 | 需要 NER 提取逻辑、实体识别有误差 | 涉及订单、金额等硬约束 |
| 分话题记忆 | 按话题分段,只加载当前话题完整记忆 | 话题切换时体验好 | 话题检测准确率是瓶颈 | 用户问题跨多个领域 |
| 子任务拆分 | 复杂任务拆成独立子对话,结果通过数据库传递 | 每个子任务上下文干净 | 用户感知到”被转接” | 需要跨系统协作的复杂售后 |
生产环境中的组合策略:不是选一种,而是分层组合——关键信息外置(保底)+ 摘要压缩(主力)+ 滑动窗口(兜底)。每轮对话的上下文结构:
[System Prompt] + [外置关键信息:用户ID/订单号/问题类型] + [近期摘要] + [最近3轮原始对话]追问:上下文压缩怎么避免压缩后丢失关键约束(比如否定条件、硬性限制)?
来源:阿里国际AI应用开发二面
压缩最怕丢的不是“聊了什么”,而是否定约束和硬性条件——“绝不能推荐含坚果的食物”“预算不超过 500”这类信息一旦被摘要吞掉,后续生成会直接违反用户意图。
解决方案分三层:
| 层级 | 策略 | 做法 |
|---|---|---|
| 提取层 | 约束显式外置 | 对话中出现否定词/条件句时,用规则或 NER 提取到独立的 constraints 字段,不参与压缩 |
| 压缩层 | 带约束的摘要 Prompt | 摘要指令中显式要求“保留所有否定条件和数字约束原文” |
| 验证层 | 压缩后回检 | 压缩完成后,用另一次 LLM 调用对比原文和摘要,检查约束是否丢失 |
工程实践:
# 每轮对话注入的结构
[硬性约束(从不压缩)]
- 不含坚果
- 预算 ≤ 500
[压缩摘要(定期更新)]
用户正在为朋友选生日礼物,偏好实用型...
[最近原始对话]
...核心思路:约束和摘要分离存储——摘要可以丢细节,但约束永远不压缩、不合并、不降权。这和数据库事务中“关键字段不可 null”是同一个设计原则。
Q:长上下文里,怎么让 Agent 不忘记关键信息?
来源:腾讯 Agent 岗终面
新手答:“用向量数据库存起来。”
高手答:
单一向量检索在长对话中很容易丢关键信息。我们的方案是三段式记忆:
- 滚动窗口记忆:最近 3-5 轮对话原样保留,保证强相关
- 关键实体记忆:用 NER 实时抽取用户提到的时间、地点、人物、任务,存入一个类似知识图谱的结构,随时可查
- 周期性摘要记忆:每 10 轮对话,让模型生成一段结构化摘要(“用户想做什么,目前进展到哪,遇到了什么障碍”)
查询时,三段信息同时召回,按权重融合。这样既能记住”用户对花生过敏”这种细节,又不会被 50 轮前的闲聊干扰。
模型层面的遗忘缓解机制:
除了工程手段,还有多种模型/架构层面的技术可以缓解长上下文信息遗忘:
| 机制 | 原理 | 效果 |
|---|---|---|
| 滑动窗口注意力 | 只关注最近 N 个 token,超出窗口的不计算 attention | 降低计算量,但会丢失远距离依赖 |
| 稀疏注意力(Longformer) | 局部窗口 + 全局 token 混合 attention | 平衡效率和长距离关注 |
| 关键信息锚定 | 把关键约束标记为”全局 token”,始终参与 attention | 防止关键信息被稀释 |
| 检索增强生成 | 长文本不全放上下文,关键段落按需检索注入 | 上下文精简,信息不丢 |
| 结构化状态外置 | 关键参数提取到独立 state,每轮强制注入 | 最可靠,不依赖模型记忆力 |
对于 Agent 场景,结构化状态外置是最可靠的方案——不依赖模型的 attention 分布,用系统机制保证关键信息每轮都在。模型层面的优化是锦上添花,工程层面的外置才是兜底。
差距在哪:新手的”向量数据库”是一个工具,不是方案。它解决了存储问题,但没解决“存什么、怎么查、怎么融合”的问题。高手的三段式记忆在不同时间粒度上各有分工——短期精确、中期结构化、长期摘要——这是 Memory 系统设计的核心思路。面试官考的是“你理不理解 Agent Memory 的多层次需求”。
Q:用户说“按老样子帮我订一下”,这种模糊需求怎么处理?
来源:腾讯 Agent 岗终面
新手答:“问用户‘老样子’具体指什么。”
高手答:
分两步处理,先“猜”再“问”:
- 猜:立刻检索用户的历史订单,找出时间最近、频次最高、或用户标记过“喜欢”的订单,作为候选
- 问:把候选的 1-3 个选项(例如“是订上次的 XX 酒店吗?”)清晰地抛给用户确认
绝不能模型自己去“猜”一个就执行。这个流程把模糊需求转化成了一个清晰的选择题,体验好,且不会错。
差距在哪:新手的“直接问”看起来安全,但体验差——用户说“老样子”就是不想再描述一遍,你让他重新说等于没理解他的意图。高手的“先猜再确认”是更好的交互模式:展示你理解了他的意思(通过历史数据),同时用确认保证不出错。面试官考的是“你有没有产品思维”,Agent 不只是技术系统,也是用户交互系统。
Q:多 Agent / 多异步任务下,如何防止上下文污染?
来源:字节后端开发 Agent 一面
新手答:“每个 Agent 用独立的上下文。”
高手答:
上下文污染是多 Agent 系统最隐蔽的 bug——一个 Agent 的中间状态泄漏到另一个 Agent 的上下文里,导致输出偏离。
污染来源:
- 共享上下文变量:多个 Agent 读写同一个 conversation history,A 的中间推理过程被 B 当成了事实
- 异步竞态:并行 Agent 同时更新共享状态,后写入的覆盖先写入的
- prompt 拼接错误:动态拼接 Prompt 时,把不属于当前 Agent 的信息混了进去
防治方案:
- 上下文隔离:每个 Agent 维护独立的消息历史,不共享 conversation history。需要传递信息时,通过显式的结构化消息(而不是共享上下文)
- 作用域控制:定义每个 Agent 能看到什么——只传入它的 System Prompt、当前任务描述、和上游传来的结构化结果,不传无关历史
- 状态快照:并行任务启动前,对共享状态做快照。每个 Agent 基于快照执行,结果通过合并策略写回,不直接覆盖
- 消息签名:每条消息标记来源 Agent ID,下游 Agent 可以按来源过滤,只接收自己应该看到的信息
核心原则:Agent 之间传递"结论",不传递"过程"对比后端思维:这和微服务之间不共享数据库、用 API 通信是同一个原则——进程隔离,接口通信。
差距在哪:新手只说了“独立上下文”——知道方向但没有方案。高手先分析了三种污染来源,再给出四种防治方案,且类比了后端微服务的隔离原则。面试官用“并发安全”视角考你对多 Agent 系统的理解——上下文污染本质就是“共享可变状态”问题。