Skip to content

Commit cd69073

Browse files
authored
Fix how thinking summaries are sent back to Responses API (#2883)
1 parent 0e3f1d9 commit cd69073

7 files changed

+1421
-1530
lines changed

pydantic_ai_slim/pydantic_ai/models/openai.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ async def _map_messages( # noqa: C901
11351135
reasoning_item: responses.ResponseReasoningItemParam | None = None
11361136
for item in message.parts:
11371137
if isinstance(item, TextPart):
1138-
if item.id and item.id.startswith('msg_'):
1138+
if item.id and message.provider_name == self.system:
11391139
if message_item is None or message_item['id'] != item.id: # pragma: no branch
11401140
message_item = responses.ResponseOutputMessageParam(
11411141
role='assistant',
@@ -1164,26 +1164,33 @@ async def _map_messages( # noqa: C901
11641164
elif isinstance(item, ThinkingPart):
11651165
if (
11661166
item.id
1167-
and item.provider_name == self.system
1168-
and OpenAIModelProfile.from_profile(
1169-
self.profile
1170-
).openai_supports_encrypted_reasoning_content
1167+
and message.provider_name == self.system
11711168
and model_settings.get('openai_send_reasoning_ids', True)
11721169
):
1170+
signature: str | None = None
11731171
if (
1174-
reasoning_item is None
1175-
or reasoning_item['id'] != item.id
1176-
and (item.signature or item.content)
1172+
item.signature
1173+
and item.provider_name == self.system
1174+
and OpenAIModelProfile.from_profile(
1175+
self.profile
1176+
).openai_supports_encrypted_reasoning_content
1177+
):
1178+
signature = item.signature
1179+
1180+
if (reasoning_item is None or reasoning_item['id'] != item.id) and (
1181+
signature or item.content
11771182
): # pragma: no branch
11781183
reasoning_item = responses.ResponseReasoningItemParam(
11791184
id=item.id,
11801185
summary=[],
1181-
encrypted_content=item.signature,
1186+
encrypted_content=signature,
11821187
type='reasoning',
11831188
)
11841189
openai_messages.append(reasoning_item)
11851190

11861191
if item.content:
1192+
# The check above guarantees that `reasoning_item` is not None
1193+
assert reasoning_item is not None
11871194
reasoning_item['summary'] = [
11881195
*reasoning_item['summary'],
11891196
Summary(text=item.content, type='summary_text'),

tests/models/cassettes/test_openai_responses/test_openai_responses_model_thinking_part.yaml

Lines changed: 165 additions & 115 deletions
Large diffs are not rendered by default.

tests/models/cassettes/test_openai_responses/test_openai_responses_thinking_part_from_other_model.yaml

Lines changed: 119 additions & 83 deletions
Large diffs are not rendered by default.

tests/models/cassettes/test_openai_responses/test_openai_responses_thinking_part_iter.yaml

Lines changed: 779 additions & 1049 deletions
Large diffs are not rendered by default.

tests/models/cassettes/test_openai_responses/test_openai_responses_thinking_with_modified_history.yaml

Lines changed: 77 additions & 88 deletions
Large diffs are not rendered by default.

tests/models/cassettes/test_openai_responses/test_openai_responses_thinking_with_tool_calls.yaml

Lines changed: 100 additions & 72 deletions
Large diffs are not rendered by default.

tests/models/test_openai_responses.py

Lines changed: 165 additions & 114 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)