ChatGPT 如何优化智能体循环:Harness、API 与推理

Posted on Jul 29, 2026

封面图

AI 实验室正以前所未有的速度推进技术,并发布迄今能力最强的模型。就在最近,Anthropic 发布了 Fable 5,随后 OpenAI 推出了 GPT-5.6 系列,其中包括其当前能力最强的 GPT-5.6 Sol;Kimi 发布了 Kimi K3,而 Opus 5 也在几天前问世。

但能力只体现了问题的一半。另一半是这些模型完成任务需要多少成本,也就是每个成功任务的成本。成本越低,用户越能负担得起,服务商的支出也越少。各家实验室投入了大量精力,优化 AI 应用的每一个组件和层级,以提高效率、降低总成本。例如,在人工分析编码智能体指数(Artificial Analysis Coding Agent Index)中,启用最高推理强度的 GPT-5.6 Sol 得分高于 Fable 5,成本却不到后者的一半。

为了了解前沿实验室采用哪些方法提升 AI 应用的效率,我们采访了 OpenAI 的工程师。他们曾为 Codex 和 ChatGPT Work 背后的系统开发并上线多种效率优化技术。感谢 Joe、Ahmed、Steve、Matthew 和 Philippe 与我们分享这些宝贵的技术细节。

本文将介绍:

  • 向 AI 智能体发出请求后,系统内部究竟会发生什么
  • Harness 层如何通过持久 WebSocket、稳定的提示词前缀、延迟工具发现和 Code Mode 减少重复工作
  • API 层如何只对增量内容进行分词,并让安全检查与推理并行执行
  • 推理层如何借助缓存感知路由、KV 缓存管理、推测解码,以及分离预填充与解码,更充分地利用 GPU
  • OpenAI 从这些实践中总结了哪些经验,以及你可以把哪些经验用在自己的系统中

效率优化技术概览

效率优化技术概览

智能体式 AI 应用的结构

当你让 Codex 或 ChatGPT Work 执行一项任务,比如修复一个 bug 时,请求并不会直接发送给大语言模型(LLM)。实际过程要复杂得多。Codex 这类 AI 应用不只包含 LLM,而是由许多组件组成的完整系统。用户查询需要经过多个层级,LLM 才会看到第一个 token。

Codex 这类 AI 应用由许多组件组成,LLM 只是其中之一

Codex 这类 AI 应用由许多组件组成,LLM 只是其中之一。

为什么不能把用户查询直接发给 LLM?先看看 LLM 到底是什么。

LLM 是一种经过训练、用于预测下一个 token 的神经网络。它接收一串 token,并输出另一串 token。它无法运行 shell 命令、编辑文件,也无法在两次调用之间保留记忆。但“修复这个 bug 并运行测试”这类智能体任务主要由一系列操作构成。系统需要把模型预测出的 token 变成真实命令,把执行结果反馈给模型,再不断重复,直到任务完成。

这些工作由 Harness 层负责。它构建在 LLM 之上,用于承担上述职责。Harness 层接收用户任务,决定要在上下文中放入哪些指令、哪些工具定义以及多少历史记录,同时维护完整的对话历史。当模型返回工具调用时,Harness 会在沙箱环境中按审批策略执行工具,把结果追加到对话,再将更新后的对话发回 LLM。

Harness 负责构建上下文并执行工具

Harness 负责构建上下文并执行工具。

不过,就连 Harness 发出的请求也不会直接到达 LLM。在可用于生产的应用中,Harness 与推理端点之间还有一个 API 层,也可以称为应用层。真实产品需要处理许多 Harness 和 LLM 本身不负责的事务,例如验证调用方身份、执行限流,以及最重要的一项工作:把文本转换成 LLM 所需的 token ID,再把模型生成的 token 转回文本。

API 层准备好上下文,并将其分词为一串 token ID 后,LLM 才开始处理输入。这一阶段由推理层完成。推理层是一个由 GPU 集群支撑、托管模型的远程端点。它的任务是尽可能高效地对准备好的 token 执行模型计算,生成新的工具调用或最终答案,再把生成的 token 交回 API 层。

