惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
Y
Y Combinator Blog
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
S
SegmentFault 最新的问题
IT之家
IT之家
Recent Announcements
Recent Announcements
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
T
The Blog of Author Tim Ferriss
Martin Fowler
Martin Fowler
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
WordPress大学
WordPress大学
博客园 - Franky
L
LangChain Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - 叶小钗
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
雷峰网
雷峰网
腾讯CDC
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Help Net Security
Help Net Security
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Schneier on Security
Schneier on Security
博客园 - 聂微东
A
Arctic Wolf
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Exploit Database - CXSecurity.com
C
Cyber Attacks, Cyber Crime and Cyber Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Google DeepMind News
Google DeepMind News

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
AI开发-python-LangGraph框架(3-34-LangGraph循环实战)
万笑佛 · 2026-04-29 · via 博客园_首页

在构建复杂 AI 工作流时,我们经常会遇到不稳定的外部服务调用、需要重试的异步任务场景 —— 比如并行获取天气、时间等第三方数据,部分接口可能随机失败,这时候就需要工作流具备自动循环重试能力,直到任务成功或达到最大重试次数。

LangGraph 作为强大的工作流编排框架,完美支持循环执行逻辑,无需复杂的嵌套代码,就能通过状态管理 + 条件决策,实现优雅的循环重试流程。今天就和大家分享,如何用 LangGraph 打造一个支持并行任务、自动循环重试的完整工作流,彻底解决不稳定任务的执行难题。

我们的目标场景很明确:

  1. 并行执行两个独立任务(获取天气、获取时间),两个任务都存在随机失败概率;
  2. 只要任意一个任务失败,就自动触发循环重试,无需手动重启流程;
  3. 支持设置最大重试次数,避免无限循环,保障流程稳定性;
  4. 全程通过状态管理数据,重试时复用原始输入,自动更新执行结果。

这种模式广泛适用于:第三方 API 重试、异步数据拉取、批量任务容错处理、AI 工具调用容错等实际业务场景,通用性极强。

LangGraph 实现循环的核心逻辑,完全围绕 **「状态管理 + 条件决策」** 展开,没有复杂的语法,核心分为三大模块:

首先定义专属的工作流状态,把输入数据、任务结果、重试次数、最大重试数、执行状态全部封装起来。状态是 LangGraph 循环的核心 —— 所有节点的执行、重试的判断、结果的更新,都基于这个状态流转,每一次循环都会自动更新重试次数和任务结果,为决策提供依据。

这是循环的主体节点,负责并行执行目标任务。我们通过线程池实现多任务并行执行,提升效率;执行完成后,会自动判断两个任务是否全部成功,并把结果、重试次数更新到状态中,传递给下一个节点。这个节点是循环的「动作执行者」,每一次重试都会重新执行这个节点。

这是实现循环的关键核心!决策节点会读取最新的状态,根据规则判断流程走向:

  • ✅ 任务全部成功 → 结束流程;
  • ❌ 任务失败 + 未达最大重试次数 → 回到执行节点,重新循环
  • ❌ 任务失败 + 达到最大重试次数 → 强制结束流程。

通过这个决策节点,LangGraph 轻松实现了闭环循环,这也是它比传统工作流框架更灵活的地方。

对比传统代码写循环 + 重试的方式,LangGraph 的循环执行有三大突出优势:

循环逻辑、任务执行逻辑、决策逻辑完全分离,每个节点只做一件事。后续修改重试次数、调整任务逻辑、新增失败处理,都不用改动核心循环代码,维护成本极低。

不用自己定义变量记录重试次数、不用手动传递任务结果,LangGraph 会自动管理状态的更新与传递,彻底避免手动管理状态带来的 bug。

针对第三方接口、网络请求等易失败场景,自动重试机制能大幅提升任务成功率;同时限制最大重试次数,兼顾效率与稳定性,生产环境直接可用。

支持在循环节点内执行并行任务,既解决了任务容错问题,又保证了执行效率,复杂工作流也能轻松编排。

