Node.js 是构建 AI 应用的热门选择 — 无论是 Express 后端、Next.js 全栈应用,还是 Electron 桌面工具。本文教你用 Node.js / TypeScript 调用 AI API,从最基础的请求到生产级别的最佳实践。
环境准备
# 初始化项目
mkdir my-ai-app && cd my-ai-app
npm init -y
# 安装 OpenAI SDK
npm install openai
# (可选)TypeScript 支持
npm install -D typescript @types/node tsx
基础调用
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.API_KEY, // 推荐用环境变量
baseURL: 'https://api2everything.xyz/v1'
});
async function chat(prompt: string) {
const response = await client.chat.completions.create({
model: 'claude-sonnet-4-6-20250514',
messages: [
{ role: 'system', content: '你是一个 Node.js 技术专家' },
{ role: 'user', content: prompt }
],
max_tokens: 2048
});
return response.choices[0].message.content;
}
// 使用
const answer = await chat('解释一下 Node.js 的事件循环机制');
console.log(answer);
流式输出(Streaming)
流式输出让用户实时看到 AI 的回答,体验更好:
async function streamChat(prompt: string) {
const stream = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
stream: true
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
process.stdout.write(content); // 逐字输出
}
}
console.log(); // 换行
}
await streamChat('用 Express 写一个 REST API 的最佳实践');
Express 后端集成
import express from 'express';
import OpenAI from 'openai';
const app = express();
app.use(express.json());
const client = new OpenAI({
apiKey: process.env.API_KEY,
baseURL: 'https://api2everything.xyz/v1'
});
// 普通请求
app.post('/api/chat', async (req, res) => {
try {
const { message, model = 'claude-sonnet-4-6-20250514' } = req.body;
const response = await client.chat.completions.create({
model,
messages: [{ role: 'user', content: message }]
});
res.json({ reply: response.choices[0].message.content });
} catch (error) {
console.error('AI API error:', error.message);
res.status(500).json({ error: '服务暂时不可用' });
}
});
// 流式输出(SSE)
app.post('/api/chat/stream', async (req, res) => {
const { message } = req.body;
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const stream = await client.chat.completions.create({
model: 'claude-sonnet-4-6-20250514',
messages: [{ role: 'user', content: message }],
stream: true
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
res.write(`data: ${JSON.stringify({ content })}\n\n`);
}
}
res.write('data: [DONE]\n\n');
res.end();
});
app.listen(3000, () => console.log('Server running on :3000'));
Next.js App Router 集成
// app/api/chat/route.ts
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.API_KEY,
baseURL: 'https://api2everything.xyz/v1'
});
export async function POST(req: Request) {
const { messages } = await req.json();
const stream = await client.chat.completions.create({
model: 'claude-sonnet-4-6-20250514',
messages,
stream: true
});
// 将 OpenAI stream 转为 Web ReadableStream
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || '';
controller.enqueue(encoder.encode(text));
}
controller.close();
}
});
return new Response(readable, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}
错误处理与重试
async function robustChat(prompt: string, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await client.chat.completions.create({
model: 'claude-sonnet-4-6-20250514',
messages: [{ role: 'user', content: prompt }],
timeout: 30000 // 30秒超时
});
return response.choices[0].message.content;
} catch (error) {
if (error instanceof OpenAI.APIError) {
if (error.status === 429) {
// 速率限制,等待后重试
const wait = Math.pow(2, i) * 1000;
console.log(`Rate limited, waiting ${wait}ms...`);
await new Promise(r => setTimeout(r, wait));
continue;
}
if (error.status >= 500) {
// 服务器错误,重试
continue;
}
}
throw error; // 其他错误直接抛出
}
}
throw new Error('Max retries exceeded');
}
模型选择指南
| 场景 | 推荐模型 | 理由 |
|---|---|---|
| 聊天机器人 | Claude Sonnet 4.6 | 对话自然,响应快 |
| 代码生成 | Claude Sonnet 4.6 | 代码能力最强 |
| 文本摘要 | GPT-4o mini | 速度快,成本低 |
| 数据分析 | GPT-4o | 结构化输出稳定 |
| 深度推理 | DeepSeek R1 / o3 | 推理链透明 |
生产部署清单
- 环境变量 — API Key 永远不要写在代码里,用
.env+dotenv - 速率限制 — 给你的 API 端点加上请求限制,防止滥用
- 超时设置 — AI API 响应可能较慢,设置合理的超时时间(30-60s)
- 日志记录 — 记录每次 API 调用的模型、token 数、耗时,便于成本追踪
- 错误告警 — 连续失败时发送通知(Telegram / 邮件)
- 缓存 — 对相同问题的回答做缓存,减少 API 调用次数
常见问题
ESM 还是 CommonJS?
OpenAI SDK v4+ 同时支持 ESM 和 CJS。推荐使用 ESM(import 语法),在 package.json 中设置 "type": "module"。
前端可以直接调用 AI API 吗?
不推荐。API Key 会暴露在浏览器中。应该在后端(Express / Next.js API Route)调用 AI API,前端通过你自己的后端接口间接调用。
如何控制 token 用量?
使用 max_tokens 限制输出长度,用 tiktoken 库在发送前估算输入 token 数。通过無量Api 控制台可以随时查看用量和余额。