Skip to content

LangChain 从入门到实战

这一篇专门只讲 LangChain,而且按小白能跟上的方式展开:先搞清楚它是什么、为什么会出现、最核心的对象有哪些,再重点拆 LangChain 里最常用也最容易混乱的工具体系、常用写法、RAG、记忆、结构化输出和典型业务场景。

先建立一个非常稳的直觉。

很多人第一次接触 LangChain,会把它想成“Prompt 模板库”或者“Agent 魔法盒子”。这两种理解都太窄。更准确的说法是:LangChain 是一套把模型、提示词、工具、检索、结构化输出、消息历史和运行逻辑组合起来的应用开发框架。 它最适合解决的问题不是“让模型凭空变聪明”,而是“当你的应用开始不止一个 prompt、不止一次调用、不止一种输出格式时,怎么把这些东西有章法地拼起来”。 如果你现在还在用“手写几段 prompt + 手写一点 if else + 手写一点接口调用”来做 AI 功能,功能少时还行;一旦要接工具、做 RAG、抽结构化字段、记录对话历史、切模型、写测试,你就会发现代码开始到处散。LangChain 的价值,就在于把这些常见拼装件收成一套比较统一的开发方式。

图 1:你可以把 LangChain 想成一套“AI 应用搭积木” 模型:Chat Model / Embedding Model ↓ 输入组织:Prompt / Messages / Variables ↓ 能力扩展:Tools / Retriever / Output Parser ↓ 运行方式:invoke / batch / stream / 组合链路 一句很重要的话 LangChain 不是“大模型本身”,而是“围绕大模型写应用时的一层工程组织方式”。你越早把这个边界想清楚,后面越不容易学乱。

02. LangChain 到底解决什么问题

很多初学者一上来就学 API 名字,结果越学越碎。更好的顺序是先问:如果没有 LangChain,我会在哪些地方开始重复劳动?

开发阶段不用框架时会发生什么LangChain 帮你做什么
只调一次模型直接请求 API 就能搞定此时价值不大,可以先不用
开始拼 Prompt变量替换、消息结构、系统提示逐渐变乱统一 Prompt / Message 组织方式
开始接工具工具描述、入参、出参、调用日志都靠手写提供 Tool 抽象和调用链组织
开始做 RAG检索、拼接上下文、结果格式越来越散把 Retriever、文档、Prompt 串起来
开始做测试很难替换模型、工具、检索结果做控制变量更容易 mock 组件、拆步骤、观察链路

2.1 它和“直接调 OpenAI / 直接写 Prompt”有什么差别

方式优点短板
直接调模型 API最直接、最轻、最容易看清底层一旦逻辑复杂就开始重复造轮子
只写 Prompt 模板适合快速试验 idea工具、检索、结构化输出难以系统组织
LangChain把常见能力收成统一抽象,方便组合和测试要先理解一套框架思路,刚开始会觉得名词多
LangGraph适合复杂状态流转、长流程、人工介入比 LangChain 更底层,学习门槛更高

什么时候值得学 LangChain

  • 你不再只是“一问一答”。
  • 你需要结构化输出。
  • 你要接工具或检索。
  • 你要把链路拆成可测试的步骤。

什么时候先别急着上框架

  • 你连模型 API 都没直接调过。
  • 你只是想写一个最小 demo。
  • 你还没想清楚业务到底要什么。
  • 你现在最大问题根本不是工程组织,而是需求没定。

2.2 用测试视角看 LangChain

这套课是“大模型测试”方向,所以你学 LangChain 时不能只站在开发视角。对测试同学来说,LangChain 的一个大好处,是它把原本揉成一团的 AI 调用过程拆成了可替换、可观察、可对账的模块:

  • Prompt 可以单独看是否变量替换正确。
  • Tool 可以单独 mock 成固定返回。
  • Retriever 可以单独喂固定文档,看结果是否稳定。
  • Output Parser 可以单独验证异常输入时怎么报错。
  • 整条 chain 可以做端到端冒烟。

03. 核心对象一次分清

初学 LangChain 最大的障碍,不是代码难,而是名词容易打架。下面这张表很重要,建议你反复看,直到能自己讲清楚每个对象是干什么的。

