Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process_schema() fails for recursive schemas #319

Open
azaroth42 opened this issue Feb 12, 2025 · 0 comments
Open

process_schema() fails for recursive schemas #319

azaroth42 opened this issue Feb 12, 2025 · 0 comments
Assignees
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@azaroth42
Copy link

azaroth42 commented Feb 12, 2025

Per https://github.com/googleapis/python-genai/blob/main/google/genai/_transformers.py#L397 the process_schema() function tries to inline all of the $defs in the schema. This generates an infinite recursion for recursive schemas.

Proposal: Provide a maximum_depth configurable parameter that will break out of any infinite loops like this at a certain point.

Environment details

  • Programming language: Python
  • OS: MacOS
  • Language runtime version: 3.12.7
  • Package version: github master at 2025-02-27

Steps to reproduce

  1. Create a recursive schema in pydantic or json schema, as below
  2. Set it as the response_schema in the config
  3. Attempt to generate content and observe the infinite recursion error

Observed Behavior:

File "/Users/rs2668/Development/llm/python-genai/./test.py", line 58, in generate
    for chunk in client.models.generate_content_stream(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/rs2668/Development/llm/python-genai/google/genai/models.py", line 4808, in generate_content_stream
    for chunk in response:
                 ^^^^^^^^
  File "/Users/rs2668/Development/llm/python-genai/google/genai/models.py", line 3864, in _generate_content_stream
    request_dict = _GenerateContentParameters_to_vertex(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/rs2668/Development/llm/python-genai/google/genai/models.py", line 1190, in _GenerateContentParameters_to_vertex
    _GenerateContentConfig_to_vertex(
  File "/Users/rs2668/Development/llm/python-genai/google/genai/models.py", line 1037, in _GenerateContentConfig_to_vertex
    t.t_schema(api_client, getv(from_object, ['response_schema'])),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 596, in t_schema
    process_schema(schema, client)
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 471, in process_schema
    process_schema(sub_schema, client, defs)
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 523, in process_schema
    process_schema(sub_schema, client, defs)
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 547, in process_schema
    process_schema(ref, client, defs)
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 523, in process_schema
    process_schema(sub_schema, client, defs)
  File "/Users/rs2668/Development/llm/python-genai/google/genai/_transformers.py", line 547, in process_schema
    process_schema(ref, client, defs)
...
RecursionError: maximum recursion depth exceeded

Expected Behavior:

That the schema would be processed

Test Case

Here is a minimal test case that produces the recursion error. I hope that it's clear.

from typing import List
from pydantic import BaseModel
from google import genai
from google.genai import types

class Node(BaseModel):
    name: str
    kids: List['Node']
Node.model_rebuild()

client = genai.Client(
      vertexai=True,
      project=" project name here ",
      location="us-central1",
)

textsi = """
You will be given a hierarchy in text. Please construct a tree of JSON objects.
Each JSON object has a "name" property for the name of the node in the hierarchy, and a "kids" property which is an array of JSON objects.
"""

generated_config = types.GenerateContentConfig(
    response_mime_type = "application/json",
    response_schema = Node,
    system_instruction=[types.Part.from_text(text=textsi)],
)

def generate(prompt):
  contents = [
    types.Content(
      role="user",
      parts=[types.Part.from_text(text=prompt)]
    )
  ]
  output = []
  for chunk in client.models.generate_content_stream(
    model = "gemini-2.0-flash-001",
    contents = contents,
    config = generated_config,
    ):
    output.append(chunk.text)
  return ''.join(output)


prompt = """
* Top
  * Materials
    * Metals
      * Gold
      * Silver
      * Bronze
    * Stone
      * Flint
      * Granite
      * Marble
"""

res = generate(prompt)

Thank you!

@azaroth42 azaroth42 added priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Feb 12, 2025
@sararob sararob self-assigned this Feb 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests

2 participants