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