23 poin oleh GN⁺ 4 hari lalu | 1 komentar | Bagikan ke WhatsApp
  • 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-L6 dengan menerapkan quantization-aware training (QAT) gaya BitNet b1.58
  • Setelah memasang @ternlight/base, cukup impor embed dan similar untuk 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, similar
    • cosineSim(embed('reset my password'), embed('I forgot my password')) → 0.88
    • similar mendukung pencarian tetangga terdekat pada korpus, dengan topK yang 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-L6 dan 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
  • Bundel tunggal

    • Mengintegrasikan model + tokenizer BERT + engine ke dalam satu .wasm
    • Tidak ada tahap postinstall maupun fetch saat runtime
  • 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 embed dan similar dari @ternlight/base untuk menjalankan pencarian berbasis makna
    import { 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 sama
  • sentence-transformers/all-MiniLM-L6-v2 — model guru tempat model siswa didistilasi
  • Lisensi: MIT

1 komentar

 
GN⁺ 4 hari lalu
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

    • Ada kamus yang memetakan kata ke tag OpenStreetMap, bentuknya seperti https://codeberg.org/cartes/web/src/branch/master/components...
      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
    • Saya benar-benar tertarik memasukkan pencarian berbasis makna sederhana ke aplikasi desktop native
      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
    • Saya baru saja meng-embedding seluruh dokumentasi django dan basis pengetahuan internal, sehingga kedua sumber itu bisa langsung dicari
  • 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

    • Setuju. Di saat yang sama, ini juga membuat saya bernostalgia dengan masa ketika kita bisa akrab mengetahui apa yang sedang terjadi hanya dari suara komputer
    • Saya kaget ketika kipas mulai berputar. Tapi toaster juga sering membuat saya kaget
    • Pemanfaatan siklus CPU sampai batas maksimal, siapa bilang hanya GPU yang istimewa?
  • 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

    • Untuk static site generator kami, saya ingin memakai sqlite-vec, tetapi terakhir kali saya cek, HNSW belum diimplementasikan atau dukungan pencarian vektor di browser belum bagus. Seingat saya, mungkin masih melakukan pemindaian seluruh tabel
      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

    • Dengan ide serupa, menggunakan DB SQLite pada host statis lewat HTTP range requests dan WASM juga bisa menarik
      https://news.ycombinator.com/item?id=27016630
    • Ide yang keren. Saya sangat suka range requests dan format yang bisa dijelajahi klien pada hosting statis
  • 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

    • Bagus. Kalau ada cara untuk mendukung atau ada use case spesifik yang perlu dibahas di roadmap, beri tahu saya
  • Bisakah pembuatan embedding yang memakan 30 detik dilakukan sebelumnya lalu dikirim ke browser?
    Setelah itu inferensinya cepat dan bagus

    • Bisa. Jalankan indeks sekali saja di sisi server, lalu kirim hanya embedding-nya ke frontend