-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Add Property Ordering Support for Gemini #8642
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
Conversation
commit b79b3e56351537215b6e2a7d1ed895bb3d93d549 Author: Nikita Herndlhofer <[email protected]> Date: Sun Sep 14 18:47:56 2025 +0100 Added support to provide just an array for simple root-level ordering commit 391159394a6f4aaa67b29e44a1234773dc5afa3b Author: Nikita Herndlhofer <[email protected]> Date: Sun Sep 14 18:40:03 2025 +0100 Added patch changeset commit 5fc0a50964868ee73c835561e3263f2aa2dfb53b Author: Nikita Herndlhofer <[email protected]> Date: Sun Sep 14 17:33:52 2025 +0100 Add property ordering support
can you share why this is needed? I looked through https://ai.google.dev/gemini-api/docs/structured-output, and I understand what it does, but what is the use case for it? |
Because LLMs generate things token-by-token the generation of every token is affected by every previous token. That means that in structured outputs it is important to specify the order of the properties. For example: You are creating a CoT pipeline and have defined the following structure:
Then you always want the llm to generate the 'reasoning' property first, and the 'result' property last. This is a really important feature for many use cases in more or less complex AI pipelines used in production. |
@NikitaHerndlhofer I have a few more questions here. When you defined the schema, like in your example const result = await generateObject({
model: google('gemini-2.0-flash'),
schema: z.object({
name: z.string(),
age: z.number(),
email: z.string(),
}),
prompt: 'Generate a person profile',
});
console.log(Object.keys(result.object));
|
@gr2m It's easier when you name your properties like
Then the lllm will be more inconsistent in the result. So the best way to test this would be:
|
To answer your specific questions:
I hope this answers your questions |
The raw response body is not relevant if the parsing through zod and your provided schema is what defines the order. And if you don't want to depend on zod, you can use your own custom schema: https://ai-sdk.dev/docs/reference/ai-sdk-core/json-schema#jsonschema Can you provide an end-to-end example using AI SDK where the resulting object keys have a different order than the schema you provide? |
It's relevant, because it directly affects the LLMs response, because LLMs generate responses token by token. And the raw response is how you can have a look at it. |
For now we don't see a need for it. You can do the sorting outside the AI SDK as needed. We will watch out for other users running into an issue with the order of keys. Thanks Nikita |
https://www.dsdev.in/order-of-fields-in-structured-output-can-hurt-llms-output https://discuss.ai.google.dev/t/output-order-in-structured-outputs/53765 @gr2m Please have a look at the example here This will also directly affect streaming the outputs as well. If you have comments to the code or the approach itself - please provide them, there is a need for this feature for production use cases. |
I did. When I run this example const schema = z.object({
tagFirst: z.string(),
tag2: z.object({
childTagFirst: z.string(),
childTag1: z.object({
subChildTagFirst: z.string(),
subchildTagRandomPosition: z.string(),
subChildTag1: z.string(),
}),
childTag2: z.string(),
childTagSecond: z.string(),
}),
tag3: z.string(),
tagLast: z.string(),
tag1: z.string(),
});
const prompt = `
You are a helpful assistant that generates tags for a post.
generate tags!
`;
const result = streamObject({
model: google('gemini-2.0-flash-001'),
temperature: 0,
seed: 42,
schema,
prompt,
});
result.partialObjectStream.pipeTo(
new WritableStream({
write(chunk) {
console.log(chunk);
},
}),
); The logged chunks are exactly as expected, following the order in the schema
|
Summary
This PR adds comprehensive support for
propertyOrdering
in the Google provider, allowing developers to control the order of properties in JSON responses from Gemini models. The implementation supports both a simple array format for basic use cases and a nested object format for complex structures.Usage Examples
Simple Array Format
For basic root-level property ordering, you can use a simple array:
Complex Nested Object Ordering
For nested structures, use the object format with dot notation:
Technical Implementation
Key Changes
Enhanced Type System:
Smart Format Normalization:
Enhanced
convertJSONSchemaToOpenAPISchema
function:Record<string, string[]>
andstring[]
formatsstring[]
for simple root-level property ordering andRecord<string, string[]>
for nested property ordering.'parent.child'
)OpenAPI Schema Generation:
The function converts property ordering definitions into OpenAPI-compliant schemas:
Path-based Property Ordering
The implementation supports:
''
(empty string) or simple array format'parent.child'
dot notationTesting
Test Cases Added:
should add propertyOrdering when provided
- Complex nested object testshould work without propertyOrdering
- Backward compatibility testshould support simple array format for root-level property ordering
- Simple array format testDocumentation Updates
README.md
Type Documentation
API Design
The API provides excellent developer experience with progressive complexity:
Breaking Changes
None. This is a purely additive feature with full backward compatibility.
References
This implementation enables developers to leverage Google's property ordering feature for more consistent, reliable, and high-quality structured outputs from Gemini models, with an API that scales from simple to complex use cases.