Surface Responses output_text logprobs on the text content - #1105
PratikDhanave (PratikDhanave) wants to merge 1 commit into
Conversation
The Responses path built a TextContent from an output_text part but never read its logprobs, so a caller requesting logprobs (Include: message.output_text.logprobs) never received them. The Python client stores them on the text content's additional_properties. Populate the TextContent's AdditionalProperties with the output_text logprobs when present, on both the non-streaming path and the streaming output_item.done path (which now emits an annotations/logprobs-only content the same way it already does for annotations).
There was a problem hiding this comment.
🟡 Changes recommended
Streaming logprobs can be lost during response collection, and the new streaming path lacks regression coverage.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates Responses API handling to expose output_text logprobs for non-streaming and streaming responses.
Changes:
- Propagates logprobs to
TextContent.AdditionalProperties. - Emits streaming metadata for logprobs.
- Adds non-streaming regression coverage.
File summaries
| File | Summary |
|---|---|
provider/openaiprovider/responses.go |
Propagates output text logprobs. |
provider/openaiprovider/responses_test.go |
Tests non-streaming logprobs exposure. |
Review details
Suppressed comments (1)
provider/openaiprovider/responses.go:1602
- When logprobs are present without annotations, this creates an empty
TextContentimmediately after the delta text.ResponseStream.Collect()then coalesces adjacent text contents and copiesAdditionalPropertiesonly from the first item (message/content.go:1175-1179), so the returned collected response loses these logprobs. Preserve the metadata through coalescing (for example, merge the content metadata) or otherwise make the logprobs update surviveCollect(); add a streaming regression test for the logprobs-only case.
populateAnnotations(outputText.Annotations, annotatedContent)
if len(outputText.Logprobs) > 0 {
annotatedContent.AdditionalProperties = map[string]any{"Logprobs": outputText.Logprobs}
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if c, ok := c.AsAny().(responses.ResponseOutputText); ok && (len(c.Annotations) > 0 || len(c.Logprobs) > 0) { | ||
| hasMetadata = true | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if hasAnnotations { | ||
| if hasMetadata { | ||
| annotatedContent := &message.TextContent{} | ||
| for _, c := range item.Content { | ||
| if outputText, ok := c.AsAny().(responses.ResponseOutputText); ok { | ||
| populateAnnotations(outputText.Annotations, annotatedContent) | ||
| if len(outputText.Logprobs) > 0 { | ||
| annotatedContent.AdditionalProperties = map[string]any{"Logprobs": outputText.Logprobs} |
|
Scope: user-visible behavior (bug fix); no public API surface changed Changed Go contract: Upstream evidence reviewed:
Result: aligned. The Go change reproduces the Python client's existing behavior (surface provider logprobs into the content's extension-properties bag) rather than introducing new Go-only behavior; there's no default/opt-in mismatch since surfacing only occurs when the caller already requested logprobs via provider-specific
|
The Responses path built a
TextContentfrom anoutput_textpart (non-streamingresponsesProcessResponse, and the streamingoutput_item.donehandler) but never readoutput_text.logprobs. So a caller that requested logprobs via raw params (Include: ["message.output_text.logprobs"],TopLogprobs) never received them.The Python client preserves them on the text content's
additional_properties["logprobs"]on both parse paths.Change
TextContentAdditionalPropertieswith theoutput_textlogprobs when present.output_item.donehandler previously emitted a text content only when annotations were present (the text itself already arrived via deltas); it now also emits when logprobs are present and carries them, mirroring the annotations handling. Key uses the PascalCase convention already used elsewhere in the provider.Test
TestResponsesOutputTextLogprobsSurfaced_NonStreaming: a canned response whoseoutput_textcarries alogprobsarray now surfacesLogprobson theTextContentAdditionalProperties. Fails before the change (nil), passes after.