SHL-recommender / build_index.py
Amaanaliii's picture
Upload 31 files
3e38c5b verified
Raw
History Blame Contribute Delete
2.76 kB
"""
Build embedding index from catalog_individual.json
Run: python -m src.build_index
"""
import os, json, numpy as np
import re
from sentence_transformers import SentenceTransformer
IN_PATH = "index/catalog_individual.json"
OUT_DIR = "index"
MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
def _clean_text(s: str) -> str:
if not s: return ""
# remove that site-level boilerplate
s = re.sub(r'Outdated browser detected.*?Latest browser options', ' ', s, flags=re.S|re.I)
s = re.sub(r'Global Offices.*', ' ', s, flags=re.S|re.I)
s = re.sub(r'\s{2,}', ' ', s)
return s.strip()
def load_items(path=IN_PATH):
with open(path, "r", encoding="utf-8") as f:
items = json.load(f)
for x in items:
name = x.get("name","") or ""
desc = _clean_text(x.get("description") or "")
tt = x.get("test_type") or ""
tt_full = {
"A":"Ability & Aptitude", "B":"Biodata & Situational Judgement",
"C":"Competencies", "D":"Development & 360", "E":"Assessment Exercises",
"K":"Knowledge & Skills", "P":"Personality & Behavior", "S":"Simulations"
}.get(tt,"")
# keep embed text concise
embed_parts = [name]
if desc and len(desc) < 800:
embed_parts.append(desc)
embed_parts.append(f"Test Type: {tt} {tt_full}")
langs = []
if x.get("languages"):
# languages may be a noisy long blob (clean and keep first few)
for l in x.get("languages")[:3]:
if isinstance(l, str):
langs.append(l.split('\n')[0].strip())
if langs:
embed_parts.append("Languages: " + ", ".join(langs))
x["_embed_text"] = "\n".join([p for p in embed_parts if p])
return items
def main():
if not os.path.exists(IN_PATH):
raise FileNotFoundError(f"Missing {IN_PATH}. Run the crawler first: python -m src.crawl_shl_catalog")
items = load_items()
texts = [it["_embed_text"] for it in items]
print("Loading model:", MODEL_NAME)
model = SentenceTransformer(MODEL_NAME)
print("Encoding", len(texts), "items (this may take a minute)...")
embs = model.encode(texts, show_progress_bar=True, normalize_embeddings=True)
embs = np.asarray(embs, dtype=np.float32)
os.makedirs(OUT_DIR, exist_ok=True)
np.save(os.path.join(OUT_DIR, "embeddings.npy"), embs)
with open(os.path.join(OUT_DIR, "items.json"), "w", encoding="utf-8") as f:
json.dump(items, f, ensure_ascii=False, indent=2)
print("Saved embeddings:", os.path.join(OUT_DIR, "embeddings.npy"))
print("Saved items:", os.path.join(OUT_DIR, "items.json"))
print("Embedding shape:", embs.shape)
if __name__ == "__main__":
main()