底座引擎:一次回合怎么跑(继承自 Codex)
30 秒导读: 前面两章讲的是 harness(仿真某个客户端的请求塑形与响应回译)。但 harness 不是引擎,它是引擎流水线上的一节。这一章把 harness 之外的 Codex agent 主干讲清楚:任务层怎么启动一个回合、回合循环(
run_turn)怎么反复采样、一次采样怎么组装 Prompt 并交给ModelClient::stream,以及模型返回的流怎么回流成ResponseItem喂给下一轮。读完你能指着流程图说出"harness 塞在哪一步"。
本章不重复 harness 内部细节——那是 01(为什么仿真、有哪些 harness、路由矩阵)和 02(一个 harness 到底改了请求/响应的什么)的活。这里只讲引擎主干,以及 harness 挂进主干的那一个挂点。
1. 先建立心智模型:回合 = 采样循环
这节先给零基础读者一个直觉,不进代码。
一次回合(turn),就是"用户说一句话 → 模型可能来回调用几次工具 → 最后模型给一段收尾话"这整个过程。它不是一次请求,而是一串请求。
引擎把这一串请求组织成一个采样循环(sampling loop)。每转一圈叫一次采样请求(sampling request),循环的规则很简单:
- 模型这一圈要是要调工具 → 引擎执行工具,把结果塞回历史,再转下一圈让模型看结果。
- 模型这一圈只说了一段话、没要工具 → 记进历史,回合结束。
这段"要工具就继续、不要就停"的判断,就写在 run_turn 的注释里(core/src/session/turn.rs:130-143,函数 run_turn)。
一句话类比: 把回合想成一场问答接力——模型每次要么"递给你一张工具申请单"(你办完再递回结果),要么"说完了,散会"。引擎就是那个来回跑腿、并在每圈之前把最新的对话历史整理成一份 Prompt 的人。