Node.js与Express构建AI对话平台后端实战
1. 项目概述AI智能体对话平台的地基搭建这个系列文章的第二部分我们要真正开始动手写代码了。作为从零开始的实战教程我会带你用Node.js和Express搭建一个最基础的AI智能体对话平台服务端。这就像盖房子要先打地基虽然看起来简单但每一步都关系到后续功能的扩展性。为什么选择Node.js三个核心原因首先JavaScript生态有丰富的AI相关库支持其次Node.js的非阻塞I/O特性特别适合处理对话场景的高并发请求最后前后端统一的语言能降低全栈开发的学习成本。我们用的Express框架相当于给Node.js装上了现成的轮子省去了自己造轮子的时间。2. 开发环境准备2.1 工具链配置我推荐使用VS Code作为主力编辑器配合这些必备插件ESLint保持代码风格一致Prettier自动格式化代码REST Client方便测试API接口DotENV管理环境变量安装Node.js时有个细节要注意不要用最新的v22版本建议选择LTS版的v20.x。太新的版本可能会遇到某些依赖包兼容性问题。验证安装成功的正确姿势是node -v npm -v2.2 项目初始化新建项目目录后别急着npm init -y。我建议手动配置package.json特别注意这两个配置项{ type: module, scripts: { dev: nodemon --inspect0.0.0.0 server.js } }使用ES模块规范(type: module)是为了方便后续集成现代前端框架。调试时用nodemon比直接node启动更高效--inspect参数是为后续接入VSCode调试器做准备。3. Express服务器搭建3.1 基础服务器结构先安装核心依赖npm install express cors dotenv npm install --save-dev nodemon基础服务器代码应该像这样分层组织/src /config env.js # 环境变量配置 constants.js # 常量定义 /routes api.js # API路由 /services ai.js # AI服务封装 server.js # 入口文件重点看server.js的关键配置import express from express; import cors from cors; import apiRouter from ./routes/api.js; const app express(); app.use(cors({ origin: process.env.CORS_ORIGIN || *, methods: [GET, POST] })); app.use(express.json({ limit: 10kb })); // 健康检查端点 app.get(/health, (req, res) { res.status(200).json({ status: ok }); }); // API路由 app.use(/api/v1, apiRouter); // 错误处理中间件要放在最后 app.use((err, req, res, next) { console.error(err.stack); res.status(500).send(Something broke!); }); const PORT process.env.PORT || 3000; app.listen(PORT, () { console.log(Server running on port ${PORT}); });3.2 环境变量管理永远不要把敏感配置硬编码在代码里使用dotenv管理环境变量时要注意在项目根目录创建.env文件在.gitignore中添加.env配置示例NODE_ENVdevelopment PORT3000 OPENAI_API_KEYyour_key_here CORS_ORIGINhttp://localhost:5173在代码中通过config/env.js统一加载import dotenv from dotenv; import path from path; dotenv.config({ path: path.resolve(process.cwd(), .env.${process.env.NODE_ENV || development}) }); export default { env: process.env.NODE_ENV, port: parseInt(process.env.PORT, 10), openaiApiKey: process.env.OPENAI_API_KEY, corsOrigin: process.env.CORS_ORIGIN };4. AI服务层封装4.1 OpenAI SDK集成安装官方SDKnpm install openai在services/ai.js中创建AI服务类import OpenAI from openai; import config from ../config/env.js; class AIService { constructor() { this.client new OpenAI({ apiKey: config.openaiApiKey, timeout: 10000 // 10秒超时 }); } async chatCompletion(messages, model gpt-3.5-turbo) { try { const response await this.client.chat.completions.create({ model, messages, temperature: 0.7, max_tokens: 500 }); return response.choices[0].message.content; } catch (error) { console.error(AI服务错误:, error); throw new Error(AI处理请求失败); } } } export default new AIService();4.2 对话路由实现在routes/api.js中创建对话端点import express from express; import aiService from ../services/ai.js; const router express.Router(); router.post(/conversation, async (req, res) { const { messages } req.body; if (!messages || !Array.isArray(messages)) { return res.status(400).json({ error: Invalid messages format }); } try { const response await aiService.chatCompletion(messages); res.json({ response }); } catch (error) { res.status(500).json({ error: error.message }); } }); export default router;5. 调试与测试5.1 接口测试创建requests/test.http文件POST http://localhost:3000/api/v1/conversation Content-Type: application/json { messages: [ {role: system, content: 你是一个专业的客服助手}, {role: user, content: 你好能介绍一下你们的产品吗} ] }使用REST Client插件发送请求预期响应{ response: 当然可以。我们提供AI智能体解决方案包括智能客服、自动问答系统等。您想了解哪个具体产品 }5.2 错误处理测试故意发送错误格式的请求POST http://localhost:3000/api/v1/conversation Content-Type: application/json { wrong_field: invalid data }应收到400状态码和错误信息{ error: Invalid messages format }6. 项目优化与扩展6.1 性能优化技巧请求限流安装express-rate-limitimport rateLimit from express-rate-limit; const limiter rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100 // 每个IP限制100次请求 }); app.use(/api/, limiter);响应缓存对常见问题答案缓存import NodeCache from node-cache; const cache new NodeCache({ stdTTL: 600 }); router.post(/conversation, async (req, res) { const cacheKey JSON.stringify(req.body.messages); const cached cache.get(cacheKey); if (cached) return res.json(cached); // ...原有处理逻辑 cache.set(cacheKey, { response }); });6.2 监控与日志安装winston日志库npm install winston配置日志服务import winston from winston; const logger winston.createLogger({ level: info, format: winston.format.json(), transports: [ new winston.transports.File({ filename: error.log, level: error }), new winston.transports.File({ filename: combined.log }) ] }); if (process.env.NODE_ENV ! production) { logger.add(new winston.transports.Console({ format: winston.format.simple() })); }7. 生产环境部署7.1 PM2进程管理安装PM2并配置npm install pm2 -g pm2 init simple修改ecosystem.config.jsmodule.exports { apps: [{ name: ai-agent, script: ./server.js, instances: max, autorestart: true, watch: false, max_memory_restart: 1G, env: { NODE_ENV: production } }] };启动命令pm2 start ecosystem.config.js7.2 Docker化部署创建DockerfileFROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . EXPOSE 3000 CMD [node, server.js]构建和运行docker build -t ai-agent . docker run -p 3000:3000 -d ai-agent8. 常见问题解决8.1 跨域问题虽然我们已经配置了CORS但前端仍可能遇到问题。解决方案确保前端请求携带credentials时后端CORS配置要加上app.use(cors({ origin: config.corsOrigin, credentials: true }));处理预检请求app.options(*, cors()); // 在所有路由前添加8.2 长响应超时AI处理复杂请求可能需要较长时间调整超时设置const server app.listen(PORT); server.setTimeout(60000); // 60秒超时同时前端fetch请求也要设置fetch(/api/conversation, { method: POST, signal: AbortSignal.timeout(60000) });9. 代码质量保障9.1 ESLint配置安装标准配置npm install eslint eslint-config-standard --save-dev.eslintrc.json配置{ extends: standard, rules: { no-console: warn, comma-dangle: [error, never] }, env: { node: true } }9.2 单元测试安装测试框架npm install jest supertest --save-dev创建测试文件import request from supertest; import app from ../server.js; describe(API Endpoints, () { it(GET /health should return 200, async () { const res await request(app).get(/health); expect(res.statusCode).toEqual(200); }); it(POST /conversation with invalid data should return 400, async () { const res await request(app) .post(/api/v1/conversation) .send({ wrong: data }); expect(res.statusCode).toEqual(400); }); });10. 项目结构优化建议随着功能增加建议采用这样的扩展结构/src /controllers aiController.js /middlewares auth.js errorHandler.js /models Conversation.js /utils logger.js cache.js /tests unit integration这种分层架构的优势业务逻辑集中在controllers数据操作抽象到models层通用功能放在utils中间件独立管理测试代码与实现分离