news 2026/5/25 17:18:24

Vercel AI SDK 入门:一行代码切换 LLM Provider

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vercel AI SDK 入门:一行代码切换 LLM Provider

本文面向:想了解如何用统一接口对接多个 LLM Provider 的开发者。
预计阅读时间:10 分钟
最终效果:理解 Vercel AI SDK 的 generateText / generateObject / embed 核心 API,掌握 Provider 工厂模式和 Zod Schema 结构化输出。


为什么需要统一抽象?

假设你正在开发一个 AI 应用,最开始用 Ollama 本地模型做原型,后来想切到 OpenAI 获得更好的效果,再后来又想试试 Anthropic 的 Claude。如果没有统一抽象,你需要:

  • 为每个 Provider 写不同的 API 调用代码
  • 处理每个 Provider 不同的请求/响应格式
  • 在切换时修改大量业务代码

Vercel AI SDK(ai包)解决了这个问题。它提供了一套统一的generateTextgenerateObjectembed等 API,底层通过 Provider 适配器对接不同的模型服务。你的业务代码只需要写一次,切换 Provider 只需改配置。

ChatCrystal 项目支持 6 种 Provider——Ollama、OpenAI、Anthropic、Google、Azure、Custom——全部通过 Vercel AI SDK 统一调用。本文以 ChatCrystal 的实际代码为例,讲解 SDK 的核心用法。

核心 API 速览

Vercel AI SDK 提供三个核心函数,覆盖了最常见的 AI 调用场景:

1. generateText — 生成文本

最基本的调用方式,给一个 prompt,返回文本结果:

import{generateText}from'ai';const{text}=awaitgenerateText({model:getLanguageModel(),prompt:'用一句话解释什么是向量数据库',});

2. generateObject — 结构化输出

这是 AI SDK 最强大的能力之一。你用 Zod 定义一个 schema,LLM 会返回严格符合该结构的 JSON 对象,无需手动解析:

import{generateObject}from'ai';import{z}from'zod';constschema=z.object({title:z.string().describe('简洁的标题,20字以内'),summary:z.string().describe('2-4 段 markdown 摘要'),key_conclusions:z.array(z.string()).describe('3-5 个关键结论'),tags:z.array(z.string()).describe('3-6 个小写英文标签'),});const{object}=awaitgenerateObject({model:getLanguageModel(),schema,system:'你是一个技术对话分析专家',prompt:transcript,});// object 的类型完全匹配 schema,TypeScript 自动推导

ChatCrystal 的对话摘要功能就是这么实现的。generateObject内部会将 Zod schema 转换为 JSON Schema,注入到 prompt 中引导 LLM 输出结构化数据,然后自动校验返回结果。如果校验失败,SDK 会自动重试(默认 3 次)。

3. embed — 生成向量嵌入

用于语义搜索的文本向量化:

import{embed}from'ai';const{embedding}=awaitembed({model,value:query});// embedding 是 number[],维度取决于模型

ChatCrystal 在两个地方用到embed

  • 笔记入库时:将笔记文本分块后逐块生成向量,存入 vectra 索引
  • 搜索查询时:将用户查询转为向量,在索引中做相似度检索

Provider 工厂模式

ChatCrystal 用工厂模式管理 6 种 Provider。核心是一个ProviderEntry接口:

interfaceProviderEntry{name:string;displayName:string;supportsEmbedding:boolean;requiresApiKey:boolean;requiresBaseURL:boolean;createLanguageModel(config:ProviderConfig):LanguageModel;createEmbeddingModel?(config:ProviderConfig):EmbeddingModel;}

每个 Provider 注册到一个 Map 中:

constproviders=newMap<string,ProviderEntry>();providers.set('ollama',{/* ... */});providers.set('openai',{/* ... */});providers.set('anthropic',{/* ... */});// ...

获取模型实例只需两步:

functiongetLanguageModel():LanguageModel{const{provider,...config}=appConfig.llm;returngetProvider(provider).createLanguageModel(config);}

getProvider(name)从 Map 中查找 Provider,调用其createLanguageModel方法返回一个LanguageModel实例。之后所有业务代码都通过这个实例调用generateText/generateObject,完全不关心底层是哪个 Provider。

