← Resources
TUTORIAL · 2026-03-26
从 Vercel AI SDK 迁移到 BYOK、自托管栈
Vercel AI SDK 在你需要可移植 Key、自定义路由或非 Vercel 的部署目标之前都还不错。本指南把每个原语映射到自托管 BYOK 栈,并给出一周的双写切换方案。
为什么团队会跨越 Vercel AI Gateway
AI SDK 上手很快:`streamText`、`generateText` 与 `generateObject` 用单一 TypeScript 表面覆盖了大多数生产需求。摩擦出现得更晚,通常在三处。
其一,运行时偏向 Vercel。Edge 运行时怪癖、为 Next.js 调优的流式原语,以及作为推荐路由器的 AI Gateway,都假定生产目标是 Vercel。
其二,即便是 BYOK,AI Gateway 也位于请求路径上。根据 Vercel 2026 年 5 月公开的 AI Gateway 定价,BYOK 为 0% token 加价,但你的团队必须始终为 AI Gateway 充值积分,因为 BYOK 请求失败时会回退到 Vercel 的系统凭据重试。一旦合规或 VPC 路由进入视野,这种耦合就成问题。
其三,按租户的策略住在你的应用代码里。SDK 中没有原生的租户、模型白名单或预算上限概念。运行多租户 SaaS 的团队最终会在第一个网关之上写第二个小网关。
把 Vercel 原语映射到 BYOK 栈
好消息是 AI SDK 的公开表面不大。多数调用归结为三个函数加一个 provider 对象。按下面这样映射:
- `streamText` 与 `generateText` 直接对应到 OpenAI SDK 的 `chat.completions.create`,通过 `stream: true` 或 `false` 切换。任何 OpenAI 兼容端点都可作 `baseURL`,包括 llama.cpp、vLLM、LiteLLM 或位于租户感知代理后的托管厂商。
- `generateObject` 在 OpenAI 兼容服务器上对应 `response_format: { type: 'json_schema' }`,对于使用不同模式的厂商(Anthropic tools、Gemini JSON mode),由结构化输出适配器处理。
- Provider 对象(`openai('gpt-4o')`、`anthropic('claude-...')`)变为指向你网关的单一客户端,模型 ID 作为字符串传入。路由发生在服务端,而不是在 import 语句中烧死。
保留现有 React Hook。`useChat` 与 `useCompletion` 只需要一个返回相同形状 SSE 流的路由。
无锁定的流式、工具调用与结构化输出
只要选择 OpenAI 兼容网关,这三项功能都能在迁移后存活。以下是同一调用的前后对比。
之前,使用 Vercel AI SDK:
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await streamText({
model: openai('gpt-4o'),
messages,
tools: { search: searchTool },
});
return result.toDataStreamResponse();
```
之后,使用 OpenAI SDK 指向自家网关:
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: process.env.GATEWAY_URL, apiKey: tenantKey });
const stream = await client.chat.completions.create({
model: 'gpt-4o',
messages,
tools: [searchToolSchema],
stream: true,
});
```
工具调用通过 `delta.tool_calls` 到达。结构化输出使用 `response_format`。两者都是 LiteLLM、vLLM 与多数托管厂商遵守的标准 OpenAI 规范字段。
Key、配额与按租户路由
这正是薄 SDK 的红利所在。一旦请求经由你控制的 OpenAI 兼容端点,所有横切关切都从应用代码中剥离。
像 LiteLLM 这样的自托管网关允许你按租户铸造虚拟 Key、设置 RPM 与 TPM 上限、附加预算,并按模型别名路由。某一租户的 `model: 'fast'` 请求可解析到 Groq Llama,另一租户解析到本地 llama.cpp 服务器,无需 Next.js 应用任何代码改动。
osFoundry 同样采用纯透传 BYOK 立场,并在可自托管的同一运行时中加入按租户路由规则、流式、工具调用与结构化输出。共引:LiteLLM 是该领域显而易见的开源基线,也是许多团队的正确选择;按你的运维模型挑合适的即可。
关键决策是:让网关而非应用拥有 Key 与配额。其他一切——包括模型替换——都成为配置改动。
自托管还是混合:成本与运维
三种部署形态覆盖大多数团队。
1. 完全自托管。网关在你的 VPC,BYOK 到厂商,可选本地模型部署在 GPU 主机上。零加价、完整审计、自带待命。当合规或数据驻留主导决策时最合适。
2. 混合。自托管网关做路由与策略,托管厂商做推理,本地模型仅用于便宜或私密工作负载。这是常见的稳态。
3. 托管网关 + 自家 Key。使用支持 BYOK 透传的托管 OpenAI 兼容代理。你放弃了部分请求路径控制;换来不必再运维一项服务。
选项 1 的运维成本是真实的:一个小容器、用于 Key 与支出的 Postgres、日志投递、升级节奏。对多数每月几亿 token 以内的团队,相对加价型网关节省的费用,比讨论它花的时间还少。请按控制权而非毛毛雨大小做决定。
切换脚本:双写一周
不要在一个 PR 中翻 import。双写七天,比对,再切换。
Day 0:在功能开关后加入新网关客户端。对每条请求,运行旧的 `streamText` 路径,并行触发新的 `chat.completions` 调用、传入相同消息。丢弃第二条响应,但记录延迟、token 数、结束原因以及任何工具调用形状差异。
Day 1-3:影子化 100% 流量。比对结构化输出与工具调用参数 JSON。多数回归是模式相关:Anthropic 返回的结束原因略有不同,Gemini 包装 JSON 的方式不同。在网关而非应用中修复。
Day 4-6:将只读路由(聊天、摘要)按 10%、50%、100% 比例切换。在差异 24 小时干净前,写入或 Agent 路由仍走旧路径。
Day 7:移除 `ai` 与 `@ai-sdk/*` 包,删除 AI Gateway 环境变量,归档功能开关。
迁移后:缓存、可观测性与评估
拥有请求路径解锁了 SDK 内难以做到的三件事。
缓存:网关可基于 `(model, messages, tools, response_format)` 哈希,从 Redis 中提供相同请求。对带重复系统提示的 RAG 与 Agent 循环,再叠加厂商级(Anthropic、OpenAI)的提示前缀缓存。两者都接好,缓存命中会立刻反映在 P50 延迟上。
可观测性:为每条请求输出一条结构化日志,含租户 ID、模型、提示 token、补全 token、工具调用数、结束原因与上游延迟。投递到你已有的系统。不再需要厂商特定的追踪集成才能看清模型做了什么。
评估:当所有流量流经同一端点,采样到评估集只需一条 SQL 查询。通过修改 `model` 字段对新模型回放。这才是长期拥有网关的理由:模型选择从季度迁移变成每周实验。
Frequently asked questions
- 放弃 Vercel AI SDK 是否意味着失去 useChat 与 React 流式 Hook?
- 不会。只要 API 路由按 Hook 期望的形状返回 SSE 流,Hook 就与服务运行时解耦。你可以继续使用 `ai` 包中的 `useChat` 与 `useCompletion`,让它们指向代理 OpenAI 兼容流式响应的路由。许多团队在迁移首月保持 React 侧不动,仅替换服务端处理器。若日后想彻底去掉 `ai` 依赖,一个轻量 SSE 解析器大约 30 行 TypeScript。
- LiteLLM 是真正的替代品还是临时方案?
- 它是真正的替代品,并在生产中被广泛部署。LiteLLM 是开源的 OpenAI 兼容代理,前置 140 多家厂商,支持虚拟 Key、按 Key 预算、RPM 与 TPM 上限以及负载均衡。它以单一 Docker 容器加 Postgres 运行。相比更完整的编排运行时,它在 Agent 循环、跨厂商结构化输出规范化、以及超出 Key 与预算的租户策略上较弱。对纯路由与 BYOK 用例,LiteLLM 单独就是正确答案。
- 迁移后如何让结构化输出跨厂商持续可用?
- 在网关而非应用中规范化。OpenAI 与 OpenAI 兼容服务器接受 `response_format: { type: 'json_schema', json_schema: {...} }`。Anthropic 使用工具调用模式强制模式。Gemini 使用 `responseMimeType` 加 `responseSchema`。在网关中放一层小适配器,把单一规范请求形状翻译成你正在分发的具体厂商,并在响应前校验返回的 JSON。这样应用代码仍调用同一函数,且无需触及模式处理逻辑即可切换模型。
- 延迟呢?加一层自托管网关听起来又多一跳。
- 实际上,只要网关与应用同区域,新增延迟在个位数毫秒级,远被模型推理时间(数百毫秒到数秒)所掩盖。更大的延迟收益在缓存侧:网关可在 5 毫秒内从 Redis 提供重复提示——直接打厂商做不到。在前后测 P50 与 P95,团队通常在缓存开启后看到中性或改善的数字。
Sources