LangGraph实战编码:核心概念、开发范式与高级特性

目录

状态定义:Agent的"记忆中枢"

节点开发:纯函数与异常捕获

路由设计:条件边与循环保护

高级特性:工具调用与人工中断

实战编码的核心价值


在上一篇教程中,我们已经从零开始搭建好了支持可视化调试的LangGraph开发环境。很多人反馈:"环境搭好了,但代码到底该怎么写才规范?为什么我写的Agent总是状态混乱、循环失控,甚至直接报错?"其实,LangGraph的编码核心就三件事:定义好状态、写好纯函数节点、连对路由边。只要掌握这三个核心范式,再结合工具调用、人工中断等高级特性,你就能写出稳定、可维护的Agent。本文将以"自动周报Agent"为贯穿案例,手把手带你掌握LangGraph的实战编码规范,所有代码均可直接运行。

状态定义:Agent的"记忆中枢"

State 是LangGraph的灵魂,它决定了节点之间传递什么数据。很多新手容易犯的错误是:把State当成普通字典随便写,导致节点之间数据丢失或覆盖。规范的写法是使用TypedDictPydantic 模型定义State,并用Annotated 指定Reducer 。Reducer决定了状态字段的更新方式,比如消息列表要用add_messages追加,而不是直接覆盖。

以下是一个规范的周报Agent状态定义,直接复制即可使用:

python 复制代码
from typing import TypedDict, Annotated
from langgraph.graph import add_messages

class WeeklyReportState(TypedDict):
    raw_data: str          # 原始工作数据(如Git日志、任务列表)
    draft: str             # 周报初稿
    final_report: str      # 最终通过的周报
    retry_count: int       # 重试次数,防止无限循环
    feedback: str          # 审核节点的反馈(如"缺少量化数据")
    messages: Annotated[list, add_messages]  # 对话历史,自动追加

避坑提示:不要直接修改传入的state对象!节点函数必须返回一个字典,LangGraph会自动用Reducer合并更新。比如想更新retry_count ,只需返回**{"retry_count": state"retry_count" + 1}** ,而不是state"retry_count" += 1。直接修改state会导致状态更新丢失,Agent无法感知到重试次数的变化,最终陷入死循环。

节点开发:纯函数与异常捕获

节点是Agent的执行单元,每个节点只负责一件事。规范的节点函数必须是纯函数:接收state 作为输入,返回更新后的state字典,不修改外部变量,不产生副作用。同时,必须在节点中做好异常捕获,避免单个节点失败导致整个工作流崩溃。

以下是一个带异常捕获的周报生成节点,可直接运行:

python 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
import os
from dotenv import load_dotenv

load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)

def report_generator_node(state: WeeklyReportState):
    """内容生成节点:根据原始数据生成周报初稿"""
    try:
        prompt = f"""
        你是一位资深技术主管,请根据以下原始工作数据生成周报。
        要求:使用【本周重点】、【量化成果】、【下周计划】三个模块,必须包含具体数字。
        原始数据:{state['raw_data']}
        """
        response = llm.invoke([HumanMessage(content=prompt)])
        print(f"[生成节点] 已生成周报初稿,字数:{len(response.content)}")
        return {"draft": response.content}
    except Exception as e:
        print(f"[生成节点] 执行失败:{str(e)}")
        return {"feedback": f"生成失败:{str(e)}", "retry_count": state["retry_count"] + 1}

避坑提示:节点返回值必须是字典!即使只更新一个字段,也要返回**{"field": value}** ,而不是直接返回value。否则LangGraph无法识别更新内容,导致状态丢失。同时,异常捕获后必须返回包含feedback和retry_count的字典,否则Agent无法感知到生成失败,也不会触发重试逻辑。

路由设计:条件边与循环保护

边决定了数据在节点之间的流动方向。普通边用于固定流程,条件边用于动态路由。很多新手在写条件边时,容易犯两个错误:一是路由函数返回值与映射字典不匹配,二是没有设置循环保护,导致Agent陷入死循环。

以下是一个带循环保护的条件路由函数,可直接运行:

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

def should_continue(state: WeeklyReportState):
    """条件路由函数:决定下一步走向"""
    # 检查是否有反馈(不合格)且未超过最大重试次数
    if state["feedback"] and state["retry_count"] < 3:
        return "regenerate"
    else:
        return "end"

