Merge duplicate indexed tool call deltas#3234
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 421986a73b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| choices[choice.index] = { | ||
| **choice.model_dump(exclude_unset=True, exclude={"delta"}), | ||
| "message": choice.delta.to_dict(), | ||
| "message": accumulate_delta({}, choice.delta.to_dict()), |
There was a problem hiding this comment.
Normalize first chunks for choices added later
This only applies the duplicate-index merge to choices present in the stream's very first chunk. If a multi-choice stream first sees a choice through the except IndexError path in _accumulate_chunk (for example, the first SSE has choice 0 and a later SSE first introduces choice 1) and that choice's first delta contains duplicate tool_calls entries with the same index, line 418 still stores choice.delta.to_dict() directly, so the duplicate entries remain and subsequent chunks merge into only one of them. Please route that new-choice path through accumulate_delta({}, choice.delta.to_dict()) as well.
Useful? React with 👍 / 👎.
Fixes #3203.
This updates the streaming delta accumulators to route initial list values through the same index-aware merge path used for later chunks. That prevents duplicate
tool_callsentries with the sameindexin the first chunk from being stored as separate list entries.The chat completion initial snapshot path now also normalizes
choice.deltathroughaccumulate_delta, so the first streamed chunk gets the same merge behavior as subsequent chunks.Tests added:
Noneaccumulator valuesNoneaccumulator valuesVerification:
uv run --with pytest --with pytest-asyncio python -m pytest -o addopts='' tests/lib/test_streaming_deltas.pyuv run --with ruff ruff check src/openai/lib/streaming/_deltas.py src/openai/lib/streaming/_assistants.py src/openai/lib/streaming/chat/_completions.py tests/lib/test_streaming_deltas.py