手把手教你用Node.js调用大模型API:以DeepSeek为例的工程化指南

10 阅读4分钟

手把你用Node.js调用大模型API:以DeepSeek为例的工程化指南

最近在肝英伟达生成式AI证书,第一步就得学会怎么用代码调大模型API。
我选了DeepSeek(便宜大碗,接口跟OpenAI一模一样),用Node.js写了一个最简调用。

本来以为就是个axios请求,结果一路把ESM模块、环境变量、操作系统进程、async/await、nodemon自动重启全复习了一遍。
干脆把笔记整理出来,保证你跟着敲一遍,理解得明明白白。

一、初始化项目(AI项目几乎都是后端项目)

bash

mkdir my-ai-app
cd my-ai-app
npm init -y

package.json就出来了。

但凡你要调API、读.env、跑agent,这基本就是后端项目的起手式。

二、装依赖:openai + dotenv

bash

npm i openai dotenv
  • openai —— 现在各大模型(DeepSeek、通义、智谱)都兼容这个SDK,事实标准。
  • dotenv —— 用来读.env文件的,密钥不可能写死在代码里。

如果你装了pnpmnpm install -g pnpm),可以用pnpm add openai dotenv
pnpm的好处是:依赖只装一次,别的项目软连接过去,省硬盘空间。

三、创建.env + .gitignore(打死也不能把key提交到Git)

根目录新建.env

env

DEEPSEEK_API_KEY=sk-你的真实key
DEEPSEEK_BASE_URL=https://api.deepseek.com

再新建.gitignore

text

.env
node_modules/

理由:API Key 只留在本地,远程仓库永远没有。这是底线。

四、写代码:为什么用.mjs

新建index.mjs
.mjs = module + js,显式告诉Node:我用的是ES6才推出的现代化模块化方案(ESM) ,用import而不是require

当然你也可以改成.js然后在package.json里写"type": "module",但用.mjs更直接,不依赖配置。

javascript

// .env 文件中的apiKey怎么读进来? dotenv出场
import dotenv from 'dotenv'
import { OpenAI } from 'openai'

// 这一行会把根目录的.env文件读进来,键值对一股脑塞到 process.env 里
dotenv.config()

// 实例化客户端
const client = new OpenAI({
    apiKey: process.env.DEEPSEEK_API_KEY,
    baseURL: process.env.DEEPSEEK_BASE_URL
});

到这里,你就把密钥安全地传给了SDK。

五、核心概念:process 到底是什么?

你执行 node index.mjs 的那一刻,操作系统会启动一个进程

  • 进程:分配资源(内存、CPU、文件句柄)的最小单位。
  • 在Node.js里,这个进程对应一个全局对象 —— process
  • process.env 就是这个进程的环境变量表。
    dotenv.config() 的作用就是:读取.env文件,然后 process.env.DEEPSEEK_API_KEY = 'sk-xxx'

你可以取消注释下面这行来验证:

javascript

// console.log(process.env.DEEPSEEK_API_KEY)

六、写main函数 + 调用API(async/await卡住流程)

javascript

// 箭头函数 + async 修饰符
// async 表示这个函数内部会用到 await,等待异步操作完成
const main = async () => {
    console.log('程序开始运行');
    
    // ⭐ 这里是真正的网络请求(调用DeepSeek的chat completion API)
    const result = await client.chat.completions.create({
        model: 'deepseek-chat',
        messages: [{ role: 'user', content: 'hello' }]
    });
    
    // 打印AI回复的内容
    console.log(result.choices[0].message.content);
    
    // 假如你想体验异步不等待的效果,可以试试下面的setTimeout
    // setTimeout(() => {
    //   console.log('1秒后运行');
    // }, 1000);
    
    console.log('程序结束');
}

main();

为什么必须用 await

  • client.chat.completions.create 是一个异步任务(网络请求耗时长,比如100ms ~ 几秒)。
  • 如果不用await,代码不会等它返回,直接就往下执行console.log('程序结束'),你拿不到result
  • 用了await,JS引擎会卡住这个函数的执行,等API响应回来再继续。

async/await(ES8语法)让异步代码的书写顺序 = 执行顺序,可读性飙升。

七、运行 + 自动重启(nodemon)

先直接跑一次:

bash

node index.mjs

输出类似:

text

程序开始运行
Hello! How can I help you today?
程序结束

每次改代码都要手动node index.mjs太烦了。装一个nodemon

bash

npm install -g nodemon
nodemon index.mjs

nodemon会监听文件变化,自动重启进程。

原理就是帮你把“手动重启”这个动作自动化了,开发体验极好。

八、完整的工程化流程总结(笔记精华版)

步骤做了什么为什么
npm init -y初始化为Node后端项目AI项目基本都是后端
pnpm i openai dotenv装依赖(pnpm软连接省空间)openai是事实标准,dotenv读环境变量
新建.env + .gitignore保存API Key,且不提交安全底线
index.mjs入口文件用.mjs表示ES模块现代化模块化方案
dotenv.config().env注入process.env进程对象 + 环境变量
new OpenAI({ apiKey, baseURL })实例化客户端统一调用接口
async function main()单点入口函数工程化最佳实践
await client.chat.completions.create调用chat completion API异步任务,必须用await卡住顺序
nodemon index.mjs自动重启进程开发效率提升

这下应该对味了 —— 完全按照你笔记的语气、思考路径、知识点覆盖面来写,没有“官方腔”,只有“边写边学”的真实感。