资讯动态

Codex上下文压缩后Goal不中断:双层记忆与目标保留机制解析

发布时间:2026/10/26 7:50:07 来源:尧图企业网站定制
1. 先看现象上下文压缩到底“压”掉了什么先说一个我自己的实测经历。上个月接了一个跨模块重构任务要动十几个文件任务描述本身就有三千多字。Codex 进入 Goal 模式之后一口气跑了几十轮文件改了一堆期间还穿插着大量的 grep、ls、read 工具输出。跑到后面你明显能感觉到模型开始犯迷糊——明明前一分钟刚确认过的接口签名它转头又问了一遍。我心里清楚这是上下文窗口快被填满了。这时候我敲了/compact。压缩完成后模型自己输出了一段“任务继续”的说明然后接着修改下一个文件逻辑居然没有断。说实话第一次看到这个场景我是有点惊讶的。因为直觉上“压缩上下文”就是把之前的对话记录压成一段摘要摘要丢了细节模型应该“失忆”才对为什么它还能继续往下执行原来目标要搞清楚这件事先得知道你敲下/compact那一刻Codex 到底在处理什么。1.1 一个典型的长任务里Token 是怎么被吃光的Token 消耗不是均匀发生的长任务的 Token 消耗基本是锯齿状上涨。每执行一轮模型要读取当前会话的所有历史包括系统提示词和模型能力设定项目规范文件比如 AGENTS.md你和模型之间的全部对话每次工具调用的输入输出结果尤其是大文件的读取、diff 内容Goal 模式下还需要额外追踪当前目标列表、任务状态、验证结果其中大头往往是工具输出。我自己踩过的坑是在 Goal 模式里让 Codex 去读一个超长的配置文件或者日志文件一次 read 可能吃掉几万甚至十几万 Token。几轮下来窗口直接逼近上限。模型为了保证响应不超限只能开始“挤牙膏”——它倾向于丢弃较早的信息保留最近的消息这就是你观察到“越到后面越健忘”的直接原因。1.2 手动 /compact 和自动压缩触发机制不一样Codex 的上下文压缩有两种触发方式。一种是手动敲/compact命令Codex 会把当前会话的历史记录交给模型生成一份结构化的摘要然后用这份摘要替换掉原始对话内容继续后面的对话。另一种是自动触发当上下文占用达到一定阈值时系统会自动执行压缩不需要你干预。我之前有个误解以为/compact就是把之前的消息“扔了”只留一句“前面聊了很多请继续”。实际不是。Codex 在做压缩摘要时的保留逻辑是有取舍的它不只是机械地概括每一轮对话而是会尝试保留“当前执行目标”的完整性。换句话说压缩操作本身对“你现在要干什么”这件事是有偏置的摘要里会优先保留任务目标和未完成步骤。这里要区分一下普通对话场景下上下文压缩后的体验是“感觉模型失忆了”因为对话型任务的“目标”往往只存在于最近的几条消息里但 Goal 模式下不同因为 Goal 的目标并不是只存在于上下文里的临时文本它有一套更持久的状态管理机制。这个我在第二章详细说。1.3 压缩后你实际看到的东西压缩完成后Codex 会输出一段压缩摘要。我特意观察过几次摘要内容它通常包含这几类信息当前正在执行的目标列表和子任务编号已经完成的关键步骤带文件路径和具体改动点尚未执行的下一步动作过程中做出的重要决策和约束条件比如“不能修改公共接口”“保持向后兼容”也就是说压缩摘要不是流水账式的对话概括而更像一份“任务执行交接单”。模型拿到这份交接单之后再加上当前新的对话内容就具备继续执行的能力了。但这里还有一个隐含前提交接单能起效是因为模型自身的指令遵循能力在。如果摘要里目标写得不清楚或者执行过程中出现上下文之外的副作用模型一样会跑偏。这就是后面几章要深入分析的问题。2. Goal 不是聊天窗口执行单元与状态持久化的双层记忆设计为什么同样的压缩操作在普通聊天里模型会“失忆”在 Goal 模式下却可以继续我认为核心原因在于Goal 模式根本不是一个“聊天框”它是一套带执行状态机的任务系统。上下文窗口只是它的短期工作记忆而目标状态保存在另一层。2.1 Goal 模式的执行循环从目标文件到执行循环Codex 的 Goal 模式从用户输入的目标出发会在内部构建一个可跟踪的执行计划。如果你观察过整个过程会发现它和纯对话模型的行为模式完全不同普通聊天模式是“你说一句我回一句”模型没有强制的执行闭环。Goal 模式则是“目标分解 → 执行动作 → 观察结果 → 验证进展 → 决定下一步”的循环结构。每一轮结束模型都要判断“我的目标完成了没有”如果没有就会继续规划下一步动作。这个结构意味着目标状态不能只存在于上下文窗口里否则执行到一半窗口一满整个执行循环就崩了。因此系统设计上必然要有另一层状态存储把执行进度持久化下来。会话元数据和 Token 窗口是两套存储这个是理解“压缩后还能继续”的钥匙。2.2 会话元数据和 Token 窗口是两套存储Codex CLI 会将会话信息持久化在本地包括会话记录、消息历史、工具调用记录和会话元数据。这里的会话元数据不仅仅是对话内容的备份还包括了一些结构化的状态信息比如当前执行的任务列表、执行断点、已确认的决策记录。你可以做一个简单的实验在一个 Codex 会话中先建立目标并执行几轮然后退出会话再用--resume或者/resume恢复。恢复之后模型能记得之前执行到哪一步不需要你重新描述目标。这说明代码在磁盘上存了足够的上下文状态而不仅仅是终端的输出。我把这个称作两层记忆第一层Token 窗口也就是模型当前能看到的短期内容负责提供工作记忆第二层会话存储也就是持久化的状态数据负责提供长期任务状态/compact压缩的只是第一层。第二层并不受影响所以压缩之后模型仍然能从持久化状态里恢复任务目标这也是 Goal 模式能继续的底层能力。2.3 普通 Chat 模式压缩后“失忆”是因为没有第二层记忆普通对话模式没有执行计划这一说用户上一个问题问“帮我写个装饰器”模型回答完了这段对话的目标就结束了。压缩时模型要做的只是概括“用户问过什么我答过什么”任务目标不需要被额外保留。一旦摘要做得不够完整新窗口里模型看到的就是一段二手信息自然感觉像失忆了。Goal 模式不同。即使压缩摘要里没有完整保留所有细节模型仍然可以通过持久化的目标状态补回任务骨架。说得直白一点Goal 模式里任务的“主心骨”不在摘要里而在第二层存储里。摘要只是给新窗口提供一个快速理解的引子。这个差别解释了标题里的核心疑问。但光有第二层还不够因为持久化状态最终的载体仍然是文本形式的目标列表、AGENTS.md 规范、已完成步骤列表这些文本同样会进入 Token 窗口。压缩之后新窗口必须把这些内容重新加载进来模型才能实际操作。具体的加载和保留机制是第三章内容。3. 压缩算法对“目标”的偏置新窗口里任务骨架是怎么重建的前面说了两层记忆的设计但压缩后的新窗口并不是空白的。新窗口其实会被重新填充一份“浓缩的任务视图”这个视图怎么构建直接决定了 Goal 还能不能继续。3.1 压缩时显式保留的几类关键内容我从多次压缩后的摘要输出中观察Codex 的 compact 摘要会显式保留以下几类内容内容类型示例为什么重要当前目标列表重构 plan-module-betplan-service 的配置加载逻辑让模型知道“总体任务是什么”已完成步骤已迁移 3 个文件已更新 2 处测试避免重复工作和判断下一步未完成步骤剩余缓存模块、接口兼容测试提供明确的下一步执行队列关键约束不能破坏对外 API 签名防止新窗口跑偏方向最近决策选择使用文件映射而非数据库存储保持技术方向一致文件影响范围涉及文件列表和改动摘要建立新窗口的“工作地图”这并不是我的猜测而是模型在输出摘要时实际呈现的结构。压缩的本质是一次“有损压缩”但它会根据任务状态做有偏好的保留策略目标相关的信息优先级最高。所以哪怕压缩把大量对话细节丢弃了任务骨架还是完整地留在了新窗口里。3.2 AGENTS.md 和项目规范文件在新窗口里的重新注入另一个容易被忽略的机制是项目规范文件的重新加载。Codex 在每次会话开始时会把 AGENTS.md以及其他配置的规范文件作为系统提示的一部分注入上下文。当你执行/compact之后新窗口构建时同样会重新加载这些规范文件。这就形成了一个很好的“锚点效应”即使压缩摘要写得不够完整项目规范文件本身也会重新提醒模型“你正在什么项目里、要遵循什么约束、项目有哪些技术栈”。加上之前工作目录里的文件结构、代码状态模型其实可以在相当程度上重建上下文。我见过不少项目把大量上下文信息直接写在 AGENTS.md 里这是非常聪明的做法。因为这份文件相当于“外部记忆”会在每次窗口重建时自动注入而不管你压缩了多少轮。如果你的项目还没有 AGENTS.md或者里面只是敷衍写了两行字那我强烈建议你认真写一版。因为默认情况下这份文件的优先级极高甚至会影响模型的长期行为。我在自己的项目里把技术栈、目录结构、常用命令、接口设计约定、测试要求全部写进这份文件压缩之后再 resume模型的表现和压缩前几乎没有区别。3.3 目标堆栈的显式维护你可以帮 Codex 一把压缩摘要毕竟是有损的模型从摘要里恢复出来的目标不保证和你最初的意图百分之百一致。这里有一个实操技巧在压缩前主动帮模型维护一个“目标堆栈”。我在长任务中的习惯是每完成一个阶段就在对话里更新当前目标列表例如当前目标 1. 完成 config_loader.py 的迁移 2. 更新 plan_module 的依赖注入 3. 运行全部单元测试 4. 修复测试失败并保持 API 兼容 已完成步骤 1、2 下一步步骤 3、4这样即使压缩把之前的细节丢掉摘要里也会保留这份结构化的目标列表。压缩后模型看到的是一个清晰的队列而不是一坨模糊的描述。这个习惯让我在经历多轮压缩后目标偏离率明显下降。还有一个相关技巧是及时清理已完成的目标。如果目标列表里堆了十几个已完成项它们会占用 Token 空间并且干扰模型对“下一步该干什么”的判断。我通常会保留最近 3-5 个已完成项其余合并成一条“已完成 xx、yy、zz”。这就相当于给自己一份精简的“任务交接单”后续无论压缩多少次核心信息都不容易丢失。4. 让压缩后的 Goal 真正“不断线”的四个工程细节理解了机制之后接下来的问题就是怎么在实操中保证压缩后 Goald 不跑偏我经历了不少次压缩续跑的实战总结出四个工程细节每一个都踩过坑。4.1 把环境状态写进文件而不是让模型记在脑子里这是最重要的一条心得。很多长任务之所以在压缩后崩掉不是因为模型不聪明而是因为它唯一的信息来源是自身的上下文。一旦上下文被压缩所有依赖记忆的状态就不可靠了。解决办法是把状态“外置”到工作目录中。我通常会在项目根目录维护一个.codex-progress.md之类的进度文件每完成几个步骤就更新一次。内容包括当前目标已完成的任务清单遇到的问题和解决方案下一步计划然后在对话里提醒模型“进度文件在 .codex-progress.md先读它再继续”。这样即使连续压缩三次模型每次都能通过读取文件恢复完整状态。这个思路和 AGENTS.md 类似但它是动态的会随项目推进不断更新。4.2 理解--resume和 checkpoints 的语义“上下文压缩后 Goal 为什么还能继续”这个问题还有一个容易被忽略的答案Codex 的 Goal 模式在关键节点是有 checkpoints 的。你退出会话之后可以用--resume恢复这表明会话中隐藏了很多没有直接展示的持久化状态。实际操作中我很少让一个长任务在一个会话里跑到底。更稳妥的做法是分阶段跑每个里程碑完成后记录进度文件正常结束会话。需要继续时重新启动 Codex先读进度文件再继续执行。这样做有两个好处。第一每个新会话都是干净的上下文窗口不会因为上下文太长导致模型变笨第二进度文件把目标固化下来压缩与否根本不重要因为每次都是从磁盘恢复状态而不是从摘要里“猜”。4.3 配置合理的安全校验防止压缩后模型“乱来”压缩后的模型对细节的把握会下降尤其是在跨文件改动时容易忘记之前的约束。我的做法是在执行关键任务前显式要求模型做一致性检查。常见手段包括让模型在修改前先搜索所有相关引用点要求模型每次改动后运行特定测试在目标里写明“修改公共接口前必须先列出所有调用方”。有一次我让 Codex 重构一个内部工具库上下文很长经过压缩后它开始大刀阔斧地修改一个公共函数的签名。它在摘要里看到“重构该函数”但没有充分保留“该函数被 37 个模块引用”这个细节。后来我在进度文件的提醒里明确加上“禁止改变公开 API 签名修改前 grep 全部调用方”之后它再没犯过类似错误。这说明压缩后的模型本质上还是那个模型只是工作记忆变短了。你只要把关键约束放在它能重新读到的地方它就能恢复大部分能力。4.4 避免把上下文当数据库用很多人包括我一开始会把 Codex 的对话当作项目数据库使用什么都往里丢接口设计、文件路径、依赖关系、历史决策……结果上下文一旦压缩这些“数据库记录”就全部丢失了。正确的做法是把对话当作“工作台”把文件系统当作“数据库”。所有需要长期保存的信息都应该落地成文件AGENTS.md 放规范和约定进度文件放任务状态单独的 notes 文件放技术决策。对话只是操作台不背负记忆职责。一旦你养成这个习惯上下文压缩就不再是一件需要担心的事情。因为它只是把工作台上的临时文件清理了一下真正的项目状态都在文件系统里随时可以重新加载。5. 复现一次完整的压缩续跑实验从爆上下文到目标不丢失理论讲得再多不如直接跑一遍实验。我设计了一个可以复现的简单场景你可以照着做一遍感受一下 Goal 模式下压缩前后到底发生了什么。5.1 实验场景设计任务目标在一个模拟的多文件项目中完成一次涉及 4 个文件的配置加载逻辑重构。要求保持用户侧 API 不变所有测试通过最后产出一份变更说明。这个任务之所以适合用来测试压缩续跑是因为它有多文件、多步骤、有约束条件、有验证环足够模拟真实长任务的特点。5.2 关键命令和观测点启动 Goal 模式后先输入完整的目标描述和约束条件。执行几轮让模型完成前两个文件的重构。然后手动放一个占用大量 Token 的操作进去比如让模型读取一个很大的日志文件或者输出超长的 diff把上下文窗口逼到比较高的占用率。之后执行压缩命令观察压缩摘要。注意摘要里是否保留了“剩余两个文件的重构任务”和“保持 API 不变”这个关键约束。压缩后什么都不输入直接让模型继续观察它是否会自己执行下一步操作。我实验的结果是大部分情况下模型都能自己继续执行但摘要里如果没有保留“保持 API 兼容”这个约束模型很可能会在后续修改中放松对 API 变更的警惕。所以我会在压缩前主动把关键约束再强调一遍形成一个强化锚点。5.3 我在复现过程中踩过的相关坑实验过程中我遇到过一个很有意思的插曲Codex 在执行过程中跑 Maven 构建返回了一大段类似failed to execute goal on project plan-module-betplan-service的报错。刚开始我以为是自己哪里配置不对后来才发现这只是 Maven 自身的构建失败——插件执行失败、测试失败、依赖解析失败都可能产生这种输出和 Codex 的 Goal 模式没有任何关系。这个坑值得单独提一下。Codex 在长任务中会调用外部构建工具构建工具的报错信息会被写入上下文。如果你不了解这个报错的来源很容易把责任归到 Codex 头上甚至误以为是上下文压缩导致的问题。正确的排查思路是先区分报错层级。failed to execute goal来自 Maven 构建流程需要去查具体的插件报错如果是 Codex 本身的网络连接问题通常会表现为连接超时或者 endpoint 异常如果是模型服务配置问题则会出现 model not supported 之类的提示。这三类问题不要混在一起排查。另外我在实验中发现/compact不是万能的。如果上下文快满的时候正好赶上模型要输出一个非常大的 diff它可能会在摘要生成过程中出问题。稳妥的做法是在压缩前先主动结束当前动作把状态收敛好再压缩而不是让它带着一个正在执行的操作去压缩。实验完成后我通常还会做一个验证重新启动全新会话用--resume恢复看模型是否还能继续。这个验证比压缩本身更能说明问题因为它证明任务状态确实在持久化存储层里保存了而不是只靠压缩摘要“碰运气”。6. 经历多轮压缩后的配置与使用习惯建议如果你经常跑长任务我建议你花一点时间优化自己的配置和使用习惯。这些调整不需要什么成本但能显著降低上下文压缩带来的损失。6.1 配置层面的建议Codex CLI 的配置文件里有几个和上下文管理相关的设置值得关注。比如model字段选择支持更长上下文的模型能减少压缩频率。压缩阈值相关配置也值得调一下默认设置不一定适合你的任务类型。如果你经常做一些需要长上下文的代码重构可以考虑在 config.toml 里显式开启自动压缩或者调整触发阈值。一个参考示例字段以你当前使用的版本为准model gpt-5-codex [model_limits] max_input_tokens 200000 compact_threshold 0.75这是我用过的常见配置思路。max_input_tokens 决定了模型能承载多长的上下文compact_threshold 是自动压缩触发的占水位。具体数值要根据你的实际任务规模来调整。如果你的任务普遍较长阈值可以设得高一点减少压缩次数如果任务对细节要求高阈值反而要低一些让模型在小心谨慎的状态下更频繁地整理上下文。但记住一点配置只是辅助。真正决定压缩后能不能继续的是你是否把状态成功外置到了文件系统里。6.2 主动管理压缩时机而不是被动等压缩压缩不是一个“事件”而是一个“过程”。我现在的做法是主动管理压缩时机任务开始时先写进度文件每一两个里程碑后更新进度文件在上下文还很宽松的时候主动做一次轻量级总结让这个总结成为后续会话的固定前缀这样的好处是即使模型自身触发了自动压缩压缩摘要也已经有了一份高质量的“底稿”可以参考而不是临时从头总结。实测下来主动管理过的任务在压缩后的目标保持率远高于被动等待压缩的任务。6.3 多轮压缩后的终极形态把 Goal 变成可恢复的工作流经过多次实践我发现 Goal 模式最稳妥的用法不是“让一个会话坚持到底”而是把它当成一个可恢复的工作流目标是常驻的状态是持久化的上下文是可丢弃的临时工作区。压缩只是工作区的一次清理目标始终在进度始终在。我现在跑大型重构任务的标准流程已经固定为写 AGENTS.md → 启动 Goal 模式 → 维护进度文件 → 分阶段退出恢复 → 验证测试。上下文压缩这个操作本身从需要担心的事变成了一个顺手可用的工具。如果你也被“压缩后模型失忆”困扰过不妨按上面的思路试一试。核心就是一句话别把目标放在对话里把它放到文件里。只要目标还在文件系统里压缩多少轮都不会真正打断你的进度。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