feat(litellm): handle reasoning_content and reasoning fields in streaming#449
feat(litellm): handle reasoning_content and reasoning fields in streaming#449daewoongoh wants to merge 4 commits into
Conversation
…ming LiteLLMHandler was not processing reasoning/thinking fields from the stream delta, causing reasoning output from DeepSeek, QwQ, and other reasoning models routed through LiteLLM to be silently dropped. Mirrors the reasoning extraction already present in BaseOpenAiCompatibleProvider: checks for `reasoning_content` first, falls back to `reasoning`, skips empty/whitespace-only values.
Add tests verifying that reasoning_content and reasoning delta fields are correctly yielded as reasoning chunks, that reasoning_content takes precedence when both fields are present, and that empty/whitespace-only values are silently ignored.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughLiteLLMHandler's streaming message creation now processes reasoning fields ( ChangesReasoning Field Support
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/api/providers/lite-llm.ts`:
- Around line 238-248: The current logic in `src/api/providers/lite-llm.ts`
inside the loop over keys "reasoning_content" and "reasoning" breaks after
finding the key even if its value is empty or null, preventing fallback to the
other key. To fix this, modify the code to only break the loop if the reasoning
text is non-empty after trimming. This ensures if `reasoning_content` is present
but empty or null, it falls back properly to `reasoning`. Apply the same fix
pattern in `src/api/providers/base-openai-compatible-provider.ts`. Additionally,
add a test case in `lite-llm.spec.ts` covering when `reasoning_content` is null
but `reasoning` contains valid text to verify the fallback behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: aba7faab-689b-45fe-92bf-f0c10079900f
📒 Files selected for processing (2)
src/api/providers/__tests__/lite-llm.spec.tssrc/api/providers/lite-llm.ts
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Add a test case where reasoning_content is undefined and reasoning is an empty string. This exercises the `|| ""` fallback in the reasoning delta handler, which was previously uncovered.
Related GitHub Issue
Closes: #447
Description
LiteLLMHandler.createMessageoverrides the streaming loop independently fromBaseOpenAiCompatibleProvider, but was missing the logic to extractreasoning_content/reasoningfields from stream deltas. As a result, thinking output from reasoning models (e.g. DeepSeek-R1, QwQ-32B) routed through a LiteLLM proxy was silently dropped and never surfaced in the UI.How it was fixed:
In the streaming loop of
lite-llm.ts, added the same reasoning extraction pattern already present inBaseOpenAiCompatibleProvider:delta.reasoning_contentfirst, fall back todelta.reasoning{ type: "reasoning", text }chunk when a non-empty value is foundNo changes to types, configuration, or other providers were needed.
Test Procedure
Unit tests (
src/api/providers/__tests__/lite-llm.spec.ts):Added a
"reasoning field handling"describe block with 4 cases:reasoning_contentdelta yields areasoningchunkreasoningdelta yields areasoningchunk (fallback)reasoning_contenttakes precedence (only one chunk emitted)Run locally with:
node_modules/.bin/vitest run --root . api/providers/__tests__/lite-llm.spec.ts All 26 tests pass.Pre-Submission Checklist
Screenshots / Videos
N/A
Documentation Updates
Additional Notes
The fix is intentionally minimal — only lite-llm.ts is touched on the implementation side. The pattern is identical to what BaseOpenAiCompatibleProvider already does, so behavior is consistent across providers.
Get in Touch
hehegwk_23849
Summary by CodeRabbit