PrefectHQ / marvin

✨ Build AI interfaces that spark joy
https://askmarvin.ai
Apache License 2.0
5.34k stars 348 forks source link

add beta retry decorator for `marvin.fn` #909

Closed zzstoatzz closed 7 months ago

zzstoatzz commented 7 months ago

adds a beta retry decorator to be used with marvin.fn that will include validation errors (as is, by default) in subsequent retries

you may also configure max_retries and a handler to parse ValidationErrors to the additional context that is actually passed back to the LLM

from typing import Annotated

import marvin
from marvin.beta.retries import retry_fn_on_validation_error
from pydantic import AfterValidator

def verify_random_number(number: int) -> int:
    if number != 37:
        raise ValueError("Everyone knows the most random number is 37!")
    return number

RandomNumber = Annotated[int, AfterValidator(verify_random_number)]

@retry_fn_on_validation_error  # shows the validation error message in subsequent retries
@marvin.fn
def get_random_number() -> RandomNumber:
    """returns a random number"""

if __name__ == "__main__":
    print(get_random_number())
pietz commented 2 months ago

I love the functionality. I don't love the execution. What do you think of this instead:

@marvin.fn(retries=1, on_errors=[ValidationError])
def get_random_number() -> RandomNumber:
    """returns a random number"""

This would be equivalent to what you did. It could also be extended to this, which is what I'm currently looking for:

@marvin.fn(retries=2, timeout=5.0)
def get_random_number() -> RandomNumber:
    """returns a random number"""

This would try up to three times (2 retries) if any type of error is thrown including a runtime longer than 5 seconds. I think the timeout option is very useful because many requests on the OpenAI API just timeout after a (way too) long time. If I call 100 functions asynchronously, theres usually at least one in there that delays the entire call.