一条请求会经过智能体式 AI 应用的三个层级

一条请求会经过智能体式 AI 应用的三个层级。

向 AI 智能体发出请求后会发生什么?

了解智能体式 AI 应用的三个主要层级后,我们用一个具体例子看看请求如何在它们之间流转。假设你让 Codex“追查结账功能的回归问题,修复它并运行测试”,系统会执行以下步骤:

Harness 把指令、工具定义和你的任务组装成请求,发送给 API。

API 先把请求缓冲到内存中,解析 JSON 并进行验证:检查请求格式是否正确,以及所选模型是否支持请求使用的每项功能。随后,API 验证调用方身份、执行限流并运行预检。

API 把对话渲染为模型所需的输入格式,再进行分词。

API 将 token 发往推理层,同时启动安全检查。这些分类器会检测网络攻击、生物武器等内容,并争取在第一个生成 token 返回前完成检查。

推理层处理提示词并开始生成内容。此时输出的不是最终答案,而是一项工具调用:在代码中搜索“checkout timeout”。

生成的 token 流回 API。

API 把 token 转成文本,并封装为 API 事件。

API 将事件以流式方式传给 Harness。

Harness 识别出工具调用,在沙箱中执行搜索,把输出追加到对话,再将更新后的对话发回 API。

从用户请求到最终总结返回的完整过程

从用户请求到最终总结返回的完整过程。

这只是一次循环。实际执行任务时,系统会多次重复这个循环,直到模型生成最终总结,Harness 再把控制权交还给用户。每轮循环都会重复上面的许多工作,例如重新发送历史记录、重新对文本分词,或重新处理提示词。消除这些重复工作,是优化过程中最主要的机会。接下来三节将介绍 OpenAI 为提高各层效率所采用的优化技术。

Harness 层优化

Harness 是最接近用户的编排层。它把原始用户请求转换成上下文,并与 LLM 循环交互,直到任务完成。它承担两项主要职责。

第一,它维护对话的唯一权威记录,保存每条指令、消息、工具调用和工具结果。第二,它负责运行智能体循环。Harness 决定发给 LLM 的上下文中应包含什么,例如哪些指令、哪些工具定义以及多少历史记录。它发送请求,以流式方式接收并解析响应,同时监测工具调用。出现工具调用后,它会在沙箱环境中按审批策略执行工具,把结果追加到对话,再发回 LLM。这个循环不断重复,直至任务完成。理论上,复杂任务可能重复 100 多次,每一轮都会产生额外开销。例如,每次模型调用多耗时一秒,一个长任务的总耗时就可能增加约半分钟。

智能体循环周期

智能体循环周期

如何提高 Harness 层的效率?

从 Harness 层的视角看,延迟来自四个方面:网络、提示词处理、上下文内容和循环往返。OpenAI 在 Harness 层采用了以下四项技术来提升效率。

1. 持久 WebSocket 与增量请求

Harness 运行在用户的机器上,模型则运行在 OpenAI 的数据中心,因此每次模型调用都需要经过网络。完成这种通信的标准方式是 HTTPS:Harness 建立连接,发送一份包含服务器(即 API 层)所需全部信息的请求,再接收响应。语言模型的响应是逐步生成的,每次生成一个 token,因此聊天应用通常会在 HTTPS 之上使用服务器发送事件(Server-Sent Events,SSE)。客户端发出一次请求后,服务器便通过保持打开的响应连接,把答案分成小块流式返回。SSE 是单向通信,很适合聊天时代的一问一答:一条用户消息触发一次模型调用,模型再流式返回一次答案。但智能体不会只执行一轮。Codex 的一次交互可能包含许多次模型调用。如果使用 HTTPS,每次调用都要建立新请求,并产生两类独立成本。

第一类是连接建立成本。新建 HTTPS 连接时,需要先完成 TCP 握手,再完成 TLS 握手,往往要经过多次网络往返,之后才能传输第一个字节的有效数据。每条用户消息只付出一次这种成本尚可接受,但在一次对话交互中反复付出,就会十分昂贵。

