概述:为什么要使用LangChain
很多人第一次接触大模型开发时,写出来的代码大概是这样的:
fromopenaiimportOpenAI client=OpenAI()response=client.chat.completions.create(model="gpt-4o-mini",messages=[{"role":"user","content":"帮我总结一下 LangChain 是什么"}],)print(response.choices[0].message.content)这段代码没有问题。它能完成一次简单问答,也能做翻译、总结、分类、改写。
但只要需求稍微真实一点,问题就来了:
- 用户问的问题依赖公司内部文档,模型训练时并不知道。
- 用户希望模型查询数据库、调用接口、读取文件,而不是只生成一段文字。
- 对话要支持多轮上下文,不能每次都像第一次见面。
- 业务里需要结构化输出,例如稳定返回 JSON,而不是一段自然语言。
- 线上系统需要可观测、可调试、可回放,而不是只看到最终答案。
- 今天用 OpenAI,明天可能要切到 Claude、Gemini、DeepSeek、本地 Ollama。
裸调 LLM API 解决的是“让模型说话”,LangChain 解决的是“让模型进入应用系统并完成任务”。
LangChain 不是一个“更聪明的模型”,它是一个 LLM 应用开发框架。它把模型、提示词、工具、检索、记忆、Agent 决策循环等能力抽象成可组合的模块,帮助开发者把一次模型调用扩展成一个可维护、可调试、可演进的应用。
核心价值:LangChain 到底帮我们省了什么?
一、屏蔽不同模型供应商的差异
不同模型供应商的 API 格式、参数命名、响应结构并不完全一致。裸调 API 时,你的业务代码很容易和某个供应商绑定在一起。
例如今天使用 OpenAI,明天切换到 Anthropic 或本地 Ollama,可能要改初始化方式、消息格式、流式输出处理、工具调用协议、错误处理逻辑。
LangChain 的模型层提供了一套相对统一的接口。开发者可以通过init_chat_model或具体模型类接入不同供应商,然后用类似的方式调用:
fromlangchain.chat_modelsimportinit_chat_model model=init_chat_model("openai:gpt-4o-mini")response=model.invoke("用一句话解释 LangChain")print(response.text())当你需要切换模型时,理想情况下业务逻辑不需要整体重写:
model=init_chat_model("anthropic:claude-sonnet-4-5")# 或者model=init_chat_model("ollama:llama3.1")模型当然不是完全等价的。不同模型在工具调用、上下文长度、结构化输出、多模态、推理能力上都有差异。LangChain 的价值不是抹掉这些差异,而是把差异集中到模型适配层,让业务链路尽量保持稳定。
二、把提示词从字符串升级成工程化组件
早期很多 LLM 应用的提示词都是这样拼出来的:
prompt="你是一个客服助手,请回答用户问题:"+user_question这种写法一开始很快,但很快会失控:
- system 指令、用户输入、历史对话混在一起。
- 变量越来越多,字符串拼接容易出错。
- 同一段提示词到处复制,修改一次要改很多文件。
- 很难做版本管理、复用和测试。
LangChain 使用消息和 Prompt 模板来管理上下文。你可以清楚地区分系统指令、用户输入、AI 回复和工具结果:
fromlangchain_core.promptsimportChatPromptTemplate prompt=ChatPromptTemplate.from_messages([("system","你是一个严谨的 LangChain 教程作者,回答要准确、简洁。"),("human","请解释这个概念:{topic}"),])messages=prompt.invoke({"topic":"Runnable"})这样做的好处不是“代码更花哨”,而是让 Prompt 变成可复用、可组合、可测试的工程资产。
三、让模型连接外部数据
大模型有两个天然限制:
- 它的上下文窗口有限,不能一次吃下所有文档。
- 它的训练知识有截止时间,不知道你的私有数据和最新业务状态。
这就是 RAG(Retrieval-Augmented Generation,检索增强生成)出现的原因。
一个典型 RAG 流程如下:
LangChain 在这个流程中提供了多类基础组件:
- Document Loader:从 PDF、Markdown、网页、数据库、Notion、Slack 等来源加载文档。
- Text Splitter:把长文档切分成适合检索和放入上下文的小块。
- Embedding Model:把文本转成向量,让语义相近的内容在向量空间中更接近。
- Vector Store:存储和检索向量,例如 Chroma、FAISS、Milvus、Pinecone 等。
- Retriever:根据用户问题取回最相关的文档片段。
RAG 让模型从“只靠训练记忆回答”,变成“带着外部资料回答”。
四、让模型调用工具,而不是只输出文字
很多业务问题不能靠“说”解决,而要靠“做”解决。
例如:
- 查天气。
- 查订单状态。
- 查询数据库。
- 创建工单。
- 调用搜索引擎。
- 执行计算。
- 写入 CRM 系统。
LangChain 中的 Tool 本质上是一个有明确输入输出定义的函数。模型可以根据对话上下文决定是否调用工具,以及传什么参数。
fromlangchain.toolsimporttool@tooldefquery_order(order_id:str)->str:"""根据订单号查询订单状态。"""returnf"订单{order_id}当前状态:已发货"在 Agent 场景里,模型看到用户问题后,不一定直接回答,而是可能先决定调用query_order,拿到结果后再组织自然语言回复。
这一步非常关键。因为它把 LLM 从“文本生成器”推向了“任务执行协调器”。
对比:裸调 API vs LangChain
下面这张表可以快速看清两者的差异:
| 维度 | 裸调 LLM API | 使用 LangChain |
|---|---|---|
| 模型接入 | 直接调用某个供应商接口 | 使用统一模型接口,便于切换供应商 |
| Prompt 管理 | 字符串拼接为主 | Prompt 模板、消息对象、变量注入 |
| 外部数据 | 需要自己写检索和拼接逻辑 | 提供 Loader、Splitter、Retriever、Vector Store 等组件 |
| 工具调用 | 自己定义协议和解析逻辑 | 使用 Tool / Agent 体系组织工具调用 |
| 多轮记忆 | 自己维护历史消息 | 可结合 checkpointer、thread state、memory 策略管理上下文 |
| 结构化输出 | 常见做法是正则或手写解析 | 可结合 schema、parser、response_format 等方式约束输出 |
| 调试观测 | 需要自己打日志 | 可结合 LangSmith 做链路追踪和评估 |
| 适合场景 | 简单问答、一次性脚本 | RAG、Agent、生产级 LLM 应用 |
这并不是说所有项目都必须使用 LangChain。
如果你的需求只是“用户输入一句话,模型返回一句话”,裸调 API 更直接。但如果你要做知识库问答、智能客服、SQL 查询助手、代码审查 Agent、多工具协作系统,LangChain 会明显降低工程复杂度。
架构地图:理解 LangChain 的几个核心模块
可以把 LangChain 理解成围绕 LLM 应用的一组积木:
用户输入 | v Prompt / Messages ----> Model | | | v | Structured Output | v Runnable / LCEL 组织调用流程 | +---- Retrieval:连接外部知识 | +---- Tools:连接外部动作 | +---- Memory / Checkpointer:保存对话状态 | v Agent:模型 + 工具 + 提示词 + 中间件 + 决策循环下面逐个拆解。
Models:模型是推理引擎
Models 是 LangChain 应用的核心推理层。它负责理解输入、生成输出、判断是否调用工具、是否返回结构化结果。
在 LangChain 中,模型既可以单独调用,也可以放进 Agent 循环中:
response=model.invoke("解释一下 RAG")当你只是做分类、总结、改写、抽取时,直接调用模型就够了。当你需要模型在多步任务中选择工具、读取上下文、根据中间结果继续决策时,就会进入 Agent 场景。
Prompts / Messages:上下文的组织方式
LLM 并不是只看一段字符串。现代聊天模型通常接收一组 messages:
- SystemMessage:告诉模型角色、边界、规则和输出风格。
- HumanMessage:用户输入。
- AIMessage:模型历史回复,也可能包含工具调用信息。
- ToolMessage:工具执行结果,用来回传给模型继续推理。
理解 Messages 很重要,因为 LangChain 的多轮对话、工具调用、Agent 状态,最终都会落到“模型这次到底看到了哪些上下文”上。
Runnable / LCEL:把组件串成流程
在 LangChain 里,很多组件都实现了 Runnable 接口。你可以把 prompt、model、parser 等组件像管道一样组合:
chain=prompt|model result=chain.invoke({"topic":"LangChain"})这就是 LCEL(LangChain Expression Language)的基本思想:把一个复杂调用流程拆成多个可组合、可替换、可观测的步骤。
后续学习 LangChain,Runnable 是必须重点理解的抽象。因为不管是简单 chain,还是复杂 Agent,背后都离不开“输入经过多个步骤变成输出”的数据流。
Retrieval:让应用拥有自己的知识库
Retrieval 负责从外部知识源中取回和用户问题相关的内容。
典型场景包括:
- 企业内部文档问答。
- 法律、医疗、金融等领域知识库。
- 产品说明书问答。
- 代码仓库理解。
- 客服 FAQ 检索。
注意,RAG 不是简单地“把所有文档塞给模型”。正确做法通常是:加载文档、切分、向量化、检索、重排、拼接上下文,再让模型回答。
Tools:让模型能执行动作
Tool 是连接模型和外部世界的桥。
如果 Retrieval 解决的是“模型不知道什么”,那么 Tool 解决的是“模型不能做什么”。
例如,模型本身不能真的查询你的订单系统。但你可以提供一个query_order工具,让模型在需要时调用它。
工具设计的关键不是函数写得多复杂,而是输入输出要清晰,描述要准确,错误处理要可控。因为模型会根据工具名称、参数 schema 和描述来判断什么时候调用它。
Memory:让多轮任务有连续性
一个没有记忆的聊天应用会很别扭:
用户第一轮说:“我想订明天去上海的票。”
第二轮问:“那后天返回呢?”
如果系统不知道“上海”和“订票”来自上一轮,就无法正确理解第二轮。
在 LangChain 新版本中,短期记忆通常和 agent state、thread、checkpointer 相关。你可以把一个 thread 理解成一段会话,checkpointer 负责保存这个 thread 的状态,使对话可以继续。
但记忆不是越多越好。历史消息太长会增加成本、拖慢响应,还可能让模型被过时信息干扰。因此真实应用里经常要做裁剪、摘要、长期记忆和短期记忆分层。
Agents:让模型进入“观察-决策-行动”循环
Agent 是 LangChain 中最容易被误解的概念。
它不是一个神秘的新模型,而是一种运行方式:模型在循环中根据当前上下文决定下一步做什么。
一个简化的 Agent 循环如下:
在 LangChain 里,可以用create_agent快速创建一个 Agent。它通常由模型、工具、系统提示词、中间件、状态管理等部分组成。
Agent = Model + Tools + Prompt + State + Loop。
适用场景:什么时候该用 LangChain?
场景一:知识库问答
这是 LangChain 最典型的入门场景。
比如你有一批 PDF、Markdown、Word 文档,希望用户提问时,系统能基于这些文档回答,并给出引用来源。
这类系统通常需要:
- 文档加载。
- 文本切分。
- 向量检索。
- 结果重排。
- 上下文拼接。
- 答案生成。
- 引用来源展示。
LangChain 在这些环节都有现成抽象,适合快速搭建原型,也适合逐步演进成生产系统。
场景二:智能客服
智能客服不是简单聊天。它通常需要:
- 识别用户意图。
- 查询订单、物流、售后状态。
- 检索 FAQ。
- 记住当前会话上下文。
- 对退款、改地址等敏感操作引入人工审批。
这类需求天然适合 Agent + Tools + Memory + RAG 的组合。
场景三:自然语言查数据库
用户输入:“帮我查一下上个月华东区销售额最高的 10 个客户。”
系统需要理解意图、读取表结构、生成 SQL、校验 SQL、执行查询、解释结果。
这不是一次模型调用能稳定完成的任务。你需要工具、结构化输出、安全校验和执行链路。
场景四:代码审查 Agent
一个代码审查 Agent 可能需要:
- 读取 Git Diff。
- 理解变更影响范围。
- 调用静态扫描工具。
- 调用安全扫描工具。
- 生成 Markdown 审查报告。
- 自动评论到 PR。
这类任务有明显的多步骤、多工具、可追踪需求,也适合 LangChain / LangGraph 体系。
常见误区:学 LangChain 前先避开这几个坑
误区一:以为 LangChain 会让模型本身变聪明
LangChain 不会改变模型能力上限。
如果模型本身数学能力弱、工具调用能力差、上下文理解差,LangChain 不能魔法般解决。但 LangChain 可以帮你更好地组织上下文、接入工具、补充外部知识、追踪错误,从工程上提高系统可靠性。
误区二:所有需求都上 Agent
Agent 很强,但也更复杂。
如果任务路径固定,例如“读取用户输入 -> 调用模型 -> 解析 JSON”,用普通 chain 就够了。只有当任务需要模型动态决定下一步时,Agent 才更有价值。
误区三:RAG 就是向量数据库
向量数据库只是 RAG 的一部分。
真正影响效果的还有文档解析、切分策略、embedding 模型、检索参数、重排、Prompt 组织、引用展示、评估集建设。
误区四:把历史对话无限塞进上下文
上下文不是垃圾桶。历史越长,成本越高,延迟越高,模型越容易被无关信息干扰。
合理的记忆系统应该区分:
- 当前任务必须保留的信息。
- 可以摘要压缩的信息。
- 可以丢弃的过期信息。
- 需要长期保存的用户偏好或业务事实。
学习路线:从这篇文章之后怎么继续?
建议按下面顺序学习:
- 先跑通一个最小 LangChain 程序,理解
model.invoke()和chain.invoke()。 - 学模型层,掌握
init_chat_model和不同供应商切换。 - 学 Prompt 模板和 Messages,搞清楚模型到底看到了什么。
- 学 LCEL / Runnable,理解 LangChain 的组合方式。
- 学 RAG,把模型接入自己的文档。
- 学 Tools 和 Agent,让模型能调用外部能力。
- 学 Memory、Middleware、LangGraph,进入生产级 Agent 开发。
- 最后读源码,理解这些抽象是如何实现的。
这个系列后续会按照这条路线展开,从能跑,到能用,再到能读源码。
总结
LangChain 的本质是什么?如果只记住一句话:
LangChain 是一个用于构建 LLM 应用的工程框架,它把模型调用、提示词、工具、检索、记忆、Agent 循环和可观测能力组织成可组合的模块。
再具体一点:
- Models解决“调用哪个模型、如何统一调用”的问题。
- Prompts / Messages解决“给模型什么上下文”的问题。
- Runnable / LCEL解决“如何把多个步骤组合成流程”的问题。
- Retrieval解决“模型如何使用外部知识”的问题。
- Tools解决“模型如何执行外部动作”的问题。
- Memory / Checkpointer解决“多轮任务如何延续状态”的问题。
- Agents解决“模型如何在循环中自主决策下一步”的问题。
LangChain 的价值不在于让一次调用更短,而在于让复杂 LLM 应用更容易被组织、调试、扩展和上线。