核心组件详解

节点设计

深入探讨节点的类型、编写规范以及异步和配置化节点的实现

📚 学习目标

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

  • 编写标准的同步及异步节点函数
  • 使用 RunnableConfig 编写可配置的节点
  • 理解节点的输入输出规范
  • 掌握节点内的错误处理最佳实践

前置知识

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

你需要了解:

  • Async/Await 异步编程模式
  • JavaScript 异常处理 (try/catch)

1️⃣ 节点函数规范

在 LangGraph 中,节点就是一个简单的函数。

基本签名

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

// state: 当前状态
// config: 运行时配置(可选)
const myNode = async (state: State, config?: RunnableConfig) => {
  // 业务逻辑
  const result = await doSomething(state.input);
  
  // 返回状态更新
  return {
    output: result,
  };
};

2️⃣ 节点类型详解

1. 异步节点(最常用)

绝大多数涉及 LLM 调用、数据库查询、API 请求的节点都是异步的。

const llmNode = async (state: typeof StateAnnotation.State) => {
  const response = await model.invoke(state.messages);
  return { messages: [response] };
};

2. 同步节点

用于纯逻辑处理,如数据格式化、简单计算。

const formatNode = (state: typeof StateAnnotation.State) => {
  return { content: state.content.trim() };
};

3. 可配置节点

通过 config 参数,让节点行为在运行时可调整。这在多用户多配置场景下非常有用。

const configurableNode = async (state: State, config?: RunnableConfig) => {
  // 从配置中读取参数,默认为 'gpt-3.5-turbo'
  const modelName = config?.configurable?.modelName || 'gpt-3.5-turbo';
  const model = new ChatOpenAI({ model: modelName });
  // ...
};

调用时传入配置:

await graph.invoke(inputs, {
  configurable: { modelName: 'gpt-4' }
});

3️⃣ 错误处理

在节点内部处理错误,可以防止整个图崩溃,并允许实现重试或降级逻辑。

推荐模式

const safeToolNode = async (state: State) => {
  try {
    const result = await tool.invoke(state.query);
    return { toolResult: result, error: null };
  } catch (e) {
    console.error("Tool execution failed", e);
    // 返回错误状态,而不是抛出异常
    return { 
      error: e.message,
      // 可选:触发重试逻辑
      retryCount: state.retryCount + 1 
    };
  }
};

4️⃣ 节点怎么拆:把复杂逻辑拆成可测试的“小块”

一个很常见的反模式是:

  • 一个节点里同时做“解析输入 -> 检索 -> 生成 -> 格式化 -> 记录指标”

结果就是:难测、难改、难复用。

更好的做法是按“职责”拆节点:

拆分之后,你可以:

  • parse 写单元测试(纯函数)
  • search 做超时/重试
  • answer 做模型切换与 token 限制

5️⃣ 特殊节点:START 和 END


5️⃣ 特殊节点:START 和 END

  • START:虽然代码中常用 addEdge(START, 'node'),但 START 本身不是一个你需要编写函数的节点,它只是一个标记,代表图的入口。
  • END:同样是标记,代表流程结束。
import { START, END } from '@langchain/langgraph';

graph.addEdge(START, 'entryNode');
graph.addEdge('finalNode', END);

💡 练习题

  1. 改造题:将一个硬编码了 API Key 的节点函数,改造成从 RunnableConfig 中读取 Key 的可配置节点。
  2. 设计题:设计一个“网络请求节点”,要求包含超时处理(例如 5 秒超时)和简单的重试机制(如果失败,检查重试计数)。

📚 参考资源

官方文档


✅ 总结

本章要点

  • 节点本质上是 (State) => Partial<State> 的函数。
  • 充分利用 async/await 处理 I/O 操作。
  • 使用 RunnableConfig 提升节点的复用性。
  • 优雅的错误处理是构建健壮 Agent 的关键。

下一步:节点只是孤岛,让我们通过将它们连接起来。

登录以继续阅读

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

立即登录

On this page