跳到主要内容

Realtime 接口(WebSocket)

Realtime 在 AI4J 当前是一条 很薄但正式存在的长连接能力面。
它的重点不是事件协议建模得多完整,而是 SDK 已经给出了统一入口、默认鉴权头和 WebSocket 建连主线。

本页代码都是可跑通的

下面的建连示例来自 AudioAndRealtimeDocExamplesLiveTest。 (realtime 端点不是所有网关都支持,测试在该场景会跳过。)

1. 当前支持矩阵​

从 AiService.createRealtimeService(...) 的分发看,当前 realtime 只支持:

  • OPENAI

这意味着它目前不是一个多 provider 已充分验证的抽象面,而是先把 OpenAI realtime 路径正式收进了 Core SDK。

2. 统一契约长什么样​

统一入口是:

  • IRealtimeService

它提供两种建连方式:

  • createRealtimeClient(String baseUrl, String apiKey, String model, RealtimeListener listener)
  • createRealtimeClient(String model, RealtimeListener listener)

这说明 realtime 层的抽象非常明确:

  • 它只负责建连
  • 不负责替你定义事件语义
  • 也不负责状态机推进

建连示例:

IRealtimeService realtime = new AiService(configuration).getRealtimeService(PlatformType.OPENAI);

WebSocket ws = realtime.createRealtimeClient("gpt-4o-realtime-preview", new RealtimeListener() {
@Override
protected void onOpen(WebSocket webSocket) {
System.out.println("realtime connected");
}

@Override
protected void onMessage(ByteString bytes) {
// 二进制音频帧
}

@Override
protected void onMessage(String text) {
// JSON 事件,自己解析事件类型后分发
System.out.println("event: " + text);
}

@Override
protected void onFailure() { /* 注意:见下文实现细节 */ }
});

3. OpenAiRealtimeService 的真实行为​

这个实现很薄,但几个默认行为必须写清楚。

配置回退​

如果调用时 baseUrl 或 apiKey 为空,会回退到:

  • OpenAiConfig.apiHost
  • OpenAiConfig.apiKey

URL 拼接​

它会使用:

  • openAiConfig.getRealtimeUrl()
  • ?model=<model>

拼出最终 WebSocket URL。

默认请求头​

当前会自动带上:

  • Authorization: Bearer <apiKey>
  • OpenAI-Beta: realtime=v1

这意味着 SDK 已经把 OpenAI realtime 所需的最基本协议头收进实现里,调用方不需要每次手工补。

4. RealtimeListener 真正封装了什么​

RealtimeListener 位于:

  • io.github.lnyocly.ai4j.listener.RealtimeListener

它继承自 WebSocketListener,并抽象出四个你必须关心的回调:

  • onOpen(WebSocket)
  • onMessage(ByteString)
  • onMessage(String)
  • onFailure()
注意

这里要特别注意一个实现细节:

  • onFailure(WebSocket, Throwable, Response) 当前只记录日志,并没有调用抽象方法 onFailure()

也就是说,接口表面看起来有一个统一失败回调,但当前实现实际上没有把底层 OkHttp failure 事件转发给你的抽象 onFailure()。

这点非常值得文档明确写出来,否则调用方会误以为覆写 onFailure() 一定能收到断连失败通知。

5. 这一层当前没有替你做什么​

Realtime service 当前只帮你做了“正确建连”,没有替你做:

  • 事件对象建模
  • 消息类型分发
  • 自动重连
  • 心跳治理
  • backpressure
  • 会话状态恢复

所以这条能力面目前更像“正式建连入口”,而不是完整 realtime runtime。

6. 为什么这页不能只写建连示例​

如果文档只写一段 createRealtimeClient(...) 示例,会漏掉三个关键事实:

它是最薄的一层抽象​

当前 realtime 层几乎不做事件语义封装,业务方要自己消费文本或二进制消息。

它依赖统一 OkHttpClient​

Realtime 和其他 HTTP 能力一样,共享 Configuration.okHttpClient。
这意味着代理、超时、连接池和 dispatcher 策略也会影响这条长连接路径。

它当前只收口了 OpenAI 建连约定​

统一接口已经存在,但 provider 覆盖还很窄,说明这一层目前更像“先建立正式能力面”,而不是已经抽象到高度稳定的跨平台协议层。

7. 业务接入时最该注意什么​

不要在回调里做重 CPU 工作​

提示

RealtimeListener 回调直接挂在 OkHttp WebSocket listener 上。 如果你在这里做重处理,很容易把消息消费和连接处理耦死。

自己定义事件路由层​

当前 SDK 没有替你把 string message 进一步拆成事件对象,所以更稳的做法是在业务层自己加一层事件分发。

连接治理责任仍在应用层​

自动重连、指数退避、会话标识、监控埋点、断连补偿,这些都还不是 SDK 当前 realtime 层的职责。

8. 这一页的结论​

AI4J 当前的 Realtime 能力是一条很薄的正式建连抽象:它统一了 OpenAI realtime 的 URL、鉴权头和 WebSocket 入口,但还没有把事件协议、失败转发、重连治理和会话恢复做成完整 runtime。用它时,应该把它理解成“长连接入口层”,而不是“完整 realtime 会话框架”。