从 Prompt 到 Agent:LangChain 究竟解决了什么问题
直接调 OpenAI API 就够了,为什么还要 LangChain?
简单场景确实不需要。但当应用从「一个 Prompt」长成「可用的 AI 系统」,复杂度会集中在组件协作上:Prompt 管理、结构化输出、Tool 接入、RAG、多步编排与调试。
LangChain 不替代 LLM,而是把这些组件串成可组合、可维护的流水线。
一、没有 LangChain 的世界
最简单的 LLM 调用
以 Node.js 为例:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const response = await client.chat.completions.create({
model: "gpt-4.1",
messages: [
{
role: "user",
content: "给登录页加一个忘记密码入口,帮我写个 React 组件",
},
],
});
console.log(response.choices[0].message.content);
非常简单:一次请求,一次响应,模型直接吐出代码片段,没有 JSON 解析、没有查仓库、也没有对照内部规范。
什么时候开始变复杂
产品提出完整需求:
做一个「智能代码助手」:用户用自然语言描述功能(比如「给登录页加一个忘记密码入口」),系统自动生成代码,并结合该项目的 GitHub 仓库现状和内部开发规范,输出一份结构化的技术方案报告。
拆解下来,后端要完成五件事:
| 步骤 | 做什么 | 为什么复杂 |
|---|---|---|
| 1. 生成代码 | 根据用户描述调用 LLM 产出代码 | 需要维护 Prompt 模板、上下文注入 |
| 2. 输出 JSON | 把结果解析成 { files, summary, risks } 等固定字段 |
LLM 输出不稳定,需要 Parser |
| 3. 查 GitHub | 调用 API 获取仓库结构、已有文件、PR 规范 | 需要 Tool 封装和鉴权 |
| 4. 检索知识库 | 从向量库拉取内部编码规范、架构文档 | 需要 RAG 流水线 |
| 5. 生成报告 | 把代码、仓库信息、规范文档合并,输出最终报告 | 多源数据合并 + 二次 LLM 调用 |
原本只是一次 chat.completions.create,现在要串起五条链路。你的代码很快会变成:
const requirement = "给登录页加一个忘记密码入口";
const prompt = buildCodeGenPrompt(requirement);
const llmResult = await callLLM(prompt);
const codeDraft = parseCodeResult(llmResult);
const repoInfo = await fetchGitHubRepo("my-org/web-app");
const standards = await vectorSearch("前端表单组件开发规范");
const report = await generateReport({ requirement, codeDraft, repoInfo, standards });
真正复杂的,已经不是调用模型,而是组织这些组件——入参出参各不相同,改一处 Prompt 可能影响 Parser 和下游 Tool。
这正是 LangChain 要解决的问题。第二至五节将沿上表五个环节依次展开,说明 LangChain 在每一层提供的抽象与实现方式。
二、Runnable 与 Chain —— 步骤 1:生成代码
对应环节:步骤 1 · 生成代码 | 核心抽象:Runnable、
pipe、Chain
LangChain 最核心的思想只有一句话:Everything is Runnable——所有组件都可以执行,都可以组合。
Runnable:统一插头
回到第一节的胶水代码,五个步骤其实是五种不同的调用方式——入参、出参、错误处理各写各的。Runnable 把它们统一成同一种插头:
| 方法 | 用途 |
|---|---|
invoke(input) |
单次调用 |
batch(inputs) |
批量调用 |
stream(input) |
流式输出 |
pipe(next) |
串联下一个 Runnable |
以步骤 1 为例,三个 Runnable 职责不同,调用方式相同:
① Prompt——把 { requirement } 格式化成 Message[]
const prompt = ChatPromptTemplate.fromTemplate(
`根据以下需求生成代码:\n{requirement}`
);
const messages = await prompt.invoke({
requirement: "给登录页加一个忘记密码入口",
});
② Model——把 Message[] 发给 LLM,拿回 AIMessage
const model = new ChatOpenAI({ model: "gpt-4.1" });
const aiMessage = await model.invoke(messages);
③ Parser——把 AIMessage 转成 string
const parser = new StringOutputParser();
const codeText = await parser.invoke(aiMessage);
三步串起来,数据形态的变化是:
Chain:pipe 把三步合成一次调用
手写三步需要手动传参;用 pipe 等价于:
const codeGenChain = prompt.pipe(model).pipe(parser);
const codeText = await codeGenChain.invoke({
requirement: "给登录页加一个忘记密码入口",
});
一次 invoke,框架自动完成 Prompt → Model → Parser 的流转——即 Chain,也是 LangChain 对步骤 1 的实现方式。
步骤 1 可由 Chain 完整覆盖。步骤 2 则引入新的约束:输出须为 { files, summary, risks } 结构,而非纯文本——Model 与 Parser 的用法均需调整。
三、结构化输出 —— 步骤 2:结构化 JSON
对应环节:步骤 2 · 输出 JSON | 核心抽象:Schema、
withStructuredOutput
步骤 1 的 Chain 输出的是字符串,下游步骤 3~5 需要的是结构化对象。如果只靠 Prompt 让模型返回 JSON:
const result = await model.invoke(
"给登录页加忘记密码入口,返回 files、summary、risks 的 JSON"
);
同一条 Prompt,模型可能返回 Markdown 代码块、字段名对不上的 JSON、或把 risks 写进 summary——fetchGitHubRepo 和 generateReport 无法稳定消费。
LangChain 用 Schema 约束输出(底层依赖 JSON Mode),目的是固定 LLM 的回复格式:
import { z } from "zod";
const codeDraftSchema = z.object({
files: z.array(z.object({ path: z.string(), content: z.string() })),
summary: z.string(),
risks: z.array(z.string()),
});
const structuredModel = model.withStructuredOutput(codeDraftSchema);
const codeDraft = await structuredModel.invoke(
"给登录页加一个忘记密码入口"
);
{
"files": [
{ "path": "src/pages/Login.tsx", "content": "..." },
{ "path": "src/api/auth.ts", "content": "..." }
],
"summary": "新增忘记密码入口,调用 /auth/reset-password 接口",
"risks": ["需确认现有 auth 中间件是否支持", "移动端样式需单独适配"]
}
codeDraft.files 可以交给 GitHub diff 对比,codeDraft.risks 可以注入最终报告——解析逻辑从业务代码挪到了框架层。
步骤 2 通过 Schema 约束得以实现。步骤 3 的需求本质不同:须由 LLM 决策是否、何时调用外部 API,而非仅格式化输出。
四、Tool 与 Tool Calling —— 步骤 3:GitHub 集成
对应环节:步骤 3 · 查 GitHub | 核心抽象:
tool()、bindTools、执行循环
第一节的写法是硬编码:
const repoInfo = await fetchGitHubRepo("my-org/web-app"); // 写死仓库,写死调用时机
Tool Calling 换了一种方式——何时查、查哪个仓库,由模型根据用户问题决定:
// 用户问 "分析 web-app" → 模型返回 tool_call
// 用户问 "这段代码什么意思" → 模型直接回答,不调 Tool
const modelWithTools = model.bindTools([githubTool]);
Tool Calling 是 OpenAI / LangChain 的常用叫法;Anthropic 称 Tool Use,早期也称 Function Calling——指的都是同一件事。
定义 Tool(对 GitHub API 的 Runnable 封装):
import { tool } from "@langchain/core/tools";
const githubTool = tool(
async ({ owner, repo }) => {
const tree = await fetchRepoTree(owner, repo);
return JSON.stringify(tree);
},
{
name: "fetch_github_repo",
description: "查询 GitHub 仓库的目录结构和协作信息",
schema: z.object({ owner: z.string(), repo: z.string() }),
}
);
用户问:「分析 my-org/web-app,为忘记密码功能生成改造方案」——模型返回 Tool Call,运行时执行后再推理:
模型负责决策,Tool 负责执行,运行时负责闭环。当 Tool 不止一个、调用顺序无法预先写死时,就进入 Agent 模式——LangChain 的 createReactAgent 会把上述循环自动迭代。
步骤 3 由 Tool Calling 机制承接。步骤 4 须检索模型训练数据之外的私有知识库;步骤 5 则将前述环节的产物合并为最终报告。
五、RAG 与报告组装 —— 步骤 4 & 5:知识检索与报告生成
对应环节:步骤 4 · 检索知识库 / 步骤 5 · 生成报告 | 核心抽象:Retriever、RAG Chain、reportChain
模型知道 React 怎么写,但不知道你们的组件命名规范、PR 模板、安全红线。步骤 4 通过 RAG 把私有文档注入上下文:
Retriever 本身也是 Runnable:
const retriever = vectorStore.asRetriever();
const docs = await retriever.invoke("前端表单组件命名与样式规范");
// 命中:《前端编码规范 v3》《Auth 模块安全 checklist》
RAG Chain 把检索和生成 pipe 在一起:
const ragChain = RunnableSequence.from([
{ context: retriever, question: new RunnablePassthrough() },
ragPrompt,
model,
parser,
]);
const complianceNotes = await ragChain.invoke(
"给登录页加忘记密码入口,需遵循哪些内部规范?"
);
步骤 5:多源数据合并与报告生成
至此,各环节的中间产物均已就绪——codeDraft(第三节)、repoInfo(第四节)、complianceNotes(第五节)。步骤 5 通过 reportChain 将多源数据合并,经二次 LLM 调用生成最终报告:
const report = await reportChain.invoke({
requirement,
codeDraft, // 步骤 2
repoInfo, // 步骤 3
complianceNotes, // 步骤 4
});
LangChain 还提供了 Document Loader、Text Splitter、VectorStore 等配套抽象——RAG 流水线同样纳入 Runnable 组合体系。
至此,「智能代码助手」五步链路的组件层已全部可由 LangChain 覆盖。 当流程规则超出线性 Pipeline 的能力边界时,则需要引入编排层。
六、Chain 的边界:何时需要编排层
对应环节:五步链路之上 · 流程编排 | 能力边界:分支、循环、共享状态
前五步如果固定顺序、从不回退,Chain 完全够用:
但产品很快会加规则:
循环——Review 不通过则重新生成:
条件分支——RAG 命中「禁止修改 Auth 核心模块」则直接终止:
并行——GitHub 查询与 RAG 检索同时进行:
Chain 本质是 Pipeline,而非 State Machine——缺少共享状态、条件路由、循环回退与 Checkpoint。这属于编排层的能力范畴,需由 LangGraph 承接。
七、LangGraph:LangChain 的编排层
对应环节:Review 回退、红线拦截、断点恢复 | 架构关系:LangGraph 负责编排,LangChain 提供组件
LangChain 覆盖 Prompt / Model / Parser / Tool / RAG 等组件层能力;LangGraph 负责流程编排与状态管理:
| 能力 | 在「智能代码助手」中 |
|---|---|
| 状态管理 | requirement、codeDraft、repoInfo 等共享于全流程 |
| 条件路由 | RAG 命中红线 → 终止;Review 通过 → 生成报告 |
| 循环执行 | Review 失败 → 带审查意见回到 Generate |
| Checkpoint | 进程崩溃后从断点恢复 |
| Human-in-the-Loop | 修改 Auth 核心模块前等待 Tech Lead 确认 |
把 Review 回退落到 LangGraph:
每个 Node 内部仍使用 LangChain 的 Chain、Model、Tool 实现具体逻辑——LangGraph 管流程,LangChain 管组件,二者同属一个生态,呈上下层协作关系。
- LangChain:一个组件库,提供大量现成的“零件”(如模型接口、提示词模板、检索器等)。它通过 pipe (LangChain 表达式语言) 将这些零件高效地组装成线性流程,适合快速构建和简单任务。
- LangGraph:一个负责状态管理和复杂编排的“运行时”。它不取代 LangChain,而是利用其组件,提供更强大的图结构(Graph)模型来构建应用
| 维度 | LangChain (上层建筑) | LangGraph (底层引擎) |
|---|---|---|
| 核心抽象 | 链 (Chain) / 线性流程 | 图 (Graph) / 状态机 |
| 控制流 | 主要由静态边定义的线性流水线。即便有工具调用,其逻辑也基本是顺序性的。 | 灵活的图结构,原生支持条件分支、循环、并行,并能处理重试机制。这对于实现复杂决策和递归任务至关重要。 |
| 状态管理 | 相对简单,通过Memory组件在步骤间传递上下文,但较难支持复杂的状态回溯。 |
内置强大的持久化状态。状态在一个共享的数据结构中流转,并且系统支持保存状态快照(Checkpoint)。 |
| 适用场景 | 简单、线性的一次性任务。例如基础的 RAG(检索增强生成)、文档摘要等。 | 复杂、有状态的系统。例如需要多轮交互的智能体(Agent)、长流程业务自动化,以及必须支持人工介入的复杂流程 |
八、LangChain 在 Agent 生态中的位置
| 框架 / 协议 | 职责 | 与本文的关系 |
|---|---|---|
| LangChain | Prompt、Model、Parser、Tool、RAG | §二~§五 的主体 |
| LangGraph | 状态图、条件路由、循环、Checkpoint | §六~§七 的延伸 |
| OpenAI Agents SDK | OpenAI 生态的 Agent 运行时 | 与 LangGraph 定位类似 |
| MCP | Tool 的标准化接入协议 | 解决 Tool 跨服务复用 |
九、什么时候该用
| 你的「智能代码助手」走到哪一步 | 建议 |
|---|---|
| 单次问答、一个 Prompt 搞定 | 直接调 API |
| 固定顺序的多步 Prompt(分析 → 设计 → 生成) | LangChain Chain |
| 需要 JSON 输出 + GitHub Tool + 内部规范 RAG(前五步) | LangChain 组件层 |
| Review 回退、红线拦截、断点恢复 | 加 LangGraph |
| 已有成熟编排,只需 LLM 封装 | 只用 LangChain 的 Model / Parser |
判断标准:如果系统只有 1-2 个固定步骤,直接调 API;如果步骤超过 3 个且需要频繁切换模型/Tool/RAG,用 LangChain 组件;如果出现分支、回退、人工审批,上 LangGraph。但每一步引入都要评估:框架省下的胶水代码,是否 worth 它带来的抽象复杂度。
总结
LangChain 不是模型框架,而是 AI 应用开发框架。
它解决的不是「怎么调用 LLM」,而是第一节五条链路里的组件协作问题:
回到开篇的问题——为什么不直接调 API?
因为「智能代码助手」这样的系统,难点不在 LLM 调用,而在 Prompt、Parser、Tool、RAG 如何统一接口、自由组合。LangChain 用 Runnable 和 Chain 提供了这套组件层;流程变复杂时,LangGraph 在同一生态内接手编排。
LangChain 不是终点,但几乎是所有 Agent 系统绕不开的起点。
更多推荐

所有评论(0)