Belajar Generative AI - Embeddings & Vector Databases
Episode 6 of 25

Belajar Generative AI - Embeddings & Vector Databases

Memahami text embeddings: mengubah makna teks menjadi vektor angka, cosine similarity untuk semantic search, lalu membangun vector database dengan ChromaDB, Qdrant, Pinecone, atau Weaviate — lengkap dengan indexing, metadata filtering, dan hybrid search keyword + vektor.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 5 kalian berhasil mengintegrasikan LLM ke aplikasi dengan streaming dan structured output, tibalah pertanyaan berikutnya: bagaimana membuat aplikasi AI memahami data kita sendiri? LLM tidak tahu isi dokumen internal perusahaan, manual produk, atau basis pengetahuan tim. Jawabannya dimulai dari embeddings dan vector databases — fondasi dari RAG yang kita bangun di episode 7.

Mengapa ini penting? Karena pencarian berdasarkan kata kunci (keyword search) sudah tidak cukup. Pengguna bertanya "gimana cara reset password", padahal dokumentasi menulis "memulihkan kredensial akun". Embeddings menangkap makna, bukan sekadar ejaan — dan itu membuat perbedaan antara aplikasi yang "kurang lebih membantu" dan yang "paham".

Text Embeddings: Teks Menjadi Angka

Sebuah embedding model mengubah sepotong teks menjadi vektor angka (misal 768 atau 1536 dimensi), dengan sifat kunci: teks yang maknanya mirip akan menghasilkan vektor yang berdekatan.

Buat embedding pertama
from openai import OpenAI
 
client = OpenAI()
 
def embed(text):
    r = client.embeddings.create(model="text-embedding-3-small", input=text)
    return r.data[0].embedding
 
v1 = embed("cara mengatur ulang kata sandi")
v2 = embed("bagaimana cara reset password akun")
v3 = embed("resep rendang sapi khas minang")
 
print(len(v1))  # 1536

Tiga kalimat di atas menghasilkan tiga vektor; v1 dan v2 akan berdekatan (makna sama), sementara v3 menjauh (makna berbeda). Ukuran vektor menentukan biaya penyimpanan dan kecepatan pencarian — model embedding yang lebih besar (misal text-embedding-3-large) lebih akurat tetapi lebih mahal.

Cosine Similarity: Mengukur Kedekatan

Ada beberapa cara mengukur kedekatan vektor; yang paling umum adalah cosine similarity — kosinus sudut antara dua vektor, bernilai 1 (searah) sampai -1 (berlawanan).

Cosine similarity manual vs library
import numpy as np
 
def cosine(a, b):
    return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
 
print("pertanyaan mirip:", round(cosine(v1, v2), 3))  # ~0.9x
print("topik berbeda:", round(cosine(v1, v3), 3))     # jauh lebih rendah

Perhatikan: cosine similarity tidak bergantung pada panjang teks (vektor dinormalisasi), jadi teks pendek dan panjang tetap bisa dibandingkan secara adil — inilah mengapa ia dipilih untuk semantic search.

Semantic Search: Dari Query ke Dokumen

Semantic search bekerja dalam tiga langkah: embed semua dokumen → simpan sebagai vektor → untuk sebuah query, embed query lalu cari dokumen dengan similarity tertinggi.

100%

Masalahnya: mencari similarity di atas jutaan vektor dengan brute-force (bandingkan semua) terlalu lambat. Di sinilah vector database masuk dengan index ANN (approximate nearest neighbor).

Vector Databases: Mengapa dan Mana yang Dipakai

Vector DB menyimpan vektor + metadata, dan menyediakan pencarian tetangga terdekat secara efisien (index seperti HNSW, IVF), beserta filter metadata. Pilihan utamanya:

EngineJenisKapan Dipakai
ChromaDBEmbedded/lokalEksperimen, prototipe, tanpa server
QdrantServer/DockerProduksi self-host, Rust, cepat
WeaviateServer/DockerProduksi, fitur hybrid search native
PineconeSaaS/managedTanpa urusan operasional, skala besar

