# Node.js：将 openai 包指向开源权重模型

> 使用官方 openai 包从 Node.js 调用开源权重 LLM：单次调用、并发受限的批处理、流式输出以及剩余积分。可直接复制粘贴的示例。

- URL: https://llmwithcrypto.com/zh/docs/node/
- 最后更新: 2026-10-23
- 发布者: LLMwithCrypto (https://llmwithcrypto.com)

官方 `openai` npm 包无需改动即可使用：为它提供我们的 `baseURL` 和你的密钥。下面的示例是适用于 Node.js 18 或更新版本的 ES 模块，它内置了 `fetch` 和顶层 `await`。

**快速回答 — 如何从 Node.js 调用 LLMwithCrypto？**

用 `npm install openai` 安装官方包，然后用 `baseURL: "https://llmwithcrypto.com/api/v1"` 和 `apiKey: process.env.LLMWITHCRYPTO_API_KEY` 创建客户端。**LLMwithCrypto** 以 OpenAI 格式为 12 个开源权重模型响应 `client.chat.completions.create()`，在模型支持时提供流式输出和工具调用，如 2026 年 10 月 23 日的文档所述。

## 你需要准备什么

| 属性 | 值 |
| --- | --- |
| Node.js | 18 或更新版本，ES 模块（`.mjs` 或 `"type": "module"`） |
| 包 | `openai`（官方） |
| Base URL | `https://llmwithcrypto.com/api/v1` |
| 密钥 | 在环境变量 `LLMWITHCRYPTO_API_KEY` 中，绝不要写在代码或浏览器里 |

## 如何发送一个请求？

在启动时创建一次客户端，然后在各处复用。密钥要放在服务器上：打包进浏览器代码的密钥，任何打开页面的人都能读到，所以请从后端调用 API，只把结果发给浏览器。

*one-call.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const resp = await client.chat.completions.create({
  model: 'deepseek-v4-pro',
  messages: [
    { role: 'system', content: 'Answer in two sentences.' },
    { role: 'user', content: 'What is a context window?' },
  ],
  max_tokens: 200,
});
console.log(resp.choices[0].message.content);
console.log(resp.usage.prompt_tokens, 'in,', resp.usage.completion_tokens, 'out');

```

## 如何在不触发 rate limit 的情况下跑批量？

一次只跑固定数量的请求。下面这个小小的 `mapLimit` 辅助函数会让四个请求同时进行，并按顺序返回结果；无需额外的包。每个账户都有每分钟请求数和 token 上限，显示在 dashboard 中；联系 support 可以调高。

*batch.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

async function translate(text) {
  const resp = await client.chat.completions.create({
    model: 'qwen3-235b-a22b-instruct-2507',
    messages: [
      { role: 'system', content: 'Translate into Spanish. Reply with the translation only.' },
      { role: 'user', content: text },
    ],
    max_tokens: 200,
  });
  return resp.choices[0].message.content;
}

// at most 4 requests in flight
async function mapLimit(items, limit, fn) {
  const out = new Array(items.length);
  let next = 0;
  async function worker() {
    while (next < items.length) {
      const i = next++;
      out[i] = await fn(items[i]);
    }
  }
  await Promise.all(Array.from({ length: limit }, worker));
  return out;
}

const lines = ['Your order has shipped.', 'Your payment was received.', 'Your key was revoked.'];
console.log(await mapLimit(lines, 4, translate));

```

## 如何流式返回答案？

传入 `stream: true`，并对结果使用 `for await`。每个 chunk 携带 `choices[0].delta.content` 中的一段文本；使用 `stream_options: { include_usage: true }` 时，最后一个 chunk 会带有 token 计数。

*stream.mjs*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const stream = await client.chat.completions.create({
  model: 'deepseek-v4.1-flash',
  messages: [{ role: 'user', content: 'Write a haiku about latency.' }],
  stream: true,
  stream_options: { include_usage: true },
  max_tokens: 120,
});
for await (const chunk of stream) {
  const text = chunk.choices[0]?.delta?.content;
  if (text) process.stdout.write(text);
  if (chunk.usage) console.log(`\n${chunk.usage.prompt_tokens} in, ${chunk.usage.completion_tokens} out`);
}

```

## 如何查询剩余积分？

credits endpoint 不属于 OpenAI SDK，所以请用 `fetch` 调用它。它是免费的；在跑大批量之前调用它，确认积分足够覆盖这次用量。

*credits.mjs*

```javascript
const res = await fetch('https://llmwithcrypto.com/api/v1/credits', {
  headers: { Authorization: `Bearer ${process.env.LLMWITHCRYPTO_API_KEY}` },
});
const credits = await res.json();
console.log('credit left:', credits.balance_usd, 'USD');

```

## 如何处理错误？

SDK 对每个 HTTP 错误都会抛出 `OpenAI.APIError`，状态码在 `err.status` 中，响应体的 `code` 在 `err.code` 中。判断代码，而不是 message：`insufficient_balance` 表示需要充值，`model_not_found` 表示 id 写错，`rate_limit_exceeded` 表示等待后重试。

SDK 已经会对部分错误暂停后重试两次（`maxRetries`）。对于长时间批量，保留这个默认行为，按上面的方式限制并发，并记录你放弃的失败。 [errors 页面](https://llmwithcrypto.com/zh/docs/errors/) 列出了每个状态码，以及哪些值得重试。失败的调用不产生费用：按 token 从余额扣费：输入和输出 token 由模型自己的 tokenizer 计数，按该模型每 1M token 的价格计费。以错误结束的调用不收费。

## 如何迁移现有的 OpenAI 应用？

修改客户端选项 `baseURL` 和 `apiKey`，并把所有 `gpt-…` 模型名替换成 [models 页面](https://llmwithcrypto.com/zh/models/) 中的 id。Prompt、流式代码以及对 `choices` 和 `usage` 的解析都保持不变。切换流量前先在新模型上跑测试：tool calling 和 JSON 输出取决于每个模型支持什么。

## Node.js：常见问题

### 我能在浏览器里调用 API 吗？

技术上可以，但绝不要把密钥放进页面里。请从服务器调用，或从一个持有密钥的 serverless function 调用。

### Vercel AI SDK 能用吗？

任何接受 OpenAI 兼容 base URL 的库都能用。API 使用 OpenAI chat completions 格式：把 OpenAI SDK、LangChain 或任何 OpenAI 兼容工具指向我们的 base URL 并带上你的密钥，再改一下模型名即可。

### 积分用完了会怎样？

调用会返回 `402 insufficient_balance`，且不产生费用。[errors 页面](https://llmwithcrypto.com/zh/docs/errors/) 说明了如何应对。

---

LLMwithCrypto: LLMwithCrypto 是一个兼容 OpenAI 的开放权重模型 LLM API，涵盖 DeepSeek V4 Pro、DeepSeek V4.1 Flash、DeepSeek R1、Qwen3.5 397B A17B、Qwen3 235B A22B Instruct、gpt-oss-120b、gpt-oss-20b、GLM-4.7、Llama 3.3 70B Instruct、Gemma 4 31B、Mistral Large 3、Mistral Small 4，按 token 从预付加密货币余额中扣费，价格比公共托管商的中位价低 5%。无需 KYC：无需身份证件、无需自拍、无需文件。不存储提示词和输出。
