LangChain.js 实战指南:从模型调用到Agent工具调用,轻松构建AI应用 📅 发布时间:2026/8/30 9:49:33 👁 浏览次数: 有人说2025 年之后做 AI 应用开发还只会“调一次大模型接口”是不够的。这个判断基本成立。原因不复杂当你的应用只做一次问答时直接调 OpenAI API 或其他模型接口完全够用。但一旦进入真实业务你很快就会遇到一连串问题怎么管理多轮对话的上下文怎么让模型调用外部工具怎么把多个模型调用组合成一个稳定的流程怎么做流式输出、错误重试、链路追踪这些问题如果全部靠手写代码量会迅速失控而且每个项目都要重复造一遍轮子。LangChain.js 在这个背景下出现它的定位不是“又一个模型封装库”而是把大模型应用开发中的通用环节抽象成标准模块。本文会用完整可运行的代码带你从零搭建一个 LangChain.js 项目理解模型调用、提示词模板、消息历史、Agent 工具调用这几条核心链路并指出实际工程中容易踩坑的地方。读完这篇文章你能获得什么第一理解 LangChain.js 的核心概念和适用边界第二完成 Node.js 环境下的项目搭建第三跑通最小问答、多轮对话、Agent 调用工具三个完整示例第四掌握基本的排错方法和工程化建议。1. 为什么 AI 应用开发现在需要 LangChain.js先看一个真实场景。假设你的产品要做一个“企业知识库问答助手”用户提问后由大模型基于文档内容回答。如果不用任何框架你的开发流程大概是这样的读取文档做切分和向量化。把用户问题转成向量在向量数据库中检索相似片段。把检索结果拼进 Prompt调用大模型。拿到回复后再决定是否要继续追问或者调用某个内部接口查询数据。如果用户连续提问还要维护每轮对话的历史消息。这套流程在第一个版本里能跑通但问题很快会出现检索逻辑、Prompt 构造、模型调用、工具调用、历史管理全部耦合在一起。今天替换模型要改调用层明天增加检索策略要改业务层后天加一个工具还要重新梳理消息格式。代码没有边界团队协作就会变成灾难。LangChain.js 提供的正是这一层的“约定”和“抽象”。它把上面这些步骤分别对应为模型封装统一不同模型的调用方式。提示词模板可复用、可参数化的 Prompt。消息对象用标准结构表达用户输入、模型输出、系统指令。链式组合把多个步骤拼接成一条可执行的流水线。工具与 Agent让模型在需要时主动调用外部能力。用一句话概括LangChain.js 想解决的是大模型应用开发中“代码组织”和“流程编排”的问题而不是解决模型本身的能力问题。模型的智能上限仍由你选择的基础模型决定框架负责把模型接入业务系统这件事变得更可控。当然它并不是万能药。如果你的应用只有一个“输入 Prompt、输出文本”的简单需求直接调用 SDK 更轻量没有必要引入框架。但如果你在做多步骤、多工具、需要维护对话状态的应用LangChain.js 的收益会非常明显。2. LangChain.js 核心概念与设计哲学在写代码之前先建立几个基本概念。第一次接触 LangChain.js 的人最容易困惑的是“它到底包含哪些东西”。这里不需要记全所有类名先抓住四个核心模型。2.1 Message模型对话的基本单位LangChain.js 里大模型的输入和输出被统一抽象为 Message 对象。常见的有SystemMessage系统指令用来设定模型角色、回答规则。HumanMessage用户发送的消息。AIMessage模型返回的消息在多轮对话中会作为历史上下文继续传回模型。这个设计的意义在于不管底层接的是 OpenAI、Anthropic、通义千问还是本地部署的模型上层都统一使用这套消息结构。你可以把 Message 理解为不同模型之间的“通用语言”。2.2 PromptTemplate把提示词变成可复用模板直接拼接字符串写 Prompt 也能用但项目复杂后你会希望提示词像代码一样可以被复用、被测试、被版本管理。PromptTemplate 就是干这个事的。它允许你定义一个带变量的模板运行时传入参数即可生成最终 Prompt。这样提示词的调整可以集中在模板文件里而不是散落在各个业务代码的拼接逻辑中。2.3 Chain 与 pipe流程编排的最小单元LangChain 的核心思想之一是“链”即把多个步骤串联起来。在 LangChain.js 中最直观的组合方式是用pipe方法const chain prompt.pipe(model);这行代码的意思是先执行prompt生成消息再把消息传给model得到回复。你可以把它理解成一个函数管道前一步的输出是后一步的输入。这种设计让代码变得非常清晰每一步都是独立的替换或调整某一步时不影响其他环节。2.4 Tool 与 Agent让模型从“会说话”变成“能办事”纯粹的对话模型只能生成文本无法访问外部系统。但很多场景需要模型“知道”当前时间、查询数据库、调用接口、执行计算。LangChain.js 允许你定义一个 Tool工具它包含名称、描述和实际执行函数。Agent 则是一个决策器模型根据用户问题决定是否需要调用工具、调用哪个工具、如何解读工具返回的结果。一个容易误解的地方是Agent 并不是一个特立独行的实体它仍然是大模型加一套循环控制逻辑。模型在每一步判断“我是否还需要工具”直到它认为自己能给出最终答案为止。2.5 Memory对话状态的保存方式模型本身没有“记忆”。所谓多轮对话实际上是把之前的所有消息重新发送给模型。Memory 模块负责保存和整理这些历史消息。LangChain.js 提供了多种记忆实现最简单的就是使用消息数组。但在生产环境中通常需要把历史会话存到 Redis 或数据库中而不是放在内存里。这一点后面会专门说明。2.6 核心模块对比概念作用类比Message统一模型输入输出的消息结构前后端通信的 DTOPromptTemplate可复用的提示词模板代码中的函数Chain / pipe串联多个处理步骤流水线作业Tool封装外部能力供模型调用给模型提供的一组 APIAgent根据任务决定调用哪些工具主管分配任务给员工Memory保存多轮对话上下文会话缓存3. 环境准备与项目搭建这一节我们开始动手。演示环境以 macOS / Linux / Windows 均可重点代码保持一致。3.1 安装 Node.jsLangChain.js 运行在 Node.js 环境建议使用 Node.js 18 及以上版本。较新的版本对 ESM 模块、原生 fetch 支持更友好可以减少不少兼容性问题。检查本机版本node -v npm -v如果版本过低建议先升级 Node.js 再继续。3.2 初始化项目创建一个目录并初始化 npm 项目mkdir langchain-demo cd langchain-demo npm init -y在package.json中加入type: module这样代码里可以直接使用import语法{ name: langchain-demo, version: 1.0.0, type: module, scripts: { start: node src/index.js } }3.3 安装核心依赖安装 LangChain.js 相关的几个包npm install langchain/openai langchain/core langchain/langgraph这里对依赖做一点说明langchain/openaiOpenAI 模型的接入封装也兼容使用 OpenAI 格式的第三方模型服务。langchain/core核心抽象包括 Message、PromptTemplate、Tool 等基础类型。langchain/langgraph用于构建 Agent 的编排库新版 LangChain.js 的 Agent 推荐基于 LangGraph 实现。3.4 配置环境变量项目需要读取 API Key。新建.env文件OPENAI_API_KEY你的APIKey在代码中想要自动加载.env文件可以安装dotenvnpm install dotenv然后在入口文件第一行引入import dotenv/config;需要提醒的是.env文件不能提交到 Git 仓库。建议创建.gitignore并加入.env、node_modulesnode_modules/ .env3.5 接入 OpenAI 兼容服务如果你使用的是国内模型的 OpenAI 兼容接口不需要改变代码逻辑只需要在初始化模型时指定baseURL。例如某兼容服务的接入方式如下import { ChatOpenAI } from langchain/openai; const model new ChatOpenAI({ model: 你的模型名称, apiKey: 你的APIKey, configuration: { baseURL: https://你的服务地址/v1, }, });这个设计是 LangChain.js 的一个优点模型服务是可替换的。你只需要修改配置业务代码无需大规模调整。4. 第一个 LangChain.js 程序模型调用与基础链路现在开始写第一个可运行的程序。我们的目标很简单让模型回答一个问题然后把答案打印到终端。4.1 最小模型调用创建src/basic.js文件import dotenv/config; import { ChatOpenAI } from langchain/openai; const model new ChatOpenAI({ model: gpt-4o-mini, temperature: 0.7, }); const response await model.invoke(用一句话介绍 LangChain.js); console.log(response.content);运行node src/basic.js预期结果是打印出一句关于 LangChain.js 的介绍。这段代码虽然短但已经涵盖了 LangChain.js 最核心的调用方式创建一个模型对象调用invoke传入输入得到输出。temperature控制回答的随机性数值越大回答越发散数值越小越稳定如果做分类、抽取类任务建议设成 0。4.2 使用 PromptTemplate 管理提示词把提示词写死在业务代码里短期没问题。但当你需要调整角色设定、补充 few-shot 示例或者同一个模型要服务多种场景时模板化的好处就会体现出来。创建src/with-prompt.jsimport dotenv/config; import { ChatPromptTemplate } from langchain/core/prompts; import { ChatOpenAI } from langchain/openai; const prompt ChatPromptTemplate.fromMessages([ [system, 你是一位资深的技术博主擅长用通俗易懂的语言解释技术概念。], [human, 帮我写一段关于 {topic} 的简短介绍控制在 200 字以内。], ]); const model new ChatOpenAI({ model: gpt-4o-mini, temperature: 0.5, }); const chain prompt.pipe(model); const result await chain.invoke({ topic: LangChain.js, }); console.log(result.content);运行方式相同node src/with-prompt.js这里的核心变化是prompt.pipe(model)。它把“生成提示词”和“调用模型”两个步骤组成了一个链。后续如果要在生成提示词之后加一个格式校验、加一个检索步骤都可以在这条链上继续扩展。需要注意temperature、maxTokens等模型参数属于模型配置应该在模型创建时设置而提示词内容属于业务配置应该收敛在 PromptTemplate 中。两者不要混在一处修改。5. 实现多轮对话从消息历史到 Memory单次调用只能处理一条用户消息但真实聊天助手显然需要上下文。这一节先说明模型是怎么“记住”上下文的再给出可运行的多轮对话示例。5.1 模型的“记忆”本质大模型本身没有记忆。你感觉它记得上一轮说过的话是因为你的代码把之前所有的消息又原样发送了一次。因此多轮对话的核心工作就是管理好历史消息列表。LangChain.js 中的标准做法是构造一个 Message 数组按顺序放入系统消息、用户消息、模型回复然后整体传给模型。5.2 多轮对话示例创建src/chat.jsimport dotenv/config; import { ChatOpenAI } from langchain/openai; import { HumanMessage, AIMessage, SystemMessage } from langchain/core/messages; const model new ChatOpenAI({ model: gpt-4o-mini, temperature: 0.7, }); const messages [ new SystemMessage(你是一位耐心的编程学习助手回答要简洁。), new HumanMessage(我正在学习 LangChain.js你觉得我第一步应该做什么), new AIMessage(建议先从一个最小调用开始跑通模型返回结果的基础链路。), new HumanMessage(那你能直接给我一个最小示例吗), ]; const response await model.invoke(messages); console.log(response.content);运行node src/chat.js在真实项目中messages数组里的内容来自每次请求的历史会话。服务端需要把每个用户的历史记录存下来而不是每次都在内存里临时拼装。严格来说上面这段代码只是用 Message 数组实现了上下文传递。LangChain.js 还提供更高级的Memory模块可以自动处理消息的追加、截断和摘要适合对话轮数很多的场景。不过了解底层消息结构仍然是第一步因为所有的 Memory 方案最终都会转换回 Message 数组。6. Agent 与工具调用让模型真正“能做事情”如果说前两节的内容是“语言问答”这一节就是“智能体应用”。Agent 是 LangChain.js 中受到最多关注的部分也是它与普通 SDK 封装拉开差距的地方。6.1 工具的价值模型不知道当前时间、不能执行精确计算、无法查询业务系统。要补上这些能力就需要把外部功能封装成工具。一个工具由三部分组成名称、描述、执行函数。名称告诉模型这个工具叫什么描述说明它在什么情况下使用执行函数是真正跑代码的逻辑。描述写得好不好直接影响模型调用工具的准确率。6.2 定义一个自定义工具这里我们先做一个最小工具计算字符串长度。创建src/tool.jsimport { DynamicTool } from langchain/core/tools; const stringLengthTool new DynamicTool({ name: string_length, description: 计算字符串的字符数量。当用户需要知道某段文本有多少个字符时使用这个工具。输入参数是一个字符串。, func: async (input) { return String(input).length.toString(); }, });DynamicTool的好处是无需自定义类直接传入函数即可适合快速验证。如果是正式项目推荐自定义一个继承自Tool的类便于做参数校验和日志埋点。6.3 构建最小 ReAct Agent创建src/agent.jsimport dotenv/config; import { ChatOpenAI } from langchain/openai; import { DynamicTool } from langchain/core/tools; import { createReactAgent } from langchain/langgraph/prebuilt; import { HumanMessage } from langchain/core/messages; const stringLengthTool new DynamicTool({ name: string_length, description: 计算字符串的字符数量。当用户需要知道某段文本有多少个字符时使用这个工具。输入参数是一个字符串。, func: async (input) { return String(input).length.toString(); }, }); const agent await createReactAgent({ llm: new ChatOpenAI({ model: gpt-4o-mini, temperature: 0, }), tools: [stringLengthTool], }); const result await agent.invoke({ messages: [ new HumanMessage(请使用 string_length 工具计算 LangChain.js 有多少个字符。), ], }); const lastMessage result.messages[result.messages.length - 1]; console.log(lastMessage.content);运行node src/agent.js预期输出类似LangChain.js 共有 13 个字符。6.4 Agent 的执行过程这段代码看起来很短但它背后经历了一个完整的循环用户消息被传给模型。模型判断需要调用string_length工具。框架执行工具得到返回结果。模型拿到工具结果生成最终回答。这个“模型决策—调用工具—观察结果—继续决策”的循环就是 ReAct 模式的核心逻辑。createReactAgent帮我们封装了循环控制我们只需要提供模型和工具列表。如果模型返回答案但明显不对可以从两个方向排查第一工具描述写得不够清晰导致模型不知道什么时候该调用它第二temperature设置过高模型在判断路径时产生了随机性。7. 常见问题与排查思路LangChain.js 发展速度快API 也在迭代实际运行中遇到的问题通常集中在下面几类。这里整理成表格方便你对照排查。问题现象可能原因排查方式解决方案请求报 401 错误API Key 未配置或配置错误检查.env文件和process.env输出确认 Key 是否有效是否配置了正确的环境变量请求报 404 错误baseURL 或模型名称不正确对比模型服务文档校准 baseURL 路径确认为/v1结尾中文输出乱码终端编码问题查看终端字符集设置在部分终端中需要设置 UTF-8或运行前执行chcp 65001Agent 不调用工具工具描述不清晰或模型不支持工具调用打印模型中间消息观察模型决策重写描述补充触发场景或更换支持 tool calling 的模型多轮对话上下文混乱消息列表顺序或角色有误打印messages数组检查顺序确认顺序为 System - Human - AI - Human...调用超时网络或服务响应过慢查看服务端状态和网络日志设置更大的超时时间或实现重试机制npm 安装依赖失败Node 版本过低或网络问题查看 npm 错误日志升级 Node 版本或更换 npm 镜像源一个有效的排查技巧是不要只看最终报错先打印中间过程。尤其是在 Agent 链路中通过输出result.messages的完整内容可以清晰看到模型每一步的思考、工具调用和工具返回问题通常一眼就能定位。8. 最佳实践与工程建议把示例程序跑通只是第一步。真正把 LangChain.js 用到生产环境下面这些建议值得提前了解。8.1 API Key 安全管理不要在代码中硬编码 API Key不要把.env文件提交到 Git 仓库。生产环境推荐使用密钥管理服务或容器平台的环境变量注入能力。同时建议为不同的应用场景申请独立的 Key方便按项目控制用量和权限。8.2 错误处理与重试大模型接口是典型的不可靠外部依赖网络抖动、限流、超时都可能发生。生产代码中必须对模型调用做异常捕获并根据错误类型决定是否重试。try { const response await model.invoke(你好); console.log(response.content); } catch (error) { console.error(模型调用失败, error.message); }重试时要注意退避策略避免并发大量请求时加重服务端压力。最稳妥的做法是用指数退避加最大重试次数限制。8.3 成本控制大模型按 Token 计费多轮对话的历史消息越长单次请求消耗越大。工程上常见的做法有只保留最近 N 轮消息过期消息丢弃。对太长的历史做摘要压缩。同一会话内缓存重复的模型回复。区分任务使用不同规格的模型简单任务用轻量模型复杂任务用更强模型。8.4 日志与可观测性AI 应用的调试难点在于同样的输入模型可能返回完全不同的输出。因此日志记录要覆盖完整的链路数据输入消息、使用的 Prompt、模型名称、Token 消耗、返回结果、耗时、是否调用了工具。建议在模型调用外层包一层统一的拦截器把上面这些字段写入日志系统。没有链路灯塔AI 应用出问题后几乎没法排查。8.5 不要在生产环境使用内存 Memory示例代码中的消息数组都保存在内存里进程重启就会丢失。生产环境的多用户会话应该把历史消息持久化到 Redis、PostgreSQL 或 MongoDB 中并按用户会话维度读取。8.6 模型选型与升级策略LangChain.js 的模型抽象让你可以较方便地替换底层模型但这不代表切换无成本。不同模型在工具调用能力、中文表现、稳定性上有差异切换前要用一套固定的测试用例做回归对比。8.7 测试策略不要只做“能跑通”的测试。对 AI 应用建议增加三类测试输入结构测试确保工具参数格式正确。输出格式测试确保模型返回了符合预期的结构。回归测试用固定的问题集验证核心能力没有退化。9. 总结与后续学习方向这篇文章到这里已经把 LangChain.js 从概念到实践梳理了一遍。核心链路就是四条模型调用、提示词模板、多轮消息、Agent 工具调用。跑通这四个示例你就具备了继续深入的基础。回到开头那个判断LangChain.js 真正解决的不是“模型能不能回答”而是“AI 应用怎么工程化”。它用 Message 统一了对话结构用 PromptTemplate 收敛了提示词管理用 pipe 组合了处理链路用 Tool 和 Agent 打通了模型与外部系统的连接。如果你接下来想继续深入学习建议按这个顺序走先彻底掌握 Message 和 PromptTemplate再研究 LangGraph 的状态图编排然后实践 RAG检索增强生成最后再探索多 Agent 协作。每走一步都回到真实项目里验证不要停留在跑通 Demo 的层面。建议收藏这篇文章将来搭 LangChain.js 项目时可以直接照着第三节到第六节的代码起步。