Skip to content

Migrate RAG retrieval to OpenRAG, add runtime health checks and env-based config#906

Merged
Smartappli merged 1 commit into
masterfrom
retravailler-rag-a-partir-d-open-rag
May 10, 2026
Merged

Migrate RAG retrieval to OpenRAG, add runtime health checks and env-based config#906
Smartappli merged 1 commit into
masterfrom
retravailler-rag-a-partir-d-open-rag

Conversation

@Smartappli
Copy link
Copy Markdown
Owner

Motivation

  • Replace the previous Qdrant-centric hybrid retrieval plumbing with an OpenRAG-backed retrieval path to support OpenRAG deployments.
  • Provide runtime readiness checks so the RAG stack can report missing dependencies or configuration at startup.
  • Make Ollama/LLM configuration environment-driven so models and endpoints can be overridden via env vars.
  • Add unit tests for the new healthcheck and OpenRAG integration pieces.

Description

  • Add RAG/openrag_backend.py with OpenRAG integration, including a pinned minimum version check (MIN_OPENRAG_VERSION), a backward-compatible _search_openrag wrapper, and normalization to LangChain Document via _to_langchain_documents.
  • Add RAG/healthcheck.py exposing rag_runtime_health() and is_rag_runtime_ready() to report dependency and config readiness.
  • Update RAG/query.py to use openrag_hybrid_search instead of Qdrant, move Ollama model and base URL to environment-controlled defaults via RAG_LLM_MODEL and OLLAMA_BASE_URL, and keep the reranker logic intact.
  • Update RAG/scripts/rag_tools.py to use OpenRAG retrieval and the same env-driven Ollama config, and merge OMOP-inferred filters with structured-LLM filters in extract_filters.
  • Modify RAG/agent.py to read RAG_LLM_MODEL and OLLAMA_BASE_URL from the environment when constructing the ChatOllama client.
  • Add unit tests: RAG/tests/test_healthcheck.py and RAG/tests/test_openrag_backend.py covering health checks, minimum version pinning, search signature compatibility, and normalization logic.
  • Update pyproject.toml to add openrag>=0.4.1,<0.5.0 and packaging>=25.0 to dependencies.

Testing

  • Added and ran RAG/tests/test_healthcheck.py which verifies rag_runtime_health() shape and is_rag_runtime_ready() behavior; tests passed.
  • Added and ran RAG/tests/test_openrag_backend.py which validates version pinning, normalization (_to_langchain_documents), and _search_openrag signature compatibility; tests passed.
  • Executed the test suite with pytest for the modified modules and observed all new tests succeeding.

Codex Task

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

Warning

Rate limit exceeded

@Smartappli has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 41 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1c25ed91-2c2f-4b84-b833-c69310dc4933

📥 Commits

Reviewing files that changed from the base of the PR and between e8627e9 and f2f9612.

📒 Files selected for processing (8)
  • AIMER-ROOT/RAG/agent.py
  • AIMER-ROOT/RAG/healthcheck.py
  • AIMER-ROOT/RAG/openrag_backend.py
  • AIMER-ROOT/RAG/query.py
  • AIMER-ROOT/RAG/scripts/rag_tools.py
  • AIMER-ROOT/RAG/tests/test_healthcheck.py
  • AIMER-ROOT/RAG/tests/test_openrag_backend.py
  • AIMER-ROOT/pyproject.toml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch retravailler-rag-a-partir-d-open-rag

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Smartappli Smartappli merged commit a1d17ef into master May 10, 2026
10 of 21 checks passed
@Smartappli Smartappli deleted the retravailler-rag-a-partir-d-open-rag branch May 10, 2026 07:47
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request transitions the RAG system from a Qdrant-specific implementation to an OpenRAG-based backend. Key changes include the introduction of a new openrag_backend.py module for integration, a health check system for dependencies and configuration, and the refactoring of query tools to use the new backend. Feedback identifies a logic inconsistency where the health check requires an environment variable that the backend provides a default for. Additionally, suggestions were made to refine error handling in the retriever search wrapper to avoid masking bugs and to improve the merging logic for metadata filters to ensure clinical concepts are correctly combined.

"langchain_ollama_installed": find_spec("langchain_ollama") is not None,
"langchain_core_installed": find_spec("langchain_core") is not None,
"dotenv_installed": find_spec("dotenv") is not None,
"openrag_endpoint_set": bool(os.getenv("OPENRAG_ENDPOINT")),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a logic inconsistency between the health check and the backend implementation. The health check marks the system as not ready if OPENRAG_ENDPOINT is missing from the environment, but openrag_backend.py (line 97) provides a default value of http://localhost:8000. If the default is intended to be supported, the health check should be updated to allow it. If the environment variable is strictly required for production safety, the default in the backend should be removed to avoid misleading behavior.

Comment on lines +70 to +73
try:
return retriever.search(**params)
except TypeError:
continue
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Catching TypeError broadly here is risky as it can mask internal bugs within the retriever.search implementation (e.g., a TypeError raised deep inside the library logic) by incorrectly treating it as a signature mismatch. It is safer to check if the error specifically refers to unexpected keyword arguments.

Suggested change
try:
return retriever.search(**params)
except TypeError:
continue
try:
return retriever.search(**params)
except TypeError as exc:
if "unexpected keyword argument" in str(exc):
continue
raise

Comment on lines +49 to +50
for key, value in omop_filters.items():
llm_filters.setdefault(key, value)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using setdefault here prevents the merging of clinical concepts when both the LLM and the OMOP detection logic identify relevant metadata. Since these fields (like omop_condition_concept_ids) are lists of identifiers, they should be combined and de-duplicated to ensure maximum retrieval recall, rather than letting the LLM output silently override the deterministic OMOP extraction.

Suggested change
for key, value in omop_filters.items():
llm_filters.setdefault(key, value)
for key, value in omop_filters.items():
existing = llm_filters.get(key) or []
llm_filters[key] = sorted(set(existing) | set(value))

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f2f96120d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

and status["langchain_ollama_installed"]
and status["langchain_core_installed"]
and status["dotenv_installed"]
and status["openrag_endpoint_set"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove mandatory endpoint gate from runtime readiness

is_rag_runtime_ready() currently requires OPENRAG_ENDPOINT to be explicitly set, but openrag_hybrid_search() already provides a working default (http://localhost:8000). This creates a false-negative health state where the service is reported “not ready” even though retrieval can run, which can block startup/traffic in environments that rely on this readiness signal.

Useful? React with 👍 / 👎.

Comment on lines +71 to +73
return retriever.search(**params)
except TypeError:
continue
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve real search errors instead of masking as signature issues

The compatibility loop catches every TypeError from retriever.search(**params) and retries alternate signatures, but TypeError can also come from inside the search implementation (e.g., bad filter payload/type). In that case the original failure is swallowed and replaced by an “incompatible signature” runtime error, which misdiagnoses production failures and makes debugging much harder.

Useful? React with 👍 / 👎.

"dotenv_installed",
"openrag_endpoint_set",
}
assert set(status.keys()) == expected
"openrag_endpoint_set",
}
assert set(status.keys()) == expected
assert all(isinstance(value, bool) for value in status.values())


def test_is_rag_runtime_ready_returns_bool() -> None:
assert isinstance(is_rag_runtime_ready(), bool)

def test_rag_runtime_not_ready_without_endpoint(monkeypatch) -> None:
monkeypatch.delenv("OPENRAG_ENDPOINT", raising=False)
assert is_rag_runtime_ready() is False
try:
openrag_hybrid_search(query="test", k=3, filters={"doc_year": 2026})
except RuntimeError as exc:
assert "required" in str(exc)
assert docs[0].page_content == "alpha"
assert docs[0].metadata == {"a": 1}
assert docs[1].page_content == "beta"
assert docs[2].page_content == "gamma"


def test_minimum_openrag_version_is_pinned() -> None:
assert str(MIN_OPENRAG_VERSION) == "0.4.1"
def test_search_openrag_supports_top_k_metadata_filters_signature() -> None:
class DummyRetriever:
def search(self, **kwargs):
assert kwargs["top_k"] == 5
class DummyRetriever:
def search(self, **kwargs):
assert kwargs["top_k"] == 5
assert kwargs["metadata_filters"] == {"doc_year": 2026}
k=5,
filters={"doc_year": 2026},
)
assert result == [{"content": "ok"}]
@codacy-production
Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 14 high · 9 minor

Alerts:
⚠ 23 issues (≤ 0 issues of at least minor severity)

Results:
23 new issues

Category Results
Documentation 9 minor
Security 14 high

View in Codacy

🟢 Metrics 33 complexity

Metric Results
Complexity 33

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants