在 LangChain 生态中,LCEL (LangChain Expression Language) 是一种声明式的链式编写方式。它将复杂的应用逻辑简化为类似 Unix 管道的语法,是官方推荐的构建生产级应用的标准路径。相比传统的嵌套构造方式,LCEL 提供了更优的可读性、健壮性和开发体验。
核心语法:管道操作符 |
LCEL 的核心在于使用管道操作符 | 连接不同的组件。数据从左向右流动,每个组件的输出会自动成为下一个组件的输入。其基本公式如下:
chain = prompt | model | parser
这种写法的优势在于,它能清晰地展示数据的流动路径,使得复杂链的构建和调试都变得直观。
为什么推荐使用 LCEL?
选择 LCEL 并非仅仅因为语法简洁,它带来了一系列生产级别的特性:
- 流式支持 (Streaming):使用 LCEL 构建的链天然支持流式输出,无需额外适配,能极大提升终端用户的体验。
- 异步支持 (Async):同一份代码无缝支持同步调用 (
invoke) 和异步调用 (ainvoke),方便根据场景灵活选择。
- 并行执行:利用
RunnableParallel 可以轻松实现多个任务的并发执行,有效缩短整体响应时间。
- 自动重试与回退:通过
with_fallbacks 可以方便地配置备用方案,当主模型调用失败时自动切换到备用模型,增强应用的鲁棒性。
- 类型检查:在运行前就能清晰地了解每个环节输入和输出的数据格式(Schema),减少运行时错误。
这些特性让 LCEL 成为从人工智能原型快速过渡到稳定服务的强大工具。
核心原语:Runnables
LCEL 的基础是各种 Runnable 组件,它们都支持 | 操作符。以下是几个关键原语:
- RunnablePassthrough
用于透传输入数据或为上下文添加新的变量,而不改变原始输入流。
- RunnableParallel
用于并行运行多个子任务。常用于将输入分发给不同的提示模板或工具,然后合并结果。
- RunnableLambda
允许你将自定义的 Python 函数包装成 LCEL 兼容的组件,提供了极大的灵活性。
实战示例:构建一个 RAG 链
下面我们通过一个完整的 RAG (检索增强生成) 流程来演示 LCEL 的实际应用。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 1. 准备基础组件
model = ChatOpenAI()
prompt = ChatPromptTemplate.from_template("基于以下上下文回答问题:\n{context}\n\n问题:{question}")
parser = StrOutputParser()
# 假设 retriever 是已定义好的向量库检索器
retriever = vectorstore.as_retriever()
# 2. 使用 LCEL 构建链
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| parser
)
# 3. 运行链
# 数据流:输入问题 -> 检索上下文并保留问题 -> 填充提示模板 -> 调用大模型 -> 解析文本输出
result = chain.invoke("LangChain 的主要优势是什么?")
print(result)
这段代码清晰地定义了一个数据处理管道:首先通过检索器获取相关上下文,与原始问题一起填入模板,交给大模型生成,最后解析出纯文本答案。
LCEL 与传统 Chain 的对比
为了更直观地理解 LCEL 的优势,我们将其与传统构造方式(如 LLMChain)进行对比:
| 特性 |
传统 Chain (如 LLMChain) |
LCEL (Runnable) |
| 组合方式 |
构造函数层层嵌套 |
使用 | 管道连接 |
| 可读性 |
步骤增多后变得臃肿 |
保持线性与简洁 |
| 中间调试 |
拦截中间步骤较复杂 |
极其简单,可利用 RunnableLambda 插入检查点 |
| 并行计算 |
需手动处理多线程 |
原生支持 RunnableParallel |
进阶技巧:配置化与故障回退
LCEL 让高级功能的实现变得异常简单。例如,配置模型故障自动回退仅需一行代码:
# 配置主模型和备用模型
primary_model = ChatOpenAI(model="gpt-4")
fallback_model = ChatOpenAI(model="gpt-3.5-turbo")
# 构建带降级策略的链
chain = prompt | primary_model.with_fallbacks([fallback_model]) | parser
当 gpt-4 因额度超限或网络问题失败时,链会自动切换至 gpt-3.5-turbo 继续执行,保障服务的可用性。
总结
LCEL 代表了 LangChain 框架向更高阶、更工程化的发展方向。它不仅仅是一种更优雅的语法糖,更重要的是它内置了流式、异步、并行、降级等生产环境必需的考量。掌握 LCEL,意味着你能更高效地将 AI 原型转化为稳定、可靠的应用服务。如果你想深入了解其设计细节,查阅技术文档中的官方说明将是很好的下一步。
|