feat: improve retry mechanism with jitter and longer delays

- Increase max retry attempts from 3 to 5
- Extend max delay from 10s to 60s for better handling of persistent 529 errors
- Add jitter (random 0-0.5s delay) to avoid synchronized retries
- Based on Cursor IDE blog best practices for handling Claude API 529 errors
This commit is contained in:
MarkLo 2025-12-01 04:16:55 +08:00
parent 42ef175ddb
commit edced35f70
1 changed files with 22 additions and 5 deletions

View File

@ -2,6 +2,7 @@
import time
import json
import logging
import random
from tenacity import (
retry,
stop_after_attempt,
@ -112,18 +113,29 @@ def create_research_manager(llm, memory):
請提供專業且可執行的投資決策報告"""
# 定義帶重試機制的 LLM 調用函數
# 只針對 Anthropic OverloadedError (529) 進行重試
# 配置:最多 3 次重試指數退避2、4、8 秒)
# 基於 Cursor IDE 博客建議的最佳實踐:
# 1. 使用指數退避策略exponential backoff
# 2. 添加隨機因子jitter避免多個客戶端同步重試
# 3. 增加重試次數和最大延遲時間
import random
@retry(
retry=retry_if_exception_type(OverloadedError),
wait=wait_exponential(multiplier=1, min=2, max=10),
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=60), # 增加最大延遲到 60 秒
stop=stop_after_attempt(5), # 增加重試次數到 5 次
before_sleep=before_sleep_log(logger, logging.WARNING)
)
def invoke_llm_with_retry(llm_instance, prompt_text):
"""
調用 LLM 並在遇到 529 錯誤時自動重試
使用指數退避策略加隨機因子jitter
- 1 次重試等待 2-4 2 * 2^0 + jitter
- 2 次重試等待 4-8 2 * 2^1 + jitter
- 3 次重試等待 8-16 2 * 2^2 + jitter
- 4 次重試等待 16-32 2 * 2^3 + jitter
- 5 次重試等待 32-60 2 * 2^4 + jitter最大 60
Args:
llm_instance: LLM 實例
prompt_text: 提示文本
@ -132,8 +144,13 @@ def create_research_manager(llm, memory):
LLM 的回應
Raises:
OverloadedError: 如果 3 次重試後仍然失敗
OverloadedError: 如果 5 次重試後仍然失敗
"""
# 添加小量隨機延遲jitter避免同步重試
jitter = random.uniform(0, 0.5)
if jitter > 0:
time.sleep(jitter)
logger.info("正在調用 Research Manager LLM...")
return llm_instance.invoke(prompt_text)