对象它是什么你什么时候会用到
Model真正负责生成文本、调用函数、做 embedding 的模型对象任何 AI 功能的底层能力入口
Prompt组织输入的模板,不只是字符串,往往还是消息结构你需要稳定地控制模型输入时
Messagessystem / human / ai 等消息对象对话式模型、历史上下文、多轮场景
Tool可被模型或程序调用的外部能力查天气、查数据库、调用搜索、执行业务动作
Retriever负责把相关文档找出来的检索组件RAG、知识库问答、文档问答
Output Parser把模型输出解析成你想要的结构需要 JSON、表格对象、固定字段时
RunnableLangChain 里非常重要的“可运行单元”抽象你要把多个步骤通过统一方式串起来时

3.1 先把 Runnable 直觉建立起来

很多人学 LangChain 学着学着就糊涂,核心原因之一就是没抓住 Runnable 这根主线。你可以把它理解成:任何一个“吃输入、吐输出”的步骤,都可以尽量统一成可运行组件。Prompt 可以是 Runnable,模型可以是 Runnable,Parser 可以是 Runnable,多个步骤拼起来的链路也可以是 Runnable。 图 2:最常见的一条 LangChain 链路

用户问题 → Prompt → Model → Parser / Structured Output

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个耐心的老师。"),
    ("human", "请用通俗语言解释:{topic}")
])

model = ChatOpenAI(model="gpt-4.1")
parser = StrOutputParser()

chain = prompt | model | parser
result = chain.invoke({"topic": "RAG"})
print(result)

3.2 这段代码到底发生了什么

步骤发生了什么测试时可看什么
Prompt把 topic 变量替换进消息模板变量是否漏传、消息角色是否正确
Model把消息发给真实模型模型名称、温度、超时、异常处理
Parser把模型输出整理成字符串空输出、截断输出、异常格式是否处理
Chain把 3 个步骤串起来一次执行输入输出是否按预期衔接

新手常见误会。

很多人以为 LangChain 里的每个类都必须背 API。其实不是。先想清楚“这一步在链路里扮演什么角色”,再去记代码,会轻松很多。

04. Tools 工具体系详细拆解

你前面特别提到“LangChain 的各种工具要仔细写”,那这里我们就把 Tools 单独展开。因为对很多人来说,真正觉得 LangChain 有意思,就是从模型不再只会“说”,而开始能“做事”开始的。

4.1 Tool 到底是什么

Tool 不是 LangChain 独有的概念,但它在 LangChain 里被组织得很系统。Tool 的本质是:把某个外部能力包装成一个模型或程序可调用的动作。这个动作一般有 3 件事:

  • 有名字。
  • 有描述,告诉模型“什么时候该用它”。
  • 有输入输出约定,告诉程序“怎么调用它”。
Tool 类型典型例子最容易出问题的地方
查询型工具天气、汇率、知识库搜索工具描述不清,模型不会用或乱用
业务动作型工具下单、审批、发邮件、建工单幂等性和权限控制没设计好
计算型工具计算器、日期处理、公式换算边界输入和异常处理不严谨
开发辅助型工具SQL 查询、代码执行、日志检索输入注入风险、安全边界不清

4.2 Tool 调用链长什么样

图 3:一次典型的工具调用生命周期 用户提出问题 ↓ 模型判断“我需要一个工具” ↓ LangChain 执行对应 Tool ↓ 把 Tool 结果再喂回模型组织最终回答

4.3 一个最小 Tool 示例

from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
    """计算两个整数的和。"""
    return a + b

别小看这几行。里面已经包含了 3 个很关键的信息:

  • add 是工具名。
  • 注释 / docstring 在很多场景下会成为模型理解这个工具用途的重要描述。
  • 参数类型会影响工具调用时的输入结构和约束。

4.4 Tool 描述为什么这么重要

写法效果
“获取信息”太泛,模型很难判断何时该调用
“根据城市名称查询实时天气,不要用于历史天气”边界更清晰,模型更容易正确使用
“创建工单”但不写权限要求模型可能在不该创建的时候乱调
“仅在用户明确确认后才执行退款申请”可以把业务规则写进工具描述和程序校验里

4.5 设计 Tool 时的 5 个原则

