Skip to content

Feat/add OpenAI reranking - #288

Merged
Ahmath-Gadji merged 11 commits into
devfrom
feat/add_openai_reranking
Apr 2, 2026
Merged

Feat/add OpenAI reranking#288
Ahmath-Gadji merged 11 commits into
devfrom
feat/add_openai_reranking

Conversation

@Ahmath-Gadji

@Ahmath-Gadji Ahmath-Gadji commented Mar 17, 2026

Copy link
Copy Markdown
Collaborator

Refactor reranker into a multi-provider architecture

Replaces the single-file reranker with a factory pattern supporting multiple backends (Infinity and OpenAI-compatible endpoints). The provider is selected at runtime via configuration.

Changes:

  • Introduced BaseReranker, InfinityReranker, and OpenAIReranker classes under openrag/components/reranker/
  • Updated pipeline to use the new factory with improved debug logging
  • Added dedicated YAML configs per provider (.hydra_config/reranker/)
  • Updated docker-compose.yaml for dynamic provider selection; added extern/reranker/openai.yaml with GPU/CPU support
  • Moved RRF test to align with new module structure
  • Updated docs to reflect new env vars and provider options

Summary by CodeRabbit

  • New Features

    • Added OpenAI-compatible reranker provider; provider selectable at runtime.
    • The "openrag-all" chat profile is now the default.
  • Configuration

    • New env vars: RERANKER_PROVIDER (infinity|openai, default infinity), RERANKER_API_KEY, RERANKER_SEMAPHORE.
    • RERANKER_TOP_K default increased 5 → 10; reranker flag renamed to enabled.
    • Docker Compose now selects reranker fragment by provider and standardizes reranker ports/CLI args.
  • Documentation

    • Reranker docs updated with provider-specific setup, defaults, and ports.

@coderabbitai

coderabbitai Bot commented Mar 17, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds multi-provider reranker support: new BaseReranker, provider implementations (Infinity, OpenAI-compatible), factory selection, discriminated config/models, env-driven compose fragments, pipeline/UI wiring, docs and Docker compose updates.

Changes

