retry_mixin.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. from tenacity import (
  2. retry,
  3. retry_if_exception_type,
  4. stop_after_attempt,
  5. wait_exponential,
  6. )
  7. from openhands.core.logger import openhands_logger as logger
  8. from openhands.utils.tenacity_stop import stop_if_should_exit
  9. class RetryMixin:
  10. """Mixin class for retry logic."""
  11. def retry_decorator(self, **kwargs):
  12. """
  13. Create a LLM retry decorator with customizable parameters. This is used for 429 errors, and a few other exceptions in LLM classes.
  14. Args:
  15. **kwargs: Keyword arguments to override default retry behavior.
  16. Keys: num_retries, retry_exceptions, retry_min_wait, retry_max_wait, retry_multiplier
  17. Returns:
  18. A retry decorator with the parameters customizable in configuration.
  19. """
  20. num_retries = kwargs.get('num_retries')
  21. retry_exceptions = kwargs.get('retry_exceptions')
  22. retry_min_wait = kwargs.get('retry_min_wait')
  23. retry_max_wait = kwargs.get('retry_max_wait')
  24. retry_multiplier = kwargs.get('retry_multiplier')
  25. return retry(
  26. before_sleep=self.log_retry_attempt,
  27. stop=stop_after_attempt(num_retries) | stop_if_should_exit(),
  28. reraise=True,
  29. retry=(retry_if_exception_type(retry_exceptions)),
  30. wait=wait_exponential(
  31. multiplier=retry_multiplier,
  32. min=retry_min_wait,
  33. max=retry_max_wait,
  34. ),
  35. )
  36. def log_retry_attempt(self, retry_state):
  37. """Log retry attempts."""
  38. exception = retry_state.outcome.exception()
  39. logger.error(
  40. f'{exception}. Attempt #{retry_state.attempt_number} | You can customize retry values in the configuration.',
  41. exc_info=False,
  42. )