news 2026/9/9 2:02:43

LangChain核心三件套:LCEL、工具调用与LangGraph状态编排实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain核心三件套:LCEL、工具调用与LangGraph状态编排实战解析

先聊点实在的。现在只要一搜 LangChain,铺天盖地的都是“Agent 实战”“智能体开发教程”,好像你不会写 Agent 就不配说自己搞大模型应用。但以我带团队做生产级 LLM 应用这一年多的经验来看,大部分被 Agent 折磨得死去活来的人,问题根本不是出在 Agent 本身,而是链(Chain)那一层就没吃透。

LangChain 这个生态,看着乱,其实有一条非常清晰的演进线索:从最初的 Chain 串联,到工具调用(Tool Calling),再到以图为基础的 Agent 编排。你只有把这条线索上的核心概念理顺了,看 LangChain 的源码也好、看 LangGraph 的文档也罢,才会有那种“原来如此”的通透感。

这篇东西我不打算给你罗列 API 文档,那玩意儿官方写得比我清楚。我想从一个开发者的实操视角,把 LangChain 生态里从链到代理这条路径上的三大核心拆开揉碎:声明式链(LCEL)、工具调用、图状态编排。搞懂这三个,你基本就掌握了这个生态的命脉。

1. 先理清 LangChain 的定位:它到底替你解决了什么问题

很多人学 LangChain 学得一头雾水,是因为他们根本不知道这个框架存在的意义。用大白话说,LangChain 解决的是LLM 应用开发中的“胶水”问题

1.1 没有 LangChain 之前,你在写什么代码

假设你现在要做一个最简单的“翻译机器人”,调用 OpenAI 的 API。没有框架,你怎么写?大概是这样:

  • 拼接 Prompt 模板,把用户输入塞进去。
  • 调用client.chat.completions.create()
  • 从返回的 JSON 里把content字段抠出来。
  • 处理报错。
  • 把这个过程封装成一个函数。

这看起来不难,对吧?可一旦你的业务变复杂,比如:老板说“不仅要翻译,还要先判断语言类型,再决定是否调用外部术语库,翻译完还得自动检查有没有敏感词”。你那个简单的函数就会膨胀成一坨充满 if-else 的意大利面条。

LangChain 的核心价值,就是把这坨面条重新规划成一条条标准化的流水线(Pipeline)。每一个环节是一个组件,组件之间通过标准接口传递数据,你可以随意插拔、组合、替换。

1.2 理解两个基础抽象:Model 与 Prompt

在深入链和代理之前,你脑子里必须建立两个最基本的抽象:

  • Model(模型):在 LangChain 里,无论是 OpenAI、Anthropic 还是本地跑的开源模型,都被封装成统一的接口。你今天用ChatOpenAI,明天想换成ChatOllama,只需要改一行实例化代码,后面所有的逻辑都不用动。这个设计在前期看没什么了不起,但一旦你进入生产环境,要搞模型灾备、成本控制的时候,你就知道这层抽象有多值钱了。
  • Prompt(提示词):LangChain 里的PromptTemplate绝不只是一个简单的字符串替换工具。它提供的是结构化的模板管理方式,支持变量校验、部分变量注入、甚至可以从对话历史里自动提取上下文。

我见过很多刚上手的人,喜欢把 Prompt 直接硬编码在业务代码里。等到 Prompt 迭代了三版之后,代码被改得面目全非,不得不重构。用PromptTemplate把这些提示词全部外置管理,你会发现迭代成本瞬间降下来了。

记住:LangChain 不管你是哪家模型,也不管你写什么提示词,它只管让这些零件能像一个整体那样协同工作。

2. 核心一:LCEL 声明式链—— LangChain 立身之本

聊完了定位,我们进入正题。LangChain 生态里第一个你必须吃透的核心,就是LCEL(LangChain Expression Language,LangChain 表达式语言)。如果你现在看的是老教程,里面还在教你用LLMChain这个类,那我建议你赶紧关掉换一篇。LLMChain是上一代的产物,现在的 LangChain 官方已经把 LCEL 定为标准方式,甚至可以说,LCEL 是整个 LangChain 未来的地基。

