in lm_human_preferences/utils/gcs.py [0:0]
def exponential_backoff(
retry_on=lambda e: True, *, init_delay_s=1, max_delay_s=600, max_tries=30, factor=2.0,
jitter=0.2, log_errors=True):
"""
Returns a decorator which retries the wrapped function as long as retry_on returns True for the exception.
:param init_delay_s: How long to wait to do the first retry (in seconds).
:param max_delay_s: At what duration to cap the retry interval at (in seconds).
:param max_tries: How many total attempts to perform.
:param factor: How much to multiply the delay interval by after each attempt (until it reaches max_delay_s).
:param jitter: How much to jitter by (between 0 and 1) -- each delay will be multiplied by a random value between (1-jitter) and (1+jitter).
:param log_errors: Whether to print tracebacks on every retry.
:param retry_on: A predicate which takes an exception and indicates whether to retry after that exception.
"""
def decorate(f):
@wraps(f)
def f_retry(*args, **kwargs):
delay_s = float(init_delay_s)
for i in range(max_tries):
try:
return f(*args, **kwargs)
except Exception as e:
if not retry_on(e) or i == max_tries-1:
raise
if log_errors:
print(f"Retrying after try {i+1}/{max_tries} failed:")
traceback.print_exc()
jittered_delay = random.uniform(delay_s*(1-jitter), delay_s*(1+jitter))
time.sleep(jittered_delay)
delay_s = min(delay_s * factor, max_delay_s)
return f_retry
return decorate