Skip to content

Commit 44d6da3

Browse files
authored
Move ThinkingPart to preceed TextPart in OpenAIResponsesModel (#2043)
1 parent 359554c commit 44d6da3

File tree

6 files changed

+83
-78
lines changed

6 files changed

+83
-78
lines changed

pydantic_ai_slim/pydantic_ai/models/openai.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,13 +644,16 @@ def _process_response(self, response: responses.Response) -> ModelResponse:
644644
"""Process a non-streamed response, and prepare a message to return."""
645645
timestamp = number_to_datetime(response.created_at)
646646
items: list[ModelResponsePart] = []
647-
items.append(TextPart(response.output_text))
648647
for item in response.output:
649648
if item.type == 'reasoning':
650649
for summary in item.summary:
651650
# NOTE: We use the same id for all summaries because we can merge them on the round trip.
652651
# The providers don't force the signature to be unique.
653652
items.append(ThinkingPart(content=summary.text, id=item.id))
653+
elif item.type == 'message':
654+
for content in item.content:
655+
if content.type == 'output_text': # pragma: no branch
656+
items.append(TextPart(content.text))
654657
elif item.type == 'function_call':
655658
items.append(ToolCallPart(item.name, item.arguments, tool_call_id=item.call_id))
656659
return ModelResponse(

tests/models/test_cohere.py

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,11 @@ async def test_cohere_model_thinking_part(allow_model_requests: None, co_api_key
441441
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
442442
ModelResponse(
443443
parts=[
444-
IsInstance(TextPart),
445444
IsInstance(ThinkingPart),
446445
IsInstance(ThinkingPart),
447446
IsInstance(ThinkingPart),
448447
IsInstance(ThinkingPart),
448+
IsInstance(TextPart),
449449
],
450450
usage=Usage(
451451
request_tokens=13,
@@ -470,11 +470,11 @@ async def test_cohere_model_thinking_part(allow_model_requests: None, co_api_key
470470
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
471471
ModelResponse(
472472
parts=[
473-
IsInstance(TextPart),
474473
IsInstance(ThinkingPart),
475474
IsInstance(ThinkingPart),
476475
IsInstance(ThinkingPart),
477476
IsInstance(ThinkingPart),
477+
IsInstance(TextPart),
478478
],
479479
usage=Usage(
480480
request_tokens=13,
@@ -495,43 +495,7 @@ async def test_cohere_model_thinking_part(allow_model_requests: None, co_api_key
495495
]
496496
),
497497
ModelResponse(
498-
parts=[
499-
TextPart(
500-
content="""\
501-
Crossing a river can be a different challenge compared to crossing a street, and the approach to safety and navigation will vary. Here are some considerations and steps to help you cross a river safely:
502-
503-
1. **Determine the River's Characteristics:**
504-
- **Width and Depth:** Measure or estimate the width of the river. Very wide rivers may require a boat or bridge for safe crossing. Also, assess the depth; shallow areas might be safe to wade through, while deeper sections may require a different method.
505-
- **Current and Flow:** Understand the river's current. Strong currents can make swimming dangerous and may carry debris. Always check the flow rate and direction before attempting to cross.
506-
- **Hazards:** Look for potential hazards like rocks, logs, or underwater obstacles that could cause injury or damage to equipment.
507-
508-
2. **Choose a Safe Crossing Method:**
509-
- **Fording:** If the river is shallow and the current is gentle, you might be able to ford the river. This involves walking through the water, often with the help of a sturdy stick or pole for balance and support. Always test the depth and current before attempting to ford.
510-
- **Swimming:** Swimming across a river is a challenging and potentially dangerous option. It requires strong swimming skills, endurance, and knowledge of river currents. Always swim with a buddy and be aware of your surroundings.
511-
- **Boat or Raft:** Using a boat, raft, or even an inflatable tube can be a safe and efficient way to cross. Ensure the boat is sturdy, properly equipped, and that you have the necessary safety gear, such as life jackets and a first-aid kit.
512-
- **Bridge or Ferry:** If available, use a bridge or a ferry service. These are typically the safest and most reliable methods for crossing a river.
513-
514-
3. **Prepare and Pack Essential Items:**
515-
- **Life Jacket/Personal Flotation Device (PFD):** Always wear a life jacket or PFD when crossing a river, especially if swimming or using a boat.
516-
- **First-Aid Kit:** Carry a basic first-aid kit to handle any minor injuries that might occur during the crossing.
517-
- **Map and Compass:** Navigate the river and its surroundings with the help of a map and compass, especially if you're in an unfamiliar area.
518-
- **Communication Device:** Have a means of communication, such as a satellite phone or a personal locator beacon, especially in remote areas.
519-
- **Dry Clothing and Shelter:** Pack extra dry clothing and a waterproof shelter (like a tarp or tent) in case you get wet or need to wait out bad weather.
520-
521-
4. **Follow River Safety Guidelines:**
522-
- **Stay on Marked Paths:** If there are designated river paths or trails, use them. These routes are often designed to be safer and less prone to hazards.
523-
- **Avoid Hazards:** Be cautious of slippery rocks, strong currents, and hidden underwater obstacles. Never swim or ford in areas with known dangers.
524-
- **Group Safety:** If crossing with others, stay together. It's easier to keep an eye on each other and provide assistance if needed.
525-
526-
5. **Be Prepared for Emergencies:**
527-
- **Know Emergency Procedures:** Familiarize yourself with river rescue techniques and procedures. Learn how to signal for help and basic survival skills.
528-
- **Carry Emergency Supplies:** Pack emergency supplies, including a whistle, a bright-colored cloth to signal, and a signal mirror (if available).
529-
- **Leave a Plan:** Inform someone on the riverbank about your crossing plans, including your expected time of return. This person can raise the alarm if you don't return as scheduled.
530-
531-
Remember, crossing a river can be a challenging and potentially dangerous endeavor. Always prioritize safety, and if in doubt, seek professional guidance or assistance from experienced river guides or local authorities. It's better to be over-prepared than caught off guard in a river crossing situation.\
532-
"""
533-
)
534-
],
498+
parts=[IsInstance(TextPart)],
535499
usage=Usage(
536500
requests=1,
537501
request_tokens=1457,

tests/models/test_gemini.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,10 +1393,36 @@ async def test_gemini_model_thinking_part(allow_model_requests: None, gemini_api
13931393
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
13941394
ModelResponse(
13951395
parts=[
1396-
IsInstance(TextPart),
13971396
IsInstance(ThinkingPart),
13981397
IsInstance(ThinkingPart),
13991398
IsInstance(ThinkingPart),
1399+
TextPart(
1400+
content="""\
1401+
Here are guidelines for safely crossing a street. Remember that these tips are general and may need to be adjusted depending on your local traffic laws and the specific situation. They are not a substitute for professional safety advice.
1402+
1403+
1. Before you approach the street:
1404+
• Use the sidewalk if available and get to the curb or edge of the road.
1405+
• If you're a child or feel unsure, try to have an adult accompany you.
1406+
1407+
2. When you're ready to cross:
1408+
• Look carefully in all directions—start by looking left, then right, and left again. In countries where you drive on the left you'll want to adjust accordingly.
1409+
• Listen for vehicles and be aware of turning cars, which might not be immediately in your line of sight.
1410+
• Make eye contact with drivers if possible so that you know they see you.
1411+
1412+
3. Use designated crossing areas whenever possible:
1413+
• If there's a pedestrian crosswalk, use it. Crosswalks and traffic signals are there to help manage the flow of both vehicles and pedestrians.
1414+
• If there's a "Walk" signal, wait until it's on before crossing. Even if the signal turns green for pedestrians, always take an extra moment to ensure that approaching drivers are stopping.
1415+
1416+
4. While crossing:
1417+
• Continue to remain alert and avoid distractions like cell phones or headphones that could prevent you from noticing approaching traffic.
1418+
• Walk at a steady pace and stay in the crosswalk until you have completely reached the other side.
1419+
1420+
5. After crossing:
1421+
• Once you've safely reached the other side, continue to be aware of any vehicles that might be turning or reversing.
1422+
1423+
Always be cautious—even if you have the right-of-way—and understand that it's better to wait a moment longer than risk being caught off guard. Stay safe!\
1424+
"""
1425+
),
14001426
],
14011427
usage=Usage(
14021428
request_tokens=13,
@@ -1424,10 +1450,10 @@ async def test_gemini_model_thinking_part(allow_model_requests: None, gemini_api
14241450
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
14251451
ModelResponse(
14261452
parts=[
1427-
IsInstance(TextPart),
14281453
IsInstance(ThinkingPart),
14291454
IsInstance(ThinkingPart),
14301455
IsInstance(ThinkingPart),
1456+
IsInstance(TextPart),
14311457
],
14321458
usage=Usage(
14331459
request_tokens=13,

tests/models/test_mistral.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,11 +1982,11 @@ async def test_mistral_model_thinking_part(allow_model_requests: None, openai_ap
19821982
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
19831983
ModelResponse(
19841984
parts=[
1985-
TextPart(content=IsStr()),
19861985
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
19871986
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
19881987
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
19891988
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
1989+
TextPart(content=IsStr()),
19901990
],
19911991
usage=Usage(
19921992
request_tokens=13,
@@ -2012,11 +2012,44 @@ async def test_mistral_model_thinking_part(allow_model_requests: None, openai_ap
20122012
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
20132013
ModelResponse(
20142014
parts=[
2015-
TextPart(content=IsStr()),
20162015
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
20172016
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
20182017
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
20192018
ThinkingPart(content=IsStr(), id='rs_68079ad7f0588191af64f067e7314d840493b22e4095129c'),
2019+
TextPart(
2020+
content="""\
2021+
I'm not a traffic safety expert, but here are some general guidelines that many people follow when crossing a street safely. Remember that local rules and conditions might vary, so always follow local traffic laws and pay close attention to your surroundings.
2022+
2023+
1. Find a Designated Crossing Point
2024+
• Look for crosswalks, pedestrian signals, or marked intersections. These areas are designed for safe crossing.
2025+
• If no crosswalk is available, choose a spot where you have clear visibility of oncoming traffic in all directions.
2026+
2027+
2. Stop at the Curb or Edge of the Road
2028+
• Before stepping off the curb, pause to assess the situation.
2029+
• Resist the urge to step into the street immediately—this helps you avoid unpredictable traffic behavior.
2030+
2031+
3. Look and Listen
2032+
• Look left, then right, and left again. In some places, you might need to check right a second time depending on the flow of traffic.
2033+
• Pay attention to the sound of approaching vehicles or any signals that indicate vehicles may be turning into your path.
2034+
• Remove or lower distractions like headphones so you can be fully aware of your environment.
2035+
2036+
4. Follow Pedestrian Signals (if available)
2037+
• If you're at an intersection with traffic signals, wait for the "Walk" signal.
2038+
• Even when the signal is in your favor, ensure that any turning vehicles (cars or bikes) see you and are stopping.
2039+
2040+
5. Make Eye Contact
2041+
• If possible, make eye contact with drivers who might be turning. This can help ensure that they see you and are taking appropriate action.
2042+
2043+
6. Cross Quickly and Carefully
2044+
• Once you've determined that it's safe, proceed at a steady pace.
2045+
• Continue to be alert while you cross, watching for any unexpected vehicle movements.
2046+
2047+
7. Stay on the Sidewalk Once You've Crossed
2048+
• After reaching the other side, stick to areas designated for pedestrians rather than walking immediately back into the roadway.
2049+
2050+
These suggestions are meant to help you think through pedestrian safety. Different regions may have additional rules or different signals, so if you're unsure, it might help to check local guidelines or ask someone familiar with the area. Stay safe!\
2051+
"""
2052+
),
20202053
],
20212054
usage=Usage(
20222055
request_tokens=13,

tests/models/test_openai.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,11 +1618,11 @@ async def test_openai_responses_model_thinking_part(allow_model_requests: None,
16181618
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
16191619
ModelResponse(
16201620
parts=[
1621-
TextPart(content=IsStr()),
16221621
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16231622
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16241623
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16251624
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
1625+
IsInstance(TextPart),
16261626
],
16271627
usage=Usage(
16281628
request_tokens=13,
@@ -1646,11 +1646,11 @@ async def test_openai_responses_model_thinking_part(allow_model_requests: None,
16461646
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
16471647
ModelResponse(
16481648
parts=[
1649-
TextPart(content=IsStr()),
16501649
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16511650
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16521651
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
16531652
ThinkingPart(content=IsStr(), id='rs_68034841ab2881918a8c210e3d988b9208c845d2be9bcdd8'),
1653+
IsInstance(TextPart),
16541654
],
16551655
usage=Usage(
16561656
request_tokens=13,
@@ -1672,10 +1672,10 @@ async def test_openai_responses_model_thinking_part(allow_model_requests: None,
16721672
),
16731673
ModelResponse(
16741674
parts=[
1675-
TextPart(content=IsStr()),
16761675
ThinkingPart(content=IsStr(), id='rs_68034858dc588191bc3a6801c23e728f08c845d2be9bcdd8'),
16771676
ThinkingPart(content=IsStr(), id='rs_68034858dc588191bc3a6801c23e728f08c845d2be9bcdd8'),
16781677
ThinkingPart(content=IsStr(), id='rs_68034858dc588191bc3a6801c23e728f08c845d2be9bcdd8'),
1678+
IsInstance(TextPart),
16791679
],
16801680
usage=Usage(
16811681
request_tokens=424,
@@ -1704,11 +1704,11 @@ async def test_openai_model_thinking_part(allow_model_requests: None, openai_api
17041704
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
17051705
ModelResponse(
17061706
parts=[
1707-
TextPart(content=IsStr()),
17081707
IsInstance(ThinkingPart),
17091708
IsInstance(ThinkingPart),
17101709
IsInstance(ThinkingPart),
17111710
IsInstance(ThinkingPart),
1711+
IsInstance(TextPart),
17121712
],
17131713
usage=Usage(
17141714
request_tokens=13,
@@ -1733,11 +1733,11 @@ async def test_openai_model_thinking_part(allow_model_requests: None, openai_api
17331733
ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]),
17341734
ModelResponse(
17351735
parts=[
1736-
TextPart(content=IsStr()),
17371736
IsInstance(ThinkingPart),
17381737
IsInstance(ThinkingPart),
17391738
IsInstance(ThinkingPart),
17401739
IsInstance(ThinkingPart),
1740+
IsInstance(TextPart),
17411741
],
17421742
usage=Usage(
17431743
request_tokens=13,

0 commit comments

Comments
 (0)