What the LLMs actually changed
We had machine learning in production at eJobs.ro for years before any of this was called AI. Skill classification and occupation taxonomies, vectorisation, recommendations, a fitness score. Then the language models arrived and changed one layer of that stack completely and the rest of it not at all.
Worth being precise about which is which, because the marketing suggests otherwise.
What genuinely changed
The representation layer, and it’s not a small thing. Getting a useful vector for a piece of text used to be a project. You trained something on your own corpus, you maintained it, and it understood your domain and nothing else.
Now a good multilingual embedding model is something you pick up. For a market where CVs arrive in Romanian and English and job ads mix both in the same paragraph, that matters more than it would elsewhere.
It also collapsed a step we used to need. The instinct was to have a model summarise a CV and then embed the summary, on the theory that the summary is cleaner. We’ve been testing the simpler thing instead: embed the last experience titles directly and skip the generation entirely. Fewer moving parts, no generated text to be wrong in a way you can’t see. I’m not going to claim a verdict yet, but the direction of the experiments is toward doing less, not more, which is not what I expected going in.
What didn’t change at all
The taxonomy still matters. We match against ESCO, and it’s working. The temptation with a good embedding model is to throw the controlled vocabulary away and let similarity handle everything. It doesn’t. A vocabulary is a shared agreement about what things are called, and similarity is a guess about whether two strings are related. Those are different objects and one doesn’t replace the other. The open question we’re still working through is the right granularity: the most specific occupation label, or the full category breadcrumb, which carries more context but dilutes the vector.
The labels still matter. Every useful thing still needs human judgement captured somewhere. A language model is a very good way to produce a first pass and a very bad way to establish ground truth about your own market.
Freshness still matters. An embedding of a stale CV is a stale embedding regardless of which model produced it.
Evaluation got harder. When the components were simple you could reason about which one was wrong. Now a bad result can come from the embedding, the retrieval, the prompt or the taxonomy mapping, and the whole thing is confident either way.
The problem none of it solved
Read a job description and tell me which requirements are real.
Some skills are must-have and some are decoration. “PHP developer with online betting experience” is a genuine constraint, because the domain knowledge is the job. Elsewhere the same shape of sentence is aspirational and the employer will hire without it.
Nothing in the stack knows the difference. There are hints. The words required and nice-to-have, an explicit number of years, and the useful observation that when requirements are an ungrouped list the first few carry more weight than the rest. But a reliable reading of which requirements actually bind is not something we have, and it’s the thing that would most improve matching.
It looks like exactly the problem language models should have solved. It’s the one they haven’t.
The general lesson
The models replaced the part of the stack that was tedious and left every part that was hard. That’s not a complaint. Tedious was most of the work.
But if you’re deciding what to build now, the durable things are the same ones as before: know what your words mean, capture human judgement, keep your representations fresh, and be able to tell whether any of it is working.