跳至主要内容

如何并行调用可运行对象

先决条件

本指南假定你熟悉以下概念

RunnableParallel(也称为 RunnableMap)基元是一个对象,其值是可运行对象(或可以强制转换为可运行对象的事物,例如函数)。它以并行方式运行其所有值,并且每个值都使用对 RunnableParallel 的初始输入进行调用。最终返回值是一个对象,其中每个值的返回值都位于其对应的键下。

使用 RunnableParallels 进行格式化

RunnableParallels 可用于并行化操作,但也可用于操纵一个可运行对象的输出以匹配序列中下一个可运行对象的输入格式。你可以使用它们来拆分或分叉链,以便多个组件可以并行处理输入。稍后,其他组件可以加入或合并结果以合成最终响应。这种类型的链创建了一个计算图,如下所示

     Input
/ \
/ \
Branch1 Branch2
\ /
\ /
Combine

下面,RunnableParallel 中每个链的输入预计是一个包含 "topic" 键的对象。我们可以通过使用与该结构匹配的对象调用我们的链来满足该要求。

npm install @langchain/anthropic @langchain/cohere @langchain/core
import { PromptTemplate } from "@langchain/core/prompts";
import { RunnableMap } from "@langchain/core/runnables";
import { ChatAnthropic } from "@langchain/anthropic";

const model = new ChatAnthropic({});
const jokeChain = PromptTemplate.fromTemplate(
"Tell me a joke about {topic}"
).pipe(model);
const poemChain = PromptTemplate.fromTemplate(
"write a 2-line poem about {topic}"
).pipe(model);

const mapChain = RunnableMap.from({
joke: jokeChain,
poem: poemChain,
});

const result = await mapChain.invoke({ topic: "bear" });
console.log(result);
/*
{
joke: AIMessage {
content: " Here's a silly joke about a bear:\n" +
'\n' +
'What do you call a bear with no teeth?\n' +
'A gummy bear!',
additional_kwargs: {}
},
poem: AIMessage {
content: ' Here is a 2-line poem about a bear:\n' +
'\n' +
'Furry and wild, the bear roams free \n' +
'Foraging the forest, strong as can be',
additional_kwargs: {}
}
}
*/

API 参考

操纵输出/输入

映射可用于操纵一个可运行对象的输出以匹配序列中下一个可运行对象的输入格式。

请注意,下面 RunnableSequence.from() 调用中的对象会自动强制转换为可运行映射。对象的所有键都必须具有可运行对象的值或可以本身强制转换为可运行对象(函数转换为 RunnableLambda 或对象转换为 RunnableMap)。此强制转换还将在使用 .pipe() 方法组合链时发生。

import { CohereEmbeddings } from "@langchain/cohere";
import { PromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
import { Document } from "@langchain/core/documents";
import { ChatAnthropic } from "@langchain/anthropic";
import { MemoryVectorStore } from "langchain/vectorstores/memory";

const model = new ChatAnthropic();
const vectorstore = await MemoryVectorStore.fromDocuments(
[{ pageContent: "mitochondria is the powerhouse of the cell", metadata: {} }],
new CohereEmbeddings({ model: "embed-english-v3.0" })
);
const retriever = vectorstore.asRetriever();
const template = `Answer the question based only on the following context:
{context}

Question: {question}`;

const prompt = PromptTemplate.fromTemplate(template);

const formatDocs = (docs: Document[]) => docs.map((doc) => doc.pageContent);

const retrievalChain = RunnableSequence.from([
{ context: retriever.pipe(formatDocs), question: new RunnablePassthrough() },
prompt,
model,
new StringOutputParser(),
]);

const result = await retrievalChain.invoke(
"what is the powerhouse of the cell?"
);
console.log(result);

/*
Based on the given context, the powerhouse of the cell is mitochondria.
*/

API 参考

这里,提示的输入预计是一个包含 "context" 和 "question" 键的映射。用户输入只是问题。因此,我们需要使用我们的检索器获取上下文并将用户输入以 "question" 键的形式传递。

后续步骤

你现在已经了解了一些使用 RunnableParallel 格式化和并行化链步骤的方法。

接下来,你可能对 使用自定义逻辑 在你的链中感兴趣。


此页面对您有帮助吗?


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