scifact-semantic-search / precompute.py
RJuro's picture
Initial deploy: SciFact multilingual semantic search
c19484b
Raw
History Blame Contribute Delete
2.76 kB
"""
Precompute corpus embeddings and store in ChromaDB.
Run once locally:
python precompute.py
Produces: data/chroma_db/ (persistent ChromaDB directory)
"""
import os
import chromadb
import pandas as pd
from datasets import load_dataset
from sentence_transformers import SentenceTransformer
MODEL_NAME = "intfloat/multilingual-e5-small"
CHROMA_PATH = os.path.join(os.path.dirname(__file__), "data", "chroma_db")
COLLECTION_NAME = "scifact"
BATCH_SIZE = 64
def load_scifact() -> pd.DataFrame:
corpus = load_dataset("mteb/scifact", "corpus", split="corpus").to_pandas()
corpus["title"] = corpus["title"].fillna("").astype(str)
corpus["text"] = corpus["text"].fillna("").astype(str)
corpus["full_text"] = (
corpus["title"].str.strip() + ". " + corpus["text"].str.strip()
).str.strip(" .")
corpus = corpus.rename(columns={"_id": "doc_id"})[
["doc_id", "title", "text", "full_text"]
]
return corpus.reset_index(drop=True)
def main():
print("Loading SciFact corpus...")
corpus_df = load_scifact()
print(f" {len(corpus_df)} documents loaded.")
print(f"Loading model: {MODEL_NAME}")
model = SentenceTransformer(MODEL_NAME)
passages = [f"passage: {t.strip()}" for t in corpus_df["full_text"].tolist()]
print(f"Encoding {len(passages)} passages...")
embeddings = model.encode(
passages,
batch_size=BATCH_SIZE,
show_progress_bar=True,
normalize_embeddings=True,
)
print(f" Embedding shape: {embeddings.shape}")
os.makedirs(CHROMA_PATH, exist_ok=True)
client = chromadb.PersistentClient(path=CHROMA_PATH)
# Delete existing collection if present
try:
client.delete_collection(COLLECTION_NAME)
except Exception:
pass
collection = client.create_collection(
name=COLLECTION_NAME,
metadata={"hnsw:space": "cosine"},
)
ids = [str(i) for i in range(len(corpus_df))]
titles = corpus_df["title"].tolist()
texts = [t[:500] for t in corpus_df["text"].tolist()]
emb_lists = embeddings.tolist()
# Add in batches
ADD_BATCH = 500
for start in range(0, len(ids), ADD_BATCH):
end = min(start + ADD_BATCH, len(ids))
collection.add(
ids=ids[start:end],
embeddings=emb_lists[start:end],
metadatas=[
{"title": titles[i], "text": texts[i]} for i in range(start, end)
],
documents=corpus_df["full_text"].tolist()[start:end],
)
print(f" Added {end}/{len(ids)} documents to ChromaDB.")
print(f"\nChromaDB persisted to: {CHROMA_PATH}")
print(f"Collection '{COLLECTION_NAME}': {collection.count()} documents")
if __name__ == "__main__":
main()