问题与目标
应用加入清洗、分类、检索和生成后,继续嵌套函数会让数据形状与错误边界越来越难看清。LangChain Expression Language(LCEL)用 | 表示串行,用映射表示并行,并让组件共享 invoke、batch、stream 和异步接口。
本篇用离线 Runnable 先验证串行、并行、分支和回退,再说明接入模型后的流式边界。示例不依赖 API Key,运行结果可重复。

同一个输入先进入确定的清洗步骤,再并行提取特征;路由只选择一条业务路径,回退只接管预期的执行失败。
核心概念
RunnableSequence:前一步输出成为后一步输入,a | b是常用写法。RunnableParallel:同一输入进入多个分支,结果按键汇总。RunnableLambda:把边界清楚的 Python 函数适配成 Runnable。RunnableBranch:按条件选择一条路径,最后一项是默认分支。with_fallbacks():主链抛出异常后调用备用链,不负责掩盖业务错误。
invoke/ainvoke 处理单个输入,batch/abatch 处理多个独立输入,stream/astream 返回增量结果。批处理并不等同于服务商的 Batch API;并发数仍要受限流和资源约束控制。
可运行实现
python -m pip install "langchain-core>=1,<2"
from langchain_core.runnables import (
RunnableBranch,
RunnableLambda,
RunnableParallel,
)
clean = RunnableLambda(lambda x: {"text": x["text"].strip()})
features = RunnableParallel(
text=RunnableLambda(lambda x: x["text"]),
length=RunnableLambda(lambda x: len(x["text"])),
urgent=RunnableLambda(lambda x: "立即" in x["text"] or "告警" in x["text"]),
)
route = RunnableBranch(
(lambda x: x["urgent"], RunnableLambda(lambda x: {**x, "queue": "urgent"})),
RunnableLambda(lambda x: {**x, "queue": "normal"}),
)
primary = RunnableLambda(
lambda x: (_ for _ in ()).throw(RuntimeError("primary unavailable"))
)
fallback = RunnableLambda(lambda x: {**x, "summary": x["text"][:20]})
chain = clean | features | route | primary.with_fallbacks([fallback])
print(chain.invoke({"text": " 节点 AX-3 告警,请立即复核 "}))
print(chain.batch(
[{"text": "设备恢复"}, {"text": "温度告警"}],
config={"max_concurrency": 2},
))
输出会保留清洗后的文本、长度、紧急标识、队列和备用摘要。真实模型链可以使用同样的调用方式:
for chunk in (prompt | model).stream({"event": "节点 AX-3 已恢复"}):
print(chunk.text, end="", flush=True)
如果链尾解析器必须等待完整 JSON 才能解析,用户就无法同时得到逐 Token 的结构化对象。可以先流式展示文本,结束后再做整体校验,或使用事件流分别展示模型片段与步骤状态。
常见问题与排查
链中途出现类型错误
把每一步的输入输出写成小字典,并逐段 invoke()。LCEL 负责组合,不会自动修正键名和数据形状。
把所有函数都包装成 RunnableLambda
只有需要进入执行图、追踪或统一调用接口的步骤才需要适配。普通、稳定、可测试的领域函数仍可保持普通函数。
回退链吞掉真实错误
回退只处理预期的模型或服务不可用。参数错误、权限失败和输出违规应显式失败并记录,不能返回看似成功的降级答案。
batch() 触发限流
使用 max_concurrency,为可重试错误设置退避,并记录每项输入的对应索引。完成顺序可能与输入顺序不同的接口,需要主动恢复关联。
小结
Runnable 的价值是统一执行语义,LCEL 的价值是让数据流可见。串行、并行、路由、回退和流式都应围绕明确的数据契约组织;链越长,越需要逐步检查与追踪,而不是把复杂度藏进一个表达式。
License: CC BY-NC 4.0
Updated 2 hours ago
Was this article helpful? Give it a like.
0 comments


