2023 年以来,随着大模型(LLM)技术的爆发式发展,AI 正在从“玩具”走向“工具”,越来越多的开发者开始尝试将语言模型集成到自己的产品中。但直接调用 API 往往只是第一步——真正难的是如何让 AI 的行为可控、可预测、可复用、可维护。
这时候,一个名为 LangChain 的框架进入了我们的视野。
它不是最火的,却可能是当前最成熟的 AI 应用开发框架。今天我们就以实际代码为引子,带你一步步理解 LangChain 的核心思想与实战技巧,深入其背后的设计哲学。
一、什么是 LangChain?lang + chain = ?
很多人第一次听到这个名字都会疑惑:“Lang” 是语言,“Chain” 是链条,合起来是“语言链”?
其实更准确的理解是:
- Lang:代表 Language Model(语言模型),也就是我们常说的大模型如 GPT、DeepSeek 等;
- Chain:代表“链式结构”,即把多个处理步骤像管道一样连接起来,形成一条完整的执行流程。
所以,LangChain = 使用语言模型构建可编排的工作流系统。
它的目标很明确:把复杂的 AI 业务拆解成一个个小而清晰的模块,并通过“链”的方式组织它们,最终实现工程化的 AI 应用开发。
这就像前端中的 React 组件化思维 —— 不再写一整块逻辑,而是设计一个个高内聚、低耦合的功能单元。
二、为什么需要 LangChain?原生调用 LLM 够用吗?
假设你正在做一个前端知识问答机器人,用户问:“什么是闭包?” 你想让它先详细解释,再总结成三个要点。
如果只用原生 API 调用,你会怎么写?
const res1 = await fetch('/api/llm', {
method: 'POST',
body: JSON.stringify({ prompt: '请解释什么是闭包...' })
});
const explanation = await res1.json();
const res2 = await fetch('/api/llm', {
method: 'POST',
body: JSON.stringify({ prompt: `总结以下内容为三点:${explanation}` })
});
const summary = await res2.json();
问题来了:
- 流程散落在各处,难以复用;
- 错误处理复杂;
- 中间数据传递不清晰;
- 模型切换成本高(比如换 DeepSeek 到 Qwen);
- 提示词无法统一管理。
而 LangChain 的出现,正是为了解决这些“胶水代码”带来的混乱。
三、LangChain 核心理念:一切皆 Runnable
LangChain 最核心的设计思想是:所有操作都应该是“可运行的”(Runnable)。
这意味着无论是提示词模板、模型调用、后处理函数,还是整个工作流,都可以被 .invoke() 执行,也可以通过 .pipe() 连接。
这种设计带来了极大的灵活性和组合性。
在langchain中,各个多个模块紧密联系
下面我们通过几个实际案例,层层递进地讲解 LangChain 的关键能力。
四、案例一:使用 Chain 构建多步工作流(Pipeline)
我们来看第一个文件 1.js,它的目标是完成这样一个任务:
用户输入一个前端概念 → 让 AI 先详细解释 → 再自动提炼成三个核心要点。
这个过程天然分为两个阶段,我们可以将其抽象为两个“节点”:
- 生成详细解释
- 提取核心要点
第一步:定义 Prompt 模板
const examplePrompt = PromptTemplate.fromTemplate(`
你是一个前端专家。
请详细介绍以下概念:{topic},
要求:覆盖定义、原理、使用方式,不超过300字。
`);
这里用了 PromptTemplate,它是 LangChain 提供的提示词模版工具。好处是:
- 支持变量注入(如
{topic}); - 可复用、可测试;
- 易于国际化或多语言支持。
接着我们创建第二个模板用于总结:
const summatyPrompt = PromptTemplate.fromTemplate(`
请将以下前端概念解释总结为三个核心要点(每点不超过20字):
{explanation}
`);
第二步:绑定模型,形成可执行链
const modal = new ChatDeepSeek({
model: 'deepseek-reasoner',
temperature: 0.7
});
const explanationChain = examplePrompt.pipe(modal);
const summaryChain = summatyPrompt.pipe(modal);
.pipe() 就像是 Unix 的管道操作符 |,表示前一个节点的输出作为下一个节点的输入。
此时,explanationChain 就是一个完整的“提示词 → 模型”的可运行对象,可以直接调用:
const result = await explanationChain.invoke({ topic: '闭包' });
console.log(result.content); // 输出关于闭包的详细解释
第三步:串联成完整工作流
现在我们要把两步串起来。LangChain 提供了 RunnableSequence 来实现顺序执行:
const fullChain = RunnableSequence.from([
(input) => explanationChain.invoke({ topic: input.topic }).then(res => res.text),
(explanation) => summaryChain.invoke({ explanation }).then(res => `知识点:${explanation} 总结:${res.text}`)
]);
注意这里的写法:
- 数组中的每一项都是一个异步函数;
- 上一步的结果会自动传给下一步;
- 最终返回的是一个全新的、可调用的
Runnable实例。
最后调用:
const response = await fullChain.invoke({ topic: '什么是闭包' });
console.log(response);
✅ 这就是 Chain 的价值:将复杂逻辑封装成一条流水线,对外暴露简洁接口。
五、案例二:Output Parser —— 让 AI 输出结构化数据
虽然 LLM 很强大,但它本质是个“文本生成器”。当我们希望它返回 JSON 数据时,往往会出现格式错误、字段缺失等问题。
例如,我们需要 AI 返回某个前端概念的结构化信息:
interface FrontendConcept {
name: string;
core: string;
usecase: string[];
difficulty: '简单' | '中等' | '复杂';
}
怎么办?靠人工解析?当然不行!
LangChain 提供了强大的 Output Parser 机制,配合 Zod 这样的校验库,可以做到:
- 强制模型输出指定格式;
- 自动验证输出合法性;
- 在 JS/TS 中获得类型安全的对象。
我们来看 2.js 的实现:
定义 Schema(使用 Zod)
import { z } from 'zod';
const FrontendConceptSchema = z.object({
name: z.string().describe('概念名称'),
core: z.string().describe('核心要点'),
usecase: z.array(z.string()).describe('常见使用场景'),
difficulty: z.enum(['简单','中等','复杂']).describe('学习难度')
});
Zod 不仅能做运行时校验,还能生成文档说明、转换为 JSON Schema。
创建 JsonOutputParser
const jsonParser = new JsonOutputParser(FrontendConceptSchema);
这个 parser 有一个神奇的方法:
jsonParser.getFormatInstructions()
它会自动生成一段提示词指令,告诉模型该怎么输出合法 JSON。比如:
返回的 JSON 必须包含字段:name(字符串)、core(字符串)、usecase(字符串数组)、difficulty(枚举值之一)。不允许增加或减少字段,必须能被 JSON.parse 解析。
注入提示词模板
const prompt = PromptTemplate.fromTemplate(`
你是一个只会输出 JSON 的 API,不允许输出任何解释性文字。
⚠️ 你必须【只返回】符合以下 Schema 的 JSON:
{format_instructions}
前端概念:{topic}
`);
关键点在于:我们将 format_instructions 动态插入到了 prompt 中,相当于“动态约束模型行为”。
构建完整 Chain
const chain = prompt.pipe(model).pipe(jsonParser);
const response = await chain.invoke({
topic: 'Promise',
format_instructions: jsonParser.getFormatInstructions(),
});
此时 response 已经是一个经过类型校验的 JavaScript 对象,可以直接用于后续业务逻辑:
console.log(response.name); // "Promise"
console.log(response.difficulty); // "中等"
💡 这就是 Output Parser 的威力:把非结构化的文本输出,变成类型安全的数据结构,极大提升程序健壮性。
六、案例三 & 四:Memory —— 让 AI 拥有记忆能力
我们知道,HTTP 请求是无状态的,每次调用 LLM 都像是第一次见面。但真实场景中,用户往往需要多轮交互。
比如:
用户:“我叫张三。”
AI:“你好,张三!”
用户:“我喜欢吃橙子。”
AI:“好的,张三,我知道你喜欢吃橙子。”
用户:“我叫什么名字?”
AI:“你叫张三。”
这就要求 AI “记得”之前的对话内容。
LangChain 如何实现这一点?答案是:Memory。
我们来看 4.js 的实现。
使用 ChatPromptTemplate 支持消息历史
const prompt = ChatPromptTemplate.fromMessages([
['system', '你是一个有记忆的问答助手'],
['placeholder', '{history}'], // 占位符,将来会被替换为真实的历史消息
['human', '{input}']
]);
这里的 {history} 是关键,它会在运行时被替换成真正的对话记录。
构建带记忆的 Runnable
const runnable = prompt.pipe(model);
const messageHistory = new InMemoryChatMessageHistory();
// 存储在内存中的聊天记录,适合单会话测试
然后使用 RunnableWithMessageHistory 包装原始链:
const chain = new RunnableWithMessageHistory({
runnable,
getMessageHistory: async () => messageHistory,
inputMessagesKey: 'input',
historyMessagesKey: 'history'
});
这样每次调用时,LangChain 会自动:
- 获取该会话的历史消息;
- 插入到 prompt 中;
- 调用模型;
- 将新消息追加到历史中。
多轮对话演示
await chain.invoke(
{ input: '我叫张三,喜欢吃橙子' },
{ configurable: { sessionId: 'makefriend' } }
);
await chain.invoke(
{ input: '我叫什么名字' },
{ configurable: { sessionId: 'makefriend' } }
);
第二次调用时,由于共享同一个 sessionId,所以能读取到之前的消息,从而正确回答“你叫张三”。
🧠 这就是 Memory 的本质:通过维护对话历史,在无状态的 API 上模拟出“有状态”的体验。
七、LangChain 的工程化价值总结
通过以上四个案例,我们可以提炼出 LangChain 的四大核心能力:
| 能力 | 解决的问题 | 关键组件 |
|---|---|---|
| 🔗 Chain | 多步骤 AI 流程难以组织 | RunnableSequence, .pipe() |
| 🧩 PromptTemplate | 提示词散乱、不易维护 | PromptTemplate, ChatPromptTemplate |
| 📦 OutputParser | 输出不可控、难解析 | JsonOutputParser, zod 集成 |
| 💬 Memory | 无法支持多轮对话 | RunnableWithMessageHistory, InMemoryChatMessageHistory |
这些能力共同构成了 AI 应用的工程化基础设施。
八、LangChain 的设计哲学:适配器模式 + 统一接口
还有一个容易被忽略但极其重要的点:LangChain 是如何兼容不同 LLM 的?
比如你可以轻松地把 ChatDeepSeek 换成 ChatOpenAI 或 ChatAnthropic,而几乎不需要改其他代码。
这是因为 LangChain 采用了 适配器模式(Adapter Pattern):
- 所有 LLM 提供商都被封装成统一接口;
- 开发者只需关注“做什么”,而不是“怎么做”;
- 更换模型就像更换数据库驱动一样简单。
这也解释了为什么推荐安装:
pnpm i @langchain/deepseek # DeepSeek 适配器
pnpm i @langchain/core # 核心类库(prompt、runnable、parser 等)
LangChain 把 LLM 当作“可插拔组件”,极大地提升了系统的可扩展性和可维护性。
九、给前端开发者的建议:如何上手 LangChain?
如果你是一名前端开发者,想快速入门 LangChain,建议按以下路径学习:
✅ 第一步:环境准备
确保项目使用 ESM 模块系统:
// package.json
{
"type": "module"
}
安装必要依赖:
pnpm add @langchain/core @langchain/deepseek dotenv zod
配置 .env 文件:
DEEPSEEK_API_KEY=your_api_key_here
✅ 第二步:从最小例子开始
import { ChatDeepSeek } from '@langchain/deepseek';
import 'dotenv/config';
const model = new ChatDeepSeek();
const res = await model.invoke('你好');
console.log(res.content);
跑通第一个请求,建立信心。
✅ 第三步:逐步引入高级特性
- 加入
PromptTemplate管理提示词; - 用
.pipe()连接多个步骤; - 引入
JsonOutputParser + zod控制输出; - 使用
RunnableWithMessageHistory实现记忆对话。
每一步都要动手实践,理解“为什么需要这个组件”。
十、结语:LangChain 是 AI 时代的“Express 框架”
如果说 Express 是 Node.js 时代 Web 开发的基石,那么 LangChain 就是当下 AI 应用开发的事实标准。
它不追求炫技,而是专注于解决实际问题:
- 如何组织复杂的 AI 逻辑?
- 如何保证输出稳定可靠?
- 如何让 AI 记住上下文?
- 如何方便地替换底层模型?
这些问题的答案,都在 LangChain 的设计之中。
未来,AI 应用不会是“调一次 API 就完事”,而是像传统软件一样讲究架构、分层、可测试性。而 LangChain,正是这条路上最重要的工具之一。
参考资料
- LangChain 官方文档
- DeepSeek 官方 API
- Zod 文档
- 掘金专题《AI 工程化实践》
📌 如果你觉得这篇文章对你有帮助,请点赞、收藏、转发,让更多人看到!也欢迎在评论区分享你的 LangChain 实战经验~