LangChain 1.3 完全教程:从入门到精通 - Part 5: LCEL(LangChain Expression Language)

Part 5: LCEL(LangChain Expression Language)

文章目录

    • [Part 5: LCEL(LangChain Expression Language)](#Part 5: LCEL(LangChain Expression Language))
      • [5.1 LCEL 概述](#5.1 LCEL 概述)
      • [5.2 Runnable 接口详解](#5.2 Runnable 接口详解)
        • 所有方法表格
        • [完整 Demo](#完整 Demo)
        • [with_retry 和 with_fallbacks](#with_retry 和 with_fallbacks)
      • [5.3 管道操作符 |](#5.3 管道操作符 |)
      • [5.4 RunnablePassthrough](#5.4 RunnablePassthrough)
      • [5.5 RunnableParallel](#5.5 RunnableParallel)
      • [5.6 RunnableLambda](#5.6 RunnableLambda)
      • [5.7 RunnableBranch](#5.7 RunnableBranch)
      • [5.8 配置与运行时修改](#5.8 配置与运行时修改)
      • [5.9 错误处理](#5.9 错误处理)
      • [5.10 LCEL 最佳实践](#5.10 LCEL 最佳实践)

5.1 LCEL 概述

LCEL 是 LangChain 的核心创新,用声明式语法组合各种组件。
类比 :LCEL 就像 Linux 管道 cat file | grep "error" | sort,在 LCEL 中:prompt | model | parser
Runnable

(核心接口)
统一方法签名
可组合组件
invoke / batch / stream
ainvoke / abatch / astream
RunnablePassthrough
RunnableLambda
RunnableParallel
RunnableBranch


5.2 Runnable 接口详解

所有方法表格
方法 说明 同步/异步
invoke(input) 单次调用 同步
batch(inputs) 批量调用 同步
stream(input) 流式调用 同步
ainvoke(input) 单次调用 异步
abatch(inputs) 批量调用 异步
astream(input) 流式调用 异步
pick(keys) 选择特定字段 -
assign(mapping) 添加字段 -
map() 对列表元素逐一应用 -
with_fallbacks(fallbacks) 设置备用方案 -
with_retry() 设置重试策略 -
with_config(config) 设置运行时配置 -
完整 Demo
python 复制代码
import asyncio
from dotenv import load_dotenv
load_dotenv()

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableParallel

prompt = ChatPromptTemplate.from_template("用一句话解释{concept}")
model = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
chain = prompt | model | StrOutputParser()

# 1. invoke
result = chain.invoke({"concept": "量子计算"})
print(result)

# 2. batch
results = chain.batch([{"concept": "机器学习"}, {"concept": "深度学习"}])
for r in results:
    print(r)

# 3. stream
for chunk in chain.stream({"concept": "AI"}):
    print(chunk, end="", flush=True)
print()

# 4-6. 异步方法
async def async_demo():
    result = await chain.ainvoke({"concept": "区块链"})
    print(result)
    results = await chain.abatch([{"concept": "云计算"}])
    async for chunk in chain.astream({"concept": "物联网"}):
        print(chunk, end="", flush=True)
    print()

asyncio.run(async_demo())

# 7. pick
parallel = RunnableParallel(
    concept=RunnablePassthrough(),
    explanation=chain,
)
picked = parallel.pick("explanation")
print(picked.invoke("Python"))

# 8. assign
assigned = parallel.assign(length=lambda x: len(x["explanation"]))
result = assigned.invoke("Python")
print(f"长度: {result['length']}")

# 9. map
simple = ChatPromptTemplate.from_template("用2个字概括{c}") | model | StrOutputParser()
mapped = simple.map()
results = mapped.invoke(["Python", "Java", "Go"])
with_retry 和 with_fallbacks
python 复制代码
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

chain = ChatPromptTemplate.from_template("解释{concept}") | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()

# with_retry:自动重试
reliable = chain.with_retry(
    stop_after_attempt=3,
    wait_exponential_multiplier=1,
    wait_exponential_max=10,
)

# with_fallbacks:备用方案
backup = ChatPromptTemplate.from_template("简单解释{concept}") | ChatOpenAI(model="gpt-4o-mini", temperature=0.0) | StrOutputParser()
fault_tolerant = chain.with_fallbacks([backup])
result = fault_tolerant.invoke({"concept": "Python"})

# with_config:运行时配置
configured = chain.with_config(
    run_name="my_chain",
    tags=["tutorial"],
    metadata={"version": "1.0"},
)

5.3 管道操作符 |

数据流动图

最终结果 OutputParser ChatModel PromptTemplate 用户输入 最终结果 OutputParser ChatModel PromptTemplate 用户输入 填充模板变量 调用 LLM 提取文本 {"topic": "AI"} "解释什么是AI" AIMessage "AI是..."

python 复制代码
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template("用一句话解释{concept}")
model = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
parser = StrOutputParser()

# 管道组合
chain = prompt | model | parser
result = chain.invoke({"concept": "量子纠缠"})
print(result)

# 验证数据流
step1 = prompt.invoke({"concept": "量子纠缠"})  # ChatPromptValue
step2 = model.invoke(step1)                      # AIMessage
step3 = parser.invoke(step2)                     # str

5.4 RunnablePassthrough

python 复制代码
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini")

# 基本用法:透传输入
pt = RunnablePassthrough()
print(pt.invoke("你好"))  # "你好"

# assign:添加字段
enriched = RunnablePassthrough.assign(
    greeting=lambda x: f"你好,{x['name']}!",
    is_adult=lambda x: x["age"] >= 18,
)
result = enriched.invoke({"name": "张三", "age": 25})
print(result)  # {'name': '张三', 'age': 25, 'greeting': '你好,张三!', 'is_adult': True}

# 在 RunnableParallel 中保留原始输入
analysis = ChatPromptTemplate.from_template("分析情感:{text}") | model | StrOutputParser()
parallel = RunnableParallel(
    original=RunnablePassthrough(),
    sentiment=analysis,
)
result = parallel.invoke("今天天气真好!")
print(f"原文: {result['original']}")
print(f"情感: {result['sentiment']}")

5.5 RunnableParallel

python 复制代码
from langchain_core.runnables import RunnableParallel
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini")

analysis = RunnableParallel(
    summary=ChatPromptTemplate.from_template("总结:{text}") | model | StrOutputParser(),
    sentiment=ChatPromptTemplate.from_template("情感分析:{text}") | model | StrOutputParser(),
    keywords=ChatPromptTemplate.from_template("提取3个关键词:{text}") | model | StrOutputParser(),
)

result = analysis.invoke({"text": "新版本性能提升50%,但安装有些复杂。"})
print(f"摘要: {result['summary']}")
print(f"情感: {result['sentiment']}")
print(f"关键词: {result['keywords']}")

# 多语言翻译
parallel = RunnableParallel(
    chinese=ChatPromptTemplate.from_template("翻译成中文:{text}") | model | StrOutputParser(),
    japanese=ChatPromptTemplate.from_template("翻译成日文:{text}") | model | StrOutputParser(),
)
result = parallel.invoke({"text": "Hello, World!"})

5.6 RunnableLambda

python 复制代码
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# 包装自定义函数
def word_count(text: str) -> int:
    return len(text)

def add_prefix(text: str) -> str:
    return f"[AI助手] {text}"

count_runnable = RunnableLambda(word_count)
print(count_runnable.invoke("Hello World"))  # 11

# 在链中使用
model = ChatOpenAI(model="gpt-4o-mini")
chain = (
    ChatPromptTemplate.from_template("解释{concept}")
    | model
    | StrOutputParser()
    | RunnableLambda(add_prefix)  # 给输出添加前缀
)
result = chain.invoke({"concept": "Python"})
print(result)  # [AI助手] Python 是一种...

5.7 RunnableBranch

python 复制代码
from langchain_core.runnables import RunnableBranch
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini")

short_chain = ChatPromptTemplate.from_template("简短回答:{text}") | model | StrOutputParser()
long_chain = ChatPromptTemplate.from_template("详细回答:{text}") | model | StrOutputParser()

branch = RunnableBranch(
    (lambda x: len(x) < 20, short_chain),  # 短文本
    long_chain,                             # 默认(长文本)
)

print(branch.invoke("什么是AI?"))  # 简短回答
print(branch.invoke("请详细解释人工智能的发展历史、技术分支和应用场景")[:100])  # 详细回答

5.8 配置与运行时修改

python 复制代码
from langchain_core.runnables import ConfigurableField
from langchain_openai import ChatOpenAI

# ConfigurableField:运行时动态修改参数
model = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=ConfigurableField(
        id="temperature",
        name="Temperature",
        description="控制随机性",
    ),
)

result = model.invoke("你好")  # 使用默认 temperature
result = model.invoke("你好", config={"configurable": {"temperature": 0.0}})  # 运行时修改

5.9 错误处理

python 复制代码
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

chain = ChatPromptTemplate.from_template("解释{concept}") | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()

# with_retry 参数
reliable = chain.with_retry(
    stop_after_attempt=3,              # 最大尝试次数
    retry_if_exception_type=(Exception,),  # 重试的异常类型
    wait_exponential_multiplier=1,     # 初始等待 1 秒
    wait_exponential_max=10,           # 最大等待 10 秒
)

# with_fallbacks 参数
backup = ChatPromptTemplate.from_template("简单解释{concept}") | ChatOpenAI(model="gpt-4o-mini", temperature=0.0) | StrOutputParser()
fault_tolerant = chain.with_fallbacks(
    [backup],                       # 备用链列表
    exceptions_to_handle=(Exception,),  # 触发 fallback 的异常
)

5.10 LCEL 最佳实践

  1. 优先使用 LCEL:所有新代码都应该使用 LCEL 的管道语法
  2. 保持链简洁:每个链只做一件事,复杂逻辑通过组合实现
  3. 善用 RunnableParallel:独立的操作应该并行执行
  4. 添加错误处理:生产环境必须配置 retry 和 fallback
  5. 使用 with_config:添加 run_name 和 tags 便于调试和监控
  6. 类型标注 :使用 with_types() 标注输入输出类型

相关推荐
不是株19 小时前
RAG
人工智能·python·langchain
打不了嗝 ᥬ᭄19 小时前
AI 开发新纪元:读懂 LangChain 与 LangGraph,把握大模型应用开发核心
人工智能·langchain
尋找記憶的魚19 小时前
基于langchain4j的ai编程助手项目(完整篇)
java·人工智能·spring boot·langchain·ai编程
这是谁的博客?1 天前
AI Agent 架构设计与实现原理深度解析
人工智能·ai·langchain·agent·架构设计
小龙在山东2 天前
基于 langchain 和通义千文 qwen-max 模型实现知识问答
langchain
糖果店的幽灵2 天前
LangChain 1.3 完全教程:从入门到精通-Part 4: Output Parsers(输出解析器)
langchain
wuxinyan1232 天前
工业级大模型学习之路024:LangChain零基础入门教程(第七篇):RAG 系统评估、全链路调优
人工智能·python·学习·langchain
专职2 天前
LangChain多模态输入与自定义输出
langchain