Ternlight - model embedding 7MB yang berjalan di browser (WASM)
(ternlight-demo.vercel.app)- Melakukan embedding teks dan pencarian kemiripan langsung di dalam browser tanpa pemanggilan server, sehingga pencarian semantik dapat dibangun dengan cepat
- Berjalan hanya dengan CPU tanpa GPU, dan paket dasar berukuran 7MB termasuk engine dan bobot, sedangkan mini berukuran 5MB
- Mengintegrasikan engine, model, dan tokenizer BERT ke dalam satu file
.wasm, sehingga tidak memerlukan postinstall atau fetch saat runtime - Didistilasi dari model
all-MiniLM-L6dengan menerapkan quantization-aware training (QAT) gaya BitNet b1.58 - Setelah memasang
@ternlight/base, cukup imporembeddansimilaruntuk membuat alur pencarian semantik hanya dengan 3 baris kode - Mencapai kompresi 30× dengan hanya sedikit penurunan akurasi, sehingga memungkinkan pencarian privat, offline, dan edge tanpa round-trip jaringan
ternlight - embedding yang selesai di dalam browser
- Alat embedding semantik yang didistribusikan sebagai bundel WebAssembly 5–7MB, menempatkan engine + model + tokenizer dalam satu file untuk menjalankan pencarian embedding di CPU
- Melakukan embedding teks dalam hitungan milidetik tanpa memanggil server
- Menyediakan dua tier dengan API yang sama, dapat dipilih sesuai trade-off ukuran/kualitas
@ternlight/base— tier kualitas (7MB wire, sekitar 5ms per embedding)@ternlight/mini— tier kecil dan cepat (5MB wire, sekitar 2.5ms per embedding)
API inti
- Satu primitive: string → mengembalikan Float32Array 384 dimensi yang dinormalisasi L2
- Menyediakan tiga fungsi:
embed,cosineSim,similarcosineSim(embed('reset my password'), embed('I forgot my password'))→ 0.88similarmendukung pencarian tetangga terdekat pada korpus, dengantopKyang dapat ditentukan- Contoh: saat mencari 'I want my money back', akan mengembalikan 'Refunds: how to get your money back' (sim 0.70), 'Update your billing address' (sim 0.24)
- Berjalan di Node ≥ 18, browser (melalui bundler), Cloudflare Workers, Vercel Edge, Deno, dan Bun, dengan routing otomatis ke loader yang sesuai untuk tiap lingkungan
Prinsip desain
- Didistilasi dari
all-MiniLM-L6dan menerapkan quantization-aware training bergaya BitNet b1.58, mencapai ukuran beberapa MB melalui tiga pilihan desain -
Bobot ternary
- Semua bobot berupa salah satu dari
-1,0,+1, sehingga inferensi diproses dengan penjumlahan dan pengurangan - Model dilatih sebagai model ternary sejak awal untuk menjaga kualitas
- Semua bobot berupa salah satu dari
-
Bundel tunggal
- Mengintegrasikan model + tokenizer BERT + engine ke dalam satu
.wasm - Tidak ada tahap postinstall maupun fetch saat runtime
- Mengintegrasikan model + tokenizer BERT + engine ke dalam satu
-
Engine inferensi SIMD
- Rust yang ditulis manual dikompilasi ke WASM SIMD
- Operasi penjumlahan/pengurangan memanfaatkan instruksi vektor CPU
Metrik performa
- Semua angka diukur berdasarkan build int4 yang dirilis (Mac seri M, Node/V8)
-
@ternlight/mini
- Wire size (gzip wasm): 5.0MB, Latency (p50): 2.5ms
- Throughput (single-thread): sekitar 400 emb/s
- Spearman (dibanding guru): 0.820, Retrieval (SciFact NDCG@10): 0.439
- Arsitektur: 2-layer · d_model=256 · 4 heads, sekitar 9.5M parameter
-
@ternlight/base
- Wire size (gzip wasm): 7.2MB, Latency (p50): 5.1ms
- Throughput (single-thread): sekitar 195 emb/s
- Spearman (dibanding guru): 0.844, Retrieval (SciFact NDCG@10): 0.465
- Arsitektur: 2-layer · d_model=384 · 6 heads, sekitar 15.4M parameter
-
Spesifikasi umum
- Output: 384 dimensi dinormalisasi L2
- Input maksimum: 128 token (sekitar 95 kata)
- Kuantisasi: bobot ternary · embedding int4
Pemanfaatan embedding on-device
-
Search-as-you-type
- Menampilkan hasil sebelum pengguna selesai mengetik, lebih cepat daripada round-trip jaringan apa pun
-
Aplikasi sensitif privasi
- Query dan dokumen tidak meninggalkan perangkat, sehingga tidak ada kebutuhan kontrak pemrosesan data maupun risiko kebocoran
-
Aplikasi offline-first
- Ekstensi browser, plugin Obsidian, aplikasi desktop
-
Aplikasi runtime edge
- Di Cloudflare Workers, Deno Deploy, dan Vercel Edge, embedding ditempatkan di lokasi yang sama dengan request handler sehingga tidak perlu memanggil layanan inferensi terpisah
-
Perangkat edge dan hardware IoT
- Raspberry Pi, komputer papan tunggal, gateway industri, kios
- Operasi penjumlahan/pengurangan berjalan efisien di core ARM sehingga tidak memerlukan GPU maupun NPU
-
Situs statis
- Di Jekyll, Hugo, dan Astro, model dapat didistribusikan bersama bundel untuk menjalankan pencarian semantik tanpa backend
Contoh instalasi dan penggunaan
- Disediakan sebagai satu paket npm, dan dapat digunakan tanpa tahap unduhan model terpisah maupun server
- Perintah instalasinya adalah sebagai berikut
npm install @ternlight/base - Impor
embeddansimilardari@ternlight/baseuntuk menjalankan pencarian berbasis maknaimport { embed, similar } from '@ternlight/base'; similar('easy weeknight dinner ideas', recipes, { topK: 3 }); // → ranked matches · ~5 ms · zero network
Open source dasar dan lisensi
- BitNet b1.58 (Ma et al., Microsoft Research, 2024) — riset arsitektur untuk pelatihan bobot ternary
bitlinear— implementasi referensi PyTorch untuk BitLinear, digunakan langsung saat pelatihan (bitlinear==2.4.6) dan engine inferensi Rust merefleksikan operasi forward pass yang samasentence-transformers/all-MiniLM-L6-v2— model guru tempat model siswa didistilasi- Lisensi: MIT
1 komentar
Komentar Hacker News
Karena ingin mencoba menjalankan model yang berguna di browser sebagai proyek hobi, saya mendistilasi encoder kalimat kecil dari MiniLM dan menerapkan pelatihan sadar kuantisasi ternary
Mesin inferensinya juga saya tulis sendiri dan didistribusikan dari Rust → WASM SIMD
Ini bukan LLM, melainkan model embedding: jika diberi teks, ia menghasilkan vektor 384 dimensi, lalu relevansi teks dinilai dengan kemiripan kosinus antara dua vektor. Misalnya, "reset my password" dan "I forgot my password" bisa menghasilkan nilai seperti 0,88
Bisa dipakai untuk pencarian berbasis makna, pencocokan FAQ/intensi, dan clustering; karena berjalan di perangkat, pencarian semantik dapat dilakukan cepat begitu input masuk tanpa bergantung pada API
Demonya mencari 2.000 dokumen React sepenuhnya di perangkat: https://ternlight-demo.vercel.app
Di npm ada dua tingkat: @ternlight/base (7MB, sekitar 5ms per embedding, embedding dengan performa lebih baik) dan @ternlight/mini (transfer 5MB, sekitar 2,5ms per embedding), dan keduanya dibundel untuk Node serta browser
Repositorinya mencakup detail teknis, lisensi MIT, dan pipeline pelatihan: https://github.com/soycaporal/ternlight
Saya penasaran apakah embedding di perangkat benar-benar berguna, dan use case apa saja yang ada
Saya penasaran apakah ini bisa membantu membuat pengguna menemukan crêpe saat mengetik "pancake", tanpa harus menulis entri kamus eksplisit "pancake = crêpe"
Kalau pemahaman saya benar, apakah strukturnya library mengunduh 5MB sekali di awal, lalu setelah itu dipakai seperti kami sekarang memakai Fuse.js?
Saya juga ingin tahu seberapa baik ia menangani bahasa selain Inggris, dan apakah bisa dilatih dengan wiki tag OpenStreetMap
Penasaran apakah ada perbandingan dengan model embedding superkecil lain. Sulit menilai apakah alasan memulai dari MiniLM-L6 adalah karena model itu sangat bagus di kelas yang sama, sementara metrik yang diberikan hanya "Retrieval (SciFact NDCG@10)"
Namun hasilnya cukup jauh dari performa yang diklaim: di Firefox pada i5-4570, saya hanya mendapat 35 embedding per detik, bukan 400 per detik. Saya menduga ada masalah sehingga jatuh ke jalur non-SIMD, dan berencana mencoba binary Rust native juga
Keren, tapi akan bagus kalau landing page punya tombol untuk memulai demo. Saya cukup kaget karena begitu membuka halaman web, terdengar kipas berputar seperti gila
Akan bagus kalau dibuat sebagai plugin Astro atau plugin meta-framework umum yang otomatis mem-parsing semua file HTML yang dihasilkan dan membuat database embedding kecil
Di frontend, ini bisa dimuat secara lazy, dan HNSW mungkin juga bisa disimpan per chunk sehingga hanya bagian yang diperlukan untuk query pencarian yang dimuat
Misalnya mirip https://pagefind.app/, tetapi menyediakan pencarian vektor yang sepenuhnya statis
Kalau setelah beberapa bulan atau tahun masih begitu, itu terasa cukup mengecewakan dan tampak seperti sinyal kurangnya kapasitas untuk benar-benar menyelesaikan proyek. Bahkan saya merekomendasikan proyek itu sebagai kandidat yang layak untuk hibah yang saya ajukan, dan mereka terpilih sementara saya tidak
Jika ada yang tahu solusi bagus di area ini, atau jika saya keliru soal SQLite-vec, saya ingin diberi tahu. Untuk SSG kami, kami kurang lebih sudah memutuskan untuk mengerjakan infrastruktur lain dulu selama beberapa bulan, lalu membuatnya sendiri jika saat itu masih belum selesai
Ini bisa menjadi tambahan yang cukup keren untuk proyek pencarian DuckDB HNSW yang pernah saya lihat di sini: https://github.com/jasonjmcghee/portable-hnsw
Sangat menarik bahwa pencarian dilakukan terhadap file Parquet yang di-host secara statis dengan memakai HTTP range requests
Saya melihat hal-hal seperti ini bisa tumbuh menjadi ekosistem pencarian yang relatif terbuka dan terdistribusi, tidak dikendalikan perusahaan besar
https://news.ycombinator.com/item?id=27016630
Ini benar-benar keren, dan mungkin merupakan bagian yang hilang dari sesuatu yang dulu ingin saya buat
Dengan https://github.com/npiesco/absurder-sql, seluruh korpus asli bisa disimpan persisten di dalam browser sebagai IndexedDB/SQLite
Lalu, seperti https://weaviate.io/blog/chunking-strategies-for-rag, alih-alih mengindeks semuanya terlebih dahulu, kita bisa memakai Ternlight untuk membuat dan meng-cache embedding saat dibutuhkan
Dengan begitu, Reciprocal Rank Fusion yang menggabungkan FTS5/BM25 native SQLite dan pencarian semantik Ternlight, alias pencarian hibrida, juga menjadi mungkin
Dibuat dengan baik
Dipromosikan sebagai 7MB, tetapi ada juga versi mini 5MB
Sepertinya mini secara internal memakai vektor 256 elemen, bukan 384, untuk mengurangi ruang, lalu pada akhirnya memproyeksikannya ke 384 demi kompatibilitas
Ukurannya berkurang sepertiga, tetapi kerugiannya tidak linear, jadi meski memakai jalur data yang lebih kecil, kehilangan informasinya tampak kurang dari sepertiga
Proyek yang keren
Saya dulu pernah mencoba sesuatu yang mirip: http://sol.quipu-strands.com/
Saya ingin memuat model embedding di browser dan mengurutkan teks secara semantik
Saya mengambil bobot ONNX (MPNet, MiniLM) dari HuggingFace, membuat embedding dengan Transformers.js, lalu menggunakan clustering dari scikit-learn yang dijalankan lewat pyodide di dalam halaman. Semuanya berjalan di sisi klien, dan saya terkejut karena ini bekerja dengan sempurna
Demonya berperilaku cukup aneh. Misalnya, jika mencari "how to use typescript with createContext", hasil teratas hanya entri typescript, jadi pencarian kemiripan tampak gagal
Terima kasih. Model lokal suatu hari akan membawa privasi, dan saya sudah tahu use case yang sangat cocok untuk model embedding kecil seperti ini: pencarian murah dan cepat di database produk
Dalam kasus saya, ketergantungannya pada CPU juga merupakan kelebihan
Bisakah pembuatan embedding yang memakan 30 detik dilakukan sebelumnya lalu dikirim ke browser?
Setelah itu inferensinya cepat dan bagus