2.1 为什么说是“声明式”,它和你平时写的代码有何不同

传统的命令式编程,是你一步步告诉计算机“怎么做”。LCEL 声明式编程,是你告诉系统“我要什么”,系统自己决定怎么把步骤串起来。

直接看代码,感受一下 LCEL 的丝滑:

from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate # 初始化模型,注意这里我们设置了 temperature 低一些,翻译任务需要更高的确定性 model = ChatOpenAI(model="gpt-4o-mini", temperature=0) # 定义提示词模板,{input} 是待填充的变量 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一位专业的科技领域英文翻译专家,请将用户输入翻译为地道的英文。"), ("user", "{input}") ]) # 用管道符 | 把 Prompt 和 Model 串成一条链 translate_chain = prompt | model # 调用链:输入一个 dict,返回一个 AIMessage result = translate_chain.invoke({"input": "我爱写代码"}) print(result.content) # I love writing code.

你看,核心就一个管道符|。它的语义非常直观:prompt的输出,作为model的输入。prompt | model就是一条最简单的链。

这条链的执行流程是:你传入一个包含input字段的字典 →prompt根据模板渲染出完整的消息列表 → 传给modelmodel返回消息对象。整个过程,你只表达了“组装”的意图,至于数据是怎么流转的,LangChain 帮你搞定了。

2.2 Runnable 协议与管道符背后的设计智慧

那管道符两边要满足什么条件才能拼起来?这就引出了 LCEL 最核心的设计——Runnable 协议

在 LangChain 的世界里,任何实现了Runnable接口的对象都可以用|连接。Runnable 协议的标准方法就三个:

  • invoke(input): 同步调用,输入一个值,输出一个值。
  • stream(input): 流式调用,返回一个迭代器,逐块产出输出。这个对提升用户体验非常重要,你的应用可以实现“打字机”效果。
  • batch(inputs): 批量调用,传入一个输入列表,返回一个输出列表。

这意味着什么?意味着Prompt、Model、还有我们后面要讲的各种 Tool、Retriever(检索器),本质上都是 Runnable。只要遵循这个接口,你怎么拼都行。

刚才那行代码prompt | model,在实际执行时,LangChain 会构建一个RunnableSequence对象。你可以把它理解成一条流水线,数据从一端进去,经过每个工位加工,最后从另一端出来。整个流水线自己也实现了 Runnable 接口,所以它还能继续被|接到别的东西后面。

这就给了你极大的组合自由度。比如你想在输出之后加一个字典解析的步骤,你可以写:

from langchain_core.output_parsers import StrOutputParser chain = prompt | model | StrOutputParser() result = chain.invoke({"input": "我爱写代码"}) print(result) # 直接输出字符串: I love writing code.

加了StrOutputParser之后,输出从AIMessage对象变成了纯字符串。你如果了解过 Java 里的 Stream 流或者 Linux 里的管道命令,你一定能 get 到这种设计的优雅之处——把大问题拆成一个个小问题,然后用一根管道串起来。这比传统那种层层嵌套调用函数不知道清爽了多少倍。

2.3 并联与分支:RunnableParallel 的妙用

你用管道把组件串起来,这只是流水线的“串联”。真实业务里还有大量需要“并联”的场景。

举个例子。你想让模型写一篇关于苹果公司(Apple Inc.)的介绍,为了内容全面,你需要同时查三个信息源:官网的最新新闻、某百科的基础信息、某股票论坛的股民讨论。这三个查询是相互独立的,完全可以并行执行。

如果不用框架,你要写asyncio.gather或者ThreadPoolExecutor,再去手动管理多个协程的协作,那代码写起来就非常繁琐。在 LCEL 里,这个过程被简化成了RunnableParallel

from langchain_core.runnables import RunnableParallel def search_official(query): # 模拟官网搜索 return f"官网结果: ...关于 {query} 的最新新闻..." def search_wiki(query): # 模拟百科搜索 return f"百科结果: ...关于 {query} 的历史..." # 这样可以并行执行3个不同的任务 parallel_chain = RunnableParallel( official=search_official, wiki=search_wiki, stock=search_stock ) result = parallel_chain.invoke("苹果公司") # 结果: {'official': '官网结果...', 'wiki': '百科结果...', 'stock': '股民讨论...'}

RunnableParallel允许你传入多个 Runnable(函数、链、模型调用均可),它会并发执行这些子任务,最终返回一个包含所有结果的字典。你的链就可以在一个节点同时开启多个执行分支,最后汇总结果交给下一步处理。在 LangChain 的世界里,这是实现并行化和信息聚合的基础手段,也是后面进阶玩法的垫脚石。

实用建议:在构建较复杂的链时,建议优先用具名的 RunnableParallel 分支来组织中间结果,而不是手动写字典合并。可读性和可维护性都会好很多。

3. 核心二:Agent 与工具调用 —— 让模型从“会说话”变成“会做事”

讲完了链,我们终于可以谈代理了。这是目前整个生态里最热闹、也最容易翻车的领域。

3.1 Agent 和执行链的本质区别

链(Chain)是一套预先定义好的、固定的执行路线。但真实业务中,很多时候你是无法预先定死路线的。比如你让 Agent “查一下本周公司的服务器有没有异常”,它是先查日志,还是先看告警平台,还是直接问运维知识库?这完全取决于它从工具里拿到的结果。

这就是 Agent 存在的意义:模型自己是判断者,由它来决定“下一步该调哪个工具、该不该结束”,而不是人类提前设定好。这是一次智能控制权的转移——从“开发者”转移到了“模型”。

3.2 Tool Calling:Agent 的一双手

如果说模型是 Agent 的大脑,那么工具(Tools)就是 Agent 的手。所以 Tool Calling(函数调用)就成了 Agent 最关键的基础能力。

现在的主流模型(如 GPT-4 系列、Claude 3 系列、开源界的 Qwen)都原生支持 function calling。它的逻辑是这样的:你把你定义的函数(比如get_weather(city))的 JSON Schema 描述(包括函数名、参数名、参数类型、函数功能描述)传给模型。模型看完你的指令后,不会直接调用这个函数,而是会输出一段结构化的 JSON,里面写明:“我决定要调用 get_weather,参数为 {city: "北京"}”。

然后,由你的业务代码来真正执行这个函数,把结果回传给模型,模型再根据结果生成最终给用户的回复。

在 LangChain 里,把普通 Python 函数变成工具,只需要一个装饰器:

from langchain_core.tools import tool @tool def get_weather(location: str, unit: str = "摄氏度") -> str: """获取指定地点的当前天气。对这个函数的描述要写的足够详细且语义清晰,这对模型是否调用它至关重要。""" # 这里应该是真实的天气 API 调用,我们假装返回固定数据 if location == "北京": return f"北京当前 25 度,{unit},晴。" return f"{location}天气数据暂不可获取。" # 检查工具对应的 JSON Schema,看看模型眼里你的函数长什么样 print(get_weather.args_schema.schema())

@tool装饰器会自动读取你函数的签名和类型注解,结合 docstring 生成一份 OpenAPI 格式的 JSON Schema。模型就靠这个 Schema 来理解你提供了什么能力。

这里有一个非常重要的经验:写工具的 docstring,比写函数体内的代码还重要。因为模型只通过 docstring 来理解这个工具是干嘛用的、什么时候该用它。你要是随便写一句“获取天气”,模型很可能在用户问“明天需要穿什么衣服”时,不调用你的天气工具。但如果你写“当用户询问任何与天气、温度、降水、穿衣指数相关的信息时,调用此工具”,模型调用的成功率会直线上升。

3.3 AgentExecutor 的运行机制(以 Tool Calling 为例)

有了模型(大脑)和工具(双手),接下来就是组装 Agent。在 LangChain 生态的早期和中期,大家最常用的就是AgentExecutor。它的循环逻辑非常经典,我把核心步骤拆出来:

  1. 接收用户输入,连同系统提示词(说明当前身份与任务)、可用工具的 Schema 列表、以及 Agent 上次生成的中间步骤(Thought/Action/Observation),一起发给模型。
  2. 模型判断:是应该输出“最终答案”,还是输出“下一步要调用的工具名和参数”。
  3. 如果模型决定调用工具,LangChain 就在你的本地环境执行这个工具函数,拿到 Observation(观察结果)。
  4. 把这一步的思考和观察结果,追加到消息列表里,继续发回给模型。
  5. 重复步骤 2-4,直到模型认为任务已结束,输出最终答案。

