news 2026/10/26 7:50:07

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Codex上下文压缩后Goal不中断:双层记忆与目标保留机制解析

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 主动管理压缩时机,而不是被动等压缩

压缩不是一个“事件”,而是一个“过程”。我现在的做法是主动管理压缩时机:

  1. 任务开始时先写进度文件
  2. 每一两个里程碑后更新进度文件
  3. 在上下文还很宽松的时候主动做一次轻量级总结
  4. 让这个总结成为后续会话的固定前缀

这样的好处是,即使模型自身触发了自动压缩,压缩摘要也已经有了一份高质量的“底稿”可以参考,而不是临时从头总结。实测下来,主动管理过的任务在压缩后的目标保持率远高于被动等待压缩的任务。

6.3 多轮压缩后的终极形态:把 Goal 变成可恢复的工作流

经过多次实践,我发现 Goal 模式最稳妥的用法不是“让一个会话坚持到底”,而是把它当成一个可恢复的工作流:目标是常驻的,状态是持久化的,上下文是可丢弃的临时工作区。压缩只是工作区的一次清理,目标始终在,进度始终在。

我现在跑大型重构任务的标准流程已经固定为:写 AGENTS.md → 启动 Goal 模式 → 维护进度文件 → 分阶段退出恢复 → 验证测试。上下文压缩这个操作本身,从需要担心的事变成了一个顺手可用的工具。

如果你也被“压缩后模型失忆”困扰过,不妨按上面的思路试一试。核心就是一句话:别把目标放在对话里,把它放到文件里。只要目标还在文件系统里,压缩多少轮都不会真正打断你的进度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 7:50:03

OpenMontage:程序化视频合成框架,批量生成视频的自动化方案

1. 项目缘起与核心定位第一次看到“OpenMontage”这个名字,我脑子里蹦出来的第一反应是“开放剪辑”或者“开源蒙太奇”。Montage这个词在影视行业里太经典了,指的是通过镜头组接来压缩时间、制造隐喻、传递情绪的那套手法。把Open放在前面,基…

作者头像 李华
网站建设 2026/10/26 7:46:59

Dyna-2.1物理智能体:构建端到端闭环工作流的工程实践

最近我一直在折腾 Dyna-2.1 这套面向端到端工作流程的物理智能体框架,说实话,一开始我对它的预期并不高。过去两年里市面上叫“智能体”的东西太多了,大部分只是接个大模型API,会解个数学题、写段代码就敢自称Agent。但物理智能体…

作者头像 李华
网站建设 2026/10/26 7:46:59

AI Agent设计模式与架构演进实践

1. AI Agent设计模式概述最近两年,AI Agent技术正在经历从单任务处理到复杂协作的范式转变。作为一名全程参与过多个人工智能项目落地的技术负责人,我深刻体会到设计模式在AI Agent开发中的重要性。传统的面向对象设计模式已经无法完全满足AI Agent的特殊…

作者头像 李华
网站建设 2026/10/26 7:46:44

OpenClaw飞书图片消息发送问题解析与优化

1. OpenClaw飞书消息发送图片的路径陷阱解析上周在给客户部署OpenClaw对接飞书机器人时,遇到个看似简单却折腾了半天的坑:通过filePath参数发送的图片消息,在PC端和移动端显示效果截然不同。这个现象背后涉及到文件路径处理、飞书客户端渲染机…

作者头像 李华
网站建设 2026/10/26 7:46:25

Hermes消息网关:20+渠道统一接入与两级守卫治理架构

1. 项目概述:为什么需要一个叫 Hermes 的消息网关?Hermes 不是一个新出的聊天工具,也不是某个大厂刚推的 AI 助手客户端——它本质上是一套面向企业级消息中台的轻量级、可插拔、高可控的消息路由与治理框架。我第一次在客户现场听到“Hermes…

作者头像 李华
网站建设 2026/10/26 7:45:36

VMware虚拟机安装Windows系统全流程与优化指南

1. VMware虚拟机安装Windows系统全流程解析作为IT从业者,我使用VMware虚拟化环境已有八年时间。今天要分享的是在VMware Workstation Pro上安装Windows系统的完整流程,包含从环境准备到系统优化的全链路操作指南。不同于网络上的碎片化教程,本…

作者头像 李华