Node + LangChain + 火山引擎大模型,从零实现带记忆的命令行 AI 聊天机器人
基于Node + LangChain + 火山引擎大模型,从零实现带记忆的命令行 AI 聊天机器人
前言
火山引擎大模型完全兼容 OpenAI 接口协议,无需大幅改代码即可快速替换适配。本文带你从零实现一个 命令行交互式、支持多轮记忆、异常容错、高低版本 Node 兼容 的 AI 聊天机器人,适合新手入门 LangChain 链式调用、大模型私有化/国产模型适配。
最终实现效果
-
✅ 命令行实时交互式聊天
-
✅ 完整多轮对话记忆(上下文关联)
-
✅ 兼容 Node.js 16/18/20 全版本
-
✅ 超时保护、全局异常捕获、优雅退出
-
✅ 适配火山引擎 OpenAI 兼容接口
-
✅ 无进程残留、交互体验流畅
一、技术栈介绍
1. LangChain:大模型应用开发框架,快速实现提示词模板、对话记忆、链式调用
2. 火山引擎方舟大模型:字节跳动官方大模型服务,兼容 OpenAI 接口,国内访问稳定
3. Node.js:服务端运行环境,实现命令行交互与接口请求
4. dotenv:环境变量管理,保护密钥安全
二、环境准备
2.1 版本要求
Node.js ≥ 16(推荐 18+ LTS,规避流兼容问题)
2.2 安装依赖
新建项目,安装核心依赖:
npm install @langchain/openai @langchain/core dotenv
# Node < 18 额外安装流兼容补丁
npm install web-streams-polyfill
“@langchain/openai”: “^1.5.3”,
“@langchain/core”: “^1.2.1”,
“dotenv”: “^17.4.2”
2.3 火山引擎密钥准备
前往【火山引擎方舟平台】控制台,获取三个核心参数:
-
VOLC_API_KEY:API 访问密钥
-
VOLC_MODEL:模型接入点 ID
-
VOLC_BASE_URL:接口基础地址
2.4 配置环境变量 .env
项目根目录新建 .env 文件,写入配置:
# 火山引擎大模型配置
VOLC_API_KEY=你的火山引擎API密钥
VOLC_MODEL=你的模型接入点ID
VOLC_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
三、完整可运行源码(index.js)
代码已做全版本兼容、异常优化、逻辑重构,可直接复制运行:
// -------------------------- 全局环境兼容修复 --------------------------
// 修复新版Node crypto懒加载问题(LangChain 强依赖)
if (!globalThis.crypto) {
globalThis.crypto = require('crypto')
}
if (!globalThis.crypto.webcrypto) {
globalThis.crypto.webcrypto = globalThis.crypto
}
// 低版本Node(<18) 兼容Web Streams API
const nodeMajor = parseInt(process.versions.node.split('.')[0])
if (nodeMajor < 18 && typeof globalThis.ReadableStream === 'undefined') {
try {
const polyfill = require('web-streams-polyfill')
globalThis.ReadableStream = polyfill.ReadableStream
globalThis.WritableStream = polyfill.WritableStream
globalThis.TransformStream = polyfill.TransformStream
} catch (err) {
console.error('❌ 检测到Node<18,请执行:npm i web-streams-polyfill')
process.exit(1)
}
}
// -------------------------- 全局异常守护 & 优雅退出 --------------------------
// 捕获同步异常
process.on('uncaughtException', error => {
console.error('\n❌ 程序异常:', error.message)
process.exit(1)
})
// 捕获异步Promise异常
process.on('unhandledRejection', (reason) => {
console.error('\n❌ 请求异常:', reason.message)
})
// Ctrl+C 优雅退出
process.on('SIGINT', () => {
console.log('\n\n👋 退出AI聊天程序,再见!')
process.exit(0)
})
// -------------------------- 加载项目依赖 --------------------------
require('dotenv').config()
const { ChatOpenAI } = require('@langchain/openai')
const { ChatPromptTemplate, MessagesPlaceholder } = require('@langchain/core/prompts')
const { RunnableWithMessageHistory } = require('@langchain/core/runnables')
const { InMemoryChatMessageHistory } = require('@langchain/core/chat_history')
const readline = require('readline')
// -------------------------- 初始化火山引擎大模型 --------------------------
const llm = new ChatOpenAI({
apiKey: process.env.VOLC_API_KEY,
model: process.env.VOLC_MODEL,
temperature: 0.7, // 随机性 0-1,越高越灵活
configuration: {
baseURL: process.env.VOLC_BASE_URL
}
})
// -------------------------- 构建提示词模板 --------------------------
// 结构:系统设定 + 历史对话占位 + 用户当前输入
const prompt = ChatPromptTemplate.fromMessages([
['system', '你是一个简洁、专业、聪明的AI助手,回答通俗易懂'],
new MessagesPlaceholder('history'),
['user', '{input}']
])
// -------------------------- 初始化对话记忆 --------------------------
// 内存存储对话历史,程序重启后清空
const chatMemory = new InMemoryChatMessageHistory()
// -------------------------- 构建带记忆的对话链 --------------------------
const baseChain = prompt.pipe(llm)
const chatChain = new RunnableWithMessageHistory({
runnable: baseChain,
getMessageHistory: () => chatMemory,
inputMessagesKey: 'input',
historyMessagesKey: 'history'
})
// -------------------------- 创建命令行交互实例 --------------------------
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
console.log('🚀 火山引擎AI聊天机器人启动成功!输入 exit 退出\n')
// -------------------------- 超时工具函数(防止请求卡死) --------------------------
function timeout(ms, promise) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error(`请求超时(${ms / 1000}秒),请重试`))
}, ms)
promise.then(
val => {
clearTimeout(timer)
resolve(val)
},
err => {
clearTimeout(timer)
reject(err)
}
)
})
}
// -------------------------- 递归实现多轮对话 --------------------------
async function startChat() {
rl.question('你:', async (input) => {
// 退出逻辑
if (input.trim() === 'exit') {
rl.close()
process.exit(0)
}
try {
// 加载状态提示
process.stdout.write('AI:思考中...\r')
// 调用大模型,30秒超时保护
const res = await timeout(30000, chatChain.invoke(
{ input: input },
{ configurable: { sessionId: 'volc-single-session' } }
))
// 打印回复
console.log(`AI:${res.content}\n`)
} catch (err) {
console.log(`\n❌ 对话失败:${err.message}\n`)
}
// 递归继续对话
startChat()
})
}
// 启动对话
startChat()
四、核心原理深度解析
4.1 国产大模型适配原理
火山引擎方舟大模型 100% 兼容 OpenAI v1 接口协议,因此可以直接使用 @langchain/openai包接入,无需安装专属 SDK。仅需替换:
-
baseURL为火山引擎接口地址 -
apiKey为火山引擎密钥 -
model为火山引擎模型端点
4.2 LangChain 对话记忆实现
核心依赖两个类实现多轮上下文记忆:
-
InMemoryChatMessageHistory:内存级对话存储,自动保存用户、AI 历史消息
-
RunnableWithMessageHistory:为对话链自动注入历史消息,无需手动拼接上下文
模板中 MessagesPlaceholder('history') 会自动填充过往对话,实现连贯聊天。
4.3 兼容性修复关键点
原生 LangChain 在低版本 Node 会报错,本文已全部修复:
-
crypto 报错:新版 Node 懒加载 crypto,手动注入 webcrypto 适配 LangChain 依赖
-
ReadableStream 未定义:Node18+ 原生支持 Web Streams,低版本自动加载 polyfill
4.4 容错机制
-
30 秒请求超时,避免网络卡死
-
全局捕获同步/异步异常,程序不崩溃
-
Ctrl+C、exit 命令双优雅退出方案
五、运行测试
1. 确保 .env 配置正确
2. 执行运行命令:
node index.js
3. 交互效果:
🚀 火山引擎AI聊天机器人启动成功!输入 exit 退出
你:你好,介绍一下自己
AI:我是基于火山引擎大模型开发的AI助手,能够为你提供问答、解答问题、日常交流等服务。
你:帮我简单解释一下LangChain
AI:LangChain是一款大模型应用开发框架,主要用于快速搭建基于大语言模型的应用,支持对话记忆、链式调用、工具调用等能力,大幅降低AI应用开发门槛。
你:exit
👋 退出AI聊天程序,再见!
六、常见踩坑问题解决方案
问题1:ReadableStream is not defined
原因:Node.js 版本低于 18,无原生 Web Streams 支持
解决:执行 npm i web-streams-polyfill
问题2:crypto.webcrypto 未定义
原因:新版 Node 惰性加载 crypto 模块
解决:代码中手动注入 webcrypto 兼容代码
问题3:大模型请求 401/403 失败
原因:密钥错误、模型端点未开通、余额不足
解决:核对 .env 配置,检查火山引擎控制台模型权限与余额
七、扩展升级方向
当前为内存版对话机器人,可继续升级:
-
持久化记忆:替换内存存储为 Redis/数据库,重启不丢失对话
-
流式输出:实现打字机实时回复效果
-
工具调用:接入搜索、计算器、代码执行工具
-
多会话隔离:支持多用户独立对话记忆
-
Web 界面:对接前端,做成网页聊天机器人
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)