Codex 的提示缓存策略非常有趣。
@cwolferesearch The prompt caching strategy for codex is really interesting. Ob…
Codex 的 prompt 缓存策略针对编码 agent 的长 prompt 设计,其 prompt 包含系统消息、工具规格、开发者指令、权限信息、agent 文件及用户请求。通过按层次结构组织信息,确保前缀匹配最大化缓存命中率,避免直接编辑早期信息导致缓存失效,而是在末尾插入新消息解释变化。多教师在线策略蒸馏相比多领域 RL 训练,能减少因不同领域响应长度和验证器成本差异导致的效率问题,更易整合领域特定专家。
Codex 的 prompt 缓存策略确实很有意思。显然,由于大量样板代码/系统信息,编码 agent 的 prompt 会非常长。在包含用户消息之前,prompt 包含以下所有内容:
- 系统消息。
- 工具规格。
- 模型/开发者指令(在配置文件中指定或默认加载,非用户提供的消息)。
- 权限信息。
然后,我们最终得到 agent 文件、当前环境信息以及用户的请求。这是一个超长的 prompt,但所有这些组件对 agent 来说都是必需的。此外,编码 agent 往往有很长的会话,因此 prompt 只会从这里变得更长。
这使得 prompt 缓存(即,重用先前推理调用中与当前 prompt 完全前缀匹配的计算)变得极其重要。
“通常,模型采样的成本主导了网络流量的成本,使采样成为我们效率工作的主要目标。这就是 prompt 缓存如此重要的原因,因为它使我们能够重用先前推理调用的计算。当缓存命中时,模型采样是线性的,而不是二次的。”——Codex 博客文章
尽管这个 prompt 很长,但信息是按层次结构组织的,以优化 prompt 缓存,这有助于 Codex 处理长 prompt 的成本。随着你在 prompt 中向上移动,组件在单个线程内或跨不同 Codex 实例中发生变化的可能性会降低,甚至对于系统控制的任何组件来说,变化是不可能的。例如,系统消息很少会改变,大多数工具可能在任务之间共享(例如,agent 的 shell 或网络搜索工具),但开发者指令和 agent 文件通常是项目特定的。
这个 prompt 是专门设计的,通过确保每个 prompt 来最大化缓存命中率。有趣的是,作者指出,即使 prompt 中较早的信息发生变化(例如,工具规格),他们也会避免直接编辑 prompt 中的先前信息,因为这会使得 prompt 缓存失效。相反,他们在 prompt 末尾插入一条新消息来解释工具或指令的变化,从而确保 prompt 缓存仍然有效。
这一讨论展示了 prompt 缓存对编码 agent 的重要性。如今,完全耗尽编码 agent 的上下文窗口,甚至通过在一个会话中执行多次压缩来多次达到上下文窗口,是很常见的。这导致了极其长的 prompt,缓存未命中会对响应性/效率造成严重破坏。因此,Codex 必须非常小心地确保 prompt 始终被缓存。
关于多教师在线策略蒸馏的效用,以及为什么这种方法可能优于在 RL 训练中仅包含多个领域,这是一个很好的观点。
多领域 RL 在以下两方面都可能很困难:
- 统计/建模角度(即,在多个领域上训练可能会在模型性能上产生权衡)。
- 效率角度(即,在批次中跨多个领域高效计算 rollout/优势可能很复杂)。
具体来说,不同领域可能需要不同的响应长度或成本差异巨大的验证器(例如,启发式验证与 LLM 评判)。这会在 RL 中引入任务间异质性,从而导致更多的空闲时间或产生低效。
相比之下,多教师在线策略蒸馏仍然可能有不同的响应长度,但从固定模型生成 rollout,并且训练信号的成本更恒定(除非每个教师模型的规模差异巨大)。因此,可能更容易/更高效地:
- 使用 RL 训练领域特定模型。
- 运行多教师蒸馏,将这些领域特定专家整合到单个策略中。