CV matching benchmark
After four fixes, across 4 jobs on the same 1,000 CVs, Formzed found 100% of the true fits within as many places as there are true fits, up from 82% before them, and average precision rose from 0.89 to 1.00. 40 of its 40 top-10 picks meet every must-have. True fits placed low fell from 39 before any fix to 1 after the third and 0 after the fourth. A first match of all four jobs cost $0.75 in AI, and asking again $0.11.
A true fit is a candidate inside the job's rules (place, start date, experience limit) who meets every must-have, according to an answer key written from what each generated CV really shows and frozen before the first run. One run per job before any fix and one after each, all scored once against the same key. The charts below show the latest run.
Five runs, four fixes
The first run cut every requirement to its first 60 characters before the AI checked CVs against it, so long either-or lists lost options such as PHP, C#, Storybook and Snowflake. The first fix keeps each requirement in the job's own words, up to 160 characters, and ranks a candidate who only partly meets a must-have below those who meet them all.
The second fix stops Formzed's proof check turning down correct answers when the AI quotes only the matching items of a skills list (“Storybook, Playwright, Jest” out of a longer list), checks old “missing” must-haves once more, and tells the AI plainly that a technology the requirement names always counts.
The third fix aims at no qualified candidate missed: everyone inside the job's rules gets the detailed check, where before only the best rated did; any requirement judged missing where the candidate's own text names it gets a second, careful look on its own; and a certificate, course or degree naming a skill shows it.
The fourth fix counts a technology named in a candidate's skills list (“Python, Django, PostgreSQL”) as meeting a requirement that only names technologies, such as “Python or Scala”, whatever a verdict said.
R-precision
Average precision
Headline numbers, run by run
| Job | Run | Answer logic | R-precision | Average precision | Top 10 meeting every must-have | True fits placed low | Wrong top-10 picks | Detailed fit rho |
|---|---|---|---|---|---|---|---|---|
| Backend Engineer | 1 | 33 | 70% | 0.77 | 9 | 15 | 1 | 0.66 |
| Backend Engineer | 2 | 34 | 82% | 0.93 | 10 | 9 | 0 | 0.86 |
| Backend Engineer | 3 | 35 | 90% | 0.96 | 10 | 5 | 0 | 0.90 |
| Backend Engineer | 4 | 36 | 100% | 1.00 | 10 | 0 | 0 | 0.98 |
| Backend Engineer | 5 | 38 | 100% | 1.00 | 10 | 0 | 0 | 0.98 |
| Frontend Engineer | 1 | 33 | 89% | 0.97 | 10 | 9 | 0 | 0.76 |
| Frontend Engineer | 2 | 34 | 88% | 0.97 | 10 | 10 | 0 | 0.77 |
| Frontend Engineer | 3 | 35 | 94% | 0.98 | 10 | 5 | 0 | 0.86 |
| Frontend Engineer | 4 | 36 | 100% | 1.00 | 10 | 0 | 0 | 0.89 |
| Frontend Engineer | 5 | 38 | 100% | 1.00 | 10 | 0 | 0 | 0.89 |
| Machine Learning Engineer | 1 | 33 | 91% | 0.94 | 10 | 5 | 0 | 0.95 |
| Machine Learning Engineer | 2 | 34 | 89% | 0.94 | 10 | 6 | 0 | 0.93 |
| Machine Learning Engineer | 3 | 35 | 91% | 0.94 | 10 | 5 | 0 | 0.95 |
| Machine Learning Engineer | 4 | 36 | 100% | 1.00 | 10 | 0 | 0 | 0.97 |
| Machine Learning Engineer | 5 | 38 | 100% | 1.00 | 10 | 0 | 0 | 0.97 |
| Data Engineer | 1 | 33 | 79% | 0.89 | 10 | 10 | 0 | 0.75 |
| Data Engineer | 2 | 34 | 90% | 0.95 | 10 | 5 | 0 | 0.88 |
| Data Engineer | 3 | 35 | 94% | 0.95 | 10 | 3 | 0 | 0.91 |
| Data Engineer | 4 | 36 | 98% | 0.99 | 10 | 1 | 0 | 0.96 |
| Data Engineer | 5 | 38 | 100% | 1.00 | 10 | 0 | 0 | 0.97 |
What each match cost
Run 4 was the first to record what each match used, and the first to check everyone inside the job's rules in detail. The four jobs checked 2,865 CVs in 8 parts and 702 seconds, for 944 credits, or $0.75 of AI cost to Formzed at $0.0007925 a credit. Answers saved by earlier runs were reused where the requirement and CV were unchanged, so a first match on CVs never matched before can cost a little more.
Asked again in the latest run, after the fourth fix, the same four jobs cost 141 credits ($0.11) in 245 seconds: nearly every answer was saved by the run before, so asking about the same job again costs a fraction of the first match.
Written tokens, the AI's verdicts, cost five times as much as the CV text it reads, so they are about half the bill although there are far fewer of them. The runs before the third fix didn't record what they used.
AI cost per job in run 4, by kind of token
Cost per job in run 4
Per 1,000 CVs: the job's cost spread over the CVs it checked in detail.
| Job | Checked in detail | Parts | Seconds | Credits | Cost | Per 1,000 CVs |
|---|---|---|---|---|---|---|
| Backend Engineer | 339 | 1 | 97 | 102 | $0.081 | $0.239 |
| Frontend Engineer | 810 | 2 | 169 | 247 | $0.196 | $0.241 |
| Machine Learning Engineer | 1,000 | 2 | 183 | 277 | $0.219 | $0.219 |
| Data Engineer | 716 | 3 | 253 | 319 | $0.253 | $0.353 |
R-precision by job
R-precision: of a job's true fits, the share Formzed placed within as many places as there are true fits. A perfect ranking scores 100%.
Backend Engineer
Frontend Engineer
Machine Learning Engineer
Data Engineer
Recall@k: how many true fits are in the top k places
Share of true fits found in the top k places
Recall in the top 10 is capped when a job has more than ten true fits, which is why R-precision is the headline.
Recall@k with 95% intervals
Found: true fits in the top k. Precision: the share of the top k who are true fits.
| Job | Top k | Found | Recall | From | To | Precision |
|---|---|---|---|---|---|---|
| Backend Engineer | 10 | 10 | 20% | 11% | 33% | 100% |
| Backend Engineer | 25 | 25 | 50% | 37% | 63% | 100% |
| Backend Engineer | 50 | 50 | 100% | 93% | 100% | 100% |
| Backend Engineer | 100 | 50 | 100% | 93% | 100% | 50% |
| Backend Engineer | 150 | 50 | 100% | 93% | 100% | 33% |
| Backend Engineer | 250 | 50 | 100% | 93% | 100% | 20% |
| Backend Engineer | 500 | 50 | 100% | 93% | 100% | 10% |
| Frontend Engineer | 10 | 10 | 13% | 7% | 22% | 100% |
| Frontend Engineer | 25 | 25 | 31% | 22% | 42% | 100% |
| Frontend Engineer | 50 | 50 | 63% | 52% | 72% | 100% |
| Frontend Engineer | 100 | 80 | 100% | 95% | 100% | 80% |
| Frontend Engineer | 150 | 80 | 100% | 95% | 100% | 53% |
| Frontend Engineer | 250 | 80 | 100% | 95% | 100% | 32% |
| Frontend Engineer | 500 | 80 | 100% | 95% | 100% | 16% |
| Machine Learning Engineer | 10 | 10 | 19% | 10% | 31% | 100% |
| Machine Learning Engineer | 25 | 25 | 46% | 34% | 59% | 100% |
| Machine Learning Engineer | 50 | 50 | 93% | 82% | 97% | 100% |
| Machine Learning Engineer | 100 | 54 | 100% | 93% | 100% | 54% |
| Machine Learning Engineer | 150 | 54 | 100% | 93% | 100% | 36% |
| Machine Learning Engineer | 250 | 54 | 100% | 93% | 100% | 22% |
| Machine Learning Engineer | 500 | 54 | 100% | 93% | 100% | 11% |
| Data Engineer | 10 | 10 | 21% | 12% | 34% | 100% |
| Data Engineer | 25 | 25 | 52% | 38% | 66% | 100% |
| Data Engineer | 50 | 48 | 100% | 93% | 100% | 96% |
| Data Engineer | 100 | 48 | 100% | 93% | 100% | 48% |
| Data Engineer | 150 | 48 | 100% | 93% | 100% | 32% |
| Data Engineer | 250 | 48 | 100% | 93% | 100% | 19% |
| Data Engineer | 500 | 48 | 100% | 93% | 100% | 10% |
Score vs. true fit
True fit: the answer key's share of the job's requirements a CV meets (a must-have counts three times as much as a nice-to-have). Formzed gives every candidate inside the rules a quick rating, then checks them in detail for a fit score.
Quick rating (0 to 10) against true fit
Everyone rated. Points are spread a little so equal values don't hide each other.
Detailed fit (out of 100) against true fit
The candidates checked in detail. A missed must-have caps the fit. The dashed line is where the two agree.
Rank correlation with true fit (Spearman)
1 means the scores order candidates exactly as the key does; 0 means no relation.
| Job | Quick rating | From | To | Rated | Detailed fit | From | To | Checked |
|---|---|---|---|---|---|---|---|---|
| Backend Engineer | 0.74 | 0.68 | 0.79 | 339 | 0.98 | 0.98 | 0.99 | 339 |
| Frontend Engineer | 0.73 | 0.68 | 0.77 | 810 | 0.89 | 0.87 | 0.91 | 810 |
| Machine Learning Engineer | 0.40 | 0.34 | 0.47 | 1,000 | 0.97 | 0.96 | 0.97 | 1,000 |
| Data Engineer | 0.70 | 0.65 | 0.74 | 716 | 0.97 | 0.96 | 0.98 | 716 |
Precision and recall down the ranking
Precision against recall, place by place
Each point is one cut-off down Formzed's order. Up and to the right is better.
Average precision with 95% intervals
The area under each curve. A random order scores the share of true fits.
| Job | Average precision | From | To | Random order |
|---|---|---|---|---|
| Backend Engineer | 1.00 | 1.00 | 1.00 | 0.050 |
| Frontend Engineer | 1.00 | 1.00 | 1.00 | 0.080 |
| Machine Learning Engineer | 1.00 | 1.00 | 1.00 | 0.054 |
| Data Engineer | 1.00 | 1.00 | 1.00 | 0.048 |
Calibration: can a score be read as a chance of fitting?
A quick rating is read as a chance out of ten of being a true fit, a detailed fit as a chance out of a hundred. Formzed's scores rank candidates and don't promise probabilities; this shows how far a score can be taken literally. Circles grow with the number of candidates in the band; whiskers are 95% intervals.
Quick rating
Detailed fit
Calibration error
ECE: the average gap between a score read as a chance and the share that truly fit, weighted by band size. Brier: the mean squared error of that chance. Lower is better for both.
| Job | Quick rating ECE | Brier | Detailed fit ECE | Brier |
|---|---|---|---|---|
| Backend Engineer | 0.229 | 0.130 | 0.336 | 0.141 |
| Frontend Engineer | 0.095 | 0.048 | 0.244 | 0.081 |
| Machine Learning Engineer | 0.047 | 0.015 | 0.253 | 0.083 |
| Data Engineer | 0.086 | 0.041 | 0.209 | 0.068 |
No true fit lost
Every true fit in the four jobs is placed within as many places as there are true fits. The causes that took true fits before are gone: none was kept from the detailed check by a low quick rating, and none was lost to a certificate, a turned-down quote, a cut requirement or a misread skills list.
True fits placed below the place a perfect ranking gives them, by cause
All four jobs together.
None: every true fit is placed within as many places as there are true fits.
What else to know
A certificate now shows a skill: candidates whose ML framework appears only as “TensorFlow Developer Certificate” count as meeting it, as the answer key reads them. Read strictly, with certificates not counting, Machine Learning Engineer's R-precision is 100% and its average precision 1.00.
Everyone inside the job's rules is now checked in detail, so the quick rating only decides the order they're checked in, not who is considered.
No top-10 pick is short of a must-have any more: a partly met must-have now ranks like a missed one. The data job's requirement is also kept as “Python or Scala”, where the first run narrowed it to “Python or Scala for data pipelines”.
How this was measured
The candidates are the 1,000 generated CVs on the test form (fictional people, 50 of them scanned images). Each was generated from a known record of skills, years, country and notice period, so the key works out every candidate's fit from what the CV shows: a skill counts when it is listed or named in a sentence. Before the run, 24,000 skill checks were repeated against the uploaded PDFs' own text with 0 disagreements, and the key was frozen on Oct 31, 2026, 22:12 UTC.
Each job was asked five times in Formzed's live matching with production settings, from Oct 31, 2026, 23:21 UTC (answer logic version 33) to Nov 1, 2026, 09:51 UTC (version 38, 245 seconds for all four); the run-by-run table gives each run's version. A benchmark switch made the match return every candidate's place, rules result, quick rating and detailed fit, since the first fix each must-have's verdict and any quote the proof check turned down, and since the third what each part used. Intervals are Wilson intervals for shares and bootstrap resamples of candidates for average precision and correlations.