<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: lmgk5133-dotcom</title>
    <description>The latest articles on DEV Community by lmgk5133-dotcom (@lmgk5133dotcom).</description>
    <link>https://dev.to/lmgk5133dotcom</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4024922%2F8dfcfd6b-8b5e-44e4-96ab-73fb551a3df3.png</url>
      <title>DEV Community: lmgk5133-dotcom</title>
      <link>https://dev.to/lmgk5133dotcom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lmgk5133dotcom"/>
    <language>en</language>
    <item>
      <title>I built a skills-extraction API that works in any language — and actually catches soft skills</title>
      <dc:creator>lmgk5133-dotcom</dc:creator>
      <pubDate>Sat, 11 Jul 2026 08:42:47 +0000</pubDate>
      <link>https://dev.to/lmgk5133dotcom/i-built-a-skills-extraction-api-that-works-in-any-language-and-actually-catches-soft-skills-2jm</link>
      <guid>https://dev.to/lmgk5133dotcom/i-built-a-skills-extraction-api-that-works-in-any-language-and-actually-catches-soft-skills-2jm</guid>
      <description>&lt;p&gt;Every "skills parser" API I tried had the same two problems.&lt;/p&gt;

&lt;p&gt;Problem 1: they return word salad. I fed one a single real resume line and got back a flat list of raw tokens — ["led",&lt;br&gt;
  "team", "backend", "kubernetes", "our"] — junk like "our" included, no structure at all. No confidence, no hard-vs-soft&lt;br&gt;
  distinction, no canonical names. You still have to clean up the mess yourself.&lt;/p&gt;

&lt;p&gt;Problem 2: they only speak English. I gave one a sentence in another language and got back an empty array. For anything with&lt;br&gt;
  a global user base, that's a dealbreaker.&lt;/p&gt;

&lt;p&gt;Here's the thing: most of what matters in a resume or job post is implicit. "Led a team of four" is Leadership. "Mentored two&lt;br&gt;
  juniors" is Mentoring. A keyword matcher will never catch those, because the words "leadership" and "mentoring" aren't&lt;br&gt;
  anywhere in the text. You need something that actually understands the sentence.&lt;/p&gt;

&lt;p&gt;So I built one.&lt;/p&gt;

&lt;p&gt;What it does&lt;/p&gt;

&lt;p&gt;One endpoint. Text in, normalized skills out — in any language.&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;p&gt;Migrated our backend to Kubernetes and led a team of 4 engineers.&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "skills": [&lt;br&gt;
      { "name": "Kubernetes",         "esco_label": "kubernetes",          "type": "hard", "confidence": 0.95 },&lt;br&gt;
      { "name": "Backend Development", "esco_label": "backend development", "type": "hard", "confidence": 0.90 },&lt;br&gt;
      { "name": "Leadership",          "esco_label": "leadership",          "type": "soft", "confidence": 0.90 }&lt;br&gt;
    ]&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;Notice what happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"led a team" → Leadership — a soft skill that never appears literally in the text.&lt;/li&gt;
&lt;li&gt;"our backend" did NOT become a skill — "our" is noise, so it gets dropped.&lt;/li&gt;
&lt;li&gt;Every skill is canonicalized (k8s, kubernetes, Kubernetes all collapse to one), tagged hard/soft, and given a confidence
score.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the exact same thing in Spanish:&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;p&gt;Migré el backend a Kubernetes y lideré un equipo de 4 ingenieros&lt;/p&gt;

&lt;p&gt;Output: the same canonical English skills — Kubernetes, Backend Development, Leadership. It normalizes across languages into&lt;br&gt;
  one vocabulary, so your downstream code only ever deals with English skill names no matter what language the input was in.&lt;/p&gt;

&lt;p&gt;I've tested English and Spanish so far, with more on the way. That multilingual + implicit-soft-skill combination is the&lt;br&gt;
  whole point — it's the exact gap the keyword parsers leave wide open.&lt;/p&gt;

&lt;p&gt;How it's built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Haiku 4.5 does the extraction, with structured outputs (a JSON schema the model is forced to conform to) so the
response is always valid JSON. No "sometimes it returns prose and your parser explodes" failures.&lt;/li&gt;
&lt;li&gt;A small normalization layer canonicalizes synonyms and de-dupes, keeping the higher-confidence instance when a skill shows
up twice.&lt;/li&gt;
&lt;li&gt;The whole thing is a single serverless function. Boring on purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting engineering wasn't the plumbing — it was guarding quality. The entire value here is extraction quality, so I&lt;br&gt;
  wrote a labeled eval set (must_include / must_exclude cases across languages) that runs before every deploy. If a prompt&lt;br&gt;
  tweak makes it start hallucinating "our" as a skill again, the eval catches it before it ships.&lt;/p&gt;

&lt;p&gt;What I learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building the API was the easy part — a weekend. Distribution is the actual business, and it's the part I'm figuring out
right now. This post is me learning that in public.&lt;/li&gt;
&lt;li&gt;Structured outputs turned "the LLM returns JSON… usually" into "the LLM returns valid JSON, always." If you're wrapping a
model in an API, use them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it / tell me where it breaks&lt;/p&gt;

&lt;p&gt;It's live with a free trial: &lt;a href="https://zylalabs.com/api-marketplace/other/skills+extraction+api/13176" rel="noopener noreferrer"&gt;https://zylalabs.com/api-marketplace/other/skills+extraction+api/13176&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd genuinely love for you to throw weird input at it — mixed-language sentences, sarcasm, job posts full of buzzwords — and&lt;br&gt;
  tell me where it falls apart. What language should I test next?&lt;/p&gt;

</description>
      <category>api</category>
      <category>ai</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
