Applicant-tracking systems used to rely almost entirely on keyword matching — a resume that never happened to type the exact phrase "project management" would be filtered out even if it described managing three cross-functional launches. Embedding-based matching fixes this by converting both resumes and job postings into numeric vectors in a shared space, then ranking candidates by how closely their vector's direction aligns with the job's, rather than by literal string overlap. The same technique — encode both sides into one geometry, then measure the angle between them — underpins modern semantic search, recommendation systems and retrieval-augmented generation, not just hiring software.
This simulation builds a small, fully transparent version of that pipeline rather than a black-box demo. A fixed taxonomy of eight skill categories plus years of experience defines a nine-dimensional vector for sixteen candidates and for whichever job posting you select. Moving the skills-vs-experience slider rescales those dimensions and recomputes real cosine similarity between every candidate and the job, instantly re-ranking the shortlist. A genuine principal component analysis — computed live via power iteration on the covariance matrix, not a canned 2D layout — projects the nine-dimensional space down to the scatter plot you see, so the plot itself visibly reorganises as the weighting or job posting changes.
What is an embedding, and why represent resumes and job postings as vectors?
An embedding is a numeric vector that places an item in a shared coordinate space so that similar items land near each other. In this simulation every resume and job posting is represented by a small, human-interpretable vector: one number per skill (proficiency from 0 to 1) plus one number for years of experience. Real production systems usually use dense vectors of a few hundred to a few thousand dimensions produced by a language model, but the underlying idea is identical — turn unstructured text into a point in space so that distance and angle between points become mathematically meaningful signals.
Why cosine similarity instead of Euclidean distance?
Cosine similarity measures the angle between two vectors regardless of their length: cos θ = (A·B)/(|A||B|). That matters here because a candidate with high proficiency across the board and a candidate with the same profile scaled down (rated a notch lower on every skill) should still be considered an equally good directional match to a job — Euclidean distance would penalise the second candidate just for having smaller magnitude, whereas cosine similarity correctly reports they point the same way. This is the standard choice for resume and document embeddings in real applicant-tracking and search systems.
What does the skills-vs-experience weight slider actually change mathematically?
Each candidate and job vector is rescaled before the similarity is computed: the eight skill dimensions are multiplied by the skills weight w, and the experience dimension is multiplied by (1 − w). Because cosine similarity depends on the relative proportions between dimensions, not their absolute size, changing w genuinely rotates every vector in the space — a candidate who is skill-strong but experience-light scores higher as w rises toward 1, and a seasoned generalist with modest skill depth climbs the list as w falls toward 0. The re-ranking you see is a direct, real consequence of that rescaling, not a scripted animation.
The simulation runs a real principal component analysis (PCA) on the current set of weighted vectors. It centres all points on their mean, builds the covariance matrix of the rescaled dimensions, and finds the top two eigenvectors by power iteration with deflation — the same iterative method used in production to approximate PCA when a full eigendecomposition is unnecessary. Every point is then projected onto those two directions, which is why moving the weight slider not only re-ranks the shortlist but also visibly reshuffles the scatter plot: the axes of maximum variance shift as the weighting changes.
This simulation reduces every resume to eight skill categories and one experience number, which is a useful teaching simplification but a real oversimplification of a resume's actual content. Production systems face harder problems this model sidesteps entirely: synonym and abbreviation matching ("JS" vs "JavaScript" vs "ECMAScript"), skill recency and decay (a skill listed but unused for eight years should count less), seniority signals buried in job titles and achievements rather than explicit ratings, and the fact that two people can describe the same underlying skill in completely different vocabulary. Real embedding models are trained specifically to be robust to that vocabulary mismatch.
Each job preset in this simulation carries its own required-skill vector and required-experience value, so switching jobs moves the point every candidate is being compared against — the job point itself relocates in the embedding space. A candidate who was the top match for a "Data Scientist" requirement (heavy Data & ML, SQL) can drop to the middle of the pack for a "Product Manager" requirement (heavy Product/UX, Leadership, Communication) because their vector's angle to the new job vector is simply less aligned, even though the candidate's own skills never changed.
Real embedding-based hiring tools have been shown to encode and amplify bias present in their training data — for example systematically down-ranking resumes that mention women's colleges, certain names, or non-traditional career gaps, because the model learned those correlations from historical hiring patterns rather than from any genuine skill signal. This simulation's hand-built, transparent skill vectors can't reproduce that failure mode, which is exactly the point: real systems need explicit fairness audits, protected-attribute scrubbing, and human review precisely because their embeddings are opaque in a way this eight-dimensional toy model deliberately is not.