import numpy as np from sklearn.metrics.pairwise import cosine_similarity def evaluasi_pilar_1(motion: str, paragraph_list: list[str], embedding_model) -> dict: """ Mengevaluasi kepadatan semantik dan kedekatan argumen terhadap mosi. Menghasilkan skor relevansi mosi dan kekompakan argumen internal. """ clean_paragraphs = [p.strip() for p in paragraph_list if p and len(p.strip()) > 10] if not clean_paragraphs: return {"skor": 0.0, "status": "Tidak ada paragraf valid", "detail": {}} motion_vector = embedding_model.encode(motion, normalize_embeddings=True).reshape(1, -1) paragraph_vectors = embedding_model.encode(clean_paragraphs, normalize_embeddings=True) similarity_per_paragraph = cosine_similarity(paragraph_vectors, motion_vector).flatten() raw_similarity = float(np.mean(similarity_per_paragraph)) speech_centroid = np.mean(paragraph_vectors, axis=0, keepdims=True) similarity_to_centroid = cosine_similarity(paragraph_vectors, speech_centroid).flatten() internal_density = float(np.mean(similarity_to_centroid)) motion_relevance_score = float(np.clip((raw_similarity - 0.15) / (0.48 - 0.15), 0.0, 1.0)) * 100.0 density_score = float(np.clip((internal_density - 0.35) / (0.75 - 0.35), 0.0, 1.0)) * 100.0 final_score = (0.60 * motion_relevance_score) + (0.40 * density_score) return { "skor": round(float(final_score), 2), "detail": { "rata_rata_kemiripan_mosi_raw": round(raw_similarity, 4), "kepadatan_centroid_internal": round(internal_density, 4), "skor_relevansi_mosi_terkalibrasi": round(motion_relevance_score, 2), "skor_fokus_centroid": round(density_score, 2) } }