-
Notifications
You must be signed in to change notification settings - Fork 5.1k
fix(streaming): merge duplicate-index entries in first tool_call chunk #3633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,13 @@ | |
| def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> dict[object, object]: | ||
| for key, delta_value in delta.items(): | ||
| if key not in acc: | ||
| acc[key] = delta_value | ||
| continue | ||
| # Seed indexed-dict lists with [] so duplicate-index entries in the | ||
| # first chunk are merged by the list path below instead of stored raw. | ||
| if is_list(delta_value) and delta_value and is_dict(delta_value[0]) and "index" in delta_value[0]: | ||
| acc[key] = [] | ||
|
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the normal role-first stream, the parsed message snapshot has Useful? React with 👍 / 👎. |
||
| else: | ||
| acc[key] = delta_value | ||
| continue | ||
|
|
||
| acc_value = acc[key] | ||
| if acc_value is None: | ||
|
|
@@ -33,7 +38,7 @@ def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> | |
| elif is_list(acc_value) and is_list(delta_value): | ||
| # for lists of non-dictionary items we'll only ever get new entries | ||
| # in the array, existing entries will never be changed | ||
| if all(isinstance(x, (str, int, float)) for x in acc_value): | ||
| if acc_value and all(isinstance(x, (str, int, float)) for x in acc_value): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an accumulated list is empty and the next delta contains primitive entries (for example, Useful? React with 👍 / 👎. |
||
| acc_value.extend(delta_value) | ||
| continue | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the stream's initial SSE chunk itself contains multiple
tool_callsentries with the same index, this branch is never reached:_accumulate_chunk()returns_convert_initial_chunk_into_snapshot()while the snapshot isNone, and that conversion copieschoice.delta.to_dict()directly. The duplicate entries therefore remain split, so later deltas merge only into the first physical entry and the final arguments can still be truncated or invalid; the same indexed-list normalization needs to be applied during initial snapshot conversion.Useful? React with 👍 / 👎.