Runnable.bind(**kwargs) 是 LangChain Expression Language (LCEL) 中用于为 Runnable 组件预绑定固定参数的核心方法。它不会修改原对象,而是返回一个新的 RunnableBinding 包装对象,调用时自动将绑定的参数传入底层组件,实现配置与调用分离。
一、核心作用与原理
- 作用:冻结(Freeze)调用参数,避免重复传递;为链中特定步骤注入固定配置。
-
原理:
- 生成新的
RunnableBinding实例,包装原始 Runnable。 - 调用时(
invoke/batch/stream),合并绑定参数与运行时参数(运行时参数优先级更高)。 - 将合并后的参数传递给原始 Runnable 执行。
- 生成新的
二、基本语法
# 通用形式
bound_runnable = original_runnable.bind(**固定参数)
# 常用:绑定模型生成参数
from langchain_openai import ChatOpenAI
# 原始模型
model = ChatOpenAI(model="gpt-3.5-turbo")
# 绑定参数后生成新模型
deterministic_model = model.bind(temperature=0, max_tokens=256, stop=["\n\n"])
三、核心使用场景(附代码)
场景 1:绑定模型生成参数(最常用)
固定 temperature、stop、max_tokens 等,无需每次调用传入。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("简要回答问题:{question}")
chain = prompt | model.bind(temperature=0.1, max_tokens=100) | StrOutputParser()
# 调用时无需再传 temperature
print(chain.invoke({"question": "什么是LCEL?"}))
场景 2:绑定 OpenAI / 通用工具(Functions/Tools)
为模型绑定可调用工具,实现函数调用。
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""查询城市天气"""
return f"{city} 晴天"
# 绑定工具列表
model_with_tools = model.bind(tools=[get_weather])
chain = prompt | model_with_tools
# 模型将根据问题自动决定是否调用工具
response = chain.invoke({"question": "北京天气如何?"})
print(response.tool_calls)
场景 3:绑定配置(Config)
使用 bind 或 with_config 绑定 RunnableConfig(如标签、回调、超时)。
from langchain_core.runnables import RunnableConfig
# 绑定配置:添加标签与元数据
model_with_config = model.bind(
config=RunnableConfig(tags=["prod", "v2"], metadata={"user_id": "123"})
)
场景 4:为 RunnableLambda 绑定额外参数
解决 RunnableLambda 仅接受单输入的限制。
from langchain_core.runnables import RunnableLambda
def greet(name: str, greeting: str = "Hello"):
return f"{greeting}, {name}!"
# 包装为Runnable(仅接受1个参数)
runnable_greet = RunnableLambda(greet)
# 绑定默认参数
friendly_greet = runnable_greet.bind(greeting="Hi")
# 调用时只需传 name
print(friendly_greet.invoke("Alice")) # 输出: Hi, Alice!
场景 5:在 LCEL 链中局部绑定
在链式调用(|)中,为某个环节单独绑定参数。
from langchain_core.runnables import RunnablePassthrough
# 前半部分用默认参数,后半部分绑定stop词
chain = (
{"input": RunnablePassthrough()}
| ChatPromptTemplate.from_messages([("human", "{input}")])
| model.bind(stop=["END"]) # 仅此处生效
| StrOutputParser()
)
四、关键特性
-
不可变性:原
Runnable不受影响,bind始终返回新对象。 -
参数合并规则:
- 同名参数:运行时传入 > bind 绑定 > 组件默认。
- 字典参数:深度合并(如
tools)。
-
可链式调用:支持多次
bind,参数叠加。# 先绑定温度,再绑定停止词 model2 = model.bind(temperature=0).bind(stop=["STOP"])
五、bind vs with_config
-
bind(**kwargs):绑定调用参数(如temperature,tools),传给invoke(input, **kwargs)。 -
with_config(config):绑定执行配置(如tags,callbacks,max_concurrency)。
六、常见误区
- ❌ 试图绑定输入字典的键(如
bind(question="固定值"))—— 应使用提示词模板或RunnableParallel。 - ❌ 混淆绑定参数与运行时输入 ——
bind用于固定配置,动态数据应通过invoke(input)传入。
总结
bind() 是 LCEL 实现灵活、可复用链的基石,主要用于固定模型参数、绑定工具、注入配置。它通过非侵入式包装,让组件行为可定制,大幅提升代码简洁度与维护性。






网友评论