langchain 中RunnableMap 和RunnableParallel区别
在 LangChain 中,RunnableMap和 RunnableParallel都是用来处理多个并行任务的工具,但它们在用途、设计目的和使用方式上有显著的区别。
为了帮你清晰理解它们的差异,我们从以下几个方面进行对比:
一、基本概念
|
名称 |
类型 |
用途简述 |
|---|---|---|
|
RunnableMap |
映射类(Mapping) |
用于对输入数据的每个键值对,分别运行不同的 Runnable,即对输入中的每个字段调用不同的链或工具,返回一个映射(dict)结果。 |
|
RunnableParallel |
并行执行类 |
用于同时运行多个 Runnable(或链),这些 Runnable 通常共享同一个输入,目的是并行调用多个工具/链并合并结果。 |
🧠 简单记忆:
RunnableMap:对输入中的每个字段,用不同的逻辑/链去处理 → 映射不同处理逻辑到不同字段。
RunnableParallel:将多个链/工具并行执行,通常这些链都使用相同的输入,然后合并它们的输出。
二、类来源(LangChain 版本相关)
-
这两个类通常来自:
from langchain_core.runnables import RunnableMap, RunnableParallel在较新的 LangChain 版本中(尤其是基于
langchain-core的版本),它们是核心组件。
⚠️ 注意:在非常旧的 LangChain 版本中,可能没有直接暴露这两个名字,或者它们可能以不同方式实现(比如通过
dict输入或自定义组合)。
三、RunnableMap 详解
✅ 用途:
-
你对输入数据中的每个字段(key)想要应用不同的 Runnable(或函数/链)。
-
相当于对输入字典的每个 key-value,使用不同的处理逻辑,最终返回一个新的字典,其中每个 key 对应处理后的结果。
🧩 工作方式:
-
接收一个 Dict[str, Runnable],即:每个 key 对应一个 Runnable。
-
输入也是一个字典,RunnableMap 会将输入中的每个字段交给对应的 Runnable 处理。
-
输出也是一个字典,结构与输入类似,但 value 是经过各个 Runnable 处理后的结果。
📌 示例:
from langchain_core.runnables import RunnableMap
from langchain_core.messages import HumanMessage
from langchain_community.llms import ChatOpenAI # 或其他 LLM
# 假设有两个简单的处理逻辑(可以是 RunnableLambda 或 LLM Chain)
def process_name(data):
return f"Processed Name: {data['name'].upper()}"
def process_age(data):
return f"Processed Age: {int(data['age']) + 1}"
# 构造 RunnableMap
runnable_map = RunnableMap({
"processed_name": lambda x: process_name(x), # 或者直接用 RunnableLambda
"processed_age": lambda x: process_age(x),
})
# 输入
input_data = {"name": "alice", "age": "30"}
# 调用
output = runnable_map.invoke(input_data)
print(output)
# 输出类似:
# {
# 'processed_name': 'Processed Name: ALICE',
# 'processed_age': 'Processed Age: 31'
# }
🎯 重点:每个字段(name, age)由不同的函数/逻辑处理,但输入是同一个字典,你可以根据字段名选择处理哪个字段。
你也可以使用 RunnableLambda或实际的 Chain 对象作为值。
四、RunnableParallel 详解
✅ 用途:
-
你希望同时运行多个 Runnable(或工具/链),这些 Runnable 都接收相同的输入,并且你想要并行地调用它们,然后合并它们的输出结果。
-
类似于并发调用多个 API / 工具 / 模块,然后汇总结果。
🧩 工作方式:
-
接收一个 Dict[str, Runnable],每个 key 是输出结果中的字段名,value 是对应的 Runnable。
-
所有 Runnable 都接收相同的输入,然后并行执行(在支持异步/并发的环境下)。
-
返回一个合并的字典,key 是你在 RunnableParallel 中定义的字段名,value 是对应 Runnable 的输出。
📌 示例:
from langchain_core.runnables import RunnableParallel
from langchain_core.messages import HumanMessage
from langchain_community.llms import ChatOpenAI # 或其他 LLM
# 假设我们有两个独立的 Chain 或工具(这里用 Lambda 模拟)
chain_a = RunnableLambda(lambda x: f"A处理结果: {x['query']} - A")
chain_b = RunnableLambda(lambda x: f"B处理结果: {x['query']} - B")
# 构建 RunnableParallel
parallel = RunnableParallel({
"result_a": chain_a,
"result_b": chain_b,
})
# 输入
input_data = {"query": "今天天气怎么样?"}
# 调用
output = parallel.invoke(input_data)
print(output)
# 输出类似:
# {
# 'result_a': 'A处理结果: 今天天气怎么样? - A',
# 'result_b': 'B处理结果: 今天天气怎么样? - B'
# }
🎯 重点:多个链/工具都用同一个输入(比如用户的 query),并行执行,返回各自的结果,并合并为一个大的字典。
五、RunnableMap vs RunnableParallel 对比表
|
特性 |
RunnableMap |
RunnableParallel |
|---|---|---|
|
目的 |
对输入中的每个字段使用不同的处理逻辑 |
并行运行多个 Runnable,通常共享同一个输入 |
|
输入 |
一个字典,通常包含多个字段 |
一个字典(通常是统一的输入,如 user query) |
|
Runnable 分配方式 |
每个字段(key)对应一个 Runnable,处理该字段 |
每个 key 是输出字段名,value 是一个 Runnable,都用相同输入 |
|
输出 |
一个字典,key 与输入字段对应,value 是处理结果 |
一个字典,key 是你定义的(如 result_a),value 是对应 Runnable 的输出 |
|
典型使用场景 |
输入数据有多个部分,需要对每部分做不同处理 |
同时调用多个工具/模型/链,比如同时查知识库 + 调用 LLM + 搜索 |
|
是否并行执行 |
不一定(取决于具体实现,通常是顺序) |
通常是设计为可以并行(尤其在异步环境下) |
|
类比 |
类似于对字典的每个字段 apply 不同函数 |
类似于并发调用多个服务,合并结果 |
六、什么时候用哪一个?
|
场景 |
推荐使用 |
|---|---|
|
我有一个输入字典,里面的每个字段(如 name, age, location)需要用不同的逻辑处理,比如对 name 做大写,对 age 做 +1 |
✅ RunnableMap |
|
我有一个输入(如用户的问题),希望同时做多件事情:比如同时调用一个搜索工具、调用一个 LLM、调用一个数据库,然后汇总所有结果 |
✅ RunnableParallel |
|
我想把多个独立的功能模块组合起来,并行执行,提升效率 |
✅ RunnableParallel |
|
我想对输入中的不同部分定制不同处理,比如对字段 A 用 Chain A,字段 B 用 Chain B |
✅ RunnableMap |
七、高级用法:组合使用
在实际的复杂工作流中,你可能会 同时使用 RunnableParallel 和 RunnableMap,比如:
-
先用
RunnableParallel同时调用多个工具获取信息, -
然后用
RunnableMap对返回的多个结果做进一步处理。
或者:
-
用
RunnableMap对输入的不同字段预处理, -
再用
RunnableParallel并发调用多个下游任务。
八、总结一句话
|
Runnable |
一句话解释 |
|---|---|
|
RunnableMap |
对输入字典的每个字段,使用不同的处理逻辑,返回处理后的字段映射。适合字段级定制处理。 |
|
RunnableParallel |
将多个 Runnable 并行运行,通常使用相同的输入,返回合并的多个结果。适合多任务并发执行。 |
九、附加提示
-
在 LangChain Graph(如 Agent 图、Workflow) 中,这两个工具也经常被用来构建节点之间的逻辑流。
-
如果你使用的是 LangChain v0.1.x 或更早,可能没有直接的
RunnableMap或RunnableParallel,而是通过字典 + 自定义组合实现类似功能。 -
在 LangChain 0.2.x 及之后(基于 langchain-core),这两个是官方推荐的标准组件,功能清晰、组合灵活。
🔗
更多推荐
所有评论(0)