Skip to main content

Runnable 接口

Runnable 接口是使用 LangChain 组件的基础,许多组件都实现了该接口,例如 语言模型输出解析器检索器编译后的 LangGraph 图 等。

本指南介绍了 Runnable 接口的主要概念和方法,它允许开发者以一致且可预测的方式与各种 LangChain 组件进行交互。

相关资源

Runnable 接口概述

Runnable 的设计定义了一个标准接口,使得一个 Runnable 组件可以:

  • 调用:将单个输入转换为输出。
  • 批量处理:高效地将多个输入转换为输出。
  • 流式传输:在输出生成时进行流式传输。
  • 检查:可以访问 Runnable 的输入、输出和配置的示意图信息。
  • 组合:可以使用 LangChain 表达式语言 (LCEL) 将多个 Runnables 组合在一起,创建复杂的流水线。

请查看 LCEL 速查表,了解涉及 Runnable 接口和 LCEL 表达式的常见模式。

优化的并行执行(批量)

LangChain Runnables 提供了一个内置的 batch API,允许你并行处理多个输入。

当需要处理多个独立输入时,使用此方法可以显著提高性能,因为处理可以并行执行而不是顺序执行。

批量处理的方法是:

  • batch:并行处理多个输入,并按输入的相同顺序返回结果。

batch 的默认实现是并行执行 invoke 方法。

某些 Runnables 可能会为其特定用例提供自己的 batch 实现(例如,依赖模型提供商提供的 batch API)。

tip

在使用 batch 处理大量输入时,用户可能希望控制最大并行调用数。这可以通过在 RunnableConfig 对象中设置 maxConcurrency 属性来实现。更多信息请参见 RunnableConfig

流式传输 API

流式传输对于使基于 LLM 的应用程序对最终用户响应迅速至关重要。

Runnables 提供了以下三个流式传输 API:

  1. stream:在输出生成时逐步返回 Runnable 的输出。
  2. streamEvents:一个更高级的流式传输 API,允许流式传输中间步骤和最终输出。
  3. 旧版 streamLog:一个旧版的流式传输 API,用于流式传输中间步骤和最终输出。

更多关于在 LangChain 中进行流式传输的信息,请参考 流式传输概念指南

输入和输出类型

每个 Runnable 都具有输入和输出类型。这些输入和输出类型可以是任何 TypeScript 对象,由 Runnable 自身定义。

导致 Runnable 执行的方法(例如 invokebatchstreamstreamEvents)都基于这些输入和输出类型工作。

  • invoke:接受一个输入并返回一个输出。
  • batch:接受一个输入列表并返回一个输出列表。
  • stream:接受一个输入并返回一个生成器,该生成器逐步返回输出。

输入类型输出类型 因组件而异:

组件输入类型输出类型
PromptobjectPromptValue
ChatModel一个 string、聊天消息列表或一个 PromptValueChatMessage
LLM一个 string、聊天消息列表或一个 PromptValuestring
OutputParserLLM 或 ChatModel 的输出依解析器而定
Retriever一个 stringDocument 列表
Tool一个 stringobject,取决于工具依工具而定

有关输入和输出类型的更多信息以及如何使用它们,请参考各个组件的文档。

RunnableConfig

任何用于执行 Runnable 的方法(例如 invokebatchstreamstreamEvents)都接受一个名为 RunnableConfig 的第二个参数 (API 参考)。该参数是一个对象,包含在运行时执行 Runnable 时使用的配置。

RunnableConfig 可以包含以下任意属性:

属性描述
runName用于给定 Runnable 的名称(不会被继承)。
runId此调用的唯一标识符。子调用将获得自己的唯一 run id。
tags此调用及所有子调用的标签。
metadata此调用及所有子调用的元数据。
callbacks此调用及所有子调用的回调。
maxConcurrency最大并行调用数(例如,用于 batch)。
recursionLimit调用递归的最大次数(例如,用于返回 Runnables 的 Runnables)。
configurable用于 Runnable 可配置属性的运行时值。

config 传递给 invoke 方法如下所示:

await someRunnable.invoke(someInput, {
runName: "myRun",
tags: ["tag1", "tag2"],
metadata: { key: "value" },
});

RunnableConfig 的传播

许多 Runnables 由其他 Runnables 组成,重要的是 RunnableConfig 能传播到 Runnable 所做的所有子调用中。这允许向父级 Runnable 提供运行时配置值,并由所有子调用继承。

如果不是这样,就无法设置和传播 回调tagsmetadata 等配置值,而这些值是期望被所有子调用继承的。

创建新 Runnables 有两种主要模式:

  1. 使用 LangChain 表达式语言 (LCEL) 声明式创建:

    const chain = prompt.pipe(chatModel).pipe(outputParser);
  2. 使用 自定义 Runnable(例如 RunnableLambda)或使用 tool 函数:

    const foo = (input) => {
    // 注意这里直接使用了 .invoke()
    return barRunnable.invoke(input);
    };
    const fooRunnable = RunnableLambda.from(foo);

LangChain 会尝试为这两种模式自动传播 RunnableConfig

手动传播 RunnableConfig 如下所示:

// 注意 config 参数
const foo = (input, config) => {
return barRunnable.invoke(input, config);
};
const fooRunnable = RunnableLambda.from(foo);

设置自定义运行名称、标签和元数据

RunnableConfig 对象中的 runNametagsmetadata 属性可用于为给定的 Runnable 设置自定义的运行名称、标签和元数据。

runName 是一个字符串,可用于为运行设置自定义名称。该名称将在日志和其他地方用于标识运行。它不会被子调用继承。

tagsmetadata 分别是数组和对象,可用于为运行设置自定义标签和元数据。这些值将被子调用继承。

使用这些属性对于跟踪和调试运行非常有用,因为它们将在 LangSmith 中作为可过滤和搜索的 trace 属性呈现。

这些属性也会传播到 回调,并作为每个事件的一部分出现在流式传输 API(如 streamEvents)中。

设置运行 ID

note

这是一个高级功能,大多数用户不需要使用。

如果你希望稍后引用某个运行或将其与其他系统关联,可能需要为该运行设置自定义 runId

runId 必须是一个有效的 UUID 字符串,并且 每个运行必须唯一。它用于标识父运行,子调用将自动获得自己的唯一 run id。

要设置自定义 runId,可以在调用 Runnable 时将它作为键值对传递到 config 对象中:

import { v4 as uuidv4 } from "uuid";

const runId = uuidv4();

await someRunnable.invoke(someInput, {
runId,
});

// 对 runId 做一些操作

设置递归限制

note

这是一个高级功能,大多数用户不需要使用。

某些 Runnables 可能会返回其他 Runnables,如果处理不当,可能导致无限递归。为防止这种情况,可以在 RunnableConfig 对象中设置 recursion_limit 来限制 Runnable 可以递归的次数。

设置最大并发数

如果使用 batch 方法,可以在 RunnableConfig 对象中设置 maxConcurrency 属性,以控制最大并行调用数。当你希望限制并行调用数以防止服务器或 API 过载时,这非常有用。

设置可配置项

configurable 字段用于传递 Runnable 可配置属性的运行时值。

它在 LangGraph 中与 LangGraph 持久化内存 经常使用。

它在 RunnableWithMessageHistory 中也用于类似目的,以指定 session_id 来跟踪对话历史。

设置回调

使用此选项可在运行时为 Runnable 配置 回调。这些回调将传递给 Runnable 所做的所有子调用。

await someRunnable.invoke(someInput, {
callbacks: [SomeCallbackHandler(), AnotherCallbackHandler()],
});

有关如何在 LangChain 中使用回调的更多信息,请阅读 回调概念指南

从函数创建 Runnable

你可能需要创建一个运行任意逻辑的自定义 Runnable。这在使用 LangChain 表达式语言 (LCEL) 组合多个 Runnables 并需要在某个步骤中添加自定义处理逻辑时特别有用。

从函数创建自定义 Runnable 有两种方式:

  • RunnableLambda:用于不需要流式传输的简单转换。
  • RunnableGenerator:用于需要流式传输的更复杂转换。

更多信息请参考 如何运行自定义函数 指南,了解如何使用 RunnableLambdaRunnableGenerator

info

用户不应尝试通过继承 Runnables 来创建新的自定义 Runnable。这种方式比使用 RunnableLambdaRunnableGenerator 更复杂且容易出错。


Was this page helpful?


You can also leave detailed feedback on GitHub.