【大模型学习】LangGraph 深度解析:定义、功能、原理与实践

LangGraph 深度解析:定义、功能、原理与实践

    • [LangGraph 深度解析:定义、功能、原理与实践](#LangGraph 深度解析:定义、功能、原理与实践)
      • [**一、什么是 LangGraph?**](#一、什么是 LangGraph?)
    • [**二、LangGraph 核心功能**](#二、LangGraph 核心功能)
      • [**1. 图结构流程定义**](#1. 图结构流程定义)
      • [**2. 循环与迭代支持**](#2. 循环与迭代支持)
      • [**3. 多代理协作**](#3. 多代理协作)
      • [**4. 与 LangChain 生态集成**](#4. 与 LangChain 生态集成)
      • [**5. 可视化与调试**](#5. 可视化与调试)
    • [**三、LangGraph 底层实现原理**](#三、LangGraph 底层实现原理)
      • [**1. 核心架构:状态机(State Machine)**](#1. 核心架构:状态机(State Machine))
      • [**2. 图执行引擎**](#2. 图执行引擎)
      • [**3. 关键技术细节**](#3. 关键技术细节)
    • [**四、使用 LangGraph 构建复杂工作流:完整示例**](#四、使用 LangGraph 构建复杂工作流:完整示例)
      • **场景描述**
      • [**步骤 1:安装依赖**](#步骤 1:安装依赖)
      • [**步骤 2:完整代码实现**](#步骤 2:完整代码实现)
    • **五、代码解析与执行结果**
    • **六、总结**

LangGraph 深度解析:定义、功能、原理与实践

一、什么是 LangGraph?

LangGraph 是 LangChain 生态 中用于构建复杂、有状态、多步骤 AI 工作流 的框架,核心特点是支持图结构(Graph) 定义流程,原生支持循环(Cycles)分支(Branches)多代理协作(Multi-Agent Collaboration),并能与 LLM、工具(Tools)、记忆(Memory)无缝集成。

它解决了传统链式调用(如 LangChain SequentialChain)难以处理的非线性流程(如迭代优化、条件跳转、并行任务),适用于构建 Agent、对话系统、数据处理流水线等复杂场景。

二、LangGraph 核心功能

LangGraph 的功能围绕"图结构工作流"展开,核心能力包括:

1. 图结构流程定义

  • 节点(Nodes):代表流程中的独立步骤(如 LLM 调用、工具执行、数据处理),可同步或异步执行。
  • 边(Edges) :定义节点间的流转逻辑,分为:
    • 普通边(Normal Edge) :固定从一个节点到另一个节点(如 A → B)。
    • 条件边(Conditional Edge):根据运行时状态动态决定下一个节点(如"若问题类型为'技术问题'则进入节点 C,否则进入节点 D")。
  • 状态(State):贯穿全流程的共享数据对象,节点可读取/更新状态(类似"上下文")。

2. 循环与迭代支持

原生支持循环逻辑(如 Agent 反复调用工具直到完成任务),通过"指向自身的边"实现(如节点 A 执行后根据状态决定是否回到 A 重新执行)。

3. 多代理协作

允许定义多个"代理节点"(每个节点可包含一个 Agent),支持并行或串行协作(如"Agent A 收集需求 → Agent B 设计方案 → Agent C 评审")。

4. 与 LangChain 生态集成

无缝对接 LangChain 组件:

  • LLM(如 GPT、Claude)、Prompt Templates、Tools(如搜索引擎、计算器);
  • 记忆模块(Memory)、检索器(Retriever);
  • 链路追踪(LangSmith)。

5. 可视化与调试

支持导出流程图(如 Mermaid 格式),并提供运行时状态追踪,便于调试复杂流程。

三、LangGraph 底层实现原理

LangGraph 的核心是**"状态机 + 有向图"** 模型,底层通过 Python 异步编程和状态管理实现灵活流转。

1. 核心架构:状态机(State Machine)

  • 状态(State) :用 Python TypedDictdataclass 定义,包含所有流程共享的键值对(如 {"step": "collect_info", "user_input": "...", "solution": None})。
  • 节点(Nodes):Python 函数,接收当前状态,返回更新后的状态(不可变更新,避免副作用)。
  • 边(Edges):决定节点执行顺序,条件边通过 Python 函数评估状态,返回下一个节点名称。

2. 图执行引擎

  • 编译阶段:将用户定义的图(节点+边)编译为可执行的有限状态机(FSM)。
  • 运行阶段
    1. 初始化状态,从"入口节点"开始执行;
    2. 节点执行后更新状态,根据边规则跳转到下一节点;
    3. 遇到循环边时,重复执行直至满足退出条件;
    4. 支持异步节点(如 LLM 调用),通过 async/await 实现并发。

3. 关键技术细节

  • 状态不可变性:节点返回新状态对象(而非修改原状态),避免并发冲突。
  • 条件边评估 :条件函数接收当前状态,返回目标节点名称(如 lambda state: "tool_node" if state["need_tool"] else "llm_node")。
  • 循环控制:通过"最大迭代次数"防止无限循环(默认配置)。

四、使用 LangGraph 构建复杂工作流:完整示例

以下以"智能客服工作流 "为例,构建一个包含问题分类、信息收集、解决方案生成、人工介入的复杂流程,涉及循环(信息不足时重新收集)和条件分支(不同类型问题走不同流程)。

场景描述

用户输入问题 → 分类问题类型(技术问题/投诉/咨询)→ 收集必要信息(若信息不足则循环收集)→ 生成解决方案(技术问题调用工具,投诉转人工)→ 输出结果。

步骤 1:安装依赖

bash 复制代码
pip install langgraph langchain openai python-dotenv  # 核心依赖
# 可选:安装可视化工具
pip install graphviz

步骤 2:完整代码实现

python 复制代码
import os
from typing import TypedDict, Literal, Annotated
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from dotenv import load_dotenv

load_dotenv()  # 加载环境变量(需配置 OPENAI_API_KEY)

# ----------------------
# 1. 定义状态(State)
# ----------------------
class CustomerServiceState(TypedDict):
    """客服工作流共享状态"""
    user_input: str  # 用户原始输入
    problem_type: Literal["technical", "complaint", "inquiry", "unknown"]  # 问题类型
    collected_info: dict  # 收集的信息(如设备型号、问题描述)
    solution: str | None  # 最终解决方案
    need_human: bool  # 是否需要人工介入
    messages: Annotated[list, lambda x,y: x + y]  # 对话历史(累加)

# ----------------------
# 2. 定义工具(Tools):模拟技术问题查询
# ----------------------
@tool
def search_tech_docs(query: str) -> str:
    """模拟查询技术文档库"""
    tech_docs = {
        "登录失败": "尝试重置密码或检查网络连接,步骤:1. 点击'忘记密码';2. 验证邮箱;3. 设置新密码。",
        "页面卡顿": "清除浏览器缓存(Ctrl+Shift+Del),或尝试更换浏览器(推荐 Chrome)。"
    }
    return tech_docs.get(query, "未找到相关文档,请联系技术支持。")

tools = [search_tech_docs]
tool_node = ToolNode(tools)  # LangGraph 预构建的工具节点

# ----------------------
# 3. 初始化 LLM(模拟大模型调用)
# ----------------------
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
llm_with_tools = llm.bind_tools(tools)  # 绑定工具的 LLM

# ----------------------
# 4. 定义节点(Nodes):工作流步骤
# ----------------------
def classify_problem(state: CustomerServiceState) -> CustomerServiceState:
    """节点 1:分类问题类型"""
    prompt = f"""用户问题:{state['user_input']}
    分类为:technical(技术问题)、complaint(投诉)、inquiry(咨询)、unknown(未知),仅返回类型名称。"""
    response = llm.invoke([HumanMessage(content=prompt)]).content.strip().lower()
    # 确保类型合法
    valid_types = ["technical", "complaint", "inquiry", "unknown"]
    problem_type = response if response in valid_types else "unknown"
    return {**state, "problem_type": problem_type, "messages": [SystemMessage(content=f"问题分类为:{problem_type}")]}

def collect_info(state: CustomerServiceState) -> CustomerServiceState:
    """节点 2:收集必要信息(循环执行直到信息足够)"""
    # 根据问题类型确定需要收集的信息
    required_info = {
        "technical": ["设备型号", "错误代码", "复现步骤"],
        "complaint": ["订单号", "投诉原因", "期望解决方案"],
        "inquiry": ["咨询主题", "具体疑问"]
    }.get(state["problem_type"], [])
    
    # 模拟信息收集(实际场景可调用表单或对话)
    collected = state.get("collected_info", {})
    if len(collected) < len(required_info):
        # 假设用户补充了信息(实际中需交互,这里模拟)
        collected.update({k: f"模拟_{k}_值" for k in required_info[:len(collected)+1]})
    return {**state, "collected_info": collected, "messages": [SystemMessage(content=f"已收集信息:{collected}")]}

def generate_solution(state: CustomerServiceState) -> CustomerServiceState:
    """节点 3:生成解决方案(调用工具或转人工)"""
    if state["problem_type"] == "technical":
        # 技术问题:调用工具查询文档
        query = state["collected_info"].get("错误代码", state["user_input"])
        tool_response = tool_node.invoke({"messages": [HumanMessage(content=query)]})
        solution = tool_response["messages"][-1].content
        need_human = False
    elif state["problem_type"] == "complaint":
        # 投诉:转人工
        solution = "您的投诉已记录,人工客服将在 24 小时内联系您。"
        need_human = True
    else:
        # 咨询:LLM 直接回答
        prompt = f"""用户咨询:{state['user_input']},收集的信息:{state['collected_info']},请给出简洁回答。"""
        solution = llm.invoke([HumanMessage(content=prompt)]).content
        need_human = False
    
    return {**state, "solution": solution, "need_human": need_human}

def human_handoff(state: CustomerServiceState) -> CustomerServiceState:
    """节点 4:人工介入处理"""
    return {**state, "solution": "人工客服已接手,正在处理中...", "messages": [SystemMessage(content="转人工成功")]}

def output_result(state: CustomerServiceState) -> CustomerServiceState:
    """节点 5:输出最终结果"""
    return {**state, "messages": [SystemMessage(content=f"最终结果:{state['solution']}")]}

# ----------------------
# 5. 定义边(Edges):流转逻辑
# ----------------------
def route_after_collect(state: CustomerServiceState) -> Literal["generate_solution", "collect_info"]:
    """收集信息后判断是否继续收集"""
    required_info = {
        "technical": ["设备型号", "错误代码", "复现步骤"],
        "complaint": ["订单号", "投诉原因", "期望解决方案"],
        "inquiry": ["咨询主题", "具体疑问"]
    }.get(state["problem_type"], [])
    # 若收集的信息不完整,则继续收集
    if len(state["collected_info"]) < len(required_info):
        return "collect_info"
    return "generate_solution"

def route_after_generate(state: CustomerServiceState) -> Literal["human_handoff", "output_result"]:
    """生成方案后判断是否转人工"""
    return "human_handoff" if state["need_human"] else "output_result"

# ----------------------
# 6. 构建图(Graph)
# ----------------------
workflow = StateGraph(CustomerServiceState)

# 添加节点
workflow.add_node("classify", classify_problem)  # 分类问题
workflow.add_node("collect", collect_info)        # 收集信息
workflow.add_node("generate", generate_solution)  # 生成方案
workflow.add_node("human", human_handoff)        # 人工介入
workflow.add_node("output", output_result)        # 输出结果
workflow.add_node("tools", tool_node)              # 工具节点(技术问题调用)

# 添加边(流转逻辑)
workflow.set_entry_point("classify")  # 入口节点:分类问题
workflow.add_edge("classify", "collect")  # 分类后进入收集信息
workflow.add_conditional_edges(  # 收集信息后条件分支
    "collect", 
    route_after_collect, 
    {"collect_info": "collect", "generate_solution": "generate"}
)
workflow.add_conditional_edges(  # 生成方案后条件分支
    "generate", 
    route_after_generate, 
    {"human_handoff": "human", "output_result": "output"}
)
workflow.add_edge("human", "output")  # 人工介入后输出结果
workflow.add_edge("output", END)       # 输出后结束

# 编译图为可执行工作流
app = workflow.compile()

# ----------------------
# 7. 运行工作流(示例)
# ----------------------
def run_customer_service(user_input: str):
    """运行客服工作流"""
    initial_state: CustomerServiceState = {
        "user_input": user_input,
        "problem_type": "unknown",
        "collected_info": {},
        "solution": None,
        "need_human": False,
        "messages": []
    }
    # 执行工作流
    result = app.invoke(initial_state)
    print(f"用户问题:{user_input}")
    print(f"问题类型:{result['problem_type']}")
    print(f"收集信息:{result['collected_info']}")
    print(f"解决方案:{result['solution']}")
    print("="*50)

# 测试用例
if __name__ == "__main__":
    # 测试 1:技术问题(需调用工具)
    run_customer_service("登录时提示错误代码 500,设备型号是 iPhone 13")
    
    # 测试 2:投诉(需转人工)
    run_customer_service("我昨天买的订单 #123 商品破损,要求退款并赔偿")
    
    # 测试 3:咨询(直接回答)
    run_customer_service("如何修改账户绑定的手机号?")

五、代码解析与执行结果

核心流程

  1. 分类问题 :LLM 将用户输入分类为 technical/complaint/inquiry
  2. 收集信息:根据问题类型收集必要信息(如技术问题的"设备型号""错误代码"),信息不足时循环收集。
  3. 生成方案
    • 技术问题:调用 search_tech_docs 工具查询文档;
    • 投诉:标记为需人工介入;
    • 咨询:LLM 直接生成回答。
  4. 人工介入/输出结果:投诉转人工,其他情况直接输出方案。

执行结果示例

复制代码
用户问题:登录时提示错误代码 500,设备型号是 iPhone 13
问题类型:technical
收集信息:{'设备型号': '模拟_设备型号_值', '错误代码': '模拟_错误代码_值', '复现步骤': '模拟_复现步骤_值'}
解决方案:尝试重置密码或检查网络连接,步骤:1. 点击'忘记密码';2. 验证邮箱;3. 设置新密码。
==================================================

六、总结

LangGraph 通过图结构+状态机模型,为大模型工程师提供了构建复杂 AI 工作流的强大工具。其核心优势在于:

  • 灵活性:支持循环、分支、并行,突破线性链式调用的限制;
  • 可维护性:图结构清晰表达流程逻辑,便于调试和扩展;
  • 生态集成:无缝对接 LangChain 组件,降低开发成本。
相关推荐
DJ斯特拉2 小时前
黑马点评技术汇总(四)缓存雪崩 && 缓存击穿
数据库·缓存
lzhdim2 小时前
SQL 入门 7:SQL 聚合与分组:函数、GROUP BY 与 ROLLUP
java·服务器·数据库·sql·mysql
lifewange2 小时前
INSERT INTO ... SELECT ...
数据库·sql
烤麻辣烫2 小时前
I/O流 基础流
java·开发语言·学习·intellij-idea
Uso_Magic2 小时前
SQLSERVER__EXPLAIN 常用分析案例。
服务器·数据库·sql
云边散步2 小时前
godot2D游戏教程系列二(22)
笔记·学习·游戏
IAtlantiscsdn2 小时前
Redis面试题总结
数据库·redis·缓存
jincheng_2 小时前
软件设计师上午题|9模块极速背诵版
学习
Schengshuo3 小时前
Spring学习——新建module模块
java·学习·spring