ModelClient 选型:Responses vs Chat
你问过一个非常关键的问题:
为什么 Chat 的 stream 看起来是 token-by-token,而 Responses 的 stream 是 event-by-event?
这页专门回答这个问题,并给出选型建议。
1. 协议层差异(本质原因)
Chat 接口
- 典型流式形态是“文本增量块”(delta)。
- 你通常看到的是接近 token 级别的追加。
Responses 接口
- 流式是 事件流,不仅有文本,还包含:
- response.created
- response.in_progress
- output_item.added
- reasoning_summary_text.delta
- output_text.delta
- response.completed
- 所以它不是“只按 token 推文本”,而是“按事件类型推状态与内容”。
2. 在 AI4J 中怎么选
选 ResponsesModelClient 的场景
- 你需要结构化事件(reasoning、message、tool call)
- 你要做可观测、审计、复杂 agent
- 你重视 system/instructions 字段语义分离
选 ChatModelClient 的场景
- 你只需要经典聊天流式输出
- 你已有大量 chat-completion 兼容代码
- 你希望最小改动接入
3. 是否可以混用
可以,而且推荐在复杂系统中混用:
- 路由/规划/格式化节点:Responses(结构化更强)
- 简单问答节点:Chat(轻量稳定)
WeatherAgentWorkflowTest 就演示了这种混用方式。
4. 代码示例
Agent weatherAgent = Agents.react()
.modelClient(new ChatModelClient(aiService.getChatService(PlatformType.DOUBAO)))
.model("doubao-seed-1-8-251228")
.toolRegistry(Arrays.asList("queryWeather"), null)
.build();
Agent formatAgent = Agents.react()
.modelClient(new ResponsesModelClient(aiService.getResponsesService(PlatformType.DOUBAO)))
.model("doubao-seed-1-8-251228")
.instructions("输出严格 JSON")
.build();
5. 流式观测建议
- Chat:主要观测文本增量和完成事件
- Responses:按事件类型分层观测(状态事件、文本事件、工具事件)
如果你的目标是构建“可追踪的 Agent 平台”,建议以 Responses 为主。
6. 常见误解
- “Responses 不支持实时输出” —— 错。它是事件化实时输出。
- “Chat 一定更快” —— 不一定,取决于模型和服务端实现。
- “必须二选一” —— 错,AI4J 支持在同一 workflow 中混用。