第一章:为什么需要"重试"?
1.1 用生活比喻理解
想象你在打电话给客服。有时候线路忙,打不通;有时候对方正在通话中;有时候你拨错号码了。
-
线路忙 :等一会儿再打,可能就通了 → 值得重试
-
拨错号码 :再打一百次也没用,号码本身就是错的 → 不值得重试
程序里的"节点"也一样。节点执行时可能遇到各种错误:
-
临时性错误:网络抖动、API 限流、数据库连接超时 → 重试几次可能就好了
-
永久性错误:参数类型传错了、代码逻辑写错了 → 重试一万次也是错
重试机制就是帮你自动判断:"这个错值不值得再试一次?"
1.2 没有重试会怎样?
假设你写了一个节点调用外部 API:
python
python
def call_api(state):
response = requests.get("https://api.example.com/data")
return {"result": response.text}
如果这次网络刚好抖动了一下,请求失败,整个图就直接崩溃,用户看到报错。但实际上,等 1 秒再试一次,可能就成功了。
加上重试机制 ,LangGraph 会自动帮你再试,你不需要写 while 循环、try...except 嵌套,只需要在 add_node 时加一个参数。
第二章:RetryPolicy 是什么
2.1 一句话定义
RetryPolicy是一个"重试规则说明书"。你把它交给某个节点,节点执行失败时,LangGraph 就按这本说明书决定"要不要重试、重试几次、哪些错误值得重试"。
2.2 它长什么样
python
python
from langgraph.types import RetryPolicy
RetryPolicy(
max_attempts=5, # 最多尝试几次
retry_on=custom_retry_on, # 遇到什么异常才重试(可选)
)
它有两个主要参数:
| 参数 | 含义 | 默认值 |
|---|---|---|
max_attempts |
最多尝试几次(包含第一次) | 5 |
retry_on |
一个函数,接收异常,返回 True 表示重试,False 表示不重试 | 内置默认函数 |
2.3 怎么用
python
在 add_node 的时候传进去:
python
builder.add_node(
"my_node", # 节点名字
my_node_function, # 节点函数
retry_policy=RetryPolicy(max_attempts=5) # 重试策略
)
就这么简单。节点执行失败时,LangGraph 自动接管重试逻辑。
第三章:默认重试策略(不用自己写,但必须懂)
3.1 默认行为是什么
python
如果你只写:
python
RetryPolicy(max_attempts=5)
没有指定 retry_on,LangGraph 会用内置的默认重试函数。这个默认函数的行为是:
遇到大多数异常都重试,但有一批"明确不该重试"的异常会直接跳过。
3.2 哪些异常默认不重试
这批"不该重试"的异常是:
text
python
ValueError 值错误(比如参数类型不对)
TypeError 类型错误
ArithmeticError 算术错误(比如除以零)
ImportError 导入错误
LookupError 查找错误(比如字典键不存在)
NameError 变量名错误
SyntaxError 语法错误
RuntimeError 运行时错误
ReferenceError 引用错误
StopIteration 迭代停止
StopAsyncIteration 异步迭代停止
OSError 操作系统错误(比如文件不存在)
为什么这些不重试?
因为它们是代码写错了导致的,不是"运气不好"。重试一百次,代码还是错的,结果还是错。所以直接放弃,把错误抛给你看。
3.3 哪些异常会重试
除了上面列出的那批,其他所有异常默认都会重试,比如:
python
Exception(通用异常)
ConnectionError(网络连接错误)
TimeoutError(超时)
你自己定义的异常类(只要不是上面那批的子类)
为什么这些要重试?
因为它们通常是临时性问题。等一会儿再试,可能就好了。
3.4 用生活比喻
默认策略就像一个"有经验的客服主管":
-
客户说"网络卡了" → 再试一次
-
客户说"我密码忘了" → 再试一次
-
客户说"你们代码有 bug" → 这个重试也没用,直接升级给技术部门(抛错)
3.5 代码里怎么体现的
python
python
def test_default_retry():
default_graph = build_retry_graph(
node_name="unstable_api",
node_func=unstable_api_call,
retry_policy=RetryPolicy(max_attempts=5) # 只设了次数,没设 retry_on
)
这里 unstable_api_call 前两次抛的是普通 Exception,所以默认策略会重试。第 3 次成功,最终返回结果。
如果这里抛的是 ValueError,默认策略不会重试,直接失败。
第四章:自定义重试策略(精细控制)
4.1 什么时候需要自定义
默认策略是"大多数异常都重试,少数不重试"。但有时候你想更精确:
-
只对特定错误信息重试
-
只对特定异常类型重试
-
根据错误码决定是否重试
这时候就要自己写一个 retry_on 函数。
4.2 retry_on 函数长什么样
python
python
def custom_retry_on(exception: Exception) -> bool:
"""接收一个异常,返回 True 表示重试,False 表示不重试"""
err_msg = str(exception)
if "模拟API调用失败" in err_msg:
return True
return False
规则很简单:
-
参数:一个异常对象
-
返回值 :
True或False -
True→ 重试 -
False→ 不重试,直接抛错
4.3 代码里的自定义函数
python
python
def custom_retry_on(exception: Exception) -> bool:
"""自定义重试规则:只对包含「模拟API调用失败」的异常重试"""
print("########################: "+str(exception))
err_msg = str(exception)
if "模拟API调用失败" in err_msg:
print(f"捕获到可重试异常: {err_msg}")
return True
print(f"捕获到不可重试异常: {err_msg}")
return False
逐行解释:
第 1 行:定义函数,接收 exception,返回布尔值。
第 3 行:把异常转成字符串,打印出来(方便调试)。
第 4 行:把异常信息存到 err_msg 变量里。
第 5-7 行:如果异常信息里包含"模拟API调用失败",返回 True(表示重试)。
第 8-9 行:否则打印"不可重试异常",返回 False。
4.4 怎么用
python
python
custom_graph = build_retry_graph(
node_name="custom_retry_api",
node_func=unstable_api_call,
retry_policy=RetryPolicy(
max_attempts=5, # 最多试 5 次
retry_on=custom_retry_on # 用你自己的判断函数
)
)
这样,节点抛出的异常会被 custom_retry_on 检查:
包含"模拟API调用失败" → 重试
其他任何异常 → 不重试,直接抛错
4.5 自定义策略的威力
你甚至可以写更复杂的规则:
python
python
def smart_retry(exception: Exception) -> bool:
# 网络错误 → 重试
if isinstance(exception, ConnectionError):
return True
# 超时错误 → 重试
if isinstance(exception, TimeoutError):
return True
# 错误信息里有 "rate limit"(限流)→ 重试
if "rate limit" in str(exception).lower():
return True
# 其他都不重试
return False
这样,你的 Agent 就能"聪明地"判断哪些错误值得再试。