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推理链透明

生产部署清单

  1. 环境变量 — API Key 永远不要写在代码里,用 .env + dotenv
  2. 速率限制 — 给你的 API 端点加上请求限制,防止滥用
  3. 超时设置 — AI API 响应可能较慢,设置合理的超时时间(30-60s)
  4. 日志记录 — 记录每次 API 调用的模型、token 数、耗时,便于成本追踪
  5. 错误告警 — 连续失败时发送通知(Telegram / 邮件)
  6. 缓存 — 对相同问题的回答做缓存,减少 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 控制台可以随时查看用量和余额。

开始构建你的 Node.js AI 应用

注册即送免费额度 · 兼容 OpenAI SDK · 支持 300+ 模型

免费注册 →