LangGraphJs 核心概念、工作流程理解及应用

LangGraph 简介

LangGraph 是由 LangChain 团队开发的一个低层级 Agent 编排框架,专为构建有状态(Stateful)、长时运行的 AI 工作流而设计。

与传统的线性 LLM 调用链不同,LangGraph 将工作流建模为有向图(Directed Graph):

  • 节点(Node):执行具体操作的函数(如调用 LLM、执行工具、处理数据)
  • 边(Edge) :定义节点之间的流转路径,支持条件分支
    1. 普通边:固定路径,nodeA -> nodeB
    2. 条件边:根据 State 动态路由,nodeA -> nodeB 或 nodeC
    3. 起始边:START -> 第一个节点
    4. 结束边:某节点 -> END
  • 状态(State):在整个工作流中共享并传递的数据

工作流程原理

为了更好的理解 LangGraphJs 的工作流程原理,我使用 ChatGpt 生成了一个MiniStateGraph实现其核心功能帮助理解。但是ChatGpt:我的知识截止时间是 2025 年 8 月。当时的版本是 1.x 以下的,MiniStateGraph的实现只是帮助理解工作流程相关的 API 的核心功能并不是最新版本的 API。

ts 复制代码
type NodeFn<S> = (state: S) => Promise<S> | S;
type NextResolver<S> = (state: S) => string;

type GraphDef<S> = {
  nodes: Record<string, NodeFn<S>>;
  edges: Record<string, string[]>; // 普通边
  condEdges: Record<string, NextResolver<S>>; // 条件边
  entry?: string | undefined;
};

export class MiniStateGraph<S extends Record<string, any>> {
  private nodes: GraphDef<S>["nodes"] = {};
  private edges: GraphDef<S>["edges"] = {};
  private condEdges: GraphDef<S>["condEdges"] = {};
  private entry?: string;

  addNode(name: string, fn: NodeFn<S>) {
    this.nodes[name] = fn;
    return this;
  }

  addEdge(from: string, to: string) {
    if (!this.edges[from]) this.edges[from] = [];
    this.edges[from].push(to);
    return this;
  }

  addConditionalEdges(from: string, resolver: NextResolver<S>) {
    this.condEdges[from] = resolver;
    return this;
  }

  setEntryPoint(name: string) {
    this.entry = name;
    return this;
  }

  compile(options?: {
    maxSteps?: number; // 防死循环
    onStep?: (info: {
      step: number;
      node: string;
      state: S;
      next?: string;
    }) => void; // 可观测性 hook
  }) {
    const def: GraphDef<S> = {
      nodes: this.nodes,
      edges: this.edges,
      condEdges: this.condEdges,
      entry: this.entry,
    };

    if (!def.entry) {
      throw new Error("Entry point is not set");
    }

    const END = "end";
    const maxSteps = options?.maxSteps ?? 100;

    async function runNode(name: string, state: S): Promise<S> {
      const fn = def.nodes[name];
      if (!fn) throw new Error(`Node not found: ${name}`);
      const nextState = await fn(state);
      if (!nextState || typeof nextState !== "object") {
        throw new Error(`Node "${name}" must return state object`);
      }
      return nextState;
    }

    function resolveNext(name: string, state: S): string {
      // 条件边优先
      if (def.condEdges[name]) {
        const n = def.condEdges[name](state);
        if (!n)
          throw new Error(`Conditional edge from "${name}" returned empty`);
        return n;
      }
      // 普通边(默认取第一条)
      const outs = def.edges[name];
      if (!outs || outs.length === 0) {
        // 没有出边,默认结束
        return END;
      }
      return outs[0] || "";
    }

    async function invoke(input: S): Promise<S> {
      let state: S = input;
      let current = def.entry as string;

      for (let step = 0; step < maxSteps; step++) {
        // 执行节点
        state = await runNode(current, state);

        // 计算下一步
        const next = resolveNext(current, state);

        options?.onStep?.({ step, node: current, state, next });

        if (next === END) {
          return state;
        }
        current = next;
      }
      throw new Error(
        `Max steps (${maxSteps}) exceeded --- possible infinite loop`,
      );
    }

    // 可选:流式执行(逐步产出)
    async function* stream(input: S) {
      let state: S = input;
      let current = def.entry as string;

      for (let step = 0; step < maxSteps; step++) {
        state = await runNode(current, state);
        const next = resolveNext(current, state);

        yield { step, node: current, state, next };

        if (next === END) return;
        current = next;
      }
      throw new Error(
        `Max steps (${maxSteps}) exceeded --- possible infinite loop`,
      );
    }

    return { invoke, stream };
  }
}

使用 LangGraphJs 实现一个 Agent 编排的智能体应用场景

用 LangGraphJs 构建一个 "电商智能客服 Agent(带 RAG + 多工具 + 审核 + 循环修正)"


一、场景目标

用户提问示例:

text 复制代码
"我昨天买的耳机还没发货,可以帮我查一下订单吗?顺便推荐一个降噪更好的款式。"

👉 Agent 要做:

  1. 识别意图(查订单 + 推荐商品)
  2. 查询订单(工具)
  3. 检索商品(RAG)
  4. 调用 LLM 生成回答
  5. 做安全/合规审核
  6. 不合格 → 自动重试(loop)

二、整体流程图(核心)

text 复制代码
             ┌────────────┐
             │   START    │
             └─────┬──────┘
                   ▼
             ┌────────────┐
             │  Router     │  ← 意图识别
             └─────┬──────┘
          ┌────────┼─────────────┐
          ▼        |             ▼
 ┌──────────────┐  |      ┌──────────────┐
 │ Order Tool   │  |      │  RAG 检索     │
 │ (查订单)      │  |      │ (商品推荐)    │
 └──────┬───────┘  |      └──────┬───────┘
        └──────────┬─────────────┘
                   ▼
            ┌────────────┐
            │   LLM生成  │<------------------------------------
            └─────┬──────┘            |
                  ▼                   |
            ┌────────────┐            |
            │  审核节点   │            |
            └─────┬──────┘            |
         ┌────────┴────────┐          | 回 LLM
         ▼                 ▼          |
   ┌───────────┐     ┌────────────┐   |
   │   END     │     │ Retry Loop │   |
   └───────────┘     └─────┬──────┘   |
                           └──------------------------|

三、State 设计(关键)

ts 复制代码
type State = {
  input: string;

  intent?: "order" | "recommend" | "llm";

  orderInfo?: any;
  products?: any[];

  draft?: string; // LLM 初稿
  output?: string; // 最终结果

  needRetry?: boolean;
};

👉 这是复杂 Agent 的核心: 状态驱动一切


四、核心节点实现

1️⃣ Router(意图识别)

ts 复制代码
const routerNode = async (state: State) => {
  const text = state.input;

  if (text.includes("订单")) return { ...state, intent: "order" };
  if (text.includes("推荐")) return { ...state, intent: "recommend" };

  return { ...state, intent: "llm" };
};

2️⃣ Order Tool(查订单)

ts 复制代码
const orderNode = async (state: State) => {
  return {
    ...state,
    orderInfo: {
      status: "已发货",
      trackingNo: "SF123456",
    },
  };
};

3️⃣ RAG 检索(商品推荐)

ts 复制代码
const ragNode = async (state: State) => {
  return {
    ...state,
    products: [
      { name: "Sony WH-1000XM5", noiseCancel: "强" },
      { name: "AirPods Pro", noiseCancel: "中" },
    ],
  };
};

4️⃣ LLM 生成

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });

const llmNode = async (state: State) => {
  const prompt = `
用户问题:${state.input}

订单信息:${JSON.stringify(state.orderInfo)}
商品推荐:${JSON.stringify(state.products)}

请生成客服回复
`;

  const res = await llm.invoke(prompt);

  return {
    ...state,
    draft: res.content as string,
  };
};

5️⃣ 审核节点(关键!)

ts 复制代码
const reviewNode = async (state: State) => {
  const bad = state.draft?.includes("违规词");

  if (bad) {
    return { ...state, needRetry: true };
  }

  return {
    ...state,
    needRetry: false,
    output: state.draft,
  };
};

五、Graph 构建(重点)

ts 复制代码
// 官方库
// import { StateGraph } from "@langchain/langgraph";
// const graph = new StateGraph<State>();

import { MiniStateGraph } from "./mini-langgraph-0.3.x";

const graph = new MiniStateGraph<State>();

graph.addNode("router", routerNode);
graph.addNode("order", orderNode);
graph.addNode("rag", ragNode);
graph.addNode("llm", llmNode);
graph.addNode("review", reviewNode);

graph.setEntryPoint("router");

// 分支
graph.addConditionalEdges("router", (state) => {
  if (state.intent === "order") return "order";
  if (state.intent === "recommend") return "rag";
  return "llm";
});

// 汇合
graph.addEdge("order", "llm");
graph.addEdge("rag", "llm");

// 审核
graph.addEdge("llm", "review");

// 循环(核心能力)
graph.addConditionalEdges("review", (state) => {
  if (state.needRetry) return "llm"; // loop
  return "end";
});

const app = graph.compile();

结束

本文介绍了 LanggraphJs 节点、边、状态三个核心概念和它的工作流程,并实现MiniStateGraph理解 LanggraphJs 的核心原理,最后实现一个 Agent 编排的智能体应用场景应用。

相关推荐
小赵同学WoW2 小时前
vue组件基础知识
前端
ZGi.ai2 小时前
LangChain做了什么?企业场景中它和专用AI平台的定位区别
人工智能·开源框架·企业ai·- langchain·- ai应用开发
牛奶2 小时前
浏览器藏了这么多神器,你居然不知道?
前端·chrome·api
WebInfra2 小时前
Rspack 2.0 正式发布!
前端·javascript·前端框架
SteveLaiTVT2 小时前
从 Curl 开始:不用 SDK,通过 DeepSeek API 手写 Agent Runtime
人工智能
小糖学代码2 小时前
LLM系列:2.pytorch入门:3.基本优化思想与最小二乘法
人工智能·python·算法·机器学习·ai·数据挖掘·最小二乘法
极速蜗牛2 小时前
Cursor最近变傻了?
前端
J_bean2 小时前
大语言模型 API Token 消耗深度剖析
人工智能·ai·llm·大语言模型·token
醉卧考场君莫笑2 小时前
规则与传统NLP之任务范式
人工智能·自然语言处理