Skip to content

[integrations][openai] Apply OpenAI native structured output#919

Open
weiqingy wants to merge 2 commits into
apache:mainfrom
weiqingy:280-pr2-openai-native
Open

[integrations][openai] Apply OpenAI native structured output#919
weiqingy wants to merge 2 commits into
apache:mainfrom
weiqingy:280-pr2-openai-native

Conversation

@weiqingy

Copy link
Copy Markdown
Collaborator

Linked issue: #280

Stacked on #843 (the structured-output foundation). Until #843 merges, this PR's diff includes the foundation commit; it will rebase to a single commit once #843 lands. Please review #843 first.

Purpose of change

Applies OpenAI's native structured output on top of the foundation in #843.

The OpenAI completions connection overrides the schema-carrying chat and requests response_format json_schema strict when native applies, and declares the capability predicate over the effective model.

Native applies only when the schema is a POJO class (Java) or a BaseModel subclass (Python) and the effective model supports it. Per OpenAI's structured-output guide, json_schema is supported on gpt-4o-mini and the gpt-4o snapshots from 2024-08-06 onward, while gpt-4-turbo and gpt-3.5-turbo have JSON mode only. Because "and later" is a snapshot cutoff rather than a name prefix, the predicate matches gpt-4o-mini by prefix (its whole family post-dates the cutoff) and the capable gpt-4o snapshots exactly, so a pre-cutoff snapshot such as gpt-4o-2024-05-13 falls back to the prompt path instead of failing at the provider. A RowTypeInfo schema stays on the prompt path.

No path passes a schema on the chat call yet, so behavior is unchanged; native output is exercised by direct callers and the unit tests.

Tests

Java: the request carries response_format json_schema strict when a capable model and a POJO schema are supplied; the capability predicate is model-dependent (an incapable and a pre-cutoff same-family snapshot both resolve to not-capable); null schema and non-POJO schema keep the prompt path.

Python: the same coverage over the BaseModel path, including the pre-cutoff snapshot regression test and policy behavior.

Java OpenAI module tests and the Python suite pass; lint and license checks are clean.

API

Touches the OpenAI connection: overrides the schema-carrying chat and declares the capability predicate. No new user-facing surface beyond the foundation in #843.

Documentation

  • doc-needed
  • doc-not-needed
  • doc-included

weiqingy added 2 commits July 18, 2026 22:00
Carry the output schema to chat model connections as an explicit parameter
and split the structured output strategy into a user policy and a per-model
capability, so a later change can apply a provider's native structured output
without threading the schema through the provider-facing model parameters.

Java adds a concrete four argument chat overload whose default body ignores
the schema and delegates to the existing abstract three argument chat, so
connections with no native mechanism need no change. Python adds an explicit
output_schema parameter to every connection, including the Java bridge
connection, so the schema binds to a named parameter and cannot be forwarded
into a provider request through kwargs.

StructuredOutputStrategy expresses user intent (AUTO, NATIVE or PROMPT) on the
setup and defaults to AUTO. Capability is separate: a connection side predicate
over the effective model, since a provider supports its native mechanism only
on some models. The base predicate returns false; a connection that adds a
native translation overrides it.

This is the mechanism only. No connection applies native structured output and
no path passes a schema on the chat call yet, so behavior is unchanged.
Override the schema-carrying chat on the OpenAI completions connection to
request the provider's native structured output when the caller supplies a
schema the provider can honor natively.

Native applies only when the schema is a POJO class (Java) or a BaseModel
subclass (Python) and the effective model supports it. Capability is a
connection-side predicate over the effective model, since the OpenAI json
schema mode is model dependent: per the provider's structured output guide it
is supported on gpt-4o-mini and the gpt-4o snapshots from 2024-08-06 onward,
while gpt-4-turbo and gpt-3.5-turbo have json mode only. The predicate matches
gpt-4o-mini by prefix (the whole family postdates the cutoff) and the capable
gpt-4o snapshots exactly, so a pre-cutoff snapshot such as gpt-4o-2024-05-13
correctly falls back to the prompt path rather than failing at the provider. A
RowTypeInfo schema stays on the prompt path.

No path passes a schema on the chat call yet, so behavior is unchanged; native
output is exercised by direct callers and the unit tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs fixVersion/0.4.0 priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant