LangGraph 实战:10分钟打造带“人工审批”的智能体流水线 (Python + LangChain)

关键词:LangGraph, LangChain, 状态机, SOP, Human-in-the-loop

大家好,我是飞哥!👋

前两周我们学习了 LlamaIndex (最强大脑) 和 AutoGen (最强团队)。

按理说,有了这两个神器,什么应用做不出来?

但当你真正把 AutoGen 做的客服系统上线后,老板可能会找你谈话:

老板 :"飞哥,昨天有个用户说要退款,你的 AI 也没查订单状态,直接就答应了?而且那个订单金额是 10 万块!AI 居然没问我直接批了?"
:"呃...那个 Agent 比较热心肠..."

痛点 :🤯

AutoGen 这种"多 Agent 自由讨论"的模式,适合创意型任务 (写研报、写代码)。

但对于业务型任务 (退款、审批、报销),企业需要的是严谨的 SOP (标准作业程序),绝不允许 AI 自由发挥。

💡 解决方案

我们需要把 AI 从"自由讨论室"拉到"工厂流水线"上。

这就是 LangGraph 的使命 ------ 构建有状态、可控的图应用


1. 为什么你需要 LangGraph?(Why) 🤔

生动类比 🍎:

  • AutoGen = 头脑风暴会议 🗣️。大家七嘴八舌,最后也能讨论出结果,但过程不可控,适合创意
  • LangGraph = 肯德基后厨流水线 🍔。
    • State (托盘):一个托盘在流水线上流动,上面放着汉堡胚(用户需求)。
    • Node (工位)
      • 工位 1 (意图识别) 🤖:服务员看单子。是做"香辣鸡腿堡"还是"牛肉堡"?(决定去哪个分支)
      • 工位 2 (规则检查) ⚖️:称重员检查。肉饼有没有少于 100g?(金额 > 1000?)
      • 工位 3 (人工审批) 🛑:质检员发现肉饼颜色不对,按停传送带!喊店长(人类)过来确认。店长说"行",才能继续包装;店长说"不行",直接扔掉。(Human-in-the-loop)
      • 工位 4 (执行) 💸:打包员装袋,递给顾客。

核心价值 💎:

LangGraph 让你能用代码画出这张"流程图",并且强制 AI 沿着线走。最重要的是,它支持 Human-in-the-loop (人在回路) ------ 关键时刻,必须人来拍板,AI 才能继续。


2. 核心概念提炼 (Skeleton) 🦴

LangGraph 的世界里主要有这几个概念:

  1. State (状态) 📦:
    • 流水线上的"包裹"。所有节点都在读写这个包裹里的数据(比如 order_id, status)。
  2. Node (节点) 👷:
    • 流水线上的"工位"。可以是 LLM,可以是 Python 函数,也可以是 API 调用。
  3. Edge (边) 🔗:
    • 连接工位的"传送带"。
    • Conditional Edge (条件边) 🔀:智能分拣机。如果 amount > 1000,传送到"经理室";否则传送到"财务室"。
  4. START & END 🏁:
    • 图的入口出口

3. 实战项目:智能客服"工单自动处理流" 🛠️

我们要实现一个严谨的退款系统,绝不让 AI 乱批款。

📦 安装依赖

bash 复制代码
pip install langgraph langchain-openai langchain-core
  • langgraph :本次课程的主角。它负责画图 (定义状态、节点、边),并管理整个流水线的运行(包括暂停、恢复)。
  • langchain-core :LangChain 家族的基础组件。它定义了 BaseMessage(消息格式)、PromptTemplate(提示词模版)等通用标准,相当于乐高的"基础积木块"。
  • langchain-openai:连接 OpenAI 模型的桥梁。如果我们的节点需要调用 GPT-4 进行意图识别或生成回复,就得靠它。

📊 流程设计图

