support thinking_blocks inputs in OpenAI Responses API via litellm.completions#21322
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryAdds bidirectional
Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| litellm/completion_extras/litellm_responses_transformation/transformation.py | Adds bidirectional thinking_blocks transformation. Two logic issues found: redacted_thinking without data creates empty reasoning items, and empty reasoning text is silently dropped in output direction creating an asymmetry with input direction. |
| tests/test_litellm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py | Comprehensive test suite with 15 tests covering input/output transformation, edge cases, and multi-turn conversations. All tests are mock-based (no network calls). Minor style issues with redundant imports. |
Flowchart
flowchart TD
subgraph INPUT["INPUT: Chat Completions → Responses API"]
A[Assistant Message with thinking_blocks] --> B{Block Type?}
B -->|type: thinking| C[Create reasoning item\nwith summary text]
B -->|type: redacted_thinking| D{Has data field?}
D -->|Yes| E[Create reasoning item\nwith encrypted_content]
D -->|No| F[Create empty reasoning item\nsummary: empty array]
B -->|unknown type| G[Skip with warning]
C --> H[Append reasoning items\nBEFORE content/tool_calls]
E --> H
F --> H
end
subgraph OUTPUT["OUTPUT: Responses API → Chat Completions"]
I[ResponseReasoningItem] --> J{Has encrypted_content?}
J -->|Yes| K[Create redacted_thinking\nthinking_block with data]
J -->|No| L{Has reasoning text?}
L -->|Non-empty| M[Create thinking\nthinking_block with text]
L -->|Empty string| N[Silently dropped]
K --> O[Attach thinking_blocks\nto Message object]
M --> O
end
INPUT -.->|Round-trip| OUTPUT
Last reviewed commit: 38670bd
litellm/completion_extras/litellm_responses_transformation/transformation.py
Show resolved
Hide resolved
litellm/completion_extras/litellm_responses_transformation/transformation.py
Show resolved
Hide resolved
...lm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py
Show resolved
Hide resolved
...lm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py
Show resolved
Hide resolved
|
@greptileai please re-review. Previous review flagged model_construct with dict summary items as a known issue causing getattr(dict, "text", "") to return "". This is incorrect — Pydantic v2's model_construct from openai.types.responses import ResponseReasoningItem item = ResponseReasoningItem.model_construct( type(item.summary[0]) # Summary (Pydantic object, not dict) All 15 tests pass including test_output_transformation_reasoning_without_encrypted_content. Regarding the two edge cases flagged in latest review:
Neither edge case affects the core functionality: encrypted_content round-tripping for stateless multi-turn reasoning, which is verified with real OpenAI API calls (o3-pro). |
Greptile SummaryThis PR adds bidirectional
Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| litellm/completion_extras/litellm_responses_transformation/transformation.py | Adds bidirectional thinking_blocks transformation. Input direction (thinking_blocks → reasoning items) is well-structured. Output direction has a reasoning_content accumulation issue where multiple reasoning items overwrite rather than accumulate, creating inconsistency with the new thinking_blocks_list which correctly accumulates. |
| tests/test_litellm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py | Comprehensive test suite with 15 tests covering both input and output directions. Tests are mock-only (no real network calls). Good coverage of edge cases including empty/None/unknown types and multi-turn conversations. |
Flowchart
flowchart TD
subgraph Input["INPUT: Chat Completions → Responses API"]
A[Assistant Message with thinking_blocks] --> B{Block Type?}
B -->|type: thinking| C[Reasoning Item with summary_text]
B -->|type: redacted_thinking| D[Reasoning Item with encrypted_content]
B -->|unknown type| E[Skip with warning]
C --> F[Add reasoning items to input_items]
D --> F
F --> G{Has tool_calls?}
G -->|Yes| H[Add function_call items]
G -->|No| I[Add message item with content]
end
subgraph Output["OUTPUT: Responses API → Chat Completions"]
J[ResponseReasoningItem] --> K{Has encrypted_content?}
K -->|Yes| L[thinking_block: redacted_thinking + data]
K -->|No| M{Has reasoning text?}
M -->|Yes| N[thinking_block: thinking + text]
M -->|No| O[No thinking_block created]
L --> P[Accumulate in thinking_blocks_list]
N --> P
P --> Q[ResponseOutputMessage]
Q --> R[Message with thinking_blocks + reasoning_content]
end
Last reviewed commit: 38670bd
litellm/completion_extras/litellm_responses_transformation/transformation.py
Show resolved
Hide resolved
|
@greptileai please rereview: The reasoning_content overwrite behavior is pre-existing code, not introduced by this PR. The diff shows those lines are unchanged — this PR only added the thinking_blocks_list reasoning_content is a str field on Message — it holds a single string by design. Changing it to accumulate would require modifying the Message type, which is out of scope for this PR This PR actually improves the situation: thinking_blocks is the proper list-based field that correctly accumulates all reasoning items. Users who need the full reasoning history should |
Greptile SummaryThis PR adds bidirectional
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/completion_extras/litellm_responses_transformation/transformation.py | Adds bidirectional thinking_blocks transformation between Chat Completions and Responses API formats. Has a duplicate type annotation that may fail mypy. |
| tests/test_litellm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py | Comprehensive mock-only test suite covering 13+ cases for input/output thinking_blocks transformation. No network calls, consistent with existing test patterns. |
Flowchart
flowchart TD
subgraph INPUT["INPUT: Chat Completions → Responses API"]
A[Assistant Message with thinking_blocks] --> B{Block Type?}
B -->|"type: thinking"| C["Reasoning Item\n{type: reasoning, summary: [{text: ...}]}"]
B -->|"type: redacted_thinking"| D["Reasoning Item\n{type: reasoning, encrypted_content: data, summary: []}"]
B -->|unknown type| E[Skip with warning]
C --> F[Extend input_items with reasoning items]
D --> F
F --> G{Has tool_calls?}
G -->|Yes| H[Append function_call items]
G -->|No, content exists| I[Append message item]
end
subgraph OUTPUT["OUTPUT: Responses API → Chat Completions"]
J[ResponseReasoningItem] --> K{Has encrypted_content?}
K -->|Yes| L["thinking_block\n{type: redacted_thinking, data: encrypted_content}"]
K -->|No, has summary text| M["thinking_block\n{type: thinking, thinking: text}"]
L --> N[Accumulate in thinking_blocks_list]
M --> N
N --> O[ResponseOutputMessage]
O --> P["Message with\nthinking_blocks + content"]
P --> Q[Flush thinking_blocks_list]
end
INPUT -.->|Round-trip via encrypted_content| OUTPUT
Last reviewed commit: 38670bd
litellm/completion_extras/litellm_responses_transformation/transformation.py
Outdated
Show resolved
Hide resolved
litellm/completion_extras/litellm_responses_transformation/transformation.py
Show resolved
Hide resolved
38670bd to
e823189
Compare
Feat: Support
thinking_blocksin OpenAI Responses API transformation layerType
New Feature
Changes
When
litellm.completion()routes to OpenAI's Responses API (e.g., o3-mini, o1), the transformation layer now handlesthinking_blocksbidirectionally:INPUT (Chat Completions → Responses API):
thinking_blocksfrom assistant messagestype: "thinking"→ reasoning item withsummary(full text preserved)type: "redacted_thinking"→ reasoning item withencrypted_content+ emptysummary: []OUTPUT (Responses API → Chat Completions):
encrypted_contentfromResponseReasoningItem→thinking_blockswithtype: "redacted_thinking"thinking_blockswithtype: "thinking"thinking_blockson the responseMessageobjectThis enables stateless multi-turn conversations with reasoning models via
encrypted_contentround-tripping, matching the unifiedthinking_blocksinterface already supported forClaude and Gemini.
Files Changed
litellm/completion_extras/litellm_responses_transformation/transformation.py— Added_convert_thinking_blocks_to_reasoning_items(), modified input/output transformation pathstests/test_litellm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py— 15 unit tests (11 input, 4 output)Test Plan
poetry run pytest tests/test_litellm/completion_extras/litellm_responses_transformation/test_thinking_blocks_transformation.py)with/without encrypted_content