介绍
LCEL(LangChain Expression Language) 是 LangChain 官方推出的声明式链式编排语法,核心用 | 管道符串联所有“可运行单元(Runnable)”,让流程像流水线一样清晰、可组合、可流式、可并行。
一句话:用写命令管道的方式,写 LLM 应用工作流。
设计理念
一切皆 Runnable
- 提示词模板、模型、解析器、工具、自定义函数——只要实现
Runnable接口,都能进管道。 - 统一接口:
invoke/ainvoke(同步/异步)、batch/abatch(批量)、stream/astream(流式)。
声明式而非命令式
你只描述“数据怎么走”,LangChain 负责优化执行(并行、缓存、批处理)。
原生支持流式与异步
链级天然支持逐字输出(stream),延迟接近直接调用模型。
基础语法
1)管道符 |(RunnableSequence)
顺序执行,前一个输出作为后一个输入:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("介绍一下 {topic}")
model = ChatOpenAI(model="gpt-3.5-turbo")
parser = StrOutputParser()
# LCEL 链式
chain = prompt | model | parser
# 调用
result = chain.invoke({"topic": "LCEL"})
print(result)
等价于:
result = parser.invoke(model.invoke(prompt.invoke({"topic": "LCEL"})))
2)字典 → RunnableParallel(并行)
字典会自动转为并行执行,多分支同时跑,结果合并:
from langchain_core.runnables import RunnableParallel
chain = RunnableParallel({
"summary": prompt | model | parser,
"joke": prompt | model | StrOutputParser()
})
out = chain.invoke({"topic": "AI"})
# out = {"summary": "...", "joke": "..."}
LCEL 简写(自动识别字典):
chain = {
"summary": prompt | model | parser,
"joke": prompt | model | parser
} | RunnablePassthrough()
3)常用 Runnable 工具
- RunnableLambda:把任意 Python 函数包装成 Runnable
from langchain_core.runnables import RunnableLambda upper = RunnableLambda(lambda x: x.upper()) chain = prompt | model | parser | upper - RunnablePassthrough:透传输入,用于保留原始数据或分支合并
chain = {"question": RunnablePassthrough()} | prompt | model - RunnableAssign:向字典追加字段
chain = RunnableAssign({"answer": model}) - RunnableBranch:条件分支(if-else)
from langchain_core.runnables import RunnableBranch branch = RunnableBranch( (lambda x: len(x["question"]) > 10, long_chain), short_chain )
执行模式(统一接口)
1)同步调用
result = chain.invoke({"topic": "LangChain"})
2)异步调用
import asyncio
async def main():
result = await chain.ainvoke({"topic": "LangChain"})
asyncio.run(main())
3)批量处理
results = chain.batch([{"topic": "AI"}, {"topic": "Python"}])
4)流式输出(核心优势)
for chunk in chain.stream({"topic": "LCEL"}):
print(chunk, end="", flush=True)
典型场景示例
场景1:检索增强(RAG)
# retrieval_chain = 检索器 | 格式化文档
# rag_chain = {"context": retrieval_chain, "question": RunnablePassthrough()} | prompt | model | parser
场景2:多工具 Agent
from langchain.agents import create_tool_calling_agent, AgentExecutor
tools = [tool1, tool2]
agent = create_tool_calling_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)
# LCEL 可直接嵌入:chain = prompt | agent_executor
场景3:多分支并行
chain = {
"code": code_prompt | model | code_parser,
"explanation": explain_prompt | model | StrOutputParser()
} | RunnablePassthrough()
LCEL 优势总结
- 简洁易读:用
|替代多层嵌套,逻辑一目了然。 - 性能更好:自动并行、流式、批处理优化,减少延迟。
- 可组合强:任意 Runnable 自由拼接,支持复杂分支与循环。
- 调试友好:每一步可单独测试,
RunnablePassthrough方便查看中间结果。 - 官方主推:LangChain 0.1+ 核心演进方向,旧 Chain 逐步弃用。
与旧 Chain 对比
| 特性 | 旧 Chain(SequentialChain) | LCEL | |
|---|---|---|---|
| 语法 | 嵌套、样板代码多 | ` | ` 管道,极简 |
| 流式 | 支持差 | 原生逐字输出 | |
| 并行 | 需手动写 | 字典自动并行 | |
| 异步 | 支持有限 | 原生 async/await |
|
| 可扩展性 | 弱 | 强,任意 Runnable 组合 |
使用注意
- 字典不是 Runnable:
{"a": ...}不能直接调用.invoke,必须放在管道中或显式RunnableParallel。 - 输入输出类型匹配:前一个输出必须和后一个输入兼容,否则报错。
- 流式时异常处理:
stream中出错会中断,建议外层加 try/except。
完整可运行代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 1. 组件定义
prompt = ChatPromptTemplate.from_template("用3句话介绍一下 {topic}")
model = ChatOpenAI(model="gpt-3.5-turbo", api_key="YOUR_KEY")
parser = StrOutputParser()
# 2. LCEL 链
chain = prompt | model | parser
# 3. 调用
if __name__ == "__main__":
# 同步
print("=== 同步 ===")
print(chain.invoke({"topic": "LCEL"}))
# 流式
print("\n=== 流式 ===")
for chunk in chain.stream({"topic": "LCEL"}):
print(chunk, end="", flush=True)