Skip to content

Conversation

@paulb777
Copy link
Member

@paulb777 paulb777 commented Dec 30, 2025

This pull request significantly enhances the Firebase AI SDK by introducing structured output streaming. It provides new generateObjectStream methods within the GenerativeModel class, allowing developers to receive AI-generated content as a stream of strongly-typed objects conforming to a specified JSON schema. A key component of this feature is the newly implemented PartialJSONParser, which intelligently handles and parses incomplete JSON fragments as they arrive, ensuring a smooth and resilient streaming experience. This change enables more dynamic and interactive AI applications by providing immediate feedback as the model generates its response.

Highlights

  • Structured Output Streaming: Introduced generateObjectStream methods to allow models to stream structured JSON output, enhancing interaction with AI models by providing strongly-typed objects.
  • Partial JSON Parsing: Added a PartialJSONParser to robustly handle and parse incomplete JSON responses received during streaming, enabling real-time processing of partial data.
  • Enhanced generateContentStream: An overload for generateContentStream was added to support passing an optional GenerationConfig, providing more flexibility in content generation.
  • Comprehensive Testing: New integration and unit tests were added to validate the generateObjectStream functionality and the PartialJSONParser's robustness across various scenarios, including partial and malformed JSON.

@gemini-code-assist
Copy link
Contributor

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

@paulb777
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces streaming support for structured outputs, which is a great feature. The implementation includes a new PartialJSONParser to handle incomplete JSON data from the stream, along with new generateObjectStream methods on GenerativeModel.

My review has identified a critical bug in the PartialJSONParser related to handling escaped characters in strings. I've also found a high-severity issue in GenerativeModel that can cause the final streamed object to be yielded twice. Additionally, I've suggested improvements to the unit tests for the new parser to increase its robustness.

Overall, the changes are well-structured, but addressing these issues is important for the feature to work correctly and reliably.

@paulb777
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces streaming support for structured outputs (generateObjectStream). The core logic is implemented in a new private _generateObjectStream function in GenerativeModel.swift, which relies on a new PartialJSONParser to handle incomplete JSON chunks from the stream. New integration and unit tests are added to cover this functionality. My review focuses on the correctness and robustness of the new streaming and parsing logic. I've identified a potential issue in _generateObjectStream regarding redundant processing and the possibility of not yielding the final object in certain edge cases. I've also suggested expanding the unit tests for the new PartialJSONParser to cover more scenarios.

@paulb777
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces streaming support for structured object generation, which is a great feature. The implementation includes a new PartialJSONParser to handle incomplete JSON streams and new generateObjectStream methods on GenerativeModel. The accompanying integration and unit tests are thorough.

My review includes a few points:

  • A high-severity bug in the PartialJSONParser that can lead to incorrect parsing of numbers.
  • A medium-severity suggestion to consider performance for very large streaming responses.
  • A low-severity comment about API consistency.

Overall, this is a solid implementation of a complex feature. Addressing the parsing bug is the most critical point.

