AI SDK 集成 Baseten Provider:语言模型与嵌入模型的完整接入指南

原创2026-09-11 21:04:001,940 阅读
文章标签:人工智能大模型AI 应用AI Agent工具调用LLM 网关MCP Clients

AI SDK 集成 Baseten Provider:语言模型与嵌入模型的完整接入指南

导读

本文介绍 AI SDK(The AI Toolkit for TypeScript)官方提供的 Baseten Provider——@ai-sdk/baseten,它让开发者能够通过统一的 AI SDK 接口调用 Baseten 推理平台上的前沿开源模型(如 DeepSeek、Kimi、Qwen、GLM 等),同时支持文本生成与嵌入向量两种能力。读完本文,你将掌握该 Provider 的安装、默认实例与自定义实例的创建、generateText/streamText 文本生成、专用部署的 modelURL 接入、嵌入模型调用,以及可选原生性能客户端的进阶用法,并能从源码层面理解其基于 OpenAI 兼容协议实现的底层原理。

概览:Baseten Provider 是什么

Baseten 是一个推理平台,用于通过 API 对外提供前沿级、企业级开源 AI 模型的托管服务。@ai-sdk/baseten 是 AI SDK 的官方 Provider 包,为 Baseten 平台提供语言模型(language model)与嵌入模型(embedding model)支持,即同时覆盖文本生成与向量化两类场景。

从源码结构看,该 Provider 没有从零实现协议,而是构建在 @ai-sdk/openai-compatible 之上:在 baseten-provider.ts 中,聊天模型实例化自 OpenAICompatibleChatLanguageModel,嵌入模型实例化自 OpenAICompatibleEmbeddingModel,其依赖关系也在 package.json 中体现(依赖 @ai-sdk/openai-compatible、@ai-sdk/provider、@ai-sdk/provider-utils)。这意味着所有 Baseten 请求都走 OpenAI 兼容协议,Provider 层主要负责任何 URL 拼接、鉴权头、错误结构与批处理策略。

安装

Baseten Provider 位于 @ai-sdk/baseten 模块,通过 npm 安装:

npm i @ai-sdk/baseten

该包以 ESM 方式发布("type": "module",入口为 dist/index.js),要求 Node.js >= 22,并声明 zod 为 peerDependency(^3.25.76 || ^4.1.8)。安装后建议在环境中配置 Baseten API Key:

export BASETEN_API_KEY=your_api_key_here

Provider 实例

默认实例

可以直接从 @ai-sdk/baseten 导入默认的 provider 实例 baseten:

import { baseten } from '@ai-sdk/baseten';

该默认实例由源码底部的 export const baseten = createBaseten(); 创建(见 baseten-provider.ts),使用全部默认配置。

自定义实例

如果默认配置不满足需求(例如要接入专用模型部署),可以通过 createBaseten 创建带自定义设置的实例:

import { createBaseten } from '@ai-sdk/baseten';

const baseten = createBaseten({
  apiKey: process.env.BASETEN_API_KEY ?? '',
});

可选配置项

createBaseten 接受 BasetenProviderSettings 对象,源码接口定义于 baseten-provider.ts,各配置项如下:

配置项 类型 说明
apiKey string Baseten API Key,通过 Authorization: Bearer 头发送。默认读取 BASETEN_API_KEY 环境变量
baseURL string API 调用地址前缀,可用于代理服务器等场景。默认值为 https://inference.baseten.co/v1
modelURL string 专用模型(聊天或嵌入)的 URL。未提供时走默认 Model APIs
headers Record<string, string> 附加的自定义请求头,会与鉴权头合并发送
fetch (input, init) => Promise<Response> 自定义 fetch 实现,可拦截请求或用于测试
performanceClient PerformanceClient 构造函数 可选接入 Baseten 原生性能客户端(仅嵌入模型),见下文

从源码看,baseURL 会经过 withoutTrailingSlash 处理去除末尾斜杠;请求头由 withUserAgentSuffix 附加 ai-sdk/baseten/${VERSION} 的 User-Agent 标识,版本号由构建期注入(见 version.ts)。这些行为均有对应单元测试验证(见 baseten-provider.unit.test.ts 的 "Headers" 与 "URL construction" 分组)。

使用语言模型(Model APIs)

Baseten 提供托管的 Model APIs,可以直接用模型 ID 选中模型。Provider 本身可被直接调用(baseten(modelId)),也暴露了 chatModel(modelId) 与 languageModel(modelId) 两个等价的工厂方法。

源码中定义的内置聊天模型 ID 列表见 baseten-chat-options.ts,当前支持(Model APIs 之外的自有模型也可通过 string & {} 放宽类型传入):

  • deepseek-ai/DeepSeek-R1-0528
  • deepseek-ai/DeepSeek-V3-0324
  • deepseek-ai/DeepSeek-V3.1
  • moonshotai/Kimi-K2-Instruct-0905
  • moonshotai/Kimi-K2-Thinking
  • Qwen/Qwen3-235B-A22B-Instruct-2507
  • Qwen/Qwen3-Coder-480B-A35B-Instruct
  • openai/gpt-oss-120b
  • zai-org/GLM-4.6
  • zai-org/GLM-4.7

文本生成示例

使用 generateText 生成文本:

import { baseten } from '@ai-sdk/baseten';
import { generateText } from 'ai';

const { text } = await generateText({
  model: baseten('deepseek-ai/DeepSeek-V3-0324'),
  prompt: 'What is the meaning of life? Answer in one sentence.',
});

Baseten 语言模型同样可用于 streamText 流式生成(相关核心概念可参考仓库中的 AI SDK Core 文档)。

源码层面的两个关键开关

在 baseten-provider.ts 中,聊天模型统一配置了 includeUsage: true 与 supportsStructuredOutputs: true:

  • includeUsage:OpenAI 兼容服务默认不会在流式响应中附带 usage(token 用量),除非请求携带 stream_options.include_usage。该开关保证流式输出也能统计用量。
  • supportsStructuredOutputs:缺少该开关时,OpenAI 兼容层会把 response_format: json_schema 改写为 json_object,静默丢弃 schema、name 与 strict 标志。开启后结构化输出(JSON Schema)可原样透传。

这两个开关对默认 Model APIs 路径和专用 /sync/v1 部署路径均生效,由测试分别验证(见 baseten-provider.unit.test.ts 的 includeUsage 与 supportsStructuredOutputs 分组)。

接入专用模型部署(Dedicated Models)

除了托管的 Model APIs,Baseten 还支持通过专用模型 URL 接入自定义部署的聊天模型与嵌入模型。此时需要在创建 provider 时指定 modelURL。

OpenAI 兼容端点(/sync/v1)

对使用 Baseten OpenAI 兼容端点部署的模型:

import { createBaseten } from '@ai-sdk/baseten';
import { generateText } from 'ai';

const baseten = createBaseten({
  modelURL: 'https://model-{MODEL_ID}.api.baseten.co/sync/v1',
});

// 指定 modelURL 后无需再传 modelId
const model = baseten();
const { text } = await generateText({
  model: model,
  prompt: 'Say hello from a Baseten chat model!',
});

从源码看,当 modelURL 包含 /sync/v1 时,provider 会以占位 modelId 'placeholder' 构造模型,实际请求 URL 由 modelURL + path 拼接而成,例如 .../sync/v1/chat/completions(测试见 baseten-provider.unit.test.ts)。

/predict 端点(不支持聊天)

/predict 端点目前不支持聊天模型,聊天功能必须使用 /sync/v1 端点。若传入包含 /predict 的 modelURL 并调用聊天模型,源码会抛出:

Not supported. You must use a /sync/v1 endpoint for chat models.

使用嵌入模型(Embedding Models)

通过 .embeddingModel() 工厂方法可创建调用 Baseten 嵌入 API 的模型。Baseten Embeddings Inference(BEI)部署天然兼容 OpenAI 协议,因此嵌入模型默认走普通 HTTP,无需额外依赖。

重要:嵌入模型必须使用专用部署并配置 modelURL。与聊天模型不同,嵌入模型无法使用 Baseten 默认的 Model APIs。

import { createBaseten } from '@ai-sdk/baseten';
import { embed, embedMany } from 'ai';

const baseten = createBaseten({
  modelURL: 'https://model-{MODEL_ID}.api.baseten.co/sync',
});

const embeddingModel = baseten.embeddingModel();

// 单个嵌入
const { embedding } = await embed({
  model: embeddingModel,
  value: 'sunny day at the beach',
});

// 批量嵌入
const { embeddings } = await embedMany({
  model: embeddingModel,
  values: [
    'sunny day at the beach',
    'rainy afternoon in the city',
    'snowy mountain peak',
  ],
});

端点的 URL 拼接规则

源码中嵌入模型的 URL 构造包含一处细节处理(baseten-provider.ts 的 getCommonModelConfig):

  • 传入 /sync 端点(不含 /v1):自动追加 /v1,最终请求形如 .../sync/v1/embeddings;
  • 传入 /sync/v1 端点:直接拼接,不会重复 /v1;
  • 传入 /predict 端点:不支持,抛出 Not supported. You must use a /sync or /sync/v1 endpoint for embeddings.

批量上限与自动分片

每次请求最多发送 128 个值(源码常量 MAX_EMBEDDINGS_PER_CALL = 128,对应 Baseten 服务端 413 batch size N > maximum allowed batch size 128 的限制)。embedMany 会将更大的输入按此大小自动分片并并行发送,因此你可以放心传入任意数量的值。对应的测试在 baseten-embedding-model.test.ts 中验证了 128 个值可正常通过、129 个值直接调用 doEmbed 会抛出 TooManyEmbeddingValuesForCallError。

实际请求体遵循 OpenAI 嵌入接口形状(input、model、encoding_format: 'float'),token 用量从响应中的 prompt_tokens 提取(见 baseten-embedding-model.test.ts)。

可选:原生性能客户端(Native Performance Client)

Baseten 额外发布了 @basetenlabs/performance-client 原生客户端,它能在你部署已有的服务端动态批处理之上,再叠加客户端批处理(client-side batching)与请求对冲(request hedging)。

需要特别注意的是:该客户端默认不安装。因为它是原生插件(native addon),在边缘运行时(edge runtime)中无法加载,打包工具也无法解析其平台二进制文件。

如需使用,需自行安装并把构造函数传入 provider:

npm i @basetenlabs/performance-client
import { createBaseten } from '@ai-sdk/baseten';
import { PerformanceClient } from '@basetenlabs/performance-client';

const baseten = createBaseten({
  modelURL:
    'https://model-{MODEL_ID}.api.baseten.co/environments/production/sync',
  performanceClient: PerformanceClient,
});

接入后,批处理交由客户端自行处理:maxEmbeddingsPerCall 被设为 Infinity,embedMany 将全部值作为一次调用交给性能客户端,而不再按 128 分片。源码通过结构类型(structural typing)声明了该客户端的最小接口(embed(input, model) 方法),使其不进入包的依赖与类型图;传给客户端的 baseUrl 会去掉 /v1 后缀(因为客户端会自行追加 /v1)。相关行为均有单元测试覆盖(见 baseten-provider.unit.test.ts 的 opt-in performance client path 分组)。

错误处理

Provider 内置了对常见 API 错误的处理逻辑。先看基本用法:

import { baseten } from '@ai-sdk/baseten';
import { generateText } from 'ai';

try {
  const { text } = await generateText({
    model: baseten('moonshotai/Kimi-K2-Instruct-0905'),
    prompt: 'Hello, world!',
  });
} catch (error) {
  console.error('Baseten API error:', error.message);
}

双形态错误信封的解析

源码中值得注意的实现细节是:Baseten 会返回两种不同的错误信封——Model APIs 返回纯字符串(如 {"error":"please check the model you provided"}),而专用部署透传其服务端的 OpenAI 形态对象。因此 baseten-provider.ts 中的 basetenErrorSchema 使用 z.union 同时接受两种形态,errorToMessage 则按类型提取可读消息。若两种形态都无法解析,错误消息会退化为 HTTP 原因短语(HTTP/1.1 下为 "Not Found",HTTP/2 下可能为空)。该行为在单元测试的 errorStructure 分组与嵌入模型的 HTTP 测试中均有覆盖(见 baseten-provider.unit.test.ts、baseten-embedding-model.test.ts)。

常见错误场景

// 1. 嵌入模型必须配置 modelURL
try {
  baseten.embeddingModel();
} catch (error) {
  // Error: "No model URL provided for embeddings. Please set modelURL option for embeddings."
}

// 2. 聊天模型不支持 /predict 端点
try {
  const baseten = createBaseten({
    modelURL:
      'https://model-{MODEL_ID}.api.baseten.co/environments/production/predict',
  });
  baseten(); // 会抛出错误
} catch (error) {
  // Error: "Not supported. You must use a /sync/v1 endpoint for chat models."
}

// 3. /sync/v1 端点对嵌入模型可用
const baseten = createBaseten({
  modelURL:
    'https://model-{MODEL_ID}.api.baseten.co/environments/production/sync/v1',
});
const embeddingModel = baseten.embeddingModel(); // 正常工作

// 4. 嵌入模型不支持 /predict 端点
try {
  const baseten = createBaseten({
    modelURL:
      'https://model-{MODEL_ID}.api.baseten.co/environments/production/predict',
  });
  baseten.embeddingModel(); // 会抛出错误
} catch (error) {
  // Error: "Not supported. You must use a /sync or /sync/v1 endpoint for embeddings."
}

// 5. 图像模型不受支持
try {
  baseten.imageModel('test-model');
} catch (error) {
  // Error: NoSuchModelError for imageModel
}

从源码看,图像模型通过 provider.imageModel 直接抛出 NoSuchModelError(见 baseten-provider.ts 与 baseten-provider.unit.test.ts 的 imageModel 分组),Provider 明确只覆盖文本与嵌入两类能力。

与 OpenAI 兼容层的关系(原理小结)

Baseten Provider 是 AI SDK 生态中"协议复用"思路的典型代表:它没有自建传输层,而是把 Baseten 的 Model APIs 与专用部署统一建模为 OpenAI 兼容端点,从而直接复用 @ai-sdk/openai-compatible 的聊天/嵌入实现。Provider 自身的核心工作集中在四件事上:

  1. 端点归一化:默认 baseURL 与专用 modelURL 的拼接、/sync → /sync/v1 的自动补全;
  2. 鉴权与标识:BASETEN_API_KEY 加载、Bearer 头与 ai-sdk/baseten/<version> User-Agent;
  3. 能力开关:includeUsage、supportsStructuredOutputs 等针对 Baseten 服务特性的适配;
  4. 错误语义化:兼容字符串/对象两种错误信封并提取可读消息。

需要进一步研究实现时,可阅读 baseten-provider.ts(Provider 主实现)、baseten-provider.unit.test.ts(配置与 URL 构造测试)、baseten-embedding-model.test.ts(真实 HTTP 嵌入链路测试),以及包的出口 index.ts(对外导出的类型与工厂函数)。

登录后查看全文
ai