6 种 Provider 的实现细节

Ollama — 本地推理

Ollama 没有官方的 Vercel AI SDK 适配器,但它提供 OpenAI 兼容的/v1/端点。所以 ChatCrystal 用@ai-sdk/openai来对接:

providers.set('ollama',{createLanguageModel({baseURL,model}){consturl=baseURL||'http://localhost:11434';constollama=createOpenAI({baseURL:`${url}/v1`,apiKey:'ollama',// Ollama 不需要真实 key,填个占位值name:'ollama',});returnollama(model);},});

这个技巧非常实用:任何提供 OpenAI 兼容 API 的服务(比如 vLLM、LiteLLM、LocalAI)都可以用createOpenAI适配。apiKey填一个占位字符串即可,因为本地服务不校验它。

OpenAI / Anthropic / Google — 原生 SDK

这三个 Provider 各有官方适配器,用法几乎一致:

// OpenAIconstopenai=createOpenAI({baseURL,apiKey});returnopenai(model);// Anthropicconstanthropic=createAnthropic({apiKey});returnanthropic(model);// Googleconstgoogle=createGoogleGenerativeAI({apiKey});returngoogle(model);

注意 Anthropic 不支持 embedding(supportsEmbedding: false),所以如果你用 Claude 做摘要,embedding 还需要单独配一个支持的 Provider。

Azure — 企业部署

Azure OpenAI 通过@ai-sdk/azure适配,需要提供 Azure 专属的 endpoint URL 和 API key:

constazure=createAzure({baseURL,apiKey});returnazure(model);

Custom — 万能兜底

Custom Provider 和 Ollama 的思路一样,用createOpenAI对接任何 OpenAI 兼容的 API:

providers.set('custom',{createLanguageModel({baseURL,apiKey,model}){constcustom=createOpenAI({baseURL,apiKey,name:'custom'});returncustom(model);},});

这是最具扩展性的设计——用户不需要等我们新增 Provider 适配,只要服务兼容 OpenAI API 格式,填个 URL 和 key 就能用。

generateObject 的 Zod Schema 验证

generateObject的结构化输出依赖 Zod schema。ChatCrystal 在两个场景中重度使用它:

场景一:对话摘要

constSummarizeSchema=z.object({title:z.string(),summary:z.string(),key_conclusions:z.array(z.string()),code_snippets:z.array(z.object({language:z.string(),code:z.string(),description:z.string(),})),tags:z.array(z.string()),});const{object}=awaitgenerateObject({model:getLanguageModel(),schema:SummarizeSchema,system:SYSTEM_PROMPT,prompt:transcript,maxOutputTokens:4096,maxRetries:3,});

.describe()方法可以给每个字段加上自然语言描述,这些描述会被注入到 prompt 中,帮助 LLM 理解每个字段的期望内容。

场景二:笔记关系发现

constRelationElementSchema=z.object({target_note_id:z.number().describe('目标笔记的 ID'),relation_type:z.enum(['CAUSED_BY','LEADS_TO','RESOLVED_BY','SIMILAR_TO','CONTRADICTS','DEPENDS_ON','EXTENDS','REFERENCES',]).describe('关系类型'),confidence:z.number().min(0).max(1).describe('置信度,0.0-1.0'),description:z.string().describe('简短说明关系,20字以内'),});const{object:rawRelations}=awaitgenerateObject({model:getLanguageModel(),output:'array',// 输出是一个数组schema:RelationElementSchema,system:RELATION_SYSTEM_PROMPT,prompt,});

这里用了output: 'array'参数,告诉 SDK 返回一个数组而非单个对象。配合z.enum()可以限制字段的合法取值范围——如果 LLM 返回了不在枚举中的关系类型,SDK 会自动重试。

配置驱动的 Provider 切换

ChatCrystal 的配置结构非常直观:

// config.json{"llm":{"provider":"openai","baseURL":"","apiKey":"sk-...","model":"gpt-4o"},"embedding":{"provider":"ollama","baseURL":"http://localhost:11434","apiKey":"","model":"nomic-embed-text"}}

LLM 和 Embedding 是独立配置的。你可以用 OpenAI 做摘要、Ollama 做 embedding,反之亦然。切换 Provider 只需要改provider字段,业务代码零修改。

这就是抽象层的价值——generateObject({ model, ... })这行代码不关心model是 GPT-4o、Claude Sonnet 还是 Qwen2.5,SDK 帮你处理了所有差异。

错误处理:自动重试

AI SDK 内置了重试机制。maxRetries参数控制失败后的重试次数:

const{object}=awaitgenerateObject({model:getLanguageModel(),schema:SummarizeSchema,system:SYSTEM_PROMPT,prompt:transcript,maxRetries:3,// 失败后最多重试 3 次});

ChatCrystal 在关系发现中设maxRetries: 2,在摘要中设maxRetries: 3。重试对处理 429(Rate Limit)和 5xx 错误特别有用。此外,ChatCrystal 在队列层还做了并发控制(concurrency=1)和 1 req/sec 的限速,与 SDK 的重试机制形成双层保护。

总结

Vercel AI SDK 的核心设计理念是抽象差异、统一接口

概念作用
generateText生成自由文本
generateObject生成结构化 JSON,Zod schema 校验
embed生成向量嵌入
Provider 适配器createOpenAI/createAnthropic/createGoogleGenerativeAI
LanguageModel统一的模型实例,所有 API 函数的第一个参数
maxRetries自动重试,处理瞬时错误

对于学生来说,理解这个设计模式比记住具体 API 更重要:当你需要对接多个外部服务时,定义一个统一接口,让每个服务实现自己的适配器,业务代码只依赖接口而不依赖具体实现。这就是 Strategy 模式在 AI 领域的典型应用。

下一步

  • 阅读 Vercel AI SDK 官方文档 了解更多 API 细节
  • 试试用createOpenAI对接一个兼容 OpenAI 的本地服务(如 vLLM、LM Studio)
  • 探索streamTextstreamObject实现流式输出
  • 了解 AI SDK 的 Tool Calling 能力,让 LLM 调用外部函数

项目地址:github.com/ZengLiangYi/ChatCrystal

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 17:16:26

解锁B站知识宝藏:BiliBiliCCSubtitle字幕下载与转换全攻略

解锁B站知识宝藏&#xff1a;BiliBiliCCSubtitle字幕下载与转换全攻略 【免费下载链接】BiliBiliCCSubtitle 一个用于下载B站(哔哩哔哩)CC字幕及转换的工具; 项目地址: https://gitcode.com/gh_mirrors/bi/BiliBiliCCSubtitle 在信息爆炸的时代&#xff0c;B站&#xff…

作者头像 李华
网站建设 2026/5/25 17:13:07

Hermes Agent解析

Hermes Agent(中文俗称"爱马仕")作为2026年初AI智能体领域崛起的明星项目,凭借其"与你共同成长"的核心理念和创新的自我进化架构,在GitHub上迅速斩获超过14万星标,跻身全球最受关注的AI基础设施项目之列。该项目由硅谷AI实验室 hResearch 开发,采用M…

作者头像 李华
网站建设 2026/5/25 17:12:24

使用Taotoken后API调用的延迟与稳定性体验观察

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 使用Taotoken后API调用的延迟与稳定性体验观察 作为一名需要频繁调用大模型API的开发者&#xff0c;将多个厂商的模型接入到自己的…

作者头像 李华
网站建设 2026/5/25 17:12:16

保姆级教程:用Python+SimpleITK搞定LUNA16肺部CT的肺实质分割(附完整代码)

零基础实战&#xff1a;PythonSimpleITK实现LUNA16肺部CT精准分割全流程第一次接触医学图像处理时&#xff0c;我被那些灰蒙蒙的CT切片弄得一头雾水——直到在LUNA16数据集上成功分割出第一个肺实质轮廓。那种看到算法从混沌中勾勒出器官边界的震撼&#xff0c;至今记忆犹新。本…

作者头像 李华
网站建设 2026/5/25 17:11:59

构建内容生成中台时借助Taotoken实现模型灵活选型

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 构建内容生成中台时借助Taotoken实现模型灵活选型 设想一个需要为运营、市场部门提供内容生成能力的技术中台项目。这类项目通常面…

作者头像 李华