Crowd_sourced_FAQ_Project / rag /vectorstore.py
Kashish
vectorstore final
d697d80
Raw
History Blame Contribute Delete
2.87 kB
from __future__ import annotations
import logging
from typing import Optional, Iterable, List
from langchain_core.embeddings import Embeddings
from langchain_community.vectorstores import FAISS
from .config import settings
from .splitter import documents
logger = logging.getLogger(__name__)
# Directory where FAISS index is persisted
_VECTORSTORE_DIR = settings.vectorstore_dir
_INDEX_NAME = settings.vectorstore_index_name
_VECTORSTORE_DIR.mkdir(parents=True, exist_ok=True)
class _LazyHuggingFaceEmbeddings(Embeddings):
def __init__(self, model_name: str, encode_kwargs: Optional[dict] = None) -> None:
self.model_name = model_name
self.encode_kwargs = encode_kwargs or {}
self._real = None
def _init(self) -> None:
if self._real is None:
from langchain_huggingface import HuggingFaceEmbeddings
self._real = HuggingFaceEmbeddings(
model_name=self.model_name, encode_kwargs=self.encode_kwargs
)
async def aembed_documents(self, texts: Iterable[str]) -> List[List[float]]:
self._init()
return await self._real.aembed_documents(texts) # type: ignore[attr-defined]
def embed_documents(self, texts: Iterable[str]) -> List[List[float]]:
self._init()
return self._real.embed_documents(texts) # type: ignore[attr-defined]
def embed_query(self, text: str) -> List[float]:
self._init()
return self._real.embed_query(text) # type: ignore[attr-defined]
async def aembed_query(self, text: str) -> List[float]:
self._init()
return await self._real.aembed_query(text) # type: ignore[attr-defined]
_EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
_embeddings = _LazyHuggingFaceEmbeddings(_EMBEDDING_MODEL, encode_kwargs={"normalize_embeddings": True})
_vectorstore: Optional[FAISS] = None
def get_vectorstore() -> FAISS:
"""Return a persisted FAISS vectorstore, building it on first run only.
This attempts to load an existing index from disk. If the index is not
available it computes embeddings for the documents and saves the index.
"""
global _vectorstore
if _vectorstore is not None:
return _vectorstore
try:
_vectorstore = FAISS.load_local(
str(_VECTORSTORE_DIR),
_embeddings,
index_name=_INDEX_NAME,
allow_dangerous_deserialization=True,
)
return _vectorstore
except (FileNotFoundError, OSError, ValueError, RuntimeError) as error:
logger.info(
"FAISS index missing or unreadable; rebuilding index. %s",
error,
)
_vectorstore = FAISS.from_documents(documents, _embeddings) # will call embed_documents
_vectorstore.save_local(str(_VECTORSTORE_DIR), index_name=_INDEX_NAME)
return _vectorstore