单一职责

一个 Tool 最好只做一件清楚的事,不要又查又改又审批。

边界清楚

描述里写清“什么时候能用,什么时候不能用”。

输入严格

参数名、类型、必填项越清晰,越不容易乱调。

输出稳定

不要一会儿返回字符串,一会儿返回 JSON,一会儿抛异常。

可观察

最好能记录工具名、入参摘要、结果摘要、耗时、错误。

可测试

业务敏感工具一定要能 mock,不能每次测试都真的打到生产动作。

4.6 Tool 最常见的测试点

Tool 测试清单

  • 工具描述是否足够让模型做出正确选择。
  • 参数缺失、参数类型错误时如何报错。
  • 相同问题多次调用时是否幂等。
  • 工具失败时,模型是重试、解释失败,还是胡编结果。
  • 敏感工具是否需要二次确认或权限校验。
  • 工具日志是否能帮助定位问题。

05. 常用方法与常见写法

这一节专门解决“会看概念,但一写代码就乱”的问题。LangChain 表面上类很多,但真正高频的操作方式并没有那么多。你先把下面这些方法和组合姿势吃透,日常开发就能跟上大半。

方法 / 写法你可以怎么理解典型使用时机
invoke()单次执行最常见,先把 happy path 跑通
batch()一批输入一起跑批量抽取、批量分类、批量评测
stream()边生成边返回前端流式输出、调试中间结果
ainvoke()异步单次执行后端并发调用、异步服务
| 管道组合把多个 Runnable 串起来Prompt → Model → Parser 这种主链
bind()提前绑定固定参数给模型预设温度、工具、停止词等

5.1 最常见的组合姿势

chain = prompt | model | parser
result = chain.invoke({"question": "什么是 LangChain"})

这一行 | 很关键。它的直觉非常简单:前一个步骤的输出,作为后一个步骤的输入。你先把这种“管道式思维”建立起来,后面很多链路就没那么吓人了。

5.2 batch 和 stream 别只会背名字

方法价值测试视角
batch()让一批输入统一走同一条链适合做批量回归、批量对账、稳定性抽样
stream()更接近真实用户交互适合看首包速度、中间状态、收口行为
ainvoke()适合服务端并发适合压测并发下的超时、异常、资源释放

5.3 一个稍微完整一点的例子

prompt = ChatPromptTemplate.from_template(
    "请把下面内容总结成 3 个要点:

{text}"
)

chain = prompt | model | StrOutputParser()

# 单次执行
one = chain.invoke({"text": "......"})

# 批量执行
many = chain.batch([
    {"text": "文档 A"},
    {"text": "文档 B"},
    {"text": "文档 C"},
])

5.4 新手写法里最容易混乱的 3 件事

把 Prompt 当成普通字符串

当场景进入对话消息、多变量和结构化输入后,普通字符串很快就不够用了。

把 Parser 省掉

一开始觉得输出能看就行,后面一旦接业务系统,就会发现“不稳定文本”很难用。

把所有逻辑揉进一个 prompt

短期看快,长期最难测。能拆成步骤的地方,尽量拆。

只会调用不会观察

没有日志、没有中间结果、没有 mock,后面定位问题会很累。

06. 结构化输出

很多业务场景里,“模型说得像那么回事”并不够。系统真正需要的是固定字段,比如:意图分类、投诉级别、联系人信息、订单号、结论和建议。这时候你就需要结构化输出。

6.1 为什么结构化输出这么重要

如果没有结构化输出会遇到什么问题
模型自由发挥写文本字段名会变,顺序会变,甚至漏字段
下游系统用正则去抠脆弱、难维护、很难应对格式漂移
测试只能肉眼看难以做自动化回归和批量对账

6.2 结构化输出常见两条路

方式思路适合场景
提示词约束 + Parser要求模型按固定 JSON / 文本格式输出,再解析通用、可迁移,但要处理格式不稳
模型原生结构化能力直接声明 schema,让模型按结构返回更稳,但依赖具体模型能力
python
from pydantic import BaseModel

class TicketInfo(BaseModel):
    category: str
    severity: str
    summary: str

