使用 SDK 开发
通过 TypeScript 与 AI SDK、OpenAI SDK 或 Anthropic SDK,把 OptiWaves 接入自己的应用。
使用通用 SDK 即可接入 OptiWaves。下面使用 TypeScript 与 Node.js,从配置环境开始,分别演示生成文本、流式输出和读取用量;选择与你的项目一致的一条路径即可。
选择 SDK
| SDK | 适合的项目 | 本页使用的协议 |
|---|---|---|
| AI SDK | 使用 generateText、streamText 构建应用,或需要统一多个模型提供商 | Responses |
| OpenAI SDK | 已使用 openai 包,或希望直接处理 Responses 对象与事件 | Responses;兼容 Chat Completions |
| Anthropic SDK | 已使用 @anthropic-ai/sdk 和 Messages 接口 | Anthropic Messages |
1. 准备项目与配置
使用 Node.js 22 或以上版本,建议使用 Node.js 24 LTS。在新目录中初始化项目:
mkdir optiwaves-example
cd optiwaves-example
npm init -y
npm pkg set type=module "scripts.typecheck=tsc --noEmit"
npm install -D typescript tsx @types/node@22在项目根目录新建 tsconfig.json,启用严格类型检查:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"types": ["node"]
},
"include": ["*.ts"]
}本页通过 tsx 运行 TypeScript,使用 tsc --noEmit 检查类型。allowImportingTsExtensions 允许示例直接导入 ./config.ts。已有 TypeScript 项目可以沿用自己的配置、目录结构和运行方式。
在 API 密钥创建密钥。在项目根目录新建 .env,将占位值替换为自己的密钥:
OPTIWAVES_API_KEY=ow_your_api_key_here
OPTIWAVES_MODEL=auto将 .env 加入 .gitignore。这些示例在服务端运行;密钥不放入浏览器代码,也不要使用 NEXT_PUBLIC_ 或 VITE_ 前缀公开它。
新建共享配置文件,后面的示例均从这里读取连接信息:
const envApiKey = process.env.OPTIWAVES_API_KEY;
if (!envApiKey) {
throw new Error('请设置 OPTIWAVES_API_KEY,并使用 --env-file=.env 启动。');
}
export const apiKey: string = envApiKey;
export const modelId = process.env.OPTIWAVES_MODEL || 'auto';
export const baseURL = 'https://api.optiwaves.app/v1';安装与你选择的 SDK 对应的依赖即可,无需安装全部 SDK。保存对应章节的示例后,先检查类型,再按该章节的命令运行:
npm run typecheck检查成功时命令正常退出,没有类型错误输出。tsx 本身不执行类型检查。
2. 使用 AI SDK
安装 AI SDK 7 与 OpenAI provider 4:
npm install ai@7 @ai-sdk/openai@4
npm install -D @types/json-schema通过 createOpenAI 指定 OptiWaves 地址,并显式选择 .responses(modelId)。这是 AI SDK OpenAI provider 的自定义连接方式。
生成文本
import { generateText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
import { apiKey, baseURL, modelId } from './config.ts';
const optiwaves = createOpenAI({ apiKey, baseURL });
const result = await generateText({
model: optiwaves.responses(modelId),
prompt: '用三点说明流式输出适合哪些应用场景。',
maxOutputTokens: 1024,
maxRetries: 0,
providerOptions: { openai: { store: false } },
});
console.log(result.text);
console.log(result.usage);运行:
npx tsx --env-file=.env ai-sdk.tsresult.text 是正文,result.usage 是 token 用量。需要多轮对话时,由应用在每次请求中发送历史消息。
流式输出
新建另一个文件,将文本片段持续输出到终端:
import { streamText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
import { apiKey, baseURL, modelId } from './config.ts';
const optiwaves = createOpenAI({ apiKey, baseURL });
const result = streamText({
model: optiwaves.responses(modelId),
prompt: '用三点说明流式输出适合哪些应用场景。',
maxOutputTokens: 1024,
maxRetries: 0,
providerOptions: { openai: { store: false } },
onError() {
process.exitCode = 1;
console.error('生成失败,请检查密钥、额度与请求参数。');
},
});
for await (const text of result.textStream) {
process.stdout.write(text);
}
console.log('\n用量:', await result.usage);npx tsx --env-file=.env ai-sdk-stream.ts必须消费流才能取得完整结果;流中的失败通过 onError 处理。更多返回值见 AI SDK 文本与流式生成。
3. 使用 OpenAI SDK
安装 OpenAI SDK:
npm install openai@7生成文本
import OpenAI from 'openai';
import { apiKey, baseURL, modelId } from './config.ts';
const client = new OpenAI({ apiKey, baseURL, maxRetries: 0 });
const response = await client.responses.create({
model: modelId,
input: '用三点说明流式输出适合哪些应用场景。',
max_output_tokens: 1024,
store: false,
});
if (response.status !== 'completed') {
throw new Error(`生成未完成:${response.status}`);
}
console.log(response.output_text);
console.log(response.usage);npx tsx --env-file=.env openai-sdk.tsresponse.output_text 是 SDK 汇总的正文,response.usage 包含输入和输出 token。baseURL 必须指向 OptiWaves,apiKey 必须显式使用你的 OptiWaves 密钥。SDK 的基础用法见 OpenAI 开发入门。
流式输出
import OpenAI from 'openai';
import { apiKey, baseURL, modelId } from './config.ts';
const client = new OpenAI({ apiKey, baseURL, maxRetries: 0 });
const stream = client.responses.stream({
model: modelId,
input: '用三点说明流式输出适合哪些应用场景。',
max_output_tokens: 1024,
store: false,
});
for await (const event of stream) {
if (event.type === 'response.output_text.delta') {
process.stdout.write(event.delta);
}
}
const response = await stream.finalResponse();
if (response.status !== 'completed') {
throw new Error(`生成未完成:${response.status}`);
}
console.log('\n用量:', response.usage);npx tsx --env-file=.env openai-sdk-stream.ts读取最终响应后再确认成功,不能仅凭连接关闭判断生成完成。事件说明见 OpenAI 流式响应和 OptiWaves Responses 参考。
已有项目使用 Chat Completions
保留上面的 client 配置,把调用替换为:
const completion = await client.chat.completions.create({
model: modelId,
messages: [{ role: 'user', content: '用三点说明流式输出适合哪些应用场景。' }],
max_tokens: 1024,
});
console.log(completion.choices[0]?.message.content);
console.log(completion.usage);这里继续使用带 /v1 的 baseURL。字段与流式格式见 Chat Completions 参考。
4. 使用 Anthropic SDK
已有 Messages 项目可以保留 SDK,修改地址、密钥和模型:
npm install @anthropic-ai/sdkimport Anthropic from '@anthropic-ai/sdk';
import { apiKey, modelId } from './config.ts';
const client = new Anthropic({
apiKey,
authToken: null,
baseURL: 'https://api.optiwaves.app',
maxRetries: 0,
});
const message = await client.messages.create({
model: modelId,
messages: [{ role: 'user', content: '用三点说明流式输出适合哪些应用场景。' }],
max_tokens: 1024,
});
for (const block of message.content) {
if (block.type === 'text') console.log(block.text);
}
console.log(message.usage);npx tsx --env-file=.env anthropic-sdk.tsAnthropic SDK 的 baseURL 不带 /v1,SDK 会追加 /v1/messages。authToken: null 避免已有 Anthropic token 环境变量与 API Key 同时发送。SDK 支持的语言见 Anthropic 客户端 SDK,请求参数见 Messages 参考。
5. 接入自己的应用
下面做一个能在浏览器中提问的小应用:网页把问题发送到你自己的 /api/chat,Express 服务端通过 OpenAI SDK 调用 OptiWaves,再把回答显示到网页。
沿用第 1 步的 .env 和 config.ts,在同一个项目目录安装依赖:
npm install express@5 openai@7
npm install -D @types/express@5
mkdir public服务端
在项目根目录创建 server.ts:
import express, { type Request, type Response } from 'express';
import OpenAI from 'openai';
import { apiKey, baseURL, modelId } from './config.ts';
const app = express();
const client = new OpenAI({ apiKey, baseURL, maxRetries: 0, timeout: 60000 });
app.use(express.json({ limit: '16kb' }));
app.use(express.static('public'));
type ChatResponse = { answer: string } | { error: string };
type ChatRequest = Request<Record<string, never>, ChatResponse, unknown>;
app.post('/api/chat', async (req: ChatRequest, res: Response<ChatResponse>) => {
const body = req.body;
const question = typeof body === 'object' && body !== null
&& 'question' in body && typeof body.question === 'string'
? body.question.trim()
: '';
if (!question || question.length > 2000) {
return res.status(400).json({ error: '请输入 1 到 2000 字的问题' });
}
try {
const response = await client.responses.create({
model: modelId,
input: question,
max_output_tokens: 2048,
store: false,
});
if (response.status !== 'completed' || !response.output_text) {
return res.status(502).json({ error: '回答未完成 请重试' });
}
res.json({ answer: response.output_text });
} catch {
res.status(502).json({ error: '生成失败 请检查 API Key 和可用额度后重试' });
}
});
app.listen(3001, '127.0.0.1', () => {
console.log('打开 http://127.0.0.1:3001');
});网页
创建 public/index.html:
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OptiWaves 问答示例</title>
<h1>向 OptiWaves 提问</h1>
<form id="chat">
<label for="question">问题</label>
<textarea id="question" required maxlength="2000" rows="4"></textarea>
<button type="submit">发送</button>
</form>
<p id="answer" role="status" style="white-space: pre-wrap"></p>
<script type="module">
const form = document.querySelector('#chat');
const question = document.querySelector('#question');
const button = form.querySelector('button');
const answer = document.querySelector('#answer');
form.addEventListener('submit', async (event) => {
event.preventDefault();
button.disabled = true;
answer.textContent = '正在生成';
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question: question.value }),
});
const data = await response.json();
if (!response.ok) throw new Error(data.error || '请求失败');
answer.textContent = data.answer;
} catch (error) {
answer.textContent = error.message || '请求失败 请重试';
} finally {
button.disabled = false;
}
});
</script>
</html>启动并提问
在项目根目录检查类型并启动:
npm run typecheck
npx tsx --env-file=.env server.ts打开 http://127.0.0.1:3001,输入“用一句话解释什么是 API”,点击 发送。页面先显示“正在生成”,收到响应后显示模型回答。
API Key 只由服务端读取,浏览器调用的是你自己的 /api/chat。这个示例每次处理一个问题;需要连续对话时,再将历史消息加入 input。部署给其他用户前,在这个接口接入你应用的登录校验和用量限制。