链式调用 (Chains)
使用 LCEL 构建复杂的工作流
什么是 LCEL?
LCEL (LangChain Expression Language) 是 LangChain 1.0 的声明式链式语法,使用 | 操作符组合组件。
python
# LCEL 基本语法
chain = prompt | model | parser
# 等价于传统写法:
# chain = prompt | model | parser
Runnable 接口
所有 LCEL 组件都实现 Runnable 接口,提供统一的方法:
| 方法 | 说明 |
|---|---|
stream() |
流式输出 |
invoke() |
同步调用 |
ainvoke() |
异步调用 |
batch() |
批量处理 |
abatch() |
异步批量处理 |
map() |
并行映射 |
基础链构建
简单链
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
# 创建组件
prompt = ChatPromptTemplate.from_template("讲个关于{topic}的笑话")
llm = ChatOpenAI(model="gpt-4o")
parser = StrOutputParser()
# 用 | 组合成链
joke_chain = prompt | llm | parser
# 调用
result = joke_chain.invoke({"topic": "程序员"})
print(result)
并行执行
python
from langchain_core.runnables import RunnableParallel
# 并行链:同时执行多个操作
chain = RunnableParallel(
joke=prompt | llm | parser,
count=prompt | llm | StrOutputParser() | len
)
# 同时获取笑话和字数
result = chain.invoke({"topic": "AI"})
print(result)
# 输出: {'joke': '...', 'count': 150}
路由链
python
from langchain_core.runnables import RunnableLambda
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# 定义不同的处理函数
def handle_code(input):
return "这是代码问题"
def handle_general(input):
return "这是一般问题"
# 创建路由
from langchain_core.runnables import RunnableBranch
branch = RunnableBranch(
(lambda x: "代码" in x, RunnableLambda(handle_code)),
(lambda x: True, RunnableLambda(handle_general))
)
# 使用路由
result = branch.invoke("我的代码有问题")
print(result) # "这是代码问题"
复杂链式组合
顺序执行
python
from langchain_core.runnables import RunnablePassthrough
# 复杂链:先总结,再翻译,再格式化
summary_prompt = ChatPromptTemplate.from_template("总结以下内容:\n{content}")
translate_prompt = ChatPromptTemplate.from_template("翻译成英文:\n{summary}")
format_prompt = ChatPromptTemplate.from_template("格式化为列表:\n{translation}")
llm = ChatOpenAI(model="gpt-4o")
chain = (
{"content": lambda x: x["content"]}
| summary_prompt | llm
| {"summary": lambda x: x.content}
| translate_prompt | llm
| {"translation": lambda x: x.content}
| format_prompt | llm
)
中间步骤访问
python
from langchain_core.runnables import RunnablePassthrough
# RunnablePassthrough 传递输入,同时添加新字段
chain = {
"original": RunnablePassthrough(), # 保留原始输入
"processed": prompt | llm | StrOutputParser() # 处理后的输出
}
result = chain.invoke({"query": "Python 是什么"})
# 输出: {'original': {'query': '...'}, 'processed': '...'}
错误处理
重试机制
python
from langchain_core.runnables import RunnableRetryWithMessage
from langchain_openai import ChatOpenAI
# 创建带重试的链
llm = ChatOpenAI(model="gpt-4o")
retry_chain = RunnableRetryWithMessage(
llm,
max_retries=3,
retry_error_message="请重新生成"
)
result = retry_chain.invoke("讲个笑话")
回退策略
python
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
# 主模型和回退模型
primary = ChatOpenAI(model="gpt-4o")
fallback = ChatAnthropic(model="claude-sonnet-4-5-20250514")
# 创建回退链
from langchain_core.runnables import RunnableWithFallbacks
chain_with_fallback = RunnableWithFallbacks(
primary,
fallbacks=[fallback]
)
# 主模型失败时自动使用回退
result = chain_with_fallback.invoke("Hello")
LCEL 流程图
graph TD
A[输入] --> B[PromptTemplate]
B --> C[ChatModel]
C --> D[OutputParser]
D --> E[输出]
C -.->|错误| F[Fallback Model]
F --> D
动态链构建
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 动态选择模型
def create_chain(model_name: str):
if model_name == "openai":
llm = ChatOpenAI(model="gpt-4o")
elif model_name == "anthropic":
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-5-20250514")
else:
raise ValueError(f"Unknown model: {model_name}")
prompt = ChatPromptTemplate.from_template("回答:{question}")
return prompt | llm
# 使用
chain = create_chain("openai")
result = chain.invoke({"question": "什么是 LCEL?"})
✏️ 练习题
选择题
1. LCEL 中的
| 操作符的作用是?
编程题
2. 创建一个链:输入问题 → 获取答案 → 翻译成英文 → 计算字数
查看参考答案
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
# 问题 -> 答案
qa_prompt = ChatPromptTemplate.from_template("回答:{question}")
qa_chain = qa_prompt | llm
# 翻译
translate_prompt = ChatPromptTemplate.from_template("翻译成英文:{text}")
translate_chain = translate_prompt | llm
# 组合完整链
chain = (
qa_chain
| {"answer": lambda x: x.content}
| (lambda x: translate_chain.invoke({"text": x["answer"]}))
| {"translation": lambda x: x.content, "count": lambda x: len(x.content)}
)
result = chain.invoke({"question": "什么是 Python?"})
print(result) # {'translation': '...', 'count': ...}