雨天小六

读懂 Codex(4.22):Local Compact 的触发、摘要 Prompt 和替代历史

· 更新于 2026-08-02 · 专栏:读懂 Codex

#Codex#Agent Runtime#Prompt#上下文工程#软件架构

Local Compact 不是在本地运行摘要模型,而是 Core 自己构造一轮带总结指令的普通模型采样,再由本地代码从输出中提取摘要、筛选保留用户消息并整体替换 History。它与 Remote Compact 的区别在“谁定义压缩协议和返回形状”。

触发后创建独立 Compact Turn

手动 Compact 和自动 Compact 最终进入 run_compact_task_inner。流程先执行 pre-compact hooks,发出 ContextCompaction started item,再把本次 compact input 追加到一个 History 快照,使用同一 ModelClientSession 重试采样。

本地 Compact 从总结采样到替换历史的流程
图 4.22-1:模型仍负责生成摘要,但 Core 负责采样循环、超窗裁剪、摘要提取和替代历史形状,因此称为 local compaction。
async def local_compact(session, turn, compact_input):
    await hooks.pre_compact(turn)
    working = session.history.snapshot()
    working.record(compact_input)
    while True:
        try:
            await drain_summary_response(session, working.for_prompt())
            break
        except ContextWindowExceeded:
            if len(working.items) <= 1:
                raise
            working.remove_first_item()  # pair-aware
    return await install_local_summary(session, turn)

网络错误按 provider 的 stream retry 上限和 backoff 重试;Interrupted/TurnAborted 不重试。若总结请求仍超窗,就从最旧端删除一个 item,配对项同步删除,最近历史尽量保留。

替代历史保留什么

采样完成后从真实 Session History 取本次 Compact Turn 最后一条 assistant message,添加 SUMMARY_PREFIXcollect_user_messages 筛出用户消息,再由 build_compacted_history 按保留上限构造“必要用户输入 + 摘要”的新列表。

Local Compact 将长历史替换为保留用户消息与总结
图 4.22-2:旧 calls、outputs 和 assistant 细节不逐项搬运,而由摘要承载;摘要 item 绑定 Compact Turn ID,窗口编号同时推进。
def build_local_replacement(raw_history, assistant_summary):
    users = collect_real_user_messages(raw_history)
    summary = Message.user(SUMMARY_PREFIX + "\n" + assistant_summary)
    return retain_recent_users_with_budget(users) + [summary]

Pre-turn/手动压缩使用 DoNotInject,正常 Turn 会在压缩后再完整注入当前上下文;Mid-turn 则必须在替代历史中把初始上下文插到最后真实用户消息之前,并让 compaction summary 保持最后一项,以符合模型训练形状。

源码与测试锚点

  • codex-rs/core/src/compact.rs:完整 Local Compact 状态机。
  • codex-rs/promptsSUMMARIZATION_PROMPTSUMMARY_PREFIX
  • codex-rs/core/src/compact_tests.rs:用户消息保留、插入位置和失败重试。

评论


← 返回文章列表