Sentence Embedding dan Semantic Search
Pada pencarian biasa, sistem sering hanya mencocokkan kata yang persis sama. Masalahnya, manusia sering menyampaikan makna yang sama dengan kata berbeda. Kalimat “cara membersihkan teks” dan “bagaimana preprocessing dilakukan” mungkin bermakna dekat, tetapi pencarian berbasis kata bisa gagal menemukan hubungan itu. Karena itulah kita memerlukan sentence embedding dan semantic search.
Jika TF-IDF ibarat menghitung seberapa sering kata muncul, maka embedding ibarat meletakkan kalimat ke dalam peta makna. Kalimat yang artinya mirip akan berada di lokasi yang berdekatan di peta itu. Dari sinilah semantic search bekerja: bukan sekadar melihat kata yang sama, tetapi melihat kedekatan makna.
Apa itu sentence embedding
Sentence embedding adalah representasi numerik dari sebuah kalimat atau paragraf dalam bentuk vektor. Vektor ini berusaha menangkap makna umum dari teks tersebut. Dengan embedding, komputer tidak hanya melihat kata per kata, tetapi juga berusaha menangkap konteks semantik secara lebih utuh.
Bayangkan setiap kalimat ditempatkan di sebuah peta kota. Kalimat yang membahas topik serupa akan berada di lingkungan yang berdekatan, walaupun rumahnya tidak persis sama. Semantic search seperti mencari tetangga terdekat di peta makna itu.
Istilah penting di sesi ini
Sentence embedding
Vektor yang mewakili makna kalimat atau dokumen pendek.
Cosine similarity
Ukuran kedekatan dua vektor. Nilai tinggi biasanya berarti dua teks punya makna yang lebih mirip.
Semantic search
Pencarian dokumen berdasarkan kedekatan makna, bukan sekadar kecocokan kata.
Retrieval
Proses mengambil dokumen atau potongan teks yang paling relevan terhadap query.
Keyword search vs semantic search
Keyword search bekerja sangat baik jika kata pada query dan dokumen benar-benar sama. Namun jika pengguna memakai sinonim, istilah berbeda, atau gaya kalimat berbeda, pencarian kata sering kurang peka. Semantic search membantu mengatasi hal itu karena ia melihat kemiripan makna. Ini sangat penting untuk tanya jawab dokumen, FAQ, pencarian materi kuliah, dan sistem rekomendasi bacaan.
Keyword search
Cepat dan sederhana, tetapi sensitif pada perbedaan kata.
Semantic search
Lebih paham makna, tetapi butuh model embedding dan perhitungan similarity.
Gabungan keduanya
Dalam banyak sistem nyata, keyword search dan semantic search justru saling melengkapi.
Mengapa cosine similarity penting
Setelah kalimat diubah menjadi vektor, kita memerlukan cara untuk mengukur seberapa mirip dua vektor. Salah satu ukuran paling umum adalah cosine similarity. Nilainya biasanya berada pada rentang -1 sampai 1, tetapi pada embedding teks modern sering berada di rentang 0 sampai 1 untuk pasangan yang cukup terkait. Semakin tinggi nilainya, biasanya semakin dekat makna kedua teks.
Secara intuitif, cosine similarity melihat “arah” vektor, bukan hanya panjangnya. Jadi dua kalimat yang mirip maknanya akan cenderung mengarah ke arah yang serupa di ruang embedding.
Praktikum 1: membuat embedding kalimat
Library yang sangat populer untuk ini adalah sentence-transformers. Contoh berikut menunjukkan cara membuat embedding dari beberapa kalimat pendek.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
kalimat = [
"Bagaimana cara membersihkan teks sebelum dianalisis?",
"Apa langkah preprocessing pada data teks?",
"Cara membuat kopi tubruk yang enak"
]
embeddings = model.encode(kalimat)
print(embeddings.shape)
print(embeddings[0][:10])Dari sini mahasiswa dapat melihat bahwa satu kalimat berubah menjadi deretan angka panjang yang mewakili maknanya.
Praktikum 2: menghitung kemiripan dua kalimat
Setelah punya embedding, langkah berikutnya adalah mengukur cosine similarity. Ini latihan paling dasar sebelum membangun semantic search.
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
kalimat1 = "Apa itu preprocessing teks?"
kalimat2 = "Bagaimana cara membersihkan data teks sebelum analisis?"
kalimat3 = "Siapa penemu lampu pijar?"
emb1 = model.encode([kalimat1])
emb2 = model.encode([kalimat2])
emb3 = model.encode([kalimat3])
sim_12 = cosine_similarity(emb1, emb2)[0][0]
sim_13 = cosine_similarity(emb1, emb3)[0][0]
print("Similarity kalimat1 vs kalimat2:", sim_12)
print("Similarity kalimat1 vs kalimat3:", sim_13)Biasanya nilai similarity untuk pasangan pertama akan lebih tinggi karena topiknya masih satu keluarga.
Praktikum 3: semantic search sederhana pada kumpulan dokumen
Berikut contoh inti dari semantic search. Kita punya beberapa dokumen kecil, lalu query akan dicocokkan ke dokumen yang paling dekat secara makna.
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
dokumen = [
"Preprocessing teks mencakup tokenisasi, stopword removal, dan stemming.",
"TF-IDF mengubah dokumen menjadi vektor berdasarkan bobot kata.",
"Transformer menggunakan attention untuk memahami hubungan antar token.",
"Semantic search memakai embedding untuk mencari dokumen berdasarkan makna."
]
query = "Bagaimana sistem mencari dokumen dengan memahami arti kalimat?"
emb_dokumen = model.encode(dokumen)
emb_query = model.encode([query])
scores = cosine_similarity(emb_query, emb_dokumen)[0]
ranking = np.argsort(scores)[::-1]
for idx in ranking:
print(f"Skor: {scores[idx]:.4f} | Dokumen: {dokumen[idx]}")Praktikum 4: membungkus semantic search menjadi fungsi
Agar lebih rapi, kode semantic search sebaiknya dibungkus menjadi fungsi yang mudah dipanggil berulang. Ini juga berguna saat nanti mahasiswa masuk ke RAG.
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
def semantic_search(query, docs, top_k=3):
doc_embeddings = model.encode(docs)
query_embedding = model.encode([query])
scores = cosine_similarity(query_embedding, doc_embeddings)[0]
ranking = np.argsort(scores)[::-1][:top_k]
hasil = []
for idx in ranking:
hasil.append({
"dokumen": docs[idx],
"score": float(scores[idx])
})
return hasil
docs = [
"Word embedding membantu menangkap hubungan semantik antarkata.",
"Sentence embedding digunakan untuk mewakili makna satu kalimat penuh.",
"KNN adalah algoritma klasifikasi berbasis tetangga terdekat.",
"RAG menggabungkan retrieval dan generation."
]
query = "Apa teknik untuk mewakili arti sebuah kalimat?"
hasil = semantic_search(query, docs, top_k=2)
for item in hasil:
print(item)Praktikum 5: membandingkan keyword search dan semantic search
Latihan ini sangat bagus karena mahasiswa bisa melihat mengapa semantic search diperlukan. Query dan dokumen memakai kata yang berbeda, tetapi tetap punya makna mirip.
dokumen = [
"Tahap membersihkan teks biasanya dilakukan sebelum fitur diekstrak.",
"Cosine similarity mengukur kedekatan dua vektor.",
"Prompt engineering membantu menghasilkan jawaban yang lebih terarah."
]
query = "Bagaimana cara melakukan preprocessing data teks?"
# keyword search sangat sederhana
keyword_scores = []
for doc in dokumen:
skor = sum(1 for kata in query.lower().split() if kata in doc.lower())
keyword_scores.append(skor)
print("Hasil keyword search:")
for skor, doc in sorted(zip(keyword_scores, dokumen), reverse=True):
print(skor, doc)
print("\nHasil semantic search:")
hasil_semantik = semantic_search(query, dokumen, top_k=3)
for item in hasil_semantik:
print(item)Praktikum 6: semantic FAQ sederhana
Ini contoh yang sangat dekat dengan aplikasi nyata. Kita buat daftar FAQ singkat, lalu sistem mengambil jawaban yang paling relevan berdasarkan pertanyaan pengguna.
faq = [
{
"pertanyaan": "Apa itu TF-IDF?",
"jawaban": "TF-IDF adalah cara memberi bobot pada kata berdasarkan frekuensi kata dalam dokumen dan kelangkaannya di seluruh koleksi dokumen."
},
{
"pertanyaan": "Apa fungsi preprocessing teks?",
"jawaban": "Preprocessing membantu membersihkan teks agar lebih rapi dan siap dianalisis oleh model."
},
{
"pertanyaan": "Apa itu semantic search?",
"jawaban": "Semantic search adalah pencarian berdasarkan makna, bukan hanya kecocokan kata."
}
]
pertanyaan_user = "Mengapa data teks perlu dibersihkan dulu?"
docs = [item["pertanyaan"] for item in faq]
hasil = semantic_search(pertanyaan_user, docs, top_k=1)
pertanyaan_terpilih = hasil[0]["dokumen"]
for item in faq:
if item["pertanyaan"] == pertanyaan_terpilih:
print("Pertanyaan paling mirip:", item["pertanyaan"])
print("Jawaban:", item["jawaban"])Praktikum 7: visualisasi embedding sederhana
Karena embedding berdimensi tinggi sulit dilihat langsung, kita bisa menurunkannya ke 2 dimensi untuk visualisasi. Ini membantu mahasiswa mendapat intuisi bahwa teks yang mirip makna sering berkumpul di area yang berdekatan.
from sentence_transformers import SentenceTransformer
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
kalimat = [
"Preprocessing teks membersihkan data.",
"Tokenisasi memecah kalimat menjadi token.",
"Semantic search mencari berdasarkan makna.",
"Embedding mewakili arti teks menjadi vektor.",
"Cuaca hari ini cukup cerah."
]
emb = model.encode(kalimat)
pca = PCA(n_components=2)
points = pca.fit_transform(emb)
plt.figure(figsize=(8,6))
plt.scatter(points[:,0], points[:,1])
for i, teks in enumerate(kalimat):
plt.text(points[i,0], points[i,1], teks[:18])
plt.title("Visualisasi embedding kalimat")
plt.xlabel("Dimensi 1")
plt.ylabel("Dimensi 2")
plt.show()Praktikum 8: contoh integrasi semantic search dengan LLM
Contoh ini menjadi jembatan alami ke sesi 13 tentang RAG. Di sini kita ambil dokumen yang relevan dulu, baru dipakai sebagai konteks untuk model generatif.
import requests
API_KEY = "gsk_XXXX"
MODEL = "llama-3.1-8b-instant"
URL = "https://api.groq.com/openai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
def ask_llm_with_context(question, context):
system_prompt = "Anda adalah asisten pembelajaran yang hanya menjawab berdasarkan konteks yang diberikan. Jika konteks tidak cukup, katakan bahwa informasi belum cukup."
user_prompt = f"Konteks: {context}\n\nPertanyaan: {question}"
payload = {
"model": MODEL,
"temperature": 0.2,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
]
}
response = requests.post(URL, headers=headers, json=payload)
data = response.json()
return data["choices"][0]["message"]["content"]
query = "Apa manfaat semantic search?"
hasil = semantic_search(query, dokumen, top_k=1)
context_terbaik = hasil[0]["dokumen"]
jawaban = ask_llm_with_context(query, context_terbaik)
print(jawaban)Praktikum 9: contoh semantic search dalam PHP
Di PHP, perhitungan embedding biasanya dibantu API atau layanan model lain. Contoh berikut menunjukkan alur dasar pengurutan hasil similarity jika embedding sudah tersedia.
<?php
function cosineSimilarity($a, $b) {
$dot = 0;
$normA = 0;
$normB = 0;
for ($i = 0; $i < count($a); $i++) {
$dot += $a[$i] * $b[$i];
$normA += $a[$i] * $a[$i];
$normB += $b[$i] * $b[$i];
}
if ($normA == 0 || $normB == 0) {
return 0;
}
return $dot / (sqrt($normA) * sqrt($normB));
}
$queryEmbedding = [0.12, 0.45, 0.30, 0.11];
$dokumen = [
['teks' => 'Preprocessing membersihkan teks.', 'embedding' => [0.10, 0.40, 0.28, 0.12]],
['teks' => 'Semantic search mencari berdasarkan makna.', 'embedding' => [0.11, 0.46, 0.31, 0.10]],
['teks' => 'KNN adalah algoritma klasifikasi.', 'embedding' => [0.60, 0.10, 0.05, 0.20]],
];
foreach ($dokumen as &$item) {
$item['score'] = cosineSimilarity($queryEmbedding, $item['embedding']);
}
usort($dokumen, function($x, $y) {
return $y['score'] <=> $x['score'];
});
print_r($dokumen);
?>Kesalahan umum pada semantic search
Kesalahan pertama adalah menganggap semantic search selalu sempurna. Padahal hasil tetap bergantung pada model embedding dan kualitas dokumen. Kesalahan kedua adalah memakai dokumen terlalu panjang tanpa dipotong, sehingga satu embedding mewakili terlalu banyak isi campuran. Kesalahan ketiga adalah tidak membandingkan dengan keyword search, padahal kadang pencarian kata masih sangat berguna. Kesalahan keempat adalah langsung memberi jawaban generatif tanpa memastikan dokumen retrieval benar-benar relevan.
Semantic search sangat kuat, tetapi bukan sihir. Jika dokumen sumber buruk atau query terlalu kabur, hasil retrieval juga bisa meleset.
Diskusi Mahasiswa dengan Sistem LLM
Tanyakan materi yang masih terkait Pembelajaran Mesin untuk Teks dan AI Generatif.
Pembahasan dibatasi pada topik mata kuliah ini. Pertanyaan di luar tema akan ditolak secara otomatis.