🎉 新版站点已上线 — 新用户请在 v2.cloudmist.cloud 注册使用,本站教程均以新站地址为准 · 老用户账号已迁移完成,用原用户名/邮箱 + 原密码可直接登录 新站(登不上请在用户名后加 _82350),原站余额可继续在 api.cloudmist.cloud 用完,新站需重建令牌并改用新站 base_url
首页 › 教程 · 文章 › Vercel AI SDK 怎么接第三方 API?消息转换与前端流配对

Vercel AI SDK 怎么接第三方 API?消息转换与前端流配对

云岚API · 教程 · 更新于 2026-10-25

Vercel AI SDK 接第三方 API,要同时接通两段:服务端按上游协议调用模型,前端按 AI SDK UI 协议接收结果。把上游 SSE 原样返回给 useChat,即使 HTTP 200,也可能无法显示。本文核对日期为 2026-10-25,依据当前 v7 文档及固定源码;未安装运行 SDK,也未联调云岚API。

先记版本,再选服务端模型适配器

本次源码快照中,ai 为 7.0.153、@ai-sdk/react 为 4.0.157、@ai-sdk/openai-compatible 为 3.0.78。它们的版本号并不相同;按项目锁文件记录实际组合,不把不同代教程的函数混用。固定源码快照

面向 Chat Completions 兼容端点,可用 createOpenAICompatible 创建提供方,再用 chatModel(准确模型ID) 明确选择聊天模型。兼容适配器配置

别将它与 @ai-sdk/openai 的同名调用习惯混为一谈:核对快照中,后者默认模型工厂走 Responses,显式 .chat() 才选择 Chat 路线。只改 baseURL 不会把不支持的 Responses 变成 Chat。OpenAI 适配器路由源码

浏览器发 UIMessage,服务器转换后再调用

前端 useChat 可配 new DefaultChatTransport({ api: '/api/chat' }),这里填的是自己的应用路由,不是上游 /chat/completions。提供方 Key 留在服务端;路由还要检查登录、会话归属和输入范围,不能只隐藏 Key 就开放给任何人调用。Transport 定义

UIMessage 包含 id、role、parts 等界面信息,不能直接当上游消息数组。下面是服务端处理片段;调用前须完成应用权限和长度限制。配置后调用会请求模型,本文只做静态核对:

import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import {
  validateUIMessages, convertToModelMessages, streamText,
  toUIMessageStream, createUIMessageStreamResponse,
} from 'ai';

const apiKey = process.env.APP_API_KEY;
const modelId = process.env.APP_MODEL_ID;
if (!apiKey || !modelId) throw new Error('Missing server configuration');
const provider = createOpenAICompatible({
  name: 'yunlan',
  baseURL: 'https://v2.cloudmist.cloud/v1',
  apiKey,
});

export async function buildReply(messages) {
  const checked = await validateUIMessages({ messages });
  const result = streamText({
    model: provider.chatModel(modelId),
    messages: await convertToModelMessages(checked),
  });
  return createUIMessageStreamResponse({
    stream: toUIMessageStream({ stream: result.stream }),
  });
}

地址是本站基础前缀示意,模型由服务端配置,不接收浏览器任意指定的上游地址。validateUIMessages 做消息结构检查,不代替身份鉴权;convertToModelMessages 返回 Promise,须等待转换完成。校验源码、消息转换参考

在自己的 POST 路由中读取请求正文,完成检查后,将其中的 messages 交给 buildReply,再直接返回得到的 Response。不要把这个 Response 再包进普通 JSON,也不要先读取完整文本再声称实时流式。校验失败与模型调用失败应分别记录,发给浏览器的错误须脱敏;上面的函数没有替应用实现这些路由处理。

自定义 data-* 部分默认会被转换过滤。界面显示了附件摘要,不代表模型读到了它;确需传入时按 convertDataPart 明确转换。工具和文件也要按各自结构处理,不能把所有 parts 拼成一个字符串。

返回流必须与前端 transport 配对

前端选择 服务端返回方向
DefaultChatTransport UI Message Stream;上例转换并封装响应
TextStreamChatTransport 纯文本流,使用 v7 的 toTextStream 与 createTextStreamResponse

纯文本流只保留基础文字,不适合传递工具等结构。UI 流虽使用 SSE,却有自己的事件字段;自定义后端还须设置 x-vercel-ai-ui-message-stream: v1。只加这个头,不能把原始上游事件变成 UI 流。优先由配套 SDK 转换,不手拼一个“看起来像流”的响应。官方流协议

本文用 v7 的独立转换与响应函数,不照搬旧教程的 result.toUIMessageStreamResponse()。前端按 message.parts 渲染 text 部分,并处理状态与错误;不要只读取旧示例里的 message.content。当前 Chatbot 示例

后端有字、前端没字,按链路留下证据

先用无工具、无附件的短任务,写明预期,例如“将会议通知改成一句礼貌提醒,保留时间”。依次记录应用路由是否收到请求、转换后是否保留输入、实际上游路径、返回协议、前端 parts 与错误。

现象 下一步查哪层
自家 /api/chat 返回 404 路由位置、部署路径和 transport 地址
服务端收到请求,但上游认证失败 服务端实际配置、Key 所属服务与模型权限
上游有输出,浏览器报流解析错误 返回封装和 transport 是否属于同一协议与版本
页面有自定义资料,回答却没用到 转换后的模型消息是否真正包含该资料

本地开发与已部署应用也分别留记录。浏览器看到的错误未必是上游原始错误;同时查看对应服务端日志,按时间和本地脱敏编号关联,不在截图中暴露凭据。

收到 text 增量只是预览,还要区分消息结束、错误或中止;不要为了让页面停止转圈伪造完成。流事件检查见SSE 与终态,重发前看超时重试决策。再验收提醒是否保留原时间,传输完成不等于答案合格。

下载前后端配对检查包,按同一配置填写空白 CSV;人工案例仅供讨论,没有预填成功记录。已有云岚API账号先在控制台确认模型与权限,新项目先完成首次接入,再加入所需能力。

常见问题

两边都用 SSE,为什么不能直接透传?

SSE 是传输格式,事件正文各有约定。上游的 choice 或响应事件,不是默认 transport 期待的 UIMessageChunk;需要正确转换。

把 baseURL 改了,为什么请求仍走 Responses?

地址与模型适配器的路线是两件事。核对导入包、调用的工厂方法及实际路径,不能靠改 URL 后缀掩盖协议不匹配。

页面里有历史,下一轮就自动带给模型吗?

还要看本次发送和转换后的消息。自定义请求裁剪、data 部分过滤都可能丢信息;持久化与会话隔离另按多轮上下文处理。

普通聊天通过,就能打开工具和结构化输出吗?

不能直接推定。适配器选项不会创造上游能力;按目标模型和渠道分别确认支持,再验收对应返回结构及业务结果。

注册后查看试用额度与领取条件

按当前模型列表选择服务,先核对令牌分组、接口协议与价格,再用自己的任务验证。

注册并查看试用条件 →已有账号?进入控制台创建令牌 · 调用报错先排查
注册、充值和调用均在云岚API 新业务站完成
相关内容
本站为云岚API 注册、登录与充值入口站点 · 模型与价格以控制台实时数据为准 · 更新于 2026-10-25
Claude、GPT、Gemini 等名称为各自权利人商标,本站为独立第三方 API 中转/聚合服务,与上述厂商无隶属或授权关系。