mlcommons / mlcommons/endpoints

OpenAI SSE accumulator assumes one token channel per streamed chunk

Open
#325 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
21
Forks
28
Avg merge
3d 17h
Merged PRs (30d)
13

Description

The current OpenAISSEAccumulator design appears to assume that each streamed SSE delta belongs to only one token channel at a time: content, reasoning, or tool-call data. That invariant is not guaranteed by OpenAI-compatible serving frameworks, especially when stream batching / larger stream intervals are used.

Code pointers:

Concrete example:

If one streamed delta contains both content and reasoning:

from inference_endpoint.openai.accumulator import OpenAISSEAccumulator
from inference_endpoint.openai.types import SSEChoice, SSEDelta

acc = OpenAISSEAccumulator("qid", stream_all_chunks=True)
acc.add_chunk(
    SSEChoice(
        delta=SSEDelta(
            content="answer",
            reasoning_content="think",
            tool_calls=[
                {
                    "index": 0,
                    "id": "call_1",
                    "type": "function",
                    "function": {"name": "f", "arguments": "{}"},
                }
            ],
        )
    )
)

result = acc.get_final_output()
print(result.response_output.as_message_parts())

Observed result:

("answer", None, (...tool_calls...))

The reasoning_content="think" token data is silently dropped because the content branch wins and the reasoning_content branch is skipped.

This may be less likely with stream_interval=1, but it is not a safe design invariant to rely on. Multiple token channels in the same streamed chunk could cause incorrect final outputs, missing reasoning data, and potentially incorrect downstream token accounting.

Potential solution:

Represent each streamed SSE frame as a structured chunk object that can carry all token-channel deltas present in that frame, e.g. content delta, reasoning delta, and tool-call delta together. The accumulator can then maintain a list of these structured chunks and build the final TextModelOutput by independently folding each channel across all chunks, instead of using mutually exclusive branch logic during ingestion.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/inference_endpoint/openai/accumulator.py, especially add_chunk() and final output reconstruction, then read TextModelOutput.as_message_parts() in src/inference_endpoint/core/types.py. Reproduce the issue's combined content, reasoning_content, and tool_calls example first. Done means no channel data is lost when one SSE delta contains multiple channels and the reconstructed output preserves them independently.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.