# 伪代码:不同模型接法会有差异,但思路类似
structured_model = model.with_structured_output(TicketInfo)
result = structured_model.invoke("用户说:支付成功但订单一直是待支付")

6.3 结构化输出怎么测

结构化输出测试清单

  • 字段是否齐全。
  • 字段类型是否稳定。
  • 边界输入是否会漏字段或塞脏值。
  • 模型失败时,Parser / schema 校验如何报错。
  • 新增字段后,下游兼容是否正常。

07. 记忆、上下文与运行时

“Memory” 是 LangChain 新手最容易误解的话题之一。很多人一听记忆,就以为模型真的学会了、永久记住了。其实大多数应用里的记忆,根本不是模型参数层面的“学会”,而是把你想保留的信息在运行时重新放回上下文

你以为的记忆真实发生的事
模型自己长期记住用户通常不是,更多是应用把历史消息重新喂给模型
只要开了 memory 就万事大吉不是,历史过长、历史脏数据、历史泄漏都会出问题
记忆就是聊天记录不止,还可能包括用户画像、任务状态、临时变量

7.1 你至少要分清 3 类“上下文”

对话历史

用户上一轮说过什么,模型上一轮答过什么。

任务状态

当前任务做到哪一步,有没有缺字段,要不要继续追问。

外部持久化信息

数据库里的用户资料、工单状态、业务上下文。

7.2 记忆为什么经常越做越乱

  • 什么都往历史消息里塞,导致 prompt 变长、变脏。
  • 没有区分“当前任务需要的状态”和“长期资料”。
  • 没有裁剪策略,越聊越贵、越聊越慢。
  • 没有测试历史污染,导致不同会话互串。

测试视角提醒。

做“记忆”测试时,至少要补三种场景:短会话正常、多轮长会话裁剪是否合理、切换会话或切换账号后是否串历史。

08. Retrieval 与 RAG

很多人学 LangChain,就是为了做 RAG。但 RAG 也很容易学偏:一旦只盯着“接个向量库”,就会漏掉真正影响结果的关键点。更准确地说,RAG 不是一个组件,而是一条链路。 图 4:一个最常见的 RAG 链路

用户问题 → 检索相关文档 → 把文档拼进 Prompt → 模型基于上下文回答

环节它负责什么常见问题
切分把原文档切成适合检索的小块切太碎丢上下文,切太大检索不准
Embedding把文本变成向量模型不合适时语义对不上
Retriever根据问题找相似文档召回不准或召回过多
Prompt 拼接把召回结果组织给模型塞得太乱,模型看不懂重点
回答阶段基于检索结果生成回答模型仍然可能幻觉、忽略检索内容

8.1 LangChain 在 RAG 里最值钱的地方

  • Retriever 可以被当成统一组件接进链路。
  • Prompt 和文档拼接可以做成标准步骤。
  • 你可以方便地替换模型、Retriever、Parser 做对比测试。
  • RAG 链路比一坨手写脚本更容易复用和观察。

8.2 RAG 特别适合做哪些测试

检索测试

同一个问题召回了哪些文档,是否漏召回、误召回。

拼接测试

检索结果是否真的被放进 Prompt,格式是否清楚。

答案归因测试

模型回答是否真的基于召回内容,还是仍然胡编。

稳定性测试

换模型、换检索参数后结果差异如何。

09. 场景举例与拆解

真正学会一个框架,不能只靠背概念。下面把几个最常见场景拆开,你会更清楚 LangChain 到底适合干什么。

9.1 场景一:客服工单归类

为什么适合 LangChain常见组件测试重点
需要 Prompt + 结构化输出,不一定要复杂 AgentPrompt、Model、Structured Output字段稳定性、分类边界、异常输入处理

9.2 场景二:知识库问答

为什么适合 LangChain常见组件测试重点
典型 RAG 场景,组件边界清楚Retriever、Prompt、Model、Parser召回质量、答案归因、幻觉率

9.3 场景三:工具型小助手

为什么适合 LangChain常见组件测试重点
模型需要根据问题决定是否调用工具Model、Tools、Agent Executor工具选择是否正确、失败时是否乱编

9.4 场景四:文档抽取和批量处理

