BaseInstructions 是一次模型请求的顶层指令,不是 History 中的一条普通消息。Session 创建时只选择一次基础值,后续采样从 SessionConfiguration 读取;这条独立通道让恢复会话可以继续沿用原来的行为基线。
三层选择规则
| 优先级 | 候选值 | 适用场景 |
|---|---|---|
| 1 | config.base_instructions | 调用方显式覆盖模型默认值 |
| 2 | Rollout session_meta.base_instructions | 恢复旧 Thread 时保持原行为 |
| 3 | ModelInfo.get_model_instructions(personality) | 新 Session 使用当前模型模板 |
get_model_instructions 还会处理 Personality:若模型提供了可插入人格的模板,就把人格内容编入模板;否则使用模型原始基础指令。这里得到的是完整基础值,不是“人格更新消息”。
def resolve_base_instructions(config, restored_meta, model_info):
if config.base_instructions is not None:
return BaseInstructions(config.base_instructions)
if restored_meta and restored_meta.base_instructions is not None:
return restored_meta.base_instructions
return BaseInstructions(
model_info.instructions_for(config.personality)
)
为什么恢复值压过当前模型默认值
恢复的目标是续接一条已经存在的执行轨迹。若仅因客户端升级或模型目录刷新就改用新默认指令,同一 Thread 在重启前后的底层规则会无提示漂移。因此历史保存的值是会话契约的一部分。
这并不禁止模型切换。切换由 TurnContext 和 World State 另行描述;Session 顶层基础值仍沿自己的更新边界管理。源码因此明确分开“请求的 instructions 字段”和“History 中的模型切换片段”。
请求边界和失败方式
build_prompt 把它作为 Prompt.base_instructions 传给模型客户端。Responses 请求编译阶段才映射为顶层 instructions;它不会先被包装成 ResponseItem::Message。因此调试时若只打印 Prompt.input,会漏掉这一层。
错误实现常见于两个地方:一是恢复时总以当前模型默认值覆盖旧值;二是每轮把 Base Instructions 追加进 History。前者造成行为漂移,后者造成重复、压缩污染和缓存前缀变化。
def build_prompt(session, history, step):
return Prompt(
base_instructions=session.base_instructions,
input=history.for_prompt(step.model.input_modalities),
tools=step.router.model_visible_specs(),
)
源码与测试锚点
codex-rs/core/src/session/mod.rs:三层优先级和 Session 初始化。codex-rs/protocol/src/openai_models.rs:模型指令与 Personality 模板。codex-rs/core/src/session/turn.rs:build_prompt和采样读取边界。codex-rs/core/src/client.rs:向 Responsesinstructions字段映射。
评论
登录后即可评论