当前位置: 首页 > article >正文

LangGraph 错误处理与超时控制全指南

这是生产级 Agent 必不可少的能力我会从原理→方法→完整代码一次性讲透如何给 Agent 加上超时控制、工具调用失败重试、模型调用异常兜底让你的 Agent 更健壮、不会轻易崩溃。一、核心概念与方法总览LangGraph 的错误处理与超时控制主要分为 3 个层面层面解决的问题核心方法超时控制模型 / 工具调用卡死、响应慢LLM / 工具初始化时设置timeout节点内错误处理单次调用失败try-except捕获异常存入 State流程级错误处理节点失败后的流程决策重试装饰器、Fallback 节点、条件边路由二、超时控制防止卡死1. LLM 调用超时在初始化模型时直接设置timeout参数单位为秒from langchain_zhipu import ChatZhipuAI llm ChatZhipuAI( api_keyos.getenv(ZHIPU_API_KEY), modelglm-4.6, temperature0, timeout15, # ✅ 15秒超时超过直接报错 max_retries0 # 先关闭自动重试方便我们手动控制 )2. 工具调用超时有两种方式方式 1在ToolNode中设置推荐from langgraph.prebuilt import ToolNode # 给所有工具设置统一超时 tool_executor ToolNode( tools, handle_tool_errorsTrue, # ✅ 自动捕获工具错误 timeout10 # ✅ 工具调用10秒超时 )方式 2在工具函数内部设置针对单个工具import time from langchain_core.tools import tool tool def get_weather(city: str) - str: 获取指定城市的天气 try: # 模拟可能超时的操作 time.sleep(2) if city 北京: return 北京晴25℃微风 return 未知天气 except TimeoutError: return ⚠️ 天气查询超时请稍后再试三、错误处理让 Agent 不崩溃1. 节点内try-except最基础、最常用在每个节点内部捕获异常把错误信息存入 State让流程继续走下去而不是直接崩溃from langchain_core.messages import AIMessage def llm_think(state: ReActState): print(f\n-- 第 {state[loop_count]}轮LLM思考 --) messages state[messages] user_id state[user_id] try: # 加载长期记忆 user_preference store.get((user_memory, user_id), preference) if user_preference: print(f 加载长期记忆{user_preference.value}) messages [HumanMessage(contentf用户偏好{user_preference.value})] messages # 调用 LLM response llm.invoke(messages) error None # 无错误 except Exception as e: print(f❌ LLM 调用失败{str(e)}) # 失败时返回友好的错误消息 response AIMessage(contentf抱歉我暂时无法处理你的请求{str(e)}) error str(e) # 记录错误 return { messages: [response], loop_count: state[loop_count] 1, user_id: user_id, error: error # ✅ 把错误存入 State }2. LangGraph 重试装饰器自动重试LangGraph 提供了retry装饰器可以给节点设置自动重试from langgraph.checkpoint.utils import retry # 给 llm_think 节点添加重试最多重试2次间隔1秒 retry( max_attempts2, # 最多重试2次 wait_before1.0, # 每次重试前等待1秒 retry_on(Exception,) # 捕获所有异常 ) def llm_think(state: ReActState): # 节点逻辑不变 ...3. Fallback 节点失败时走备用方案当主节点失败时自动切换到备用节点比如用更简单的模型、或者返回固定回复# 备用 LLM比如用更轻量的模型 backup_llm ChatZhipuAI( api_keyos.getenv(ZHIPU_API_KEY), modelglm-4-flash, # 更轻量、更稳定的模型 temperature0, timeout10 ) def backup_llm_think(state: ReActState): 备用节点主节点失败时调用 print(\n-- 切换到备用 LLM --) response backup_llm.invoke(state[messages]) return { messages: [response], loop_count: state[loop_count] 1, user_id: state[user_id], error: None } # 条件边根据 error 决定走主节点还是备用节点 def should_route(state: ReActState) - Literal[llm_think, backup_llm_think, end]: if state.get(error) and state[loop_count] 2: return backup_llm_think # 失败且次数少走备用 elif not state[messages][-1].tool_calls or state[loop_count] 5: return end else: return tool_executor4. 条件边路由根据错误状态决策修改 State 增加error字段然后在条件边中根据错误信息决定下一步# 修改 State 定义 class ReActState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages] loop_count: int user_id: str error: str | None # ✅ 新增存储错误信息四、完整代码示例带超时 错误处理这是基于你之前的代码添加了超时控制、节点内错误处理、错误状态记录、防崩溃机制的完整可运行版本import os from typing import TypedDict, Sequence, Literal, Annotated import redis from dotenv import load_dotenv from langchain_core.messages import BaseMessage, HumanMessage, AIMessage from langchain_core.tools import tool from langchain_zhipu import ChatZhipuAI from langgraph.constants import START, END from langgraph.graph import StateGraph, add_messages from langgraph.prebuilt import ToolNode from langgraph.store.redis import RedisStore from langgraph.checkpoint.redis import RedisSaver # 加载环境变量 load_dotenv() # 工具定义带内部错误处理 tool def get_weather(city: str) - str: 获取指定城市的天气 try: if city 北京: return 北京晴25℃微风 elif city 上海: return 上海多云28℃东南风 else: return f{city}未知仅支持北京/上海 except Exception as e: return f⚠️ 天气查询失败{str(e)} tool def calculator(a: float, b: float, op: str) - float: 计算器支持 - * / try: if op : return a b elif op -: return a - b elif op *: return a * b elif op /: return a / b if b ! 0 else 除数不能为0 else: return 不支持的运算符 except Exception as e: return f⚠️ 计算失败{str(e)} tools [get_weather, calculator] # 状态定义新增 error 字段 class ReActState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages] loop_count: int user_id: str error: str | None # ✅ 存储错误信息 # 初始化持久化组件 redis_client redis.Redis(hostlocalhost, port6379, db0) checkpointer RedisSaver(redis://localhost:6379/0) checkpointer.setup() store RedisStore(redis_client) store.setup() print(✅ Redis 索引已创建) # 初始化 LLM带超时控制 llm ChatZhipuAI( api_keyos.getenv(ZHIPU_API_KEY), modelos.getenv(LLM_MODEL), temperature0, timeout15, # ✅ 15秒超时 max_retries0 ) # 备用 LLM更轻量、更稳定 backup_llm ChatZhipuAI( api_keyos.getenv(ZHIPU_API_KEY), modelglm-4-flash, temperature0, timeout10 ) # 工具执行节点带超时和错误处理 tool_executor ToolNode( tools, handle_tool_errorsTrue, # ✅ 自动捕获工具错误 timeout10 # ✅ 工具调用10秒超时 ) # 节点定义带 try-except 错误处理 def llm_think(state: ReActState): print(f\n-- 第 {state[loop_count]}轮LLM思考 --) messages state[messages] user_id state[user_id] error None try: # 加载长期记忆 user_preference store.get((user_memory, user_id), preference) if user_preference: print(f 加载长期记忆{user_preference.value}) messages [HumanMessage(contentf用户偏好{user_preference.value})] messages # 调用 LLM response llm.invoke(messages) except Exception as e: print(f❌ LLM 调用失败{str(e)}) response AIMessage(contentf抱歉我暂时遇到了一点问题{str(e)}) error str(e) return { messages: [response], loop_count: state[loop_count] 1, user_id: user_id, error: error } def backup_llm_think(state: ReActState): 备用节点主 LLM 失败时调用 print(\n-- 切换到备用 LLM --) try: response backup_llm.invoke(state[messages]) error None except Exception as e: print(f❌ 备用 LLM 也失败了{str(e)}) response AIMessage(content非常抱歉服务暂时不可用请稍后再试。) error str(e) return { messages: [response], loop_count: state[loop_count] 1, user_id: state[user_id], error: error } # 条件路由根据错误状态决策 def should_continue(state: ReActState) - Literal[llm_think, backup_llm_think, tool_executor, end]: last_message state[messages][-1] # 优先处理错误 if state.get(error): if state[loop_count] 2: return backup_llm_think # 失败次数少走备用 else: return end # 失败次数多直接结束 # 正常流程 if not last_message.tool_calls or state[loop_count] 5: print(→ 结束无需工具 或 达到最大轮次) return end print(→ 继续需要调用工具) return tool_executor # 构建图 builder StateGraph(ReActState) builder.add_node(llm_think, llm_think) builder.add_node(backup_llm_think, backup_llm_think) builder.add_node(tool_executor, tool_executor) builder.add_edge(START, llm_think) builder.add_conditional_edges( llm_think, should_continue, { backup_llm_think: backup_llm_think, tool_executor: tool_executor, end: END } ) builder.add_conditional_edges( backup_llm_think, should_continue, { tool_executor: tool_executor, end: END } ) builder.add_edge(tool_executor, llm_think) # 编译图 react_agent builder.compile( checkpointercheckpointer, storestore ) # 测试运行 if __name__ __main__: print( LangGraph 带错误处理的 Agent 启动 ) config { configurable: { thread_id: session_001, user_id: user_001 } } # 第一轮对话 print(\n--- 第一轮对话 ---) initial_state { messages: [HumanMessage(content北京今天天气上海比北京高3度上海多少度)], loop_count: 0, user_id: user_001, error: None } result1 react_agent.invoke(initial_state, configconfig) print(f第一轮答案{result1[messages][-1].content}) # 保存长期记忆 store.put((user_memory, user_001), preference, 喜欢用摄氏度偏好简洁回答) print(\n✅ 已保存长期记忆) # 第二轮对话 print(\n--- 第二轮对话 ---) result2 react_agent.invoke( {messages: [HumanMessage(content上海天气符合我的偏好吗)]}, configconfig ) print(第二轮答案, result2[messages][-1].content)五、关键要点总结超时控制在 LLM 和ToolNode初始化时设置timeout防止卡死节点内错误处理用try-except捕获异常把错误信息存入 State返回友好回复备用方案设置 Fallback 节点主节点失败时切换到更稳定的备用方案条件边决策根据 State 中的错误信息灵活决定下一步是重试、走备用还是结束错误记录在 State 中增加error字段方便后续调试和分析

相关文章:

LangGraph 错误处理与超时控制全指南

这是生产级 Agent 必不可少的能力!我会从原理→方法→完整代码,一次性讲透如何给 Agent 加上超时控制、工具调用失败重试、模型调用异常兜底,让你的 Agent 更健壮、不会轻易崩溃。一、核心概念与方法总览LangGraph 的错误处理与超时控制主要分…...

Python 爬虫进阶技巧:网页乱码问题全方位解决办法

前言 在 Python 爬虫项目落地与数据采集过程中,网页乱码是高频出现且极易影响数据解析质量的核心问题。各类网站开发规范不统一、编码格式自定义、响应头标识缺失、压缩传输等多重因素,都会导致爬虫获取的 HTML 文本、接口数据出现问号、方框、异形字符…...

ngx_connection_local_sockaddr

1 定义 ngx_connection_local_sockaddr 函数 定义在 ./nginx-1.24.0/src/core/ngx_connection.cngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,ngx_uint_t port) {socklen_t len;ngx_uint_t addr;ngx_sockaddr_t …...

如何免费下载Steam创意工坊模组:跨平台玩家的终极解决方案

如何免费下载Steam创意工坊模组:跨平台玩家的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在Epic Games Store或GOG平台购买了心仪的游戏&…...

GRETNA开源工具实战指南:从零掌握MATLAB脑网络分析

GRETNA开源工具实战指南:从零掌握MATLAB脑网络分析 【免费下载链接】GRETNA A Graph-theoretical Network Analysis Toolkit in MATLAB 项目地址: https://gitcode.com/gh_mirrors/gr/GRETNA 在神经科学研究中,如何从复杂的大脑影像数据中提取有意…...

5个实战技巧:高效使用WebAssembly进行浏览器端图像处理

5个实战技巧:高效使用WebAssembly进行浏览器端图像处理 【免费下载链接】opencvjs JavaScript Bindings for OpenCV 项目地址: https://gitcode.com/gh_mirrors/op/opencvjs OpenCV.js是OpenCV计算机视觉库的JavaScript绑定版本,通过Emscripten将…...

3个步骤掌握AI Toolkit:从零到一的完整AI开发指南

3个步骤掌握AI Toolkit:从零到一的完整AI开发指南 【免费下载链接】vscode-ai-toolkit 项目地址: https://gitcode.com/GitHub_Trending/vs/vscode-ai-toolkit AI Toolkit for Visual Studio Code是一款专为开发者设计的AI应用开发扩展,它将Azur…...

小龙虾养成记:小龙虾和爱马仕(OpenClaw vs Hermes)源码对比与选型指南

适用人群:第一次接触 OpenClaw / Hermes,想快速看懂差异、做选型、不踩坑。 OpenClaw:偏本地与可控编排 | Hermes:偏在线与持续运营 小龙虾和爱马仕怎么选?是不是很多朋友都有这个疑惑。其实很多朋友第一次看 OpenClaw 和 Hermes,会有同一个感受: “都能接微信/飞书/…...

如何快速配置Lab Streaming Layer:科研数据同步与流式处理的完整指南

如何快速配置Lab Streaming Layer:科研数据同步与流式处理的完整指南 【免费下载链接】labstreaminglayer LabStreamingLayer super repository comprising submodules for LSL and associated apps. 项目地址: https://gitcode.com/gh_mirrors/la/labstreamingla…...

CSS旋转效果在Edge旧版支持_添加-ms-transform前缀与过渡

本文教你如何将 random.randint(100, 999) 生成的三位整数拆解为各位数字,高效判断是否存在重复数字(如 112、333),并量化重复程度(双重复/三重复),从而为游戏逻辑提供可编程的胜率倍数变量。 …...

5分钟搞定小说离线阅读:Novel-Downloader终极使用指南

5分钟搞定小说离线阅读:Novel-Downloader终极使用指南 【免费下载链接】novel-downloader 一个可扩展的通用型小说下载器。 项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader 你是否经常遇到这样的情况:追更到一半的小说突然网站打…...

星露谷农场规划器:专业级农场布局设计与优化方案

星露谷农场规划器:专业级农场布局设计与优化方案 【免费下载链接】stardewplanner Stardew Valley farm planner 项目地址: https://gitcode.com/gh_mirrors/st/stardewplanner 星露谷农场规划器(Stardew Valley Farm Planner)是一款专…...

终极指南:如何用RPFM快速上手《全面战争》模组制作

终极指南:如何用RPFM快速上手《全面战争》模组制作 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址: https://gitcod…...

构建现代化IT资产管理体系:开源CMDB如何解决企业运维核心痛点

构建现代化IT资产管理体系:开源CMDB如何解决企业运维核心痛点 【免费下载链接】open-cmdb 开源资产管理平台 项目地址: https://gitcode.com/gh_mirrors/op/open-cmdb 在数字化转型的浪潮中,企业IT基础设施日益复杂,资产管理混乱、运维…...

零基础入门kohya_ss:在AMD GPU上轻松训练你的专属AI绘画模型

零基础入门kohya_ss:在AMD GPU上轻松训练你的专属AI绘画模型 【免费下载链接】kohya_ss 项目地址: https://gitcode.com/GitHub_Trending/ko/kohya_ss 你是否曾经想过,用自己的AMD显卡就能训练出专属的AI绘画模型?不用羡慕那些拥有昂…...

我开源了一款本地音乐播放器 —— Yeah Music,欢迎大家体验

我开源了一款本地音乐播放器 —— Yeah Music,欢迎大家体验 🎵 大家好,我是一名普通的开发者,也是个重度本地音乐爱好者。 这些年被各种商业音乐App的广告、会员、联网要求搞得很烦,尤其是想好好听自己收藏的无损音乐时…...

【PostgreSQL从零到精通】第48篇:PL/Proxy数据分片——PostgreSQL的水平扩展利器

上一篇【第47篇】Bucardo多主复制——实现真正的双向数据同步 下一篇【第49篇】pgpool-II完全指南——连接池复制负载均衡的三合一方案 单台 PostgreSQL 服务器的读写能力总有一个上限。当数据量达到 TB 级别、并发请求达到数万 QPS 时,再怎么优化硬件也无济于事——…...

看完100个失败私域直播案例,90%的人死在预热前

前年刚开始搞私域直播的时候,我特别自信,觉得产品也好、主播也专业,开播肯定有人看。结果呢?第一场播下来,场观不到两百,卖了不到一千块。我当时完全懵了,不知道问题出在哪。后来我一个做私域的…...

D3.js:数据可视化的终极利器

什么是 D3.js D3.js(Data-Driven Documents)是一个基于 JavaScript 的数据可视化库,用于创建动态、交互式的数据可视化图表。它通过绑定数据到 DOM(文档对象模型),并利用 HTML、SVG 和 CSS 实现数据驱动的…...

从零搭建一个拼多多CPS返利小程序:我的踩坑记录与避坑指南

从零搭建一个拼多多CPS返利小程序:我的踩坑记录与避坑指南 去年夏天,我决定尝试开发一个拼多多CPS返利小程序。作为一个独立开发者,我本以为凭借多年的编程经验,两周就能搞定这个"小项目"。没想到从API对接、用户绑定到…...

从D435i的深度图反推:如何让OpenCV SGBM的输出更接近工业级传感器效果?

从D435i深度图反推:OpenCV SGBM算法优化实战指南 当你在机器人导航或三维重建项目中对比OpenCV SGBM算法生成的深度图与Intel RealSense D435i输出的结果时,是否发现前者总是显得"平面化"且噪声明显?这背后隐藏着工业级深度传感器在…...

RAG进阶:下一代RAG怎么玩?

基础RAG能解决80%的问题,但剩下20%的难题,需要更进阶的技术。一、基础RAG碰到了什么天花板 基础RAG的套路很简单:文档切块 → Embedding → 向量检索 → 拼接Prompt → 大模型生成答案。 简单场景够用,但往深了用,三个…...

用GD32F470的ADC+DMA实现高精度电流采样,附梁山派开发板实测波形

GD32F470高精度电流采样实战:ADC过采样与DMA传输的工程化实现 在电机控制和电源监测领域,电流采样的精度和实时性直接决定了系统性能的上限。传统12位ADC往往难以兼顾噪声抑制和动态响应,而外置高精度ADC又会增加BOM成本和布线复杂度。本文将…...

【Docker 工程实践】AI 服务容器化部署全流程

文章目录Docker 工程实践:AI 服务容器化部署全流程一、引言二、核心挑战:Mac arm64 → Linux amd64 的跨平台陷阱2.1 为什么会出现 exec format error2.2 一个镜像跑两端:统一构建 amd64三、Dockerfile 工程规范3.1 标准生产模板3.2 多阶段构…...

VMware Workstation 虚拟机创建客户端系统,出现此主机不支持64位客户机操作系统问题解决

安装VMware Workstation 虚拟机(版本15.5),选择windows 11 64位是出现此主机不支持64位客户机操作系统.硬件以及系统支持64位。网上找了几个情况1、hyper-v 功能选项是否开启状态,关闭它2、看CPU技术是否支持虚拟技术,打开任务管…...

如何配置Data Guard环境中的应用连接_客户端TAF与服务漂移Service Trigger

TAF配置不生效主因是TNSNAMES.ORA中未正确定义FAILOVER_MODE参数,需显式设置TYPE(SESSION/SELECT)、METHOD(BASIC)、RETRIES、DELAY及ADDRESS_LIST顺序;srvctl服务需配合DB_ROLE_CHANGE触发器或Broker手动启…...

从Claude Code源码泄露事件看AI CLI工具的五层架构与安全设计

1. 项目概述:一次对Claude Code CLI的深度技术考古最近,AI编程助手领域发生了一件颇有意思的技术事件:Anthropic官方推出的命令行工具Claude Code,其完整的TypeScript源代码意外地在npm包中被公开了。这并非一次主动的开源&#x…...

告别Hackbar解析错误!用Burp Suite搞定复杂GET/POST请求的保姆级教程

告别Hackbar解析错误!用Burp Suite搞定复杂GET/POST请求的保姆级教程 在Web安全测试和CTF比赛中,处理HTTP请求是基本功。许多初学者习惯使用浏览器插件Hackbar快速构造请求,但当遇到复杂参数时,Hackbar的解析能力就显得力不从心。…...

Scratch编程实战:手把手教你实现坦克大战的“穿墙”与“子弹反弹”效果(附完整源码)

Scratch编程实战:从零构建坦克大战的穿墙与子弹反弹机制 引言:为什么选择坦克大战作为Scratch进阶项目? 坦克大战作为经典游戏,其核心机制对编程初学者极具教学价值。不同于简单动画项目,它需要处理角色移动边界检测、…...

不止于Hello World:在IDEA里用Lua写一个自动化运维小工具(环境搭建+实战)

不止于Hello World:在IDEA里用Lua写一个自动化运维小工具(环境搭建实战) 当开发者第一次接触Lua时,往往止步于打印"Hello World"的成就感。但Lua真正的魅力在于其轻量级特性与嵌入式优势,特别适合作为自动化…...