01. configurable_fields 方法使用技巧
在某些场合下除了在构建链的时候配置对应的调用参数,也可能让链在执行调用的时候才去配置对应的运行时链内部(运行时修改链相应参数),包括运行时动态调整温度、停止词、传递自定义参数、甚至是运行时动态替换模型为另外一个。
针对这类需求,在 LangChain
也提供了相应的解决方案:
configurable_fields()
:和 bind()
方法接近,但是并不是在构建时传递对应的参数,而是在链运行时为链中的给定步骤指定参数,比 bind()
更灵活。
configurable_alternatives()
:使用这个方法可以在链运行时,将链中的某一个部分替换成其他替换方案,例如:运行中更换提示模板、更换大语言模型等。
configurable_fields()
方法使用分成两个流程:
为 Runnable
定义哪些字段可以在链运行时动态配置;
在调用 invoke()
函数时,传递对应的配置信息 configurable
完成动态配置;
例如,在链的调用过程中,将 temperature
温度设置为 0
,使用代码如下:
import dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import ConfigurableField
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
# 1.创建提示模板
prompt = ChatPromptTemplate.from_template("请生成一个小于{x}的随机整数")
# 2.创建LLM大语言模型,并配置temperature参数为可在运行时配置,配置键位llm_temperature
llm = ChatOpenAI(model="gpt-3.5-turbo-16k").configurable_fields(
temperature=ConfigurableField(
id="llm_temperature",
name="大语言模型温度",
description="用于调整大语言模型生成内容的随机性"
),
)
# 3.构建链应用
chain = prompt | llm | StrOutputParser()
# 4.正常调用内容
content = chain.invoke({"x": 1000})
print(content)
# 5.将temperature修改为0调用内容
content = chain.invoke(
{"x": 1000},
config={"configurable": {"llm_temperature": 0}}
)
print(content)
资料推荐
02. configurable_fields 运行流程与解析
configurable_fields()
和 bind()
非常接近,但是可配置范围更广,只要 Runnable
组件下有的所有属性,都可以通过 configurable_fields()
进行配置,而 bind()
只能配置调用参数(一般调用参数都和组件参数有关系)。
可以通过以下函数来查看 configurable_fields()
支持配置哪些字段(父类属性也可以配置,但是在这里不显示):
Runnable.__fields__.keys()
例如 PromptTemplate
组件下存在 template
字段,这个字段是提示模板的模板本体,同样也可以快速实现动态配置。
代码如下:
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import ConfigurableField
# 1.创建提示模板并配置支持动态配置的字段
prompt = PromptTemplate.from_template("请写一篇关于{subject}主题的冷笑话").configurable_fields(
template=ConfigurableField(
id="prompt_template",
name="提示模板",
description="提示模板字符串本身",
)
)
# 2.传递配置更改prompt_template并调用生成内容
content = prompt.invoke(
{"subject": "程序员"},
config={"configurable": {"prompt_template": "请写一篇关于{subject}主题的藏头诗"}}
).to_string()
print(content)
输出结果:
请写一篇关于程序员主题的藏头诗
configurable_fields()
的运行原理及流程其实也非常简单,在调用 invoke()
函数调用链的时候,会调用 _prepare()
预处理函数,在预处理函数这里,会重新依据原有参数+配置的参数创建对应的组件进行覆盖,从而实现配置运行时链内部。
运行流程:
3. 资料推荐
核心源码:
# langchain_core/runnables/configurable.py --> RunnableConfigurableFields
def _prepare(
self, config: Optional[RunnableConfig] = None
) -> Tuple[Runnable[Input, Output], RunnableConfig]:
config = ensure_config(config)
specs_by_id = {spec.id: (key, spec) for key, spec in self.fields.items()}
configurable_fields = ...
configurable_single_options = ...
configurable_multi_options = ...
configurable = {
**configurable_fields,
**configurable_single_options,
**configurable_multi_options,
}
if configurable:
init_params = {
k: v
for k, v in self.default.__dict__.items()
if k in self.default.__fields__
}
return (
self.default.__class__(**{**init_params, **configurable}),
config,
)
else:
return (self.default, config)