RunnableParallel 原语本质上是一个字典,其值是可运行组件(或可以转换为可运行组件的内容,如函数)。它并行运行其所有值,每个值都使用 RunnableParallel 的整体输入进行调用。最终返回值是一个字典,其中包含每个值的结果,这些结果位于其适当的键下。
使用 RunnableParallels 格式化
RunnableParallels 可用于并行化操作,也可以用于将一个可运行组件的输出调整为匹配序列中下一个可运行组件的输入格式。您可以使用它们来拆分或分叉链,以便多个组件可以并行处理输入。稍后,其他组件可以加入或合并结果以综合最终响应。这种类型的链创建了一个如下所示的计算图:
Input
/ \
/ \
Branch1 Branch2
\ /
\ /
Combine
以下示例中,提示的输入是一个包含 "context" 和 "question" 键的映射。用户输入只是问题。因此我们需要使用我们的检索器获取上下文,并将用户输入作为 "question" 键传递。
from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
# 创建 FAISS 实例
vectorstore = FAISS.from_texts(
["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
# 创建检索器
retriever = vectorstore.as_retriever()
# 定义提示模板
template = """
Answer the question based only on the following context:
{context}
Question: {question}
"""
# 创建 ChatPromptTemplate 实例
prompt = ChatPromptTemplate.from_template(template)
# 创建 ChatOpenAI 实例
model = ChatOpenAI()
# 创建检索链
retrieval_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
# 调用检索链
retrieval_chain.invoke("where did harrison work?")
输出示例:
'Harrison worked at Kensho.'
::: {.callout-tip}
注意,当将 RunnableParallel 与另一个可运行组件组合时,我们甚至不需要将我们的字典包装在 RunnableParallel 类中 —— 类型转换由系统自动处理。在链的上下文中,这些是等价的:
:::
{"context": retriever, "question": RunnablePassthrough()}
RunnableParallel({"context": retriever, "question": RunnablePassthrough()})
RunnableParallel(context=retriever, question=RunnablePassthrough())
使用 itemgetter 作为简写
注意,您可以使用 Python 的 itemgetter 作为从映射中提取数据的简写,与 RunnableParallel 结合使用。您可以在 Python 文档中找到有关 itemgetter 的更多信息。
以下示例中,我们使用 itemgetter 从映射中提取特定键:
from operator import itemgetter
from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
vectorstore = FAISS.from_texts(
["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever()
template = """Answer the question based only on the following context:
{context}
Question: {question}
Answer in the following language: {language}
"""
prompt = ChatPromptTemplate.from_template(template)
chain = (
{
"context": itemgetter("question") | retriever,
"question": itemgetter("question"),
"language": itemgetter("language"),
}
| prompt
| model
| StrOutputParser()
)
chain.invoke({"question": "where did harrison work", "language": "italian"})
输出示例:
'Harrison ha lavorato a Kensho.'
并行化步骤
RunnableParallels 使得执行多个可运行组件并行化变得容易,并可以将这些可运行组件的输出作为映射返回。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel
from langchain_openai import ChatOpenAI
# 创建 ChatOpenAI 实例
model = ChatOpenAI()
# 创建笑话链
joke_chain = ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
# 创建诗歌链
poem_chain = (
ChatPromptTemplate.from_template("write a 2-line poem about {topic}") | model
)
# 创建并行链
map_chain = RunnableParallel(joke=joke_chain, poem=poem_chain)
# 调用并行链
map_chain.invoke({"topic": "bear"})
输出示例:
{
'joke': AIMessage(content="..."),
'poem': AIMessage(content="In the quiet of the forest, the bear roams free\nMajestic and wild, a sight to see.")
}
并行性
RunnableParallel 也适用于并行运行独立进程,因为映射中的每个可运行组件都是并行执行的。例如,我们可以看到我们之前的 joke_chain、poem_chain 和 map_chain 运行时间大致相同,尽管 map_chain 执行了其他两个。
%%timeit
joke_chain.invoke({"topic": "bear"})
输出示例:
610 ms ± 64 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
poem_chain.invoke({"topic": "bear"})
输出示例:
599 ms ± 73.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
map_chain.invoke({"topic": "bear"})
输出示例:
643 ms ± 77.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
您现在已经了解了使用 RunnableParallel 格式化和并行化链步骤的一些方法。
总结:
本文介绍了如何在LangChain中使用RunnableParallel原语来并行执行多个可运行组件,并通过字典形式返回它们的输出结果。通过实际的代码示例,展示了如何使用RunnableParallel进行操作的并行化,以及如何使用itemgetter来简化从映射中提取数据的过程。此外,还讨论了RunnableParallel在执行独立进程时的效率优势。
扩展知识:
- RunnableParallel:LangChain中的一个原语,允许并行执行多个可运行组件。
- itemgetter:Python中的一个函数,用于从映射中提取特定键的值。
- 并行化:一种编程技术,允许多个进程或任务同时执行,以提高效率。
778

被折叠的 条评论
为什么被折叠?



