LangChain.js 实战指南:从调用到 Agent 工具编排的 LLM 应用开发

发布时间:2026/8/31 14:15:51
LangChain.js 实战指南:从调用到 Agent 工具编排的 LLM 应用开发 这次我们来看 LangChain.js。它不是某个聊天应用也不是单纯的大模型调用示例而是专门给 JavaScript/TypeScript 开发者用的 LLM 应用开发框架。简单说LangChain 在 Python 生态里积累了很强的模型编排能力LangChain.js 就是把这一套能力搬到 Node.js 环境里让前端、全栈和后端团队可以用熟悉的 JS 技术栈来搭 AI 应用。如果你之前直接调过大模型 API应该会有这种感觉单个接口调用很简单但一旦要管理对话历史、提示词模板、多个模型切换、工具调用和流式输出代码就很容易变成“面向接口复制粘贴”。LangChain.js 的核心价值是把整个调用过程结构化让模型接入、提示词、Agent、检索这些模块可以被统一组织和复用而不是每次都在业务代码里拼字符串。这篇文章会围绕一条完整链路展开环境准备、安装依赖、写第一个对话程序、测试提示词模板与 Agent 工具调用、封装 HTTP API、跑批量任务、观察资源占用最后给常见问题和排查方法。你不需要 GPU也不一定需要固定选某家大模型Node.js 环境加一个模型服务 API Key 就能开始。1. LangChain.js 核心能力速览能力项说明项目类型LLM 应用开发框架JavaScript/TypeScript所属生态LangChain 官方生态与 Python 版 LangChain 对应运行环境Node.js不依赖 GPU 或特定显卡主要功能模型调用封装、提示词模板、链式编排、Agent 工具调用、流式输出、多轮对话、检索增强支持模型通过官方或社区包接入 OpenAI、Anthropic、Google 等模型服务也可接入 OpenAI 兼容协议的本地模型服务启动方式npm 项目 Node 脚本启动可扩展 Express/Fastify 提供 HTTP API接口 API框架本身提供编程 APIHTTP 接口需要自行封装批量任务可用 Promise 并发控制实现需自行设计队列与重试适合场景AI 聊天机器人、知识库问答、Agent 自动化、内容生成、内部工具集成从表格能看出LangChain.js 不是“装完就有界面”的工具而是一个开发框架。它的价值在于把 AI 应用里重复出现的部分抽出来比如模型切换、消息格式转换、Prompt 组织、Agent 调用外部工具等。这样你的业务代码不会越写越乱模型层也被隔离在框架内部。另外要注意一点LangChain.js 和 LangChain Python 虽然同源但两边并不完全等价。很多新能力会先在 Python 生态里出现再迁移到 JS 版所以做技术选型时不要默认两边 API 一致具体以你安装版本的官方文档为准。2. 适用场景与使用边界2.1 适合谁LangChain.js 适合以下几类人写过 Node.js 后端想快速把大模型能力接进业务系统。需要在同一个应用里切换不同模型服务而不想为每家厂商单独写适配层。要做 AI Agent让模型根据用户意图自动调用工具、查询数据、执行动作。团队已经有提示词模板、对话记录、检索逻辑想把这些东西标准化管理。2.2 能解决什么问题它最直接的价值是“统一接入层”。比如你今天用 OpenAI 的模型明天想换成兼容 OpenAI 协议的本地模型只需要改环境变量和模型配置不用把业务代码里的 API 调用全部重写。Prompt 模板、Agent 工具、对话记忆这些能力也能在项目里形成可复用的模块。2.3 不适合什么场景如果只是做一次简单翻译、单轮问答直接用官方 SDK 往往更轻没必要引入框架。如果团队对依赖体积、启动速度极其敏感也要评估框架带来的抽象层是否值得。LangChain.js 是一个快速迭代的框架API 在不同版本里可能有调整生产环境必须锁版本不能无脑升级。2.4 合规与安全边界无论把 LangChain.js 接入云模型还是本地模型都要注意API Key 不能提交到 Git 仓库对话内容要按公司或项目的敏感数据规范处理如果 Agent 要调用内部系统、数据库或第三方平台必须做细粒度权限控制生成内容要设置审核机制不能直接把模型输出当作事实结果。模型输出可控性有限事实类业务不要直接面向最终用户要加人工确认或事实校验。涉及人脸、声音、版权素材或内部业务数据的 AI 应用必须确认授权范围不能拿未授权数据直接丢给大模型。3. 环境准备与前置条件3.1 基础环境LangChain.js 本身不挑硬件常规开发机就能跑。建议准备以下环境Node.js 18 以上 LTS 版本。npm 或 pnpm用来安装依赖。一个终端或 IDE。能访问你选择的模型服务公网模型或内网模型都可以。由于不需要 GPU也没有本地模型文件磁盘占用主要集中在 node_modules 和代码文件上普通项目几十到几百 MB 都很正常。3.2 准备模型 API Key要跑通示例需要一个大模型服务的 API Key。可以选 OpenAI 等云服务也可以选本地部署的大模型服务只要它提供 OpenAI 兼容接口即可。比如本地跑一个支持 OpenAI 协议的模型服务然后在代码里配置baseURL指向本地地址LangChain.js 就能把请求发过去。API Key 不要硬编码在源码里。建议统一放在环境变量文件.env中并通过dotenv加载。3.3 项目目录规划建议先建一个干净的目录方便后续扩展langchain-demo/ ├── .env ├── package.json └── src/ ├── chat.js ├── prompt.js ├── stream.js ├── memory.js ├── agent.js ├── server.js └── batch.jssrc目录下每个文件对应一个测试点后面运行和排查都更清晰。4. 安装部署与首个对话程序4.1 初始化项目并安装依赖先创建项目目录并初始化mkdir langchain-demo cd langchain-demo npm init -y然后安装核心依赖。LangChain.js 从 0.x 后期开始把模型厂商接入拆到独立子包所以安装时会同时装核心包和 OpenAI 接入包npm install langchain langchain/openai dotenvlangchain/openai负责 OpenAI 及兼容协议服务的接入langchain是核心编排包dotenv用来加载环境变量。如果你后续要用其他模型服务商再按需安装对应的接入包。4.2 创建环境变量文件在项目根目录创建.envOPENAI_API_KEY你的API_KEY OPENAI_MODELgpt-4o-mini TEMPERATURE0.7OPENAI_MODEL是可选配置用于默认模型名TEMPERATURE控制随机性。如果你接的是本地模型服务可以在代码里额外设置接口地址具体字段名根据你使用的服务来定。4.3 第一个对话调用在src/chat.js中写代码import dotenv/config; import { ChatOpenAI } from langchain/openai; import { HumanMessage } from langchain/core/messages; const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, temperature: parseFloat(process.env.TEMPERATURE || 0.7), }); const response await model.invoke([ new HumanMessage(请用一句话介绍 LangChain.js), ]); console.log(response.content);运行node src/chat.js如果配置正确终端会输出模型返回的文本。这个例子虽然短但已经覆盖了 LangChain.js 最核心的链路加载环境变量、创建模型实例、构造消息、调用模型、拿到结果。4.4 启动验证启动后如果正常输出文本说明环境没问题。如果报错优先检查 API Key 是否正确、网络是否通、模型名是否可用。后面第 8 节会展开常见问题。5. 功能测试与效果验证5.1 基础对话测试测试目的验证模型连通和调用链路的正确性。操作步骤运行node src/chat.js。预期结果终端输出一句关于 LangChain.js 的介绍。判断标准拿到文本且无异常报错基础链路通过。5.2 提示词模板测试测试目的验证提示词模板能否动态注入参数。在src/prompt.js中写代码import dotenv/config; import { ChatOpenAI } from langchain/openai; import { ChatPromptTemplate } from langchain/core/prompts; const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, }); const prompt ChatPromptTemplate.fromMessages([ [system, 你是一名{topic}技术编辑回答要简洁、专业。], [human, 请回答{question}], ]); const chain prompt.pipe(model); const result await chain.invoke({ topic: 前端工程化, question: LangChain.js 在什么场景下值得引入, }); console.log(result.content);运行node src/prompt.js预期结果模型按照 system 中设定的“技术编辑”角色回答并且回答内容围绕传入的 question。常见失败原因模板变量名不匹配{topic}和{question}必须与invoke传入的字段名一致。5.3 流式输出测试测试目的验证流式输出是否可用为后续接入聊天界面做准备。在src/stream.js中写代码import dotenv/config; import { ChatOpenAI } from langchain/openai; import { HumanMessage } from langchain/core/messages; const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, }); const stream await model.stream([ new HumanMessage(写一首关于 JavaScript 的短诗), ]); for await (const chunk of stream) { process.stdout.write(chunk.content || ); } console.log();运行node src/stream.js预期结果终端逐字或逐段出现内容而不是一次性打印全部。判断标准内容能持续输出且不中断流式链路正常。5.4 多轮对话测试测试目的验证上下文是否能通过消息数组正确传递。在src/memory.js中写代码import dotenv/config; import { ChatOpenAI } from langchain/openai; import { HumanMessage, AIMessage } from langchain/core/messages; const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, }); const messages [ new HumanMessage(请记住我的名字叫小明), ]; let response await model.invoke(messages); console.log(第一轮, response.content); messages.push(new AIMessage(response.content)); messages.push(new HumanMessage(我叫什么名字)); response await model.invoke(messages); console.log(第二轮, response.content);运行node src/memory.js预期结果第二轮回答能正确说出“小明”。关键点多轮对话不是框架自动记录的而是需要把历史消息按顺序放回 messages 数组。实际项目中可以自己管理一个会话列表或者引入持久化存储。5.5 Agent 工具调用测试测试目的验证模型能否根据用户问题自动选择并调用外部工具。在src/agent.js中写代码import dotenv/config; import { ChatOpenAI } from langchain/openai; import { HumanMessage } from langchain/core/messages; import { tool } from langchain/core/tools; import { createToolCallingAgent, AgentExecutor } from langchain/agents; import { z } from zod; const getWeather tool( async ({ city }) { return ${city}明天多云气温 18℃~26℃; }, { name: get_weather, description: 查询指定城市的天气, schema: z.object({ city: z.string().describe(城市名称), }), }, ); const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, }); const agent createToolCallingAgent({ llm: model, tools: [getWeather], }); const executor new AgentExecutor({ agent }); const result await executor.invoke({ messages: [new HumanMessage(北京今天天气怎么样)], }); console.log(result.output);运行前先安装 zodnpm install zod运行node src/agent.js预期结果模型识别到问题需要查询天气自动调用get_weather工具并返回包含城市信息的回答。重点提示Agent 相关 API 在不同版本中调整比较频繁如果导入路径或函数名不一致以你安装版本的官方文档为准。这个例子里的天气工具是模拟实现真实项目中应该接入实际的天气服务。5.6 测试结果判断与失败定位现象可能原因排查方向所有调用直接报错API Key 错误或环境变量未加载检查.env文件和dotenv配置提示词模板报变量缺失模板变量名与传入字段不一致检查{xxx}占位符和 invoke 参数Agent 不调用工具模型不支持 tool calling 或 description 不够清晰更换模型或调整工具描述输出不按预期角色回答system 提示词没有生效检查消息顺序和模板结构6. 接口 API 与批量任务6.1 用 Express 封装 HTTP 接口LangChain.js 本身不提供 HTTP Server但可以非常方便地封装成标准 API。这里用 Express 做一个简单的/api/chat接口。安装依赖npm install express在src/server.js中写代码import dotenv/config; import express from express; import { ChatOpenAI } from langchain/openai; import { HumanMessage, SystemMessage } from langchain/core/messages; const app express(); app.use(express.json()); const model new ChatOpenAI({ model: process.env.OPENAI_MODEL || gpt-4o-mini, }); app.post(/api/chat, async (req, res) { const { message, system } req.body || {}; try { const messages []; if (system) { messages.push(new SystemMessage(system)); } messages.push(new HumanMessage(message)); const response await model.invoke(messages); res.json({ content: response.content }); } catch (error) { res.status(500).json({ error: error.message }); } }); const port process.env.PORT || 3000; app.listen(port, () { console.log(LangChain.js API 服务已启动: http://127.0.0.1:${port}); });启动node src/server.js6.2 curl 调用测试接口启动后可以用 curl 验证curl -X POST http://127.0.0.1:3000/api/chat \ -H Content-Type: application/json \ -d { system: 你是一个技术科普作者, message: 用两句话介绍 LangChain.js }预期返回{ content: LangChain.js 是 LangChain 的 JavaScript 实现用于构建大模型应用。它提供了模型封装、提示词模板、Agent 工具调用等能力适合在 Node.js 环境中快速开发 AI 应用。 }判断标准HTTP 状态码 200返回结构包含content字段。接口能跑通之后就可以接到自己的前端、脚本或其他后端服务里。6.3 批量任务批量任务在 LangChain.js 里本质上是并发执行多个invoke。最简单的方式是Promise.allconst questions [ LangChain.js 和 LangChain(Python) 有什么差异, Node.js 后端接入大模型 API 要注意什么, Agent 工具调用适合什么业务场景, ]; const results await Promise.all( questions.map(async (question) { const response await model.invoke([new HumanMessage(question)]); return { question, answer: response.content }; }), ); console.log(JSON.stringify(results, null, 2));这种方式实现简单但会把所有请求同时打出去容易触发上游限流。更稳妥的方式是做一个带并发控制的批量处理函数async function mapWithConcurrency(tasks, limit, worker) { const results []; const queue [...tasks]; async function run() { while (queue.length 0) { const task queue.shift(); results.push(await worker(task)); } } const workers Array.from({ length: limit }, () run()); await Promise.all(workers); return results; } const allResults await mapWithConcurrency( questions, 2, async (question) { const response await model.invoke([new HumanMessage(question)]); return { question, answer: response.content }; }, );limit控制并发数比如 2 表示同时最多只有两个请求在跑能有效降低限流风险。6.4 失败重试大模型 API 调用可能因为网络波动、上游限流等原因失败。批量任务里建议加重试逻辑async function runWithRetry(question, retries 2) { for (let i 0; i retries; i) { try { const response await model.invoke([new HumanMessage(question)]); return { question, answer: response.content }; } catch (error) { if (i retries) { return { question, error: error.message }; } await new Promise((resolve) setTimeout(resolve, 1000 * (i 1))); } } } const results await Promise.all( questions.map((question) runWithRetry(question)), );这里采用指数退避的简化版本第一次失败等 1 秒第二次失败等 2 秒。更复杂的场景可以记录失败详情把失败任务重新投递到队列。7. 资源占用与性能观察7.1 观察维度LangChain.js 是纯 Node.js 框架本身不消耗 GPU。运行时资源主要取决于模型 API 的响应时间。并发请求数量。单次请求的输入输出 token 数量。内存中保留的对话历史长度。可以在代码里直接测量耗时和内存console.time(invoke); const response await model.invoke([new HumanMessage(测试)]); console.timeEnd(invoke); const memory process.memoryUsage(); console.log(RSS: ${(memory.rss / 1024 / 1024).toFixed(2)} MB); console.log(Heap Used: ${(memory.heapUsed / 1024 / 1024).toFixed(2)} MB);7.2 Token 使用统计很多模型响应会附带 token 使用量LangChain.js 中可以通过响应对象拿到。字段名根据模型厂商不同会有差异常见的是usage_metadata或response_metadata。第一次接入时建议先打印完整响应结构再按实际字段写统计逻辑console.log(JSON.stringify(response, null, 2));7.3 流式与非流式流式输出适合对话类产品首字延迟更低用户感知更快。非流式适合批量处理代码更简单方便做重试和结果落库。如果业务场景不要实时打字效果批量处理时建议使用非流式减少连接管理复杂度。7.4 并发控制大模型 API 普遍有速率限制。并发太高会影响稳定性和成本。常见做法单用户场景限制并发数为 1 到 3。批量任务先跑一个小样本测试观察限流响应再逐步调整并发数。长时间任务使用任务队列配合失败重试和日志记录。如果服务要暴露给外部调用建议在 HTTP 接口层加限流避免一个上游接口被过度调用。8. 常见问题与排查方法问题现象可能原因排查方式解决方案dotenv配置不生效环境变量文件路径不对或没有被加载检查项目根目录是否存在.env在入口文件最顶部import dotenv/config调用时报 401API Key 错误或已过期检查.env中的 Key 是否正确重新申请或更新 API Key报模型不存在模型名写错或当前账号无权限对照模型服务商文档检查模型名修改OPENAI_MODEL配置请求超时网络不稳定或回复过长查看日志中的超时时间增加超时时间或优化提示词控制输出长度依赖版本冲突不同包版本不兼容检查package.json中的版本范围锁定版本号重新执行npm installAgent 不调用工具模型不支持 tool calling 或工具描述不明确打印中间消息查看模型意图换支持 tool calling 的模型优化工具描述批量任务被限流并发过高或触发上游速率限制观察错误响应码降低并发数加重试和退避逻辑内存持续增长对话历史或批量结果没有释放检查消息数组是否无限增长设置对话长度上限定期清理历史9. 最佳实践与使用建议9.1 先跑通最小示例第一次接触 LangChain.js 时不要一上来就搭复杂 Agent。先把最简单的model.invoke跑通确认环境、模型服务和 API Key 没有问题再逐步引入提示词模板、流式输出和工具调用。9.2 锁定依赖版本LangChain.js 迭代比较快API 可能存在破坏性变更。生产项目建议在package.json中锁定主版本范围升级依赖时单独验证核心功能不要直接npm update。9.3 使用单元测试把提示词模板、模型调用、Agent 工具逻辑拆成独立函数方便做单元测试。模型调用部分可以 mock 返回结果这样测试不依赖真实 API也不消耗 token。9.4 日志与可观测性模型调用的输入、输出、耗时、token 使用量建议都记录下来。批量任务尤其需要日志否则任务中途失败时很难定位是哪个输入导致的。9.5 内容安全与权限控制如果 Agent 要调用内部系统必须在工具函数里做权限校验不能让用户通过自然语言绕过限制。所有生成内容在正式发布前需要人工抽查尤其是面向公众或涉及事实判断的场景。9.6 密钥与配置分离API Key、数据库连接串、内部服务地址不要写在代码里。统一用环境变量或配置中心管理并在.gitignore中排除.env文件。10. 总结与下一步LangChain.js 最值得尝试的点是它能把 AI 应用开发里的碎片化逻辑串起来。从一次模型调用开始到提示词模板、流式输出、多轮对话、Agent 工具调用再到 HTTP API 和批量任务每个环节都能在几行代码内完成。对于已经熟悉 Node.js 的团队它是一套上手成本比较低的 AI 工程化方案。建议优先验证三个功能基础对话调用、提示词模板、Agent 工具调用。这三个能力确认没问题就已经能覆盖大多数实际业务场景。最容易踩的坑有两个一是不同版本的 API 差异二是批量任务并发控制不当导致上游限流。前者靠锁版本和官方文档解决后者靠并发限制和失败重试缓解。后续可以继续扩展的方向包括接入向量数据库做 RAG 知识库问答、结合 LangSmith 做调用链追踪、用多 Agent 编排处理更复杂的业务流。先把最小示例跑起来再按真实业务需求往上加能力是 LangChain.js 项目最稳妥的推进方式。建议收藏备用动手时能省不少排错时间。