Skip to content

Python: [Bug]: Chat Completions streaming loses logprobs after null chunks #8996

Description

@quifox

Description

A Chat Completions streaming chunk with choice.logprobs=None overwrites populated logprobs from an earlier chunk during final response aggregation. A terminal chunk with an empty delta is sufficient to reproduce this.

Expected: The final response retains the last populated logprobs object.

Actual: response.text is hello, but response.additional_properties["logprobs"] is None.

Code Sample

This uses a mocked provider/client and makes no service request.

import asyncio
from unittest.mock import AsyncMock, patch

from agent_framework import Message
from agent_framework_openai import OpenAIChatCompletionClient
from openai.types.chat.chat_completion_chunk import ChatCompletionChunk


class MockStream:
    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        pass

    def __aiter__(self):
        async def chunks():
            populated = {"content": [{"token": "hello", "bytes": [104, 101, 108, 108, 111], "logprob": -0.1, "top_logprobs": []}]}
            for delta, logprobs, finish_reason in [({"content": "hello"}, populated, None), ({}, None, "stop")]:
                yield ChatCompletionChunk.model_validate({
                    "id": "example-stream",
                    "object": "chat.completion.chunk",
                    "created": 0,
                    "model": "test-model",
                    "choices": [{"index": 0, "delta": delta, "logprobs": logprobs, "finish_reason": finish_reason}],
                })
        return chunks()


async def main():
    client = OpenAIChatCompletionClient(api_key="test-key", model="test-model")
    with patch.object(client.client.chat.completions, "create", new=AsyncMock(return_value=MockStream())):
        response = await client.get_response(
            messages=[Message(role="user", contents=["test"])],
            options={"logprobs": True},
            stream=True,
        ).get_final_response()
    print(response.text, response.additional_properties.get("logprobs"))
    assert response.additional_properties.get("logprobs") is not None


asyncio.run(main())

Package Versions

Source checkout e9857bd75a21843803431a2e7dfa41ee9b017ac7: agent-framework-core 1.20.0, agent-framework-openai 1.15.0; OpenAI SDK 3.23.0.

Python Version

Python 3.12.12.

Additional Context

I will submit a focused fix with regression coverage for this behavior.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 3, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 3, 2026
  3. github-actions commented on Oct 3, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: python/packages/openai/agent_framework_openai/_chat_completion_client.py::_get_metadata_from_chat_choice emits logprobs: None for a terminal streaming choice, and _parse_response_update_from_openai places it in update metadata. Use a mocked two-chunk stream containing populated logprobs with "hello", followed by an empty delta with null logprobs and finish_reason="stop", then call get_final_response() and observe that final logprobs are None.

    • Failing test: python/packages/openai/tests/openai/test_openai_chat_completion_client.py::test_streaming_final_response_preserves_logprobs_after_null_chunk
    • Files examined: python/packages/openai/agent_framework_openai/_chat_completion_client.py, python/packages/openai/tests/openai/test_openai_chat_completion_client.py, python/packages/core/agent_framework/_clients.py, python/packages/core/agent_framework/_types.py, python/packages/openai/pyproject.toml
    • Tests run: test_streaming_final_response_preserves_logprobs_after_null_chunk, test_streaming_closes_provider_stream_on_completion
    • Reported version: agent-framework-openai 1.15.0
    • Current version: agent-framework-openai 1.15.0
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agentsUsage: [Issues, PRs], Target: Single agentpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions