Skip to content

Q46 · LangChain 的链式调用(Chain)和 LCEL 是什么关系? ​

客服已经从可信的政策库查到一段耳机退货规则,用户问:“耳机几天可退?”接下来要做三件事:把“用户问题”和“已核实政策”填进提示模板,交给模型生成答复,再把模型消息取成可展示的文字。这三步有固定先后顺序,前一步的输出就是后一步的输入;日常说的一条 Chain(链),就是这样一条从输入走到输出的处理路径。

LCEL 是 LangChain Expression Language(LangChain 表达式语言):用 | 等组合写法把具备共同调用接口的 Runnable(可运行组件)接起来,构造这条路径。因此可以说“用 LCEL 写了一条 chain”。但 Chain 还可能特指旧版 langchain_classic.chains.base.Chain 类,不能把这个历史类名与“处理流程”混成一个东西。LangChain 官方仍用 LCEL 称呼这种组合写法;当前参考文档把 RunnableSequence 定义为前一个 Runnable 的输出传给下一个,并说明通常用 | 构建;v1 迁移指南把 LLMChain 等旧链放入 langchain-classic。LangChain:LCEL 示例 · LangChain:RunnableSequence · LangChain:v1 迁移指南

术语与概念:这些名字各指哪一层 ​

名字零基础理解在耳机问答里的位置
Chain(普通含义)把多个步骤连成完整处理流程;它是一个工作方式的称呼从用户问题和政策到最后答复的路径
Chain(旧版类名)旧链 API 的基类,现位于 langchain-classic;它是具体代码类型老项目里可能见到的类,不是下面示例的必要依赖
LLMChain旧式“提示模板加模型”封装类;当前参考文档标为弃用并给出 Runnable 写法阅读旧教程时常见
LCEL把 Runnable 组合成处理流程的一套表达写法`prompt
Runnable能以统一方法接收输入、给出输出的组件接口提示模板、模型、解析器都可参与组合
RunnableSequence把多个 Runnable 按顺序执行的组合对象上述三个步骤用 `
ChatPromptTemplate根据给定字段制作聊天消息的模板把 question 和 policy 填入角色消息
StrOutputParser从模型输出消息取出文本字符串的解析器把模型答复变成页面可展示的文字
invoke / ainvoke对一个输入执行;后者是异步调用,适合异步环境用一份耳机问题数据运行整条链
batch / stream分别用于一批输入、单个输入的流式结果;具体效果还取决于各组件实现批量处理问句或逐步显示模型文本

这里的 question 是“耳机几天可退?”,policy 是应用已经核实的规则。提示模板不负责核实政策;模型也不能因为收到一句政策文字就自动获得订单权限。LangChain 的 Runnable 参考列出 invoke、ainvoke、batch 和 stream 等接口,并说明 Runnable 可以组合成链。LangChain:Runnable 接口

一条链里的数据怎样流动 ​

Chain 是从输入到回答的完整处理流程,LCEL 用管道符连接提示模板、模型和输出解析

按图从左向右看,整条路径叫 chain。LCEL 是把路径写出来的方法:提示模板 | 模型 | 输出解析。图中的三个步骤都可按 Runnable 方式调用;最右侧的“回答”是运行结果。实际业务里,查政策、权限校验和最终答复审查可以在这条链前后由应用负责,图只展示固定的提示、生成、解析三步。

数据的形状也在变化:

位置收到什么交给下一步什么
链入口字典 {"question": "耳机几天可退?", "policy": "…"}原样交给提示模板
提示模板question 与 policy 两个字段带系统消息、用户消息的提示值 ChatPromptValue
聊天模型提示值中的消息一条模型消息 AIMessage
文本解析器AIMessage普通 Python 字符串,供页面显示

| 在这里不是把两个字符串拼起来,而是 LangChain 给 Runnable 定义的组合操作符。左边的输出若不能作为右边的输入,整条链就会在运行时失败。例如提示模板要求 policy,调用时却只给 question,第一步就缺字段。管道能把组件连接起来,但不能自动补出缺失的业务数据。官方参考说明 RunnableSequence 按顺序传递输出到输入;它也说明中间组件的实现会影响流式输出何时开始,不能只因写了 | 就认为每一步都能逐字流式返回。LangChain:RunnableSequence 细节

一段无需模型密钥的可运行示例 ​

以下示例按 langchain-core 1.x 写法,安装 pip install 'langchain-core>=1,<2' 后可在 Python 3.10+ 运行。为避免读者先申请模型密钥,用官方 FakeListChatModel 充当模拟聊天模型:它依次返回预先写好的字符串,不会真的阅读政策或推理。代码展示的是组件怎样接起来、输入输出怎样传递;生产环境应替换为实际模型接入,并核查回答是否以政策为依据。LangChain:FakeListChatModel · LangChain:ChatPromptTemplate

代码里的 prompt 是提示模板,model 是模拟模型,parser 是文字解析器,chain 是把三者组合后的 RunnableSequence。data 是单次调用的输入字典,两个键名必须与提示模板中的 {question}、{policy} 对上。FakeListChatModel(responses=[...]) 中的列表是固定示例答复,绝不是从 policy 算出的结果。

python
from langchain_core.language_models.fake_chat_models import FakeListChatModel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是客服。只根据已核实政策回答,缺少条件时说明不足。"),
    ("human", "用户问题:{question}\n已核实政策:{policy}"),
])

model = FakeListChatModel(responses=[
    "按演示政策,耳机自签收次日起 7 个自然日内可申请退货;"
    "是否通过仍需核对订单条件。"
])
parser = StrOutputParser()

chain = prompt | model | parser

data = {
    "question": "耳机几天可退?",
    "policy": "耳机自签收次日起 7 个自然日内可申请退货,需核对订单条件。",
}
print(type(chain).__name__)
print(chain.invoke(data))

运行会先打印 RunnableSequence,再打印预设的演示答复。逐步看:from_messages 把系统要求和带占位符的用户消息组成模板;prompt.invoke(data) 会把两处 {...} 替换成输入值,得到 ChatPromptValue;model 接收消息并返回一条 AIMessage;parser 抽出文本,最终 chain.invoke(data) 返回 str。其中 type(...).__name__ 只是为了让读者看到组合对象的类型,业务代码通常只关心 invoke 的结果。LangChain:ChatPromptTemplate · LangChain:StrOutputParser

如果把输入误写成 {"question": "耳机几天可退?"} 而漏了 policy,模板会因为缺少变量而报错,模型根本不该继续回答。若 policy 虽有值却来自过期或不可信的文档,链本身也不会识别真假;需要在进入链之前检查来源、版本和适用范围。模拟模型更要特别小心:它对不同问题仍会按预设列表返回文本,所以示例能跑通只能证明接线和类型流转,不能证明真实问答准确。这就是可运行示例与生产系统的边界。

遇到旧教程的 LLMChain,怎样读才不混乱 ​

旧教程里可能写 from langchain.chains import LLMChain,再用 LLMChain(prompt=..., llm=...) 和 .run(...)。它表达的业务意思仍是“先格式化提示,再调用模型”,但不能把这段导入直接当成当前 v1 新项目的代码。LangChain v1 迁移指南写明,LLMChain 等 legacy chains 移到另装的 langchain-classic;当前 LLMChain 参考页标为 deprecated,并给出 prompt | model | StrOutputParser() 的 Runnable 替代示例;旧 Chain.run 方法本身也被标为 deprecated。LangChain:v1 迁移 · LangChain:LLMChain 参考 · LangChain:Chain.run 参考

对比同一个“提示模板 + 模型”任务时,抓住抽象层级:

看见的写法它代表什么当前阅读或新写代码时的判断
“这条 chain 接收问题并输出答案”对完整处理流程的普通称呼这个说法现在仍可用
LLMChain(...)旧版预制类阅读遗留代码时识别;新例子不要默认它还在 langchain.chains
`promptmodelparser`
chain.invoke(data)对组合后的 Runnable 执行一次先检查入口字段与每步输入输出是否兼容

LCEL 能把固定步骤组合得很清楚,也支持通过 RunnableParallel 让独立分支接收同一输入再合并;但它不会替你决定是否调用工具、如何循环、何时等待人工批准。需要复杂状态、动态分支或长时间恢复时,要按需求考虑 LangGraph 等更明确的编排方式,不能把 | 管道误认为完整 Agent 运行时。RunnableParallel 与 RunnableSequence 都是官方 Runnable 组合原语;是否采用哪一种,应从步骤依赖出发。LangChain:Runnable 组合

面试时怎样回答 ​

“Chain 可以泛指把几个处理步骤接成一条从输入到输出的流程;LCEL 是 LangChain 用来表达这种组合的写法,核心是 Runnable 接口和 | 管道。比如客服已有核实政策后,把 ChatPromptTemplate | 聊天模型 | StrOutputParser 接起来,调用 invoke 时,输入字典先变成提示消息,再变成模型消息,最后变成字符串。这条组合通常是 RunnableSequence。要注意 Chain 也可能指旧 API 的基类;旧 LLMChain 在 v1 已进入 langchain-classic 且标为弃用,不能照搬旧 import。LCEL 很适合输入输出明确的固定流程,但政策核实、权限、动态工具选择和复杂状态要另行设计。”

若面试官追问“写了 | 就一定能流式输出吗”,可以答:组合对象提供 stream 之类的统一方法,但实际流式粒度受每个组件影响;中间步骤若必须等完整输入或输出才工作,后面的流式结果也要等它结束。先查看所用组件的实现,再用真实输入测首字延迟,不能只看语法判断。LangChain:RunnableSequence 的流式说明

最后更新2026-09-26
难度P1
频率high
阅读15 min
主题langchain / chain / lcel
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题