Skip to content

Commit 11832f8

Browse files
authored
Merge pull request #1322 from are-ces/okp-source-attribute
LCORE-1402: OKP Index name missing in chunk metadata (tool RAG)#69
2 parents 89cac0f + e3d0931 commit 11832f8

File tree

2 files changed

+120
-24
lines changed

2 files changed

+120
-24
lines changed

src/configuration.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,38 @@
22

33
from typing import Any, Optional
44

5+
import yaml
6+
57
# We want to support environment variable replacement in the configuration
68
# similarly to how it is done in llama-stack, so we use their function directly
79
from llama_stack.core.stack import replace_env_vars
810

9-
import yaml
1011
import constants
12+
from cache.cache import Cache
13+
from cache.cache_factory import CacheFactory
14+
from log import get_logger
1115
from models.config import (
1216
A2AStateConfiguration,
17+
AuthenticationConfiguration,
1318
AuthorizationConfiguration,
1419
AzureEntraIdConfiguration,
1520
Configuration,
21+
ConversationHistoryConfiguration,
1622
Customization,
23+
DatabaseConfiguration,
24+
InferenceConfiguration,
1725
LlamaStackConfiguration,
26+
ModelContextProtocolServer,
1827
OkpConfiguration,
28+
QuotaHandlersConfiguration,
1929
RagConfiguration,
20-
UserDataCollection,
2130
ServiceConfiguration,
22-
ModelContextProtocolServer,
23-
AuthenticationConfiguration,
24-
InferenceConfiguration,
25-
DatabaseConfiguration,
26-
ConversationHistoryConfiguration,
27-
QuotaHandlersConfiguration,
2831
SplunkConfiguration,
32+
UserDataCollection,
2933
)
30-
31-
from cache.cache import Cache
32-
from cache.cache_factory import CacheFactory
33-
3434
from quota.quota_limiter import QuotaLimiter
35-
from quota.token_usage_history import TokenUsageHistory
3635
from quota.quota_limiter_factory import QuotaLimiterFactory
37-
from log import get_logger
36+
from quota.token_usage_history import TokenUsageHistory
3837

3938
logger = get_logger(__name__)
4039

@@ -382,18 +381,28 @@ def okp(self) -> "OkpConfiguration":
382381

383382
@property
384383
def rag_id_mapping(self) -> dict[str, str]:
385-
"""Return mapping from vector_db_id to rag_id from BYOK RAG config.
384+
"""Return mapping from vector_db_id to rag_id from BYOK and OKP RAG config.
386385
387386
Returns:
388-
dict[str, str]: Mapping where keys are llama-stack vector_db_ids
389-
and values are user-facing rag_ids from configuration.
387+
dict[str, str]: Mapping where keys are llama-stack vector_store_ids
388+
(old vector_db_id) and values are user-facing rag_ids from configuration.
390389
391390
Raises:
392391
LogicError: If the configuration has not been loaded.
393392
"""
394393
if self._configuration is None:
395394
raise LogicError("logic error: configuration is not loaded")
396-
return {brag.vector_db_id: brag.rag_id for brag in self._configuration.byok_rag}
395+
byok_mapping = {
396+
brag.vector_db_id: brag.rag_id for brag in self._configuration.byok_rag
397+
}
398+
399+
rag = self._configuration.rag
400+
okp_id = constants.OKP_RAG_ID
401+
okp_enabled = okp_id in (rag.inline or []) or okp_id in (rag.tool or [])
402+
okp_mapping = (
403+
{constants.SOLR_DEFAULT_VECTOR_STORE_ID: okp_id} if okp_enabled else {}
404+
)
405+
return {**byok_mapping, **okp_mapping}
397406

398407
@property
399408
def score_multiplier_mapping(self) -> dict[str, float]:

tests/unit/test_configuration.py

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
# pylint: disable=too-many-lines
44

5+
from collections.abc import Generator
56
from pathlib import Path
67
from typing import Any
7-
from collections.abc import Generator
8-
from pydantic import ValidationError
98

109
import pytest
10+
from pydantic import ValidationError
11+
12+
import constants
13+
from cache.in_memory_cache import InMemoryCache
14+
from cache.sqlite_cache import SQLiteCache
1115
from configuration import AppConfig, LogicError
1216
from models.config import CustomProfile, ModelContextProtocolServer
13-
from cache.sqlite_cache import SQLiteCache
14-
from cache.in_memory_cache import InMemoryCache
1517

1618

1719
# pylint: disable=broad-exception-caught,protected-access
@@ -954,11 +956,61 @@ def test_load_configuration_with_incomplete_azure_entra_id_raises(tmpdir: Path)
954956
cfg.load_configuration(str(cfg_filename))
955957

956958

957-
def test_rag_id_mapping_empty_when_no_byok(minimal_config: AppConfig) -> None:
958-
"""Test that rag_id_mapping returns empty dict when no BYOK RAG configured."""
959+
def test_rag_id_mapping_excludes_solr_when_okp_not_configured(
960+
minimal_config: AppConfig,
961+
) -> None:
962+
"""Test that rag_id_mapping does not include OKP/Solr when OKP is not in rag config."""
959963
assert minimal_config.rag_id_mapping == {}
960964

961965

966+
def test_rag_id_mapping_includes_solr_when_okp_in_inline() -> None:
967+
"""Test that rag_id_mapping includes OKP/Solr mapping when OKP is in rag.inline."""
968+
cfg = AppConfig()
969+
cfg.init_from_dict(
970+
{
971+
"name": "test",
972+
"service": {"host": "localhost", "port": 8080},
973+
"llama_stack": {
974+
"api_key": "k",
975+
"url": "http://test.com:1234",
976+
"use_as_library_client": False,
977+
},
978+
"user_data_collection": {},
979+
"authentication": {"module": "noop"},
980+
"rag": {"inline": [constants.OKP_RAG_ID]},
981+
}
982+
)
983+
assert constants.SOLR_DEFAULT_VECTOR_STORE_ID in cfg.rag_id_mapping
984+
assert (
985+
cfg.rag_id_mapping[constants.SOLR_DEFAULT_VECTOR_STORE_ID]
986+
== constants.OKP_RAG_ID
987+
)
988+
989+
990+
def test_rag_id_mapping_includes_solr_when_okp_in_tool() -> None:
991+
"""Test that rag_id_mapping includes OKP/Solr mapping when OKP is in rag.tool."""
992+
cfg = AppConfig()
993+
cfg.init_from_dict(
994+
{
995+
"name": "test",
996+
"service": {"host": "localhost", "port": 8080},
997+
"llama_stack": {
998+
"api_key": "k",
999+
"url": "http://test.com:1234",
1000+
"use_as_library_client": False,
1001+
},
1002+
"user_data_collection": {},
1003+
"authentication": {"module": "noop"},
1004+
"rag": {"tool": [constants.OKP_RAG_ID]},
1005+
}
1006+
)
1007+
assert constants.SOLR_DEFAULT_VECTOR_STORE_ID in cfg.rag_id_mapping
1008+
assert (
1009+
cfg.rag_id_mapping[constants.SOLR_DEFAULT_VECTOR_STORE_ID]
1010+
== constants.OKP_RAG_ID
1011+
)
1012+
1013+
9621014
def test_rag_id_mapping_with_byok(tmp_path: Path) -> None:
9631015
"""Test that rag_id_mapping builds correct mapping from BYOK config."""
9641016
db_file = tmp_path / "test.db"
@@ -987,6 +1039,41 @@ def test_rag_id_mapping_with_byok(tmp_path: Path) -> None:
9871039
assert cfg.rag_id_mapping == {"vs-001": "my-kb"}
9881040

9891041

1042+
def test_rag_id_mapping_with_byok_and_okp(tmp_path: Path) -> None:
1043+
"""Test that rag_id_mapping includes both BYOK and OKP entries when OKP is configured."""
1044+
db_file = tmp_path / "test.db"
1045+
db_file.touch()
1046+
cfg = AppConfig()
1047+
cfg.init_from_dict(
1048+
{
1049+
"name": "test",
1050+
"service": {"host": "localhost", "port": 8080},
1051+
"llama_stack": {
1052+
"api_key": "k",
1053+
"url": "http://test.com:1234",
1054+
"use_as_library_client": False,
1055+
},
1056+
"user_data_collection": {},
1057+
"authentication": {"module": "noop"},
1058+
"rag": {"inline": [constants.OKP_RAG_ID]},
1059+
"byok_rag": [
1060+
{
1061+
"rag_id": "my-kb",
1062+
"vector_db_id": "vs-001",
1063+
"db_path": str(db_file),
1064+
},
1065+
],
1066+
}
1067+
)
1068+
assert "vs-001" in cfg.rag_id_mapping
1069+
assert cfg.rag_id_mapping["vs-001"] == "my-kb"
1070+
assert constants.SOLR_DEFAULT_VECTOR_STORE_ID in cfg.rag_id_mapping
1071+
assert (
1072+
cfg.rag_id_mapping[constants.SOLR_DEFAULT_VECTOR_STORE_ID]
1073+
== constants.OKP_RAG_ID
1074+
)
1075+
1076+
9901077
def test_resolve_index_name_with_mapping(minimal_config: AppConfig) -> None:
9911078
"""Test resolve_index_name uses mapping when available."""
9921079
mapping = {"vs-x": "user-friendly-name"}

0 commit comments

Comments
 (0)