Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ dependencies = [
"jinja2>=3.1.0",
# To be able to fix multiple CVEs, also LCORE-1117
"requests>=2.33.0",
# Used for RAG chunk reranking (cross-encoder)
"sentence-transformers>=2.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should the sentence-transformer dependency be added @syedriko @tisnik? In that case uv.lock will need to be updated too

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes, it needs to be updated to pass CI etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks missed that - will update uv.lock

"datasets>=4.7.0",
# Used for error tracking and monitoring
"sentry-sdk[fastapi]>=2.58.0",
Expand Down
8 changes: 8 additions & 0 deletions src/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
OkpConfiguration,
QuotaHandlersConfiguration,
RagConfiguration,
RerankerConfiguration,
RlsapiV1Configuration,
ServiceConfiguration,
SplunkConfiguration,
Expand Down Expand Up @@ -465,6 +466,13 @@ def okp(self) -> "OkpConfiguration":
raise LogicError("logic error: configuration is not loaded")
return self._configuration.okp

@property
def reranker(self) -> "RerankerConfiguration":
"""Return reranker configuration."""
if self._configuration is None:
raise LogicError("logic error: configuration is not loaded")
return self._configuration.reranker

@property
def rag_id_mapping(self) -> dict[str, str]:
"""Return mapping from vector_db_id to rag_id from BYOK and OKP RAG config.
Expand Down
2 changes: 2 additions & 0 deletions src/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@
# Inline RAG constants
BYOK_RAG_MAX_CHUNKS: Final[int] = 10 # retrieved from BYOK RAG
OKP_RAG_MAX_CHUNKS: Final[int] = 5 # retrieved from OKP RAG
# Score multiplier applied to BYOK chunks after cross-encoder reranking (Solr chunks unchanged)
BYOK_RAG_RERANK_BOOST: Final[float] = 1.2

# Solr OKP constants
SOLR_VECTOR_SEARCH_DEFAULT_K: Final[int] = 5
Expand Down
69 changes: 69 additions & 0 deletions src/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,29 @@ class OkpConfiguration(ConfigurationBase):
)


class RerankerConfiguration(ConfigurationBase):
"""Reranker configuration for RAG chunk reranking."""

enabled: bool = True
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: can be initialized as Field so it would be possible to specify title and description.

model: str = Field(
default="cross-encoder/ms-marco-MiniLM-L6-v2",
title="Reranker model",
description="Cross-encoder model name for reranking RAG chunks. "
"Defaults to 'cross-encoder/ms-marco-MiniLM-L6-v2' from sentence-transformers.",
)

# Private attribute to track if this was explicitly configured
_explicitly_configured: bool = PrivateAttr(default=False)

@model_validator(mode="after")
def mark_as_explicitly_configured(self) -> Self:
"""Mark this configuration as explicitly set when instantiated from user input."""
if self.model_fields_set:
self._explicitly_configured = True

return self
Comment thread
Anxhela21 marked this conversation as resolved.


class AzureEntraIdConfiguration(ConfigurationBase):
"""Microsoft Entra ID authentication attributes for Azure."""

Expand Down Expand Up @@ -1970,6 +1993,12 @@ class Configuration(ConfigurationBase):
"in rag.inline or rag.tool.",
)

reranker: RerankerConfiguration = Field(
default_factory=RerankerConfiguration,
title="Reranker configuration",
description="Configuration for neural reranking of RAG chunks using cross-encoder.",
)

@model_validator(mode="after")
def validate_mcp_auth_headers(self) -> Self:
"""
Expand Down Expand Up @@ -2072,6 +2101,46 @@ def validate_rlsapi_v1_quota_configuration(self) -> Self:

return self

@model_validator(mode="after")
def validate_reranker_auto_enable(self) -> Self:
"""Automatically enable reranker when both BYOK and OKP RAG are configured.

When users have both BYOK (Bring Your Own Key) entries in byok_rag and OKP
(OpenShift Knowledge Platform) configured in the RAG strategies, automatically
enable the reranker if it's not explicitly disabled. This improves result
quality when multiple knowledge sources are available.

Returns:
Self: The validated configuration instance with reranker potentially enabled.
"""
# Check if BYOK RAG entries are configured
has_byok = len(self.byok_rag) > 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should also check that there are any entries registered in inline RAG

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh good point!


# Check if OKP is configured in either inline or tool RAG strategies
# pylint: disable=no-member
has_okp = (
constants.OKP_RAG_ID in self.rag.inline
or constants.OKP_RAG_ID in self.rag.tool
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why should the re-ranked be active if OKP is in RAG as a Tool?

Copy link
Copy Markdown
Contributor Author

@Anxhela21 Anxhela21 Apr 29, 2026

Choose a reason for hiding this comment

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

this is looking if okp is enabled either as inline or tool since we can configure okp either way unless I'm mistaken?

)

# If both BYOK and OKP are present and reranker is using default settings,
# ensure it's enabled for optimal results
if (
has_byok
and has_okp
and not self.reranker.enabled
):

logger.info(
"Automatically enabling reranker: Both BYOK RAG (%d entries) and OKP "
"are configured. Reranking improves result quality when multiple "
"knowledge sources are available.",
len(self.byok_rag),
)
self.reranker.enabled = True

return self

def dump(self, filename: str | Path = "configuration.json") -> None:
"""
Write the current Configuration model to a JSON file.
Expand Down
Loading
Loading