8000 OpenRouter using Gemini Flash model results in Pydantic Validation Error on Nested Object Models · Issue #1616 · 567-labs/instructor · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
OpenRouter using Gemini Flash model results in Pydantic Validation Error on Nested Object Models #1616
Open
@dmastylo

Description

@dmastylo
  • This is actually a bug report.
  • I have tried asking for help in the community on discord or discussions and have not received a response.

What Model are you using?

  • Other (please specify)
    google/gemini-2.0-flash-001 through OpenRouter

Describe the bug
Instructor with OpenRouter using Gemini model fails to validate response models with nested objects

Traceback (most recent call last):
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/instructor/retry.py", line 191, in retry_sync
    raise e
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/instructor/retry.py", line 174, in retry_sync
    return process_response(  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/instructor/process_response.py", line 170, in process_response
    model = response_model.from_response(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/instructor/function_calls.py", line 266, in from_response
    return cls.parse_tools(completion, validation_context, strict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/instructor/function_calls.py", line 580, in parse_tools
    return cls.model_validate_json(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dmastylo/.pyenv/versions/3.12.1/envs/filing-automation/lib/python3.12/site-packages/pydantic/main.py", line 625, in model_validate_json
    return cls.__pydantic_validator__.validate_json(json_data, strict=strict, context=context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 2 validation errors for DateContextData
relevant_dates.0
  Input should be an object [type=model_type, input_value='{"start_date": "2024-07-...ncomplete_date": false}', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/model_type
relevant_dates.1
  Input should be an object [type=model_type, input_value='{"start_date": "2023-07-...ncomplete_date": false}', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/model_type

To Reproduce

import os

import httpx
import instructor
import instructor.exceptions
from openai import OpenAI
from pydantic import BaseModel, Field


OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY")
OPENROUTER_CLIENT = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=OPENROUTER_API_KEY,
    timeout=httpx.Timeout(90),
)

client = instructor.from_openai(OPENROUTER_CLIENT, mode=instructor.Mode.TOOLS)


class DateContext(BaseModel):
    end_date: str
    start_date: str
    incomplete_date: bool


class DateContextData(BaseModel):
    chain_of_thought: str = Field(description="Let's think step by step")
    relevant_dates: list[DateContext]


# response = client.chat.completions.create(
#     model="google/gemini-2.0-flash-001",
#     response_model=DateContextData,
#     messages=[
#         {
#             "role": "system",
#             "content": f"Extract dates from the given text.",
#         },
#         {"role": "user", "content": "I had the car from Jan 1 2024 to Jan 12 2025"},
#     ],
#     extra_body={"provider": {"require_parameters": True}},
#     strict=False,
#     # retry_if_exception_type=instructor.exceptions.InstructorRetryException,
#     max_retries=3,
# )

# print(response)

from google import genai

GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
GOOGLE_TIMEOUT = 1 * 90 * 1000  # 1.5 minutes
GOOGLE_CLIENT = (
    genai.Client(api_key=GOOGLE_API_KEY, http_options={"timeout": GOOGLE_TIMEOUT})
    if GOOGLE_API_KEY
    else None
)
client = instructor.from_genai(
    GOOGLE_CLIENT,
    mode=instructor.Mode.GENAI_TOOLS,
    use_async=False,
)

response = client.chat.completions.create(
    model="gemini-2.0-flash",
    response_model=DateContextData,
    messages=[
        {
            "role": "system",
            "content": f"Extract dates from the given text.",
        },
        {"role": "user", "content": "I had the car from Jan 1 2024 to Jan 12 2025"},
    ],
    # retry_if_exception_type=instructor.exceptions.InstructorRetryException,
    max_retries=3,
)
print(response)

Note the genai way works, the OpenRouter way does not.

Using JSON mode with OpenRouter works, but would prefer TOOLS.

Expected behavior
This model works normally with the genai provider

Screenshots
N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0