LangChain 之 LCEL表达式语法

AI大模型工程师-应用篇 系列目录:

├── LangChain

│ ├── 提示词模板、对话管理与结构化输出核心用法

│ ├── LCEL 表达式语法(本文)

│ └── 多模态聊天机器人实战

├── Embedding

│ └── Embedding 与向量数据库简单应用------从文本向量化到 RAG 检索增强生成

├── LangGraph

│ └── 工作流与 Agent 开发(即将发布)

└── MCP

└── 协议与 Agent 通信实战(即将发布)
本文旨在从基础语法出发,系统介绍 LangChain 中 LCEL(LangChain Expression Language)表达式的核心用法,涵盖组件封装、链式调用、并行执行、数据透传、Fallback 与 Retry、动态路由等关键能力,帮助开发者快速掌握 LCEL 的编排思想,构建灵活、可靠的 AI 应用链路。

文章目录

  • 环境准备
  • [一、什么是 LCEL?](#一、什么是 LCEL?)
  • [二、Runnable------LCEL 的基本构建单元](#二、Runnable——LCEL 的基本构建单元)
    • [2.1 RunnableLambda:将函数封装为节点](#2.1 RunnableLambda:将函数封装为节点)
    • [2.2 三种调用方式:invoke / batch / stream](#2.2 三种调用方式:invoke / batch / stream)
  • 三、链的组合------串行与并行
    • [3.1 串行链:管道操作符 `|`](#3.1 串行链:管道操作符 |)
    • [3.2 并行链:RunnableParallel](#3.2 并行链:RunnableParallel)
    • [3.3 串行 + 并行:自由嵌套](#3.3 串行 + 并行:自由嵌套)
  • 四、数据透传与中间处理------RunnablePassthrough
    • [4.1 原样透传](#4.1 原样透传)
    • [4.2 assign:透传的同时追加新字段](#4.2 assign:透传的同时追加新字段)
    • [4.3 pick:从字典中筛选指定字段](#4.3 pick:从字典中筛选指定字段)
    • [4.4 实战场景:在 RAG 中透传用户问题](#4.4 实战场景:在 RAG 中透传用户问题)
  • [五、Fallback 与 Retry------链路的异常恢复策略](#五、Fallback 与 Retry——链路的异常恢复策略)
    • [5.1 with_fallbacks:降级回退](#5.1 with_fallbacks:降级回退)
    • [5.2 with_retry:自动重试](#5.2 with_retry:自动重试)
  • 六、动态路由------条件分支链
    • [6.1 基于 RunnableLambda 的简单条件分支](#6.1 基于 RunnableLambda 的简单条件分支)
    • [6.2 基于 RouterRunnable 的多路由调度](#6.2 基于 RouterRunnable 的多路由调度)
  • 七、生命周期管理------with_listeners
  • 八、实战案例
    • [8.1 案例一:多阶段链式调用------生成 + 审核](#8.1 案例一:多阶段链式调用——生成 + 审核)
    • [8.2 案例二:多阶段提示词编排------旅行规划](#8.2 案例二:多阶段提示词编排——旅行规划)
    • [8.3 案例三:带上下文记忆的对话链](#8.3 案例三:带上下文记忆的对话链)
  • [九、总结:LCEL 核心组件速查表](#九、总结:LCEL 核心组件速查表)
  • 写在最后

环境准备

本文使用 uv 作为 Python 包管理工具。将以下内容保存为项目根目录下的 pyproject.toml 文件,然后在终端执行 uv sync,即可自动创建虚拟环境并安装所有依赖:

toml 复制代码
[project]
name = "lcel-expression-demo"
version = "0.1.0"
description = "LangChain LCEL 表达式语法核心用法"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
    "dotenv>=0.9.9",
    "langchain>=1.2.10",
    "langchain-community>=0.4.1",
    "langchain-openai>=1.1.10",
    "openai>=2.24.0",
]

一、什么是 LCEL?

LCEL(LangChain Expression Language)是 LangChain 提供的一套声明式链路编排语法 。它的核心思想是:将提示词模板、大模型、输出解析器、自定义函数等组件视为可组合的节点(Runnable) ,通过管道操作符 | 将它们串联成一条完整的处理链。

下面是一个最简单的 LCEL 链路示例:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from models import llm

parser = StrOutputParser()

prompt = ChatPromptTemplate.from_messages([
    ('system', '你是一个专业的技术顾问'),
    ('human', '{input}')
])

# LCEL 表达式:用 | 将组件串联
chain = prompt | llm | parser

result = chain.invoke({'input': '用一句话解释什么是微服务架构'})
print(result)

核心价值

  • 声明式:只需描述"数据流经哪些节点",无需手动编排调用顺序。
  • 统一接口 :所有节点都实现 Runnable 协议,支持 invokebatchstream 等统一调用方式。
  • 可组合:链与链之间可以自由嵌套、并行和路由,构建出任意复杂度的工作流。

二、Runnable------LCEL 的基本构建单元

在 LCEL 中,一切皆 Runnable。提示词模板、LLM、解析器本身已经是 Runnable,而普通的 Python 函数则需要通过 RunnableLambda 包装后才能接入链路。

2.1 RunnableLambda:将函数封装为节点

核心技术RunnableLambda 可以将任意 Python 函数封装为一个标准的 Runnable 组件,使其具备 invokebatchstream 等能力。

python 复制代码
from langchain_core.runnables import RunnableLambda

def add_ten(x: int):
    return x + 10

# 将普通函数封装为 Runnable 节点
r1 = RunnableLambda(add_ten)

result = r1.invoke(4)
print(result)  # 14

2.2 三种调用方式:invoke / batch / stream

每个 Runnable 节点都原生支持以下三种调用模式:

方法 说明 返回值
invoke(input) 单次调用 单个结果
batch([input1, input2, ...]) 批量调用 结果列表
stream(input) 流式调用 生成器(逐块返回)
python 复制代码
# 1. 单次调用
r1.invoke(4)    # 14

# 2. 批量调用:对多个输入并行处理
r1.batch([4, 5])  # [14, 15]

# 3. 流式调用:适合处理大段文本的逐步输出
def tokenize(prompt: str):
    for item in prompt.split(' '):
        yield item

r2 = RunnableLambda(tokenize)
for chunk in r2.stream('This is a Dog.'):
    print(chunk)
# 输出:This / is / a / Dog.

原理解析

  • batch 本质是对多个输入并发执行 invoke,无需手动编写循环。
  • stream 要求被封装的函数是一个生成器函数 (使用 yield),返回的是一个可迭代对象,调用方可逐块接收结果,适用于大模型的流式输出场景。

三、链的组合------串行与并行

3.1 串行链:管道操作符 |

使用 | 操作符可以将多个 Runnable 节点按顺序串联。前一个节点的输出会自动作为下一个节点的输入。

python 复制代码
from langchain_core.runnables import RunnableLambda

r1 = RunnableLambda(lambda x: x + 10)
r2 = RunnableLambda(lambda x: x * 2)

# 串行链:先 +10,再 ×2
chain = r1 | r2

print(chain.invoke(2))  # (2 + 10) * 2 = 24

3.2 并行链:RunnableParallel

当需要对同一个输入同时执行多个独立操作 时,使用 RunnableParallel

python 复制代码
from langchain_core.runnables import RunnableLambda, RunnableParallel

r1 = RunnableLambda(lambda x: x + 10)
r2 = RunnableLambda(lambda x: x * 2)

# 并行链:对同一个输入同时执行 r1 和 r2
chain = RunnableParallel(add_result=r1, mul_result=r2)

print(chain.invoke(2))
# {'add_result': 12, 'mul_result': 4}

关键要点

  • RunnableParallel 的关键字参数名(如 add_resultmul_result)就是输出字典的 key。
  • 可通过 config={'max_concurrency': N} 控制最大并发数。

3.3 串行 + 并行:自由嵌套

串行链和并行链可以自由组合。例如,先串行处理,再对结果并行分叉:

python 复制代码
chain1 = r1 | r2                              # 串行:先 +10 再 ×2
chain2 = RunnableParallel(branch_a=r1, branch_b=r2)  # 并行

combined = chain1 | chain2  # 先串行,再并行
print(combined.invoke(2))
# chain1 输出 24 → chain2 对 24 同时执行 r1 和 r2
# {'branch_a': 34, 'branch_b': 48}

可以调用 chain.get_graph().print_ascii() 打印链的拓扑结构图,直观地查看数据流向。


四、数据透传与中间处理------RunnablePassthrough

在复杂链路中,经常需要将原始输入或中间数据"透传"给后续节点,同时可能需要对其进行补充或筛选。RunnablePassthrough 正是为此设计的。

4.1 原样透传

RunnablePassthrough() 不做任何修改,直接将上游数据传递给下游。

python 复制代码
from langchain_core.runnables import RunnableLambda, RunnablePassthrough

r1 = RunnableLambda(lambda x: {'key1': x})

# RunnablePassthrough() 原样透传,不做任何修改
chain = r1 | RunnablePassthrough()
print(chain.invoke(2))  # {'key1': 2}

4.2 assign:透传的同时追加新字段

.assign() 可以在透传原始数据的同时,额外计算并追加一个新字段到输出字典中。

python 复制代码
from langchain_core.runnables import RunnableLambda, RunnablePassthrough

r1 = RunnableLambda(lambda x: {'key1': x})
r2 = RunnableLambda(lambda x: x['key1'] + 10)

# 透传 r1 的输出,同时追加一个 new_key 字段(值由 r2 计算)
chain = r1 | RunnablePassthrough.assign(new_key=r2)

print(chain.invoke(2))
# {'key1': 2, 'new_key': 12}

数据流分析

  1. r1.invoke(2){'key1': 2}
  2. RunnablePassthrough.assign(new_key=r2) 会将 {'key1': 2} 同时传给 r2 和自身:
    • r2 收到 {'key1': 2},计算 2 + 10 = 12
    • 原数据 {'key1': 2} 与新字段 {'new_key': 12} 合并
  3. 最终输出:{'key1': 2, 'new_key': 12}

4.3 pick:从字典中筛选指定字段

当中间数据包含多个字段,但下游只需要其中一部分时,使用 .pick() 进行过滤。

python 复制代码
from langchain_core.runnables import RunnableLambda, RunnableParallel, RunnablePassthrough

r1 = RunnableLambda(lambda x: {'key1': x})
r2 = RunnableLambda(lambda x: x['key1'] + 10)
r3 = RunnableLambda(lambda x: x['new_key']['key2'])

# 复杂组合:并行分叉 → 筛选 → 提取
chain = (
    r1
    | RunnableParallel(
        foo=RunnablePassthrough(),
        new_key=RunnablePassthrough.assign(key2=r2)
      )
    | RunnablePassthrough().pick(['new_key'])
    | r3
)

print(chain.invoke(2))  # 12

总结

工具 能力 适用场景
RunnablePassthrough() 原样透传 保留上游数据不变
.assign(key=runnable) 透传 + 追加字段 在不丢失原数据的前提下补充信息
.pick(keys) 按 key 过滤 从复杂字典中提取下游所需的部分

4.4 实战场景:在 RAG 中透传用户问题

RunnablePassthrough 最典型的应用场景是 RAG(检索增强生成):在将检索结果注入提示词的同时,需要将用户的原始问题一并透传给模板。

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from models import llm

# 模拟一个检索器:根据问题返回相关文档片段
def fake_retriever(query: dict):
    docs = {
        "Python": "Python 是一种解释型、面向对象的高级编程语言,由 Guido van Rossum 于 1991 年发布。",
        "default": "暂未检索到相关资料。"
    }
    question = query["question"]
    return docs.get("Python", docs["default"]) if "Python" in question else docs["default"]

# RAG 提示词模板:同时需要 context(检索结果)和 question(用户原问题)
prompt = ChatPromptTemplate.from_template(
    "请根据以下参考资料回答用户问题。\n\n参考资料:{context}\n\n用户问题:{question}"
)

# 核心:RunnablePassthrough.assign 透传原始输入,同时追加 context 字段
chain = (
    RunnablePassthrough.assign(context=RunnableLambda(fake_retriever))
    | prompt
    | llm
    | StrOutputParser()
)

print(chain.invoke({"question": "Python 是什么?"}))

数据流分析

  1. 输入 {"question": "Python 是什么?"}
  2. RunnablePassthrough.assign(context=...) 同时执行两件事:
    • 透传 :保留原始的 {"question": "Python 是什么?"}
    • 追加 :调用 fake_retriever 计算 context 字段
  3. 合并后输出 {"question": "Python 是什么?", "context": "Python 是一种解释型..."}
  4. 该字典恰好匹配 prompt 模板中的 {question}{context} 两个变量

五、Fallback 与 Retry------链路的异常恢复策略

生产环境中,LLM 调用可能因网络波动、服务超时、速率限制等原因抛出异常。LCEL 在 Runnable 协议中内置了 Fallback(降级回退)Retry(自动重试) 两种异常恢复策略,保障链路的稳定运行。

5.1 with_fallbacks:降级回退

当主节点抛出异常时,自动捕获并降级至备用节点执行,确保链路不会因单点故障而中断。

python 复制代码
from langchain_core.runnables import RunnableLambda

def add_ten(x: int):
    return x + 10

r1 = RunnableLambda(add_ten)
r2 = RunnableLambda(lambda x: int(x) + 20)

# r1 为主链路,r2 为降级链路
chain = r1.with_fallbacks([r2])

# 传入字符串 '2',r1 执行 '2' + 10 (str + int) 抛出 TypeError → 自动降级至 r2
print(chain.invoke('2'))  # 22

典型应用场景:为 LLM 调用配置多模型降级策略,例如主用 GPT-4o,异常时自动回退至 DeepSeek:

python 复制代码
chain = (prompt | gpt4o_llm | parser).with_fallbacks(
    [prompt | deepseek_llm | parser]
)

5.2 with_retry:自动重试

对于瞬态故障(Transient Errors),如网络抖动、服务限流(HTTP 429),可配置自动重试策略。

python 复制代码
from langchain_core.runnables import RunnableLambda

counter = -1

def unstable_function(x):
    """模拟不稳定的函数:第一次调用会除零报错"""
    global counter
    counter += 1
    print(f'执行了 {counter} 次')
    return x / counter  # counter=0 时会抛出 ZeroDivisionError

# 最多执行 4 次(含首次调用,即最多重试 3 次)
r1 = RunnableLambda(unstable_function).with_retry(stop_after_attempt=4)
print(r1.invoke(2))
# 执行了 0 次  → 报错
# 执行了 1 次  → 成功,返回 2.0

原理with_retry 会捕获异常并在设定次数内自动重新执行该节点,适合应对网络超时、速率限制等瞬态故障。官方建议将重试范围限定在最小粒度的节点上,而非整条链路。


六、动态路由------条件分支链

某些场景下,我们需要根据运行时的中间结果来决定后续执行哪条链路。LCEL 提供了两种方式实现动态路由。

6.1 基于 RunnableLambda 的简单条件分支

python 复制代码
from langchain_core.runnables import RunnableLambda

r1 = RunnableLambda(lambda x: x + 10)
r2 = RunnableLambda(lambda x: [x] * 2)

# 根据 r1 的输出决定后续走向
chain = r1 | RunnableLambda(
    lambda x: r2 if x > 12 else RunnableLambda(lambda y: y)
)

print(chain.invoke(1))   # 1+10=11, 11<=12, 直接输出 11
print(chain.invoke(5))   # 5+10=15, 15>12, 执行 r2 → [15, 15]

原理 :RunnableLambda 内部返回的可以是另一个 Runnable,LCEL 会自动对其调用 invoke。这种模式适合分支逻辑简单的场景。

6.2 基于 RouterRunnable 的多路由调度

业务场景:用户提问涵盖多个领域(数学、物理、历史、计算机等),需要先对问题进行分类,再动态分发到对应领域的专属提示词模板处理。

python 复制代码
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda, RouterRunnable, RunnableSequence
from models import llm

# Step 1:定义各领域的专属提示词模板
physics_chain = ChatPromptTemplate.from_template(
    "你是一位物理学教授,擅长用简洁易懂的方式回答物理问题。问题:{input}"
) | llm

math_chain = ChatPromptTemplate.from_template(
    "你是一位数学家,擅长分步骤解决数学问题。问题:{input}"
) | llm

history_chain = ChatPromptTemplate.from_template(
    "你是一位历史学家,对历史事件有深入研究。问题:{input}"
) | llm

default_chain = ChatPromptTemplate.from_template(
    "输入内容无法归类,请直接回答:{input}"
) | llm

# Step 2:定义路由函数(根据分类结果分发)
def route(input):
    if '物理' in input['type']:
        return {"key": 'physics', "input": input['input']}
    elif '数学' in input['type']:
        return {"key": 'math', "input": input['input']}
    elif '历史' in input['type']:
        return {"key": 'history', "input": input['input']}
    else:
        return {"key": 'default', "input": input['input']}

# Step 3:构建路由调度器
router = RouterRunnable(runnables={
    'physics': physics_chain,
    'math': math_chain,
    'history': history_chain,
    'default': default_chain
})

# Step 4:第一个 LLM 负责分类,输出 JSON
classify_prompt = ChatPromptTemplate.from_template(
    "不要回答用户的问题,只需判断分类,类别有[物理,历史,计算机,数学,其他]。\n"
    "用户输入:{input}\n"
    "输出 JSON 格式,类别 key 为 type,用户输入 key 为 input"
)
classify_chain = classify_prompt | llm | JsonOutputParser()

# Step 5:组装完整链路
full_chain = RunnableSequence(
    classify_chain,
    RunnableLambda(route),
    router,
    StrOutputParser()
)

# 测试
inputs = [
    {"input": "光的波粒二象性如何理解?"},        # 物理问题
    {"input": "求解方程 x² - 5x + 6 = 0。"},    # 数学问题
    {"input": "丝绸之路的起源和影响是什么?"},     # 历史问题
]

for inp in inputs:
    result = full_chain.invoke(inp)
    print(f'问题: {inp["input"]}\n回答: {result}\n')

数据流分析

复制代码
用户输入 → [分类 LLM + JSON 解析] → {"type": "物理", "input": "..."}
         → [路由函数] → {"key": "physics", "input": "..."}
         → [RouterRunnable] → 自动选择 physics_chain 执行
         → [StrOutputParser] → 最终文本结果

RunnableSequence(a, b, c) 等价于 a | b | c,是管道操作符的显式写法,适合链路较长时提升可读性。


七、生命周期管理------with_listeners

LCEL 允许为节点注册生命周期回调,在节点启动和结束时自动触发,适用于日志记录、性能监控等场景。

python 复制代码
import time
from langchain_core.runnables import RunnableLambda
from langchain_core.tracers import Run

def slow_task(n: int):
    time.sleep(n)
    return n * 2

r1 = RunnableLambda(slow_task)

# 注册生命周期监听器
def on_start(run_obj: Run):
    print('节点启动时间:', run_obj.start_time)

def on_end(run_obj: Run):
    print('节点结束时间:', run_obj.end_time)

chain = r1.with_listeners(on_start=on_start, on_end=on_end)
print(chain.invoke(2))
# 节点启动时间:2025-xx-xx xx:xx:xx
# 节点结束时间:2025-xx-xx xx:xx:xx
# 4

应用场景

  • 性能监控:记录每个节点的执行耗时,定位瓶颈。
  • 日志审计:追踪链路中每一步的执行状态。
  • 异常告警 :在 on_end 回调中检测执行过程中是否出现异常。

八、实战案例

8.1 案例一:多阶段链式调用------生成 + 审核

需求:先由 LLM 根据关键词生成一段产品广告文案,再由 LLM 从专业角度对文案进行质量审核与打分。两个阶段通过 LCEL 串联为一条完整链路。

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambda
from models import llm

# 第一步:生成广告文案
prompt1 = PromptTemplate.from_template(
    '请为{product}写一段{style}风格的广告文案,字数不超过{count}。'
)

# 第二步:质量审核
prompt2 = PromptTemplate.from_template(
    '请从创意性、吸引力、准确性三个维度审核以下广告文案,满分10分,给出评分:\n{text_content}'
)

# 组装第一段链
chain1 = prompt1 | llm | StrOutputParser()

# 用 RunnableLambda 做中间数据转换,将文本映射为 prompt2 需要的字典格式
def bridge(text):
    print(text)           # 打印中间生成的文案
    print('--' * 30)
    return {'text_content': text}

# 组装完整链路
chain = chain1 | RunnableLambda(bridge) | prompt2 | llm | StrOutputParser()

print(chain.invoke({'product': '智能手表', 'style': '科技感', 'count': 200}))

关键技巧 :当两段链路的输入/输出格式不匹配时,使用 RunnableLambda 作为"桥接器"进行数据转换。也可以用字典简写代替:

python 复制代码
# 简写方式:用字典将 chain1 的输出映射为 prompt2 的输入
chain = {'text_content': chain1} | prompt2 | llm | StrOutputParser()

8.2 案例二:多阶段提示词编排------旅行规划

需求:构建三阶段处理管线------需求提取 → 行程规划 → 摘要生成。

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from models import llm

prompt1 = ChatPromptTemplate.from_template(
    "用户描述了一些旅行偏好:{input1}\n请将用户的偏好提炼为明确的出行需求:"
)

prompt2 = ChatPromptTemplate.from_template(
    "基于以下出行需求:{input2}\n请规划一份 3 天的旅行行程,并说明每日亮点:"
)

prompt3 = ChatPromptTemplate.from_template(
    "以下是详细的旅行行程规划:\n{input3}\n请浓缩为 2-3 句话的行程摘要,方便用户快速预览:"
)

# 三段式串联:prompt → LLM → prompt → LLM → prompt → LLM → 解析
chain = prompt1 | llm | prompt2 | llm | prompt3 | llm | StrOutputParser()

print(chain.invoke({'input1': '想去海边度假,预算有限,最好有当地美食体验。'}))

此处体现了 LCEL 的隐式类型转换机制:当 LLM 输出的 AIMessage 直接传入下一个 ChatPromptTemplate 时,LangChain 会自动提取 AIMessage.content 填入模板变量。因此多阶段 Prompt 可以直接串联,无需手动进行格式转换。

8.3 案例三:带上下文记忆的对话链

需求:构建一个支持多轮对话的编程助手,历史消息持久化到本地 SQLite 数据库。

python 复制代码
from langchain_community.chat_message_histories import SQLChatMessageHistory
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory
from models import llm

parser = StrOutputParser()

prompt = ChatPromptTemplate.from_messages([
    ('system', '你是一个专业的编程助手,擅长用简洁的语言解释技术概念'),
    MessagesPlaceholder(variable_name='history'),  # 历史消息占位符
    ('human', '{input}')
])

# LCEL 链路
chain = prompt | llm | parser

# 根据会话 ID 获取对应的历史记录存储
def get_session_history(sid):
    return SQLChatMessageHistory(sid, 'sqlite:///history.db')

# 包装为带记忆的 Runnable
runnable = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key='input',       # 指定输入中哪个 key 是当前消息
    history_messages_key='history'    # 指定模板中哪个占位符接收历史
)

# 同一 session_id 下的多轮对话
res1 = runnable.invoke(
    {'input': 'Python 中列表和元组有什么区别?'},
    config={'configurable': {'session_id': 'user_001'}}
)
print(res1)

res2 = runnable.invoke(
    {'input': '那它们的性能差异大吗?'},
    config={'configurable': {'session_id': 'user_001'}}
)
print(res2)  # 模型能根据历史记录理解"它们"指代列表和元组

核心要点

  • RunnableWithMessageHistory 会自动在每次调用前读取历史、调用后保存新消息。
  • session_id 用于隔离不同用户/会话的历史记录。
  • 存储后端可替换为 Redis、MongoDB 等,只需实现 BaseChatMessageHistory 接口。

九、总结:LCEL 核心组件速查表

组件 核心能力 典型应用场景
RunnableLambda 将函数封装为 Runnable 节点 自定义数据处理、桥接转换
RunnableParallel 对同一输入并行执行多个分支 多任务并发处理
RunnablePassthrough 数据透传 / 追加字段 / 字段筛选 保留上游数据、数据增强
RunnableSequence 显式串行组合(等价于 ` `)
RouterRunnable 根据 key 动态分发到不同链路 多领域路由、条件分支
with_fallbacks 异常时降级至备用链路 多模型降级、高可用保障
with_retry 瞬态故障自动重试 网络超时、速率限制
with_listeners 注册生命周期回调 日志、监控、性能分析
RunnableWithMessageHistory 自动管理对话历史 带记忆的多轮对话

写在最后

LCEL 的设计哲学是"一切皆 Runnable,万物皆可组合"。掌握了本文介绍的核心组件后,开发者可以灵活编排从简单到复杂的 AI 处理链路。结合上一篇文章中的提示词模板与结构化输出,我们已经具备了链路编排、数据流转、异常恢复等方面的基础能力。

下一篇文章将把这些知识串联起来,动手构建一个支持图片、音频等多模态输入的聊天机器人,在实战中综合运用提示词模板、LCEL 链式编排、会话记忆管理等技术,真正从零搭建一个完整的 AI 应用,敬请期待。

如有疑问或建议,欢迎留言讨论!

相关推荐
来一斤小鲜肉2 小时前
Spring AI核心:高阶API之ChatMemory
langchain·aigc
white-persist2 小时前
【红队渗透】Cobalt Strike(CS)红队详细用法实战手册
java·网络·数据结构·python·算法·安全·web安全
geovindu2 小时前
python: Adapter Pattern
java·python·设计模式·适配器模式
0wioiw03 小时前
Google-Oauth
python
2501_921649493 小时前
全球股票行情API:如何高效获取实时与逐笔成交数据
开发语言·后端·python·金融·restful
华研前沿标杆游学3 小时前
3月14日追觅科技苏州总部参观游学
python
快乐得小萝卜3 小时前
记录: python-cpp数据验证
开发语言·python
Fleshy数模3 小时前
从基础到实战:词向量转换在评价文本分析中的应用
爬虫·python·机器学习
敏编程3 小时前
一天一个Python库:requests-oauthlib - 轻松实现OAuth授权与认证
python