Untuk series ini kita mulai dengan ChromaDB karena tanpa server — cukup pip install chromadb.

Ingest dan query dengan ChromaDB
import chromadb
 
client = chromadb.PersistentClient(path="./vectordb")
collection = client.get_or_create_collection("docs")
 
collection.add(
    ids=["doc-1", "doc-2", "doc-3"],
    embeddings=[v1, v2, v3],
    metadatas=[{"category": "faq", "date": "2026-01-01"},
               {"category": "faq", "date": "2026-02-01"},
               {"category": "recipe", "date": "2026-03-01"}],
)
 
res = collection.query(query_embeddings=[embed("lupa password")], n_results=2)
print(res["ids"])  # doc-1 atau doc-2 paling relevan

Dengan ChromaDB, embed query dan pencarian digabung jadi satu operasi — ini pola inti yang akan kita pakai untuk membangun RAG di episode 7.

Metadata Filtering

Sering kali kita tidak hanya ingin "yang paling mirip", tetapi "yang paling mirip dari kategori tertentu". ChromaDB mendukung pre-filter:

Filter sebelum similarity search
res = collection.query(
    query_embeddings=[embed("cara reset")],
    where={"category": {"$eq": "faq"}},     # hanya kategori faq
    n_results=2,
)

Filter metadata menurunkan jumlah kandidat sebelum pencarian vektor — lebih cepat dan hasil lebih relevan.

Hybrid search menggabungkan keyword search (BM25/FT) dengan vector search. Mengapa? Untuk istilah teknis eksak (kode, nama produk seperti "ChromaDB") keyword search sering menang, sementara untuk makna ("cara ganti kata sandi") vector search menang. Qdrant dan Weaviate punya dukungan native; di ChromaDB bisa disimulasikan dengan menggabungkan hasil dua pencarian.

Idea hybrid: gabungkan dua ranking
# 1. Vector: cari 20 terdekat maknanya
vec_hits = collection.query(query_embeddings=[embed(q)], n_results=20)
 
# 2. Keyword: cari istilah eksak di metadata/content
kw_hits = collection.query(query_texts=[q], n_results=20)
 
# 3. Gabungkan (reciprocal rank fusion) → ranking final

Kombinasi ini adalah standar produksi untuk retrieval yang robust — kita perdalam di episode 8 (RAG lanjutan).

Common Pitfalls

  • Biasa meng-embed query dan dokumen dengan model berbeda: harus konsisten satu embedding model, jika tidak jarak antar-vektor tidak bermakna.
  • Mengubah embedding model tanpa re-index: mengganti model berarti seluruh vektor lama harus dibuat ulang.
  • Index default tanpa filter: untuk dataset besar dengan banyak kategori, aktifkan filter sejak awal.
  • Memakai vektor untuk angka/teks pendek: embedding lemah untuk string pendek acak (ID, kode) — campur dengan keyword search.

Tip

Simpan teks asli di metadata/collection bersama embedding-nya. Vektor saja tidak bisa ditampilkan ke pengguna — retrieval selalu perlu mengambil teks sumber untuk konteks RAG (episode 7) dan untuk menampilkan citation.

Penutup

Inti yang harus dibawa pulang:

  • Embedding mengubah teks jadi vektor; teks bermakna mirip menghasilkan vektor berdekatan.
  • Cosine similarity mengukur kedekatan vektor secara normalisasi panjang.
  • Vector DB (ChromaDB, Qdrant, Pinecone, Weaviate) menyediakan index ANN + metadata filter.
  • Metadata filtering & hybrid search meningkatkan kualitas retrieval secara signifikan.

Di episode 7 selanjutnya kita akan membangun RAG (Retrieval-Augmented Generation) secara utuh — chunking, indexing, retrieval, dan generation yang grounded pada dokumen — plus pipeline dokumen PDF/website ke Q&A dan evaluasi retrieval & kualitas jawaban. Sampai jumpa di episode 7!