instructor icon indicating copy to clipboard operation
instructor copied to clipboard

Gemini cannot deal with Enums in the JSON schema

Open DavidNemeskey opened this issue 5 months ago • 3 comments

I am trying to use Gemini with a schema that includes an Enum and it raises a validation error. The same code works perfectly fine with OpenAI or Together AI models. The MWE below is a combination of the Gemini primer into structured outputs and your own code example for Gemini:

import instructor
from google import genai
from pydantic import BaseModel, ConfigDict

from enum import Enum

class RecipeType(Enum):
    DESSERT = 'dessert'
    MAIN = 'main'

class Recipe(BaseModel):
    recipe_type: RecipeType
    ingredients: list[str]

cli = instructor.from_provider(
    "google/gemini-2.5-flash", mode=instructor.Mode.GENAI_STRUCTURED_OUTPUTS
    # "openai/gpt-4.1-mini"
)

user = cli.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "Write a recipe.",
        },
    ],
    response_model=Recipe,
)

It doesn't matter which mode I choose. Also, the commented out GPT model works perfectly. What also works perfectly is running the same through genai:

from enum import Enum

from google import genai
from pydantic import BaseModel


class RecipeType(Enum):
    DESSERT = 'dessert'
    MAIN = 'main'

class Recipe(BaseModel):
    recipe_type: RecipeType
    ingredients: list[str]

client = genai.Client()
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="List a few popular cookie recipes, and include the amounts of ingredients.",
    config={
        "response_mime_type": "application/json",
        "response_schema": list[Recipe],
    },
)
# Use the response as a JSON string.
print(response.text)

# Use instantiated objects.
my_recipes: list[Recipe] = response.parsed

So the error is definitely how instructor interfaces with genai. Please look into this, it kind of defeats the purpose of having a unified API if it fails for some providers.

DavidNemeskey avatar Jul 31 '25 14:07 DavidNemeskey

@DavidNemeskey Had this problem as well. I reported it but it was closed. https://github.com/567-labs/instructor/issues/1469

Was told to use strict=False but was worried about side effects. My work-around is I set those enums to str and in the field description I give it the allowed values directly from the enum class. I then have a "public" model that is a copy-paste of the one fed into LLM, but with enum as the types. I have a validator on the internal model that ensures it's a valid value, otherwise instructor will retry. It's annoying boilerplate but preserves the enum-ability for outside callers and preserves the restriction of values to be selected.

dmastylo avatar Aug 04 '25 20:08 dmastylo

@dmastylo but doesn't that completely defeat the purpose of the library, i.e. to be able to access all major LLMs with (almost) the same code?

DavidNemeskey avatar Aug 04 '25 20:08 DavidNemeskey

@DavidNemeskey for most usecases you can use Literals instead of Enums. (also enums get defined at a different place in the json schema, so literals probably result in more reliable outputs as well).

(but agreed that it should "just work" :)

oegedijk avatar Aug 12 '25 12:08 oegedijk