这套 LangGraph 循环重试模式,是生产级工作流的必备能力,适用场景非常广泛:

  • 第三方 API 调用容错(天气、地图、支付等接口);
  • AI Agent 工具调用自动重试(LLM 接口、插件调用);
  • 批量数据拉取 / 处理,保障任务完整性;
  • 异步任务执行,失败自动恢复。

它让工作流从「一次性执行」变成「智能容错执行」,大幅提升系统的稳定性和健壮性。

LangGraph 的循环执行能力,通过状态驱动 + 条件决策的设计,让复杂的循环重试工作流变得极简、优雅。

我们不需要编写嵌套的循环代码,只需要:定义状态承载数据→编写执行节点处理任务→编写决策节点控制循环,就能快速构建出支持并行、自动重试、容错性强的工作流。

这也是 LangGraph 的核心魅力:用最简洁的编排方式,解决最复杂的工作流问题,无论是 AI 应用还是常规业务流程,都能轻松驾驭。

代码流程图:

图片

 实现代码:

from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
import time
import random
from concurrent.futures import ThreadPoolExecutor, as_completed

# 1. 定义带重试状态的 State
class LoopState(TypedDict):
    input_data: str                  # 输入数据
    weather_data: str | None         # 天气数据
    time_data: str | None            # 时间数据
    retry_count: int                 # 重试次数
    max_retries: int                 # 最大重试次数
    is_success: bool                 # 是否执行成功(用于判断循环退出)

# 2. 模拟不稳定的并行任务(可能失败,触发循环)
def fetch_weather(input_data: str) -> str:
    """模拟天气数据获取(30%概率失败)"""
    print(f"\n[天气任务] 处理: {input_data}")
    if random.random() < 0.3:  # 30%失败概率
        print("[天气任务] ❌ 数据获取失败")
        return ""
    time.sleep(1)  # 模拟耗时
    result = f"{input_data} 天气:25℃ 晴天"
    print(f"[天气任务] ✅ 成功: {result}")
    return result

def fetch_time(input_data: str) -> str:
    """模拟时间数据获取(20%概率失败)"""
    print(f"\n[时间任务] 处理: {input_data}")
    if random.random() < 0.2:  # 20%失败概率
        print("[时间任务] ❌ 数据获取失败")
        return ""
    time.sleep(1)  # 模拟耗时
    result = f"{input_data} 时间:15:30 下午"
    print(f"[时间任务] ✅ 成功: {result}")
    return result

# 3. 并行执行节点(循环的核心执行节点)
def parallel_execution(state: LoopState) -> LoopState:
    """并行执行天气/时间任务,返回更新后的状态"""
    input_data = state["input_data"]
    retry_count = state["retry_count"] + 1
    print(f"\n{'='*50}")
    print(f"[循环执行] 第 {retry_count} 次重试")
    print('='*50)

    # 线程池并行执行
    with ThreadPoolExecutor(max_workers=2) as executor:
        future_weather = executor.submit(fetch_weather, input_data)
        future_time = executor.submit(fetch_time, input_data)

        # 收集结果
        weather_data = ""
        time_data = ""
        for future in as_completed([future_weather, future_time]):
            if future == future_weather:
                weather_data = future.result()
            elif future == future_time:
                time_data = future.result()

    # 判断本次执行是否成功
    is_success = bool(weather_data and time_data)

    # 返回更新后的状态
    return {
        "input_data": input_data,
        "weather_data": weather_data,
        "time_data": time_data,
        "retry_count": retry_count,
        "max_retries": state["max_retries"],
        "is_success": is_success
    }

# 4. 循环决策节点(判断是否继续重试)
def loop_decision(state: LoopState) -> str:
    """
    决策节点:返回下一个节点名称(循环/结束)
    - 成功 → END
    - 失败且未达最大重试 → parallel_execution(继续循环)
    - 失败且达最大重试 → END
    """
    print(f"\n[决策节点] 重试次数: {state['retry_count']}/{state['max_retries']} | 执行成功: {state['is_success']}")

    # 退出条件1:执行成功
    if state["is_success"]:
        print("[决策节点] ✅ 所有任务成功,结束循环")
        return END
    # 退出条件2:达到最大重试次数
    elif state["retry_count"] >= state["max_retries"]:
        print("[决策节点] ❌ 达到最大重试次数,强制结束")
        return END
    # 继续循环:返回并行执行节点名称
    else:
        print("[决策节点] 🔄 任务失败,继续重试")
        return "parallel_execution"

# 5. 初始化节点(设置初始状态)
def init_state(state: LoopState) -> LoopState:
    """初始化循环状态"""
    return {
        "input_data": state["input_data"],
        "weather_data": None,
        "time_data": None,
        "retry_count": 0,          # 初始重试次数0
        "max_retries": state["max_retries"],  # 最大重试次数(外部传入)
        "is_success": False        # 初始未成功
    }

# 6. 构建带循环的图
def create_loop_graph():
    graph_builder = StateGraph(LoopState)

    # 添加节点
    graph_builder.add_node("init", init_state)
    graph_builder.add_node("parallel_execution", parallel_execution)

    # 设置入口点
    graph_builder.set_entry_point("init")

    # 添加边:初始化 → 并行执行
    graph_builder.add_edge("init", "parallel_execution")

    # 核心:添加条件边(决策节点 → 循环/结束)
    graph_builder.add_conditional_edges(
        source="parallel_execution",       # 源节点:并行执行节点
        path=loop_decision,                # 决策函数(返回下一个节点名称)
        path_map={                         # 路径映射(决策结果 → 目标节点)
            "parallel_execution": "parallel_execution",  # 继续循环
            END: END                                     # 结束
        }
    )

    return graph_builder.compile()

# 7. 执行测试
if __name__ == "__main__":
    # 编译图
    loop_graph = create_loop_graph()

    # ========== 修复点1:跳过易报错的 ASCII 绘图 ==========

    # 导出 Mermaid 语法(循环结构也能正常展示)
    # 初始输入
    initial_input = {
        "input_data": "北京",
        "max_retries": 3  # 最大重试3次
    }

    # 执行循环图
    print("\n" + "="*60)
    print("🚀 开始执行带循环的LangGraph")
    print("="*60)
    start_time = time.time()

    # 调用图
    final_result = loop_graph.invoke(initial_input)

    # 输出结果
    elapsed = time.time() - start_time
    print(f"\n" + "="*60)
    print(f"✅ 执行完成!总耗时: {elapsed:.2f} 秒")
    print(f"🔍 最终状态:")
    print(f"   - 重试次数: {final_result['retry_count']}")
    print(f"   - 执行成功: {final_result['is_success']}")
    print(f"   - 天气数据: {final_result['weather_data'] or '获取失败'}")
    print(f"   - 时间数据: {final_result['time_data'] or '获取失败'}")
    print("="*60)

 
结果输出:

============================================================
🚀 开始执行带循环的LangGraph
============================================================

==================================================
[循环执行] 第 1 次重试
==================================================

[天气任务] 处理: 北京
[天气任务] ❌ 数据获取失败

[时间任务] 处理: 北京
[时间任务] ✅ 成功: 北京 时间:15:30 下午

[决策节点] 重试次数: 1/3 | 执行成功: False
[决策节点] 🔄 任务失败,继续重试

==================================================
[循环执行] 第 2 次重试
==================================================

[天气任务] 处理: 北京

[时间任务] 处理: 北京
[天气任务] ✅ 成功: 北京 天气:25℃ 晴天
[时间任务] ✅ 成功: 北京 时间:15:30 下午

[决策节点] 重试次数: 2/3 | 执行成功: True
[决策节点] ✅ 所有任务成功,结束循环

============================================================
✅ 执行完成!总耗时: 2.02 秒
🔍 最终状态:
   - 重试次数: 2
   - 执行成功: True
   - 天气数据: 北京 天气:25℃ 晴天
   - 时间数据: 北京 时间:15:30 下午
============================================================

更多学习资料尽在 老虎网盘资源