# 构建状态图
workflow = StateGraph(WeeklyReportState)
workflow.add_node("generator", report_generator_node)
workflow.add_node("checker", quality_checker_node)
workflow.add_edge("generator", "checker")
workflow.add_conditional_edges(
    "checker",
    should_continue,
    {
        "regenerate": "generator",  # 不合格且未超重试次数 → 退回生成器
        "end": END                  # 合格或超重试次数 → 结束
    }
)

避坑提示:条件边的映射字典key必须与路由函数返回值完全一致!比如路由函数返回**"regenerate"** ,映射字典就不能写"retry",否则会直接报错KeyError 。同时,一定要在路由函数中检查retry_count,避免死循环。建议将最大重试次数设置为3,既给Agent足够的修正机会,又避免无效消耗。

高级特性:工具调用与人工中断

当Agent需要调用外部工具(如查询数据库、调用API)时,可以使用ToolNode自动接管工具调用。同时,在关键节点插入人工中断,让Agent在重要决策前等待人类确认。

以下是一个带工具调用和人工中断的完整示例,可直接运行:

python 复制代码
from langgraph.prebuilt import ToolNode
from langgraph.graph import interrupt
from langchain_core.tools import tool

# 定义工具
@tool
def query_git_log(branch: str) -> str:
    """查询指定分支的Git提交记录"""
    return f"分支{branch}本周提交记录:修复登录Bug、完成单元测试、参与需求评审"

tools = [query_git_log]
tool_node = ToolNode(tools)

# 人工审批节点
def human_approval_node(state: WeeklyReportState):
    """人工审批节点:等待用户确认周报内容"""
    print(f"[人工审批] 当前周报草稿:\n{state['draft']}")
    # 暂停工作流,等待用户输入
    user_input = interrupt("请确认周报内容是否合格(输入'yes'或'no'):")
    if user_input.lower() == "yes":
        return {"final_report": state["draft"]}
    else:
        return {"feedback": "用户审核未通过,请重新生成", "retry_count": state["retry_count"] + 1}

避坑提示:interrupt()会暂停整个工作流,直到用户输入才会继续。在生产环境中,建议将中断结果持久化到数据库,避免服务重启后丢失审批状态。同时,工具节点的返回值必须与ToolMessage格式一致,否则LLM无法正确解析工具结果。ToolNode会自动处理工具调用和结果返回,无需手动构造ToolMessage。

实战编码的核心价值

掌握状态定义、节点开发、路由设计这三个核心范式,你就已经具备了编写规范LangGraph代码的能力。高级特性则是在此基础上的延伸,帮助你构建更复杂、更稳定的Agent。本文的完整代码已整理为单文件,可直接在上一篇文章搭建的环境中运行。如果你在编码过程中遇到任何问题,欢迎在评论区留言。下一篇**《LangGraph生产维护》**将带你深入稳定性、可观测性与运维实战,让Agent真正敢上线、能落地。

相关推荐
AI办公探索者9 小时前
仓储物流AI任务执行的技术拆解:从WMS自动化到多设备协同的落地路径
运维·人工智能·ai·自动化
delishcomcn9 小时前
边缘计算+AI模型:电化铝分切装备的智能化改造路径
大数据·人工智能·边缘计算
fai厅的秃头姐!10 小时前
OpenCV——进阶
人工智能·opencv·计算机视觉
蓝速科技10 小时前
蓝速 AI 双屏翻译机酒店涉外接待部署指南
人工智能
q5673152310 小时前
人工智能训练数据采集:稳定代理IP高并发方案全解析
人工智能·爬虫·网络协议·tcp/ip·代理模式·代理ip
太原geo小侦探10 小时前
2026门店AI流量实测测评:同为实体门店,AI问答曝光差距在哪?
大数据·人工智能·生活·流量运营·内容运营
大鹏的NLP博客10 小时前
机器学习中的统计波动控制与表征几何优化原则:从函数稳定性到隐空间结构学习
人工智能·深度学习·机器学习
AI大法师10 小时前
一个机场如何被做成 IP 场景:宝可梦机场的设计方法总结
大数据·人工智能·设计模式·新媒体运营
yangshicong10 小时前
第19章:AI安全防护与AI安全
人工智能·python·安全·prompt·ai编程