fix(rag): serve streaming chat completions as text/event-stream (#2837) - #2839
fix(rag): serve streaming chat completions as text/event-stream (#2837)#2839Anai-Guo wants to merge 3 commits into
Conversation
…ainers#2837) rag_framework's _stream_completion returned the SSE stream with media_type="text/plain" while already emitting correct SSE framing (data: {...} chunks terminated by data: [DONE]). Strict OpenAI clients (e.g. Open WebUI) require content-type: text/event-stream and reject the stream otherwise, appearing to hang and then failing with a decode error even though the model server is generating tokens normally. Set the media type to text/event-stream to match the OpenAI streaming contract. Signed-off-by: Anai-Guo <antai12232931@outlook.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe RAG streaming chat-completions response now declares ChangesRAG streaming responses
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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.
Code Review
This pull request updates the media type of the StreamingResponse in the RagService from 'text/plain' to 'text/event-stream' to correctly handle streaming responses. No review comments were provided, and there is no additional feedback to offer.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
@Anai-Guo are you AI or Human? @bmahabirbu PTAL and see if this makes sense. |
|
@Anai-Guo Please add a test-case to validate the new behavior, and ensure it doesn't regress in the future. |
|
Hmm small change make sense @Anai-Guo would love a test case to confirm this fix adds functionality to things that need it Im the long run serve should really be an mcp server but since this is a small change im ok as long as I can test it |
|
@bmahabirbu @mikebonnet Added a regression test in Since Also restored the executable bit on the script, which an earlier revision had dropped. |
28bee1b to
7f5f658
Compare
Adds a regression test for containers#2837 that loads the standalone rag_framework container script and checks _stream_completion sets media_type to text/event-stream (not text/plain). Container-only deps (fastapi, pydantic, openai, qdrant_client, uvicorn, aiohttp) are stubbed when absent so the test runs in the unit-test environment. Also restores the executable bit on the rag_framework script. Signed-off-by: Anai-Guo <antai12232931@outlook.com>
7f5f658 to
cbcbd17
Compare
|
@Anai-Guo "An AI" looks like you are an AI and not a Human. |
Signed-off-by: Anai-Guo <antai12232931@outlook.com>
|
Pushed |
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 `@test/unit/test_rag_stream_content_type.py`:
- Around line 99-102: Move the rag_framework SourceFileLoader bootstrap and
exec_module call behind the Python version guard so it cannot run during
collection on Python versions below 3.10. In
test_stream_completion_uses_sse_media_type, perform the version check before
loading the framework, or add a module-level pytest skip before the bootstrap
while preserving the existing test behavior on supported versions.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d6d241d7-37a6-473f-8768-a418e0058422
📒 Files selected for processing (1)
test/unit/test_rag_stream_content_type.py
| @pytest.mark.skipif( | ||
| sys.version_info < (3, 10), | ||
| reason="rag_framework uses PEP 604 unions in class bodies; it only runs in the RAG container image (Python 3.11+)", | ||
| ) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n 'SourceFileLoader|exec_module|load_module|pytest\.mark\.skipif|pytest\.skip' \
test/unit/test_rag_stream_content_type.py
sed -n '1,110p' test/unit/test_rag_stream_content_type.pyRepository: containers/ramalama
Length of output: 3857
Move the RAG framework bootstrap behind the version guard.
SourceFileLoader(...).exec_module(module) runs during test collection, so Python 3.9 can hit the PEP 604 syntax in rag_framework before pytest.mark.skipif takes effect. Load rag_framework only inside test_stream_completion_uses_sse_media_type after checking sys.version_info, or add pytest.skip(..., allow_module_level=True) before the bootstrap code.
🤖 Prompt for 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.
In `@test/unit/test_rag_stream_content_type.py` around lines 99 - 102, Move the
rag_framework SourceFileLoader bootstrap and exec_module call behind the Python
version guard so it cannot run during collection on Python versions below 3.10.
In test_stream_completion_uses_sse_media_type, perform the version check before
loading the framework, or add a module-level pytest skip before the bootstrap
while preserving the existing test behavior on supported versions.
Source: Coding guidelines
4aa0f43 to
0755fcd
Compare
Summary
Fixes #2837. When serving with
ramalama serve --rag, the RAG proxy's streamingchat-completion path returned the SSE stream with
media_type="text/plain"insteadof
text/event-stream. Strict OpenAI-compatible clients (e.g. Open WebUI) requirecontent-type: text/event-streamfor"stream": trueresponses and reject thestream otherwise — the chat appears to hang and then fails with a decode error, even
though the model server underneath is generating tokens normally. Non-streaming
requests are unaffected (they correctly return
application/json).Fix
_stream_completionincontainer-images/scripts/rag_frameworkalready emits correctSSE framing (
data: {...}\n\nchunks terminated bydata: [DONE]\n\n); only theresponse media type was wrong. Set it to
text/event-streamto match the OpenAI ChatCompletions streaming contract so unmodified clients can consume the stream.
return StreamingResponse( generate(), - media_type="text/plain", + media_type="text/event-stream", headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}, )Assisted-by: Claude
🤖 Generated with Claude Code