RunnableConfig 是 LangChain 里的运行时配置(Runtime Configuration),用来控制和管理 Runnable 的执行

示例代码:

import time
from langchain_core.runnables import RunnableLambda, RunnableConfig

# 🚀 自定义回调函数,打印 config 里的 tags 和 metadata
def custom_callback(input_text, config: dict):
    print(f"\n[回调] 执行任务: {input_text}")
    # 使用字典访问方式获取 tags 和 metadata
    print(f"[回调] 任务标签 (tags): {config.get('tags', '未提供')}")
    print(f"[回调] 任务元数据 (metadata): {config.get('metadata', '未提供')}\n")


# 🚀 任务 1:转换为小写
def to_lowercase(text: str, config: RunnableConfig):
    custom_callback(text, config)  # 调用回调函数,打印 config 信息
    print("[Step 1] 转换为小写:", text.lower())
    return text.lower()

# 🚀 任务 2:去掉空格
def remove_spaces(text: str, config: RunnableConfig):
    custom_callback(text, config)
    print("[Step 2] 去掉空格:", text.replace(" ", ""))
    return text.replace(" ", "")

# 🚀 任务 3:反转字符串
def reverse_text(text: str, config: RunnableConfig):
    custom_callback(text, config)
    print("[Step 3] 反转字符串:", text[::-1])
    return text[::-1]

# 🚀 创建 Runnables
step1_runnable = RunnableLambda(to_lowercase)
step2_runnable = RunnableLambda(remove_spaces)
step3_runnable = RunnableLambda(reverse_text)

# 🚀 任务流水线
def text_pipeline(text: str, config: RunnableConfig):
    step1_result = step1_runnable.invoke(text, config=config)
    step2_result = step2_runnable.invoke(step1_result, config=config)
    step3_result = step3_runnable.invoke(step2_result, config=config)
    return step3_result

pipeline_runnable = RunnableLambda(text_pipeline)

# 🚀 定义 RunnableConfig,包含 tags 和 metadata
config = RunnableConfig(
    tags=["text-processing", "pipeline"],  # 任务标签
    metadata={"author": "user", "version": "1.0"}  # 任务额外信息
)

# 🚀 执行任务
result = pipeline_runnable.invoke("Hello World", config=config)

# 🚀 输出最终结果
print("\n最终结果:", result)

输出:


[回调] 执行任务: Hello World
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 1] 转换为小写: hello world

[回调] 执行任务: hello world
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 2] 去掉空格: helloworld

[回调] 执行任务: helloworld
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 3] 反转字符串: dlrowolleh

最终结果: dlrowolleh

RunnableConfig 是什么?

RunnableConfigLangChain 里的运行时配置(Runtime Configuration),用来控制和管理 Runnable 的执行

它的作用类似于:

  • 配置执行参数(比如超时时间、并发数)
  • 传递日志、回调(可以监控 Runnable 的运行情况)
  • 添加元数据(比如给每个调用打上标签,方便追踪)
  • 影响子 Runnable 的行为(如果 Runnable 由多个子 Runnable 组成,RunnableConfig 会让子 Runnable 继承父 Runnable 的设置)

🌟 你可以把 RunnableConfig 理解成执行任务时的一张「运行指令卡」,它规定了任务的运行方式和额外信息。


RunnableConfig 的作用

1. 让 Runnable 知道怎么运行

比如:

  • 设置超时时间(防止任务执行太久)
  • 限制并发数(防止任务同时执行太多次)
  • 启用调试模式(可以看到详细的日志)

2. 让 Runnable 记录运行信息

比如:

  • 添加 tags 标签(方便后续查询任务记录)
  • 添加 metadata 元数据(保存额外的信息,比如任务来源)

3. 让 Runnable 可以执行回调

比如:

  • 在任务开始、结束、出错时执行回调
  • 可以实时监控任务的执行情况

如果不用 RunnableConfig,会有什么副作用?

副作用 1:无法管理 Runnable 的运行

  • 没有超时控制,导致任务可能一直运行
  • 没有并发限制,可能会过载系统
  • 没有日志,无法调试任务运行情况

副作用 2:无法追踪任务执行

  • 任务执行时不会带 tags,后续查询不到记录
  • 任务执行的信息不会被存入 metadata
  • 任务出错时不会触发回调,无法自动处理错误

副作用 3:子 Runnable 不能继承配置

  • 任务的子步骤不会继承超时、回调等设定,导致行为不一致

什么场景下需要用 RunnableConfig

✅ 场景 1:给任务设置超时,防止死循环

from langchain_core.runnables import RunnableLambda, RunnableConfig
import time

# 定义一个带有超时控制的任务
from langchain_core.runnables import RunnableLambda, RunnableConfig
import time

# 定义一个带有超时控制的任务
def slow_task(input_text, config):
    # 从 "configurable" 子字典中获取 timeout 参数
    timeout = config.get("configurable", {}).get("timeout", 5)
    print('timeout===', timeout)
    start_time = time.time()
    
    # 假设任务执行时间5s
    while time.time() - start_time < 5: 
        time.sleep(1)  # 模拟任务执行中
        print("任务正在执行...")
    
        if time.time() - start_time >= timeout:
            raise TimeoutError("TimeoutError任务超时!")
    
    return input_text.upper()

task_runnable = RunnableLambda(slow_task)

# 设置配置,传递超时参数到 "configurable" 字段
config = RunnableConfig(configurable={"timeout": 2})

try:
    result = task_runnable.invoke("hello", config=config)
    print('result===',result)
except TimeoutError as e:
    print('出错了===',e)


输出:
在这里插入图片描述

  • 如果没有 RunnableConfig,任务会执行 10 秒,可能卡死。
  • 加上 timeout=2 后,任务会在 2 秒后超时终止。

✅ 场景 2:给任务打标签,方便后续查询

config = RunnableConfig(tags=["text-processing", "uppercase"])

result = task_runnable.invoke("hello", config=config)
  • 如果不加 tags,以后想找这个任务的执行记录会很难。
  • 加上 tags=["text-processing", "uppercase"] 后,可以用这个标签查询任务记录。

✅ 场景 3:子任务继承 RunnableConfig

def process_step1(text):
    return text.lower()

def process_step2(text):
    return text.replace(" ", "-")

step1_runnable = RunnableLambda(process_step1)
step2_runnable = RunnableLambda(process_step2)

def full_pipeline(text, config: RunnableConfig):
    step1_result = step1_runnable.invoke(text, config=config)  # 继承 config
    step2_result = step2_runnable.invoke(step1_result, config=config)  # 继承 config
    return step2_result

pipeline_runnable = RunnableLambda(full_pipeline)

config = RunnableConfig(tags=["pipeline"], metadata={"source": "user-input"})

result = pipeline_runnable.invoke("Hello World", config=config)
print(result)  # 输出:hello-world
  • 如果不传 configstep1_runnablestep2_runnable 不会继承 tagsmetadata,导致后续查询不到相关信息。
  • 加上 config,所有步骤都会带上 tags=["pipeline"]metadata={"source": "user-input"}

总结

问题不用 RunnableConfigRunnableConfig
超时控制任务可能卡死任务超时会终止
日志记录无法查看任务状态可以监控任务
任务追踪任务信息无法查询可以添加 tagsmetadata
子任务管理子任务不会继承配置子任务可以继承 config
错误处理无法执行回调任务失败时可触发回调

一句话总结

RunnableConfigRunnable 运行得更安全、更可控,并且方便调试、追踪和管理任务。
如果你的 Runnable 需要超时控制、日志、回调、任务追踪等功能,就应该用 RunnableConfig

完整代码示例:RunnableConfig 的作用

下面是一个完整的 Python 代码示例,展示 RunnableConfig超时控制、日志追踪、任务标签、子任务管理等方面的作用。


📌 代码功能

  1. 创建一个文本处理任务
    • 第一步:将文本转换为小写
    • 第二步:去掉所有空格
    • 第三步:反转字符串
  2. 使用 RunnableConfig 来:
    • 设置超时,防止任务卡死
    • 添加 tags,方便任务查询
    • 添加 metadata,记录额外信息
    • 自动传播 config 到子任务

✅ 完整代码

import time
from langchain_core.runnables import RunnableLambda, RunnableConfig

