← All models Β· MiniLM

use case Β· multi-model Β· MiniLM + DistilBERT

Multi-model: semantic search, with tone

Rank by meaning, then read the mood. First MiniLM embeds a corpus of reviews and finds the entries closest to your query; then DistilBERT labels each hit POSITIVE or NEGATIVE. Search "battery life" and instantly see who's praising it and who's complaining β€” two tiny models, one on-device pipeline, no server.

This page loads two models (~25 MB + ~65 MB). A returning visitor with both cached sees them auto-initialise; a first-time visitor gets a Download control for each. Once both are ready, index the corpus once, then search β€” each hit is ranked by cosine similarity and tagged with its sentiment.

MiniLM embeddings (~25 MB)

DistilBERT sentiment (~65 MB)

How the two models compose

Each model does the one thing it's good at, and the output of the first shapes the work of the second:

// 1. MiniLM β€” rank the corpus by meaning (cosine over 384-d embeddings)
const q = await embed([query]);
const hits = corpus
  .map((t, i) => ({ t, sim: dot(q[0], corpusVecs[i]) }))
  .sort((a, b) => b.sim - a.sim)
  .slice(0, TOP_K);

// 2. DistilBERT β€” label just the top hits' tone (cheap: only TOP_K, not the whole corpus)
for (const hit of hits) hit.tone = await classify(hit.t); // POSITIVE / NEGATIVE

Only the top hits get the sentiment pass, so adding the second model costs almost nothing. Both run in their own Web Workers β€” the embedding worker and the sentiment worker β€” so the page stays responsive throughout.

Ranking and tone are independent signals: a highly-relevant hit can still be scathing. That's the point β€” you find what's about your query, then immediately see whether it's praise or a complaint, without reading every line.

← Back to MiniLM Β· DistilBERT β†’