17
17
from dataclasses import dataclass , field , replace
18
18
from typing import Any , Union
19
19
20
- from pydantic_ai ._thinking_part import END_THINK_TAG , START_THINK_TAG
21
20
from pydantic_ai .exceptions import UnexpectedModelBehavior
22
21
from pydantic_ai .messages import (
23
22
ModelResponsePart ,
@@ -72,7 +71,7 @@ def handle_text_delta(
72
71
* ,
73
72
vendor_part_id : VendorId | None ,
74
73
content : str ,
75
- extract_think_tags : bool = False ,
74
+ thinking_tags : tuple [ str , str ] | None = None ,
76
75
) -> ModelResponseStreamEvent | None :
77
76
"""Handle incoming text content, creating or updating a TextPart in the manager as appropriate.
78
77
@@ -85,7 +84,7 @@ def handle_text_delta(
85
84
of text. If None, a new part will be created unless the latest part is already
86
85
a TextPart.
87
86
content: The text content to append to the appropriate TextPart.
88
- extract_think_tags: Whether to extract `<think>` tags from the text content and handle them as thinking parts.
87
+ thinking_tags: If provided, will handle content between the thinking tags as thinking parts.
89
88
90
89
Returns:
91
90
- A `PartStartEvent` if a new part was created.
@@ -110,10 +109,10 @@ def handle_text_delta(
110
109
if part_index is not None :
111
110
existing_part = self ._parts [part_index ]
112
111
113
- if extract_think_tags and isinstance (existing_part , ThinkingPart ):
114
- # We may be building a thinking part instead of a text part if we had previously seen a `<think>` tag
115
- if content == END_THINK_TAG :
116
- # When we see `</think>` , we're done with the thinking part and the next text delta will need a new part
112
+ if thinking_tags and isinstance (existing_part , ThinkingPart ):
113
+ # We may be building a thinking part instead of a text part if we had previously seen a thinking tag
114
+ if content == thinking_tags [ 1 ] :
115
+ # When we see the thinking end tag , we're done with the thinking part and the next text delta will need a new part
117
116
self ._vendor_id_to_part_index .pop (vendor_part_id )
118
117
return None
119
118
else :
@@ -123,8 +122,8 @@ def handle_text_delta(
123
122
else :
124
123
raise UnexpectedModelBehavior (f'Cannot apply a text delta to { existing_part = } ' )
125
124
126
- if extract_think_tags and content == START_THINK_TAG :
127
- # When we see a `<think>` tag (which is a single token), we'll build a new thinking part instead
125
+ if thinking_tags and content == thinking_tags [ 0 ] :
126
+ # When we see a thinking start tag (which is a single token), we'll build a new thinking part instead
128
127
self ._vendor_id_to_part_index .pop (vendor_part_id , None )
129
128
return self .handle_thinking_delta (vendor_part_id = vendor_part_id , content = '' )
130
129
0 commit comments