fix: add content when the RAG response is empty#461
Conversation
|
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:
📝 WalkthroughWalkthroughAdds fallback handling for empty model outputs after stripping source blocks. A shared constant ChangesEmpty Response Fallback Handling
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
openrag/routers/openai.py (1)
438-445:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMissing empty-content fallback for
/completionsendpoint.The
/chat/completionsendpoint (lines 368-369) now returns a fallback message whenclean_contentis empty after source stripping. The/completionsendpoint processes sources similarly (lines 438-440) but lacks the corresponding guard for emptyclean_text. If the LLM response consists solely of a[Sources: ...]tag, the client would receive an emptytextfield.If this asymmetry is intentional, consider adding a comment explaining why. Otherwise, apply the same fallback:
Proposed fix
filtered = filter_sources_by_citations(sources, citations) complete_response["extra"] = json.dumps({"sources": filtered}) log.debug("Returning completion response.") + if not clean_text.strip(): + complete_response["choices"][0]["text"] = "I do not have the necessary documentation in order to answer your message" return JSONResponse(content=complete_response)🤖 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 `@openrag/routers/openai.py` around lines 438 - 445, The /completions response path omits the empty-content fallback used in /chat/completions: after calling extract_and_strip_sources_block(text) you must guard against clean_text being empty and replace it with the same fallback message used for clean_content in the chat path; update the block handling complete_response (variables: text, clean_text, citations, complete_response) so that if clean_text == "" you set complete_response["choices"][0]["text"] to the fallback string before serializing extra sources via filter_sources_by_citations and returning the JSONResponse (keep using extract_and_strip_sources_block and filter_sources_by_citations).
🧹 Nitpick comments (1)
openrag/components/utils.py (1)
276-281: 💤 Low valueConsider extracting the fallback message to a shared constant.
The same fallback message string appears here and in
openrag/routers/openai.py:369. Defining it once (e.g., in this module or a shared constants file) would prevent drift if the wording is later updated.🤖 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 `@openrag/components/utils.py` around lines 276 - 281, Extract the repeated fallback string "I do not have the necessary documentation in order to answer your message" into a shared constant (e.g., FALLBACK_NO_DOCS_MESSAGE) and replace the inline literal in utils.py where _sse is yielded (inside the chunk_template branch that yields the default message) and in openrag/routers/openai.py at the location referenced (around line 369) to use that constant; ensure the constant is exported from a shared module or the utils module and imported where needed so both places reference the same symbol.
🤖 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.
Outside diff comments:
In `@openrag/routers/openai.py`:
- Around line 438-445: The /completions response path omits the empty-content
fallback used in /chat/completions: after calling
extract_and_strip_sources_block(text) you must guard against clean_text being
empty and replace it with the same fallback message used for clean_content in
the chat path; update the block handling complete_response (variables: text,
clean_text, citations, complete_response) so that if clean_text == "" you set
complete_response["choices"][0]["text"] to the fallback string before
serializing extra sources via filter_sources_by_citations and returning the
JSONResponse (keep using extract_and_strip_sources_block and
filter_sources_by_citations).
---
Nitpick comments:
In `@openrag/components/utils.py`:
- Around line 276-281: Extract the repeated fallback string "I do not have the
necessary documentation in order to answer your message" into a shared constant
(e.g., FALLBACK_NO_DOCS_MESSAGE) and replace the inline literal in utils.py
where _sse is yielded (inside the chunk_template branch that yields the default
message) and in openrag/routers/openai.py at the location referenced (around
line 369) to use that constant; ensure the constant is exported from a shared
module or the utils module and imported where needed so both places reference
the same symbol.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 403765fa-387a-45a8-be66-c8449c5b9089
📒 Files selected for processing (2)
openrag/components/utils.pyopenrag/routers/openai.py
c16efdb to
17a43de
Compare
| if chunk_template and not final_clean.strip(): | ||
| # Response was only a [Sources: ...] tag (or empty) — send a default | ||
| # message so the client never receives an empty completion. | ||
| yield _sse({"content": "I do not have the necessary documentation in order to answer your message"}) |
There was a problem hiding this comment.
This leaves internationalisation pretty tough.
There was a problem hiding this comment.
Agreed — suggest making this configurable (e.g. a Hydra llm.empty_response_message / env var) defaulting to the current string, so deployments can localize. The product already targets non-English users (WEBSEARCH_LANG defaults to fr-FR).
17a43de to
79aac85
Compare
79aac85 to
ba34c4c
Compare
| log.debug("Returning non-streaming completion chunk.") | ||
| if not clean_content.strip(): | ||
| log.warning("LLM and RAG response empty after source stripping, returning fallback message") | ||
| chunk["choices"][0]["message"]["content"] = EMPTY_RESPONSE_FALLBACK_MESSAGE |
There was a problem hiding this comment.
When the fallback fires, extra.sources is still populated (all sources if citations is None, or the cited ones if the reply was only a [Sources: ...] tag) — so the client gets "I do not have the necessary documentation" alongside a non-empty source list, which is contradictory. Consider clearing the sources here (and in the streaming / /completions paths), or softening the message.
ba34c4c to
1d22eaa
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
openrag/components/utils.py (1)
19-21: 💤 Low valueRemove orphaned comment.
This comment describing
EMPTY_RESPONSE_FALLBACK_MESSAGEis disconnected from both its definition (inprompts.py) and its usage (lines 284-288, which has inline comments). It disrupts the import → globals flow.Proposed fix
-# Sent to the client when the LLM produces no usable content (e.g. the whole -# response was a [Sources: ...] tag), so it never receives an empty completion. # Global variables🤖 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 `@openrag/components/utils.py` around lines 19 - 21, Remove the orphaned comment block at lines 19-21 that describes EMPTY_RESPONSE_FALLBACK_MESSAGE. This comment is disconnected from both the variable's definition in prompts.py and its usage later in the file at lines 284-288 (which already has inline comments), and it disrupts the import-to-globals flow in the file. Simply delete these three lines entirely.
🤖 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 `@openrag/components/utils.py`:
- Line 8: The import statement for EMPTY_RESPONSE_FALLBACK_MESSAGE uses a
fully-qualified path beginning with openrag.components.prompts.prompts while the
rest of the file uses bare import paths (e.g., components.indexer,
utils.logger). Change the import from the fully-qualified
openrag.components.prompts.prompts path to match the project convention by using
the bare path components.prompts.prompts instead, which will resolve the Ruff
I001 linting failure related to import style consistency.
---
Nitpick comments:
In `@openrag/components/utils.py`:
- Around line 19-21: Remove the orphaned comment block at lines 19-21 that
describes EMPTY_RESPONSE_FALLBACK_MESSAGE. This comment is disconnected from
both the variable's definition in prompts.py and its usage later in the file at
lines 284-288 (which already has inline comments), and it disrupts the
import-to-globals flow in the file. Simply delete these three lines entirely.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e5ad9bbb-0a6c-4ff1-9346-6e3fdab089df
📒 Files selected for processing (3)
openrag/components/prompts/prompts.pyopenrag/components/utils.pyopenrag/routers/openai.py
✅ Files skipped from review due to trivial changes (1)
- openrag/components/prompts/prompts.py
🚧 Files skipped from review as they are similar to previous changes (1)
- openrag/routers/openai.py
231cd69 to
1977169
Compare
…t-when-the-RAG-response-is-empty # Conflicts: # openrag/components/utils.py
1977169 to
0c03f03
Compare
Adding tests in open_ai_chat_completion() and streaming_with_source filtering that verify if the message sent by the llm has any text in it and if not, it had a generic text (I wrote something but it is just an exemple...) : I do not have the necessary documentation in order to answer your message
Summary by CodeRabbit