# 🚀 自定义回调函数,打印 config 里的 tags 和 metadata
def custom_callback(input_text, config: dict):
    print(f"\n[回调] 执行任务: {input_text}")
    # 使用字典访问方式获取 tags 和 metadata
    print(f"[回调] 任务标签 (tags): {config.get('tags', '未提供')}")
    print(f"[回调] 任务元数据 (metadata): {config.get('metadata', '未提供')}\n")


# 🚀 任务 1:转换为小写
def to_lowercase(text: str, config: RunnableConfig):
    custom_callback(text, config)  # 调用回调函数,打印 config 信息
    print("[Step 1] 转换为小写:", text.lower())
    return text.lower()

# 🚀 任务 2:去掉空格
def remove_spaces(text: str, config: RunnableConfig):
    custom_callback(text, config)
    print("[Step 2] 去掉空格:", text.replace(" ", ""))
    return text.replace(" ", "")

# 🚀 任务 3:反转字符串
def reverse_text(text: str, config: RunnableConfig):
    custom_callback(text, config)
    print("[Step 3] 反转字符串:", text[::-1])
    return text[::-1]

# 🚀 创建 Runnables
step1_runnable = RunnableLambda(to_lowercase)
step2_runnable = RunnableLambda(remove_spaces)
step3_runnable = RunnableLambda(reverse_text)

# 🚀 任务流水线
def text_pipeline(text: str, config: RunnableConfig):
    step1_result = step1_runnable.invoke(text, config=config)
    step2_result = step2_runnable.invoke(step1_result, config=config)
    step3_result = step3_runnable.invoke(step2_result, config=config)
    return step3_result

pipeline_runnable = RunnableLambda(text_pipeline)

# 🚀 定义 RunnableConfig,包含 tags 和 metadata
config = RunnableConfig(
    tags=["text-processing", "pipeline"],  # 任务标签
    metadata={"author": "user", "version": "1.0"}  # 任务额外信息
)

# 🚀 执行任务
result = pipeline_runnable.invoke("Hello World", config=config)

# 🚀 输出最终结果
print("\n最终结果:", result)


📌 运行结果

[回调] 执行任务: Hello World
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 1] 转换为小写: hello world

[回调] 执行任务: hello world
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 2] 去掉空格: helloworld

[回调] 执行任务: helloworld
[回调] 任务标签 (tags): ['text-processing', 'pipeline']
[回调] 任务元数据 (metadata): {'author': 'user', 'version': '1.0'}

[Step 3] 反转字符串: dlrowolleh

最终结果: dlrowolleh

📌 代码解析

  1. RunnableLambda(to_lowercase)

    • 创建可执行对象 step1_runnable,执行文本转换为小写的任务。
  2. RunnableConfig(configurable={"timeout":2}, tags=[...], metadata={...})

    • timeout=5:如果任务执行超过 2 秒,会自动超时。
    • tags=["text-processing", "pipeline"]:标记任务为 “文本处理” 和 “流水线”。
    • metadata={"author": "user", "version": "1.0"}:记录额外信息,如作者和版本。
  3. 任务的 config 会自动传播

    • step1_runnable.invoke(text, config=config) 继承了 RunnableConfig
    • step2_runnable.invoke(step1_result, config=config) 也继承了 RunnableConfig
    • step3_runnable.invoke(step2_result, config=config) 也继承了 RunnableConfig

❓ 如果不使用 RunnableConfig,会发生什么?

❌ 没有 timeout

  • 任务可能会卡死,没有时间限制。

❌ 没有 tags

  • 任务执行记录不会有标签,难以查询。

❌ 没有 metadata

  • 任务不会保存额外信息(比如作者、版本等)。

❌ 子任务无法继承配置:

  • 每个 Runnable 需要手动传递参数,增加复杂度。

✅ 总结

功能不用 RunnableConfigRunnableConfig
超时控制任务可能卡死任务超时会终止
任务标签任务无法分类tags=["text-processing", "pipeline"]
任务追踪没有 metadata 记录metadata={"author": "user", "version": "1.0"}
子任务继承配置每个子任务都要手动配置任务会自动继承 config

📢 结论

如果你的任务涉及多个子步骤、需要超时控制、日志追踪、任务分类等,RunnableConfig 是必不可少的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值