🤔 问题:LangGraph 到底做了什么?

你的观察很准确:

  • 提示词 → 由 Python 代码编写(graph_nodes.py 中的 system_prompt
  • 节点逻辑 → 由 Python 函数实现(classify_alert, plan_queries 等)
  • 思考推理 → 由 LLM(Azure OpenAI)完成

那么 LangGraph 到底实现了什么?


🎯 LangGraph 的核心价值

1. 工作流编排引擎 🔄

LangGraph 提供了一个声明式的工作流定义和执行引擎

# app/graph_workflow.py

# ❌ 如果没有 LangGraph,你需要手写这样的代码:
async def manual_workflow(alert):
    # 步骤1:分类
    classify_result = await classify_alert(alert)
    
    # 步骤2-N:循环查询
    iteration = 0
    while iteration < 3:
        plan_result = await plan_queries(classify_result)
        
        if not plan_result.needs_more_info:
            break
            
        query_result = await execute_queries(plan_result)
        iteration += 1
    
    # 步骤N+1:分析
    final_result = await analyze_and_conclude(query_result)
    return final_result
# ✅ 使用 LangGraph,只需声明节点和边:
workflow = StateGraph(GraphState)

# 添加节点
workflow.add_node("classify_alert", self.nodes.classify_alert)
workflow.add_node("plan_queries", self.nodes.plan_queries)
workflow.add_node("execute_queries", self.nodes.execute_queries)
workflow.add_node("analyze_and_conclude", self.nodes.analyze_and_conclude)

# 声明流转关系
workflow.add_edge("classify_alert", "plan_queries")
workflow.add_conditional_edges("plan_queries", self._should_query, {...})
workflow.add_edge("execute_queries", "plan_queries")  # 循环边
workflow.add_edge("analyze_and_conclude", END)

# 自动编译和执行
graph = workflow.compile()

价值

  • 不需要手写复杂的流程控制逻辑
  • 不需要管理循环、条件分支、状态传递
  • 代码更清晰、可维护性更高

2. 智能状态管理 📦

LangGraph 提供了强大的状态管理机制:

# app/graph_state.py

class GraphState(TypedDict):
    # ... 普通字段
    alert_id: str
    alert_message: str
    
    # ⚠️ 重点:使用 Annotated[List, add] 实现增量累加
    thoughts: Annotated[List[ThoughtRecord], add]  # 自动累加
    query_plans: Annotated[List[QueryPlan], add]   # 自动累加
    query_results: Annotated[List[QueryResult], add]  # 自动累加

LangGraph 自动处理的状态逻辑

# ❌ 如果没有 LangGraph,每个节点都需要手动管理状态:
def classify_alert(state):
    # 需要手动合并 thoughts
    new_thoughts = [...]
    state['thoughts'] = state.get('thoughts', []) + new_thoughts
    return state

def plan_queries(state):
    # 需要手动合并 thoughts 和 query_plans
    new_thoughts = [...]
    state['thoughts'] = state.get('thoughts', []) + new_thoughts
    new_plans = [...]
    state['query_plans'] = state.get('query_plans', []) + new_plans
    return state
# ✅ 使用 LangGraph,只需返回增量数据:
def classify_alert(state):
    new_thoughts = [ThoughtRecord(...)]
    return {
        "thoughts": new_thoughts,  # LangGraph 自动累加到现有 thoughts
        "alert_type": AlertType.SECURITY
    }

def plan_queries(state):
    new_thoughts = [ThoughtRecord(...)]
    new_plans = [QueryPlan(...)]
    return {
        "thoughts": new_thoughts,    # 自动累加
        "query_plans": new_plans      # 自动累加
    }

价值

  • 自动处理列表的累加(Annotated[List, add]
  • 自动合并字典更新
  • 不需要在每个节点中手动管理状态合并逻辑

3. 条件路由 🔀

LangGraph 提供了灵活的条件分支:

# app/graph_workflow.py

# 条件函数:根据状态决定下一步
def _should_query(self, state: GraphState) -> Literal["query", "analyze"]:
    if state.get("needs_more_info") and state.get("current_iteration") < 3:
        return "query"    # 继续查询
    return "analyze"      # 开始分析

# 添加条件边
workflow.add_conditional_edges(
    "plan_queries",           # 从哪个节点
    self._should_query,       # 条件判断函数
    {
        "query": "execute_queries",      # 如果返回 "query"
        "analyze": "analyze_and_conclude"  # 如果返回 "analyze"
    }
)

价值

  • 声明式的条件分支,不需要在节点中写 if/else
  • 支持动态路由,根据状态智能决策
  • 代码逻辑清晰,容易理解和修改

4. 循环控制 ♻️

LangGraph 天然支持循环工作流:

# 创建循环:execute_queries -> plan_queries -> execute_queries
workflow.add_edge("execute_queries", "plan_queries")

# 配合条件边实现智能循环:
# plan_queries -> (需要更多信息?) -> execute_queries -> plan_queries
#             -> (不需要) -> analyze_and_conclude

实际效果

1. classify_alert      → 分类告警
2. plan_queries        → 规划第1轮查询
3. execute_queries     → 执行第1轮查询
4. plan_queries        → 规划第2轮查询(自动循环)
5. execute_queries     → 执行第2轮查询
6. plan_queries        → 判断是否需要第3轮
7. analyze_and_conclude → 综合分析(不需要更多查询)

价值

  • 不需要手写 while 循环逻辑
  • 自动管理迭代次数
  • 支持动态决定是否继续循环

5. 异步执行支持

LangGraph 原生支持异步节点:

# 所有节点都是 async 函数
async def classify_alert(self, state: GraphState) -> dict:
    response = await self.llm.ainvoke(messages)  # 异步调用
    return {...}

# LangGraph 自动处理异步执行
final_state = await self.graph.ainvoke(state)

价值

  • 所有节点可以并发执行(如果没有依赖关系)
  • 支持异步 I/O 操作(API 调用、数据库查询)
  • 自动处理异步协程的调度

6. 可视化和调试 🔍

LangGraph 内置工作流可视化:

# 生成 Mermaid 流程图
mermaid_code = self.graph.get_graph().draw_mermaid()

# 生成 PNG 图片
graph_image = self.graph.get_graph().draw_mermaid_png()

输出

__start__
classify_alert
plan_queries
execute_queries
analyze_and_conclude
__end__

价值

  • 自动生成流程图,便于理解和文档化
  • 方便团队沟通和 Code Review
  • 支持调试和监控

7. 检查点和持久化 💾

LangGraph 支持工作流状态的持久化(虽然当前项目未启用):

# langgraph.json 配置
"compile_options": {
    "checkpointer": false,  # 当前未启用
    "interrupt_before": [],
    "interrupt_after": []
}

如果启用,可以实现

  • 中断和恢复工作流(如等待人工审批)
  • 状态持久化到数据库
  • 支持长时间运行的任务
  • 错误恢复和重试

📊 对比总结

功能 手写代码 使用 LangGraph
流程定义 需要手写 if/while/for 逻辑 声明式添加节点和边
状态管理 手动合并字典和列表 自动累加和合并
条件分支 嵌套 if/else add_conditional_edges
循环控制 手写 while + 计数器 添加循环边 + 条件判断
异步执行 手动管理 async/await 自动处理异步节点
可视化 需要手写或使用第三方工具 内置 Mermaid 生成
持久化 需要自己实现 内置 Checkpointer
调试 需要大量 print/log 状态追踪和可视化

🎯 总结:LangGraph 的核心价值

LangGraph 是一个 “让复杂工作流变简单” 的框架:

  1. 你不需要写

    • ❌ 复杂的流程控制代码(循环、分支)
    • ❌ 状态合并和传递逻辑
    • ❌ 异步调度和错误处理
  2. 你只需要写

    • ✅ 每个节点的业务逻辑(调用 LLM、查询数据)
    • ✅ 节点之间的流转关系(声明式)
    • ✅ 条件判断函数(简单的 if/else)
  3. LangGraph 帮你处理

    • ✅ 自动编排节点执行顺序
    • ✅ 自动管理状态传递和累加
    • ✅ 自动处理条件分支和循环
    • ✅ 自动支持异步执行
    • ✅ 内置可视化和调试工具

💡 类比:LangGraph 就像什么?

可以把 LangGraph 看作是 “工作流的 React/Vue”

  • React/Vue: 你只需要定义组件(Component)和状态(State),框架自动处理 DOM 更新和事件响应
  • LangGraph: 你只需要定义节点(Node)和状态(State),框架自动处理流程编排和状态传递

或者类比为 “LLM 应用的 Kubernetes”

  • Kubernetes: 你只需要定义 Pod 和 Service,K8s 自动处理容器调度和流量分配
  • LangGraph: 你只需要定义节点和边,LangGraph 自动处理工作流调度和状态管理

🚀 如果没有 LangGraph 会怎样?

假设我们用纯 Python 实现相同的功能,代码会变成这样:

class ManualAlertAnalysis:
    async def analyze(self, alert):
        # 初始化状态
        state = {
            "alert_id": alert.alert_id,
            "alert_message": alert.alert_message,
            "thoughts": [],
            "query_plans": [],
            "query_results": [],
            "current_iteration": 0,
            "max_iterations": 3,
            "needs_more_info": True
        }
        
        # 步骤1:分类
        classify_result = await self._classify_alert(state)
        state["thoughts"].extend(classify_result.get("thoughts", []))
        state["alert_type"] = classify_result.get("alert_type")
        
        # 步骤2-N:循环查询
        while state["current_iteration"] < state["max_iterations"]:
            # 规划查询
            plan_result = await self._plan_queries(state)
            state["thoughts"].extend(plan_result.get("thoughts", []))
            state["query_plans"].extend(plan_result.get("query_plans", []))
            
            # 判断是否需要查询
            if not plan_result.get("needs_more_info"):
                break
            
            # 执行查询
            execute_result = await self._execute_queries(state)
            state["query_results"].extend(execute_result.get("query_results", []))
            
            state["current_iteration"] += 1
        
        # 步骤N+1:综合分析
        analyze_result = await self._analyze_and_conclude(state)
        state["root_cause"] = analyze_result.get("root_cause")
        state["recommendations"] = analyze_result.get("recommendations")
        
        return state

问题

  • 代码冗长,难以维护
  • 状态管理容易出错(忘记 extend?)
  • 流程变更需要修改多处代码
  • 没有内置可视化和调试工具
  • 错误处理需要自己实现

✅ 结论

LangGraph 不是 “可有可无” 的框架,而是:

  1. 简化开发:把复杂的流程控制变成简单的声明式配置
  2. 提高可维护性:代码结构清晰,易于理解和修改
  3. 增强扩展性:添加新节点或修改流程非常简单
  4. 内置最佳实践:状态管理、异步执行、错误处理都是开箱即用

你写的是业务逻辑,LangGraph 处理的是底层基础设施! 🎯

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