Coverage for src/local_deep_research/vector_stores/config.py: 100%

19 statements  

« prev     ^ index     » next       coverage.py v7.15.1, created at 2026-07-20 07:11 +0000

1"""Vector-store provider registry and factory. 

2 

3Mirrors ``embeddings/embeddings_config.py``: a flat list of valid providers, a 

4lazily-populated class registry, and a single resolution entry point. Only 

5FAISS is registered today, and there is no settings key selecting a provider 

6yet — ``resolve_provider`` always returns ``"faiss"``. The seam exists so a 

7future backend is a bounded addition (register the class, add a setting) rather 

8than a rewrite of the call sites. 

9""" 

10 

11from typing import Dict, Optional, Type 

12 

13from .base import BaseVectorStore 

14 

15VALID_VECTOR_STORE_PROVIDERS = ["faiss"] 

16 

17_DEFAULT_PROVIDER = "faiss" 

18 

19# Lazily-populated {provider_key: class}. Populated on first use to avoid 

20# importing faiss at module import time. 

21_PROVIDER_CLASSES: Dict[str, Type[BaseVectorStore]] = {} 

22 

23 

24def _load_provider_classes() -> Dict[str, Type[BaseVectorStore]]: 

25 if not _PROVIDER_CLASSES: 

26 from .implementations.faiss_store import FaissVectorStore 

27 

28 _PROVIDER_CLASSES[FaissVectorStore.provider_key] = FaissVectorStore 

29 return _PROVIDER_CLASSES 

30 

31 

32def resolve_provider(settings_snapshot: Optional[dict] = None) -> str: 

33 """Return the configured vector-store provider key. 

34 

35 No settings key selects this yet — always ``"faiss"``. The 

36 ``settings_snapshot`` parameter is accepted now so callers don't change when 

37 a setting is introduced later. 

38 """ 

39 return _DEFAULT_PROVIDER 

40 

41 

42def get_vector_store_class( 

43 provider: Optional[str] = None, 

44 settings_snapshot: Optional[dict] = None, 

45) -> Type[BaseVectorStore]: 

46 """Return the :class:`BaseVectorStore` subclass for ``provider``. 

47 

48 Callers construct instances via the class's ``.create(...)`` / ``.load(...)`` 

49 classmethods (a vector store is stateful, unlike the stateless embeddings 

50 providers, so the factory hands back the class rather than an instance). 

51 """ 

52 key = provider or resolve_provider(settings_snapshot) # gitleaks:allow 

53 # Normalize like embeddings_config.get_embeddings: a provider from a 

54 # settings/DB value may carry surrounding whitespace/quotes/case. 

55 key = key.strip().strip("\"'").strip().lower() 

56 classes = _load_provider_classes() 

57 if key not in classes: 

58 raise ValueError( 

59 f"Unknown vector-store provider '{key}'. " 

60 f"Valid providers: {sorted(classes)}" 

61 ) 

62 return classes[key]