第二类是重复传输请求载荷。HTTP 是无状态协议,因此每个请求都必须携带服务器需要的全部内容,包括指令、工具定义和截至当前的完整对话。到了第二十次工具调用时,Harness 仅仅为了在末尾添加一条新结果,就要重新发送原始提示词、此前十九次工具调用及其十九份结果。载荷会随每轮循环持续增长,Harness 花在上传服务器已经见过的数据上的时间也越来越多。

HTTPS 与 WebSocket 对比

HTTPS 与 WebSocket 对比

这两类成本该如何消除?

连接成本的解决办法是只建立一次连接并让它保持活动,而不是每次调用都新建连接。WebSocket 正是为此设计的。WebSocket 只需在开始时握手一次,此后双方随时都能发送消息,无须为每条消息重新建立连接。Codex 会与 API 建立一条 WebSocket,并在一次交互的所有模型调用期间保持连接,从而消除重复的 TCP 和 TLS 建连成本。

要解决载荷重复问题,就不要再发送服务器已经知道的内容。Harness 会保留上一次请求及其完整响应。如果变化的只有对话输入,它只发送新增项,并附上对前一次响应的引用。一次工具调用结束后,WebSocket 连接上的下一条消息可以精简到如下程度:

注意,这条消息没有指令、工具 schema 或历史记录。服务器会根据自己保留的状态重建完整上下文,因此模型看到的内容没有减少,减少的只是网络传输的数据量。

Harness 只发送新的工具结果

Harness 只发送新的工具结果。

2. 稳定的提示词前缀

LLM 服务商使用提示词缓存来避免重复计算。收到提示词后,模型会查找与先前请求开头部分(即前缀)完全匹配的内容,复用这部分已经缓存的内部状态,只计算剩余部分。这种匹配要求逐 token 完全一致。如果修改了提示词前部的一个 token,后面的所有内容都必须重新计算。

在提示词末尾追加内容可以保持缓存有效

在提示词末尾追加内容可以保持缓存有效。

这意味着 Harness 每次调用构建的提示词,都必须与前一次提示词从完全相同的字节开始。听起来很简单,但 Harness 每次都会根据实时内存状态重建请求,组装方式上的任何细微差异都可能悄悄破坏匹配。OpenAI 分享过一个例子:Codex 曾把 MCP 工具定义保存在哈希映射中,而哈希映射不保证顺序。因此,同一组工具在每次请求中可能以不同顺序序列化。上下文里的工具没有变化,只是顺序不同。Codex 依然能完成任务,只是成本更高。

优化方法是把历史记录当作只能追加的内容,并让审批设置等易变的运行时状态留在提示词之外。例如,用户在会话过程中修改审批设置时,Harness 不会改动提示词中的工具定义,而会在下次执行工具时自行应用新策略。这样,提示词保持不变,缓存也继续有效。

3. 延迟工具发现

稳定的提示词前缀可以降低重复处理上下文的成本,却无法让提示词本身保持短小精简。对能够访问大量工具的智能体而言,这会成为问题。例如,把外部集成和 MCP 服务器计算在内后,一次 Codex 会话可能会暴露数百种工具,单是工具 schema 就会占用大量空间。每个工具 schema 都是一个 JSON 对象,包含名称、描述和参数定义。一旦把这些内容全部放进提示词,即使其中多数工具不会用于当前任务,LLM 也必须处理它们。

OpenAI 使用延迟发现来避免把未使用的工具放入提示词。提示词只携带 shell、文件编辑等核心工具,再加一个 tool_search 工具,其余数百项集成定义完全留在提示词之外。模型需要某项能力时,会调用搜索工具,并给出“list deployments”之类的关键词。Harness 在目录中搜索,再把匹配的工具定义加载到上下文。搜索使用 BM25,这是一种词法排序算法,会找出描述与模型生成关键词相重合的工具。

模型在需要时搜索工具

