AI 开发者必备:Vercel AI SDK 轻松搞定多厂商 AI 调用

前言

随着近两年 AI 大模型的井喷式增长,国内外涌现出了众多大模型厂商。国外有 ChatGPT、Claude、Gemini、Grok 等,国内则有 DeepSeek、通义千问、豆包、KIMI 等。此外还有我们常用的量化模型部署框架 Ollama。尽管很多厂商已经提供了与 OpenAI 兼容的接口,但像 Gemini、Ollama 等仍然没有兼容。为了兼容所有 AI 模型厂商的接口,开发者往往需要自行编写兼容层。

那么今天,将为大家介绍一个由 Vercel 开源的新 npm 库------ai。这个库不仅提供了官方支持的几个 AI 厂商接口的兼容层,还包含了社区贡献的 AI 接口兼容层,如 Ollama、LLamaCpp、Chrome AI 等。有了它,开发者无需再担心接口规范不统一的问题。

AI SDK

安装 AI SDK

AI SDK 分为两部分:AI Core SDK 和 AI Provider SDK,也就是核心包和 AI 供应商接口包

AI Core SDK:

bash 复制代码
npm install ai

AI Provider SDK:

每个 AI 供应商都有自己的接口实现。例如,如果我们使用 OpenAI、DeepSeek 和 Ollama,就需要安装以下三个包:

bash 复制代码
npm install @ai-sdk/openai @ai-sdk/deepseek ollama-ai-provider

这里要特别说明一下,尽管提供了单独的 @ai-sdk/deepseek 包,但由于 DeepSeek 本身兼容 OpenAI 接口,因此也可以直接使用 @ai-sdk/openai 包。

另外,OpenAI 和 DeepSeek 这两个包是由 Vercel 官方提供的,而 Ollama 则是社区贡献的包。从包名上就能看出二者的区别。

使用示例

AI Core SDK 提供的接口并不多,但如果我们仅用于对话和文本生成,常用的接口主要有两个。

js 复制代码
import { generateText } from 'ai'
import { createDeepSeek } from '@ai-sdk/deepseek'

const deepseek = createDeepSeek({
  baseURL: 'https://api.deepseek.com/v1',
  apiKey: process.env.DEEPSEEK_API_KEY,
})

const { text } = await generateText({
  model: deepseek('deepseek-reasoner'),
  prompt: '你好,请介绍一下你自己,不少于 100 字',
})

console.log(text)

可以看到,调用起来非常简单。以下是输出结果:

常用方法

上面是基本方法,接下来我们将介绍 AI SDK 常用的几个方法。

生成文本

在上面的示例中,我们使用了生成文本的方法:generateText

js 复制代码
const { text } = await generateText({
	model: ollama('qwen2.5:7b'),
	prompt: '你好,请介绍一下你自己,不少于 100 字',
})

以下是一部分参数和说明,另外还支持传入 temperaturetopPtopKpresencePenalty 等大模型参数,这里不再一一列举。