Cohort / File(s) Summary
Compose & Quick Start
docker-compose.yaml, extern/reranker/infinity.yaml, extern/reranker/openai.yaml, quick_start/extern/infinity.yaml
Main compose now includes provider fragment via RERANKER_PROVIDER (default infinity); added openai.yaml; updated Infinity fragments to fix container port to 7997 and pass --api-key.
Documentation
docs/content/docs/documentation/env_vars.md
Documented RERANKER_PROVIDER (infinity
Config & Models
conf/config.yaml, openrag/config/loader.py, openrag/config/models.py
Replaced enableenabled, added provider, api_key, timeout, semaphore; loader env overrides updated and no longer derives base_url from RERANKER_PORT; models use discriminated union for provider-specific defaults.
Reranker Core & Factory
openrag/components/reranker/base.py, openrag/components/reranker/__init__.py
Added BaseReranker with abstract rerank() and static rrf_reranking(); added RerankerFactory.get_reranker(config) selecting provider by discriminator.
Provider Implementations
openrag/components/reranker/infinity.py, openrag/components/reranker/openai.py
Added InfinityReranker (Infinity client, semaphore, maps relevance_score) and OpenAIReranker (httpx async client to /rerank, semaphore, result mapping); both return reordered documents.
Pipeline, UI & Tests
openrag/components/pipeline.py, openrag/app_front.py, openrag/components/reranker/test_rrf_reranking.py
Pipeline now obtains reranker via RerankerFactory.get_reranker() and uses config.reranker.enabled; chat profiles mark the all partition model as default; tests use package-relative import for base.
Quick Config Fragments
extern/reranker/openai.yaml
New vLLM/OpenAI-compatible reranker fragment with healthcheck on port 8000, shared env anchors, GPU/CPU service variants and model/startup command including --api-key.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant ConfigLoader as Config Loader
    participant Factory as RerankerFactory
    participant Reranker as Reranker Impl
    participant External as External Reranker Service

    Client->>ConfigLoader: load settings (provider, api_key, semaphore, top_k)
    Client->>Factory: get_reranker(config)
    Factory->>Factory: select provider by config.reranker.provider
    Factory->>Reranker: instantiate InfinityReranker / OpenAIReranker
    Factory-->>Client: return BaseReranker instance

    Client->>Reranker: rerank(query, documents, top_k)
    Reranker->>Reranker: acquire semaphore
    Reranker->>External: API call (model, query, docs, top_n)
    External-->>Reranker: ranked indices & scores
    Reranker->>Reranker: map indices to Documents, set metadata["relevance_score"]
    Reranker-->>Client: return reranked documents
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through configs, ports, and keys,
Two rerankers now dance upon the breeze,
Semaphore taps and async heartbeats rhyme,
I nibbled defaults, picked a provider in time,
Hooray — more choices for the search-time!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Feat/add OpenAI reranking' directly reflects the main feature addition in this changeset: support for OpenAI-compatible reranker providers alongside the existing Infinity backend, implemented via a multi-provider factory pattern.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add_openai_reranking

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.

@Ahmath-Gadji Ahmath-Gadji added breaking-change Change of behavior after upgrade feat Add a new feature labels Mar 17, 2026
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from b9a9bbd to c4c3346 Compare March 17, 2026 14:44
@Ahmath-Gadji
Ahmath-Gadji marked this pull request as ready for review March 17, 2026 14:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
openrag/components/reranker/openai.py (1)

48-55: Prefer bare raise to preserve the original traceback.

Using raise e can subtly alter the traceback. Use bare raise instead.

-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` around lines 48 - 55, The except block
in the reranker method logs the exception but re-raises using "raise e", which
can alter the traceback; update the except handler that references logger,
self.model_name and documents (the block that logs "Reranking failed") to
re-raise the caught exception with a bare "raise" instead of "raise e" so the
original traceback is preserved.
openrag/components/reranker/infinity.py (1)

45-52: Prefer bare raise to preserve the original traceback.

-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/infinity.py` around lines 45 - 52, In the except
Exception as e block that logs reranking failures (the block referencing
logger.error with model_name=self.model_name and
documents_count=len(documents)), replace the current "raise e" with a bare
"raise" so the original traceback is preserved; keep the logger.error call and
exception variable for logging, but re-raise using "raise" instead of "raise e".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extern/reranker/openai.yaml`:
- Around line 17-20: The service listens on container port 8000 but the Docker
port mapping uses ${RERANKER_PORT:-8003}, causing mismatch when RERANKER_PORT is
overridden; update the OpenAI vLLM service command blocks in openai.yaml to
include a --port flag using the same variable (e.g., add --port
${RERANKER_PORT:-8003}) in both the main reranker command and the reranker-cpu
command so the container binds to the same overridable port used in the mapping
and Hydra URLs, ensuring port alignment across RERANKER_PORT, the command lines,
and the port mapping.

In `@openrag/components/reranker/infinity.py`:
- Line 7: Change the relative-style import to an absolute import from the
openrag package: replace the current import of get_logger in infinity.py with an
absolute import that references openrag.utils.logger (e.g., import get_logger
from openrag.utils.logger) so the symbol get_logger is imported via the
project's top-level package name per coding guidelines.

In `@openrag/components/reranker/openai.py`:
- Line 5: Replace the relative import of the logger used in openai.py: instead
of importing get_logger from a local/relative utils module, change it to use the
project-root absolute package import so get_logger is imported from the
top-level utils.logger package (i.e., the absolute openrag package path) to
comply with the coding guideline; update the import statement that currently
references utils.logger to the absolute package import for get_logger.
- Around line 27-38: The Async HTTP call to self.rerank_url using
httpx.AsyncClient.post has no timeout and can hang; update the reranker to set a
request timeout (either by adding a configurable attribute like self.timeout on
the reranker class and passing timeout=self.timeout to client.post, or by
constructing httpx.AsyncClient(timeout=...) / using httpx.Timeout) so the post
call to self.rerank_url will fail fast on slow/unresponsive services; ensure the
timeout value is used in the call site that invokes httpx.AsyncClient().post and
consider catching httpx.TimeoutException where appropriate.

In `@openrag/components/reranker/test_rrf_reranking.py`:
- Line 5: The test file uses a relative import for BaseReranker; change the
relative import to an absolute one so it imports BaseReranker from the package
root (use the full module path, e.g. import BaseReranker from
openrag.components.reranker.base) to comply with project import guidelines and
avoid relative import issues.

---

Nitpick comments:
In `@openrag/components/reranker/infinity.py`:
- Around line 45-52: In the except Exception as e block that logs reranking
failures (the block referencing logger.error with model_name=self.model_name and
documents_count=len(documents)), replace the current "raise e" with a bare
"raise" so the original traceback is preserved; keep the logger.error call and
exception variable for logging, but re-raise using "raise" instead of "raise e".

In `@openrag/components/reranker/openai.py`:
- Around line 48-55: The except block in the reranker method logs the exception
but re-raises using "raise e", which can alter the traceback; update the except
handler that references logger, self.model_name and documents (the block that
logs "Reranking failed") to re-raise the caught exception with a bare "raise"
instead of "raise e" so the original traceback is preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 30e4cae1-728d-4d4c-a208-50bebaee0198

📥 Commits

Reviewing files that changed from the base of the PR and between 896764e and c4c3346.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • .hydra_config/config.yaml
  • .hydra_config/reranker/base.yaml
  • .hydra_config/reranker/infinity.yaml
  • .hydra_config/reranker/openai.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
💤 Files with no reviewable changes (1)
  • openrag/components/reranker.py

Comment thread extern/reranker/openai.yaml
Comment thread openrag/components/reranker/infinity.py
Comment thread openrag/components/reranker/openai.py
Comment thread openrag/components/reranker/openai.py Outdated
Comment thread openrag/components/reranker/test_rrf_reranking.py
@Ahmath-Gadji
Ahmath-Gadji marked this pull request as draft March 23, 2026 15:35
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from c4c3346 to c254449 Compare March 24, 2026 09:52
@Ahmath-Gadji
Ahmath-Gadji marked this pull request as ready for review March 24, 2026 10:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
openrag/components/reranker/test_rrf_reranking.py (1)

5-5: ⚠️ Potential issue | 🟡 Minor

Use an absolute import for BaseReranker.

Line 5 uses a relative import; this should import from the openrag root package.

🔧 Proposed fix
-from .base import BaseReranker
+from openrag.components.reranker.base import BaseReranker

As per coding guidelines, **/*.py: Use absolute imports from the openrag/ directory (which is the Python path root).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/test_rrf_reranking.py` at line 5, Replace the
relative import in test_rrf_reranking.py with an absolute import from the
package root: change the `.base` import to import BaseReranker from
openrag.components.reranker.base so the file uses the project-root absolute
import (e.g., use openrag.components.reranker.base -> BaseReranker).
🧹 Nitpick comments (5)
openrag/app_front.py (1)

128-128: Avoid hardcoding the all-partitions model ID in default selection.

Line 128 hardcodes "openrag-all", while model IDs are prefix-driven elsewhere. If PARTITION_PREFIX changes, default profile selection will silently break.

♻️ Proposed change
-                    default=m.id == "openrag-all",
+                    default=m.id == f"{PARTITION_PREFIX}all",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/app_front.py` at line 128, Replace the hardcoded model id check
default=m.id == "openrag-all" with a construct that uses the PARTITION_PREFIX
constant so the default selection follows the current prefix; for example,
compare m.id to f"{PARTITION_PREFIX}-all" (or build it via PARTITION_PREFIX +
"-all") so the default logic uses the dynamic PARTITION_PREFIX and will not
break if the prefix changes.
openrag/components/reranker/openai.py (1)

56-56: Use bare raise to preserve original traceback.

raise e resets the traceback origin to this line. Use raise to preserve the full stack trace for debugging.

-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` at line 56, In the exception handler
inside openrag/components/reranker/openai.py (the block that currently does
"raise e"), replace the explicit re-raise with a bare "raise" to preserve the
original traceback; locate the try/except around the relevant function (e.g.,
the reranker/OpenAI call handler) and change "raise e" to "raise" so the full
stack trace is kept for debugging.
openrag/components/reranker/infinity.py (1)

52-52: Use bare raise to preserve original traceback.

raise e resets the traceback origin to this line. Use raise to preserve the full stack trace for debugging.

-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/infinity.py` at line 52, Replace the bare "raise
e" in the except block with a plain "raise" so the original traceback is
preserved; locate the occurrence of "raise e" in
openrag/components/reranker/infinity.py (the exception handling block where the
code currently does "raise e") and change it to "raise" without an exception
expression.
openrag/components/reranker/__init__.py (1)

13-14: Type hint dict conflicts with attribute-style access.

The parameter is typed as dict, but line 14 accesses config.reranker.get("provider") using attribute notation. Hydra/OmegaConf configs support this, but the type hint is misleading.

Suggested fix
+from omegaconf import DictConfig
+
 class RerankerFactory:
     `@staticmethod`
-    def get_reranker(config: dict) -> BaseReranker:
+    def get_reranker(config: DictConfig) -> BaseReranker:
         provider = config.reranker.get("provider")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/__init__.py` around lines 13 - 14, The function
get_reranker currently types its parameter as plain dict but uses
attribute-style access (config.reranker.get(...)); update the type hint to
reflect Hydra/OmegaConf usage (e.g., change the parameter type from dict to
omegaconf.DictConfig or typing.Any) and add the corresponding import (from
omegaconf import DictConfig) or use Any to silence type checkers so attribute
access on config and config.reranker is valid; keep the function name
get_reranker and return type BaseReranker unchanged.
openrag/components/reranker/base.py (1)

10-10: Improve type annotation for doc_lists parameter.

The parameter is typed as list[list] but should be list[list[Document]] to match the return type and usage.

-    def rrf_reranking(doc_lists: list[list], k: int = 60) -> list[Document]:
+    def rrf_reranking(doc_lists: list[list[Document]], k: int = 60) -> list[Document]:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/base.py` at line 10, The doc_lists parameter in
rrf_reranking is currently typed as list[list] which is too generic; update the
annotation to list[list[Document]] so it accurately reflects that each inner
list contains Document instances and matches the function's return type and
usage; modify the def rrf_reranking(doc_lists: list[list], k: int = 60) ->
list[Document]: signature to def rrf_reranking(doc_lists: list[list[Document]],
k: int = 60) -> list[Document]: and adjust any imports or forward references
(Document) if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.hydra_config/reranker/openai.yaml:
- Line 6: The base_url currently falls back to
"http://reranker:${oc.env:RERANKER_PORT, 8000}" which incorrectly derives the
in-container service port from RERANKER_PORT; update the fallback to a fixed
in-container address by changing the base_url entry to use
"http://reranker:8000" as the default so it no longer references RERANKER_PORT
(keep the RERANKER_BASE_URL env override as-is and remove the nested reference
to RERANKER_PORT).

In `@docs/content/docs/documentation/env_vars.md`:
- Around line 240-241: The docs incorrectly state that RERANKER_PORT controls
the service port used internally; update the RERANKER_PORT/RERANKER_BASE_URL
documentation to clarify provider-specific behavior: state that for the OpenAI
provider inter-container traffic uses the fixed internal address reranker:8000
and RERANKER_PORT only documents the host-side port mapping (not an override of
the container's internal port), and show that RERANKER_BASE_URL falls back only
to host:port when appropriate but OpenAI should still target reranker:8000
internally.

In `@extern/reranker/openai.yaml`:
- Around line 21-23: The healthcheck currently hardcodes port 8000 while the run
flag --port uses ${RERANKER_PORT:-8000}, causing a mismatch when RERANKER_PORT
is overridden; either remove the --port flag in the run command so vLLM stays on
its default 8000, or update the healthcheck test command (the healthcheck test:
["CMD", "curl", "-f", "http://localhost:8000/health"]) to reference the same
environment variable (e.g., using ${RERANKER_PORT:-8000}) so it matches the
--port setting; locate and edit the --port flag and the healthcheck test entries
to apply one of these fixes.

In `@openrag/components/pipeline.py`:
- Line 23: The import in pipeline.py uses a relative path; change the import of
reranker types to an absolute import from the package root: replace the relative
import that references BaseReranker and RerankerFactory with an absolute import
from the openrag package (import BaseReranker and RerankerFactory using the
openrag.reranker module names) so the file imports BaseReranker and
RerankerFactory via the package root rather than a relative module path.

In `@openrag/components/reranker/infinity.py`:
- Line 37: InfinityReranker currently makes an unbounded call to rerank.asyncio
using self.client; update the Client initialization for InfinityReranker to pass
httpx_args with a timeout (matching OpenAIReranker’s 60s) so calls like
rerank.asyncio(...) cannot hang indefinitely. Locate the Infinity client
construction (the class InfinityReranker and where Client(...) is instantiated)
and add httpx_args={"timeout": httpx.Timeout(60.0)} (or equivalent numeric
timeout) to the Client(...) call, ensuring imports/reference to httpx.Timeout
are present and used when calling rerank.asyncio via self.client.

---

Duplicate comments:
In `@openrag/components/reranker/test_rrf_reranking.py`:
- Line 5: Replace the relative import in test_rrf_reranking.py with an absolute
import from the package root: change the `.base` import to import BaseReranker
from openrag.components.reranker.base so the file uses the project-root absolute
import (e.g., use openrag.components.reranker.base -> BaseReranker).

---

Nitpick comments:
In `@openrag/app_front.py`:
- Line 128: Replace the hardcoded model id check default=m.id == "openrag-all"
with a construct that uses the PARTITION_PREFIX constant so the default
selection follows the current prefix; for example, compare m.id to
f"{PARTITION_PREFIX}-all" (or build it via PARTITION_PREFIX + "-all") so the
default logic uses the dynamic PARTITION_PREFIX and will not break if the prefix
changes.

In `@openrag/components/reranker/__init__.py`:
- Around line 13-14: The function get_reranker currently types its parameter as
plain dict but uses attribute-style access (config.reranker.get(...)); update
the type hint to reflect Hydra/OmegaConf usage (e.g., change the parameter type
from dict to omegaconf.DictConfig or typing.Any) and add the corresponding
import (from omegaconf import DictConfig) or use Any to silence type checkers so
attribute access on config and config.reranker is valid; keep the function name
get_reranker and return type BaseReranker unchanged.

In `@openrag/components/reranker/base.py`:
- Line 10: The doc_lists parameter in rrf_reranking is currently typed as
list[list] which is too generic; update the annotation to list[list[Document]]
so it accurately reflects that each inner list contains Document instances and
matches the function's return type and usage; modify the def
rrf_reranking(doc_lists: list[list], k: int = 60) -> list[Document]: signature
to def rrf_reranking(doc_lists: list[list[Document]], k: int = 60) ->
list[Document]: and adjust any imports or forward references (Document) if
needed.

In `@openrag/components/reranker/infinity.py`:
- Line 52: Replace the bare "raise e" in the except block with a plain "raise"
so the original traceback is preserved; locate the occurrence of "raise e" in
openrag/components/reranker/infinity.py (the exception handling block where the
code currently does "raise e") and change it to "raise" without an exception
expression.

In `@openrag/components/reranker/openai.py`:
- Line 56: In the exception handler inside openrag/components/reranker/openai.py
(the block that currently does "raise e"), replace the explicit re-raise with a
bare "raise" to preserve the original traceback; locate the try/except around
the relevant function (e.g., the reranker/OpenAI call handler) and change "raise
e" to "raise" so the full stack trace is kept for debugging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 80e4f456-6993-4a32-b4cc-ddad1d49e13c

📥 Commits

Reviewing files that changed from the base of the PR and between 1a0f643 and c254449.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • .hydra_config/config.yaml
  • .hydra_config/reranker/base.yaml
  • .hydra_config/reranker/infinity.yaml
  • .hydra_config/reranker/openai.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
💤 Files with no reviewable changes (1)
  • openrag/components/reranker.py

Comment thread .hydra_config/reranker/openai.yaml Outdated
Comment thread docs/content/docs/documentation/env_vars.md Outdated
Comment thread extern/reranker/openai.yaml Outdated
Comment thread openrag/components/pipeline.py
Comment thread openrag/components/reranker/infinity.py
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from c254449 to c85b13d Compare March 24, 2026 11:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (3)
openrag/components/reranker/infinity.py (1)

7-7: 🛠️ Refactor suggestion | 🟠 Major

Use absolute import from openrag/ directory.

Per coding guidelines, imports should use absolute paths from the openrag/ directory.

-from utils.logger import get_logger
+from openrag.utils.logger import get_logger

As per coding guidelines, **/*.py: Use absolute imports from the openrag/ directory (which is the Python path root).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/infinity.py` at line 7, The import in infinity.py
is using a relative/non-absolute path; update the import to use the absolute
package path rooted at openrag (e.g., replace the current "from utils.logger
import get_logger" with the absolute import from openrag, such as "from
openrag.utils.logger import get_logger") so that the module resolution follows
the project guideline; ensure you update any other imports in this file that
reference utils or sibling packages to the openrag.* namespace as needed.
openrag/components/pipeline.py (1)

23-23: 🛠️ Refactor suggestion | 🟠 Major

Use absolute import for reranker types/factory.

Line 23 uses a relative import which violates coding guidelines. Should import from the openrag package root.

-from .reranker import BaseReranker, RerankerFactory
+from openrag.components.reranker import BaseReranker, RerankerFactory

As per coding guidelines, **/*.py: Use absolute imports from the openrag/ directory (which is the Python path root).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/pipeline.py` at line 23, Replace the relative import in
pipeline.py with an absolute import from the package root: change the statement
that imports BaseReranker and RerankerFactory (currently "from .reranker import
BaseReranker, RerankerFactory") to import them from openrag.reranker instead;
update any references if necessary so functions/classes that use BaseReranker
and RerankerFactory continue to resolve via the new absolute import.
openrag/components/reranker/openai.py (1)

5-5: 🛠️ Refactor suggestion | 🟠 Major

Use absolute import from openrag/ directory.

Per coding guidelines, imports should use absolute paths from the openrag/ directory.

-from utils.logger import get_logger
+from openrag.utils.logger import get_logger

As per coding guidelines, **/*.py: Use absolute imports from the openrag/ directory (which is the Python path root).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` at line 5, The import in
openrag/components/reranker/openai.py currently uses a non-absolute module path
("from utils.logger import get_logger"); update it to use an absolute import
rooted at the project package (replace the relative-style import with the
absolute path starting with openrag, e.g. import the get_logger from
openrag.utils.logger) so it follows the repository's absolute-import guideline.
🧹 Nitpick comments (2)
openrag/components/reranker/infinity.py (1)

49-56: Use bare raise to preserve full traceback.

Same as OpenAIReranker - use bare raise instead of raise e.

♻️ Minor improvement
             except Exception as e:
                 logger.error(
                     "Reranking failed",
                     error=str(e),
                     model_name=self.model_name,
                     documents_count=len(documents),
                 )
-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/infinity.py` around lines 49 - 56, The except
block in the reranker (the try/except that logs "Reranking failed" using logger
with model_name=self.model_name and documents_count=len(documents)) currently
does "raise e", which drops the original traceback; change it to a bare "raise"
so the original exception context/traceback is preserved after logging, keeping
the same logger.error call and fields.
openrag/components/reranker/openai.py (1)

49-56: Use bare raise to preserve full traceback.

Using raise e instead of bare raise can truncate the traceback in some Python versions.

♻️ Minor improvement
             except Exception as e:
                 logger.error(
                     "Reranking failed",
                     error=str(e),
                     model_name=self.model_name,
                     documents_count=len(documents),
                 )
-                raise e
+                raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` around lines 49 - 56, In the exception
handler inside the reranker method (the except Exception as e block that logs
"Reranking failed" and references self.model_name and len(documents)), replace
the explicit re-raise "raise e" with a bare "raise" so the original traceback is
preserved; keep the logger.error call as-is and only change the re-raise to bare
raise to maintain full exception context.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@openrag/components/pipeline.py`:
- Line 23: Replace the relative import in pipeline.py with an absolute import
from the package root: change the statement that imports BaseReranker and
RerankerFactory (currently "from .reranker import BaseReranker,
RerankerFactory") to import them from openrag.reranker instead; update any
references if necessary so functions/classes that use BaseReranker and
RerankerFactory continue to resolve via the new absolute import.

In `@openrag/components/reranker/infinity.py`:
- Line 7: The import in infinity.py is using a relative/non-absolute path;
update the import to use the absolute package path rooted at openrag (e.g.,
replace the current "from utils.logger import get_logger" with the absolute
import from openrag, such as "from openrag.utils.logger import get_logger") so
that the module resolution follows the project guideline; ensure you update any
other imports in this file that reference utils or sibling packages to the
openrag.* namespace as needed.

In `@openrag/components/reranker/openai.py`:
- Line 5: The import in openrag/components/reranker/openai.py currently uses a
non-absolute module path ("from utils.logger import get_logger"); update it to
use an absolute import rooted at the project package (replace the relative-style
import with the absolute path starting with openrag, e.g. import the get_logger
from openrag.utils.logger) so it follows the repository's absolute-import
guideline.

---

Nitpick comments:
In `@openrag/components/reranker/infinity.py`:
- Around line 49-56: The except block in the reranker (the try/except that logs
"Reranking failed" using logger with model_name=self.model_name and
documents_count=len(documents)) currently does "raise e", which drops the
original traceback; change it to a bare "raise" so the original exception
context/traceback is preserved after logging, keeping the same logger.error call
and fields.

In `@openrag/components/reranker/openai.py`:
- Around line 49-56: In the exception handler inside the reranker method (the
except Exception as e block that logs "Reranking failed" and references
self.model_name and len(documents)), replace the explicit re-raise "raise e"
with a bare "raise" so the original traceback is preserved; keep the
logger.error call as-is and only change the re-raise to bare raise to maintain
full exception context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d11f8a4d-bebd-4cca-9b23-cdadac500c97

📥 Commits

Reviewing files that changed from the base of the PR and between c254449 and c85b13d.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • .hydra_config/config.yaml
  • .hydra_config/reranker/base.yaml
  • .hydra_config/reranker/infinity.yaml
  • .hydra_config/reranker/openai.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
  • quick_start/extern/infinity.yaml
💤 Files with no reviewable changes (1)
  • openrag/components/reranker.py
✅ Files skipped from review due to trivial changes (4)
  • .hydra_config/reranker/openai.yaml
  • openrag/components/reranker/test_rrf_reranking.py
  • .hydra_config/config.yaml
  • .hydra_config/reranker/base.yaml
🚧 Files skipped from review as they are similar to previous changes (4)
  • .hydra_config/reranker/infinity.yaml
  • openrag/components/reranker/init.py
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/openai.yaml

@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from be7afb2 to 96dd7e5 Compare March 31, 2026 09:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
openrag/components/reranker/openai.py (1)

16-17: Consider validating that base_url is non-empty.

If config.reranker.base_url is missing or empty, rerank_url becomes /rerank, which will fail at runtime. While the Hydra config should always provide a default, adding a guard or logging a warning would improve debuggability.

🛡️ Optional defensive check
         base_url = config.reranker.get("base_url", "").rstrip("/")
+        if not base_url:
+            logger.warning("base_url is empty; reranker requests will fail")
         self.rerank_url = f"{base_url}/rerank"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` around lines 16 - 17, The code sets
base_url = config.reranker.get("base_url", "").rstrip("/") and then
self.rerank_url = f"{base_url}/rerank" without checking for an empty base_url;
add a guard in the initializer that checks if base_url is falsy and either (a)
raise a clear error (e.g., ValueError/RuntimeError) indicating
config.reranker.base_url is required, or (b) log a warning and disable the
reranker by not setting self.rerank_url (or setting it to None). Update the code
paths that use self.rerank_url to handle the None/disabled state accordingly;
reference the symbols base_url and self.rerank_url in
openrag/components/reranker/openai.py when making the change.
docs/content/docs/documentation/env_vars.md (1)

238-249: Consider clarifying that RERANKER_BASE_URL default depends on the selected provider.

The table shows RERANKER_BASE_URL defaulting to http://reranker:7997, but the "Reranker Providers" section indicates OpenAI-compatible endpoints use port 8000. Users switching to openai provider need to also set RERANKER_BASE_URL=http://reranker:8000 (or the appropriate endpoint).

A brief note or example showing the typical configuration for each provider would help avoid misconfiguration.

📝 Suggested clarification
 | `RERANKER_BASE_URL` | `str` | `http://reranker:7997` | Base URL of the reranker service |
+
+> **Note:** The default `RERANKER_BASE_URL` is configured for the Infinity provider. When using `RERANKER_PROVIDER=openai`, set `RERANKER_BASE_URL=http://reranker:8000` (or your OpenAI-compatible endpoint).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/documentation/env_vars.md` around lines 238 - 249, Update
the RERANKER_BASE_URL documentation to clarify that its default host/port
depends on RERANKER_PROVIDER; mention that when RERANKER_PROVIDER=infinity the
typical default is http://reranker:7997 and when RERANKER_PROVIDER=openai the
typical default is http://reranker:8000, and remind users to set
RERANKER_API_KEY when using the openai provider; add a short note or example
mapping next to the RERANKER_BASE_URL row and/or under the "Reranker Providers"
section so readers know which base URL to use per provider.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/content/docs/documentation/env_vars.md`:
- Around line 238-249: Update the RERANKER_BASE_URL documentation to clarify
that its default host/port depends on RERANKER_PROVIDER; mention that when
RERANKER_PROVIDER=infinity the typical default is http://reranker:7997 and when
RERANKER_PROVIDER=openai the typical default is http://reranker:8000, and remind
users to set RERANKER_API_KEY when using the openai provider; add a short note
or example mapping next to the RERANKER_BASE_URL row and/or under the "Reranker
Providers" section so readers know which base URL to use per provider.

In `@openrag/components/reranker/openai.py`:
- Around line 16-17: The code sets base_url = config.reranker.get("base_url",
"").rstrip("/") and then self.rerank_url = f"{base_url}/rerank" without checking
for an empty base_url; add a guard in the initializer that checks if base_url is
falsy and either (a) raise a clear error (e.g., ValueError/RuntimeError)
indicating config.reranker.base_url is required, or (b) log a warning and
disable the reranker by not setting self.rerank_url (or setting it to None).
Update the code paths that use self.rerank_url to handle the None/disabled state
accordingly; reference the symbols base_url and self.rerank_url in
openrag/components/reranker/openai.py when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: abfb09a3-21f0-421d-9ea3-87beb3471044

📥 Commits

Reviewing files that changed from the base of the PR and between be7afb2 and 96dd7e5.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • .hydra_config/config.yaml
  • .hydra_config/reranker/base.yaml
  • .hydra_config/reranker/infinity.yaml
  • .hydra_config/reranker/openai.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
  • quick_start/extern/infinity.yaml
💤 Files with no reviewable changes (1)
  • openrag/components/reranker.py
✅ Files skipped from review due to trivial changes (5)
  • openrag/components/reranker/test_rrf_reranking.py
  • .hydra_config/reranker/openai.yaml
  • openrag/components/pipeline.py
  • .hydra_config/reranker/base.yaml
  • extern/reranker/openai.yaml
🚧 Files skipped from review as they are similar to previous changes (7)
  • .hydra_config/reranker/infinity.yaml
  • docker-compose.yaml
  • openrag/components/reranker/init.py
  • quick_start/extern/infinity.yaml
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/app_front.py

@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from 96dd7e5 to c5a9a33 Compare April 1, 2026 15:27

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
docs/content/docs/documentation/env_vars.md (1)

234-242: Consider documenting RERANKER_TIMEOUT.

The PR objectives mention that RERANKER_TIMEOUT was added to make the OpenAI reranker respect the configured timeout (fixing a hardcoded timeout=60.0 issue). However, this variable is not documented in the environment variables table.

If RERANKER_TIMEOUT is now a supported configuration option, consider adding it to the documentation table alongside RERANKER_SEMAPHORE.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/documentation/env_vars.md` around lines 234 - 242, Add a
new row for the environment variable RERANKER_TIMEOUT to the environment
variables table so the docs reflect the new configuration; document its name
`RERANKER_TIMEOUT`, type `float` (or `int` if preferred by implementation), a
sensible default (e.g., `60.0` or the actual default used in code), and a short
description like "Timeout in seconds for reranker requests (applies to OpenAI
provider)"; place this entry next to `RERANKER_SEMAPHORE` so users can discover
timeout and concurrency settings together.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openrag/components/pipeline.py`:
- Line 54: The debug call is accessing a non-existent attribute
config.reranker.provider which will raise AttributeError because RerankerConfig
lacks a provider field; fix by changing the logger.debug call in pipeline.py to
use the safe dict access used elsewhere (config.reranker.get("provider")) or
alternatively add provider: str to the RerankerConfig model in
openrag/config/models.py so config.reranker.provider becomes valid; update the
logger.debug invocation (and any similar accesses) to use the chosen approach.
- Line 52: The code reads config.reranker.get("enabled", True) but
RerankerConfig exposes the flag as "enable", so change the lookup in the
Pipeline initializer to use config.reranker.get("enable", True) (or otherwise
read RerankerConfig.enable directly) so self.reranker_enabled correctly reflects
the configured value; update any related references where config.reranker is
accessed to use the "enable" key or the RerankerConfig attribute.

In `@openrag/components/reranker/openai.py`:
- Around line 14-15: Add an api_key field to the RerankerConfig model and ensure
OpenAIReranker reads it correctly; specifically, update the RerankerConfig
definition to include api_key (string, optional or required per project rules)
and then change OpenAIReranker to pull the key from the config object (e.g., use
config.reranker.api_key or the corresponding dict key consistently) so
config.reranker["api_key"] no longer raises a KeyError; also replace the
relative import from utils.logger with the absolute import from
openrag.utils.logger (references: RerankerConfig, OpenAIReranker, get_logger).

---

Nitpick comments:
In `@docs/content/docs/documentation/env_vars.md`:
- Around line 234-242: Add a new row for the environment variable
RERANKER_TIMEOUT to the environment variables table so the docs reflect the new
configuration; document its name `RERANKER_TIMEOUT`, type `float` (or `int` if
preferred by implementation), a sensible default (e.g., `60.0` or the actual
default used in code), and a short description like "Timeout in seconds for
reranker requests (applies to OpenAI provider)"; place this entry next to
`RERANKER_SEMAPHORE` so users can discover timeout and concurrency settings
together.
🪄 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: c6ad371f-b875-43f8-acd0-42769e1d00f9

📥 Commits

Reviewing files that changed from the base of the PR and between 96dd7e5 and c5a9a33.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
  • quick_start/extern/infinity.yaml
✅ Files skipped from review due to trivial changes (5)
  • openrag/components/reranker/test_rrf_reranking.py
  • openrag/components/reranker/init.py
  • quick_start/extern/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/components/reranker/infinity.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • extern/reranker/infinity.yaml
  • openrag/app_front.py
  • docker-compose.yaml

Comment thread openrag/components/pipeline.py Outdated
Comment thread openrag/components/pipeline.py
Comment thread openrag/components/reranker/openai.py Outdated
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from c5a9a33 to f26e505 Compare April 1, 2026 15:48
BREAKING CHANGE: docker-compose.yaml now includes
`extern/reranker/${RERANKER_PROVIDER:-infinity}.yaml` instead of
`extern/infinity.yaml`. Set RERANKER_PROVIDER=infinity or leave unset
to preserve existing behavior.

Add OpenAI-compatible reranker provider selectable via RERANKER_PROVIDER
(values: `infinity`, `openai`). New env vars: RERANKER_API_KEY, RERANKER_SEMAPHORE.
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch 2 times, most recently from a3deac5 to 3e13b30 Compare April 1, 2026 16:01
@Ahmath-Gadji
Ahmath-Gadji force-pushed the feat/add_openai_reranking branch from 3e13b30 to 4ffafee Compare April 1, 2026 16:32
Make BaseReranker an abstract class with @AbstractMethod so missing
implementations are caught at instantiation. Fix rrf_reranking type
hint from list[list] to list[list[Document]].
Use dot notation consistently across InfinityReranker and pipeline.py,
matching the style in OpenAIReranker. Remove redundant .get() fallbacks
that duplicated (and in the case of semaphore, contradicted) Pydantic
model defaults.
Each provider config now has its own correct base_url default
(Infinity: http://reranker:7997, OpenAI: http://reranker:8000/v1),
so the port-based URL construction is no longer needed and would
produce wrong URLs for the OpenAI provider.
Create the client once in __init__ instead of per rerank() call so
connection pooling is preserved.
Only import the selected provider so a missing optional dependency
(e.g. infinity_client) doesn't break the other provider.
@EnjoyBacon7

Copy link
Copy Markdown
Collaborator

@CodeRabbit final review please

@EnjoyBacon7

Copy link
Copy Markdown
Collaborator

Pleaaaase @CodeRabbit, do the review pretty please

@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown

@EnjoyBacon7 Sure! Triggering a full review of the PR now. 🐇

✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown

@EnjoyBacon7 Of course! Triggering a full review of the PR right away! 🐇

✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
openrag/components/reranker/openai.py (1)

5-7: ⚠️ Potential issue | 🟡 Minor

Use absolute imports for project modules.

utils.logger and .base should both be imported from the openrag package root here.

♻️ Suggested fix
-from utils.logger import get_logger
-
-from .base import BaseReranker
+from openrag.components.reranker.base import BaseReranker
+from openrag.utils.logger import get_logger

As per coding guidelines, "Use absolute imports from the openrag/ directory (which is the Python path root)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` around lines 5 - 7, The imports in
openrag/components/reranker/openai.py use relative/project-root-escaping forms;
replace from utils.logger import get_logger and from .base import BaseReranker
with absolute imports from the openrag package (e.g., import get_logger from
openrag.utils.logger and BaseReranker from openrag.components.reranker.base or
the appropriate openrag path) so that get_logger and BaseReranker are imported
via absolute module paths consistent with the project's import guidelines.
openrag/components/reranker/infinity.py (1)

7-9: ⚠️ Potential issue | 🟡 Minor

Use absolute imports for project modules.

utils.logger and .base should both be imported from the openrag package root here.

♻️ Suggested fix
-from utils.logger import get_logger
-
-from .base import BaseReranker
+from openrag.components.reranker.base import BaseReranker
+from openrag.utils.logger import get_logger

As per coding guidelines, "Use absolute imports from the openrag/ directory (which is the Python path root)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/infinity.py` around lines 7 - 9, Replace
relative/local imports with absolute imports from the openrag package root:
change "from utils.logger import get_logger" to "from openrag.utils.logger
import get_logger" and change "from .base import BaseReranker" to "from
openrag.components.reranker.base import BaseReranker" so the module uses
absolute project-root imports; update any other similar imports in this file to
match the same pattern.
🧹 Nitpick comments (3)
docs/content/docs/documentation/env_vars.md (1)

240-249: Consider clarifying provider-specific RERANKER_BASE_URL defaults.

The table mentions default ports per provider (7997 for Infinity, 8000 for OpenAI), but RERANKER_BASE_URL shows only http://reranker:7997. Consider updating the description to note that the default URL depends on the selected provider, or that users should set RERANKER_BASE_URL to http://reranker:8000 when using the openai provider.

📝 Suggested clarification
-| `RERANKER_BASE_URL` | `str` | `http://reranker:7997` | Base URL of the reranker service |
+| `RERANKER_BASE_URL` | `str` | `http://reranker:<port>` | Base URL of the reranker service. Default port is `7997` for Infinity, `8000` for OpenAI |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/documentation/env_vars.md` around lines 240 - 249, Update
the RERANKER_BASE_URL documentation to clarify provider-specific defaults:
mention that when RERANKER_PROVIDER is set to "infinity" the typical default is
http://reranker:7997, whereas for "openai" users should typically set
RERANKER_BASE_URL to http://reranker:8000 (or an OpenAI-compatible endpoint),
and add a short note referencing RERANKER_PROVIDER and RERANKER_API_KEY so
readers know to change the base URL when switching providers.
conf/config.yaml (1)

69-78: Update the env-var comment to include new variables.

The comment on line 69 lists RERANKER_ENABLED, RERANKER_MODEL, RERANKER_TOP_K, RERANKER_BASE_URL, RERANKER_PORT but is missing the newly added RERANKER_PROVIDER, RERANKER_API_KEY, RERANKER_TIMEOUT, and RERANKER_SEMAPHORE.

 # --- Reranker ---
-# Env: RERANKER_ENABLED, RERANKER_MODEL, RERANKER_TOP_K, RERANKER_BASE_URL, RERANKER_PORT
+# Env: RERANKER_PROVIDER, RERANKER_ENABLED, RERANKER_MODEL, RERANKER_TOP_K, RERANKER_BASE_URL, RERANKER_API_KEY, RERANKER_TIMEOUT, RERANKER_SEMAPHORE
 reranker:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@conf/config.yaml` around lines 69 - 78, Update the environment-variable
comment above the reranker block so it lists all current env vars: include
RERANKER_PROVIDER, RERANKER_API_KEY, RERANKER_TIMEOUT, and RERANKER_SEMAPHORE in
addition to the existing RERANKER_ENABLED, RERANKER_MODEL, RERANKER_TOP_K,
RERANKER_BASE_URL, and RERANKER_PORT to reflect the keys present in the reranker
config (provider, api_key, timeout, semaphore, model_name, top_k, base_url,
enabled).
openrag/components/reranker/openai.py (1)

19-21: Expose a shutdown path for the shared AsyncClient.

This class owns a long-lived httpx.AsyncClient but never closes it. HTTPX recommends either using async with or explicitly calling aclose(); otherwise connections stay open and can leak when reranker instances are recreated. Add an aclose() method here and invoke it from the app shutdown path. (python-httpx.org)

🛠️ Suggested fix
 class OpenAIReranker(BaseReranker):
     def __init__(self, config):
         self.model_name = config.reranker.model_name
         base_url = config.reranker.base_url.rstrip("/")
         self.rerank_url = f"{base_url}/rerank"
         self.semaphore = asyncio.Semaphore(config.reranker.semaphore)
         self.timeout = config.reranker.timeout
         self.client = httpx.AsyncClient(
             headers={"Authorization": f"Bearer {config.reranker.api_key}"},
         )
         logger.debug("OpenAI Reranker initialized", model_name=self.model_name)
+
+    async def aclose(self) -> None:
+        await self.client.aclose()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/components/reranker/openai.py` around lines 19 - 21, The shared
httpx.AsyncClient created in the Reranker class (self.client in
openrag.components.reranker.openai) is never closed; add an async teardown
method (e.g., async def aclose(self): await self.client.aclose()) on the class
that explicitly calls the client's aclose(), and ensure the application's
shutdown path invokes this method for the reranker instance so connections are
properly closed and not leaked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extern/reranker/openai.yaml`:
- Around line 40-41: Remove the non-standard empty-string profiles block from
the reranker-gpu service (i.e., delete the profiles: - "" entry under the
reranker-gpu service), leaving reranker-gpu without any profiles so it is
enabled by default; ensure only reranker-cpu retains the profiles: ["cpu"] entry
to keep it conditional.

In `@openrag/components/reranker/__init__.py`:
- Around line 1-17: The module uses relative imports; change them to absolute
imports from the package root: import BaseReranker with "from
openrag.components.reranker.base import BaseReranker" and inside
RerankerFactory.get_reranker replace "from .infinity import InfinityReranker"
with "from openrag.components.reranker.infinity import InfinityReranker" and
"from .openai import OpenAIReranker" with "from
openrag.components.reranker.openai import OpenAIReranker" so all imports are
absolute while retaining the same factory logic in RerankerFactory.get_reranker.

In `@openrag/config/models.py`:
- Around line 148-150: Create a callable helper named _default_reranker_config
that returns a concrete instance of the union (e.g., an OpenAIRerankerConfig or
InfinityRerankerConfig) and use it as the Field default_factory for the reranker
field; specifically add a function _default_reranker_config() -> RerankerConfig
that constructs and returns a sensible default (for example
OpenAIRerankerConfig(provider="openai", ...) or the project's preferred default)
and then change the reranker annotation to reranker: RerankerConfig =
Field(default_factory=_default_reranker_config) so Pydantic receives a callable
that returns an instance.

---

Duplicate comments:
In `@openrag/components/reranker/infinity.py`:
- Around line 7-9: Replace relative/local imports with absolute imports from the
openrag package root: change "from utils.logger import get_logger" to "from
openrag.utils.logger import get_logger" and change "from .base import
BaseReranker" to "from openrag.components.reranker.base import BaseReranker" so
the module uses absolute project-root imports; update any other similar imports
in this file to match the same pattern.

In `@openrag/components/reranker/openai.py`:
- Around line 5-7: The imports in openrag/components/reranker/openai.py use
relative/project-root-escaping forms; replace from utils.logger import
get_logger and from .base import BaseReranker with absolute imports from the
openrag package (e.g., import get_logger from openrag.utils.logger and
BaseReranker from openrag.components.reranker.base or the appropriate openrag
path) so that get_logger and BaseReranker are imported via absolute module paths
consistent with the project's import guidelines.

---

Nitpick comments:
In `@conf/config.yaml`:
- Around line 69-78: Update the environment-variable comment above the reranker
block so it lists all current env vars: include RERANKER_PROVIDER,
RERANKER_API_KEY, RERANKER_TIMEOUT, and RERANKER_SEMAPHORE in addition to the
existing RERANKER_ENABLED, RERANKER_MODEL, RERANKER_TOP_K, RERANKER_BASE_URL,
and RERANKER_PORT to reflect the keys present in the reranker config (provider,
api_key, timeout, semaphore, model_name, top_k, base_url, enabled).

In `@docs/content/docs/documentation/env_vars.md`:
- Around line 240-249: Update the RERANKER_BASE_URL documentation to clarify
provider-specific defaults: mention that when RERANKER_PROVIDER is set to
"infinity" the typical default is http://reranker:7997, whereas for "openai"
users should typically set RERANKER_BASE_URL to http://reranker:8000 (or an
OpenAI-compatible endpoint), and add a short note referencing RERANKER_PROVIDER
and RERANKER_API_KEY so readers know to change the base URL when switching
providers.

In `@openrag/components/reranker/openai.py`:
- Around line 19-21: The shared httpx.AsyncClient created in the Reranker class
(self.client in openrag.components.reranker.openai) is never closed; add an
async teardown method (e.g., async def aclose(self): await self.client.aclose())
on the class that explicitly calls the client's aclose(), and ensure the
application's shutdown path invokes this method for the reranker instance so
connections are properly closed and not leaked.
🪄 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: d2dc0f52-2069-458e-83e0-503e41bc32b1

📥 Commits

Reviewing files that changed from the base of the PR and between 651902c and 905be0a.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • conf/config.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
  • openrag/config/loader.py
  • openrag/config/models.py
  • quick_start/extern/infinity.yaml

Comment thread extern/reranker/openai.yaml
Comment thread openrag/components/reranker/__init__.py
Comment thread openrag/config/models.py
@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
openrag/config/models.py (1)

148-151: ⚠️ Potential issue | 🔴 Critical

RerankerConfig is not a valid default_factory.

Settings.reranker still uses Field(default_factory=RerankerConfig) on Line 483, but this symbol is now an Annotated[...] union alias rather than a concrete config class. That breaks the documented “load defaults when config is missing” path in load_config(). Please switch the factory to a helper that returns a concrete provider config, e.g. InfinityRerankerConfig().

Required fix
 RerankerConfig = Annotated[
     InfinityRerankerConfig | OpenAIRerankerConfig,
     Field(discriminator="provider"),
 ]
+
+def _default_reranker_config() -> InfinityRerankerConfig:
+    return InfinityRerankerConfig()

Then update Line 483 to:

reranker: RerankerConfig = Field(default_factory=_default_reranker_config)
#!/bin/bash
set -euo pipefail

python - <<'PY'
from typing import Annotated

class A: ...
class B: ...

T = Annotated[A | B, "provider"]
try:
    T()
except Exception as exc:
    print(type(exc).__name__, exc)
PY

rg -n 'RerankerConfig = Annotated|default_factory=RerankerConfig' openrag/config/models.py
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/config/models.py` around lines 148 - 151, The default_factory
currently points to the Annotated union alias RerankerConfig which is not
callable; add a small helper function named like _default_reranker_config that
returns a concrete config instance (e.g. return InfinityRerankerConfig()) and
then change the Settings.reranker Field to use
Field(default_factory=_default_reranker_config) so missing configs load the
concrete default; reference RerankerConfig for typing but use
_default_reranker_config and InfinityRerankerConfig for the actual factory.
🧹 Nitpick comments (1)
openrag/app_front.py (1)

128-128: Use the PARTITION_PREFIX constant instead of hardcoding "openrag-all".

The backend constructs this model ID as f"{PARTITION_PREFIX}all" (see openrag/routers/openai.py lines 103-110). Using the same pattern here ensures consistency and avoids silent failures if the prefix ever changes.

♻️ Suggested fix
-                    default=m.id == "openrag-all",
+                    default=m.id == f"{PARTITION_PREFIX}all",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/app_front.py` at line 128, Replace the hardcoded model id check
default=m.id == "openrag-all" with the partition-aware constant by using the
PARTITION_PREFIX constant (e.g. default=m.id == f"{PARTITION_PREFIX}all"); also
ensure PARTITION_PREFIX is imported into this module (from openrag.settings or
the module where PARTITION_PREFIX is defined) so the expression resolves
correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@conf/config.yaml`:
- Line 78: The comment for base_url is incorrect: update the comment for
base_url to reflect that its defaults are set in the code
(InfinityRerankerConfig.base_url defaults to "http://reranker:7997" and
OpenAIRerankerConfig.base_url defaults to "http://reranker:8000/v1") and that
RERANKER_PORT only affects Docker host port mapping and is not used to construct
the config value; reference base_url, InfinityRerankerConfig.base_url,
OpenAIRerankerConfig.base_url and RERANKER_PORT in the updated comment for
clarity.
- Line 69: Update the env var comment in conf/config.yaml to match the actual
mappings in openrag/config/loader.py: remove RERANKER_PORT and replace the list
with the real mapped variables (RERANKER_PROVIDER, RERANKER_ENABLED,
RERANKER_MODEL, RERANKER_TOP_K, RERANKER_BASE_URL, RERANKER_API_KEY,
RERANKER_TIMEOUT, RERANKER_SEMAPHORE) so the comment accurately reflects the
environment-to-config mapping used by the loader.

In `@openrag/components/reranker/base.py`:
- Around line 32-35: The loop that computes fused_scores uses doc_id =
doc.metadata.get("_id"), which collapses all docs missing "_id" under None;
update the code to detect missing IDs and either fail fast or assign a
per-document fallback key: if "_id" not in doc.metadata then either raise a
clear exception (e.g., raise KeyError(f"Missing _id in doc.metadata: {doc}")) or
set doc_id = f"__anon__{id(doc)}" (or another deterministic per-document
fallback such as hashing doc content) before using fused_scores.get(doc_id,
...); ensure you update references to doc_id, fused_scores and keep the existing
scoring expression (score + 1 / (rank + k), d).

In `@openrag/config/loader.py`:
- Around line 56-63: The YAML default blank for reranker.base_url means
Settings(**data) will keep an empty string and cause OpenAIReranker to post to
"/rerank" or InfinityReranker to receive an invalid URL; update the loader to
normalize an empty reranker.base_url back to the provider default before
constructing Settings (i.e., if data.get("reranker", {}).get("base_url") is
falsy or empty, replace it with the provider's default URL based on
data["reranker"]["provider"] or the known provider defaults used by
OpenAIReranker and InfinityReranker) so Settings(**data) never receives an empty
base_url and both OpenAIReranker and InfinityReranker get valid base URLs.

---

Duplicate comments:
In `@openrag/config/models.py`:
- Around line 148-151: The default_factory currently points to the Annotated
union alias RerankerConfig which is not callable; add a small helper function
named like _default_reranker_config that returns a concrete config instance
(e.g. return InfinityRerankerConfig()) and then change the Settings.reranker
Field to use Field(default_factory=_default_reranker_config) so missing configs
load the concrete default; reference RerankerConfig for typing but use
_default_reranker_config and InfinityRerankerConfig for the actual factory.

---

Nitpick comments:
In `@openrag/app_front.py`:
- Line 128: Replace the hardcoded model id check default=m.id == "openrag-all"
with the partition-aware constant by using the PARTITION_PREFIX constant (e.g.
default=m.id == f"{PARTITION_PREFIX}all"); also ensure PARTITION_PREFIX is
imported into this module (from openrag.settings or the module where
PARTITION_PREFIX is defined) so the expression resolves correctly.
🪄 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: 67d15860-e3b5-4a5e-a620-64b78261b5cd

📥 Commits

Reviewing files that changed from the base of the PR and between 651902c and 905be0a.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • conf/config.yaml
  • docker-compose.yaml
  • docs/content/docs/documentation/env_vars.md
  • extern/reranker/infinity.yaml
  • extern/reranker/openai.yaml
  • openrag/app_front.py
  • openrag/components/pipeline.py
  • openrag/components/reranker/__init__.py
  • openrag/components/reranker/base.py
  • openrag/components/reranker/infinity.py
  • openrag/components/reranker/openai.py
  • openrag/components/reranker/test_rrf_reranking.py
  • openrag/config/loader.py
  • openrag/config/models.py
  • quick_start/extern/infinity.yaml

Comment thread conf/config.yaml Outdated
Comment thread conf/config.yaml Outdated
Comment thread openrag/components/reranker/base.py Outdated
Comment thread openrag/config/loader.py
- Fix RerankerConfig default_factory using non-callable Annotated alias
- Strip blank reranker.base_url so provider-specific Pydantic defaults apply
- Prevent RRF score collapse when documents lack _id metadata
- Use PARTITION_PREFIX constant instead of hardcoded "openrag-all"
- Fix stale env var comments in config.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openrag/app_front.py (1)

117-128: ⚠️ Potential issue | 🟡 Minor

Keep the “all partitions” check exact in both places.

Line 128 now matches only the synthetic f"{PARTITION_PREFIX}all" profile, but the description still branches on "all" in m.id. A profile like openrag-small or openrag-allhands would still show the global-partitions description even though it is not the all profile.

Suggested fix
         for i, m in enumerate(models, start=1):
             partition = m.id.split(PARTITION_PREFIX)[1]
+            is_all_profile = m.id == f"{PARTITION_PREFIX}all"
             description_template = "You are interacting with the **{name}** LLM.\n" + (
                 "The LLM's answers will be grounded on **all** partitions."
-                if "all" in m.id
+                if is_all_profile
                 else "The LLM's answers will be grounded only on the partition named **{partition}**."
             )
             chat_profiles.append(
                 cl.ChatProfile(
                     name=m.id,
                     markdown_description=description_template.format(name=m.id, partition=partition),
                     icon="/public/favicon.svg",
-                    default=m.id == f"{PARTITION_PREFIX}all",
+                    default=is_all_profile,
                 )
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/app_front.py` around lines 117 - 128, The description branching uses
a substring check ("all" in m.id) which is inconsistent with the default-profile
check (m.id == f"{PARTITION_PREFIX}all"); update the description logic in the
block building chat_profiles so it uses the exact same equality check (compare
m.id to f"{PARTITION_PREFIX}all") instead of the substring test, ensuring
PARTITION_PREFIX, description_template, m.id and the default check remain
aligned and the markdown_description reflects only the true "all" partition
profile.
♻️ Duplicate comments (1)
openrag/config/loader.py (1)

277-284: ⚠️ Potential issue | 🟠 Major

Normalize the reranker block after all merges, and absorb the legacy enable key.

This cleanup only covers the YAML/env state. An override like {"reranker": {"provider": "openai", "base_url": ""}} can still recreate the blank URL after this block runs, and older custom configs that still use reranker.enable: false now miss the renamed field and fall back to the new default. Normalize the reranker dict once after _deep_merge() so both cases land on the new schema before validation.

Suggested fix
-    # Strip blank reranker.base_url so the provider-specific Pydantic default applies
-    reranker = data.get("reranker")
-    if isinstance(reranker, dict) and not reranker.get("base_url"):
-        reranker.pop("base_url", None)
-
     # 3. Apply programmatic overrides (tests)
     if overrides:
         data = _deep_merge(data, overrides)
+
+    # Normalize reranker config after all merges
+    reranker = data.get("reranker")
+    if isinstance(reranker, dict):
+        if "enabled" not in reranker and "enable" in reranker:
+            reranker["enabled"] = reranker.pop("enable")
+        if not reranker.get("base_url"):
+            reranker.pop("base_url", None)
 
     # 4. Resolve paths (after all merging so overrides are honored)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openrag/config/loader.py` around lines 277 - 284, Move the reranker
normalization to run after the programmatic overrides merge: after data =
_deep_merge(data, overrides) retrieve reranker = data.get("reranker") and if
it's a dict then (1) absorb the legacy key by mapping reranker["enable"] to
reranker["enabled"] (pop "enable" after copying) and (2) strip a blank base_url
by popping "base_url" when the value is falsy so the provider-specific Pydantic
default can apply; update the code around the existing reranker, overrides, and
_deep_merge usage to perform these steps once after merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@openrag/app_front.py`:
- Around line 117-128: The description branching uses a substring check ("all"
in m.id) which is inconsistent with the default-profile check (m.id ==
f"{PARTITION_PREFIX}all"); update the description logic in the block building
chat_profiles so it uses the exact same equality check (compare m.id to
f"{PARTITION_PREFIX}all") instead of the substring test, ensuring
PARTITION_PREFIX, description_template, m.id and the default check remain
aligned and the markdown_description reflects only the true "all" partition
profile.

---

Duplicate comments:
In `@openrag/config/loader.py`:
- Around line 277-284: Move the reranker normalization to run after the
programmatic overrides merge: after data = _deep_merge(data, overrides) retrieve
reranker = data.get("reranker") and if it's a dict then (1) absorb the legacy
key by mapping reranker["enable"] to reranker["enabled"] (pop "enable" after
copying) and (2) strip a blank base_url by popping "base_url" when the value is
falsy so the provider-specific Pydantic default can apply; update the code
around the existing reranker, overrides, and _deep_merge usage to perform these
steps once after merging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a6766ee4-a73f-4ca6-ad73-3f215dda6674

📥 Commits

Reviewing files that changed from the base of the PR and between 905be0a and 2c180c6.

📒 Files selected for processing (5)
  • conf/config.yaml
  • openrag/app_front.py
  • openrag/components/reranker/base.py
  • openrag/config/loader.py
  • openrag/config/models.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • conf/config.yaml
  • openrag/components/reranker/base.py

@EnjoyBacon7

Copy link
Copy Markdown
Collaborator

All good on my side

Comment thread openrag/components/reranker/infinity.py Outdated
Comment on lines -16 to -23
self.model_name = config.reranker["model_name"]
self.model_name = config.reranker.model_name
self.client = Client(
base_url=config.reranker["base_url"],
timeout=config.reranker.get("timeout", 60.0),
headers={"Authorization": f"Bearer {config.reranker['api_key']}"},
base_url=config.reranker.base_url,
timeout=config.reranker.timeout,
headers={"Authorization": f"Bearer {config.reranker.api_key}"},
)
semaphore = config.reranker.get("semaphore", 40)
self.semaphore = asyncio.Semaphore(semaphore)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I made those adjustments, but they don’t seem to be reflected in my commits. Something must have gone wrong during the rebase.

@Ahmath-Gadji
Ahmath-Gadji merged commit 250c66c into dev Apr 2, 2026
4 checks passed
@Ahmath-Gadji
Ahmath-Gadji deleted the feat/add_openai_reranking branch April 2, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Change of behavior after upgrade feat Add a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants