文档 / 接入指南
原始 Markdown ↗

接入 AI 大模型对话

更新日期:2026-10-25。当前生产版本:65ddec15。

本文面向调用知影平台大模型能力的 iOS、Web、UniApp 和外部应用。API 根地址为 https://work.zingyang.com/api。平台封装模型选择、会话、鉴权与权益计量;客户端不持有模型厂商密钥。

这不是 OpenAI API 的直接兼容地址。 请使用下文的平台请求、标准 Result 响应及命名 SSE 事件,不要将 OpenAI SDK 的 baseURL 直接改到这里并假定协议一致。

1. 调用前提

每次发起 AI 调用都必须同时满足:

  1. 平台登录 token 有效,用户存在且未停用、未删除。
  2. 当前租户存在、启用且在有效期内,租户 ID 为正数。
  3. 当前用户在该租户内具有有效成员关系。
  4. 租户具有有效的 AI_CHAT_TOKENS 权益,且剩余额度足以覆盖本次调用预算。

管理员也不豁免。服务端覆盖请求中的 userId/tenantId,不能通过 JSON 冒用用户、切换租户或指定免扣费。有效订阅、附加包、赠送及无限额度沿用平台现有权益计算;不能只判断“购买过套餐”就认定可以调用。

X-Access-Token: <平台登录token>
X-Tenant-Id: <当前已确认租户ID>
Content-Type: application/json

不要传 Apple identity token,不要把模型厂商 API Key 放在这里,也不要假设 Bearer 头可以替代平台认证头。登录流程见 Apple 登录与平台会话。

如果是 AI 工具代理用户发起调用,按平台 AI 调用规则先取得授权,并携带 X-Zing-Ai-Context: 1;涉及写入的调用还需 X-Open-Confirm: confirmed。对话会保存会话/消息并产生用量,不能把它当作无副作用的 GET 查询。普通客户端页面操作无需伪装成 AI 工具请求。

2. 模型选择

接口 用途
GET /ai/model/config/options 获取已启用模型选项;客户端选择平台已有配置
GET /ai/model/config/default 获取当前可用默认模型配置;无可用默认项时返回业务失败

两者使用相同认证与租户头。读取模型选项不等于已经通过推理额度检查。

首次接入建议省略模型字段,使用服务端默认配置。需要固定模型时,使用选项接口返回的配置 id 作为 modelConfigId,并沿用所选项的 providerCode、modelCode 对应填入 provider、model;不要猜测配置 ID 或拼装不匹配的组合。

模型配置和厂商密钥由平台管理。新增或编辑平台模型是另一个管理功能,有 ai:model:* 权限要求;不应由普通客户端通过新增配置来绕过现有模型选择或套餐限制。

3. 普通对话

POST /ai/chat/completions

最小请求:

{"prompt":"请用三句话介绍会议纪要应该包含什么。"}
字段 类型 用法
prompt string 本轮用户问题;简单接入优先使用
conversationId string 首轮省略,后续填服务端返回的会话 ID
modelConfigId string 可选,平台模型配置 ID
provider string 可选,所选配置的 providerCode
model string 可选,所选配置的 modelCode
messages array 高级调用的消息数组,成员包含 role、content;普通客户端无需重复发送整个已保存历史
knowledgeBaseIds string[] 可选,仅传用户有权使用的知识库 ID
toolCallEnabled boolean 默认 false;接入工具调用前须完成权限及写操作确认交互

首次只发送 prompt;不要同时拼装重复的 prompt 和全量 messages。已有 conversationId 必须属于当前用户与租户,不能复用其他账号的会话 ID。平台会话入口会启用个人记忆处理,具体行为受服务端实现和用户配置影响。

不要把 userId、tenantId、quotaExempt 当成客户端可控制的授权参数。quotaExempt 不从 JSON 接收;stream 也不代替选择流式接口。本文不把内部 hitsPayload、answerMeta、availableTools 等字段作为普通客户端协议。

curl --request POST 'https://work.zingyang.com/api/ai/chat/completions' \
  --header 'X-Access-Token: <平台token>' \
  --header 'X-Tenant-Id: <当前租户ID>' \
  --header 'Content-Type: application/json' \
  --data '{"prompt":"请用三句话介绍会议纪要应该包含什么。"}'

成功响应示意(值仅为示例):

{
  "success": true,
  "code": 200,
  "message": "",
  "result": {
    "conversationId": "<会话ID>",
    "provider": "<实际提供方>",
    "model": "<实际模型>",
    "content": "会议纪要应包含议题、结论和行动项。",
    "finishReason": "stop",
    "promptTokens": 100,
    "completionTokens": 30,
    "totalTokens": 130,
    "ragContext": null,
    "citations": [],
    "toolCalls": []
  },
  "timestamp": 1792886400000
}

检查 HTTP 状态后,还必须检查 success 和 code。答案在 result.content,不是 choices[0].message.content。用量字段可能包含平台估算或厂商返回值,不保证等于套餐账本的预算占用或厂商最终账单;有剩余额度也可能因不足以覆盖本轮预算被拒绝。

4. 流式对话(SSE)

POST /ai/chat/completions/stream
Accept: text/event-stream

