HomeRealty / src /rag /retriever.py
jaydeb2023
Moved project files to root for Hugging Face Space
4ab8820
Raw
History Blame Contribute Delete
3.47 kB
import os
import pickle
from pathlib import Path
from src.config.settings import FAQS_TXT, VECTORS_DIR
_chunks = []
_index = None
def _chunk_text(text: str, chunk_size: int = 400, overlap: int = 80) -> list[str]:
words = text.split()
chunks = []
i = 0
while i < len(words):
chunk = " ".join(words[i: i + chunk_size])
chunks.append(chunk)
i += chunk_size - overlap
return chunks
def build_vector_store():
try:
import faiss
import numpy as np
import google.generativeai as genai
from src.config.settings import GEMINI_API_KEY
genai.configure(api_key=GEMINI_API_KEY)
text = FAQS_TXT.read_text()
chunks = _chunk_text(text)
embeddings = []
for chunk in chunks:
result = genai.embed_content(
model="models/embedding-001",
content=chunk,
task_type="retrieval_document",
)
embeddings.append(result["embedding"])
emb_array = np.array(embeddings, dtype="float32")
index = faiss.IndexFlatL2(emb_array.shape[1])
index.add(emb_array)
VECTORS_DIR.mkdir(parents=True, exist_ok=True)
faiss.write_index(index, str(VECTORS_DIR / "faqs.index"))
with open(VECTORS_DIR / "chunks.pkl", "wb") as f:
pickle.dump(chunks, f)
print(f"Vector store built with {len(chunks)} chunks.")
except Exception as e:
print(f"Vector store build failed (using keyword fallback): {e}")
def load_vector_store():
global _chunks, _index
chunks_path = VECTORS_DIR / "chunks.pkl"
index_path = VECTORS_DIR / "faqs.index"
if chunks_path.exists():
with open(chunks_path, "rb") as f:
_chunks = pickle.load(f)
if index_path.exists():
try:
import faiss
_index = faiss.read_index(str(index_path))
except Exception:
_index = None
# Always load raw text as fallback
if not _chunks and FAQS_TXT.exists():
text = FAQS_TXT.read_text()
_chunks = _chunk_text(text)
def retrieve_faq(query: str, top_k: int = 3) -> str:
global _chunks, _index
if not _chunks:
load_vector_store()
# Try FAISS semantic search first
if _index is not None and _chunks:
try:
import numpy as np
import google.generativeai as genai
from src.config.settings import GEMINI_API_KEY
genai.configure(api_key=GEMINI_API_KEY)
result = genai.embed_content(
model="models/embedding-001",
content=query,
task_type="retrieval_query",
)
q_emb = np.array([result["embedding"]], dtype="float32")
distances, indices = _index.search(q_emb, top_k)
retrieved = [_chunks[i] for i in indices[0] if i < len(_chunks)]
return "\n\n---\n\n".join(retrieved)
except Exception:
pass
# Keyword fallback
return _keyword_search(query)
def _keyword_search(query: str) -> str:
if not _chunks:
load_vector_store()
q_lower = query.lower()
scored = []
for chunk in _chunks:
score = sum(1 for word in q_lower.split() if word in chunk.lower())
scored.append((score, chunk))
scored.sort(key=lambda x: -x[0])
top = [c for _, c in scored[:3] if _ > 0]
return "\n\n---\n\n".join(top) if top else ""