Jawaban singkat: nomic-embed-text berukuran 274.302.450 byte di disk, punya 137 juta parameter dalam format F16, dan menghasilkan vektor 768 dimensi. Pada host uji tanpa GPU (3 vCPU, RAM 3.915 MB), satu embedding butuh median 0,133 detik setelah model termuat, dengan panggilan pertama 2,334 detik karena proses pemuatan model. Delapan belas embedding berurutan selesai dalam 2,02 detik, jadi sekitar 0,11 detik per teks pada kondisi hangat.
- TL;DR model 274 MB, 137 juta parameter F16, vektor 768 dimensi, konteks 2.048 token.
- Panggilan pertama 2,334 detik, panggilan berikutnya 0,102 sampai 0,295 detik dengan median 0,133 detik.
- Kemiripan antar kalimat parafrase 0,8617 dan 0,9072, sedangkan antar topik berbeda 0,4172 dan 0,4454.
- Vektor keluaran tidak dinormalisasi: panjangnya 20,5986, jadi normalisasi tetap tugas pemanggil.
- Seluruh uji berjalan di CPU, tanpa GPU dan tanpa akselerasi perangkat keras khusus.
Embedding adalah langkah pertama hampir semua sistem pencarian dan tanya-jawab berbasis dokumen. Menjalankannya lokal menghapus biaya per panggilan dan ketergantungan jaringan, dengan harga berupa memori dan CPU. Angka di bawah ini menjawab pertanyaan yang paling sering muncul sebelum memilih jalur lokal: seberapa besar, seberapa cepat, dan apakah kualitasnya cukup untuk membedakan topik.
Berapa ukuran dan dimensi modelnya?
Model yang dipakai adalah nomic-embed-text varian terbaru dari pustaka Ollama, dengan keluarga arsitektur nomic-bert, 137 juta parameter, dan kuantisasi F16. Berkas modelnya 274.302.450 byte, jadi sekitar 274 MB di disk dan hampir sama besar saat dimuat ke memori. Angka konteks yang dilaporkan model adalah 2.048 token, dan panjang vektor keluarannya 768 dimensi, yang terkonfirmasi langsung dari hasil pemanggilan pertama.
Dua angka itu penting untuk perencanaan. Dengan 768 dimensi dan tipe data float32, satu vektor memakan 3.072 byte sebelum kompresi. Untuk 100.000 potongan dokumen, itu berarti sekitar 307 MB hanya untuk vektor, belum termasuk indeks dan metadata. Bila koleksinya sampai jutaan potongan, penyimpanan vektor menjadi pertimbangan tersendiri, dan penggunaan format float16 atau kuantisasi vektor bisa memotongnya separuh.
Berapa kecepatan embedding di CPU tanpa GPU?
Enam kalimat pendek diuji berurutan pada mesin yang sama. Panggilan pertama jauh lebih lambat karena model baru dimuat, sedangkan panggilan berikutnya menunjukkan kecepatan sebenarnya. Variasi 0,102 sampai 0,295 detik di antaranya berasal dari panjang kalimat dan jadwal proses lain di mesin.
| Urutan panggilan | Waktu | Catatan |
|---|---|---|
| 1 | 2,334 detik | termasuk pemuatan model ke memori |
| 2 | 0,107 detik | kondisi hangat |
| 3 | 0,102 detik | kondisi hangat |
| 4 | 0,133 detik | kalimat lebih panjang |
| 5 | 0,104 detik | kondisi hangat |
| 6 | 0,295 detik | ada proses lain berjalan bersamaan |
Untuk beban kerja nyata, pola yang berlaku bukan median per panggilan, melainkan total waktu per dokumen. Satu dokumen 1.000 kata perlu dipecah menjadi beberapa potongan, dan tiap potongan adalah satu panggilan HTTP ke server embedding. Pada laju sekitar 0,11 detik per potongan, 1.000 potongan selesai dalam waktu sekitar dua menit di mesin 3 vCPU ini, dan itu bisa dipercepat dengan batched request dari sisi klien karena server memproses permintaan secara berurutan.
Apakah skor kemiripannya masuk akal?
Enam kalimat dari tiga topik berbeda diuji: dua pasang parafrase dan dua kalimat yang topiknya jauh. Hasilnya memisahkan parafrase dari topik berbeda dengan jarak yang cukup lebar, yang berarti vektor ini bisa dipakai untuk pencarian kemiripan tanpa penyesuaian tambahan.
| Pasangan kalimat | Kemiripan kosinus | Tafsir |
|---|---|---|
| Dua kalimat soal instalasi Docker di Ubuntu 24.04 | 0,8617 | parafrase, sangat mirip |
| Dua kalimat soal konfigurasi nginx sebagai reverse proxy | 0,9072 | parafrase, sangat mirip |
| Instalasi Docker dibanding resep nasi goreng | 0,4172 | topik berbeda |
| Instalasi Docker dibanding harga tiket kereta | 0,4454 | topik berbeda |
Jarak antara 0,86 dan 0,42 terlihat lega, tapi jangan langsung memakai 0,6 sebagai ambang untuk semua data. Skor kemiripan bergantung pada panjang teks dan gaya bahasa, dan pada kalimat pendek nilainya cenderung lebih tinggi secara umum. Yang lebih aman: ambil ambang dari data Anda sendiri dengan menyiapkan beberapa pasang positif dan negatif, lalu pilih nilai yang memisahkan keduanya.
Pentingnya normalisasi vektor
Karena panjang vektor yang dikembalikan bukan 1. Pada uji ini norma vektor pertama adalah 20,5986. Artinya bila Anda menghitung perkalian titik langsung tanpa normalisasi, hasilnya bukan kemiripan kosinus melainkan skor yang ikut dipengaruhi panjang vektor, sehingga dokumen dengan vektor lebih panjang bisa mendominasi peringkat. Kemiripan kosinus di tabel sebelumnya dihitung setelah membagi tiap vektor dengan normanya.
Beberapa basis data vektor menerima jarak kosinus sebagai parameter dan menormalkan sendiri di dalam, jadi hasilnya tetap benar. Yang berbahaya adalah menyimpan vektor lalu memakai perkalian titik dengan asumsi vektor sudah berskala satu. Kesalahan ini tidak menimbulkan error, hanya peringkat hasil pencarian yang tampak sedikit aneh, dan itu jenis bug yang paling sulit dilacak. Normalisasi sekali saat penyimpanan, atau pastikan basis data vektor yang dipakai memang menangani jarak kosinus.
Kapan embedding lokal lebih masuk akal daripada API?
Lokal menang bila dokumennya sensitif dan tidak boleh keluar dari jaringan, bila volume embedding-nya besar dan berjalan berulang, atau bila Anda butuh proses yang tetap hidup tanpa internet. API menang bila Anda butuh kualitas tertinggi, dimensi besar, atau model yang terus diperbarui tanpa biaya operasional sendiri. Perbandingan di bawah ini memakai angka yang terukur di host uji, ditambah pertimbangan yang bersifat arsitektural.
| Pertimbangan | Embedding lokal | Embedding lewat API |
|---|---|---|
| Biaya per 1.000 potongan | nol biaya panggilan, hanya listrik dan waktu CPU | berbayar per token |
| Kecepatan pada 3 vCPU | sekitar 110 detik per 1.000 potongan | bergantung jaringan dan batas laju |
| Kerahasiaan data | dokumen tidak meninggalkan host | dokumen dikirim ke penyedia |
| Beban operasional | perlu menjalankan dan memantau server embedding | tidak ada |
| Ukuran model | 274 MB untuk nomic-embed-text | tidak relevan |
Ada satu batasan yang perlu diingat: konteks model ini 2.048 token. Potongan dokumen yang lebih panjang dari itu akan dipotong, dan bagian akhirnya hilang tanpa peringatan. Untuk chunking, ukuran 300 sampai 500 token per potongan jauh lebih aman dan juga membuat kualitas pencarian lebih baik, karena satu vektor yang mewakili terlalu banyak topik cenderung kabur.
Cara memanggil endpoint embedding
Endpoint yang dipakai pada pengukuran ini menerima permintaan POST berisi JSON dengan dua medan: nama model dan teks yang akan diubah menjadi vektor. Jawabannya berisi array angka dengan panjang 768. Tidak ada parameter dimensi tambahan yang perlu dikirim, karena panjang vektor sudah ditentukan oleh model yang dimuat. Bila nama modelnya tidak cocok dengan yang terpasang, permintaan akan gagal, jadi nama model sebaiknya dibaca dari daftar model yang tersedia sebelum dipakai di kode.
Pada uji ini, panggilan pertama memakan 2,334 detik karena model dimuat ke memori. Perilaku itu penting untuk desain sistem: jangan menaruh panggilan embedding pertama di jalur yang sensitif terhadap waktu, misalnya saat pengguna menekan tombol cari. Lakukan pemanasan sekali setelah layanan hidup, atau jalankan warm-up dengan satu teks pendek supaya permintaan nyata berikutnya mendapat respons di kisaran 0,1 detik.
Untuk volume besar, kirim teks satu per satu tapi jaga koneksi tetap hidup, karena sebagian besar waktu hilang di pembukaan koneksi bila klien membuat koneksi baru setiap permintaan. Pada uji throughput, 18 panggilan berurutan selesai dalam 2,02 detik, yang berarti sekitar 0,11 detik per teks termasuk overhead HTTP. Angka itu berguna sebagai dasar perkiraan: seribu potongan dokumen akan memakan waktu sekitar dua menit pada mesin yang sama.
Yang perlu dihindari adalah memotong vektor sendiri tanpa memahami konsekuensinya. Beberapa model mendukung pemotongan dimensi, tapi kualitas kemiripan setelah pemotongan tidak otomatis sama. Bila Anda butuh vektor lebih kecil untuk menghemat ruang, ukur dulu dampaknya pada sekumpulan pasangan uji, karena penurunan kualitas akibat pemotongan tidak muncul sebagai error, hanya sebagai hasil pencarian yang kurang tepat.
Simpan juga model dan versinya bersama vektor. Bila model diganti, vektor lama dan vektor baru tidak bisa dibandingkan karena ruang vektornya berbeda. Mencampur keduanya di satu indeks akan menghasilkan skor kemiripan yang tidak bermakna, dan kesalahan ini sulit terdeteksi karena semuanya tetap berjalan tanpa pesan error.
Penanganan error juga perlu dipikirkan sejak awal. Bila server embedding mati, permintaan yang sedang berjalan akan gagal, dan mengulanginya tanpa jeda hanya memperpanjang antrean. Batasi percobaan ulang, beri jeda yang bertambah, lalu tandai potongan yang gagal agar bisa diproses ulang nanti tanpa membangun ulang seluruh indeks dari nol.
Untuk pemakaian jangka panjang, catat juga waktu respons rata-rata di sisi klien. Angka median 0,133 detik di atas berasal dari pengukuran bersih tanpa beban lain, dan pada mesin yang juga menjalankan basis data serta web server, waktu nyata bisa lebih panjang. Mencatatnya membuat perencanaan kapasitas berdiri di atas data sendiri, bukan di atas angka mesin yang kebetulan sedang kosong.
FAQ
Apakah model ini butuh GPU?
Tidak. Seluruh uji di atas berjalan di CPU dengan 3 vCPU dan RAM 3.915 MB, dan model 274 MB tetap memberi median 0,133 detik per teks. GPU mempercepat proses, terutama untuk batch besar, tapi untuk koleksi puluhan ribu potongan yang dibangun sekali, CPU sudah memadai.
Berapa dimensi vektor yang dihasilkan?
768 dimensi, terkonfirmasi dari panjang array hasil pemanggilan. Dengan float32, satu vektor memakan 3.072 byte, jadi 100.000 potongan membutuhkan sekitar 307 MB penyimpanan vektor sebelum kompresi. Angka ini yang dipakai untuk menghitung kebutuhan disk indeks.
Apakah embedding perlu dihitung ulang bila dokumen berubah?
Ya, untuk potongan yang berubah saja. Vektor terikat pada isi teks, jadi setiap penyuntingan membuat vektor lama tidak lagi mewakili potongan tersebut. Simpan sidik jari isi potongan bersama vektornya supaya proses pembaruan hanya menghitung ulang yang benar-benar berubah.
Apakah 2.048 token cukup untuk satu dokumen?
Untuk satu potongan, cukup. Untuk dokumen utuh, tidak. Praktik yang lazim adalah memecah dokumen menjadi potongan 300 sampai 500 token dengan sedikit tumpang tindih, lalu memberi embedding per potongan. Satu dokumen panjang diwakili banyak vektor, bukan satu vektor tunggal yang kehilangan detail.
Rujukan resmi untuk model dan API yang dipakai: kartu model nomic-embed-text di Ollama, model card nomic-embed-text-v1.5 di Hugging Face, dokumentasi API Ollama, dan paper MTEB tentang evaluasi embedding.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