""" Uji empiris pendekatan EMBEDDING SIMILARITY untuk deteksi salah-field. Ide: embed isi field, bandingkan (cosine) ke centroid embedding contoh-prototipe tiap field; field dengan kemiripan tertinggi = prediksi. Jauh lebih cepat dari zero-shot (1 forward per field). Kasus uji sama seperti test_fieldfit_ml.py agar hasilnya bisa diperbandingkan. Model: sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 (multibahasa). Jalankan: pip install sentence-transformers python scripts/test_fieldfit_embed.py """ from __future__ import annotations import time from sentence_transformers import SentenceTransformer, util MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2" # Contoh-prototipe per field (beberapa frasa khas tiap field). PROTOS = { "task": [ "Buatkan ringkasan materi pelajaran", "Jelaskan konsep fotosintesis", "Rangkum perbedaan dua hal", "Susun rencana pelaksanaan pembelajaran", "Analisis dampak suatu peristiwa", "Buatkan soal latihan", ], "context": [ "Untuk kelas 7 SMP dengan durasi 80 menit", "Siswa belum pernah belajar topik ini", "Latar belakangnya pembelajaran daring", "Materi diajarkan setelah bab sebelumnya", "Situasi kelas dengan kemampuan beragam", ], "references": [ "Gunakan buku paket IPA halaman 20 sampai 35", "Berdasarkan kurikulum merdeka", "Mengacu pada jurnal ilmiah terbaru", "Sumber: catatan guru dan modul", "Pakai kompetensi dasar 3.7", ], "role": [ "Kamu adalah seorang guru IPA", "Bertindaklah sebagai dokter spesialis anak", "Berperan sebagai ahli sejarah", "Anggap dirimu konsultan pendidikan", "Kamu seorang penulis profesional", ], "audience": [ "Ditujukan untuk siswa kelas 3 SD", "Untuk pemula yang baru belajar", "Pembacanya mahasiswa tingkat akhir", "Target pembaca orang awam", "Khusus untuk anak usia dini", ], "tone": [ "Gunakan bahasa yang ramah dan santai", "Nada formal dan profesional", "Gaya bahasa lugas dan tegas", "Bahasa yang hangat dan mudah dipahami", "Sampaikan dengan nada persuasif", ], "constraints": [ "Jangan lebih dari 500 kata", "Maksimal tiga paragraf saja", "Hindari istilah teknis yang rumit", "Tanpa menggunakan bahasa asing", "Batasi jawaban sampai lima poin", ], "outputFormat": [ "Sajikan dalam bentuk tabel", "Tampilkan sebagai poin-poin bernomor", "Format daftar dengan bullet", "Keluaran berupa struktur kolom", "Buat dalam bentuk paragraf terstruktur", ], "example": [ "Contoh: Pendahuluan sepuluh menit berisi apersepsi", "Misalnya seperti berikut ini", "Sebagai contoh hasil yang diharapkan", "Contoh format keluaran yang diinginkan", "Ilustrasi hasil akhir", ], } CASES = [ ("Buatkan rencana pelaksanaan pembelajaran tentang fotosintesis", "task"), ("Rangkum perbedaan sel hewan dan sel tumbuhan", "task"), ("Untuk kelas 7 SMP dengan durasi 80 menit, siswa belum pernah belajar topik ini", "context"), ("Gunakan buku paket IPA kelas 7 halaman 20 sampai 35 dan kurikulum merdeka", "references"), ("Kamu adalah seorang guru IPA yang berpengalaman mengajar SMP", "role"), ("Bertindaklah sebagai dokter spesialis anak", "role"), ("Ditujukan untuk siswa kelas 3 SD yang baru belajar membaca", "audience"), ("Gunakan bahasa yang ramah, santai, dan mudah dipahami", "tone"), ("Jangan lebih dari 500 kata dan hindari istilah teknis yang rumit", "constraints"), ("Sajikan dalam bentuk tabel dengan kolom tujuan, kegiatan, dan penilaian", "outputFormat"), ("Contoh: 1. Pendahuluan sepuluh menit berisi apersepsi tentang tumbuhan", "example"), ("Kamu adalah seorang ahli sejarah Indonesia", "role"), ("Tampilkan hasilnya sebagai poin-poin bernomor", "outputFormat"), ("Khusus untuk mahasiswa tingkat akhir", "audience"), ("Maksimal tiga paragraf saja", "constraints"), ] def main() -> None: print(f"Memuat embedding model: {MODEL} ...") t0 = time.time() model = SentenceTransformer(MODEL) print(f" siap dalam {time.time()-t0:.1f}s\n") ids = list(PROTOS) centroids = {} for fid, exs in PROTOS.items(): emb = model.encode(exs, convert_to_tensor=True, normalize_embeddings=True) centroids[fid] = emb.mean(dim=0) correct = 0 lat = [] print(f"{'EXPECTED':12} {'PRED':12} {'cos':>5} {'margin':>6} match teks") print("-" * 100) for text, expected in CASES: t1 = time.time() e = model.encode(text, convert_to_tensor=True, normalize_embeddings=True) sims = sorted(((util.cos_sim(e, centroids[f]).item(), f) for f in ids), reverse=True) lat.append(time.time() - t1) (s0, top), (s1, _) = sims[0], sims[1] ok = top == expected correct += ok print(f"{expected:12} {top:12} {s0:5.2f} {s0-s1:6.2f} " f"{' OK ' if ok else 'SALAH'} {text[:46]}") n = len(CASES) print("-" * 100) print(f"Akurasi field: {correct}/{n} = {correct/n*100:.0f}%") print(f"Latency per field: rata-rata {sum(lat)/len(lat)*1000:.0f} ms") if __name__ == "__main__": main()