用户向聊天模型输入一句“资料页点击保存没有反应,请修一下”,模型可以分析可能的原因,也可以给出排查步骤。但它看不到项目目录,不能读取日志,也不会修改磁盘上的文件。
同一句话交给 Coding Agent,执行过程会不同。Coding Agent 是能够围绕编程目标读取项目、调用开发工具并根据结果继续工作的系统。它可能先搜索资料页组件,再检查事件处理函数和网络请求。找到问题后,它可以修改代码、运行测试,并根据测试结果继续调整。用户只提供了目标,具体路径由系统在执行过程中逐步确定。
这些动作来自一套由模型、上下文、工具和运行时组成的系统。理解 Codex 的第一步,是把语言模型的生成能力与外层系统的执行能力分开。
语言模型生成下一个 token
语言模型接收一段已有文本,计算下一个 token 的条件概率分布。token 是模型处理文本的基本单位。中文里的一个 token 可能对应一个字、词的一部分或标点;源代码里的关键字、括号和空白也会被分词器编码为 token。
假设输入是“乌云越来越低,看样子马上要”,模型可能给“下雨”分配较高概率,也可能认为“天黑”可以接在后面。“吃饭”与当前上下文的关系较弱,概率通常更低。
模型输出概率分布后,解码算法从中选择一个 token。贪心解码会选择概率最高的候选,采样算法则保留一定随机性。选出的 token 被追加到输入末尾,模型再计算下一步。重复这个过程,最终得到完整回答。
早期统计语言模型依赖词频和相邻词组合。它们可以处理见过的局部模式,但很难表示长距离依赖。神经网络语言模型使用可训练的向量表示词语,并通过多层网络学习更复杂的关系。
2017 年提出的 Transformer 使用自注意力机制处理序列中的依赖关系。以“杯子放在桌上,它已经空了”为例,模型可以在计算“它”的表示时,为“杯子”和“桌子”分配不同权重。这里的“注意力”是一种数值计算,不表示模型具有人类的注意或意识。
Transformer 还适合在训练阶段并行处理序列中的多个位置。研究者可以使用更大的数据集和更多计算资源训练通用语言模型,再将模型用于问答、摘要、翻译和代码生成等任务。
GPT 是 Generative Pre-trained Transformer 的缩写,即生成式预训练 Transformer。训练过程中,优化算法根据预测误差调整模型参数。训练完成后,一次普通推理通常不会修改这些参数;模型根据已有参数和当前输入生成结果。
预训练模型怎样学会遵循指令
预训练主要教会模型预测文本。仅经过预训练的模型收到一个问题时,可能继续生成更多问题,也可能模仿网页内容补出作者、日期和评论。这些续写在统计上合理,却不一定符合用户意图。
后训练把模型的生成能力调整到指令遵循场景。监督微调使用“指令与理想回答”示例训练模型。偏好优化则利用人类或其他评估器对多个回答的比较结果,让模型的输出更符合用户意图。具体训练方法并不只有一种,但它们解决的是同一类问题:怎样让文本续写服务于用户给出的任务。
经过后训练,模型能够把“总结这份文档”“解释这段代码”或“找出报错原因”识别为需要完成的指令。不过,它的输入和输出仍然是 token 序列。持续对话与外部操作都由模型之外的系统提供。
对话连续性来自上下文
聊天应用在每次请求模型前组织一份输入。它通常包含当前用户消息、相关历史消息以及系统提供的行为说明。模型根据这份输入生成回答。
这些随请求一起交给模型的内容称为上下文。上下文还可以包含用户粘贴的文档、代码片段、工具返回结果和项目规则。模型在一次推理中只能使用当前上下文窗口内的信息。
应用可以在模型外部保存长期记录,也可以从数据库或搜索系统中检索资料。但检索到的内容必须重新进入上下文,或者通过工具接口提供给模型,才能影响本轮生成。模型不会在两次请求之间自行回忆上一次对话。
因此,对话过长时,应用可能删除、压缩或摘要较早的内容。新会话如果没有重新加载旧记录,模型也不会自动知道之前讨论过什么。对话的连续性由应用维护,不是模型参数在聊天过程中发生了变化。
上下文解决了连续交流问题,但不能直接改变外部环境。模型可以描述怎样整理目录,却无法仅靠一段文本移动文件。系统还需要把模型的意图转换为受控操作。
工具连接模型与外部环境
工具是外层程序向模型开放的操作接口。读取文件、搜索代码、执行命令、应用补丁和查询数据库都可以封装为工具。
每个工具需要定义名称、参数和返回结果。模型要读取文件时,会生成类似下面的结构化请求,而不是只输出一句自然语言说明。
{
"name": "read_file",
"arguments": {
"path": "src/profile.tsx"
}
}
运行时解析这个请求,检查参数和执行条件,然后调用文件系统。文件内容或错误信息会作为工具结果返回。模型在下一次调用中读到结果,才能基于项目的实际状态继续判断。
工具结果可能改变原来的计划。指定路径可能不存在,测试命令可能失败,日志也可能指出另一个模块的问题。模型必须观察每次执行结果,再决定后续动作。单次“请求与回答”无法覆盖这种过程。
反馈循环构成 Agent
Agent 通常译为“智能体”。本书把它定义为一个围绕目标观察环境、选择行动,并根据行动结果继续工作的系统。这个定义关注工作机制,不涉及意识或人格。
一次简化的 Agent 循环如下。
模型可能在一轮中请求一个工具,也可能请求多个可以并行执行的工具。运行时收集这些结果后,判断是否需要再次调用模型。循环在模型给出最终回复、系统遇到无法恢复的错误、达到资源限制或收到中止请求时结束。
Agent 与自动化脚本之间没有绝对边界。脚本的主要路径通常由程序员预先写入代码;Agent 允许模型根据刚得到的观察结果选择后续动作。复杂脚本也能包含动态分支,Agent 也可以只调用一次工具。判断重点是执行路径是否会根据环境反馈在运行时改变。
动态选择使系统能够处理程序员没有预先枚举的错误路径,也增加了执行成本。循环可能调用模型多次,工具可能失败,上下文会持续增长,停止条件也可能判断错误。运行时需要处理超时、取消、重试和上下文限制,而不能只负责转发模型请求。
Coding Agent 在代码仓库中运行循环
软件项目能为 Agent 提供密集而具体的反馈。代码搜索返回定义位置,编译器报告语法和类型错误,测试暴露行为偏差,版本控制记录文件变化。这些结果可以验证模型的判断,也可以推翻它的初始假设。
以“资料页点击保存没有反应”为例,Coding Agent 可以按下面的顺序推进任务:
- 查看项目结构,确认前端代码和测试的位置。
- 搜索保存按钮及其事件处理函数。
- 沿调用链检查请求参数、认证信息和错误处理。
- 运行相关测试或复现命令,根据输出缩小范围。
- 修改代码,再运行测试、类型检查和差异检查。
这组步骤会随反馈变化。搜索结果决定下一步读取哪个文件,测试输出决定是否修改原来的判断。如果现有测试没有覆盖故障路径,Agent 还需要补充验证方法,并在最终回复中说明证据缺口。
反馈也不能保证修改正确。测试可能缺失,日志可能不完整,需求本身也可能含糊。Coding Agent 的优势在于它能够获取和使用工程反馈,而不是仅凭生成的文字宣称任务已经完成。
Runtime 负责维持执行过程
模型不负责保存会话状态、路由工具、管理并发或记录任务进度。这些职责属于 Runtime,也就是运行时。
Runtime 为每次模型调用构造上下文,并向模型提供当前可用的工具说明。模型返回工具请求后,Runtime 选择对应执行器,收集输出,再把结果写入后续上下文。如果模型需要继续处理,Runtime 发起下一次模型调用;如果任务被取消,Runtime 停止仍在运行的操作并发出终止事件。
Codex 是一套面向软件开发任务的 Agent 系统。模型负责理解输入和生成下一步意图,工具负责读取或修改外部环境,Runtime 维护反馈循环。终端、编辑器和其他客户端负责接收用户操作并展示执行事件。
从用户请求到任务结束,可以先把主链路概括为:
用户提交任务
↓
Codex 组织上下文与工具说明
↓
模型生成回复或工具请求
↓
Runtime 路由并执行工具
↓
工具结果写回上下文
↓
模型继续处理,直到任务结束
当前实现还包含上下文压缩、流式事件、动态工具、并行调用和持久化等机制。第一章只保留这条主链路,后续章节再讨论状态所有权和具体组件。
沙箱与审批限制工具执行
模型生成的命令可能包含错误,也可能受到仓库中不可信内容的影响。工具执行因此需要明确的安全边界。
Codex 使用沙箱和审批策略控制外部操作。两者处理不同问题。
| 机制 | 处理的问题 | 作用 |
|---|---|---|
| 沙箱 | 命令在技术上可以访问什么 | 限制可读写路径、网络和其他系统资源 |
| 审批策略 | 哪些动作必须由用户决定 | 在执行越界或高风险操作前暂停并请求确认 |
会产生外部副作用的工具调用先经过策略判断,再在指定执行环境中运行。执行成功时,输出返回模型。沙箱错误可以返回模型用于调整方案;审批被拒绝时,系统可以取消当前动作或中止任务,具体行为由审批策略决定。安全控制位于 Agent 循环内部,因为工具调用正是系统产生外部副作用的位置。
权限放得过宽会扩大误操作和数据泄露风险,限制过严则会让任务频繁中断。具体配置取决于代码仓库的可信程度、任务需要的资源和用户允许的自动化范围。
下一章进入 Codex 的执行路径
这一章建立了后续分析需要的系统边界。语言模型根据上下文生成 token;后训练让模型能够遵循指令;工具把结构化意图转换为外部操作;Runtime 通过反馈循环组织多次模型调用和工具执行;沙箱与审批策略限制副作用。
下一章将沿着一次实际任务进入 Codex,检查用户请求如何被接收、模型调用怎样构造、工具结果如何回到上下文,以及执行进度怎样成为客户端可见的事件。之后再引入 Thread、Turn 和 Step,就能把这些术语放到已经建立的执行链路中理解。
评论
登录后即可评论