为什么适合 LangChain常见组件测试重点
batch 很适合做批量信息抽取、批量分类Prompt、Model、Parser、batch批量稳定性、吞吐、坏样本对整体影响

一句经验。

如果你的场景大多数时候仍是“单链路处理”,LangChain 通常已经够用。别一上来就把所有项目都做成多节点图,那样会把学习成本和维护成本一起抬高。

10. 新手常见误区

误区为什么不对更稳的做法
一上来就堆 Agent复杂度上升太快,问题难定位先从 Prompt → Model → Parser 起步
把所有逻辑都塞进 Prompt短期快,长期最难维护和测试能拆成 Tool、Retriever、Parser 就拆
只看最终回答,不看中间步骤出了问题不知道是 Prompt、Tool 还是 RAG分层观察、分层 mock
把 Memory 想成“模型学会了”大多数只是运行时重新喂上下文区分历史消息、状态和持久化数据
觉得框架能替代测试框架只帮你组织,不替你保证正确照样要做功能、稳定性、回归和安全测试

11. 什么时候该去学 LangGraph

这个判断特别重要。不是学完 LangChain 就必须马上上 LangGraph,而是当你开始出现这些信号时,LangGraph 会变得非常值:

  • 一条任务要经过多个阶段,而且阶段间要带状态。
  • 任务中途可能停下来,后面还要恢复继续。
  • 需要人工审批、人工修改、人工确认后再往下跑。
  • 你已经开始用很多 if else 手写工作流,而且越来越乱。
  • 你想把 Agent 从“能跑”推进到“可恢复、可观察、可控”。

图 5:一个简单的判断办法

单链路、少状态 → 先用 LangChain → 流程复杂、可中断、要恢复 → 再学 LangGraph

12. 一个完整小项目怎么搭

前面讲了很多组件,现在我们把它们真正拼成一个稍微完整的小项目。场景选一个最常见也最有教学价值的:企业内部知识库问答 + 工单归类助手。这个项目不追求一步做到最复杂,而是故意选一个能把 Prompt、Retriever、Structured Output、Tool、测试都串起来的场景。

模块作用为什么这个项目需要它
Prompt定义问答和归类的输入格式不同任务要给模型不同指令
Retriever召回内部知识库文档让回答尽量基于资料,不靠瞎猜
Model生成最终回答与分类结果负责理解问题、组合信息
Structured Output输出 category / severity / summary让工单系统可直接消费
Tool必要时创建工单或查单状态让系统不只是“回答”,还能“做事”

图 6:一个教学型 LangChain 小项目主链 用户提问:支付成功但订单还是待支付 ↓ Retriever 召回支付 FAQ 和订单状态文档 ↓ Prompt 把用户问题 + 检索结果 + 输出要求组织起来 ↓ 模型输出结构化结果 + 给用户的解释

12.1 这个项目的最小版本应该先做到什么

  • 先只做“输入问题 → 检索资料 → 输出一段解释”。
  • 再把输出改成结构化字段,比如分类、严重级别、摘要。
  • 最后再决定要不要加 Tool,比如自动建工单。

这个顺序非常关键。因为很多人一开始就想“做一个万能 Agent”,结果项目刚起步就过度设计。更稳的方式,是先把主链做对,再逐步加动作能力。

12.2 一个业务视角的拆法

用户层问题LangChain 层拆法测试层关注点
回答是否准确Retriever + Prompt + Model是不是基于召回内容回答
分类是否稳定Structured Output字段是否稳定、边界是否混淆
动作是否安全Tool是否幂等、是否需要确认、是否有权限控制
结果是否可回归Runnable 链路每一步能不能单独 mock 和对账

13. 调试与测试怎么做

这一节特别重要。因为很多人学框架只学“怎么跑起来”,但真正到了项目里,80% 的时间花在“为什么这次不对”上。LangChain 的可贵之处,在于它其实很适合分层调试,只要你别把所有逻辑揉成一团。

13.1 最稳的调试顺序

  1. 先看 Prompt 最终长什么样。
  2. 再看 Model 配置是否正确,比如模型名、温度、超时。
  3. 如果接了 Tool,看模型是否真的选择了对的 Tool。
  4. 如果做了 RAG,看 Retriever 究竟召回了什么。
  5. 最后再看 Parser / Structured Output 是否是失败根因。

