AI_Book_Librarian / src /embeddings.py
lst0004's picture
Upload 18 files
aeb54b7 verified
Raw
History Blame Contribute Delete
1.46 kB
"""Build the two retrieval indices used by the NLP block:
1. Dense embeddings via sentence-transformers (semantic search).
2. A TF-IDF baseline (the comparison required for the NLP block: dense vs sparse retrieval).
Both are saved to models/ and loaded at inference time by recommend.py.
Run: python -m src.embeddings
"""
import joblib
import numpy as np
import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from src import config as cfg
def _doc(row) -> str:
parts = [str(row.get("title", "")), str(row.get("genre_str", "")), str(row.get("description", ""))]
return ". ".join(p for p in parts if p and p != "nan")
def main():
cat = pd.read_parquet(cfg.CATALOG_PARQUET)
docs = cat.apply(_doc, axis=1).tolist()
ids = cat["book_id"].to_numpy()
print(f"Embedding {len(docs)} books with {cfg.EMBED_MODEL} ...")
model = SentenceTransformer(cfg.EMBED_MODEL)
emb = model.encode(docs, batch_size=64, show_progress_bar=True, normalize_embeddings=True)
np.save(cfg.EMBEDDINGS_NPY, emb.astype("float32"))
np.save(cfg.EMB_IDS_NPY, ids)
tfidf = TfidfVectorizer(max_features=20000, stop_words="english")
mat = tfidf.fit_transform(docs)
joblib.dump(tfidf, cfg.TFIDF_VECTORIZER)
joblib.dump(mat, cfg.TFIDF_MATRIX)
print(f"Saved embeddings {emb.shape} and TF-IDF matrix {mat.shape}")
if __name__ == "__main__":
main()