雨天小六

读懂 Codex(5.2):ModelsManager 的模型目录、缓存和覆盖

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

#Codex#Agent Runtime#Responses API#流式协议#软件架构

模型目录既不能每次启动都依赖网络,也不能永远相信打包时的旧数据。ModelsManager 把内置目录、磁盘缓存、远端响应和用户覆盖组合为一个有 ETag 与 TTL 的可刷新视图。

具体问题与启用条件

本节研究目录来源、刷新策略和覆盖顺序,不讨论某个模型字段如何影响请求;后者回到 5.1 和 5.4。

条件来源决定字段或状态对本机制的影响
刷新策略Online / Offline / OnlineIfUncached决定是否读取网络
磁盘缓存client version、fetched_at、TTL决定缓存能否作为远端目录
响应元数据Models ETag发现目录变化时触发刷新

协议、类型与状态所有权

状态或协议所有者生命周期关键不变量
Bundled models程序资源版本固定始终提供离线下限
Remote models + ETagModelsManager内存刷新周期同一快照内一致
models_cache.json模型缓存层跨进程,受 TTL/版本限制损坏不可阻断启动
Config overrides有效配置Session最终覆盖匹配模型字段

机制调用链如下:

RefreshStrategy
→ 尝试读取并验证磁盘缓存
→ 按策略决定远端请求
→ 用远端条目覆盖/扩展 bundled catalog
→ 应用用户 overrides
→ 排序并暴露 ModelInfo 快照
ModelsManager 根据策略、版本和 TTL 刷新目录
图 5.2-1:缓存新鲜度先判定,刷新策略再决定是否联网。

机制怎样工作

Online 会主动请求远端,Offline 完全不联网,OnlineIfUncached 只在没有可用缓存时请求。缓存是否“可用”同时检查客户端版本和 TTL;旧客户端写出的目录不会被新版本盲用。远端返回成功后,Manager 保存 models、ETag、抓取时间和客户端版本。

最终目录不是简单拼接。内置目录提供保底字段与顺序,远端条目可以补充或替换同 slug 的模型,配置覆盖最后修改明确指定的字段。缓存过半寿命后可续期,避免活跃进程在临界点集中刷新。Responses 流中出现新 ETag 时,Session 调用 refresh_if_new_etag,使目录变化能在不重启的情况下进入后续 Turn。

Python 风格伪代码

这段伪代码保留生产实现中会改变结果的状态、分支和异步边界;认证 SDK、遥测字段和 Rust 所有权样板被折叠为明确的领域对象。

class RefreshStrategy(Enum):
    ONLINE = auto()
    OFFLINE = auto()
    ONLINE_IF_UNCACHED = auto()

async def load_catalog(strategy: RefreshStrategy, cache: Cache) -> Catalog:
    cached = cache.read_if_version_and_ttl_match()
    should_fetch = strategy is RefreshStrategy.ONLINE or (
        strategy is RefreshStrategy.ONLINE_IF_UNCACHED and cached is None
    )
    remote = await fetch_models(cached.etag if cached and should_fetch else None)         if should_fetch else cached
    merged = overlay_by_slug(bundled_models(), remote.models if remote else [])
    return apply_config_overrides(merged)

async def refresh_if_new_etag(current: Catalog, etag: str) -> None:
    if etag != current.etag:
        await current.refresh_online()

失败、取消与恢复

内置模型、远端模型和用户覆盖的合并顺序
图 5.2-2:同 slug 先由远端叠加,再由配置覆盖,ETag 只负责触发刷新。
故障或边界已发生的状态对上层的结果能否直接重试恢复动作
缓存 JSON 损坏内置目录仍在忽略缓存并记录诊断按策略联网或离线退回
TTL 过期旧文件保留但不采信需要远端刷新请求模型目录
远端不可达可能已有内置/缓存使用可用下限或报刷新错误后续再刷新
未知 override slug目录未改变覆盖不生效修正配置目标

设计取舍与验证

内置目录保证离线可启动,远端目录允许服务端快速修正能力,配置覆盖给用户最后控制权。代价是同一模型字段可能有三层来源,因此合并顺序和缓存版本必须被测试固定。ETag 负责变化检测,TTL 负责时间新鲜度,二者不是重复机制。

可验证契约证据方式预期结果
新鲜缓存避免网络集成测试统计请求次数OnlineIfUncached 为零次远端请求
客户端版本变化使缓存失效缓存测试重新抓取并重写版本
配置覆盖最后生效override 测试目标字段使用用户值

Mini Codex 对照

Mini Codex 可以把内置目录写在 Python 模块中,用带版本和时间戳的 JSON 缓存模拟远端;必须把合并函数写成纯函数并测试顺序。可以省略半寿命续期,但需承认并发刷新会更粗糙。

本节边界

本节得到可用的 ModelInfo 快照。下一节说明连接客户端为什么还要再分 Session 与 Turn 两个生命周期。

评论


← 返回文章列表