- Ternlight は、サーバー呼び出しなしにブラウザ内でテキスト埋め込みと類似度検索を実行し、小規模なクライアント側セマンティック検索をすばやく構築できるようにします
- 基本パッケージはエンジンと重みを合わせて 7MB、mini 版は 5MB で、GPU なしに CPU で動作します
@ternlight/base をインストールして embed、similar を取り込むと、3行程度で意味ベースの検索フローを作れます
- サンプル呼び出しではレシピ一覧から上位3件の結果を並べ替え、約 5ms とネットワーク呼び出しなしである点を強調しています
- React ドキュメント検索デモでは、ユーザーが質問を入力するとブラウザで検索を実行し、5MB ティアの @ternlight/mini がこれを動かします
ブラウザ内で完結する埋め込み
- Ternlight は「7MBの埋め込みモデル」を掲げ、テキストをミリ秒単位で埋め込み、サーバーを呼び出しません
-
実行特性
- API 呼び出しなし
- エンジン + 重み: 7MB
- mini 版: 5MB
- 高速な埋め込み: 約 5ms
- CPU 専用、GPU なし
インストールと使用例
- npm パッケージ1つとして提供され、別途モデルをダウンロードする手順やサーバーなしで利用できます
- インストールコマンドは次のとおりです
npm install @ternlight/base
@ternlight/base から embed、similar を取り込み、意味ベースの検索を実行します
import { embed, similar } from '@ternlight/base';
similar('easy weeknight dinner ideas', recipes, { topK: 3 });
// → ranked matches · ~5 ms · zero network
1件のコメント
Hacker News のコメント
趣味プロジェクトとしてブラウザ上で有用なモデルを動かしてみたくて、MiniLM から小さな文エンコーダを蒸留し、三値量子化を意識した学習を適用した。
推論エンジンも自分で書き、Rust → WASM SIMD として配布した。
LLM ではなく埋め込みモデルなので、テキストを入力すると 384 次元ベクトルが出力され、2 つのベクトルのコサイン類似度でテキストの関連性を判断する。たとえば「reset my password」と「I forgot my password」は 0.88 のような値になる。
意味ベース検索、FAQ/意図マッチング、クラスタリングに使え、デバイス内実行なので API に依存せず、入力直後に高速な意味検索が可能になる。
デモでは React ドキュメント 2,000 件を完全にデバイス内で検索する: https://ternlight-demo.vercel.app
npm には @ternlight/base(7MB、埋め込み 1 件あたり約 5ms、より高性能な埋め込み)と @ternlight/mini(転送 5MB、埋め込み 1 件あたり約 2.5ms)の 2 段階があり、Node とブラウザ向けにバンドルされている。
リポジトリには技術的詳細、MIT ライセンス、学習パイプラインが含まれている: https://github.com/soycaporal/ternlight
デバイス内埋め込みが実際に役立つのか、どんなユースケースがあるのか気になっている。
ユーザーが「pancake」と入力したとき、明示的に「pancake = crêpe」という辞書項目を書かなくても crêpe を見つけられるようにする助けになるのか気になる。
理解が正しければ、このライブラリは最初に 5MB を一度ダウンロードし、その後は今 Fuse.js を使っているのと同じように使う構造なのかも気になる。
英語以外の言語をどの程度うまく扱えるのか、OpenStreetMap タグ Wiki で学習させられるのかも知りたい。
他の超小型埋め込みモデルとの比較があるのか気になる。MiniLM-L6 から始めた理由が、同じクラスの中で特に優れたモデルだからなのか判断しづらく、提示されている指標は「Retrieval (SciFact NDCG@10)」だけだ。
ただし主張されている性能とはかなり差があり、i5-4570 の Firefox では秒間 400 件ではなく、秒間 35 件の埋め込みしか出ない。SIMD ではない経路に落ちている問題があるのではないかと疑っていて、ネイティブ Rust バイナリも試すつもりだ。
すばらしいが、ランディングページにデモを開始するボタンを置くとよさそう。Web ページを開いた瞬間、ファンが狂ったように回る音がしてかなり驚いた。
Astro や汎用メタフレームワークのプラグインにして、生成されたすべての HTML ファイルを自動でパースし、小さな埋め込みデータベースを作れるとよさそう。
フロントエンドではそれを遅延ロードでき、HNSW もチャンク単位で保存して、検索クエリに必要な部分だけ読み込めるかもしれない。
たとえば https://pagefind.app/ に似ているが、完全に静的なベクトル検索を提供する形だ。
数か月、数年が経ってもその状態なら、プロジェクトをきちんと完成させる能力が足りないサインのように見えて、かなり失望した。しかも私が支援した助成金でそのプロジェクトを有力候補として推薦したのに、そちらは採択され、私は落ちた。
この領域でよい解決策を知っている人がいるか、SQLite-vec について私が間違っているなら教えてほしい。私たちの SSG では、まず別のインフラを数か月作業し、その時点でも完成していなければ自分で作る方向でほぼ決めている。
以前ここで見た DuckDB HNSW 検索プロジェクトに、かなりいい追加機能になりそう: https://github.com/jasonjmcghee/portable-hnsw
静的にホストされた Parquet ファイルを対象にHTTP Range リクエストを使って検索が行われる点が本当に興味深い。
こういうものが、大企業に支配されない比較的オープンで分散的な検索エコシステムへと成長し得ると思う。
https://news.ycombinator.com/item?id=27016630
これは本当にすばらしく、以前作りたかったものに欠けていたピースかもしれない。
https://github.com/npiesco/absurder-sql を使えば、元のコーパス全体をブラウザ内の IndexedDB/SQLite に永続保存できる。
そのうえで https://weaviate.io/blog/chunking-strategies-for-rag のようにすべてを事前にインデックス化せず、Ternlight で必要なときに埋め込み生成とキャッシュができる。
そうすると、ネイティブ SQLite の FTS5/BM25 と Ternlight の意味検索を組み合わせる Reciprocal Rank Fusion、つまりハイブリッド検索も可能になる。
よくできている。
7MB として宣伝されているが、5MB の mini 版もある。
mini は内部的に 384 ではなく256 要素ベクトルを使って容量を減らし、最後に互換性のため 384 に射影しているように見える。
サイズは 3 分の 1 減るが損失は線形ではないので、より小さいデータパスを使っても情報損失は 3 分の 1 未満に見える。
すばらしいプロジェクト。
以前、似たことを試したことがある: http://sol.quipu-strands.com/
ブラウザ内で埋め込みモデルを読み込み、テキストを意味的に整列させたかった。
HuggingFace から ONNX 重み(MPNet、MiniLM)を取得し、Transformers.js で埋め込みを作り、その後ページ内で pyodide により実行される scikit-learn のクラスタリング器を使った。すべてクライアント側で動き、これが完全に動作して驚いた。
デモはかなり変な動きをする。たとえば「how to use typescript with createContext」を検索すると、上位結果が typescript 項目ばかりなので、類似度検索が失敗しているように見える。
ありがとう。ローカルモデルはいずれプライバシーをもたらすだろうし、こうした小さな埋め込みモデルにぴったりの優れたユースケースもすでに知っている。製品データベースで安価かつ高速に検索する用途だ。
私の場合、CPU に依存する点も利点だ。
30 秒かかる埋め込み生成を事前に済ませてブラウザへ送れるのか?
その後の推論は速くてよい。