如何在链的状态中添加值
先决条件
一种替代的 传递数据 通过链的步骤的方法是在保留链状态的当前值的同时,在给定键下分配一个新值。 RunnablePassthrough.assign()
静态方法接受一个输入值,并将传递给 assign 函数的额外参数添加到其中。
这在常用的 LangChain 表达式语言 模式中很有用,该模式累加创建字典以用作稍后步骤的输入。
以下是一个示例
import {
RunnableParallel,
RunnablePassthrough,
} from "@langchain/core/runnables";
const runnable = RunnableParallel.from({
extra: RunnablePassthrough.assign({
mult: (input: { num: number }) => input.num * 3,
modified: (input: { num: number }) => input.num + 1,
}),
});
await runnable.invoke({ num: 1 });
{ extra: { num: 1, mult: 3, modified: 2 } }
让我们分解一下这里发生了什么。
- 链的输入是
{"num": 1}
。它传递到一个RunnableParallel
中,RunnableParallel
会并行调用它所传递的 Runnable,并使用该输入。 extra
键下的值被调用。RunnablePassthrough.assign()
保留输入字典 ({"num": 1}
) 中的原始键,并分配一个名为mult
的新键。该值是lambda x: x["num"] * 3)
,结果是3
。因此,结果是{"num": 1, "mult": 3}
。{"num": 1, "mult": 3}
被返回到RunnableParallel
调用,并被设置为extra
键的值。- 同时,
modified
键被调用。结果是2
,因为 lambda 从其输入中提取名为"num"
的键并加一。
因此,结果是 {'extra': {'num': 1, 'mult': 3}, 'modified': 2}
。
流式传输
该方法的一个便利功能是它允许值在可用时立即传递。为了展示这一点,我们将使用 RunnablePassthrough.assign()
在检索链中立即返回源文档
提示
请参阅 此部分了解有关安装集成软件包的一般说明。
- npm
- yarn
- pnpm
npm i @langchain/openai @langchain/core
yarn add @langchain/openai @langchain/core
pnpm add @langchain/openai @langchain/core
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "langchain/vectorstores/memory";
const vectorstore = await MemoryVectorStore.fromDocuments(
[{ pageContent: "harrison worked at kensho", metadata: {} }],
new OpenAIEmbeddings()
);
const retriever = vectorstore.asRetriever();
const template = `Answer the question based only on the following context:
{context}
Question: {question}
`;
const prompt = ChatPromptTemplate.fromTemplate(template);
const model = new ChatOpenAI({ model: "gpt-4o" });
const generationChain = prompt.pipe(model).pipe(new StringOutputParser());
const retrievalChain = RunnableSequence.from([
{
context: retriever.pipe((docs) => docs[0].pageContent),
question: new RunnablePassthrough(),
},
RunnablePassthrough.assign({ output: generationChain }),
]);
const stream = await retrievalChain.stream("where did harrison work?");
for await (const chunk of stream) {
console.log(chunk);
}
{ question: "where did harrison work?" }
{ context: "harrison worked at kensho" }
{ output: "" }
{ output: "H" }
{ output: "arrison" }
{ output: " worked" }
{ output: " at" }
{ output: " Kens" }
{ output: "ho" }
{ output: "." }
{ output: "" }
我们可以看到第一个块包含原始的 "question"
,因为它是立即可用的。第二个块包含 "context"
,因为检索器第二个完成。最后,generation_chain
的输出会以块的形式流式传输,只要它可用。
下一步
现在您已经了解了如何将数据传递到您的链中,以帮助格式化流经链的数据。
要了解更多信息,请参阅本部分中关于 Runnable 的其他操作指南。