这就是经典的 ReAct 模式的工程实现。模型在循环里不断地“思考 - 行动 - 观察”。你甚至可以在控制台里打印出这个过程,你会看到模型像个人一样在思考:

Thought: 用户想知道北京天气,我需要调用 get_weather 工具。Action: get_weatherAction Input: {"location": "北京"}Observation: 北京当前 25 度,摄氏度,晴。Thought: 我已经拿到了天气信息,可以回答用户了。Final Answer: 北京现在晴,25 度,体感挺舒服的。

我们在改造客服机器人的时候,就发现一个很有意思的规律:任务越垂直、工具越精简,Agent 发挥越稳定;任务越开放、工具给得越多,Agent 就越容易自己把自己绕晕。所以别迷信“Agent 万能论”。

3.4 从 AgentExecutor 到 LangGraph 的必然性

AgentExecutor好用吗?对于简单场景,很好用。但作为早起从 Chain 切换到 Agent 的团队,我们很快撞上了两堵墙:

  • 缺乏可控性AgentExecutor内部的循环是一个黑盒。开发者很难在中间插入一个人工审批节点,或者规定“最多只能调用三次工具,否则强制结束”。
  • 缺乏状态管理:Agent 执行过程中的上下文(Context)管理很粗糙。当你需要让它操作 Excel 并生成图表这种多步骤任务时,中间状态很容易丢失,或者让模型产生幻觉。

这时候,LangChain 生态里那个“隐藏的第三个核心”就该上场了。

4. 核心三:LangGraph 图编排 —— 重新定义复杂 Agent 的可能

如果说 LCEL 是 LangChain 的“过去式”,Agent 是“现在式”,那LangGraph 就是 LangChain 生态当之无愧的“未来式”。这也是判断一个开发者是否资深的隐性分水岭——你是在用AgentExecutor硬扛,还是已经切换到图状态编排了。

用一句话概括 LangGraph 的本质:它把 Agent 的执行流程,从“一个隐式的循环”升级成了“一张可控的图”。你可能在热搜词里看到了“langgraph和langchain的区别”这个问题,我在这里给你讲透。

4.1 StateGraph:把流程画成图

AgentExecutor的问题在于循环是硬编码的,LangGraph 则允许你用节点(Node)和边(Edge)来显式定义流程。

在 LangGraph 里,有这几个你需要记住的概念:

  • State(状态):一个全局的数据对象(通常是一个 TypedDict),在整个图的执行过程中不断被更新。每个节点都能读取它,并返回一个包含部分修改的字典来更新它。这就像是图里的“共享记忆库”。
  • Node(节点):就是一个函数或一个 Runnable。它接收当前 State 作为输入,执行一些逻辑(比如“调用模型”或“调用工具”),然后返回一个字典,里面是它想更新进 State 的字段。
  • Edge(边):连接节点的路径,决定了执行的走向。
  • 条件边(Conditional Edge):这是图的灵魂。它的存在让流程可以在运行时动态改变走向——比如模型判断“还需要再调一次工具”,就走“继续”的边;判断“已有足够信息”,就走“结束”的边。

做个对比你就明白了:LCEL 里的|是静态编写流水线,LangGraph 里的节点和条件边是动态决策状态机。AgentExecutor 是 LangGraph 的一个特殊化封装实例,而非最佳形态。

4.2 一个最小可用的 LangGraph Agent 示例

这一步可能会颠覆你过去写 Agent 的方式,我们实际写一个带有“人工确认审核”环节的 Agent 节点图:

from typing import TypedDict, Literal from langgraph.graph import StateGraph, START, END from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langgraph.prebuilt import ToolNode # 1. 定义 Agent 的全局状态 class AgentState(TypedDict): user_query: str intermediate_response: str final_answer: str # 2. 定义工具节点要执行的东西 @tool def search_product(name: str) -> str: """在内部商品库检索商品名称,返回商品编号和价格。""" return f"商品 {name} 的编号是 P10086,价格是 3999 元。" # 3. 定义两个节点函数 def agent_node(state: AgentState) -> dict: """核心决策节点:模型决定要不要调用工具,还是直接回答。""" model = ChatOpenAI(model="gpt-4o", temperature=0).bind_tools([search_product]) prompt = f"用户的诉求是:{state['user_query']}。如果你觉得有必要查询商品库,请调用工具。" response = model.invoke(prompt) return {"intermediate_response": response} def human_approval_node(state: AgentState) -> dict: """模拟人工审核:实际应用中可对接邮件、企微通知等审批流。""" print(f"【人工审核】AI 中间结果:{state['intermediate_response']}") print("是否批准放行?Y/N") user_input = input().strip().upper() # 生产环境中应替换为异步审批 API return {"should_continue": "execute_tool" if user_input == "Y" else "stop"} # 4. 构建图 graph = StateGraph(AgentState) # 添加节点 graph.add_node("agent", agent_node) graph.add_node("human_approval", human_approval_node) graph.add_node("tools", ToolNode([search_product])) # 添加边 graph.add_edge(START, "agent") graph.add_edge("agent", "human_approval") # 条件边:根据人工审核结果,决定下一步走工具还是直接结束 def route_after_approval(state: AgentState) -> Literal["tools", "final"]: return "tools" if state.get("should_continue") == "execute_tool" else "final" graph.add_conditional_edges("human_approval", route_after_approval) graph.add_edge("tools", "agent") # 工具执行完,回到 agent 节点继续决策 graph.add_edge("final", END) app = graph.compile()

看到没有?在这个图里,我们做到了过去AgentExecutor完全做不到的事情——在模型决定调用工具后,插入了一个必须由真人确认的节点。模型说它要查商品库,可以,但得老板点头。这在涉及金钱交易、内容发布、代码部署等高风险场景里,是刚需中的刚需。

LangGraph 的价值不止于此。它还内置了持久化(Checkpoint)机制,支持人机交互任务的暂停与恢复;它的节点天然支持流式输出;它甚至能处理循环图,这在 LangChain 原生的 LCEL 里是没法做到的。

4.3 双 Agent 协作:从单点流程走向团队协作

LangGraph 真正让我觉得“这个框架能干活”的,是你可以在一个图里跑多个模型节点,每个模型节点扮演不同角色,这就是业界说的 Multi-Agent(多代理)协作。

我在前公司做过一个合同审查应用,就是用 LangGraph 搭的。图里有三个模型节点:

  • 风险识别模型:负责扫描合同正文,提取可能存在的法律风险点。
  • 财务评估模型:负责审阅付款条件、赔偿条款等涉及钱的部分。
  • 汇总仲裁模型:把前两个模型的意见吸收进来,解决它们之间的冲突,并生成给用户的最终风险报告。

这三个模型节点各自拿着不同的 Prompt 和 Tool(比如风险识别模型能调法条数据库,财务评估模型能调内部费率系统),它们通过共享的 State 来传递信息。这种架构下,你不会得到一个“万能 Agent”,但你会得到一个配合默契的“专业团队”。可控性、专业性、可解释性,都远胜于单体 Agent。

这也是为什么 CrewAI 今年会那么火,因为它把“多个各司其职的角色组队干活”这个概念推向了大众。但 LangGraph 作为底层编排工具,其表达能力和灵活度是更高的。

5. 开发者必须理清的三大核心关系与选型经验

最后,我们做一个横向对比总结。我知道很多人看教程最痛苦的点,就是不知道什么场景用什么方案。我把自己的选型经验分享出来,希望能帮你少走一些弯路。

5.1 LangChain、LangGraph、CrewAI:它们之间到底是什么关系

这是一个高频困惑点。“langgraph和langchain的区别”这个热搜词下,回答基本千篇一律。我用自己的话说:

  • LangChain是一个工具链生态,提供模型接入、Prompt 管理、文档加载、输出解析等基础服务。你可以把它当做一个大工具箱,LCEL 就是装这个工具箱的底板。
  • LangGraph是基于 LangChain 的底层编排引擎。如果你的应用流程是一张有分支、有循环、有状态流转的图,用它。它管的是“流程的骨架”。
  • CrewAI是更上层的、面向角色协作的封装。如果你希望快速实现“一个研究分析师 + 一个文案撰写人”这种多角色协作,用 CrewAI 上手会快一些。但在高度定制和低层控制上,它不如 LangGraph 灵活。

