跳到主要内容

如何向链的状态添加值

另一种在链的步骤之间传递数据的方式是保持链状态的当前值不变,同时在给定键下分配新值。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 并行调用传递给它的 runnables,并使用该输入。
  • 调用 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() 在检索链中立即返回源文档

提示

有关安装集成包的通用说明,请参阅此部分

yarn 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 的输出在可用时立即以块的形式流式传输。

下一步

现在您已经学习了如何通过链传递数据,以帮助格式化流经链的数据。

要了解更多信息,请参阅本节中关于 runnables 的其他操作指南。


此页是否对您有帮助?


您也可以留下详细的反馈 在 GitHub 上.