模型在需要时搜索工具。

除了延迟发现,还有两种方法能缩小上下文。Schema 压缩会按 token 预算缩减过大的工具 schema:删除描述、折叠嵌套结构,同时保留参数名称。对话压缩则会把冗长的历史记录浓缩成简短摘要。

4. Code Mode

在常规模式下,模型发出一次工具调用,等待结果,进行推理,再发出下一次调用。许多场景中,这些工具调用之间并不需要推理,模型只是逐个调用工具,以收集所需结果。这种方式成本很高,因为每次工具调用都需要让模型完整往返一次。每次调用后,工具结果还会继续加入上下文,白白占用上下文空间。

在 Code Mode 下,模型不再逐个发出工具调用,而是编写一小段程序来执行这些调用。Harness 会在内嵌的 JavaScript 运行时中执行该程序,其中每个工具都能像函数一样调用。脚本可以并行发出相互独立的调用,用普通代码筛选、合并结果,并且只返回精简后的答案。中间数据会留在运行时中,只有最终结果进入上下文。

直接调用工具与 Code Mode 对比

直接调用工具与 Code Mode 对比

API 层优化

API 层是与 Harness 通信的服务,位于 Harness 层和推理层之间,运行在普通 CPU 上。Harness 发送的 JSON 描述了结构化的对话项,而模型接收和生成的都是 token ID。一条请求抵达后,会依次经过以下步骤:

请求体先被缓冲到内存中。

系统解析 JSON,并根据 schema 验证请求,例如字段格式是否正确、数组是否在预期范围内。

第二轮验证检查语义。例如,所选模型是否支持请求使用的功能。

系统执行预检,包括授权与权限、限流,以及对请求中所有图片的检查。

API 渲染对话并进行分词,随后同时启动两项任务:向 GPU 发出推理请求,以及对提示词执行安全检查。

生成的 token 从推理层流回后,API 把每个 token 转换成文本,封装为 API 事件,再以流式方式发送给客户端。

一条请求在 API 层内部经历的步骤

一条请求在 API 层内部经历的步骤

循环的每一轮都会重复这些步骤。推理本身不受 API 层控制,API 无法让 GPU 运行得更快。它能做的是尽量减少推理前后的额外延迟。API 层花在解析、验证或分词上的时间,都会成为用户能直接感受到的额外等待。

如何提高 API 层的效率?

OpenAI 采用以下技术,降低 API 层不同环节产生的开销。

1. 只对增量内容进行分词

模型无法直接读取文本。推理开始前,必须先把提示词转换为 token ID。分词器以 O(n) 的时间复杂度线性遍历提示词中的每个 token,并将其替换为对应的 token ID。在无状态 HTTP 模式下,每次调用都要重新对整段对话进行分词。到了第二十次工具调用时,API 为了提取一条新结果,需要重新读取数千个 token。GPU 只需要新的工具结果,CPU 却每次都要从第一页开始重读整本书,而且成本会随输入长度持续上升。

使用 WebSocket 后,API 会把完成分词的对话保存在服务器内存中。第一次请求仍需对完整提示词分词,但后续请求只会发送新增项。API 只对新增片段分词,再把结果追加到已有序列。这样,每次调用的分词成本不再取决于整段对话的长度,而是取决于增量输入的长度,因此更接近 O(1)。

无状态 HTTP 与 WebSocket 下的分词过程

无状态 HTTP 与 WebSocket 下的分词过程

2. 让安全检查与推理并行执行

智能体向用户展示输出前,必须对每个请求进行安全检查。OpenAI 在 API 层实现了这些检查。图片由专门的分类器处理,提示词文本则会交给分类模型,检查网络攻击、生物武器操作指南等危险内容。运行这些分类器需要时间。最直接的设计是先完成检查,通过后再开始推理。问题在于,这段延迟会被加入所有请求的首 token 延迟(time to first token,TTFT),而绝大多数请求完全无害。

