[LangGraph] 边

边是两个节点的连接线,决定了图在运行时从哪里到哪里。

LangGraph 中边有 4 种类型:

  1. 普通边
  2. 条件边
  3. 入口点:START
  4. 条件入口点

普通边

连接两个节点,例如 nodeAnodeB

graph.addEdge("nodeA", "nodeB");

注意这里添加的边是有流向的,代表着从 nodeA 流向 nodeB

条件边

语法如下:

graph.addConditionalEdges("nodeA", routingFunction [, mapping]);
  • "nodeA":哪个节点跑完以后要做分流。
  • routingFunction(state):路由函数,接收当前 state,返回一个“去向”。
  • mapping(可选):把路由函数的返回值翻译成真正的节点名或节点名列表。

路由函数

顾名思义就是一个函数,例如:

function shouldSearch(state) {
  return state.query?.trim() ? true : false;
}
function route(state) {
  if (state.needTools) return "tools";
  if (state.done) return "stop";
  return "finalize";
}
function fanOut(state) {
  return ["fetchProfile", "fetchOrders"]; // 下一步并发的跑两个节点
}

路由函数的返回值:

  1. 返回字符串
  2. 返回字符串数组,字符串数组就代表要并发跑的节点
  3. 返回自定义的标签:如 true/false"search"
  4. 返回END

mapping

让路由函数只关心判定结果,不耦合具体的节点名字。

mapping 是做一个节点的映射,目的是让路由函数和具体的节点名称解耦。

graph.addConditionalEdges("nodeA", routingFunction, {
  true: "nodeB",
  false: "nodeC",
});

routingFunction 是路由函数,只需要返回 true/false,具体映射的节点由 mapping 来决定。

条件入口点

其实就是条件边,只不过第一个参数为 START

graph.addConditionalEdges(START, routingFunction);

routingFunction(state) 是一个路由函数,会根据初始 state 做判断,然后路由函数的返回值决定从哪个节点开始运行。

条件入口点也可以使用映射表:

graph.addConditionalEdges(START, routingFunction, {
  true: "nodeB",
  false: "nodeC",
});

routingFunction 返回值:

  • true:以 nodeB 作为起点
  • false:以 nodeC 作为起点

import { END, START, StateGraph } from "@langchain/langgraph";
import { registry } from "@langchain/langgraph/zod";
import z from "zod";

const Schema = z.object({
  a: z.string().optional(),
  b: z.string().optional(),
  c: z.string().optional(),
  path: z.enum(["B", "C"]).optional(),
  logs: z.array(z.string()).register(registry, {
    reducer: {
      fn: (oldVal, newVal) => [...oldVal, ...newVal],
    },
    default: () => [],
  }),
});
type TState = z.infer<typeof Schema>;

const graph = new StateGraph(Schema)
  .addNode("A", () => {
    console.log("运行A节点");
    return {
      a: "A节点执行后的结果",
      logs: ["A节点"],
    };
  })
  .addNode("B", async (state: TState) => {
    console.log("运行B节点");
    return {
      b: "B节点执行后的结果",
      logs: ["B节点"],
    };
  })
  .addNode("C", async (state: TState) => {
    console.log("运行C节点");
    return {
      c: "C节点执行后的结果",
      logs: ["C节点"],
    };
  })
  .addNode("D", async (state: TState) => {
    console.log("运行D节点");
    return {
      d: "D节点执行后的结果",
      logs: ["D节点"],
    };
  })
  .addEdge(START, "A")
  .addConditionalEdges(
    "A",
    (state: TState) => {
      return state.path === "B" ? "B" : "C";
    },
    {
      B: "B",
      C: "C",
    },
  )
  .addEdge("B", "D")
  .addEdge("C", "D")
  .addEdge("D", END)
  .compile();

const result = await graph.invoke({
  logs: [],
  path: "C",
});
console.log(result);

posted @ 2026-02-11 14:33  Zhentiw  阅读(85)  评论(0)    收藏  举报