runnable = RunnableLambda(foo)
            runnable_with_retries = runnable.with_retry(
                retry_exception_types=(ValueError,), # Retry only on ValueError
                wait_exponential_jitter=True, # Add jitter to the exponential backoff
                max_attempt_number=2, # Try twice
            )
            # The method invocation above is equivalent to the longer form below:
            runnable_with_retries = RunnableRetry(
                bound=runnable,
                retry_exception_types=(ValueError,),
                max_attempt_number=2,
                wait_exponential_jitter=True
            )
    This logic can be used to retry any Runnable, including a chain of Runnables,
    but in general it's best practice to keep the scope of the retry as small as
    possible. For example, if you have a chain of Runnables, you should only retry
    the Runnable that is likely to fail, not the entire chain.
    Example:
        .. code-block:: python
            from langchain_core.chat_models import ChatOpenAI
            from langchain_core.prompts import PromptTemplate
            template = PromptTemplate.from_template("tell me a joke about {topic}.")
            model = ChatOpenAI(temperature=0.5)
            # Good
            chain = template | model.with_retry()
            # Bad
            chain = template | model
            retryable_chain = chain.with_retry()
    """
    retry_exception_types: Tuple[Type[BaseException], ...] = (Exception,)
    """The exception types to retry on. By default all exceptions are retried.
    
    In general you should only retry on exceptions that are likely to be
    transient, such as network errors.
    
    Good exceptions to retry are all server errors (5xx) and selected client
    errors (4xx) such as 429 Too Many Requests.