跳到主要内容

在 Vercel AI SDK 中使用 OceanToken

OceanToken 的 API 兼容 OpenAI,所以 AI SDK 的 OpenAI Compatible 提供方 @ai-sdk/openai-compatible 只需要基础地址(Base URL)和你的 API Key 就能用,不需要安装任何 OceanToken 专用的包。Claude 模型也可以通过 AI SDK 的 Anthropic 提供方 @ai-sdk/anthropic 调用(见下文)。

本页的每个示例都是一个文件,发布前我们都会用它实际调用一遍服务。测试日期为 2026-10-19,使用的版本是 ai 7.0.142、@ai-sdk/openai-compatible 3.0.70、@ai-sdk/anthropic 4.0.81 和 zod 4.6.7。

安装​

npm install ai @ai-sdk/openai-compatible zod
export OCEANTOKEN_API_KEY=sk-...

在控制台创建一个 API Key;如果想限制这个应用最多能花多少,给它设置 消费上限。只在服务器端使用这个 API Key:放在路由处理程序、服务器操作或后台任务里,绝不要放进在浏览器中运行的代码。

创建提供方​

提供方只需创建一次,然后在每个调用模型的地方导入它:

oceantoken.ts
// npm install ai @ai-sdk/openai-compatible
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";

export const oceantoken = createOpenAICompatible({
name: "oceantoken",
baseURL: process.env.OCEANTOKEN_BASE_URL ?? "https://api.oceantoken.ai/v1",
apiKey: process.env.OCEANTOKEN_API_KEY,
// Token counts in streamed responses, as in non-streamed ones.
includeUsage: true,
// Send your schema with structured-output requests (Output.object).
supportsStructuredOutputs: true,
});
  • baseURL 是 https://api.oceantoken.ai/v1。示例会先读取 OCEANTOKEN_BASE_URL,这只是为了让我们能在测试环境中运行它们;你可以把这一步去掉。
  • apiKey 以 Authorization: Bearer <key> 的形式发送。
  • includeUsage: true 会在流式响应中加上 token 数。
  • supportsStructuredOutputs: true 会在结构化输出请求中发送你的 schema。不设置的话,SDK 只要求返回 JSON,不带 schema。

模型 ID 要和模型页上写的完全一致,前面带上发布方:openai/gpt-5.5、anthropic/claude-sonnet-5.5、deepseek/deepseek-v4.1-flash、google/gemini-3.5-flash。带上你的 API Key 请求 GET https://api.oceantoken.ai/v1/models,会列出这个 API Key 能用的所有模型;带价格的完整目录也以 JSON 形式发布在 https://api.oceantoken.ai/public/model_hub。

生成文本​

generate-text.ts
import { generateText } from "ai";
import { oceantoken } from "./oceantoken";

const { text, usage } = await generateText({
model: oceantoken("openai/gpt-5.5"),
prompt: "Explain what an API gateway does in one sentence.",
});

console.log(text);
console.log(usage.inputTokens, "input tokens,", usage.outputTokens, "output tokens");

usage 里是这次请求计费的 token 数。在控制台的日志里也能看到这个请求及其费用。

流式输出文本​

stream-text.ts
import { streamText } from "ai";
import { oceantoken } from "./oceantoken";

const result = streamText({
model: oceantoken("deepseek/deepseek-v4.1-flash"),
prompt: "Write a four-line poem about a lighthouse.",
});

for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}

const usage = await result.usage; // needs includeUsage: true
console.log("\n", usage.inputTokens, "input tokens,", usage.outputTokens, "output tokens");

只要有人在等结果,就用流式输出:token 一生成就会送达,长回答也不会碰到限制中说明的请求超时。

调用工具​

tools.ts
// npm install zod
import { generateText, stepCountIs, tool } from "ai";
import { z } from "zod";
import { oceantoken } from "./oceantoken";

const { text, steps } = await generateText({
model: oceantoken("google/gemini-3.5-flash"),
tools: {
weather: tool({
description: "Get the current weather in a city",
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city, temperatureC: 18, sky: "clear" }),
}),
},
// Let the model call the tool, read the result, then answer.
stopWhen: stepCountIs(5),
prompt: "What is the weather in Lisbon right now?",
});

console.log(text);
console.log(steps.flatMap((step) => step.toolCalls.map((call) => call.toolName)));

模型请求调用 weather,SDK 运行 execute 并把结果发回去,模型再根据结果作答。stopWhen: stepCountIs(5) 最多允许这样的五步;不设置它,生成会在第一次工具调用后停止。streamText 同样支持工具调用。请使用在模型页上标明支持工具调用的模型;上面提到的四个模型都用 generateText 和 streamText 测试过。

结构化输出​

structured-output.ts
import { generateText, Output } from "ai";
import { z } from "zod";
import { oceantoken } from "./oceantoken";

const { output } = await generateText({
model: oceantoken("openai/gpt-5.5"),
output: Output.object({
schema: z.object({
name: z.string(),
ingredients: z.array(z.object({ item: z.string(), amount: z.string() })),
minutes: z.number(),
}),
}),
prompt: "A simple recipe for pancakes.",
});