参数名 参数类型 参数描述
model LanguageModel 指定使用的语言模型实例。需通过构造函数初始化模型,示例:openai('gpt-4-turbo') 表示调用 OpenAI 的 GPT-4 Turbo 版本模型。
system string 系统级角色定义指令,用于设定模型在对话中的基础行为模式(如角色定位、响应格式要求等)。该指令具有最高优先级,会持续影响后续对话的生成逻辑。
prompt string 单轮对话的文本生成输入。适用于非连续对话场景,与 messages 参数互斥,二者只能选其一。
messages `Array<CoreSystemMessage CoreUserMessage
maxTokens? number 输出内容的长度限制(按token计算)。1个token≈0.75个英文单词或1个汉字。设置过低可能导致输出截断,建议根据模型上下文窗口合理设定。
maxRetries? number API调用失败时的最大重试次数(默认2次)。设置为0将禁用重试机制。注意:仅对可重试错误(如网络抖动、速率限制)生效,认证错误等致命错误不会重试。
abortSignal? AbortSignal 支持传入AbortController的signal对象,用于实现生成过程的主动中断控制。典型应用场景:用户取消生成、页面跳转时终止未完成请求。
headers? Record<string, string> 自定义HTTP请求头。适用于需要添加代理、自定义认证、特殊路由等高级场景。注意:仅对基于REST API的模型提供商生效,SDK方式集成的模型可能忽略此参数。

Tips:

参数传入 prompt 是单轮对话文本生成,但需要多轮对话时,参数使用 messages

messages 中的 role 只有 userassistant,系统提示词通过 system 参数传入。

流式文本

我们最常见的就是用于 AI Chat 对话的流式生成接口,通过 streamText 实现。

获取到 textStream 后,通过 for await 可以获取每个流的文本内容。

streamText 的参数和 generateText 基本一样,这里不再重复说明。

js 复制代码
const { textStream } = await streamText({
	model: ollama('qwen2.5:7b'),
	prompt: '你好,请介绍一下你自己,不少于 100 字',
})

for await (const chunk of textStream) {
	console.log(chunk)
}

调用结果示例:

生成对象

使用 LLM 为给定的提示和模式生成类型化、结构化的对象。它可用于 LLM 返回结构化数据,例如用于信息提取、合成数据生成或分类任务。

例如,下面的示例通过 generateObject 生成了十组数据。需要注意的是,该方法依赖于 zod 库,需要提前安装。

js 复制代码
import { z } from 'zod'

const { object } = await generateObject({
  model: ollama('qwen2.5:7b'),
  output: 'array',
  prompt: '请你生成三组数据,数据包含姓名、性别、年龄、身高、体重、地址、电话',
  schema: z.object({
    name: z.string(),
    sex: z.string(),
    age: z.number(),
    height: z.number(),
    weight: z.number(),
    address: z.string(),
    phone: z.string(),
  })
})

console.log(JSON.stringify(object, null, 2))

以下是简化后的参数表格,几乎支持大部分 generateText 参数,这里不再列举。主要介绍 generateObject 中比较重要和独有的参数。

参数名 类型 描述
model LanguageModel 语言模型实例化对象,需通过构造函数初始化。示例:openai('gpt-4-turbo') 调用OpenAI的GPT-4 Turbo模型
output `'object' 'array'
mode `'auto' 'json'
schema `Zod Schema JSON Schema`
schemaName `string undefined`
schemaDescription `string undefined`
enum string[] 枚举约束 。限定输出值的可选范围,仅当output='enum'时生效

调用结果示例:

流式对象

流式生成对象,参数和 generateObject 基本一致,这里不再赘述。通过遍历 partialObjectStream 获取每一次的 chunk,每次获取都是一个完整的对象。

js 复制代码
import { z } from 'zod'

const { partialObjectStream } = await streamObject({
  model: ollama('qwen2.5:7b'),
  output: 'array',
  prompt: '请你生成三组数据,数据包含姓名、性别、年龄、身高、体重、地址、电话',
  schema: z.object({
    name: z.string(),
    sex: z.string(),
    age: z.number(),
    height: z.number(),
    weight: z.number(),
    address: z.string(),
    phone: z.string(),
  })
})

for await (const chunk of partialObjectStream) {
  console.log(JSON.stringify(chunk, null, 2))
}

调用结果示例:

剩下还有诸如 generateImagejsonSchemaembed 等等工具方法,这里就不一一列举了。

封装方法

对于不同的 AI Provider SDK,Vercel 提供了一套标准,所有接入的包都遵循此标准开放对应的接口。因此,如果我们需要接入多个 AI 厂商,可以创建一个工厂,统一管理所有的包。后续新增、删除都可以在这个工厂中进行操作。如下,我们封装了一个 AIProviderFactory 方法,可以通过 createProvider 创建 provider 实例。

js 复制代码
import { createDeepSeek } from '@ai-sdk/deepseek'
import { createOpenAI } from '@ai-sdk/openai'
import { createOllama } from 'ollama-ai-provider'

export const AIProviderType = {
  OLLAMA: 'ollama',
  OPENAI: 'openai',
  DEEPSEEK: 'deepseek',
}

export const AIProviderFactories = {
  [AIProviderType.OLLAMA]: createOllama,
  [AIProviderType.OPENAI]: createOpenAI,
  [AIProviderType.DEEPSEEK]: createDeepSeek,
}

export class AIProviderFactory {
  /**
   * 创建 AI Provider
   * @param {string} providerType - AI Provider 类型
   * @param {Object} config - AI Provider 配置
   * @returns {Object} - AI Provider 实例
   */
  static createProvider(providerType, config) {
    const factory = AIProviderFactories[providerType]

    if (!factory) {
      throw new Error(`不支持的 AI Provider 类型: ${providerType}`)
    }

    return factory({
      baseURL: config.baseURL || undefined,
      apiKey: config.apiKey || undefined,
    })
  }
}

我们只需要在调用生成文本之前,创建一个 provider 即可。

js 复制代码
import { AIProviderFactory, AIProviderType } from './src/ai.js'
import { generateText } from 'ai'

async function main() {
  const provider = AIProviderFactory.createProvider(AIProviderType.OLLAMA, {
    baseURL: 'http://localhost:11434/api',
  })

  const { text } = await generateText({
    model: provider('qwen2.5:7b'),
    prompt: '你好,请介绍一下你自己,不少于 100 字',
  })

  console.log(text)
}

main()

调用结果示例:

通过封装 provider factory,可以统一管理 AI Provider,简化了调用时的方法和复杂度。

结语

通过 Vercel 推出的 AI SDK,我们能够大幅简化对接不同 AI 厂商的工作。同时,AI SDK 提供了许多工具类,能够方便地用于 AI 的使用和调用。如果是 React 项目,我们还可以使用 AI SDK UI 进一步简化前端的开发工作量。

相关链接

相关推荐
失乐园4 分钟前
Java 新特性全解析:从 Lambda 到虚拟线程,一文掌握最新演进
java·后端·面试
巽星石8 分钟前
【Web】HTML5 Canvas 2D绘图的封装
前端·es6·html5·canvas·
Lx35211 分钟前
初识面向对象:类与对象的概念
java·后端
万事可爱^16 分钟前
深度迁移学习实战指南:从理论到产业级应用
人工智能·pytorch·深度学习·机器学习·迁移学习·tensorflow2
小杰~20 分钟前
轻量级模块化前端框架:快速构建强大的Web界面
前端·前端框架
仰望丨苍穹26 分钟前
JavaScript性能优化实战
前端·javascript·性能优化
大G哥31 分钟前
Spring Boot 与 Spring MVC 有何不同
java·spring boot·后端·spring·mvc
一个处女座的程序猿O(∩_∩)O31 分钟前
神经网络的探秘:从基础到实战
人工智能·深度学习·神经网络
JavinLu32 分钟前
idea超级AI插件,让 AI 为 Java 工程师
java·前端·intellij-idea
Aska_Lv35 分钟前
生产redis数据出问题了_shell脚本刷redis数据
后端·命令行