解决办法是同时运行安全检查和推理。模型处理提示词并生成第一个 token 需要一定时间,安全检查可以利用这段窗口完成。如果检查未通过,API 会根据模型采取不同处理方式。对某些模型,API 会立即向用户流式发送 token,并在检查失败时中断数据流;对更敏感的模型,API 会暂存输出,等检查通过后再放行。无论采用哪种方式,安全检查所用的时间都被隐藏在原本就不可避免的等待中。

并行运行安全检查

并行运行安全检查

3. 把流量路由到较新的 CPU

当一家公司大规模运营服务器集群时,其中会混有不同年份采购的机器,CPU 也来自不同代际。调度软件通常把同一类型的机器视为完全相同,但实际并非如此。OpenAI 通过 Kubernetes 查询各部署背后的真实处理器型号,发现标注为同一机器类型的设备中,既有较旧的 Broadwell 芯片,也有较新的 Ice Lake 芯片。旧机器处理相同流量时,首 token 延迟大约高 20%,CPU 用量则约为新机器的两倍。

为了解决这个问题,OpenAI 把更多流量转向使用新处理器的机器,并开始在容量规划中明确考虑 CPU 代际。有时,最有效的软件优化就是换用更好的硬件。

推理层优化

模型真正运行在推理层。这里既有 GPU 和其他加速器集群,也有负责操作这些设备的服务软件,即推理引擎。模型的核心计算是规模庞大的矩阵运算,可以分布到加速器的数千个核心上并行执行。推理层负责在整个集群中调度并批处理传入请求,保存生成过程依赖的每段对话状态,执行模型的前向计算,再把每个生成的 token 交给 API 层。

每台机器都保存模型权重,以及所服务对话的 KV 状态

每台机器都保存模型权重,以及所服务对话的 KV 状态。

如何提高推理层的效率?

token 需求的增长速度超过了硬件扩容速度,因此在这一层,慢和浪费是一回事。浪费主要藏在四个地方:工作被路由到错误的机器,内存保存了错误的状态,并行硬件被迫等待串行生成,以及特性迥异的两个阶段共用同一批机器。

OpenAI 采用了以下技术来提升推理层效率。

1. 使用缓存感知路由均衡负载

OpenAI 在许多 GPU 机器上提供模型服务,每个请求都必须被发送到其中一台。如果路由不均,有些机器会闲置,另一些机器却会积压任务。闲置 GPU 是整套技术栈中成本最高的浪费。除此之外,还有一个不太明显的问题:每台机器都会保存最近处理过的对话计算状态,也就是缓存。如果同一对话的下一个请求落到另一台机器上,这份缓存就无法使用。即使计算结果已经存在于其他机器上,新机器仍须从头重算所有内容。

因此,路由器需要兼顾两个目标:

均匀分散负载: 把请求发送到负载最低的机器。

利用缓存: 把请求发回已经保存该对话状态的机器。

缓存感知路由

缓存感知路由

OpenAI 的路由系统会对每个请求综合权衡这两个目标,同时考虑地理位置和可用容量等基本因素。仅改进负载均衡,就已经大幅降低了模型服务成本。

2. 管理 KV 缓存

Transformer 生成一个 token 时,会对之前的所有 token 执行注意力计算。为了避免每生成一个新 token 就重新计算这些注意力状态,服务系统会把它们保存在加速器内存中,这就是 KV 缓存。缓存大小会随对话长度线性增长,还要乘以集群同时服务的对话数量。在长上下文中,KV 缓存的大小甚至可能接近模型权重本身。如果软件淘汰了错误的状态,那么当相应对话再次发来请求时,推理层就要重新付出全部处理成本。

这里的优化方法是根据真实使用情况管理缓存。OpenAI 分析生产环境的追踪记录,判断哪些缓存状态更可能再次被需要;根据这些数据而不是直觉测试淘汰策略;同时优化缓存状态在不同内存层级中的存储和移动方式。这样既能让价值最高的计算结果保留更长时间,又能避免耗尽内存或把时间浪费在数据搬运上。

活跃对话状态留在 GPU 上,较冷的状态被转移或淘汰

活跃对话状态留在 GPU 上,较冷的状态被转移或淘汰。

3. 推测解码

生成过程是串行的。每个 token 都依赖前一个 token,因此,即使模型能用一次大规模并行计算处理很长的提示词,也必须逐 token 生成答案。对大模型而言,即便下一个 token 很容易猜出,生成它依然缓慢且昂贵。面对“法国的首都是”这样的输入,下一个 token 几乎肯定是“巴黎”,但模型仍要处理整段对话并执行大规模矩阵乘法,才能得出这个预测。

推测解码会用一个较小的草稿模型提出接下来的若干 token,再让大模型用一次并行计算同时验证它们。许多情况下,草稿模型的提议是正确的,会被大模型接受,从而省去大模型逐个生成这些 token 所需的时间。如果某个提议错误,大模型就丢弃它并生成自己的 token,因此输出质量不会改变。评估草稿模型时,最主要的指标是平均接受长度,也就是主模型每次计算平均接受多少个候选 token。

推测解码

推测解码

4. 分离预填充与解码

推理分为预填充(prefill)和解码(decode)两个阶段。预填充通过一次大规模并行计算处理全部输入提示词,并构建模型所需的内部状态,也就是 KV 缓存。解码阶段再逐 token 生成响应。这两种工作负载差异很大:预填充受计算能力限制,解码则受内存限制,大部分时间都花在通过内存传输权重和缓存状态上。让两者运行在同一批机器上,意味着任何一方都无法使用针对自身负载优化的硬件配置。

优化方法是把两个阶段分开。集群的一部分专门处理预填充,另一部分专门处理解码,各自按自身瓶颈进行配置。一条请求完成预填充后,系统把计算得到的状态,也就是 KV 缓存,传送到解码机器,再由后者逐 token 生成响应。

三个层级的效率优化技术总结

三个层级的效率优化技术总结

至此,我们已经介绍了智能体式 AI 应用每个层级的效率优化技术。Harness 不再重复发送服务器已有的内容,API 不再重复处理已经处理过的数据,推理层也不再重做已经完成的计算。最后,我们来看看这些工作中有哪些经验可以应用到 OpenAI 之外的系统。

从 OpenAI 提升效率、降低每个成功任务成本的实践中学到什么

从整体上看,不同层级的这些优化技术都在设法避免为同一份工作付费两次。Harness 只发送新增内容,并维持稳定前缀,让缓存持续有效。API 只对增量内容分词,并把不可避免的工作隐藏在本来就要等待的时间窗口里。推理层则把对话路由回保存其缓存状态的机器,避免重新计算。各层优化还会相互促进。Harness 保持缓存完整,API 提高缓存命中率,最终节省会体现在 GPU 上,从而降低用户成本。除了具体技术,OpenAI 工程师还分享了以下几条经验。

保持设计简单。 把简单性置于复杂性之前。例如,工具发现使用词法搜索,而不是向量嵌入(embedding);对话压缩只保留一条路径,而不是提供一组选项。LLM 本身已经足够聪明,在它前面增加更多机制,往往只会增加复杂度,不能带来相应价值。先构建最简单的可行方案,再逐步扩展。

让智能体优化自己的技术栈。 Codex 编写了为 Codex 提供服务的 API 迁移工作中的大部分代码,让两名工程师原本需要数年完成的重写缩短到几个月。推理团队也用它分析追踪记录和制作内核原型。智能体开始编写代码后,编程语言不必再以方便人类书写为首要条件,团队可以直接选择运行效率最高的语言。效率优化正变成一个自我加速的循环。

进行端到端优化。 推理团队告诉我们,每当他们只挑选一种最看好的技术集中投入,最后都会后悔。只关注技术栈的一个部分,会让其他部分投入不足。没有哪一种优化能单独带来决定性改变,真正显著的收益来自许多小优化的叠加。他们还学会使用与生产环境相同的流量形态进行测试,因为离线测试中看似有效的改动,到了真实流量下反而可能损害性能。