Skip to content

Commit df14088

Browse files
authored
Create separate ThinkingParts for separate OpenAI Responses reasoning summary parts (#2775)
1 parent 55ad5bd commit df14088

File tree

7 files changed

+2109
-1533
lines changed

7 files changed

+2109
-1533
lines changed

pydantic_ai_slim/pydantic_ai/_parts_manager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ def handle_thinking_delta(
154154
*,
155155
vendor_part_id: Hashable | None,
156156
content: str | None = None,
157+
id: str | None = None,
157158
signature: str | None = None,
158159
) -> ModelResponseStreamEvent:
159160
"""Handle incoming thinking content, creating or updating a ThinkingPart in the manager as appropriate.
@@ -167,6 +168,7 @@ def handle_thinking_delta(
167168
of thinking. If None, a new part will be created unless the latest part is already
168169
a ThinkingPart.
169170
content: The thinking content to append to the appropriate ThinkingPart.
171+
id: An optional id for the thinking part.
170172
signature: An optional signature for the thinking content.
171173
172174
Returns:
@@ -197,7 +199,7 @@ def handle_thinking_delta(
197199
if content is not None:
198200
# There is no existing thinking part that should be updated, so create a new one
199201
new_part_index = len(self._parts)
200-
part = ThinkingPart(content=content, signature=signature)
202+
part = ThinkingPart(content=content, id=id, signature=signature)
201203
if vendor_part_id is not None: # pragma: no branch
202204
self._vendor_id_to_part_index[vendor_part_id] = new_part_index
203205
self._parts.append(part)

pydantic_ai_slim/pydantic_ai/models/openai.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,12 +1270,7 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:
12701270
tool_call_id=chunk.item.call_id,
12711271
)
12721272
elif isinstance(chunk.item, responses.ResponseReasoningItem):
1273-
content = chunk.item.summary[0].text if chunk.item.summary else ''
1274-
yield self._parts_manager.handle_thinking_delta(
1275-
vendor_part_id=chunk.item.id,
1276-
content=content,
1277-
signature=chunk.item.id,
1278-
)
1273+
pass
12791274
elif isinstance(chunk.item, responses.ResponseOutputMessage):
12801275
pass
12811276
elif isinstance(chunk.item, responses.ResponseFunctionWebSearch):
@@ -1291,7 +1286,11 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:
12911286
pass
12921287

12931288
elif isinstance(chunk, responses.ResponseReasoningSummaryPartAddedEvent):
1294-
pass # there's nothing we need to do here
1289+
yield self._parts_manager.handle_thinking_delta(
1290+
vendor_part_id=f'{chunk.item_id}-{chunk.summary_index}',
1291+
content=chunk.part.text,
1292+
id=chunk.item_id,
1293+
)
12951294

12961295
elif isinstance(chunk, responses.ResponseReasoningSummaryPartDoneEvent):
12971296
pass # there's nothing we need to do here
@@ -1301,19 +1300,17 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:
13011300

13021301
elif isinstance(chunk, responses.ResponseReasoningSummaryTextDeltaEvent):
13031302
yield self._parts_manager.handle_thinking_delta(
1304-
vendor_part_id=chunk.item_id,
1303+
vendor_part_id=f'{chunk.item_id}-{chunk.summary_index}',
13051304
content=chunk.delta,
1306-
signature=chunk.item_id,
1305+
id=chunk.item_id,
13071306
)
13081307

13091308
# TODO(Marcelo): We should support annotations in the future.
13101309
elif isinstance(chunk, responses.ResponseOutputTextAnnotationAddedEvent):
13111310
pass # there's nothing we need to do here
13121311

13131312
elif isinstance(chunk, responses.ResponseTextDeltaEvent):
1314-
maybe_event = self._parts_manager.handle_text_delta(
1315-
vendor_part_id=chunk.content_index, content=chunk.delta
1316-
)
1313+
maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=chunk.item_id, content=chunk.delta)
13171314
if maybe_event is not None: # pragma: no branch
13181315
yield maybe_event
13191316

0 commit comments

Comments
 (0)