实用功能

配置管理与 Configurable

使用 RunnableConfig 动态控制图的行为,实现参数热更新

📚 学习目标

学完这篇文章后,你将能够:

  • 理解 RunnableConfig 对象的作用
  • 在节点中访问运行时配置
  • 实现可配置的 Agent(如动态切换模型、Prompt)

前置知识

在开始学习之前,建议先阅读:

你需要了解:

  • 环境变量的基本概念

1 什么是 RunnableConfig?

在调用 invoke, stream, batch 时,LangGraph 允许传入第二个参数:RunnableConfig

import { RunnableConfig } from '@langchain/core/runnables';

await app.invoke(inputs, {
  configurable: {
    model: "gpt-4",
    temperature: 0.5
  },
  recursionLimit: 50,
  runName: "MyAgentRun"
});

这些配置不仅控制运行时的行为(如递归限制),还可以透传给图中的每个节点。

如果你把它当成一个“运行时上下文对象”会更好理解:

  • configurable:你自定义的运行参数(用户ID、模型名、feature flag...)
  • tags/metadata:可观测性与追踪用(打标签、记录额外信息)
  • recursionLimit:防止循环失控

2 RunnableConfig 里常用的字段

下面是一个“面向教学”的简化心智模型(不同版本字段可能略有差异):

export type ExampleRunnableConfig = {
  configurable?: Record<string, unknown>;
  tags?: string[];
  metadata?: Record<string, unknown>;
  recursionLimit?: number;
  runName?: string;
};

3 节点内访问配置

节点函数的第二个参数就是 config

const myNode = async (state: State, config: RunnableConfig) => {
  // 1. 获取配置
  const modelName = config.configurable?.model || "gpt-3.5-turbo";
  
  // 2. 使用配置
  const model = new ChatOpenAI({ model: modelName });
  const response = await model.invoke(state.messages);
  
  return { messages: [response] };
};

为什么这很有用?

  • 多租户支持:不同用户使用不同的 prompt 或模型。
  • A/B 测试:运行时动态决定使用哪个策略。
  • 安全性:动态传入 User ID 或 API Token。

📝 提醒

不要把明文 API Key 放进 configurable。更稳妥的方式是传 keyId / tenantId,在节点里再去你的密钥系统取真实 key。


4 预置配置项

LangGraph 有一些内置的配置键:

  • recursionLimit: 最大递归深度(默认 25)。防止死循环。
  • thread_id: 用于 Checkpoint 持久化(区分不同会话)。
  • runName: 在 LangSmith 追踪中显示的名称。
// 防止死循环的保护机制
try {
  await app.invoke(inputs, { recursionLimit: 5 });
} catch (e) {
  console.log("达到递归限制!");
}

5 配置继承:子图/节点如何拿到同一套参数

当你把一个“编译后的 subgraph”当作节点接入父图时,运行时配置通常会沿调用链传递下去。


6 配置优先级

当同一参数在多处定义时,优先级通常是:

  1. 运行时传入(invoke/stream)
  2. 节点内覆盖(节点逻辑里手动覆盖)
  3. 默认值(Annotation/代码默认值)
const config = { configurable: { model: 'gpt-4' } };
await app.invoke(inputs, config); // 最高优先级

7 环境变量 + Configurable 组合

你可以用环境变量做全局默认,用 configurable 做动态覆盖:

const defaultModel = process.env.OPENAI_MODEL_NAME ?? 'gpt-4o-mini';
const modelName = config.configurable?.model ?? defaultModel;

💡 说明

环境变量适合部署级配置,configurable 适合运行时差异化。

8 A/B 测试示例

通过 config 传入实验组:

const group = config.configurable?.experiment ?? 'control';
const temperature = group === 'variant' ? 0.7 : 0.2;

9 类型安全与校验

为了避免运行时出错,建议给 configurable 做简单校验:

const ConfigSchema = z.object({
  model: z.string().optional(),
  temperature: z.number().min(0).max(1).optional(),
});

const safeConfig = ConfigSchema.parse(config.configurable ?? {});

⚠️ 注意

校验失败时要有兜底策略,避免直接崩溃。


💡 练习题

  1. 编码题:修改你的 ReAct Agent,使其接受一个 systemPrompt 配置参数。在运行时动态传入不同的角色设定(如“你是一个海盗” vs “你是一个医生”)。

    点击查看答案

    在节点中读取 config.configurable?.systemPrompt,作为 SystemMessage 注入。

  2. 场景题:如果在 configurable 中传入了一个敏感的 API Key,它会被 LangSmith 记录吗?如何避免?

    点击查看答案

    不建议明文传入;可以传 keyId 并在节点内获取真实密钥。

  3. 操作题:为配置添加 temperature 校验,超出范围自动回退默认值。

    点击查看答案

    用 zod 校验并在 catch 中回退默认温度。

  4. 思考题:什么时候应该用环境变量而不是 configurable?

    点击查看答案

    环境变量适合部署级配置,configurable 适合运行时差异化。

  5. 操作题:实现一个简单的 A/B 测试配置,控制不同温度值。

    点击查看答案

    根据 config.configurable?.experiment 选择温度。


✅ 总结

本章要点

  • configurable 字段是运行时动态传参的主要通道。
  • 节点函数的签名是 (state, config) => ...
  • 合理使用配置可以让你的 Graph 更加通用和灵活。

下一步:如果运行出错了怎么办?继续学习:错误处理

登录以继续阅读

解锁完整文档、代码示例及更多高级功能。

立即登录

On this page