Improve rate limit message to indicate automatic retry (#9281)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Graham Neubig 2025-07-02 12:27:35 -04:00 committed by GitHub
parent 7bfa05d38a
commit d2fc5679ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 15 deletions

View File

@ -262,6 +262,7 @@ export enum I18nKey {
CHAT_INTERFACE$AGENT_RUNNING_MESSAGE = "CHAT_INTERFACE$AGENT_RUNNING_MESSAGE",
CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE = "CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE",
CHAT_INTERFACE$AGENT_RATE_LIMITED_MESSAGE = "CHAT_INTERFACE$AGENT_RATE_LIMITED_MESSAGE",
CHAT_INTERFACE$AGENT_RATE_LIMITED_STOPPED_MESSAGE = "CHAT_INTERFACE$AGENT_RATE_LIMITED_STOPPED_MESSAGE",
CHAT_INTERFACE$AGENT_PAUSED_MESSAGE = "CHAT_INTERFACE$AGENT_PAUSED_MESSAGE",
LANDING$TITLE = "LANDING$TITLE",
LANDING$SUBTITLE = "LANDING$SUBTITLE",

View File

@ -4176,20 +4176,36 @@
"uk": "Агент очікує на введення даних від користувача..."
},
"CHAT_INTERFACE$AGENT_RATE_LIMITED_MESSAGE": {
"en": "Agent is Rate Limited",
"zh-CN": "智能体已达到速率限制",
"zh-TW": "智慧代理已達到速率限制",
"de": "Agent ist ratenbegrenzt",
"ko-KR": "에이전트가 속도 제한되었습니다",
"no": "Agenten er hastighetsbegrenset",
"it": "L'agente è limitato dalla frequenza",
"pt": "O agente está com limite de taxa",
"es": "El agente está limitado por tasa",
"ar": "الوكيل مقيد بحد السرعة",
"fr": "L'agent est limité en fréquence",
"tr": "Ajan hız sınırına ulaştı",
"ja": "エージェントがレート制限中",
"uk": "Агента обмежено кількістю запитів"
"en": "Agent is Rate Limited. Retrying...",
"zh-CN": "智能体已达到速率限制。正在重试...",
"zh-TW": "智慧代理已達到速率限制。正在重試...",
"de": "Agent ist ratenbegrenzt. Wiederholungsversuch...",
"ko-KR": "에이전트가 속도 제한되었습니다. 재시도 중...",
"no": "Agenten er hastighetsbegrenset. Prøver på nytt...",
"it": "L'agente è limitato dalla frequenza. Riprovando...",
"pt": "O agente está com limite de taxa. Tentando novamente...",
"es": "El agente está limitado por tasa. Reintentando...",
"ar": "الوكيل مقيد بحد السرعة. إعادة المحاولة...",
"fr": "L'agent est limité en fréquence. Nouvelle tentative...",
"tr": "Ajan hız sınırına ulaştı. Yeniden deniyor...",
"ja": "エージェントがレート制限中。再試行しています...",
"uk": "Агента обмежено кількістю запитів. Повторюємо спробу..."
},
"CHAT_INTERFACE$AGENT_RATE_LIMITED_STOPPED_MESSAGE": {
"en": "Agent is rate-limited. Stopped.",
"zh-CN": "智能体已达到速率限制。已停止。",
"zh-TW": "智慧代理已達到速率限制。已停止。",
"de": "Agent ist ratenbegrenzt. Angehalten.",
"ko-KR": "에이전트가 속도 제한되었습니다. 중지됨.",
"no": "Agenten er hastighetsbegrenset. Stoppet.",
"it": "L'agente è limitato dalla frequenza. Fermato.",
"pt": "O agente está com limite de taxa. Parado.",
"es": "El agente está limitado por tasa. Detenido.",
"ar": "الوكيل مقيد بحد السرعة. توقف.",
"fr": "L'agent est limité en fréquence. Arrêté.",
"tr": "Ajan hız sınırına ulaştı. Durduruldu.",
"ja": "エージェントがレート制限中。停止しました。",
"uk": "Агента обмежено кількістю запитів. Зупинено."
},
"CHAT_INTERFACE$AGENT_PAUSED_MESSAGE": {
"en": "Agent has paused.",

View File

@ -275,7 +275,20 @@ class AgentController:
err_id = 'STATUS$ERROR_LLM_CONTENT_POLICY_VIOLATION'
self.state.last_error = err_id
elif isinstance(e, RateLimitError):
await self.set_agent_state_to(AgentState.RATE_LIMITED)
# Check if this is the final retry attempt
if (
hasattr(e, 'retry_attempt')
and hasattr(e, 'max_retries')
and e.retry_attempt >= e.max_retries
):
# All retries exhausted, set to ERROR state with a special message
self.state.last_error = (
'CHAT_INTERFACE$AGENT_RATE_LIMITED_STOPPED_MESSAGE'
)
await self.set_agent_state_to(AgentState.ERROR)
else:
# Still retrying, set to RATE_LIMITED state
await self.set_agent_state_to(AgentState.RATE_LIMITED)
return
self.status_callback('error', err_id, self.state.last_error)

View File

@ -72,6 +72,30 @@ class RetryMixin:
def log_retry_attempt(self, retry_state: Any) -> None:
"""Log retry attempts."""
exception = retry_state.outcome.exception()
# Add retry attempt and max retries to the exception for later use
if hasattr(retry_state, 'retry_object') and hasattr(
retry_state.retry_object, 'stop'
):
# Get the max retries from the stop_after_attempt
stop_condition = retry_state.retry_object.stop
# Handle both single stop conditions and stop_any (combined conditions)
stop_funcs = []
if hasattr(stop_condition, 'stops'):
# This is a stop_any object with multiple stop conditions
stop_funcs = stop_condition.stops
else:
# This is a single stop condition
stop_funcs = [stop_condition]
for stop_func in stop_funcs:
if hasattr(stop_func, 'max_attempts'):
# Add retry information to the exception
exception.retry_attempt = retry_state.attempt_number
exception.max_retries = stop_func.max_attempts
break
logger.error(
f'{exception}. Attempt #{retry_state.attempt_number} | You can customize retry values in the configuration.',
)