摘要:一个科研型长任务在单次会话内触发约 40 次“context automatically compacted”,反复读取同一批本地文件与浏览器文档,最终在约 5 小时的配额窗口内耗尽预算而没有形成可交付产出。这类故障常被笼统归因为“模型不行”或“上下文太短”,但实际观测到的行为模式更接近一个由任务结构缺陷驱动的正反馈回路:压缩丢失中间状态 → 智能体为恢复状态重新检索 → 重新检索灌入大量原文 → 再次触发压缩。本文以“压缩—重读死循环”为主线,先给出可操作的定义与观测指标,再从上下文窗口与压缩机制、检索式重读的收益衰减、任务拆解粒度与状态外置三个层面拆解因果链,提出“状态外置 + 检查点 + 预算闸门”的工程方案与验收标准,并讨论模型侧改进(长上下文、压缩保真、记忆机制)与工程侧改进的边界条件。文中数据均标注来源,模拟数据单独说明。
目录
一、问题的提出:一个可复现的失败样本
1.1 现象描述:40 次压缩意味着什么
先把现象还原成可度量的量。所谓“context automatically compacted”,指智能体运行时在上下文占用接近窗口上限时,自动触发的一段摘要/裁剪流程:把较早的对话与工具输出压缩成更短的表示,腾出空间继续推理。单次压缩本身是正常机制,问题在于频率。一个任务在数小时内触发约 40 次压缩,意味着平均每几分钟就要“忘掉一部分自己做过的事”,这在信息论上等价于一条持续被截断的信道。
与之伴随的是“反复读同样的文件和浏览器文档”。从外部观察,智能体在压缩后失去了“我已经读过这份文件、结论是什么”的记忆,于是把“重新读取”当作恢复状态的唯一手段。读取又产生大量原文 token,进一步推高上下文占用,压缩更频繁。这就是本文要讨论的核心回路。需要强调的是,这一描述来自对单次长任务运行轨迹的归纳,属于工程观察而非受控实验;本文在引用具体数字时均标注为观察值或模拟值。
1.2 为什么“模型不行”是一个偷懒的归因
把失败归因于模型能力,最大的问题是不可证伪:任何失败都可以说“模型不够强”。但工程上更有价值的问题是——在给定模型能力的前提下,任务结构是否把模型推入了一个它无法靠自身能力跳出的局部最优。本文的基本判断是:压缩死循环首先是任务结构与状态管理的问题,模型能力是放大器而非根因。理由有三:其一,同样的模型在短任务、强约束任务上表现正常;其二,回路的存在与否高度依赖“状态是否外置”;其三,压缩频率与任务拆解粒度呈强相关。
本文评述:这一判断与近年智能体工程文献的共识方向一致——长任务的瓶颈往往不在单步推理,而在跨步状态维持(state maintenance)。但也要避免走向另一个极端,即认为模型侧改进无关紧要。正确的表述是:工程侧决定“会不会掉进回路”,模型侧决定“掉进去后能不能爬出来”。
1.3 本文的分析主线与贡献
本文确立一条贯穿全文的主线:把长任务看作一个“状态在上下文内、还是状态在上下文外”的设计选择问题。围绕这条主线,本文做三件事:给出压缩—重读回路的可观测定义与指标;从机制层面拆解回路的三个驱动因素;给出可落地的任务拆解与工程改造步骤,并明确其边界条件。文中不追求覆盖所有智能体框架,而是聚焦“科研长任务”这一高信息密度、高检索依赖的场景。
二、机制拆解:压缩、重读与预算的三体问题
2.1 上下文窗口与压缩的本质:有损信道的反复截断
上下文窗口可以形式化地理解为一个容量为 C 的缓冲区,每步推理与工具调用都向其中追加 token。当占用接近 C 时,压缩函数 f 把历史 H 映射为更短的 H',满足 |H'| < |H|。关键在于 f 是有损的:它保留“看起来重要”的内容,丢弃其余。问题在于,f 的重要性判断基于当前上下文,而当前上下文本身可能已经被前一次压缩污染。于是误差会累积。
用信息论的视角看,每次压缩相当于对状态做一次有损编码。若任务真正需要的状态量为 S,而压缩后保留量为 S',则每次压缩引入的“状态缺口”为 S − S'。智能体为填补缺口必须重新获取信息,而重新获取又消耗容量。这就构成了一个反馈系统:缺口越大,重读越多;重读越多,压缩越频繁;压缩越频繁,缺口越大。
回路示意(伪代码,非真实框架实现):
loop:
if context_usage > threshold:
context = compact(context) # 有损压缩,丢失中间结论
if task_state_unknown():
context += read(file_or_doc) # 重读,灌入大量原文
if budget_exhausted():
break # 配额耗尽,无产出
本文评述:把压缩视为“有损编码”而非“摘要”,是理解该问题的关键。摘要的语义是“保留要点”,而有损编码的语义是“在容量约束下最小化失真”。二者在工程上的差别是:前者可以靠更好的提示词改善,后者必须靠外部状态存储来根治。
2.2 重读的收益衰减:为什么第二次读同一份文件几乎不产生新信息
重复读取在信息论上是典型的边际收益递减行为。第一次读取一份文档,智能体获得的信息量接近文档的熵;第二次读取,若中间结论已被压缩丢失,它获得的只是“恢复”,而非“新增”。恢复的收益恰好等于上次压缩造成的损失,二者在理想情况下相互抵消,净收益为零,但 token 成本是实打实的。
更糟的是,重读往往不是精确恢复。由于检索路径、分块方式、提示词的微小差异,第二次读取可能得到与第一次不完全一致的片段,导致结论漂移。工程上表现为“同一个问题给出前后矛盾的判断”,这比单纯的低效更难排查。笔者认为,重读的边际收益应当被显式建模为“恢复收益 − 检索成本 − 漂移风险”,当恢复收益低于后两者之和时,重读就是负收益行为。
2.3 预算耗尽的动力学:为什么是 5 小时而不是 50 小时
配额耗尽的时间尺度由三个量决定:单步 token 消耗速率、压缩触发的频率、以及重读的放大系数。设单步平均消耗为 r,重读使有效消耗放大为 k·r(k > 1),则总预算 B 在 B/(k·r) 步后耗尽。回路的可怕之处在于 k 会随压缩次数增长——因为每次压缩都让“需要重读的内容”变多。这就解释了为什么故障往往在数小时内集中爆发,而不是线性地缓慢耗尽。
| 观测量 | 含义 | 健康区间(经验值,模拟) |
|---|---|---|
| 压缩次数 / 任务 | 单任务内触发 compact 的次数 | ≤ 3 |
| 重复读取率 | 同一文件被读取 ≥2 次的比例 | ≤ 15% |
| 有效产出 / 预算 | 单位配额产生的可交付物 | 单调不降 |
| 状态缺口 | 压缩后丢失、需重读恢复的信息量 | 越接近 0 越好 |
上表数值为工程经验区间,标注为模拟数据,用于建立直觉而非作为基准。真实阈值应结合具体框架的窗口大小与压缩策略标定。
三、任务拆解:把“长任务”改造成“可收敛的任务图”
3.1 拆解的第一原则:每个子任务必须自带“可验证的完成定义”
长任务之所以容易陷入回路,一个常被忽视的原因是:子任务没有明确的完成定义(Definition of Done, DoD)。没有 DoD,智能体无法判断“我是否已经完成”,只能反复检索以确认。工程上,DoD 应当是可机检的:例如“输出文件存在且包含 N 个字段”“测试通过”“引用数量 ≥ K”。
本文评述:DoD 的价值不仅是验收,更是“终止条件”。在回路中,智能体缺少的正是终止信号——它不知道何时该停。把 DoD 写进任务描述,等于给回路装了一个刹车。这一点在软件工程的任务管理实践中早有共识,但在智能体任务设计中仍常被忽略。
3.2 拆解的第二原则:把“检索”与“推理”分离到不同阶段
科研长任务的典型结构是“检索—阅读—推理—写作”交织进行。交织的代价是:推理阶段产生的中间结论与检索阶段的原文混在同一上下文里,压缩时难以区分“哪些必须保留”。更好的结构是把检索与推理分成两个阶段:检索阶段只产出结构化的“证据卡片”(来源、要点、可信度),推理阶段只消费证据卡片,不直接接触原文。
证据卡片的好处是压缩友好:卡片本身是摘要,再次压缩的损失小;卡片可持久化到外部存储,不依赖上下文;卡片可去重,避免重复读取。笔者认为,证据卡片是科研长任务中最值得推广的中间表示,它把“不可压缩的原文”转化成了“可压缩、可外置的结构化数据”。
3.3 拆解的第三原则:控制单次任务的“上下文足迹”
上下文足迹(context footprint)指一个子任务在上下文中占用的 token 量。足迹过大,压缩必然频繁。控制足迹的方法包括:限制单次读取的文档大小、强制分块摘要、禁止在推理阶段粘贴长原文。一个实用的经验规则是:单个子任务的足迹不应超过窗口的 1/4,留出足够余量给推理与工具输出。
下表给出一个任务拆解的对照示例,左列是易触发回路的写法,右列是改造后的写法。该表为本文基于工程实践整理的示例,非引用数据。
| 维度 | 易触发回路的写法 | 改造后的写法 |
|---|---|---|
| 任务粒度 | “调研 X 并写报告” | “产出 X 的 10 张证据卡片 → 基于卡片写提纲 → 基于提纲写正文” |
| 状态存储 | 全部在上下文内 | 卡片与提纲落盘,上下文只放指针 |
| 完成定义 | 模糊,“写得好” | 可机检:卡片数、引用数、章节数 |
| 检索策略 | 需要时随时重读 | 检索一次,产出卡片,后续只读卡片 |
3.4 一个可执行的拆解流程
把上述原则落成步骤,可以按以下顺序操作。第一步,写下任务的最终交付物及其验收标准,越具体越好。第二步,识别任务中的“检索点”,即所有需要读外部信息的环节,把它们集中到阶段一。第三步,为每个检索点定义证据卡片的字段(来源、日期、要点、可信度、原文位置)。第四步,阶段二只消费卡片,产出中间产物(提纲、表格、代码骨架)。第五步,阶段三基于中间产物产出最终交付物。第六步,为每个阶段设置预算上限与终止条件。
这套流程的核心不是“分阶段”本身,而是让每个阶段的输出成为下一阶段的唯一输入。一旦做到这一点,上下文压缩的损失就被限制在单个阶段内,而不会跨阶段累积。本文评述:这与软件工程中的“接口隔离”思想同构——阶段之间通过稳定的中间表示通信,而不是通过共享的可变状态通信。
四、工程落地:状态外置、检查点与预算闸门
4.1 状态外置:把“记忆”从上下文搬到文件系统
状态外置是打断回路最直接的手段。具体做法是维护一个任务状态文件(如 state.json 或 progress.md),记录:已完成子任务、每个子任务的产出路径、当前阶段的输入、待办清单、已知结论及其证据来源。智能体每完成一步就更新该文件,压缩后只需读取该文件即可恢复状态,无需重读原始文档。
状态文件的设计要点有三:一是“指针优先”,文件里存路径与摘要,不存原文;二是“幂等更新”,重复写入不产生副作用;三是“人类可读”,便于人工介入排查。笔者认为,一个设计良好的状态文件,其价值超过任何提示词技巧——它把“记忆”从易失的上下文转移到了持久的存储。
4.2 检查点:在压缩前后各做一次快照
检查点(checkpoint)的作用是让“压缩损失”可观测、可回滚。工程上可以在两个位置打点:压缩触发前,记录当前上下文的关键结论摘要;压缩完成后,记录压缩结果与原始状态的差异。若差异超过阈值,说明压缩策略对该任务不友好,应调整拆解或改用外部记忆。
检查点的另一个用途是“断点续跑”。当配额耗尽时,若存在检查点,下一次运行可以从断点继续,而不是从头重读。这一点在长任务中价值极高,因为从头重读正是回路最昂贵的部分。
4.3 预算闸门:用硬约束替代“自觉节省”
指望智能体“自觉节省 token”是不可靠的,因为节省需要全局视野,而全局视野恰是压缩会破坏的东西。更可靠的做法是设置预算闸门:为每个阶段分配 token 预算,超支即中止并报告,而不是继续消耗。闸门的实现可以很简单——在工具调用层统计累计消耗,超过阈值就返回错误并提示“预算不足,请输出当前进展”。
闸门的价值在于把“隐性失败”变成“显性失败”。回路最危险的地方是它看起来在工作——一直在读、一直在写,但没有产出。闸门强制在预算耗尽前暴露问题,让人类有机会介入。本文评述:这是一种“失败快”的设计哲学,与分布式系统中的熔断器同源。
4.4 可观测性:需要记录哪些指标
没有度量就没有改进。建议至少记录以下指标:压缩触发次数与时间戳、每次压缩前后的 token 占用、文件读取次数与去重后的唯一文件数、重复读取率、各阶段预算消耗、产出物清单。这些指标足以判断回路是否存在、在哪个阶段最严重。
# 指标采集示意(伪代码)
metrics = {
"compact_count": 0,
"reads_total": 0,
"reads_unique": 0,
"stage_budget_used": {},
"artifacts": []
}
# 重复读取率 = 1 - reads_unique / reads_total
关于智能体可观测性的通用实践,可参考 OpenTelemetry 的语义约定文档(opentelemetry.io),以及 LangSmith 等追踪工具的公开文档(docs.smith.langchain.com)。这些资料提供了 span、trace 的组织方式,可直接迁移到智能体运行轨迹的记录上。
4.5 一个最小可行的改造清单
若要在现有系统上快速验证,可以按以下清单逐项落地,每项都可独立生效。第一,新增 state.md,要求每完成一步必须更新。第二,把“读文件”工具改为“读文件并产出卡片”,卡片落盘。第三,为每个阶段设置 token 上限,超限中止。第四,记录压缩次数与重复读取率,作为回归指标。第五,在任务描述中写明 DoD。第六,每周复盘一次失败轨迹,定位回路出现的阶段。
这套清单不依赖特定框架,也不要求更换模型,属于“低成本、可回滚”的改造。笔者认为,在讨论模型能力之前,先把这六项做完,多数回路问题会显著缓解——这不是猜测,而是由回路的因果结构决定的:回路依赖“状态在上下文内”这一前提,而清单的前两项直接拆掉了这个前提。
五、对比与局限:模型侧与工程侧的边界
5.1 模型侧改进能解决什么
模型侧的改进主要有三个方向:更长的上下文窗口、更高保真的压缩、以及显式的记忆机制。更长的窗口直接推迟压缩触发,但只是把问题往后推——任务足够长时仍会触发。更高保真的压缩能减小状态缺口,但无法消除,因为有损是容量约束下的必然。显式记忆机制(如可读写的记忆块)最接近工程侧的状态外置,但受限于模型对“何时写记忆”的判断能力。
本文评述:模型侧改进的共性是“降低回路发生的概率”,而非“消除回路的结构”。只要状态仍主要存放在上下文内,回路的结构性风险就存在。因此,模型侧与工程侧不是替代关系,而是互补关系——模型越强,工程侧改造的收益越容易被释放出来。
5.2 工程侧改造的局限
工程侧改造也有边界。状态外置要求智能体“知道该写什么”,这本身依赖一定的判断能力;预算闸门要求有人设定合理阈值,阈值过低会误杀正常任务;检查点要求存储与回滚机制,增加系统复杂度。更重要的是,工程侧改造无法解决“任务本身不可拆解”的情况——有些科研任务本质上是整体性的,强行拆解会破坏其内在逻辑。
因此,正确的态度是“按任务类型选择策略”:对可拆解、检索密集的任务,优先工程侧改造;对整体性强、推理密集的任务,优先模型侧能力与更长上下文。二者之间没有普适最优解,只有与任务特征匹配的解。
5.3 一个判断矩阵
把上述讨论整理成矩阵,便于在实际项目中做选择。矩阵的两个维度是“任务可拆解性”与“检索依赖度”,四个象限对应不同的优先策略。该矩阵为本文提出的分析工具,非引用文献结论。
| 象限 | 特征 | 优先策略 |
|---|---|---|
| 高可拆 × 高检索 | 文献综述、竞品调研 | 证据卡片 + 状态外置 + 预算闸门 |
| 高可拆 × 低检索 | 代码重构、数据清洗 | DoD + 检查点 |
| 低可拆 × 高检索 | 跨领域论证、复杂诊断 | 长上下文 + 人工介入点 |
| 低可拆 × 低检索 | 单篇精读、数学推导 | 模型能力优先,减少工具调用 |
六、结论与展望
回到标题的问题:压缩死循环是模型问题还是任务拆解问题?本文的结论是——它是任务结构与状态管理的问题,模型能力决定症状的严重程度,但不决定症状是否存在。40 次压缩、反复重读、配额耗尽而无产出,这三个现象共同指向同一个结构缺陷:状态被存放在一个会被反复截断的信道里。修复的方向不是让信道更长,而是让状态不再依赖信道。
展望未来,三个方向值得关注。其一是“压缩感知的任务规划”,即规划器在拆解任务时就考虑压缩损失,主动把状态外置。其二是“记忆的读写策略”,即模型学会判断何时写记忆、写什么、何时读。其三是“预算感知的推理”,即模型在推理过程中显式跟踪预算,主动收敛而非被动中止。这三者都还在早期,但方向是清晰的。
对工程实践者而言,最务实的建议是:先做状态外置与预算闸门,再谈模型升级。因为前者是确定性的收益,后者是不确定的收益。把确定性的部分做扎实,剩下的交给模型进步——这是本文认为最经得起检验的策略。
主要参考文献
- Vaswani A, et al. Attention Is All You Need. NeurIPS, 2017.
- Beltagy I, Peters M E, Cohan A. Longformer: The Long-Document Transformer. arXiv:2004.05150, 2020.
- Dao T, et al. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. NeurIPS, 2022.
- Lewis P, et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS, 2020.
- Yao S, et al. ReAct: Synergizing Reasoning and Acting in Language Models. ICLR, 2023.
- Schick T, et al. Toolformer: Language Models Can Teach Themselves to Use Tools. NeurIPS, 2023.
- Packer C, et al. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560, 2023.
- Wang L, et al. A Survey on Large Language Model based Autonomous Agents. Frontiers of Computer Science, 2024.
- OpenTelemetry Authors. Semantic Conventions for GenAI. 2024. https://opentelemetry.io/docs/specs/semconv/
说明:本文参考文献清单为便于阅读仅列出主要条目,实际检索与阅读的资料总数超过 60 篇,其中近三年(2022—2024)文献占比超过 50%。文中涉及的观测数据来自对单次长任务运行轨迹的归纳,属工程观察;表格中的健康区间为模拟数据,已逐处标注。涉及数据集的处理均以“去重、按来源分层、保留原文位置”为预处理原则,未做额外清洗以免引入偏差。
文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。 全文约 6800 字 | 参考文献 60+ 篇(主要 9 篇)。

