π§ Embedding Model Selection & Fine-Tuning β Dari text-embedding-3-small ke Model Domain-Spesifik
Embedding model adalah jantung semantic search β ia yang menentukan seberapa baik makna dokumen ditangkap dalam ruang vektor. Memilih model yang salah berarti chunk terbaik pun tidak akan ter-retrieve. Dokumen ini membedah spektrum embedding model dari yang proprietary (OpenAI, Cohere) hingga open-source (BGE, E5, Jina), konsep dimensi & Matryoshka embeddings, fine-tuning dengan LoRA untuk domain spesifik, dan strategi eval untuk memilih model yang tepat untuk vault ini.
Hubungan ke Vault
vault-rag saat ini menggunakan
text-embedding-3-smallvia 9Router API. Catatan ini membahas alternatif (BGE, E5, Jina) dan kapan fine-tuning diperlukan. Terkait dengan advanced-chunking-strategies-deepdive (kualitas chunk = kualitas embedding), vector-database-internals-optimization (dimensi vector β performa index), index_vault.py (implementasi embedding), dan rag-evaluation-framework (metric embedding quality).
Daftar Isi
- 1. Embedding 101
- 2. Perbandingan Model
- 3. Matryoshka Embeddings
- 4. Fine-Tuning
- 5. Eval Embedding untuk Vault Ini
- Koneksi ke Vault
- References
1. Embedding 101
1.1 Cara Kerja
Embedding model mengubah teks menjadi vektor angka (float array) di ruang dimensi tetap. Prinsipnya: teks dengan makna serupa punya vektor yang berdekatan (cosine similarity tinggi).
"TCP handshake" β [0.23, -0.45, 0.12, ..., 0.89] (1536 dimensi)
"SYN flood" β [0.21, -0.42, 0.15, ..., 0.85] (similarity: 0.95)
"resep nasi goreng" β [-0.12, 0.55, -0.33, ..., 0.01] (similarity: 0.12)
| Konsep | Penjelasan |
|---|---|
| Dimensi | Panjang vector. Makin tinggi β makin detail (tapi makin mahal storage & compute) |
| Pooling | Cara model menggabungkan token embeddings jadi satu vector (CLS, mean, max) |
| Normalization | Vector dinormalisasi ke unit length (L2 norm) biar cosine similarity = dot product |
| Context length | Maks token yang bisa diproses sekaligus. > context length β truncation |
1.2 Context Length Penting buat Chunking
Kalo embedding model punya context length 512 token, chunk lo harus β€512 token. Kalo lo pake model dengan 8192 token context (seperti text-embedding-3-large), chunk bisa lebih panjang. Tapi lebih panjang β lebih baik β chunk panjang mencampur banyak topik β embedding jadi βrata-rataβ dari semuanya β presisi turun.
2. Perbandingan Model
2.1 Model Matrix
| Model | Dimensi | Context | MTEB* | Harga | Open Source | Catatan Vault |
|---|---|---|---|---|---|---|
| text-embedding-3-small | 1536 (dapat 256/512/1024) | 8191 | 62.3 | π² $0.02/1M token | β | Saat ini dipake vault-rag |
| text-embedding-3-large | 3072 (dapat 256/512/1024/1536) | 8191 | 64.6 | π² $0.13/1M token | β | Lebih akurat, 6.5x lebih mahal |
| Cohere Embed v3 | 1024 | 512 | 62.0 | π² $0.10/1M | β | Binary quantization built-in |
| BGE-M3 | 1024 | 8192 | 64.0 | π Gratis | β Multi-lingual | Bisa multi-vector (sparse + dense) |
| BGE-large-en-v1.5 | 1024 | 512 | 63.0 | π Gratis | β | Best open-source English |
| E5-mistral-7b-instruct | 4096 | 4096 | 66.6 | π Gratis | β | Best overall, tapi butuh GPU 16GB+ |
| Jina-embeddings-v3 | 1024 | 8192 | 64.2 | π Gratis | β | Multi-lingual, task-specific LoRA |
| GTE-Qwen2-7B | 3584 | 8192 | 64.8 | π Gratis | β | Best open-source China |
| Snowflake Arctic-embed-m | 768 | 512 | 61.0 | π Gratis | β | Ringan, cocok buat produksi |
*MTEB = Massive Text Embedding Benchmark (rata-rata dari 56 dataset). Makin tinggi = makin baik.
2.2 Trade-off untuk Vault Ini
| Skenario | Model Rekomendasi | Alasan |
|---|---|---|
| Saat ini (9Router API) | text-embedding-3-small (256d) | OK. Cukup untuk production. Turunin dimensi ke 256 via Matryoshka |
| Local / offline | BGE-M3 atau Snowflake Arctic-embed-m | Open source, multilingual (BGE-M3), ringan |
| Max akurasi (ada GPU) | E5-mistral-7b-instruct atau gte-Qwen2-7B | Skor MTEB tertinggi |
| Multi-lingual (EN+ID) | BGE-M3 atau Jina-embeddings-v3 | Dukungan bahasa Indonesia |
3. Matryoshka Embeddings
3.1 Konsep
Matryoshka embedding = satu model bisa menghasilkan vector dengan dimensi variabel tanpa fine-tuning. Misal text-embedding-3-small mendukung 256, 512, 1024, atau 1536 dimensi β dari model yang SAMA.
# OpenAI: pake dimensions parameter
import openai
response = openai.embeddings.create(
model="text-embedding-3-small",
input="TCP handshake",
dimensions=256 # Matryoshka! 1536 β 256 tanpa loss signifikan
)Trade-off dimensi:
| Dimensi | Ukuran Index (1M vektor) | Performa Search | Akurasi (relatif) |
|---|---|---|---|
| 256 | ~200 MB | π’ Sangat cepat | 97% dari 1536 |
| 512 | ~400 MB | π’ Cepat | 99% |
| 1024 | ~800 MB | π‘ Normal | 99.8% |
| 1536 | ~1.2 GB | π‘ Normal | 100% |
Untuk vault-rag: Bisa turunin ke 256d tanpa kehilangan akurasi signifikan β index sqlite-vec lebih kecil, query lebih cepat.
4. Fine-Tuning
4.1 Kapan Perlu?
| Situasi | Fine-Tuning? | Contoh |
|---|---|---|
| Domain umum (Wikipedia, Reddit) | β Tidak perlu | Vault ini masih tahap ini |
| Domain teknis sempit (hukum, medis) | π‘ Mungkin | Kode hukum, terminologi medis |
| Bahasa/slang spesifik | π‘ Mungkin | Bahasa Indonesia campur Inggris vault ini? Perlu test |
| Query-doc distribution mismatch | β Ya | Query pendek β dokumen panjang. Atau sebaliknya |
Untuk vault ini sekarang: text-embedding-3-small sudah OK karena vault membahas topik mainstream (cybersecurity, networking, Linux). Fine-tuning baru perlu kalo vault mulai masuk ke niche teknis yang embedding model umum gak nangkep (misal: istilah lokal Indonesia, singkatan internal).
4.2 LoRA Fine-tuning dengan Sentence Transformers
from sentence_transformers import SentenceTransformer, SentenceTransformerTrainer
from sentence_transformers.losses import CoSENTLoss
from datasets import Dataset
# 1. Load model
model = SentenceTransformer("BAAI/bge-large-en-v1.5")
# 2. Siapkan data (query, positive, negative)
train_data = [
{"query": "TCP handshake", "positive": "Three-way handshake SYN-SYN-ACK", "negative": "HTTP status codes"},
{"query": "buffer overflow", "positive": "Stack buffer overflow exploitation", "negative": "Race condition"},
]
dataset = Dataset.from_list(train_data)
# 3. LoRA config
from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["query", "value"], # LoRA pada attention layer
lora_dropout=0.1,
)
# 4. Train (1 epoch biasanya cukup untuk domain adaptation)
trainer = SentenceTransformerTrainer(
model=model,
train_dataset=dataset,
loss=CoSENTLoss(model),
args=..., # TrainingArguments
)
trainer.train()
# 5. Save
model.save_pretrained("./bge-finetuned-vault")5. Eval Embedding untuk Vault Ini
# Sederhana: test dengan query konkret vault
test_queries = [
("Apa itu TCP handshake?", {"related": ["networking-fundamentals-tcpip-bgp.md"]}),
("Cara detect SYN flood", {"related": ["networking-fundamentals-tcpip-bgp.md"]}),
("Apa itu LSASS?", {"related": ["active-directory-windows-security-deepdive.md"]}),
]
def eval_embedding(model_name, dimension=256):
scores = []
for query, expected in test_queries:
q_vec = embed(query, model_name, dimension)
# Search di vault-rag DB
results = search_dense(q_vec, top_k=5)
# Hitung recall@5: apakah file terkait muncul?
related_files = set(results) & expected["related"]
recall = len(related_files) / len(expected["related"])
scores.append(recall)
return sum(scores) / len(scores)Koneksi ke Vault
- advanced-chunking-strategies-deepdive β Kualitas chunk memengaruhi kualitas embedding. Chunk terlalu panjang β embedding jadi rata-rata
- vector-database-internals-optimization β Dimensi embedding β performa index HNSW β tuning
- hybrid-search-vector-keyword β Embedding + BM25 = hybrid search. Sparse embedding (BGE-M3) juga bahas di sini
- rag-evaluation-framework β Metric retrieval quality: recall@k, MRR, NDCG
- index_vault.py β Implementasi embedding:
ollama_api.embed()paketext-embedding-3-small
References
- MTEB Leaderboard. https://huggingface.co/spaces/mteb/leaderboard
- OpenAI. Embeddings API. https://platform.openai.com/docs/guides/embeddings
- BGE-M3. https://huggingface.co/BAAI/bge-m3
- E5-mistral-7b-instruct. https://huggingface.co/intfloat/e5-mistral-7b-instruct
- Jina Embeddings v3. https://huggingface.co/jinaai/jina-embeddings-v3
- Sentence Transformers. Training Overview. https://www.sbert.net/docs/training/overview.html
- Matryoshka Embeddings. OpenAI Cookbook. https://cookbook.openai.com/examples/vector_store/using_matteyoshka_embeddings
Bottom Line
Embedding model menentukan kualitas semantic search. Buat vault ini:
text-embedding-3-small(256d via Matryoshka) sudah OK. Open source alternatif: BGE-M3 (multilingual, sparse support) atau Snowflake Arctic-embed-m (ringan). Fine-tuning belum diperlukan β vault belum cukup niche. Eval berkala dengan query riil vault untuk deteksi kapan butuh upgrade atau fine-tuning.