资讯动态

InternLM2-Chat-1.8B与Node.js后端集成教程:构建全栈AI应用

发布时间:2026/8/22 18:43:52 来源:尧图企业网站定制
InternLM2-Chat-1.8B与Node.js后端集成教程构建全栈AI应用想给你的Node.js应用加上一个能聊天的“大脑”吗今天咱们就来聊聊怎么把InternLM2-Chat-1.8B这个轻量又好用的对话模型塞进你的Express或者Koa项目里。整个过程比你想象的要简单跟着步骤走一个下午就能让后端“开口说话”。我最近在一个小项目里试了试效果挺让人惊喜的。1.8B的参数量对于大多数需要智能对话的中小型应用来说完全够用而且部署和集成起来比那些动辄几十B的“大块头”要友好得多。最关键的是用Node.js来搭桥前后端都是JavaScript/TypeScript开发起来特别顺手。1. 准备工作环境与模型服务在开始写代码之前咱们得先把“舞台”搭好。这里主要分两步一是确保你的Node.js环境没问题二是得有一个正在运行的InternLM2模型服务。1.1 检查并配置Node.js环境首先打开你的终端敲入下面这行命令看看Node.js和它的包管理器npm或者你用的yarn、pnpm是不是已经就位了。node --version npm --version如果看到了版本号比如v18.18.0和9.8.1那就恭喜你第一步完成了。如果提示“命令未找到”那就需要先去Node.js官网下载安装包。我建议选择LTS长期支持版本用起来更稳当。安装好之后可以创建一个新的项目文件夹并初始化它。mkdir my-ai-backend cd my-ai-backend npm init -y这会在文件夹里生成一个package.json文件记录项目信息和依赖。1.2 启动InternLM2模型服务我们的Node.js后端自己并不直接运行大模型那是GPU服务器的活儿。我们需要的是一个已经启动并提供API的模型服务。假设你的运维同事或者你自己已经在某台服务器上部署好了InternLM2-Chat-1.8B并且它提供了一个HTTP接口。通常这类服务会有一个基础的URL比如http://your-model-server:8000并且有一个用于对话的端点例如/v1/chat/completions。你需要知道这个地址和端口。为了在代码里方便管理我们可以在项目根目录创建一个.env文件来存放这个配置。# .env 文件内容 MODEL_API_BASE_URLhttp://192.168.1.100:8000 MODEL_API_KEYyour_api_key_here # 如果服务需要认证的话记得把.env文件加入到.gitignore里避免把敏感信息传到代码仓库。2. 构建基础后端Express篇Express是Node.js里最流行的Web框架咱们先用它来快速搭建一个骨架。如果你更喜欢Koa别急下一章我们再讲。2.1 安装依赖并创建基础服务在你的项目目录下安装Express和必要的工具包。npm install express dotenv axios corsexpress: 我们的Web框架本体。dotenv: 用来读取刚才创建的.env文件中的环境变量。axios: 一个非常好用的HTTP客户端库用来向模型API发送请求。cors: 处理跨域请求的中间件方便前端调用。接下来创建入口文件app.js。// app.js require(dotenv).config(); // 加载环境变量 const express require(express); const cors require(cors); const axios require(axios); const app express(); const PORT process.env.PORT || 3000; // 中间件 app.use(cors()); // 启用CORS允许前端跨域访问 app.use(express.json()); // 解析JSON格式的请求体 // 创建一个axios实例配置模型服务的基础地址 const modelApi axios.create({ baseURL: process.env.MODEL_API_BASE_URL, timeout: 60000, // 模型推理可能较慢超时时间设长一点 headers: { Content-Type: application/json, // 如果有API Key可以在这里添加认证头 // Authorization: Bearer ${process.env.MODEL_API_KEY} } }); // 一个简单的健康检查路由 app.get(/, (req, res) { res.json({ message: AI 后端服务运行正常, model: InternLM2-Chat-1.8B }); }); // 启动服务器 app.listen(PORT, () { console.log( 后端服务已启动监听端口: ${PORT}); console.log( 模型服务地址: ${process.env.MODEL_API_BASE_URL || 未配置}); });现在运行node app.js你应该能在终端看到启动成功的消息访问http://localhost:3000会返回一个JSON问候。基础框架这就搭好了。2.2 实现核心对话API路由现在我们来添加最重要的部分一个接收用户消息、转发给InternLM2、并返回模型回复的接口。在app.js中添加以下路由// 对话补全接口 app.post(/api/chat, async (req, res) { try { const userMessage req.body.message; const history req.body.history || []; // 支持传递历史对话 if (!userMessage) { return res.status(400).json({ error: 消息内容不能为空 }); } // 构造符合InternLM2接口要求的请求体 // 注意这里需要根据你实际模型服务的API文档调整格式 const payload { model: internlm2-chat-1.8b, // 模型名称 messages: [ ...history, // 历史对话 { role: user, content: userMessage } ], stream: false, // 先实现非流式流式响应后面讲 temperature: 0.7, // 创造性0-1之间越高越随机 max_tokens: 1024 // 生成的最大token数 }; console.log( 转发用户消息至模型: ${userMessage.substring(0, 50)}...); // 向模型服务发送请求 const response await modelApi.post(/v1/chat/completions, payload); // 从模型响应中提取回复内容 const modelReply response.data.choices[0]?.message?.content || 模型未返回有效内容。; console.log( 收到模型回复长度: ${modelReply.length} 字符); // 返回给前端 res.json({ reply: modelReply, usage: response.data.usage // 可选返回token消耗情况 }); } catch (error) { console.error(❌ 调用模型API失败:, error.message); // 更细致的错误处理 if (error.response) { // 模型服务返回了错误状态码 console.error(模型服务响应错误:, error.response.data); res.status(error.response.status).json({ error: 模型服务错误: ${error.response.status}, details: error.response.data }); } else if (error.request) { // 请求发出了但没有收到响应 res.status(503).json({ error: 无法连接到模型服务请检查网络或服务状态。 }); } else { // 其他错误 res.status(500).json({ error: 服务器内部错误 }); } } });这个/api/chat接口已经具备了基本功能。你可以用Postman或者curl测试一下curl -X POST http://localhost:3000/api/chat \ -H Content-Type: application/json \ -d {message: 你好请介绍一下你自己。}如果一切顺利你会收到InternLM2-Chat-1.8B的自我介绍。3. 进阶功能流式响应与生产级考量基础对话有了但体验上还能优化。比如模型生成一段长文本需要好几秒让用户干等着可不友好。另外直接把API暴露在网上也不安全。3.1 实现流式响应Server-Sent Events流式响应能让模型生成一个字就返回一个字前端可以实时显示体验就像真人打字一样。我们用Server-Sent Events (SSE) 来实现。首先修改/api/chat接口支持一个stream参数。我们创建一个新的流式端点/api/chat/stream来演示。// 流式对话接口 app.get(/api/chat/stream, async (req, res) { const userMessage req.query.message; if (!userMessage) { return res.status(400).json({ error: 消息内容不能为空 }); } // 设置SSE相关的响应头 res.writeHead(200, { Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, Access-Control-Allow-Origin: *, // 根据你的前端地址调整 }); try { const payload { model: internlm2-chat-1.8b, messages: [{ role: user, content: userMessage }], stream: true, // 关键要求模型服务返回流式数据 temperature: 0.7, max_tokens: 1024 }; // 向模型服务发起流式请求 const modelResponse await modelApi.post(/v1/chat/completions, payload, { responseType: stream // 告诉axios我们期待一个流 }); // 将模型服务的流式输出转发给客户端 modelResponse.data.on(data, (chunk) { // 模型服务通常以 \n\n 分隔多个事件每个事件是 data: {...} 格式 const lines chunk.toString().split(\n\n).filter(line line.trim()); for (const line of lines) { if (line.startsWith(data: )) { const dataStr line.replace(data: , ); if (dataStr [DONE]) { res.write(event: end\ndata: [DONE]\n\n); res.end(); return; } try { const data JSON.parse(dataStr); const content data.choices[0]?.delta?.content; if (content) { // 将内容以SSE格式发送给前端 res.write(data: ${JSON.stringify({ content })}\n\n); } } catch (e) { // 忽略非JSON数据 } } } }); modelResponse.data.on(end, () { console.log(✅ 流式响应结束); res.end(); }); modelResponse.data.on(error, (err) { console.error(模型流错误:, err); res.write(event: error\ndata: ${JSON.stringify({ error: 流中断 })}\n\n); res.end(); }); } catch (error) { console.error(流式请求失败:, error); res.write(event: error\ndata: ${JSON.stringify({ error: error.message })}\n\n); res.end(); } });前端需要用一个EventSource对象来连接这个端点就能实时收到文字了。这比等全部生成完再一次性显示体验提升了好几个档次。3.2 添加基础安全与管控一个要上线的服务安全是必须考虑的。我们加两个最常用的中间件速率限制和简单的API密钥认证。先安装速率限制包npm install express-rate-limit然后在app.js中引入并配置const rateLimit require(express-rate-limit); // 全局速率限制每个IP每15分钟最多100次请求 const globalLimiter rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, message: { error: 请求过于频繁请稍后再试。 }, standardHeaders: true, // 返回标准的 RateLimit-* 头部 legacyHeaders: false, // 禁用 X-RateLimit-* 头部 }); // 对特定路由应用更严格的限制比如对话接口 const chatLimiter rateLimit({ windowMs: 1 * 60 * 1000, // 1分钟 max: 10, // 每分钟最多10次对话请求 message: { error: 对话请求过于频繁请休息一下。 }, }); // 应用中间件 app.use(globalLimiter); // 应用到所有路由 app.use(/api/chat, chatLimiter); // 对对话接口应用额外限制 // 简单的API Key认证中间件示例生产环境需更复杂 const apiKeyAuth (req, res, next) { const clientApiKey req.headers[x-api-key]; const validApiKey process.env.API_KEY; // 从环境变量读取合法Key if (!validApiKey) { // 如果服务端未配置API_KEY则跳过认证不推荐用于生产 return next(); } if (clientApiKey clientApiKey validApiKey) { next(); } else { res.status(401).json({ error: 无效或缺失API Key }); } }; // 将认证应用到需要保护的路由 app.use(/api/chat, apiKeyAuth); app.use(/api/chat/stream, apiKeyAuth);这样你的服务就有了基础的防滥用和访问控制能力。4. 另一种选择使用Koa框架如果你或者你的团队更偏爱Koa这种更现代、基于异步中间件的框架集成过程也非常类似。我们来快速过一遍。4.1 搭建Koa服务骨架安装Koa及相关生态包npm install koa koa/cors koa-bodyparser koa-router dotenv axios创建koa-app.js// koa-app.js require(dotenv).config(); const Koa require(koa); const Router require(koa-router); const cors require(koa/cors); const bodyParser require(koa-bodyparser); const axios require(axios); const app new Koa(); const router new Router(); const PORT process.env.PORT || 3001; // 中间件 app.use(cors()); app.use(bodyParser()); // 同样的axios实例配置 const modelApi axios.create({ baseURL: process.env.MODEL_API_BASE_URL, timeout: 60000, headers: { Content-Type: application/json } }); // 健康检查 router.get(/, (ctx) { ctx.body { message: Koa AI 后端服务运行正常, model: InternLM2-Chat-1.8B }; }); // 对话接口 (非流式) router.post(/api/chat, async (ctx) { try { const { message, history [] } ctx.request.body; // ... 参数校验和请求构造逻辑与Express版相同 ... const response await modelApi.post(/v1/chat/completions, payload); const modelReply response.data.choices[0]?.message?.content; ctx.body { reply: modelReply }; } catch (error) { // ... 错误处理逻辑 ... ctx.status 500; ctx.body { error: 处理请求时出错 }; } }); // 流式对话接口 router.get(/api/chat/stream, async (ctx) { const userMessage ctx.query.message; ctx.request.socket.setTimeout(0); // 防止超时 ctx.req.socket.setNoDelay(true); ctx.req.socket.setKeepAlive(true); ctx.set({ Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, }); ctx.status 200; ctx.body null; // Koa中我们将手动写响应 // 由于Koa的ctx.body对SSE支持不直接我们使用原生res对象 const streamResponse (data) { ctx.res.write(data: ${JSON.stringify(data)}\n\n); }; try { const payload { /* ... 构造流式请求体 ... */ }; const modelResponse await modelApi.post(/v1/chat/completions, payload, { responseType: stream }); modelResponse.data.on(data, (chunk) { // ... 解析chunk并调用streamResponse转发 ... }); modelResponse.data.on(end, () { ctx.res.end(); }); // 等待流结束 await new Promise((resolve) { modelResponse.data.on(close, resolve); }); } catch (error) { streamResponse({ error: error.message }); ctx.res.end(); } }); app.use(router.routes()).use(router.allowedMethods()); app.listen(PORT, () { console.log( Koa后端服务已启动监听端口: ${PORT}); });Koa的中间件机制和错误处理与Express略有不同但核心的“接收请求-转发模型-返回结果”的逻辑是完全相通的。选择哪个框架更多是团队偏好和项目特性的考量。5. 总结与后续建议走完这一趟你应该已经成功地把InternLM2-Chat-1.8B接入了你的Node.js后端。无论是用Express还是Koa核心思路都是一样的你的后端充当了一个智能的“中转站”和“调度员”。它负责接收前端的用户输入按照模型服务要求的格式打包好送过去再把模型的回复整理好送回给前端中间还加上了流式输出、限流、认证这些提升体验和安全的“调料”。在实际项目里你可能还会遇到更多需要琢磨的地方。比如对话历史怎么更高效地管理用户上下文很长的时候怎么处理模型返回的内容要不要在发给用户前做个安全检查这些都可以在你的这个基础骨架上慢慢添砖加瓦。我建议你先用这个最简单的版本跑起来让前后端联调通过看到模型真的能通过你的服务进行对话。有了这个“正反馈”再去考虑优化和扩展方向会更明确。毕竟能跑起来的代码才是最好的代码。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价