跳到主要内容
Open on GitHub

Runnable 接口

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

本指南涵盖 Runnable 接口的主要概念和方法,这些概念和方法允许开发人员以一致且可预测的方式与各种 LangChain 组件进行交互。

相关资源

Runnable 接口概述

Runnable 方式定义了一个标准接口,允许 Runnable 组件

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

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

优化的并行执行(批量)

LangChain Runnables 提供了一个内置的 batch(和 batch_as_completed)API,允许您并行处理多个输入。

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

两种批量处理选项是

  • batch:并行处理多个输入,并以与输入相同的顺序返回结果。
  • batch_as_completed:并行处理多个输入,并在完成后立即返回结果。结果可能会乱序到达,但每个结果都包含用于匹配的输入索引。

batchbatch_as_completed 的默认实现使用线程池执行器并行运行 invoke 方法。这允许高效的并行执行,而无需用户管理线程,并加速了 I/O 密集型代码(例如,发出 API 请求、读取文件等)。对于 CPU 密集型操作,它不会那么有效,因为 Python 中的 GIL(全局解释器锁)会阻止真正的并行执行。

某些 Runnables 可能会提供它们自己优化的 batchbatch_as_completed 实现,以用于其特定用例(例如,依赖于模型提供商提供的 batch API)。

注意

abatchabatch_as_completed 的异步版本依赖于 asyncio 的 gatheras_completed 函数来并行运行 ainvoke 方法。

提示

当使用 batchbatch_as_completed 处理大量输入时,用户可能希望控制最大并行调用数。这可以通过在 RunnableConfig 字典中设置 max_concurrency 属性来完成。有关更多信息,请参阅 RunnableConfig

聊天模型还具有内置的速率限制器,可用于控制发出请求的速率。

异步支持

Runnables 公开了一个异步 API,允许使用 Python 中的 await 语法调用它们。异步方法可以通过“a”前缀来识别(例如,ainvokeabatchastreamabatch_as_completed)。

请参阅LangChain 异步编程指南以了解更多详情。

流式 API

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

Runnables 公开了以下三个流式 API

  1. 同步 stream 和异步 astream:在生成 Runnable 输出时产生输出。
  2. 异步 astream_events:一个更高级的流式 API,允许流式传输中间步骤和最终输出
  3. 旧版异步 astream_log:一个旧版流式 API,用于流式传输中间步骤和最终输出

请参阅流式传输概念指南,了解有关如何在 LangChain 中进行流式传输的更多详情。

输入和输出类型

每个 Runnable 都以输入和输出类型为特征。这些输入和输出类型可以是任何 Python 对象,并由 Runnable 本身定义。

导致 Runnable 执行的方法(例如,invokebatchstreamastream_events)使用这些输入和输出类型。

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

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

组件输入类型输出类型
提示字典PromptValue
ChatModel字符串、聊天消息列表或 PromptValueChatMessage
LLM字符串、聊天消息列表或 PromptValue字符串
输出解析器LLM 或 ChatModel 的输出取决于解析器
检索器字符串文档列表
工具字符串或字典,取决于工具取决于工具

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

检查模式

注意

这是一个高级功能,对于大多数用户来说是不必要的。除非您有检查 Runnable 模式的特定需求,否则您可能应该跳过本节。

在更高级的用例中,您可能希望以编程方式检查 Runnable,并确定 Runnable 期望和生成哪些输入和输出类型。

Runnable 接口提供了获取 Runnable 的输入和输出类型的 JSON Schema 以及输入和输出类型的 Pydantic 模式的方法。

这些 API 主要在内部用于单元测试,并由LangServe使用,LangServe 将这些 API 用于输入验证和 OpenAPI 文档的生成。

此外,除了输入和输出类型之外,某些 Runnables 还设置了额外的运行时配置选项。有相应的 API 可以获取 Runnable 的配置选项的 Pydantic Schema 和 JSON Schema。有关更多信息,请参阅可配置的 Runnables部分。

方法描述
get_input_schema给出 Runnable 的输入模式的 Pydantic Schema。
get_output_schema给出 Runnable 的输出模式的 Pydantic Schema。
config_schema给出 Runnable 的配置模式的 Pydantic Schema。
get_input_jsonschema给出 Runnable 的输入模式的 JSONSchema。
get_output_jsonschema给出 Runnable 的输出模式的 JSONSchema。
get_config_jsonschema给出 Runnable 的配置模式的 JSONSchema。

With_types

LangChain 将自动尝试根据可用信息推断 Runnable 的输入和输出类型。

目前,这种推断对于使用LCEL组合构建的更复杂的 Runnables 效果不佳,并且推断的输入和/或输出类型可能不正确。在这些情况下,我们建议用户使用 with_types 方法覆盖推断的输入和输出类型(API 参考)。

RunnableConfig

用于执行 runnable 的任何方法(例如,invokebatchstreamastream_events)都接受第二个参数,称为 RunnableConfigAPI 参考)。此参数是一个字典,其中包含 Runnable 的配置,该配置将在运行时在 runnable 执行期间使用。

RunnableConfig 可以定义以下任何属性

属性描述
run_name用于给定 Runnable 的名称(不继承)。
run_id此调用的唯一标识符。子调用将获得它们自己的唯一运行 ID。
tags此调用和任何子调用的标签。
metadata此调用和任何子调用的元数据。
callbacks此调用和任何子调用的回调。
max_concurrency要进行的最大并行调用数(例如,由 batch 使用)。
recursion_limit调用可以递归的最大次数(例如,由返回 Runnables 的 Runnables 使用)
configurableRunnable 的可配置属性的运行时值。

config 传递给 invoke 方法的方式如下

some_runnable.invoke(
some_input,
config={
'run_name': 'my_run',
'tags': ['tag1', 'tag2'],
'metadata': {'key': 'value'}

}
)

RunnableConfig 的传播

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

如果不是这种情况,则不可能设置和传播回调或其他配置值,如 tagsmetadata,这些值应由所有子调用继承。

创建新 Runnables 主要有两种模式

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

    chain = prompt | chat_model | output_parser
  2. 使用自定义 Runnable(例如,RunnableLambda)或使用 @tool 装饰器创建

    def foo(input):
    # Note that .invoke() is used directly here
    return bar_runnable.invoke(input)
    foo_runnable = RunnableLambda(foo)

LangChain 将尝试自动传播两种模式的 RunnableConfig

为了处理第二种模式,LangChain 依赖于 Python 的 contextvars

在 Python 3.11 及更高版本中,这开箱即用,您无需执行任何特殊操作即可将 RunnableConfig 传播到子调用。

在 Python 3.9 和 3.10 中,如果您正在使用异步代码,则需要在调用 Runnable 时手动将 RunnableConfig 传递给它。

这是由于 Python 3.9 和 3.10 中 asyncio 的任务的限制(它们不接受 context 参数)。

手动传播 RunnableConfig 的方式如下

async def foo(input, config): # <-- Note the config argument
return await bar_runnable.ainvoke(input, config=config)

foo_runnable = RunnableLambda(foo)
注意

当使用 Python 3.10 或更低版本并编写异步代码时,RunnableConfig 无法自动传播,您需要手动进行传播!当尝试使用 astream_eventsastream_log 流式传输数据时,这是一个常见的陷阱,因为这些方法依赖于正确传播 RunnableConfig 中定义的回调

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

RunnableConfig 字典的 run_nametagsmetadata 属性可用于为给定的 Runnable 设置自定义运行名称、标签和元数据。

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

tagsmetadata 属性分别是列表和字典,可用于为运行设置自定义标签和元数据。这些值由子调用继承。

使用这些属性对于跟踪和调试运行非常有用,因为它们将在LangSmith中作为跟踪属性显示,您可以在其上进行过滤和搜索。

这些属性还将传播到回调,并将作为流中每个事件的一部分出现在诸如astream_events之类的流式 API 中。

设置运行 ID

注意

这是一个高级功能,对于大多数用户来说是不必要的。

您可能需要为给定的运行设置自定义 run_id,以防您想稍后引用它或将其与其他系统关联起来。

run_id 必须是有效的 UUID 字符串,并且对于每次运行都是唯一的。它用于标识父运行,子类将自动获得它们自己的唯一运行 ID。

要设置自定义 run_id,您可以在调用 Runnable 时将其作为键值对在 config 字典中传递

import uuid

run_id = uuid.uuid4()

some_runnable.invoke(
some_input,
config={
'run_id': run_id
}
)

# Do something with the run_id

设置递归限制

注意

这是一个高级功能,对于大多数用户来说是不必要的。

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

设置最大并发数

如果使用 batchbatch_as_completed 方法,您可以在 RunnableConfig 字典中设置 max_concurrency 属性,以控制要进行的最大并行调用数。当您想限制并行调用数以防止服务器或 API 过载时,这非常有用。

提示

如果您尝试限制 Chat Model 发出的请求数量,您可以使用内置的速率限制器而不是设置 max_concurrency,这将更有效。

有关更多信息,请参阅如何处理速率限制指南。

设置可配置项

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

它在 LangGraph 中与 LangGraph 持久化内存 结合使用非常频繁。

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

此外,您可以使用它来指定任何自定义配置选项,以传递给他们创建的任何可配置 Runnable

设置回调

使用此选项在运行时为 runnable 配置回调。回调将被传递给 runnable 进行的所有子调用。

some_runnable.invoke(
some_input,
{
"callbacks": [
SomeCallbackHandler(),
AnotherCallbackHandler(),
]
}
)

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

重要提示

如果您在异步环境中使用 Python 3.9 或 3.10,则在某些情况下您必须手动将 RunnableConfig 传播到子调用。请参阅传播 RunnableConfig 部分以获取更多信息。

从函数创建 runnable

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

有两种方法可以从函数创建自定义 Runnable

  • RunnableLambda:对于不需要流式传输的简单转换,请使用此方法。
  • RunnableGenerator:当需要流式传输时,对于更复杂的转换,请使用此方法。

有关如何使用 RunnableLambdaRunnableGenerator 的更多信息,请参阅如何运行自定义函数指南。

重要提示

用户不应尝试子类化 Runnables 来创建新的自定义 Runnable。这比简单地使用 RunnableLambdaRunnableGenerator 更复杂且更容易出错。

可配置的 runnables

注意

这是一个高级功能,对于大多数用户来说是不必要的。

它有助于配置使用 LangChain 表达式语言 (LCEL) 创建的大型“链”,并被 LangServe 用于已部署的 Runnables。

有时您可能想要试验,甚至向最终用户公开,使用 Runnable 执行操作的多种不同方式。这可能涉及调整聊天模型中的温度等参数,甚至在不同的聊天模型之间切换。

为了简化此过程,Runnable 接口提供了两种在运行时创建可配置 Runnables 的方法

  • configurable_fields:此方法允许您配置 Runnable 中的特定属性。例如,聊天模型的 temperature 属性。
  • configurable_alternatives:此方法使您能够指定可以在运行时运行的替代 Runnables。例如,您可以指定可以使用的不同聊天模型的列表。

有关如何配置运行时链内部组件的更多信息,请参阅如何配置运行时链内部组件指南。


此页面是否对您有帮助?