Runnable组件动态添加默认调用参数

01. bind 函数用途与使用技巧

在使用 LangChain 开发时,某些场景我们希望在一个 Runnable 队列中调用另一个 Runnable 并传递常量参数,这些参数既非前序 Runnable 的输出,也不是用户输入,而是组件自身的部分参数。此时可以使用 Runnable.bind() 传递默认参数。

典型应用场景

  1. 创建 ChatOpenAI 大语言模型构建两条链:
    • 第 1 条链设置 temperature=0.7(确定性输出)
    • 第 2 条链设置 temperature=1.2(创意性输出)
  2. 通过 LLM.bind(temperature=0.7)LLM.bind(temperature=1.2) 设置不同参数

bind() 用于修改 Runnable 底层的默认调用参数,调用时自动传递无需手动输入。适合在构建链时已知参数值的场景。


1.1 动态添加默认调用参数

通过绑定运行时参数实现 LLM 的多场景复用:

import dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

dotenv.load_dotenv()

prompt = ChatPromptTemplate.from_messages([
    (
        "system",
        "你正在执行一项测试,请重复用户传递的内容,除了重复其他均不要操作"
    ),
    ("human", "{query}")
])
llm = ChatOpenAI(model="gpt-4o")

chain = prompt | llm.bind(stop="world") | StrOutputParser()

content = chain.invoke({"query": "Hello world"})

print(content)

输出:

Hello

资料推荐


1.2 解决 RunnableLambda 多参传递问题

在 LangChain 中,如果要将一个函数变成 Runnable 组件,可以通过 RunnableLambda 函数进行包装。但是封装后,所有的 Runnable 组件的 invoke 函数,调用时,只能传递一个参数(类型不限制),如果原本的函数支持多个参数,并且是必填参数,就会出现报错。
例如:

import random

from langchain_core.runnables import RunnableLambda


def get_weather(location: str, unit: str) -> str:
    """根据传入的位置+温度单位获取对应的天气信息"""
    print("location:", location)
    print("unit:", unit)
    return f"{location}天气为{random.randint(24, 40)}{unit}"


get_weather_runnable = RunnableLambda(get_weather)

resp = get_weather_runnable.invoke({"location": "北京", "unit": "摄氏度"})

print(resp)

上述代码在执行 invoke 时虽然传递了字典,并且包含了 location 和 unit 两个参数,但是这个参数只会作为唯一的一个值,传递给 get_weather 函数的 location 参数,所以实际上 get_weather 函数接收的参数如下:

{
    "location": {"location": "北京", "unit": "摄氏度"},
    "unit": None
}

而使用 bind() 函数绑定添加其他默认调用参数,从而巧妙实现 RunnableLambda 组件实现接收多个参数,修改示例:

import random

from langchain_core.runnables import RunnableLambda


def get_weather(location: str, unit: str) -> str:
    """根据传入的位置+温度单位获取对应的天气信息"""
    print("location:", location)
    print("unit:", unit)
    return f"{location}天气为{random.randint(24, 40)}{unit}"


get_weather_runnable = RunnableLambda(get_weather).bind(unit="摄氏度")

resp = get_weather_runnable.invoke("北京")

print(resp)

输出内容:

location: {'location': '北京', 'unit': '摄氏度'}
unit: 摄氏度
{'location': '北京', 'unit': '摄氏度'}天气为31摄氏度

资料推荐


02 bind 函数运行流程解析

通过上述的案例,可以知道 .bind() 函数是在构建应用的时候添加上对应的默认调用参数,而在 Runnable.bind() 函数的底层,本质上是往 Runnable 的 kwargs 属性添加对应的字段,并生成一个新的 Runnable,当 Runnable 组件执行调用时(invoke、ainvoke、stream、astream、batch、abatch等),会自动将 kwargs 字段里的所有参数合并并覆盖默认调用参数。

从而完成动态添加默认调用参数的效果,Runnable.bind() 的实现原理:

  1. 在构建时向 Runnable 的 kwargs 属性添加字段
  2. 调用时自动合并覆盖默认参数
  3. 生成携带新参数的新 Runnable 实例

运行流程为:在这里插入图片描述

注意事项
虽然 .bind() 是所有 Runnable 共有的方法,但是并不是所有的 Runnable 组件都支持绑定默认调用参数,部分组件底层并没有默认调用参数的概念,例如 PromptTemplate 底层的 invoke 方法,并没有使用到 .bind() 的逻辑。

# langchain_core/prompts/base.py -> BasePromptTemplate
def invoke(
    self, input: Dict, config: Optional[RunnableConfig] = None
) -> PromptValue:
    config = ensure_config(config)
    if self.metadata:
        config["metadata"] = {**config["metadata"], **self.metadata}
    if self.tags:
        config["tags"] = config["tags"] + self.tags
    return self._call_with_config(
        self._format_prompt_with_error_handling,
        input,
        config,
        run_type="prompt",
    )

"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值