Under the Hood

AI that shows its work.

Most AI career tools are a prompt wrapped in a UI: ask it the same question twice, get two different answers. Skillsy is built the opposite way. This page explains exactly how our engine works, and then proves it, live, on your device.

Same CV. Same job. Same score.
01 / The Enemy

The wobbly score is a lie.

Ask a typical AI career tool to score your CV today, and it might say 68. Ask again tomorrow: 74. Nothing changed. That gap is not a feature, it is a coin flip wearing a suit. Job seekers make real decisions on that number. It has to hold still.

68Monday, same CV
74Tuesday, same CV

What most tools actually do: one LLM call, "please rate this CV from 0 to 100", temperature 0.7. The score is creative writing.

02 / The Bet

The machine decides. The AI narrates.

Our rule is strict: an LLM is never allowed to produce a number or a verdict. It reads, extracts, and explains. Every judgment is made by deterministic code, and every explanation is locked to a verdict the machine already fixed. The AI is a journalist with an editor; it cannot change the headline.

Deterministic Engine (decides)

Verdicts from a synonym engine with 100+ skill groups and transferable-credit logic. Experience measured in years against bands. Final score from a fixed formula.

  • Same input, same output, always
  • Every verdict explainable in one line of code
  • Zero hallucination possible on numbers
LLM Layer (reads & narrates)

Parses messy job postings and CVs into structured JSON, then writes natural Indonesian explanations locked to the machine's verdicts.

  • Explicitly forbidden from contradicting or softening a verdict
  • If narration fails, template text falls back, score untouched
  • temperature 0.1 everywhere it runs
03 / The Pipeline

Four beats. Click through them.

A small model turns the messy job posting into strict structure: minimum years, required skills, plus-skills, education, industry. Real output from our production logs:

Input: a real senior backend posting  |  model: gpt-oss-20b, temperature 0.1 1 LLM call

{
  "min_years": 5,
  "must_skills": ["Go", "Java", "Kubernetes", "Docker", "PostgreSQL"],
  "plus_skills": ["gRPC", "AWS"],
  "education_requirement": "Bachelor in Computer Science or related field",
  "work_arrangement": null
}

Then a sanitizer (plain code) strips noise the model might sneak in: work mode, salary, office location. Those are never judged.

A second model reads the CV: total years of experience, every skill evidenced anywhere in it (including implied ones: Laravel implies PHP), and judgment on non-skill requirements like education and industry, each with a cited reason.

model: gpt-oss-120b, temperature 0.1 1 LLM call

{
  "cv_years_estimate": 0.5,
  "cv_skills": ["Python", "JavaScript", "Node.js", "React", "PostgreSQL", "Docker", "Git"]
}

Fresh graduate against a senior posting. Note the number: 0.5 years. Brutal, but honest, and it comes with receipts.

Now the LLMs are done. Everything from here is arithmetic. Skills are matched by a strict synonym engine (with transferable credit: PHP earns partial credit toward Python). Experience is banded by ratio. The score is a fixed formula.

pure code 0 LLM calls

score = 25% experience + 45% must_skills + 15% plus_skills + 15% education

hard filter: 5 years required, 0.5 found  ->  score capped at 55

The cap is the honesty feature: no amount of good vibes lets a fresh graduate score 80 against a senior role. The engine would rather be unpopular than wrong.

Only now does a model write. It receives the final verdicts as locked facts and turns them into natural Indonesian that connects to your actual background. Its instructions forbid changing or softening any verdict.

model: gpt-oss-20b, temperature 0.1 1 LLM call

{
  "synthesis": "Lowongan ini mid-level, dan kamu belum siap. Kekuatan utamamu
     Python dan Docker, tetapi syarat 5 tahun pengalaman belum terpenuhi..."
}

If this stage fails, template text takes over and the score ships anyway. Narration is decoration; the verdict is the product.

04 / The Receipts

Guards you will never see, working always.

[v] Hard filters

A 0.5-year CV against a 5-year requirement is capped at 55, with the reason shown to the user. The engine is allowed to say "skip this one".

[v] Noise sanitizer

Work mode, salary, benefits and office location are stripped by code before scoring. "Hybrid, 3 days in office" is job metadata, never a skill gap.

[v] Transferable credit

PHP does not equal Python, but they share a paradigm. Related skills earn partial credit instead of a harsh zero, the way a good recruiter would read it.

[v] Text-presence guard

If a required skill is literally written in the CV but missed by the parser, it degrades to partial, never missing. Deterministic, not an AI apology.

[v] Privacy by architecture

The CV file is parsed inside your browser and never uploaded. Analysis text is processed in memory, never stored.

[v] Multi-model routing

Four stages run across two model tiers fitted to free quotas. Marginal cost per analysis is near zero, so honesty does not need a budget.

05 / The Proof

Run it twice. Right now. On this page.

Live determinism check

This runs our real production engine twice, back to back, on the same input. If the scores differ, our entire pitch is wrong and you should close this tab. And because a curated sample is easy to dismiss: use your own CV and your own job posting. Try to break it.

idle
Run 1?
=?
Run 2?

Each live proof costs us roughly 20k tokens of API budget. We think showing the work is worth more than the tokens. The curated sample result is cached on your device; your own inputs are never cached or stored. One honest caveat: this proves consistency, not correctness. Two identical wrong scores are still wrong. Accuracy is measured separately against a human-labeled benchmark, and that number will be published here when it is ready.

Now try it with your own CV.

The demo runs this exact pipeline on whatever you paste. Free, no signup.

Open the Live Demo