请求体及认证头与普通对话一致。浏览器应使用支持 POST、JSON body 和认证头的 fetch 流式读取方式;原生 EventSource 不能直接满足这组请求条件。iOS 可使用 URLSession 的流式接收能力,UniApp 应选支持分块读取的平台适配。

curl --no-buffer --request POST 'https://work.zingyang.com/api/ai/chat/completions/stream' \
  --header 'X-Access-Token: <平台token>' \
  --header 'X-Tenant-Id: <当前租户ID>' \
  --header 'Accept: text/event-stream' \
  --header 'Content-Type: application/json' \
  --data '{"prompt":"帮我列出会议纪要的三个要点。"}'

协议示意(省略未使用的可选字段):

event: start
data: {"conversationId":"<会话ID>","provider":"<提供方>","model":"<模型>"}

event: delta
data: {"conversationId":"<会话ID>","content":"第一个要点"}

event: delta
data: {"conversationId":"<会话ID>","content":"是会议结论。"}

event: done
data: {"conversationId":"<会话ID>","messageId":"<消息ID>","finishReason":"stop","totalTokens":130}

事件 客户端处理
start 保存 conversationId,可包含模型及业务附加信息
delta 追加 content,不要覆盖之前收到的文本
heartbeat 保持连接,不追加到答案
tool_start / tool_result / tool_error 可选工具执行进度;按工具数据展示,不能当作文本增量
done 本轮完成,保存 messageId、用量、引用等信息;不保证携带完整答案
error 本轮失败,读取 message,停止成功状态展示

SSE data 是事件 JSON 本身,没有外层 Result,也没有 OpenAI 的 choices[].delta 或 [DONE] 约定。

解析时使用流式 UTF-8 解码;网络 chunk 可能截断汉字、JSON 或事件。按 SSE 空行分隔缓冲完整事件,支持 LF/CRLF、多行 data 和注释,不能每收到一个网络 chunk 就直接 JSON.parse。只有收到 done 才标记正常完成;连接结束不自动等于成功。

5. 错误与升级提示

普通 JSON 接口沿用标准结构:

业务码 含义与建议处理
401 登录或用户无效,重新登录
403 租户无效、未生效、停用、缺少成员关系,或调用确认条件不满足;按实际 message 提示
402 对应权益未开通、失效或额度不足;提示查看/续费/升级套餐,不自动无限重试
510 其他能力(例如知识库、工具、管理接口)的角色权限不足;不能通过换接口绕过
500 等 模型配置、参数、厂商或其他业务异常;保留实际错误信息,不全部提示为套餐不足

不能只看 HTTP 200:同步业务失败可能仍是 HTTP200 + success=false。

流式错误需要单独处理:认证过滤器等前置拒绝可能返回非 SSE 的 JSON/HTTP 错误;检查状态和 Content-Type 后再选择解析器。进入 SSE 后,当前控制器会把同步准备阶段错误转成 error 事件,数据只有 message 等事件字段,不保证附带 401/402/403 业务码:

event: error
data: {"message":"<服务端实际错误信息>"}

因此不要对 SSE error 执行 data.code === 402 并假定一定能识别套餐状态,也不要靠匹配某一句中文消息作为稳定协议。需要准确区分升级场景时,应结合客户端现有套餐状态界面;流式错误本身按实际 message 展示。本文不虚构新的升级接口、错误结构或套餐购买地址。

6. 会话恢复、重命名和删除

接口 请求
GET /ai/chat/conversations 本人当前租户会话列表
GET /ai/chat/conversations/{id} 会话详情及已保存消息
PUT /ai/chat/conversations/{id}/rename JSON:{"title":"新标题"}
DELETE /ai/chat/conversations/{id} 删除本人会话

以上接口仍要求有效身份及租户归属,但读取历史、重命名和删除不作为新的模型推理扣费。不要绕过归属校验。AI 工具执行 DELETE 还须采用 X-Open-Confirm: text:<至少4字符的确认文本>。

网络断开后,服务端可能继续生成并保存回答。客户端中止 HTTP 接收不等于厂商任务已取消,也不等于自动退还额度;先用会话详情核实结果,避免立即重试造成重复生成和用量。通用对话接口没有在本文承诺幂等请求键或独立停止接口;不要套用 Talk 的专用取消协议。

7. 知识库、工具与其他 AI 能力

  • 知识库问答通过 knowledgeBaseIds 关联已授权资料,答案可带 citations;不要把普通模型回答伪装成有资料出处。
  • 工具调用默认关闭。开启后仍受当前用户权限及数据写操作确认限制;模型决定调用工具不等于用户已经授权写入。
  • 应用固定的人设、指令和输出模板应复用平台提示词管理;不要在客户端复制一套长期维护的系统提示词。用户当轮问题作为输入提交。
  • 图片附件、录音问答、ASR/OCR、图片生成有各自业务协议与计量口径;不能仅修改本接口字段就假定调用了这些能力。文件上传见 COS 上传文档。
  • TTS 当前未核实到可发布的业务调用入口,本文不提供虚构路径。

8. 验证边界

源码依据:AiChatController、AiChatRequest/Response/StreamEvent、AiChatServiceImpl、AiInvocationAccess、AiModelConfigController;实际调用方为 Admin 的 ai.api.ts 和共享 SSE 解析链路。基础准入随65ddec15部署;本次文档编写没有发起新的生产模型推理或消耗客户额度,不将协议示例当作真实厂商联调结果。