背景
相信很多小伙伴在刷 BOSS 直聘时会看到AI工程师开发岗位基本都要求掌握 LangChain.js 框架。那么LangChain.js 框架到底是什么呢? 很多岗位 JD 要求必须掌握LangChain.js。下面跟随笔者快速掌握LangChain.js。
LangChain.js 是 LangChain 的 JavaScript / TypeScript 版本,它是一个用于构建基于大语言模型(LLMs)的应用程序的开发框架。LangChain 最早是 Python 版本,后来推出了 JS 版本,以便前端和全栈开发者也能方便地构建智能应用。
各种大模型(LLMs)本身提供 HTTP/WS 等多种方式提供服务,为什么还需要使用 LangChain.js 访问大模型呢?
作用
相比直接调用大模型接口,LangChain.js 有很多优势:
- 对 Prompt 管理和链式执行很友好
- 内置 Agent 支持(调用工具)
- 对接多种数据源(RAG)
- 模块化能力强,适合构建复杂链条
- 跨平台能力好
下面详细说明这些优势
对 Prompt 管理和链式执行很友好
LangChain.js 提供 PromptTemplate 、Chain 、Memory 等模块可以让开发人员管理复杂prompt 模板、复用提示词逻辑、支持上下文记忆(这一点非常重要)、以及串联多个步骤形成链条等功能。这些开箱即用的功能让程序员将精力聚焦在业务开发上。
LangChain.js 的 PromptTemplate
是用来管理和组织 Prompt(提示词)模板的核心工具。帮助构建、复用、动态插值 prompt,非常适合构建复杂的 LLM 调用逻辑
在 AI 程序开发中,我们直接写 prompt 的格式是这样的
js
const prompt = `请写一封主题为"${topic}"的中文邮件,语气要正式。`;
这虽然简单,但在构建复杂的 AI 应用时,容易出现:多个 prompt 写重复代码,Prompt 结构不清晰,维护麻烦,变量插值不安全或不一致等问题
而使用 LangChain.js 后,可以利用它定义一个结构清晰的模板:
js
const formatted = await prompt.format({
topic: "会议通知",
tone: "正式",
});
最后的formatted结果是
txt
请写一封主题为"`会议通知`"的中文邮件,语气要正式。
上面说的是简单模板,下面看看复杂模板的例子
js
const template = `
你是一位{role}。
请根据以下任务生成内容:
任务描述:{task}
要求:
1. 语言风格:{style}
2. 字数限制:{length}字以内
请开始:
`;
const prompt = new PromptTemplate({
template,
inputVariables: ["role", "task", "style", "length"],
});
"role", "task", "style", "length"等都支持变量输入,显著提高模板准确性。上面的模板与LLMChain 联用
js
import { LLMChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
const llm = new ChatOpenAI({ temperature: 0.7 });
const chain = new LLMChain({
llm,
prompt,
});
const result = await chain.call({
role: "营销专家",
task: "推广一款新型运动饮料",
style: "轻松幽默",
length: "100",
});
这就完成了一个完整的「Prompt → 调用模型 → 返回结果」链条。
LangChain.js 中的 Chain
是整个框架的核心之一,它代表的是一个可组合、可复用的推理过程。你可以把它理解为一条「流水线」,每一步都基于上一步的结果,可以串联多个模块、多个大模型、多个工具,最终完成一个任务。
在 LangChain.js 里,Chain
是一个有输入、有输出的执行单元,通常包含以下几个部分:
- 输入(input):来自用户或上一步链条的结果
- 处理逻辑(prompt、模型调用、工具调用等)
- 输出(output):用于展示、保存、或传给下一个 Chain
Chain 的类型有很多,LLMChain 是最常用的链。使用PromptTemplate
构建提示词,喂给 AI 模型,生成结果。如下所示
js
import { LLMChain } from "langchain/chains";
import { PromptTemplate } from "langchain/prompts";
import { ChatOpenAI } from "langchain/chat_models/openai";
const prompt = new PromptTemplate({
template: "写一篇关于{topic}的科普文章,语气要{tone}。",
inputVariables: ["topic", "tone"],
});
const model = new ChatOpenAI({ temperature: 0.7 });
const chain = new LLMChain({ llm: model, prompt });
const res = await chain.call({
topic: "量子计算",
tone: "通俗易懂",
});
console.log(res.text);
SimpleSequentialChain
是顺序链,把多个 LLMChain 串起来,前一个的输出是后一个的输入。
js
import { SimpleSequentialChain } from "langchain/chains";
// chain1: 根据主题生成文章大纲
// chain2: 根据大纲生成文章内容
const chain = new SimpleSequentialChain({
chains: [chain1, chain2],
verbose: true,
});
const res = await chain.run("人工智能教育");
一步一步处理的流程,比如先写大纲 → 再扩写内容 → 再润色。
MultiPromptChain
是多 prompt 选择链,根据输入的不同选择不同prompt 来调用模型,适合场景切换。
js
// 如果你输入是"写代码",就用编码 prompt;
// 如果你输入是"写诗",就用文艺 prompt。
RetrievalQAChain
是基于知识库问答,结合向量数据库和文档检索,实现 RAG(检索增强生成)
js
import { RetrievalQAChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
const chain = RetrievalQAChain.fromLLM(model, retriever);
const res = await chain.call({
query: "ComfyUI 如何使用节点连接?",
});
ConversationalChain
是带记忆的对话链,用于实现多轮对话的上下文记忆,适用于聊天机器人
上面说了这么多内置的 Chain,实际上 LangChain.js 支持自定义 Chain,根据你的业务场景,通过继承 BaseChain 自定义链,或者组合多个 Chain、Tool、Agent构建高级流程
LangChain.js 中最后一个重要的模块是Memory模块。大家使用 ChatGPT 时经常会对一个问题进行多轮对话,小伙伴们开发这类产品时需要将多轮对话的内容传给 AI 模型,这样才利于AI 模型解决问题,而LangChain.js的Memory模块就是在多轮对话中保存和管理上下文信息,并在每次调用 LLM(大语言模型)时自动注入这些上下文内容。
在 LangChain 中,无论是 Runnable
、Chain
还是 Agent
,都可以通过 Memory 插件实现上下文记忆功能。
下面是一些常用的 Memory:
- BufferMemory 保存对话的完整历史。
- ConversationSummaryMemory 将对话内容通过 LLM 压缩为摘要,节省 token
- BufferWindowMemory 和 BufferMemory 类似,但只保留最近 N 条对话,控制上下文大小。
- ChatMessageHistory 这是一个更底层的模块,
BufferMemory
也用它来管理历史消息。可以自定义实现,比如保存到数据库、Redis 等。
通过一个例子熟悉如何使用 Memory 模块
js
import { ConversationChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
const model = new ChatOpenAI({ temperature: 0 });
const chain = new ConversationChain({ llm: model, memory });
const res1 = await chain.call({ input: "你好!" });
const res2 = await chain.call({ input: "刚刚我们聊到哪了?" });
第二次调用时,它会自动带上第一次的上下文。
内置 Agent 支持
LangChain.js 中的 Agent 是其最强大也最复杂的部分之一,允许开发人员构建可以"思考"和"行动"的智能体。这些 Agent 可以根据用户输入自动选择合适的工具(Tools)来执行任务,是实现 AI 助理、RPA、智能搜索等高级功能的关键。
在LangChain.js中,Agent 是一种可以 动态选择工具并调用它们来完成任务 的架构。它不是一段静态的 Chain,而是一个具有决策能力的系统。它会分析输入 → 决定用哪个工具 → 使用工具获得结果 → 再判断是否继续。
Agent 的核心组成部分:
- LLM(大语言模型) :负责思考与决策
- Tools(工具) :可以调用的实际功能,比如搜索、计算、数据库查询等
- AgentExecutor:驱动 Agent 运行的引擎
- Memory(可选) :用于保存历史,提高上下文智能
下面以 ZeroShotAgent
举例演示如何构建简单的 Agent
js
import { initializeAgentExecutorWithOptions } from "langchain/agents";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { Calculator } from "langchain/tools/calculator";
const model = new ChatOpenAI({ temperature: 0 });
const tools = [new Calculator()];
const executor = await initializeAgentExecutorWithOptions(tools, model, {
agentType: "zero-shot-react-description",
});
const result = await executor.call({ input: "What is 25% of (456 * 34)?" });
console.log(result.output);
上面是一个简单的推理 Agent。有关 Agent 更多使用内容,请阅读官方文档
对接多种数据源(RAG)
RAG 是 Retrieval-Augmented Generation 的缩写,中文常翻译为"检索增强生成"。它是一种结合了信息检索和**生成式 AI(如大型语言模型)**的技术,广泛用于构建问答系统、文档助手、知识库问答等应用。
传统大模型(如 GPT)是"封闭式"的:它只能回答它训练数据中包含的信息。而 RAG 增强了这个过程:
- Retrieval(检索):首先从一个外部知识库(可以是文档、数据库、网页等)中,根据用户的问题检索出最相关的内容。
- Augmented(增强) :把检索到的内容作为上下文输入,拼接到用户的问题前,一起交给语言模型处理。
- Generation(生成) :模型结合上下文内容,生成更加准确、有依据的回答。
多数据源是什么呢?在现实生活中,我们的知识来方方面面,包括不限于:
- 文档(PDF、Markdown、TXT)
- 数据库(MySQL、MongoDB 等)
- API 数据(如天气、股票、内部业务系统)
- 向量数据库(Pinecone、Weaviate、Supabase 等)
- 云存储(如 Notion、Google Drive、S3)
- ... 等等
LangChain.js 对接多种数据源是说 LangChain.js 从多个不同的数据源中并行或统一检索信息,整合为上下文,让模型回答更全面。
对接多种数据源会用到下列组件:
- Retriever 检索器,从某个数据源中检索文档
- VectorStore 向量数据库,用于相似度搜索
- DocumentLoader 数据加载器,从不同格式中读取文档
- Chain 串联多个组件形成问答流程
- MultiRetriever 支持多个 Retriever 的组合(LangChain 的高级特性)
比如从各类文档中检索数据
js
import { PDFLoader } from "langchain/document_loaders/fs/pdf";
const loader = new PDFLoader("file.pdf");
const docs = await loader.load();
从数据库中检索数据
js
import mysql from "mysql2/promise";
const connection = await mysql.createConnection({ host, user, password, database });
const [rows] = await connection.execute("SELECT * FROM knowledge_base");
const docs = rows.map(row => ({
pageContent: row.content,
metadata: { source: "mysql", id: row.id }
}));
从 Web/API 中检索数据
js
import axios from "axios";
const res = await axios.get("https://api.com/data");
const docs = res.data.items.map(item => ({
pageContent: item.description,
metadata: { source: "api", id: item.id }
}));
将上面的数据源通过嵌入模型、构建向量库
js
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
const allDocs = [...docsFromPDF, ...docsFromMySQL, ...docsFromAPI];
const vectorStore = await MemoryVectorStore.fromDocuments(allDocs, new OpenAIEmbeddings());
const retriever = vectorStore.asRetriever();
最后构建RAG流程
js
import { RetrievalQAChain } from "langchain/chains";
const chain = RetrievalQAChain.fromLLM(openai, multiRetriever);
const res = await chain.call({ query: "关于A和B的知识是什么?" });
console.log(res.text);
对接多种数据源主要解决什么问题?
因为每个LLM的训练的知识不是最新的,如果要获取今天或者昨天的数据,大模型不能提供,那么通过LangChain.js 去网络中搜索对应的知识,进行向量化、再思考优化回复问题,这样做到闭环
模块化能力强,适合构建复杂链条
笔者前面讲述了LangChain.js 的prompt 模版、Chain 和对接多数据源,可以发现这些都是 LangChain.js 提供的各种模块做的,所以说LangChain.js的模块化能力强。
LangChain.js 提供了很多"独立的功能模块",各个功能模块都解耦独立,可以像拼积木一样任意组合、替换、嵌套,来构建自己的 AI 工作流。
LangChain.js 常见的"独立的功能模块"如下:
模块名 | 作用 |
---|---|
LLM |
调用大语言模型(如 OpenAI、Claude、LLama) |
PromptTemplate |
生成提示词模板 |
Chain |
串联模块形成"处理链" |
Retriever |
用于从向量库等中检索文档 |
Memory |
记录对话历史等上下文 |
Tool |
插件能力,可调用 API、函数等 |
Agent |
智能体,拥有思考和调用工具的能力 |
VectorStore |
向量数据库(如 Pinecone、Weaviate) |
DocumentLoader |
加载不同格式数据为文档 |
根据自己的产品业务,选择不同的模块进行拼接,搭建出 AI 应用
跨平台能力好
LangChain.js 的跨平台能力非常强,这是它相较于 Python 版本的一个突出优势。它能够在 Web 前端、Node.js 服务端、移动端甚至 Serverless 环境中灵活运行,为开发 AI 产品(如网页 AI 助理、移动应用、浏览器插件等)提供了极大的便利。
我们知道很多 AI 工具都是用 Python 写的,相关的生态工具也是 Python 写的。LangChain.js 完全使用 TypeScript/JavaScript 编写,没有 Python 库依赖,不需要额外环境配置。适合前端开发者直接上手,尤其是做 MPA、SPA、PWA、小程序、Expo和 Electron等,非常适合前端开发人员使用
下面是LangChain.js支持的运行环境
平台 | 说明 |
---|---|
Node.js | 最主要平台,支持大部分功能 |
浏览器 (Web) | 支持运行在浏览器中(无后端) |
移动端 (React Native, Expo) | 可用,依赖 fetch 和一些 polyfill |
Edge / Serverless (Vercel, Cloudflare Workers) | 函数部署轻松 |
Bun / Deno | 因为 JS 本身特性,也能支持一些使用 |
LangChain.js 使用场景
- 构建智能问答系统(例如 ChatGPT 接入企业知识库)
- Agent 应用(模型会调用搜索、数据库、API)
- 多轮对话系统(例如客服机器人)
- 智能总结、翻译、内容生成
实战
接下来笔者以一个完整的小项目体现 LangChain.js 的运用。用 LangChain.js 设计天气推送机器人 AI Agent,从 0 到 1 设计一个完整的智能体系统,既可以每天获取天气信息,又能通过邮件推送,完全自动化。
架构设计
- 配置和风天气 API
- 用大模型生成播报文本
- 邮件发送
- 总调度器 + 定时任务
配置和风天气 API
第三方天气API很多,笔者在这里选用的是和风天气的API。和风天气是一个非常稳定好用的天气 API 平台,适合开发天气查询、天气推送、气象分析等功能。

进入官网注册账户后,在「控制台」中申请 API Key,每个 Key 有不同的权限范围。我们选用今日天气预报。接口路径如下
bash
/v7/weather/now
除此之外,你还需要配置your_api_host
。最后完整的 getWeather.js 内容如下
js
export async function getWeather() {
try {
const res = await fetch(
"https://mh6fr67wbe.re.qweatherapi.com/v7/weather/now?location=101200105&lang=en",
{
method: "GET",
headers: {
"X-QW-Api-Key": "your Api-Key",
},
}
).then((res) => res.json());
if (res.code === "200") {
return {
text: res?.now?.text,
temp: res?.now?.temp,
};
}
return {};
} catch (error) {
console.error("Error fetching weather data:", error);
return {};
}
}
其中 X-QW-Api-Key 是你的 API_KEY
用大模型生成播报文本
我们使用 LangChain.js 封装星火大模型去生成播报文本。
js
// ChatSpark.js
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
import crypto from "crypto";
import WebSocket from "ws";
export class ChatSpark extends BaseChatModel {
constructor(fields) {
super(fields);
this.appId = fields.appId;
this.apiKey = fields.apiKey;
this.apiSecret = fields.apiSecret;
this.temperature = fields.temperature ?? 0.5;
this.maxTokens = fields.maxTokens ?? 1024;
}
_llmType() {
return "spark";
}
async _call(messages) {
const prompt = this.formatMessages(messages);
return await this.callSpark(prompt);
}
formatMessages(messages) {
return messages.map((msg) => {
if (msg._getType() === "human") {
return { role: "user", content: msg.content };
} else {
return { role: "assistant", content: msg.content };
}
});
}
async callSpark(messages) {
return new Promise((resolve, reject) => {
const host = "spark-api.xf-yun.com";
const path = "/v4.0/chat";
const date = new Date().toUTCString();
const signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${path} HTTP/1.1`;
const signatureSha = crypto
.createHmac("sha256", this.apiSecret)
.update(signatureOrigin)
.digest("base64");
const authorization = `api_key="${this.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signatureSha}"`;
const authorizationBase64 = Buffer.from(authorization).toString("base64");
const url = `wss://${host}${path}?authorization=${authorizationBase64}&date=${encodeURIComponent(
date
)}&host=${host}`;
const ws = new WebSocket(url);
let result = "";
ws.on("open", () => {
const payload = {
header: {
app_id: this.appId,
},
parameter: {
chat: {
domain: "4.0Ultra",
temperature: this.temperature,
max_tokens: this.maxTokens,
},
},
payload: {
message: {
text: messages,
},
},
};
ws.send(JSON.stringify(payload));
});
ws.on("message", (data) => {
const resData = JSON.parse(data.toString());
const choices = resData.payload?.choices?.text || [];
for (const item of choices) {
result += item.content;
}
if (resData.header?.status === 2) {
ws.close();
resolve(result);
}
});
ws.on("error", reject);
ws.on("close", () => {});
});
}
}
启动文件代码如下
js
// bootstrap.js
import { ChatSpark } from "./ChatSpark.js";
import { HumanMessage } from "@langchain/core/messages";
import nodemailer from "nodemailer";
import { getWeather } from "./getWeather.js";
const APP_ID = "your APP_ID";
const API_KEY = "your API_KEY";
const API_SECRET = "your API_SECRET";
const chat = new ChatSpark({
appId: APP_ID,
apiKey: API_KEY,
apiSecret: API_SECRET,
temperature: 0.5,
});
async function bootstrap() {
const { text, temp } = await getWeather();
const prompt = `今天天气如下:气温是${JSON.stringify(
temp
)}、状态是${text}。请用简洁、亲切的语气,为用户生成一段天气播报(中文)`;
const answer = await chat._call([new HumanMessage(prompt)]);
console.log("answer", answer);
emailPush(answer);
}
bootstrap();
邮件服务
node.js 社区提供一个 nodemailer 功能模块。用于邮件推送服务,笔者选用网易邮箱进行发送,根据要求配置网易邮箱。代码如下
js
async function emailPush(htmlContent) {
const user = "user email";
const transporter = nodemailer.createTransport({
host: "smtp.163.com",
port: 587,
secure: true,
auth: {
user,
pass: "your pass",
},
});
const subject = getSubject();
const info = await transporter.sendMail({
from: user,
to: "user email",
subject,
html: htmlContent,
});
console.log("Message sent: %s", info.messageId);
}
function getSubject() {
const years = new Date().getFullYear();
const month = new Date().getMonth() + 1;
const day = new Date().getDate();
return `${years}年${month}月${day}天气预报`;
}
总调度器 + 定时任务
笔者这里为了简单,直接利用 GitHub Action 执行定时任务
yml
name: Run Every Day
on:
workflow_dispatch:
schedule:
- cron: "0 23 * * *"
jobs:
upcoming_movies:
runs-on: ubuntu-24.04
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: "20"
- name: Install dependencies
run: npm install --legacy-peer-deps
- name: Start
run: npm run start
因为GitHub Action用的是UTC 时间,中国在东八区,设置的23 也就是北京时间早上7点
结果如下

总结
LangChain.js 是做AI应用开发必备技能,提供很多开箱即用的功能模块,可以像搭乐高一样搭建 AI 应用