Comment on lines 540 to 558
var fullText = ""
// Accumulate the response text.
for try await chunk in responseStream {
if let text = chunk.text {
fullText += text
}

// Attempt to parse and yield partial results.
let cleanText = GenerativeModel.cleanedJSON(from: fullText)
let parser = PartialJSONParser(input: cleanText)
if let jsonValue = parser.parse() {
do {
let rawContent = ModelOutput(jsonValue: jsonValue)
let contentValue = try contentProvider(rawContent)
continuation.yield(Response(content: contentValue, rawContent: rawContent))
} catch {
// Ignore conversion errors for partial content.
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation accumulates the entire response text in fullText and re-parses it from the beginning with each new chunk. For very large streaming responses, this could become inefficient in terms of both memory (for fullText) and CPU (for re-parsing).

A potential future optimization could be to design the PartialJSONParser to work with a stream of characters or chunks directly, avoiding the need to buffer the entire response and re-parse known-good sections.

While the current approach is simple and likely sufficient for typical response sizes, it's worth keeping this in mind for future performance improvements.

@paulb777
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces streaming support for structured JSON output. The changes include a new PartialJSONParser to handle incomplete JSON data from the stream, new generateObjectStream methods in GenerativeModel to provide an AsyncThrowingStream of response objects, and comprehensive unit and integration tests for the new functionality.

The implementation is well-structured. The partial parser is robust and well-tested, and the streaming logic in GenerativeModel correctly handles yielding both partial and final results. The new integration tests provide good coverage for the end-to-end streaming flow.

I have one minor suggestion to improve debuggability by adding a log for ignored errors during partial content conversion.

@paulb777
Copy link
Member Author

/gemini summarize

@gemini-code-assist
Copy link
Contributor

Summary of Changes

This pull request significantly enhances the Firebase AI SDK by introducing structured output streaming. It provides new generateObjectStream methods within the GenerativeModel class, allowing developers to receive AI-generated content as a stream of strongly-typed objects conforming to a specified JSON schema. A key component of this feature is the newly implemented PartialJSONParser, which intelligently handles and parses incomplete JSON fragments as they arrive, ensuring a smooth and resilient streaming experience. This change enables more dynamic and interactive AI applications by providing immediate feedback as the model generates its response.

Highlights

  • Structured Output Streaming: Introduced generateObjectStream methods to allow models to stream structured JSON output, enhancing interaction with AI models by providing strongly-typed objects.
  • Partial JSON Parsing: Added a PartialJSONParser to robustly handle and parse incomplete JSON responses received during streaming, enabling real-time processing of partial data.
  • Enhanced generateContentStream: An overload for generateContentStream was added to support passing an optional GenerationConfig, providing more flexibility in content generation.
  • Comprehensive Testing: New integration and unit tests were added to validate the generateObjectStream functionality and the PartialJSONParser's robustness across various scenarios, including partial and malformed JSON.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • FirebaseAI/Sources/GenerativeModel.swift
    • Added an overload for generateContentStream to accept an optional GenerationConfig.
    • Implemented a private _generateObjectStream helper function to manage the core logic for structured output streaming, including accumulating text, partial JSON parsing, and yielding content.
    • Introduced two public generateObjectStream methods (one conditional on FoundationModels import) that leverage the new streaming logic to return AsyncThrowingStream<Response<Content>, Error> for FirebaseGenerable and FoundationModels.Generable types.
  • FirebaseAI/Sources/PartialJSONParser.swift
    • New file containing the PartialJSONParser class, designed to parse potentially incomplete JSON strings and extract valid JSONValue objects from them. This parser is crucial for handling streaming JSON responses.
  • FirebaseAI/Tests/TestApp/Tests/Integration/GenerateObjectStreamIntegrationTests.swift
    • New file introducing integration tests for the generateObjectStream functionality. These tests cover scenarios like streaming complete recipe objects and handling partial recipe objects, ensuring the end-to-end flow works as expected.
  • FirebaseAI/Tests/Unit/PartialJSONParserTests.swift
    • New file containing extensive unit tests for the PartialJSONParser. These tests validate the parser's ability to handle various JSON structures, including complete objects, partial strings, arrays, nested objects, escaped characters, primitives (true, false, null), partial numbers, and incomplete Unicode sequences.
Activity
  • gemini-code-assist[bot] provided a critical review comment regarding a logical error in PartialJSONParser.parseString() for escape sequence handling.
  • gemini-code-assist[bot] identified a high-priority issue in _generateObjectStream where the final object might be yielded twice.
  • gemini-code-assist[bot] suggested adding more comprehensive unit tests to PartialJSONParser for escaped characters.
  • gemini-code-assist[bot] raised a medium-priority concern about redundancy and potential missed data in the final validation block of _generateObjectStream.
  • gemini-code-assist[bot] suggested adding more edge case tests for PartialJSONParser covering primitives, partial numbers, incomplete Unicode, trailing commas, and empty structures.
  • gemini-code-assist[bot] identified a high-priority bug in PartialJSONParser.parseNumber() related to greedy index advancement and lack of backtracking for invalid numbers.
  • gemini-code-assist[bot] provided a medium-priority suggestion for performance optimization in _generateObjectStream by avoiding full text re-parsing.
  • gemini-code-assist[bot] suggested adding the @available attribute to a new generateContentStream overload for consistency.
  • gemini-code-assist[bot] suggested adding debug logging for conversion errors in _generateObjectStream for better debugging experience.
  • paulb777 made multiple requests for /gemini review and one request for /gemini summarize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant