Files
Xin Wang 2649d64b55
Quality gate / backend (push) Canceled after 0s
Quality gate / frontend (push) Canceled after 0s
feat: harden public OpenAI API contracts
2026-09-07 14:25:48 +08:00

150 lines
7.5 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: OpenAI 兼容范围
description: OpenAI-compatible subset v1 的字段、事件、错误与版本兼容矩阵。
icon: brackets
---
# OpenAI-compatible subset v1
平台公开协议命名为 **OpenAI-compatible subset v1**。它兼容 OpenAI Responses 与 Realtime 的核心调用方式,但只承诺本页列出的子集;没有列为“支持”的 OpenAI 字段,不能视为已经实现。
字段分为三种状态:
| 状态 | 含义 |
| --- | --- |
| 支持 | 字段会被校验并产生文档描述的效果 |
| 平台锁定 | 能力存在,但值来自助手配置;调用方提交时返回 `immutable_configuration` 或 `immutable_session_field` |
| 不支持 | 当前版本不实现;显式提交时返回 `unsupported_parameter`、`unsupported_operation` 或 `invalid_event` |
## HTTP 资源
| 接口 | 状态 | 说明 |
| --- | --- | --- |
| `GET /v1/models` | 支持 | 返回可通过公开协议调用的 `assistant:asst_xxx` |
| `POST /v1/responses` | 支持 | 非流式 JSON 或 Responses SSE |
| `GET /v1/responses/{id}` | 支持 | 只允许创建它的长期 API Key 查询 |
| `GET /v1/responses/{id}/input_items` | 支持 | `after`、`limit`、`order` 游标分页 |
| `DELETE /v1/responses/{id}` | 支持 | 逻辑删除;既有子 Response 的祖先链仍可恢复 |
| `POST /v1/responses/{id}/cancel` | 不支持 | subset v1 不支持 background,固定返回 `unsupported_operation` |
| `POST /v1/realtime/client_secrets` | 支持 | 使用长期 Key 签发短期、绑定助手的令牌 |
| `POST /v1/realtime/calls` | 支持 | `multipart/form-data` 或原始 `application/sdp` |
| `GET /v1/realtime` WebSocket upgrade | 支持 | 服务端或自定义客户端 Realtime 连接 |
| `/v1/chat/completions` | 不支持 | 不提供旧 Chat Completions 兼容层 |
## Responses 请求字段
| 字段 | 状态 | subset v1 行为 |
| --- | --- | --- |
| `model` | 支持 | 首轮必填,格式为 `assistant:asst_xxx`;后续可继承 |
| `input` 字符串 | 支持 | 转换为一条 `user` 文本消息 |
| `input[].message` | 支持 | 仅文本 `input_text` / `output_text` |
| `input[].function_call_output` | 支持 | 只能解析父链尚未完成的 Client Tool call ID |
| `previous_response_id` | 支持 | 恢复祖先上下文,允许从同一父节点分支 |
| `stream` | 支持 | `false` 返回 JSON;`true` 返回 SSE |
| `store` | 支持但固定 | 只能省略或为 `true` |
| `x_interactive_media.variables` | 支持 | 首轮赋值,后续继承并增量覆盖 |
| `instructions` | 平台锁定 | 来自助手配置 |
| `tools`、`tool_choice` | 平台锁定 | 来自助手及工具绑定 |
| `background`、`conversation` | 不支持 | 状态只通过 `previous_response_id` 管理 |
| `include`、`reasoning`、`text` | 不支持 | 显式拒绝,不静默忽略 |
| `temperature`、`top_p`、`truncation` | 不支持 | 由底层助手和模型资源控制 |
| 图片、文件输入 | 不支持 | 文本接口只接受文本;实时图片走 Realtime item |
Response 返回标准 `response` 对象。`output` 当前可能包含 `message` 或 `function_call`。如果底层 Provider 能稳定提供 token 统计,`usage` 返回真实值;当前无法取得时明确返回 `null`,不会估算。
## Responses SSE 事件
| 事件 | 状态 | 顺序约束 |
| --- | --- | --- |
| `response.created` | 支持 | 第一个事件 |
| `response.in_progress` | 支持 | 紧随 created |
| `response.output_item.added` / `done` | 支持 | 每个输出项各一组 |
| `response.content_part.added` / `done` | 支持 | 文本输出项使用 |
| `response.output_text.delta` / `done` | 支持 | delta 为零到多个,done 恰好一个 |
| `response.function_call_arguments.delta` / `done` | 支持 | Client Tool 参数使用;done 恰好一个 |
| `response.completed` | 支持 | 正常终态,最后一个事件 |
| `error` + `response.failed` | 支持 | 失败终态 |
每个事件都有从 `0` 开始单调递增的 `sequence_number`。流式终态、同一 Response 的非流式结果和随后 GET 的资源语义一致。
## Realtime 客户端事件
以下客户端事件属于 Core 支持范围:
- `session.update`
- `conversation.item.create`
- `conversation.item.truncate`
- `input_audio_buffer.append`
- `input_audio_buffer.commit`
- `input_audio_buffer.clear`
- `output_audio_buffer.clear`
- `response.create`
- `response.cancel`
会话中的 `model`、`instructions`、`voice`、`tools` 和 `tool_choice` 为平台锁定字段。`output_modalities` 与 Server VAD / PTT 参数可更新。WebSocket 支持 Base64 PCM16 音频;WebRTC 音频走媒体轨道,事件走 `oai-events` DataChannel。连续视频只通过协商后的 WebRTC video track 提供。
服务端事件的完整名称与最小 envelope 由仓库中的 `backend/contracts/openai-realtime-server-events.schema.json` 定义;客户端事件由 `backend/contracts/openai-realtime-client-events.schema.json` 定义。
## Interactive Media Extensions v1
所有扩展事件都使用 `x.interactive_media.*` 命名空间,并独立版本化为字符串 `"1"`。
客户端先协商能力:
```json
{
"type": "x.interactive_media.capabilities.update",
"event_id": "evt_caps_001",
"version": "1",
"capabilities": ["dynamic_variables", "workflow_events"]
}
```
服务端以 `x.interactive_media.capabilities.updated` 返回 `capabilities`、`rejected` 和实际 `version`。只有协商成功后,服务端才发送相应扩展事件。当前能力为:
| capability | 作用 |
| --- | --- |
| `dynamic_variables` | 运行中更新声明过的动态变量 |
| `workflow_events` | 接收节点、业务事件、变量和错误事件 |
| `handoff` | 接收人工接管和通话结束事件 |
| `video_track` | 协商项目扩展的 WebRTC 视频轨道 |
扩展事件缺少版本或使用未知版本时返回 `invalid_event`;未知 capability 会出现在 `rejected` 中,不会被静默启用。
## 错误与状态码
所有公开 HTTP 错误统一返回:
```json
{
"error": {
"type": "invalid_request_error",
"code": "response_not_ready",
"message": "Previous response is in_progress",
"param": "previous_response_id"
}
}
```
| HTTP 状态 | 使用规则 |
| --- | --- |
| `400` | schema 合法但字段不支持、平台锁定或业务语义无效 |
| `401` | Bearer Key 缺失、无效、过期,或令牌类型不适用于接口 |
| `404` | 资源不存在、已删除或属于另一个 API Key |
| `409` | 父响应未结束、幂等键冲突或资源状态冲突 |
| `422` | JSON、路径或查询参数不符合公开 schema |
| `429` | 请求、并发或容量限制;当前为预留标准状态 |
| `500` | 运行中不可恢复的内部失败 |
| `503` | 服务暂时不能接收请求;当前为预留标准状态 |
| `504` | Responses 生成超过服务端超时 |
每个 HTTP 响应都带 `X-Request-ID`。调用方传入符合格式的 ID 时服务端透传,否则生成 `req_...`。Realtime `error` 事件中的 `error.event_id` 指向导致错误的客户端 `event_id`。
## 兼容性规则
- subset v1 内新增可选字段、可选事件字段和新错误码属于向后兼容变更。
- 新增必须由调用方主动使用的扩展 capability 属于向后兼容变更。
- 删除字段、改变字段含义、改变既有事件顺序或把可选字段改为必填,必须升级协议主版本。
- 平台锁定或不支持的字段转为支持,可以在 v1 内发布,但必须同步 schema、兼容矩阵、示例和 SDK 契约测试。
- 废弃项至少在开发者文档中标记一个发布周期;破坏性变更不得在原版本中静默上线。