如何向链的状态添加值
先决条件
本指南假定您熟悉以下概念:
通过链的步骤传递数据的另一种方法是保持链状态的当前值不变,同时在给定键下分配新值。这RunnablePassthrough.assign()static 方法接受一个 input 值,并添加传递给 assign 函数的额外参数。
这在常见的 LangChain 表达式语言模式中非常有用,即以附加方式创建字典以用作后续步骤的输入。
下面是一个示例:
%pip install --upgrade --quiet langchain langchain-openai
import os
from getpass import getpass
if "OPENAI_API_KEY" not in os.environ:
os.environ["OPENAI_API_KEY"] = getpass()
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
runnable = RunnableParallel(
extra=RunnablePassthrough.assign(mult=lambda x: x["num"] * 3),
modified=lambda x: x["num"] + 1,
)
runnable.invoke({"num": 1})
API 参考:RunnableParallel | RunnablePassthrough
{'extra': {'num': 1, 'mult': 3}, 'modified': 2}
让我们分解一下这里发生的事情。
- 链的输入是
{"num": 1}.这会传递到RunnableParallel,它会调用与该输入并行传递的 runnables。 - 该值在
extrakey 中。RunnablePassthrough.assign()将原始键保留在 input dict ({"num": 1}),并分配一个名为mult.值为lambda x: x["num"] * 3),即3.因此,结果是{"num": 1, "mult": 3}. {"num": 1, "mult": 3}将返回到RunnableParallelcall 调用,并设置为 keyextra.- 同时,
modifiedkey 被调用。结果是2,因为 lambda 会提取一个名为"num"并从其输入中添加 1。
因此,结果是{'extra': {'num': 1, 'mult': 3}, 'modified': 2}.
流
此方法的一个便捷功能是,它允许值在可用时立即传递。为了演示这一点,我们将使用RunnablePassthrough.assign()要立即返回检索链中的源文档:
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)
stream = retrieval_chain.stream("where did harrison work?")
for chunk in stream:
print(chunk)
{'question': 'where did harrison work?'}
{'context': [Document(page_content='harrison worked at kensho')]}
{'output': ''}
{'output': 'H'}
{'output': 'arrison'}
{'output': ' worked'}
{'output': ' at'}
{'output': ' Kens'}
{'output': 'ho'}
{'output': '.'}
{'output': ''}
我们可以看到第一个 chunk 包含原始的"question"因为这是立即可用的。第二个数据块包含"context"因为Retriever获得第二名。最后,来自generation_chain流。
后续步骤
现在,您已经了解了如何通过链传递数据,以帮助格式化流经链的数据。
要了解更多信息,请参阅本节中有关 runnables 的其他操作指南。