用盖楼来类比:LangChain 是建材市场(买水泥、钢筋、砖头),LangGraph 是施工图纸和脚手架(决定楼怎么盖),CrewAI 是精装修团队(专门负责把人住的体验感做出来)。

5.2 实际项目里的选型建议

那实际工作里,到底怎么选?这里给出我自己的判断框架:

场景特征推荐方案理由
流程固定,输入输出明确,例如“查天气”、“翻译”LCEL 链简单、高效、易维护,不需要引入复杂的状态管理
需要模型自主决定调用多个工具,且流程线性原生AgentExecutor快速实现,内置了 ReAct 循环逻辑
流程需要分支、人工介入核对、多步骤循环操作LangGraph可控性最强、状态可追踪、可插桩
需要多个智能体分工扮演不同角色,相互协作产出LangGraph/CrewAI落地优先可用 CrewAI,深度定制选 LangGraph

5.3 重要提醒

最后再分享一个贯穿始终的心态准备。LangChain 生态目前仍处于快速迭代期。你看到这篇博文的时候,AgentExecutor或许已经被官网标注为了“旧版”,取而代之的是create_tool_calling_agent等新方法。框架版本 API 变更的速度,远比你学得快。

所以,我建议你学 LangChain 生态时,可以带一些“历史视角”——去看 Chain 是怎么被设计出来的,为什么后来被 LCEL 替代;AgentExecutor有什么缺陷,为什么官方用 LangGraph 重写了所有 Agent 构造器。你才能以不变应万变。

工具会过时,API 会变更,但这套“基础工具 → 固定流水线 → 动态决策图”的设计思想,会一直在。把它装进脑子里,比记住任何具体函数签名都值钱。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 2:02:31

从零搭建WebRTC音视频通话Demo:信令、SDP与ICE实战指南

简介:面向Android开发者的WebRTC音视频通话示例工程,聚焦如何在移动端快速搭建类似微信通话体验的实时音视频方案。资源为RAR压缩包,共1460个文件,约94.92MB,包含XML布局与Android资源、Java/Kotlin源码、Class及DEX编…

作者头像 李华
网站建设 2026/9/9 2:01:08

卡密加密验证系统服务端设计与脱机部署全解析

简介:这套在线卡密加密软件企业版服务端,面向需要快速构建网络授权验证体系的小型软件团队与独立开发者。它摒弃传统机器码绑定,通过可视化后台统一管理卡密生成、加密算法、试用策略、用户注册与版本更新,内置AES-256加密和自定义…

作者头像 李华
网站建设 2026/9/9 1:57:51

Windows文件夹分类实战:从命名到归档的高效文件管理指南

你有没有经历过这种时刻:老板急着要一个文件,你在电脑里翻了五分钟还没找到;下载文件夹里堆了上千个文件,想找出上周那个PDF只能靠滚动;桌面图标多到遮住壁纸,C盘莫名其妙就满了。这些问题的根源&#xff0…

作者头像 李华
网站建设 2026/9/9 1:57:28

哈尔滨专升本机构排名不靠谱?选培训班要看这些门道

先别急着照单全收网上那些五花八门的“哈尔滨专升本培训机构排名”榜单。作为一个在哈尔滨教育圈摸爬滚打多年、自己也带过不少专升本学生的过来人,我可以很肯定地告诉你:市面上你搜到的绝大多数排名,要么是机构自己花钱买的软文,…

作者头像 李华
网站建设 2026/9/9 1:54:36

电商网站前端页面怎么写?WEB开发基础形考任务高分攻略

简介:面向国家开放大学《WEB开发基础》课程形考任务1的实践项目资源,围绕电商网站前端页面内容编写展开,适合正在完成形考作业的学员及想要练习电商首页、详情页与列表页布局的Web前端初学者。资源中包含三个核心HTML页面,以及大量…

作者头像 李华