一个经验。

大多数“模型答错了”并不是模型单点问题,而是链路前面某一步已经偏了:Prompt 没组织好、Retriever 召回错了、Tool 返回脏数据、Parser 把结果误处理了。

13.2 测试类型可以怎么分

组件级测试

单测 Prompt、Parser、Tool、Retriever,各看自己是否符合预期。

链路级测试

把 Prompt → Model → Parser 或 RAG 主链跑通,看整体输入输出。

回归测试

固定一批问题,换模型或换 Prompt 后做前后对比。

13.3 特别适合做自动化的点

对象为什么适合自动化
Structured Output字段是否齐全、类型是否稳定,很容易程序校验
Tool输入输出规则清楚,容易做 mock 和断言
Retriever可以固定问题和知识库,观察召回 TopK 是否漂移
Prompt 模板可对变量替换结果做快照比对

13.4 一个测试同学很好用的回归模板

测试对象:知识库问答链路
范围:Prompt + Retriever + Model + Structured Output
固定输入:20 条典型问题
固定知识库:支付 FAQ v3
固定输出字段:category / severity / answer
检查项:
1. category 是否稳定
2. answer 是否引用召回资料
3. 未召回资料时是否出现明显幻觉
4. 边界问题是否误调 Tool

14. 练习题与高频追问

你如果真的想学会,不能只看一遍。下面这组题,适合自己答,也适合带新人时当讨论题。

14.1 基础题

问题你至少应该答到什么程度
LangChain 解决的是哪一层问题?它解决的是 LLM 应用开发的工程组织层,不是训练模型本身
Runnable 为什么重要?因为它把很多不同步骤统一成“可运行组件”,便于组合和测试
Tool 和普通函数有什么差别?Tool 不只是函数,还要考虑描述、边界、可被模型选择和调用
RAG 为什么不是“接个向量库就完了”?因为它是一整条链路,检索、拼接、回答、归因都可能出问题

14.2 进阶追问

  • 为什么很多项目做着做着会从 LangChain 走向 LangGraph?
  • 为什么 Structured Output 对测试同学特别友好?
  • 为什么“模型答错”不能直接等于“模型能力差”?
  • 如果 Tool 很敏感,比如退款申请,你会怎么设计确认链路?

本页自测标准

  • 你能不能自己画出一条 Prompt → Model → Parser 的最小链路。
  • 你能不能解释 Tool 设计的 5 个关键点。
  • 你能不能讲清 RAG 各环节分别会出什么问题。
  • 你能不能从测试角度给出一套回归思路。

15. 官方资料与练习建议

这一篇如果你想真正学会,建议别只看。最好的方法是按“最小 demo → Tool → Structured Output → RAG → 测试回归”这个顺序做练习。

练习 1

写一个最小链:Prompt → Model → Parser,只做一个名词解释助手。

练习 2

加一个 Tool,比如计算器或天气查询,并观察模型什么时候会调它。

练习 3

把输出改成结构化字段,比如“category / severity / summary”。

练习 4

接一个最简单的 Retriever,做小型文档问答。

练习 5

给每个步骤加测试:固定 Prompt、固定 Tool 返回、固定检索结果。

练习 6

最后再思考:哪些场景已经开始需要 LangGraph 的状态图能力。 学完本页,你至少应该能回答这些问题

  • LangChain 解决的到底是哪一层问题。
  • Prompt、Model、Tool、Retriever、Parser 各自是什么角色。
  • 为什么 Runnable 是一条重要主线。
  • Tool 应该怎么设计,怎么测。
  • 结构化输出和 RAG 在 LangChain 里如何落地。
  • 什么时候 LangChain 已经不够,需要 LangGraph。

补充参考答案要点

  • 练习题部分应优先关注最小 runnable demo、Tool 调用正确性、结构化输出稳定性和 RAG 回归,而不是 API 背诵。
  • 高频追问的核心答案是:能先用最小链路跑通,再逐步引入 memory、retriever 和 callback,避免一次堆太多组件。
  • 如果链路不稳定,优先检查 prompt、工具 schema、输出解析和回调日志,而不是一开始怀疑框架本身。