-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix streaming thinking tags split across multiple chunks #3206
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
Open
dsfaccini
wants to merge
40
commits into
pydantic:main
Choose a base branch
from
dsfaccini:handle-streamed-thinking-over-multiple-chunks
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 30 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
6e145e6
Refactor handle_text_delta() to generator pattern with split tag buff…
dsfaccini 11b5f1f
fix test suite for generator pattern and ensure coverage
dsfaccini 0f876de
Merge main into fix-split-thinking-tags-v2
dsfaccini b5c0910
Merge remote-tracking branch 'origin/main' into fix-split-thinking-ta…
dsfaccini 3439159
rename _tag_buffer to _thinking_tag_buffer
dsfaccini 876ebb2
remove pragmas
dsfaccini adc51e6
adds a finalize method to prevent lost content from buffered chunks t…
dsfaccini 0818191
fix: handle thinking tags with trailing content and vendor_part_id=…
dsfaccini f50d4b4
fix coverage
dsfaccini 551d035
remove pragmas
dsfaccini 0998a63
Merge main to stay updated with latest changes
dsfaccini 9b598dd
models
dsfaccini 41a38e2
- include incomplete closing tags in thinking part
dsfaccini dcac211
wip: improve coverage
dsfaccini b9bdd78
- reduce complexity in parts manager
dsfaccini 4b7f0c1
Merge branch 'main' into handle-streamed-thinking-over-multiple-chunks
dsfaccini ac03e38
add tests for coverage
dsfaccini 5fae762
- fix coverage
dsfaccini 28578bf
- fix case multiple_thinking_parts_with_text_between
dsfaccini 0838109
test more cases without vendor id
dsfaccini 2bc1304
refactor parts manager and add parametrized cases
dsfaccini 3c74ee4
delay emission of empty thinking parts
dsfaccini 2674084
update the groq test
dsfaccini 593e02f
Merge branch 'main' into handle-streamed-thinking-over-multiple-chunks
dsfaccini 0214933
fix coverage
dsfaccini 7c44cd9
add more tests and fix coverage
dsfaccini 06c74c6
fix coverage?
dsfaccini e0fd678
fix coverage
dsfaccini 792cb06
Merge branch 'main' into handle-streamed-thinking-over-multiple-chunks
dsfaccini 712d39b
fix google model stream after merge
dsfaccini 33b6eda
apply review fixes
dsfaccini 4f89122
use partial objects to track buffers
dsfaccini a554910
lift vendor part id restriction for embedded thinking - checking for …
dsfaccini aed5347
wip: increase coverage
dsfaccini 23f37dd
wip: rerun coverage
dsfaccini 7ead79d
wip: fix test for CI env
dsfaccini 706ad78
replace open streaming snapshot with lbl assertions
dsfaccini 6dac474
fix final_flush coverage
dsfaccini a3159b5
replace line by linee asserts with snapshots
dsfaccini a244b98
Merge branch 'main' into handle-streamed-thinking-over-multiple-chunks
dsfaccini File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| from __future__ import annotations as _annotations | ||
|
|
||
| import base64 | ||
| import copy | ||
| import warnings | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import AsyncIterator, Callable, Iterator | ||
|
|
@@ -568,7 +569,7 @@ class StreamedResponse(ABC): | |
| _event_iterator: AsyncIterator[ModelResponseStreamEvent] | None = field(default=None, init=False) | ||
| _usage: RequestUsage = field(default_factory=RequestUsage, init=False) | ||
|
|
||
| def __aiter__(self) -> AsyncIterator[ModelResponseStreamEvent]: | ||
| def __aiter__(self) -> AsyncIterator[ModelResponseStreamEvent]: # noqa: C901 | ||
| """Stream the response as an async iterable of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s. | ||
|
|
||
| This proxies the `_event_iterator()` and emits all events, while also checking for matches | ||
|
|
@@ -615,7 +616,17 @@ def part_end_event(next_part: ModelResponsePart | None = None) -> PartEndEvent | | |
| next_part_kind=next_part.part_kind if next_part else None, | ||
| ) | ||
|
|
||
| async for event in iterator: | ||
| async def chain_async_and_sync_iters( | ||
dsfaccini marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| iter1: AsyncIterator[ModelResponseStreamEvent], iter2: Iterator[ModelResponseStreamEvent] | ||
| ) -> AsyncIterator[ModelResponseStreamEvent]: | ||
| async for event in iter1: | ||
| yield event | ||
| for event in iter2: # pragma: no cover - idk why this isn't covered | ||
|
||
| yield event | ||
|
|
||
| async for event in chain_async_and_sync_iters( # pragma: no cover - related to above | ||
dsfaccini marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| iterator, self._parts_manager.final_flush() | ||
| ): | ||
| if isinstance(event, PartStartEvent): | ||
| if last_start_event: | ||
| end_event = part_end_event(event.part) | ||
|
|
@@ -649,8 +660,14 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: | |
|
|
||
| def get(self) -> ModelResponse: | ||
| """Build a [`ModelResponse`][pydantic_ai.messages.ModelResponse] from the data received from the stream so far.""" | ||
| # Flush any buffered content before building response | ||
| # clone parts manager to avoid modifying the ongoing stream state | ||
| cloned_manager = copy.deepcopy(self._parts_manager) | ||
| for _ in cloned_manager.final_flush(): | ||
| pass | ||
|
|
||
| return ModelResponse( | ||
| parts=self._parts_manager.get_parts(), | ||
| parts=cloned_manager.get_parts(), | ||
| model_name=self.model_name, | ||
| timestamp=self.timestamp, | ||
| usage=self.usage(), | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.