CapStone / backend /services /embeddings.py
Muizah's picture
First v
d6c005e
Raw
History Blame Contribute Delete
2 kB
import numpy as np
from itertools import combinations
from sentence_transformers import SentenceTransformer
embedding_model = None
def load_embedding_model():
global embedding_model
if embedding_model is not None:
return
print("Loading sentence transformer model...")
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
print("Embedding model loaded.")
# ── Cosine Similarity ──────────────────────────────────────────────────────
def cosine_similarity(vec_a: np.ndarray, vec_b: np.ndarray) -> float:
dot_product = np.dot(vec_a, vec_b)
magnitude = np.linalg.norm(vec_a) * np.linalg.norm(vec_b)
if magnitude == 0:
return 0.0
score = dot_product / magnitude
return float(np.clip(score, 0.0, 1.0))
# ── Main Entry Point ───────────────────────────────────────────────────────
async def compute_similarity(texts: dict) -> list[dict]:
load_embedding_model()
valid_texts = {
strategy: text
for strategy, text in texts.items()
if text and isinstance(text, str) and text.strip()
}
if len(valid_texts) < 2:
return []
strategies = list(valid_texts.keys())
text_list = list(valid_texts.values())
print(f"Embedding {len(text_list)} texts...")
embeddings = embedding_model.encode(text_list, convert_to_numpy=True)
print("Embeddings computed.")
scores = []
for i, j in combinations(range(len(strategies)), 2):
score = cosine_similarity(embeddings[i], embeddings[j])
scores.append({
"strategy_a": strategies[i],
"strategy_b": strategies[j],
"score": round(score, 4),
})
scores.sort(key=lambda x: x["score"], reverse=True)
return scores