PrefectHQ / marvin

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

`from __future__ import annotations` causes ai functions to return strings #950

Open jimkring opened 3 months ago

jimkring commented 3 months ago

First check

Bug summary

I was having a strange issue where ai functions were returning string data instead of the type specified in my function signature. It turns out that having from __future__ import annotations was causing the issue.

Reproduction

from __future__ import annotations  # this causes the problem to appear
import inspect  # we'll use this to look at why it's happening 

import marvin
from pydantic import BaseModel

@marvin.fn
def recipe(
        ingredients: list[str],
        max_cook_time: int = 15,
        cuisine: str = "North Italy",
        experience_level: str = "beginner",
) -> Recipe:
    """
    Returns a complete recipe that uses all the `ingredients` and
    takes less than `max_cook_time`  minutes to prepare. Takes 
    `cuisine` style and the chef's `experience_level` into account 
    as well.
    """

# get a recipe
my_recipe = recipe(["milk", "sugar", "flour"])

# verify the output is a Recipe
assert isinstance(my_recipe, Recipe)

# let's check the function signature
sig = inspect.signature(recipe)

# make sure it's output is a Recipe
assert type(sig.return_annotation) is Recipe

Error

No response

Versions

> marvin version
Version:                2.3.6
Python version:         3.11.4
OS/Arch:                windows/amd64

Additional context

No response

zzstoatzz commented 3 months ago

hi @jimkring - thanks for the issue!

can you show the definition of the Recipe type?

jimkring commented 3 months ago

This is from the Marvin examples. https://www.askmarvin.ai/docs/text/functions/#parameters


class Recipe(BaseModel):
    name: str
    cook_time_minutes: int
    ingredients: list[str]
    steps: list[str]
jimkring commented 3 months ago

@zzstoatzz lmk if this is enough info for you to reproduce. Thx.

zzstoatzz commented 3 months ago

hi @jimkring

thanks for the issue! i have reproduced, it looks like the import itself indeed causes this, which is interesting. will take a look as soon as I can

jimkring commented 3 months ago

@zzstoatzz Thank you. I was able to work around this issue by keeping my model definitions separate (in a different module) from where I call marvin. So, if a fix is not easy, a suitable workaround might be to just generate an error if this condition is detected along with a message that helps point to a solution.