是退款
闲聊
金额 < 1000
金额 >= 1000
经理同意
经理拒绝
用户输入
意图识别节点
退款规则检查节点
直接回复
自动批准
经理审批节点
拒绝退款

💻 核心代码拆解

第一步:定义状态 (包裹里有什么?) 📦
python 复制代码
from typing import TypedDict, Annotated, List, Optional
import operator
from langchain_core.messages import BaseMessage

class AgentState(TypedDict):
    messages: Annotated[List[BaseMessage], operator.add] # 聊天记录 (使用 operator.add 追加新消息)
    order_id: Optional[str]        # 订单号
    amount: Optional[float]        # 订单金额
    # 状态机核心字段:
    # pending: 初始状态
    # waiting_approval: 等待经理审批 (金额 > 1000)
    # approved: 已批准 (金额 < 1000 或 经理同意)
    # rejected: 已拒绝 (经理拒绝)
    refund_status: str             
第二步:定义节点 (工人在干什么?) 👷
python 复制代码
def node_process_refund(state: AgentState):
    """
    退款规则检查节点
    输入: state['order_id']
    输出: 更新 state['amount'] 和 state['refund_status']
    """
    
    # 模拟查询数据库
    def get_order_amount(order_id):
        # 假设所有订单都是 1200 元 (大于 1000,触发审批)
        return 1200.0
    
    amount = get_order_amount(state['order_id']) 
    
    # 规则引擎逻辑
    if amount > 1000:
        print("⚠️ 金额 > 1000, 需要经理审批")
        # 返回的部分数据会自动 merge 到 State 中
        return {"amount": amount, "refund_status": "waiting_approval"}
    else:
        print("✅ 金额 < 1000, 自动批准")
        return {"amount": amount, "refund_status": "approved"}

def node_human_approval(state: AgentState):
    """
    人工审批节点
    注意:这里其实是个空函数,因为我们会在进入这个节点前使用 interrupt_before 暂停。
    当人工 update_state 后,会直接跳过这个节点的执行,进入下一个节点。
    """
    pass
第三步:构建图与人工介入 (关键!) 🛑

这里最神奇的是 interrupt_before。它告诉 LangGraph:在进入 human_approval 节点之前,把程序暂停,把状态存到数据库里(MemorySaver),然后等待指令!

注意:这里的"暂停"不是进程退出,而是图的执行挂起。如果你用的是 Web 服务,这意味着 API 请求结束,等待下一个 API 请求来唤醒它。

python 复制代码
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver

# 构建图
workflow = StateGraph(AgentState)

# 1. 添加节点 (Add Nodes)
# 注册我们的"工人"和"工位"
workflow.add_node("process", node_process_refund)
workflow.add_node("human_approval", node_human_approval) 

# 2. 设置入口 (Set Entry Point)
# 告诉图从哪里开始跑 (这里假设直接进入 process)
workflow.set_entry_point("process")

# 3. 添加条件边 (Conditional Edges)
# 相当于流水线上的"分拣机"
def route_process(state):
    # 如果状态是 waiting_approval,就传送到 human_approval 工位
    if state['refund_status'] == "waiting_approval":
        return "human_approval"
    # 否则直接结束 (END)
    return END

# 将 process 节点连接到分拣逻辑 (route_process)
# 意味着:process 跑完后,下一步去哪儿?问问 route_process!
workflow.add_conditional_edges("process", route_process)

# 4. 添加普通边 (Edges)
# 经理审批完,直接结束
workflow.add_edge("human_approval", END)

# 5. 编译图 (Compile)
# memory: 用于保存图的运行状态 (Checkpointer)
memory = MemorySaver()

app = workflow.compile(
    checkpointer=memory, 
    # interrupt_before: 在进入这些节点之前,强制暂停!
    # 这是实现 Human-in-the-loop 的关键
    interrupt_before=["human_approval"] 
)
第四步:运行与交互 (Human-in-the-loop) 🤝

当程序暂停时,你可以去喝杯咖啡。回来后,经理输入 yes,程序会从断点处恢复执行。

python 复制代码
# 1. 配置 (Config)
# thread_id: 每个用户的对话都有唯一的 ID,类似微信号
config = {"configurable": {"thread_id": "thread-1"}}

# 2. 初始运行 (Run)
# 我们只给一个空的输入,因为这里假设从 process 节点开始,它会自己去查 order_id
print("🚀 系统启动...")
for event in app.stream({"order_id": "BIG888"}, config=config):
    # stream 会逐步输出每个节点的执行结果
    pass

# 3. 检查断点 (Check Interrupt)
# 运行结束后,检查一下图的状态
state = app.get_state(config)
if state.next and "human_approval" in state.next:
    # 发现下个节点是 human_approval,说明被暂停了!
    print(f"🛑 触发风控!等待经理审批... (金额: {state.values['amount']})")
    
    user_input = input("经理是否批准?(yes/no): ")
    
    if user_input == "yes":
        # 4. 人工干预 (Human Intervention)
        # 经理说 OK,我们直接修改图里的状态
        print("✅ 经理已批准,更新状态为 approved")
        app.update_state(config, {"refund_status": "approved"})
    else:
        print("❌ 经理已拒绝,更新状态为 rejected")
        app.update_state(config, {"refund_status": "rejected"})

    # 5. 恢复执行 (Resume)
    # 再次调用 stream,这次传入 None,LangGraph 会自动从断点处继续跑
    print("▶️ 继续执行后续流程...")
    for event in app.stream(None, config=config):
        pass

🎯 运行结果展示

当你运行这段代码时,你会看到类似下面的交互过程:

text 复制代码
🚀 系统启动...
⚠️ 金额 > 1000, 需要经理审批
🛑 触发风控!等待经理审批... (金额: 1200.0)
经理是否批准?(yes/no): yes
✅ 经理已批准,更新状态为 approved
▶️ 继续执行后续流程...
✅ 金额 < 1000, 自动批准 (注意:这里可能是后续节点的日志)

看!这就是 Human-in-the-loop 的魅力。

AI 跑得再快,关键时刻也得停下来听你的。这种"暂停-修改-继续"的能力,正是传统自动化脚本做不到的,也是构建负责任 AI (Responsible AI) 的基石。


4. 飞哥总结 📝

  • AutoGen文科生,擅长创意、协作、发散思维。
  • LangGraph理科生,擅长逻辑、规则、流程控制。

在真正的企业级 AI 应用(如 ERP、CRM、OA 系统)中,LangGraph 才是那个能让老板放心的"定海神针"。

下期预告

做好了功能,怎么知道 AI 到底稳不稳定?会不会哪天突然变笨了?

下周我们将进入 LLMOps (运维与监控) 的世界,教你用 LangSmith 监控 AI 的一举一动!

创作不易,记得👇关注飞哥👇 ,点赞、收藏哦~~,下篇见👋

相关推荐
yy.y--1 小时前
Java数组逆序读写文件实战
java·开发语言
jz_ddk1 小时前
[实战] 从冲击响应函数计算 FIR 系数
python·fpga开发·信号处理·fir·根升余弦·信号成形
醒醒该学习了!2 小时前
如何将json文件转成csv文件(python代码实操)
服务器·python·json
Polaris北2 小时前
第二十七天打卡
开发语言·c++·算法
忘忧记2 小时前
pythonQT版本的图书管理系统
python·fastapi
一只理智恩2 小时前
AI 实战应用:从“搜索式问答“到“理解式助教“
人工智能·python·语言模型·golang
亓才孓2 小时前
【Exception】CONDITIONS EVALUATION REPORT条件评估报告
java·开发语言·mybatis
Katecat996632 小时前
输液泵设备检测与识别基于改进YOLO11模型的实现详解_ETB
python
Sirius.z2 小时前
第T7周:咖啡豆识别
python