Instructions to use destava/destava-flash-mini-info with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- sentence-transformers
How to use destava/destava-flash-mini-info with sentence-transformers:
from sentence_transformers import SentenceTransformer model = SentenceTransformer("destava/destava-flash-mini-info") sentences = [ "The weather is lovely today.", "It's so sunny outside!", "He drove to the stadium." ] embeddings = model.encode(sentences) similarities = model.similarity(embeddings, embeddings) print(similarities.shape) # [3, 3] - Notebooks
- Google Colab
- Kaggle
license: apache-2.0 base_model: Qwen/Qwen3-Embedding-0.6B library_name: sentence-transformers pipeline_tag: feature-extraction tags: - sentence-similarity - embeddings - job-matching - matryoshka language: - en
destava-flash-mini
A 0.6B-parameter embedding model that ranks job postings for one person over a whole job market on a laptop. Built by Destava, the AI career manager. The weights are not public yet; this page says why the model exists, what it is and what it scores. For access, write to us through destava.com.
Why we built it
A job seeker faces a market of about two million live postings. Reading them with a large language model, one posting at a time, is the accurate way and the impossible one: about a second a posting, 22 days for the market, and real money on every search. Keyword search is instant and free and misses most of what a résumé means. Destava's production search sits between the two: filters, stored vectors, then an LLM judge over the top rows, which costs an LLM call per search and runs on a server.
We wanted the judge's quality at the cost of a dot product, so that matching can run on the member's own device, over the whole market rather than a shortlist, every day, for nothing per search, with her data staying with her. That calls for a small model: 0.6B parameters fit a laptop, each posting is turned into one vector once, and ranking two million of them takes half a second on a CPU. A larger teacher model scored the training pairs so the small one could learn what "a strong fit" means for a career, not just for a keyword.
We are publishing the model, when its checks are done, for three reasons. Anyone should be able to run meaning-based job matching locally, without an API and without sending a résumé anywhere. Anyone should be able to check our numbers against the test sets we describe below. And the model alone is the floor, not the product: Destava's search adds the steps a model cannot carry (eligibility by hiring region, repost resolution, a memory of graded pairs, a second-stage re-order), so the open weights are a fair baseline and the product is what we run on top of them.
The weights wait on two checks we have not finished: the terms of the training postings' sources, and a human-graded slice beside the LLM grader. This page will say when they are done.
What it is
- Base. Qwen3-Embedding-0.6B (Apache-2.0), fine-tuned end to end with Sentence Transformers. One vector per text, 1,024 dimensions, Matryoshka-trained so the first 256 dimensions rank on their own. 512-token window.
- Inputs. The person as a short structured card (target role, current role and years, jobs with dates and skills, skills by use) behind one instruction; the posting as its title, company, location, remote flag and text. A cosine between the two is the score.
- Teacher. Clef-flash (Cloudflare, Apache-2.0) scored 187,611 (person, posting) pairs for expected fit, on our own hardware. The student learned those scores: Margin-MSE on score gaps, a per-person list loss, gap-balanced triples, same-bucket hard negatives, in-batch negatives. Seven later variants (more labels, a binarising term, a weight average, a work-rights rule, code-label heads) did not beat the first model on the test set; that first model is the release.
- Training data. 5,863 synthetic people whose careers are drawn from O*NET occupations (US Department of Labor, CC BY 4.0) and 80,628 public job postings from one week of October 2026. No résumé dataset and no member data were used in training.
What it scores
NDCG@10 over each person's filtered week of postings, every top-10 job graded 0 to 3 by one LLM grader blind to every system, paired bootstrap over people (10,000 resamples). "Today's search" is Destava's production job search: filters, stored vectors and an LLM judge over the top rows.
| Test set | destava-flash-mini | Today's search | Paired difference, model − today |
|---|---|---|---|
| 15 people (6 real CVs, 9 written US personas) | 0.736 | 0.730 | +0.006, range crosses zero: level |
| 150 real CVs, none from the first set | 0.794 | 0.792 | +0.003 [−0.025, +0.030]: level |
Against its own untrained base (Qwen3-Embedding-0.6B as downloaded) the model is ahead by 0.090 [0.020, 0.153] on the first set (0.736 against 0.646); against keyword search (BM25, 0.537) by 0.199. Over the whole market of 1,929,809 postings a search takes 0.54 s on a laptop CPU and costs nothing per query, against 1.20 s and an LLM call for today's search.
The shipped fast path (a first pass over sign codes of the vectors, then an int8 rescore of the top 1,000) is level with the float ranking on the 15 and 0.020 below it on the 150 at 1,024-bit codes (0.033 at 256-bit codes); against today's search the 1,024-bit path is level and the 256-bit path is behind, so the fast path ships at 1,024-bit codes and the 256-bit option was dropped.
26 Oct 2026, the v0 re-read with the served vectors (docs/s4b-v0-week.md): the S4b numbers above for v0 were measured with each posting's title in the text twice (a rendering slip in the rank runs); the representation the model is served with (the title once, the S9 index) reads 0.767 [0.743, 0.790] on the same 150 people under the merged grades, against 0.782 for today's search, still level by the pre-registered rule (today − v0-week +0.015 [−0.012, +0.042] crosses zero), and the 1,024-bit fast path on that input is the same number (+0.002 crosses zero). The doubled title is worth about 0.02 of NDCG@10 to the float ranking (v0 − v0-week +0.018 [+0.008, +0.028]); tested the same morning as a rendering step for the served path (the week re-encoded with the title twice, the same fast path over it): +0.006 [−0.002, +0.015] against the title-once fast path, crossing zero, so the rendering stays as it is (docs/s4b-title-repeat.md).
Formats
- Sentence Transformers checkpoint, bfloat16 safetensors, 1.1 GB.
- ONNX, weight-only 8-bit with the vocabulary table in float16, 782 MB: cosine 0.9997 to the float model on reference texts, deterministic, and level with the float model on the 15-person test set (NDCG@10 0.722 against 0.733, the paired range crossing zero). Float32 ONNX (2.4 GB) matches at 1.000. A 4-bit variant distorts the vectors and is not offered.
Reading the score as a probability
The cosine is an order, not a judgement: 0.62 means "higher than 0.58". Since 26 Oct 2026 a calibration laid over it
(jobs/calibration/v0-fable.json, docs/calibration.md) reads it as the probability that the blind grader of our test
sets would call the posting a plausible or strong fit for the person:
P(fit) = 1 / (1 + exp(−(12.23 · cosine − 12.45)))
| Cosine | 0.75 | 0.80 | 0.85 | 0.90 | 0.95 |
|---|---|---|---|---|---|
| P(fit) | 0.04 | 0.07 | 0.11 | 0.19 | 0.30 |
Fitted by Platt scaling on 3,863 graded person–posting pairs (the pooled top 10s of every search on two test sets, 165 people), held out by person in five folds: Brier 0.142 against 0.147 for the base rate, expected calibration error 0.006, AUC 0.61. The model does not change; the map is monotone, so no ranking changes. Read it as a frequency ("one in five of the postings scored like this are fits"), not as a verdict on one posting: inside the top of a ranked list the cosine separates fits from near-misses only weakly, and a strong fit (grade 3) is not predictable from it. The number is calibrated to that grader on those pools, and is trusted at the top of a ranked list, where a search reads it, not over a random posting. The same curve held on 776 pairs graded by a second model (Brier 0.126).
Limits, stated
- It does not know where the person lives. The person text has no location, so the model cannot tell a job's hiring region from the person's. Destava applies eligibility as a filter beside the model; a model download does not.
- Level direction and must-haves are the other two causes of its wasted top-10 slots. A cosine cannot tell a level below from a level above.
- Graded by one LLM. Every number above is one grader's; a human-graded slice is planned, not done.
- Test people are 165 real résumés (English, from one Eastern European job board's public dataset) plus 9 written US personas; no other region or non-English market has been measured.
- Training postings are US-centric (68 metros, 13 outside the US).
Licences and attribution
| Component | Licence | Use |
|---|---|---|
| Qwen3-Embedding-0.6B (Qwen) | Apache-2.0 | base weights, fine-tuned |
| Clef-flash (Cloudflare) | Apache-2.0 | teacher: scored the training pairs on our hardware |
| Djinni Recruitment Dataset (Drushchak and Romanyshyn, UNLP 2024) | MIT | test people only; never in training |
| O*NET 31.0 (US Department of Labor) | CC BY 4.0 | occupations behind the synthetic training people |
| Job postings | public postings' text | training texts; not redistributed |
Proposed licence for the weights, when released: Apache-2.0, with the attributions above.
What is not in the model
The steps Destava runs beside the model in production (eligibility by hiring region, repost resolution, a memory of graded pairs, a second-stage re-order) are the server's, not the weights'. The model on its own matches today's search; the server steps are where the product goes past it.
Last updated 25 October 2026.