console.log(output.name, output.minutes, output.ingredients.length);

SDK 会按你的 schema 校验回答,output 的类型也由它推导出来。这需要在提供方上设置 supportsStructuredOutputs: true。在 AI SDK 7 中,generateObject 已被弃用,改为使用带 output 的 generateText;不过 generateObject 在同一个提供方上仍然可用。

向量​

embeddings.ts
import { cosineSimilarity, embedMany } from "ai";
import { oceantoken } from "./oceantoken";

const { embeddings, usage } = await embedMany({
model: oceantoken.embeddingModel("openai/text-embedding-3-small"),
values: [
"The lighthouse keeper rowed out before dawn.",
"At first light the keeper took the boat out.",
"Quarterly revenue rose by four percent.",
],
});

console.log(embeddings[0].length, usage);
console.log(cosineSimilarity(embeddings[0], embeddings[1])); // close in meaning
console.log(cosineSimilarity(embeddings[0], embeddings[2])); // unrelated

用 oceantoken.embeddingModel() 调用模型页上的任意向量模型,例如 openai/text-embedding-3-small 或 baai/bge-m3。embed 接受一个值,embedMany 接受多个值。

生成图像​

image.ts
import { randomUUID } from "node:crypto";
import { writeFile } from "node:fs/promises";
import { generateImage } from "ai";
import { oceantoken } from "./oceantoken";

const { image } = await generateImage({
model: oceantoken.imageModel("openai/gpt-image-2"),
prompt: "A small lighthouse on a calm sea at dawn, watercolor",
size: "1024x1024",
// A retry with the same key, including the SDK's own retries, gets the
// first result back instead of running (and charging) a second time.
headers: { "Idempotency-Key": randomUUID() },
});

await writeFile("lighthouse.png", image.uint8Array);
console.log(image.mediaType, image.uint8Array.length, "bytes");

用 oceantoken.imageModel() 调用模型页上的任意图像模型。SDK 会下载结果,所以 image 里就是文件本身。图像请求在运行时就会扣费,而 SDK 默认会对失败的请求重试两次;带上 Idempotency-Key 请求头,重试就会直接返回第一次的结果,不会再运行一次(错误)。

通过 @ai-sdk/anthropic 使用 Claude​

Claude 模型和其他模型一样,可以通过上面兼容 OpenAI 的提供方使用。如果想改用 AI SDK 的 Anthropic 提供方,给它同样的基础地址:

npm install ai @ai-sdk/anthropic
claude.ts
// npm install ai @ai-sdk/anthropic
// Claude models also answer on the Anthropic Messages API. Unlike the
// Anthropic SDKs, this package's baseURL includes /v1.
import { createAnthropic } from "@ai-sdk/anthropic";
import { generateText } from "ai";

const anthropic = createAnthropic({
baseURL: process.env.OCEANTOKEN_BASE_URL ?? "https://api.oceantoken.ai/v1",
apiKey: process.env.OCEANTOKEN_API_KEY,
});

const { text, usage } = await generateText({
model: anthropic("anthropic/claude-sonnet-5.5"),
prompt: "Explain what an API gateway does in one sentence.",
});

console.log(text);
console.log(usage.inputTokens, "input tokens,", usage.outputTokens, "output tokens");

@ai-sdk/anthropic 要填 https://api.oceantoken.ai/v1,带 /v1。Python 和 TypeScript 的 Anthropic SDK 要填 https://api.oceantoken.ai,它们会自己加上 /v1(快速开始)。

文本、流式输出和工具调用的用法与上文相同。结构化输出需要设置提供方的 JSON 工具模式:

const { output } = await generateText({
model: anthropic("anthropic/claude-sonnet-5.5"),
output: Output.object({ schema }),
providerOptions: { anthropic: { structuredOutputMode: "jsonTool" } },
prompt: "...",
});

不设置的话,@ai-sdk/anthropic 会把 schema 放在 output_config.format 里发送,而 OceanToken 目前还不会应用它:模型会用普通文字作答,SDK 则报告没有生成对象。兼容 OpenAI 的提供方调用 Claude 时不需要这项设置。

故障排查​

你看到的怎么处理
Invalid API key. Check the key, or create one in the OceanToken console.API Key 写错了、已被撤销,或带了多余的空格。检查 OCEANTOKEN_API_KEY,或创建一个新的 API Key。
Unknown model '…'. GET /v1/models lists the models your key can use.模型 ID 要和模型页上写的完全一致,前面带上发布方(是 deepseek/deepseek-v4.1-flash,不是 deepseek-v4.1-flash)。
Insufficient balance - please add credit to continue.充值。
使用 Output.object 时出现 No object generated在 createOpenAICompatible 上设置 supportsStructuredOutputs: true。使用 @ai-sdk/anthropic 时,设置 structuredOutputMode: "jsonTool"(见上文)。
streamText 之后 usage 为空在提供方上设置 includeUsage: true。

SDK 会抛出 APICallError,它的 statusCode 和 responseBody 里是 OceanToken 返回的错误;错误页列出了每个错误码及其处理方法。

参考资料​