fix(sap): normalize list-shaped reasoning_content into a string#34613
fix(sap): normalize list-shaped reasoning_content into a string#34613devin-ai-integration[bot] wants to merge 1 commit into
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Greptile SummaryThis PR normalizes SAP list-shaped reasoning content before shared response validation.
Confidence Score: 5/5The PR appears safe to merge, with the SAP-specific normalization confined to list-shaped reasoning content and covered across synchronous and streaming paths. Existing string values pass through unchanged, list values are converted before schema validation, structured signatures are retained, and the changed response paths have focused regression coverage.
|
| Filename | Overview |
|---|---|
| litellm/llms/sap/chat/handler.py | Adds a localized response-normalization helper and consistently invokes it before validating SAP streaming chunks. |
| litellm/llms/sap/chat/transformation.py | Normalizes SAP final-result reasoning content before constructing the shared ModelResponse. |
| tests/test_litellm/llms/sap/chat/test_sap_transformation.py | Adds mock-based regression tests covering list, empty, string, and streaming reasoning-content forms. |
Reviews (1): Last reviewed commit: "fix(sap): normalize list-shaped reasonin..." | Re-trigger Greptile
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
TLDR
Problem this solves:
sap/gemini-3.5-flashcompletions fail with a Pydantic errorreasoning_contentas a list of blocksMessage.reasoning_contentonly accepts a stringHow it solves it:
reasoning_contentlists before validating the responsethinking_blocksRelevant issues
Fixes #34612
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
I don't have SAP AI Core / Generative AI Hub credentials on hand, so I couldn't run a live
sap/gemini-3.5-flashcall against a local proxy; the reproduction and the fix are covered by unit tests that fail on the parent commit and pass on this branch. Happy to capture live curl output if someone can share a service key, or the reporter can validate with:Before the fix that returns
litellm.APIConnectionError: 1 validation error for ModelResponse reasoning_content Input should be a valid string [input_value=[{'content': '', 'signature': '...'}]]; after it, a normal completion withreasoning_contentas a stringType
🐛 Bug Fix
Changes
GenAIHubOrchestrationConfig.transform_responsefed the raw SAP payload straight intoModelResponse.model_validate. Gemini models on SAP put the model's chain of thought inreasoning_contentas a list of blocks, e.g.[{"content": "...", "signature": "..."}], which blows up against the OpenAI-compatible schema where the field is a stringnormalize_reasoning_content(inlitellm/llms/sap/chat/handler.py, so both the non-streaming transform and the stream parser can use it) rewrites each choice'smessage/delta:{"reasoning_content": [{"content": "thinking...", "signature": "sig"}]} -> { "reasoning_content": "thinking...", "thinking_blocks": [{"type": "thinking", "thinking": "thinking...", "signature": "sig"}], }Empty blocks (the shape in the issue, where SAP sends
content: ""with just a signature) collapse toNonerather than an empty string, string values pass through untouched, and an existingthinking_blockson the payload wins over the derived oneLink to Devin session: https://app.devin.ai/sessions/3782d36dd4e24d4ea7a6f4a70d62646f