How we built a realtime system for responsive voice AI in six months · Justin Uberti、Zahan Malkani(OpenAI 技术团队)· 2026-08-03
中文译述 · 红字是原文重点,下划线是限定条件,黄底是我补充的想法
对语音 AI 来说,知道什么时候该开口,比听上去要难。人跟人之间交接发言权只用几分之一秒,而此前的语音 AI 跟不上这个节奏。它们的回合制架构依赖一种叫 turn detector 的小模型,这个模型的任务不太好做:猜早了,用户被打断;猜晚了,回应显得迟钝。而且只有等它做完判断,那个大得多的 LLM 才能开始干活。
GPT-Live 是 OpenAI 的第三代语音系统,它把 turn detector 从音频路径上直接拿掉了。它的语音模型是全双工的,能一边听一边说,于是不再需要一个单独的检测器,对话也显得更即时、更自然。需要更深的推理或者用工具时,GPT-Live 还可以去咨询 GPT-5.5 这样的前沿模型,而不打断对话本身的流动。
要把这种体验做到规模化,需要一套围绕低延迟重新设计的系统架构。和典型的请求—响应式推理不同,这套系统把进来的音频流式送进语音模型,把输出的语音流式送回用户,而把委派放在另一条异步路径上处理。过去六个月里,模型推理、上下文管理和媒体传输都被重做了一遍,目的是让语音从头到尾平顺地流动。
这套架构还在核心语音路径和应用逻辑之间划出了一条干净的边界:定制应用行为不会影响响应速度。它支撑着 ChatGPT Voice 里不断增加的能力,包括刚上线的在 ChatGPT 桌面端控制电脑、协调你的 agent。
从轮流发言到流式
早期的语音架构继承了文本 LLM 的回合制,只不过每个回合不是文本,而是一段离散的音频。级联式系统里,语音转文字、LLM、文字转语音三者串行执行,这个顺序既增加延迟,又丢掉了语气和节奏这类线索。
speech-to-speech 模型直接处理音频,改进了这一点:让模型原生地理解和生成语音,就能保住转写过程中丢失的细节,回应也更快。但系统仍然靠 turn detector 来决定推理什么时候可以开始。模型承担了交互中更多的部分,交互本身还是回合制的。
GPT-Live 把对话的控制权交给语音模型:音频流进流出模型,更深的推理和工具调用异步发生。这个系统的首要任务,是维持一条不中断的媒体循环。其他工作——调用前沿模型、把对话持久化——都发生在这条实时路径之外。
按原文描述自绘的结构示意:音频在一条专用快路径上进出语音模型,委派、工具和其他应用逻辑都放在异步边界之后。
让连续推理成为可能
维持这条媒体循环并不总是简单的事。传输、处理、推理中任何一处的延迟,都可能变成能被听见的停顿或杂音。回合制系统可以容忍音频块到达时间的波动,而实时媒体系统必须让每一个音频帧都按时送达。
此前在 ChatGPT Voice 和 Realtime API 上的工作打下了基础:他们已经重建过语音基础设施,让音视频直接流式进出系统,延迟更低也更可预测。GPT-Live 把这个设计又往前推了一步,通过一套为连续对话构建的、有状态的新推理系统,把媒体一路流到模型面前。
让媒体流得快
一个很早就定下的决定是:把媒体流与应用及业务逻辑明确分开。音频在客户端和语音模型之间走一条专用的快路径;委派、工具调用和其他应用层的工作,都放在一个异步 RPC 边界之后。一次慢的工具调用或者某个后端服务变慢,只会拖慢它自己的结果,不会让媒体流停下来。
这种分离也给定制留出了干净的边界:应用可以改自己的工具、策略和后端行为,而不影响那个负责让音频持续流动的媒体前端。实时路径保持得很小、可预测,只做必须实时完成的事。
媒体前端和推理逻辑用 Go 重写,替换了原先的 Python asyncio 实现。这显著改善了帧投递的平滑度:新系统的 p95 与旧系统的 p50 相当。
传输层的基础是 WebRTC。它本来就是为低延迟媒体设计的,能在丢包、时钟漂移和客户端连接变化的情况下继续工作。包晚到时,WebRTC 可以不易察觉地把音频拉长以免出现空档,随后短暂加快播放追回实时进度。
把整个系统里的缓冲和阻塞都压到最小,才谈得上人们在对话中期待的亚秒级响应。
“p95 追平旧系统的 p50”这句话值得单独抄下来:在每一帧都有交付期限的系统里,平均延迟几乎不提供信息,能不能用取决于尾部。文章后面讲生产测试时给出的容量口径改写——从“一块 GPU 能扛多少请求”改成“系统能维持多少并发会话、且每一帧都按时”——其实是同一件事的另一面。先把指标从均值换成尾部,再把容量从吞吐换成并发会话,两步之后,压测数据才和真实体验对得上。
有状态的对话怎么续下去
有状态推理有它自己的运维代价:一个语音会话可能长时间活跃,但它的上下文在持续增长,而模型实例会按需求起停。
为此他们做了跨模型实例的无缝切换:需要转移时,在现有实例旁边预热一个替代实例,用当前会话的上下文把它 prefill 好,两边并行推理,等新实例完全就绪再切过去。
同一套机制也支撑动态的上下文压缩。对话进行下去,累积的上下文最终会超过模型的上下文上限。压缩可以把它压回限额内,但这个操作需要时间;而且因为它改变了过去的上下文,还会让模型的 KV 缓存失效——这个缓存保存的是此前已处理 token 的注意力键值——重建这部分状态需要重新 prefill,又引入额外的延迟。
于是压缩也被当成一次受管的切换:原来的模型实例继续聊天,系统在旁边压缩上下文、准备好装着新上下文的替代实例,就绪后再切换,媒体完全不中断。这样系统就能支撑长时间通话,需要时随时压缩。重活留在实时路径之外,即便正在切换,对话也不漏一拍。
按原文描述自绘:压缩被当成一次受管的实例切换,重活发生在实时路径之外,所以切换期间对话不漏拍。同一套机制也用于按需求起停实例。
委派,但不阻塞对话
GPT-Live 能调用已有的前沿模型,这让它很有力量——等于把“说话”和更深的“思考”解耦了。但要让这种双模型架构用起来像一个系统,需要解决两个相关的工程问题。
第一,结果必须回得足够快,才能在正在进行的交流里派上用场,所以整条委派路径的延迟都得压下来:路由、提示处理、推理、工具调用。第二,产品里别处的系统仍然需要离散的消息,所以还得把这段连续进行的对话,表示成它们能理解的形式。
原文在这里给了一段示例音频:GPT-Live 负责快速、自然地接话,GPT-5.5 在后台完成搜索(示例用的是 GPT-5.5 Instant)。
让委派快到显得自然
一次委派派发出去之后,优化的目标是“前沿模型产出对这段对话有用的东西”所需要的时间。语音模型可以在前沿模型推理或调用工具期间短暂地把交流维持住,但它掩盖不了一个任意慢的响应。所以整个委派回路——路由、提示处理、推理、工具调用——都被算进了响应预算。
第一个优化是在委派被请求之前,就把前沿模型和它需要的工具准备好:语音会话一开始,应用服务器就为前沿模型创建一个推理会话,并用初始的对话上下文把它 prefill,确保首次委派请求到来之前,提示已经被完整处理过。
这个推理会话在整段语音对话期间保持可用,后续请求尽量落到同一个推理实例。配合提示缓存(prompt caching),这些做法改善了延迟,同时单个 worker 出故障仍然容易恢复。
推理 effort、输出长度上限、工具 schema、模型与工具之间的往返次数,也都影响对话什么时候能拿到有用的结果,这些杠杆同样被调过。把委派路径上需要做的事压到最少,语音模型才能迅速把前沿模型的结果吸收进来。
从连续语音里切出离散回合
尽管语音模型面对的是连续的语音流,它周围的许多系统仍然按“用户回合 / 助手回合”工作,包括 ChatGPT 的对话界面,以及分析和安全基础设施的一部分。于是应用服务器要把这段重叠的、有时含糊的对话拆成一条条离散消息。
音频到达时,服务器用部分转写和时间信号推断此刻是谁握着发言权,并建立一个消息队列。最新的那条消息始终是暂定的:它的文本、时间和说话人归属都可能随着更多语音到来而改变。等某个说话人持续占有发言权足够久、归属可以确信了,服务器才把对应的消息定稿。
说话重叠让这件事更麻烦。用户正在说话时,助手一句简短的应答(比如“嗯嗯”“好的”)不一定要单独成为一条消息;但助手实质性的插话往往应该。同样,即使用户中途插话,显示出来的助手回复也优先保证连贯。
每一种切分策略都在新鲜度和确定性之间做取舍:提交得太早,历史会变得零碎、顺序不稳;等得太久,转写以及依赖转写的功能都会被推迟。所以系统同时维护两种相关的对话视图:一份关于当前状态的推测视图,和一份“究竟说了什么”的权威记录。应用界面里的对话视图能够处理更新,用的是推测视图;而写入分析管线则需要最终的转写。这样,ChatGPT 的其余部分拿到了一份稳定的交流视图,又不必把回合制强加回实时语音路径。
这里讲的“推测视图 + 权威记录”解决的是转写的时效问题,文章没有展开的是委派结果的时效问题:对话一直在往前走,一次委派派出去时的问题,和结果回来时用户关心的问题,可能已经不是同一个。按文中的架构推断,这个判断落在应用服务器一侧,但原文没有说它依据什么来决定一份迟到的结果还要不要说出口。如果要照着这套结构自己搭一版,我会把“每次委派对应的条件”记下来,结果回来时先比对当前问题——这一条属于我的补充,不是原文的做法。
用更快的协议启动会话
用户按下按钮的那一刻,响应速度就开始计算了。系统必须先建好媒体路径、把音频喂进模型,对话才谈得上开始,所以启动序列的每一段都落在关键路径上。
如前所述,WebRTC 是很强的实时基础,但启动一个标准的 WebRTC 会话,需要的协议握手和网络往返次数多得出人意料。WebRTC 早于 QUIC 这类后来才把“减少往返”当作核心目标的协议,因此它底下那些协议放在一起用时,有时会重复做同样的事——比如每个协议都自带一套抗 DoS 机制,哪怕在完整的 WebRTC 栈里并不需要。
他们分析了这套协议栈,做出 WARP(WebRTC Abridged Roundtrip Protocol),把媒体与数据的启动从六个网络往返压缩到一个。WARP 靠的是一组向后兼容的协议改进:把 DTLS 握手搭载在 ICE 上(SPED)、使用更快的 DTLS 1.3 握手、预先协商 SCTP 握手(SNAP),以及预先协商 data channel 而不再走 DCEP。
WARP 被设计成一组开放规范,和 WebRTC 社区的合作者一起做,让整个生态都能受益。相关提案正在 IETF 的 TSVWG 工作组推进,libwebrtc 和 Pion 都已经加入了 WARP 支持,其他 WebRTC 实现也在跟进。
媒体握手优化之后,还剩一处延迟很显眼:WebRTC 连接之前用来交换 SDP 参数的信令往返。为了把它移出关键路径,他们做了一个叫 Instant Connect 的机制,提前协商这些参数,既不预留服务器容量,也不需要改动现有的 WebRTC 实现。Instant Connect 与标准信令流程并行运行:如果预协商的参数有效,服务器可以在第一个媒体包到达时直接创建会话并开始处理媒体;如果参数已经过期或无效,标准信令流程本来就在进行中,客户端可以回退,不增加额外延迟。
两者合起来,从“用户想用”到“媒体真正流动”之间的时间被大幅压缩:SDP 交换离开关键路径,WARP 把传输握手折叠起来,客户端现在可以用一个 UDP 包启动一次会话。
按原文数值自绘。WARP 将媒体与数据启动压缩到一个网络往返;Instant Connect 提前协商 SDP, 将信令交换移出关键路径。两者配合,客户端才可以用一个 UDP 包启动会话。
这一节是全文里唯一一处别人可以直接拿走的成果:WARP 是公开草案,而且已经进了 libwebrtc 和 Pion,用 WebRTC 做实时应用的团队不必自己实现就能受益。按往返次数与 RTT 成正比推断,省掉五个往返带来的绝对收益,在高延迟链路(移动网络、跨区域)上会比在机房内网明显得多——这是我的推断,原文没有给分地域的启动耗时数据。
用真实数据在生产里安全地测
一个系统可以在纸面上很快,真到了语音流量下还是会卡住。在让 GPT-Live 跟用户对话之前,他们跑了一次静默测试:把一小部分、比例逐步提高的生产 ChatGPT Voice 会话同时路由到现有的 Advanced Voice Mode 和新系统。Advanced Voice Mode 照常服务用户,影子路径以只读模式跑推理,于是新系统暴露在真实的客户端、网络、会话长度和地理分布之下,而用户听到的内容没有任何变化。
第一课是容量不能简化成 GPU 吞吐。语音会话会一直开着并持续发送帧,所以 CPU 侧的流处理器、队列和网络路径必须跟着推理一起扩容。真实负载下,某个支撑组件比压测估计的更早饱和,导致推理请求堆积、延迟层层叠加。于是容量问题从“一块 GPU 能处理多少请求”改写成了“系统能维持多少并发会话,同时让每一帧都按时送达”。
这次测试也让地理位置变成了一等问题:把会话路由到远处的容量,会在启动和流传输的好几个环节上增加延迟。他们开始把模型的上线与区域容量、流量调度配置放在一起验证,再按来源地域拆解延迟。把推理搬得离用户更近确实有帮助,但也印证了一个更大的教训:端到端的响应速度取决于路径上的每一个服务,不只是模型服务器。
还有一些故障只有在真实的会话生命周期里才会现身:长会话暴露内存和持久化压力,重连会触发压缩与状态恢复,普通的客户端断开暴露了关闭握手中的竞态。这些问题在短时压测里很少出现,因为它们依赖时间、依赖累积起来的状态,也依赖跨服务边界的行为。
最后,生产测试逼他们改进可观测性和发布控制。他们发现有些指标把不同来源的延迟混在了一起,有些仪表盘的聚合数字掩盖了个别不健康的引擎,测试环境与部署环境之间存在配置漂移。对策是更细粒度的遥测、对照已知良好配置做校验、分阶段放量,以及快速隔离或关停单条路径的能力。这次静默测试于是成了一次提前的上线演练——不只是演练系统能接住多少流量,也演练他们能多快发现、遏制并从故障中恢复。
从客户端到模型,都要有响应
把 GPT-Live 做到 ChatGPT 的规模,需要一套围绕一条根本原则重建的系统:声音必须流动。流式推理让全双工模型持续有音频可用,专用媒体路径保证帧被可靠送达,异步委派让更深的思考并行进行,优化过的传输把响应速度一路保持到用户那一端。
这套架构正在变成一个更广的实时交互平台:它支撑 ChatGPT Voice 从对话扩展到 agent 协调,也将成为即将到来的 GPT-Live API 的底座。
后记
这篇文章讲的是语音,但它的结构问题和现在很多 agent 产品是同一个:一条必须保持流动的交互路径,加上一堆时快时慢的后台工作。GPT-Live 的答案很朴素——把两者用一个异步边界分开,实时那条路径上只留必须实时完成的事,慢的部分只能拖慢自己。
如果拿它当参照来做自己的系统,我认为有三个口径值得一起抄走:延迟看尾部而不是均值,容量按“能维持多少并发会话且不掉帧”而不是按吞吐,上线前用影子流量在真实网络和真实会话长度上跑一遍。文中那些只在长会话、重连和断开时才出现的故障,说明短时压测漏掉的往往正是上线后最先遇到的。