Skip to content

fix: run the local embedding model on onnxruntime-web - #526

Merged
RobertLD merged 2 commits into
mainfrom
fix/wasm-local-embeddings
Oct 9, 2026
Merged

RobertLD merged 2 commits into
mainfrom
fix/wasm-local-embeddings

Conversation

@RobertLD

@RobertLD RobertLD commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Problem

npm install -g libscope@2.0.0 fails on Linux x64 when nuget.org is unreachable. @huggingface/transformers depends on onnxruntime-node, whose install script downloads CUDA binaries (about 270 MB) and fails the whole install when that download fails. libscope cannot turn that download off for its users: .npmrc and overrides from a dependency are ignored for npm i -g and npx.

Change

  • The local provider runs all-MiniLM-L6-v2 on onnxruntime-web (WebAssembly) with @huggingface/tokenizers: tokenize, truncate, run, mean-pool, normalize. @huggingface/transformers, onnxruntime-node and sharp are removed. No native code is installed for the model.
  • Full-precision model.onnx instead of model_quantized.onnx. The model files are pinned to Hugging Face revision 751bff3 and cached in ~/.libscope/models (about 90 MB).
  • Truncation at 256 tokens, keeping [SEP], as sentence-transformers does (max_seq_length: 256).
  • WebAssembly threads = number of cores (the runtime default is min(4, cores / 2)).
  • Forced rebuild. The local provider's model id is now sentence-transformers/all-MiniLM-L6-v2, so 2.0.0 vector indexes fail the existing identity check with "Run libscope admin reindex --rebuild". Migration 20 records a placeholder model for 1.x vector indexes, which recorded none, so they fail the same check.
  • Docs: a "Rebuild the vector index (2.0.1)" section in docs/migration-v2.md, model size and runtime updates, and the Dockerfile comment about the CUDA download is removed.

Quality

Measured on 100 chunks from a real index, against Python onnxruntime with the Hugging Face tokenizer:

Cosine vs full-precision model
2.0.0 (native, quantized) mean 0.990, min 0.978
This PR (WebAssembly, full precision) 1.00000

tests/unit/local-embedding.test.ts checks the provider against reference vectors from Python for a short and a truncated long input. The neural retrieval-quality suite passes.

Cost

  • Embedding is about 2.5–3x slower than 2.0.0's native quantized model: 100 chunks in about 3.8 s vs 1.2–1.5 s on a 9-core VM. Rebuilding a 13,275-chunk index took 447 s.
  • The first download is about 90 MB, up from 23 MB.

Verification

  • npm run lint (0 errors), format:check, typecheck, test:coverage: 2138 tests pass.
  • Global install of the packed tarball: no install script touches nuget, and onnxruntime-node is not installed.
  • A copy of a real 2.0.0 database (809 documents): search stopped with the rebuild message, libscope admin reindex --rebuild re-embedded 13,275/13,275 chunks, and search returned the expected pages.
  • Model download into an empty cache: files byte-identical to the Hugging Face originals.

Release-please should make this 2.0.1.

Installing 2.0.0 fails on Linux x64 without access to nuget.org:
@huggingface/transformers depends on onnxruntime-node, whose install
script downloads CUDA binaries and fails the install when that download
fails. A dependent package cannot turn the download off.

Run all-MiniLM-L6-v2 on onnxruntime-web (WebAssembly) with
@huggingface/tokenizers instead. Nothing native is installed for the
model, so the install works offline from nuget and on any libc;
transformers, onnxruntime-node and sharp are gone.

Vectors change, so existing vector indexes need
`libscope admin reindex --rebuild`:
- Full-precision model.onnx instead of model_quantized.onnx. The
  quantized model's vectors drift from the original model's (cosine
  min 0.978 on 100 indexed chunks); the WebAssembly runtime reproduces
  the full-precision model exactly (cosine 1.00000 against Python
  onnxruntime).
- Truncation at 256 tokens keeping [SEP], as sentence-transformers
  (max_seq_length 256) does.
- The local provider's model id is now
  sentence-transformers/all-MiniLM-L6-v2, so 2.0.0 indexes no longer
  match and ask for the rebuild. Migration 20 records a placeholder
  model for 1.x indexes, which recorded none.

The model is pinned to a Hugging Face revision and downloaded with
progress into ~/.libscope/models (about 90 MB). Inference uses one
WebAssembly thread per core; it is about 2.5-3x slower than the native
quantized model was.
@vercel

vercel Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
libscope Ignored Ignored Preview Oct 9, 2026 7:31pm UTC

@sonarqubecloud

sonarqubecloud Bot commented Oct 9, 2026

Copy link
Copy Markdown

@RobertLD
RobertLD merged commit 9220a7e into main Oct 9, 2026
11 checks passed
@RobertLD
RobertLD deleted the fix/wasm-local-embeddings branch October 9, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant