Skip to content

fix(google-genai): report a streamed response as one output message per candidate - #908

Open
pcbeingused333 wants to merge 3 commits into
open-telemetry:mainfrom
pcbeingused333:fix/google-genai-stream-merge-output
Open

pcbeingused333 wants to merge 3 commits into
open-telemetry:mainfrom
pcbeingused333:fix/google-genai-stream-merge-output

Conversation

@pcbeingused333

Copy link
Copy Markdown

Description

generate_content_stream (sync and async) recorded each streamed chunk's candidate as its own output message, so a response streamed in N chunks showed up as N assistant messages holding fragments. The stream wrappers now merge candidates by index before building output messages: adjacent text fragments of the same kind (thought or not) are joined, other parts keep their order, and the last finish reason wins, matching the non-streamed output.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How has this been tested?

  • test_merges_streamed_chunks_into_one_output_message in streaming_base.py (runs for the sync and async streaming tests); fails on main with two messages.
  • New test_merge_streamed_candidates.py: merging per candidate index, thought text kept apart, function calls kept, last finish reason, and no mutation of the streamed chunks.
  • Package tests/ (without conformance): same 8 e2e errors as main (need credentials), 4 more passing.

Checklist

  • Followed the style guidelines of this project
  • Changelog updated if the change requires an entry
  • Unit tests added
  • Documentation updated

This change was made with Claude Code; the tests above were run on main and on this branch.

…er candidate

The streaming wrappers collected every chunk's candidates and turned each
into its own output message, so a response streamed in N chunks was
recorded as N assistant messages holding fragments of the text. Merge the
streamed candidates by index before building the output messages: adjacent
text fragments of the same kind (thought or not) are joined, other parts
are kept in order, and the last finish reason wins, so a streamed response
is reported like the non-streamed one.
@pcbeingused333
pcbeingused333 requested a review from a team as a code owner October 16, 2026 22:10
Copilot AI balanced review requested due to automatic review settings October 16, 2026 22:10
Signed-off-by: Alex Castillo <alex.castillog33@gmail.com>
@linux-foundation-easycla

linux-foundation-easycla Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-10-17 03:28 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Contentless candidates now produce artificial empty output messages instead of being omitted.

1 open issue
What changed in this PR

Fixes Google GenAI streaming telemetry to report one output message per candidate rather than per chunk.

Changes:

  • Merges candidates by index, joining adjacent text while preserving part order and the latest finish reason.
  • Adds merge tests and shared sync/async streaming coverage.
  • Records the fix in the changelog.
File Description
instrumentation/​opentelemetry-instrumentation-google-genai/​tests/​generate_content/​test_merge_streamed_candidates.py Tests merging and chunk immutability.
instrumentation/​opentelemetry-instrumentation-google-genai/​tests/​generate_content/​streaming_base.py Adds sync/async output-message regression coverage.
instrumentation/​opentelemetry-instrumentation-google-genai/​src/​opentelemetry/​instrumentation/​google_genai/​generate_content.py Merges candidates before generating streamed output messages.
instrumentation/​opentelemetry-instrumentation-google-genai/​.changelog/​908.fixed Documents the streaming correction.

Review effort: Balanced

Comment on lines +603 to +611
target = merged[index] = Candidate(
index=candidate.index, content=Content(parts=[])
)
if candidate.finish_reason is not None:
target.finish_reason = candidate.finish_reason
if not candidate.content:
continue
if candidate.content.role:
target.content.role = candidate.content.role
…tput messages

The merge created an empty Content for every candidate index, so a stream
whose candidate never carried content (for example a blocked response)
was reported as an output message with no parts. Non-streamed responses
skip such candidates. Create the merged content only once a chunk
supplies some.
@pcbeingused333

Copy link
Copy Markdown
Author

/easycla

@pcbeingused333
pcbeingused333 force-pushed the fix/google-genai-stream-merge-output branch from dda3275 to e470616 Compare October 17, 2026 03:25

This branch has not been deployed

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants