Skip to content

test(gemini): add parity test between native and chat schema normalization - #27814

Closed
mateo-berri wants to merge 7 commits into
litellm_internal_stagingfrom
claude/review-sameer-feedback-kpzld
Closed

test(gemini): add parity test between native and chat schema normalization#27814
mateo-berri wants to merge 7 commits into
litellm_internal_stagingfrom
claude/review-sameer-feedback-kpzld

Conversation

@mateo-berri

@mateo-berri mateo-berri commented May 13, 2026

Copy link
Copy Markdown
Contributor

Addresses @Sameerlite review on #27775:

So if we have a method there as well, can we have a test which makes sure that if any one of the 2 paths method changes, this test fails, so that we make sure that both paths are always updated with the schema changes.

Adds test_response_schema_normalization_parity_across_chat_and_native_paths which feeds the same schema through both GoogleGenAIConfig._normalize_response_schema (native generateContent) and VertexGeminiConfig.apply_response_schema_transformation (/chat/completions) and asserts equality on Gemini 2.0+ and Gemini 1.5. If either path drifts, the test fails — forcing both to be updated together.

This branch builds on the tip of #27775; the parity test is the only delta.


Note

Medium Risk
Changes how responseSchema/responseJsonSchema are emitted for Gemini native/Vertex GenAI requests, which can alter structured-output behavior across model versions. Risk is mitigated by extensive new tests, but schema edge cases could still regress.

Overview
Adds native generateContent response-schema normalization so Gemini 2.0+ promotes responseSchema to responseJsonSchema (preserving $defs/$ref), while Gemini 1.5 keeps responseSchema but flattens it via _build_vertex_schema.

Applies the same normalization in the Vertex GenAI transformation path and adds a broad test suite, including a parity test ensuring native (GoogleGenAIConfig._normalize_response_schema) and chat (VertexGeminiConfig.apply_response_schema_transformation) schema normalization stay in sync.

Reviewed by Cursor Bugbot for commit bf20bd8. Bugbot is set up for automated code reviews on this repo. Configure here.

mateo-berri and others added 7 commits May 12, 2026 16:59
The /v1beta/models/{model}:generateContent passthrough forwarded
generationConfig.response_schema verbatim, so schemas containing $defs,
$ref, anyOf-with-null, default, or title were rejected by Gemini even
though /chat/completions already handles them.

GoogleGenAIConfig.transform_generate_content_request now calls a new
_normalize_response_schema helper that mirrors the chat/completions
path: Gemini 2.0+ models get the schema promoted to responseJsonSchema
via _build_json_schema (preserving $defs/$ref natively), older models
keep responseSchema but the schema is flattened with
_build_vertex_schema. VertexAIGoogleGenAIConfig (which overrides the
transform entirely) calls the same helper before building the request.
…eSchema co-present

Previously, when both responseJsonSchema and responseSchema were present
on Gemini 2.0+, _normalize_response_schema processed responseJsonSchema
first (no-op normalization) then unconditionally promoted responseSchema
to responseJsonSchema, clobbering the caller-supplied value.

Now skip the promotion (and drop the redundant responseSchema) when the
caller already supplied responseJsonSchema.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
Drop the docstring on _normalize_response_schema and the two inline
comments that just restated what the surrounding code/asserts already
say. Function name + variable names carry the intent; PR description
covers the why-it-exists context.
_build_json_schema is a no-op (returns its argument unchanged), so the
deepcopy + round-trip on the responseJsonSchema branch allocated a full
schema copy on every request with no observable effect. Forward the
caller's value as-is, and just move the popped responseSchema value when
promoting on Gemini 2.0+.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
…ation

Per @Sameerlite review: lock the two Gemini schema-normalization paths
together. If either GoogleGenAIConfig._normalize_response_schema (native
generateContent) or VertexGeminiConfig.apply_response_schema_transformation
(/chat/completions) drifts, the parity test fails — forcing both to be
updated together.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 3 committers have signed the CLA.

✅ mateo-berri
❌ cursoragent
❌ claude
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.47619% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/llms/gemini/google_genai/transformation.py 90.47% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@mateo-berri
mateo-berri deleted the claude/review-sameer-feedback-kpzld branch May 13, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants