Trnitá cesta od nápadu k realitě: Jak jsme z dat “vařili” SkillMatch aplikaci

Táňa Honkyšová
12 min readJun 2, 2024

--

❤ To jsme my ❤

Téma púrojektu: SkillMatch: najdi práci, která ti sedne

Nad projektem spolupracovali:

Mentees: Olga Murzinskaja, Táňa Honkyšová

Mentor: Vojta Tůma (Keboola)

Jak bychom mohly poutavě začít? V podstatě celý příběh projektu začínal triviálně. Měly jsme okolo šesti či sedmi, nebo i více nápadů, jakým směrem bychom se mohly ubírat. Nakonec jsme se rozhodly, že téma ke zpracování má být buď velmi zajímavé a neobvyklé, nebo užitečné a aplikovatelné. Zbyly tři (mezi nimi Spotify a Táňou extrémně oblíbený k-pop). Když ale přišla akce Meet Your Mentor, kdy jsme poprvé viděly (profesní láska na první pohled, mimochodem) Vojtu, po párminutové diskuzi bylo jasné, do čeho půjdeme a co nás čeká.

Dál začíná hlavní příběh…

Naše vize, cíle a vidina jednoduché cesty:

Téma vzniklo na základě vlastního zájmu, ale také zájmu kamarádek, spolužaček a blízkého okolí. “Dokončuji IT kurz (teprve se chystám toto dobrodružství podniknout), získám penzum znalosti a dovednosti, užitečných v IT světě, ale co teď s tím? Kam se mám hlásit? Kde to dám? Pro kterou pozici budu vhodná? Jak napasovat to, co umím k nabídkám, které vyhledám?…” To jsou otázky, které vrtají v hlavách budoucích datových analytiček nebo securiťáček, nebo třeba webových designérek. Rozhodly jsme se proto prolustrovat nabídky pracovních portálů, vybrat inzeráty z IT sféry, vytáhnout požadavky na uchazeče a napasovat tyto požadavky na dovednosti, které holky v kurzu Czechitas (libovolného) získaly.

Cílem se stala aplikace, přesněji řečeno dashboard v Tableau, který by se tvářil jako aplikace a byl by uživatelský přívětivý a usnadnil by vyhledávání práce na míru. Stačilo vybrat potřebné dovednosti, kterými disponuji, úroveň, o kterou se zajímám (interface aplikace je v angličtině, úrovně tedy jsou Junior, Middle, Senior) a voilà — mám před sebou seznam pozic s krátkým popisem a odkazem na web.

Skica — návrh budoucího dashboardu — aplikace.
Tak nějak jsme si představovaly výsledek…

To bude hračka, řekly jsme si…ale všechno bylo jinak.

Strategický plán:

(zvládnuto rychle a bez problémů) ***(výzvy, slepé uličky, objevy, komplikace, řešení problémů)

  1. Získání dat. Zdroje — data z portálů job.cz, LinkedIn.com, Indeed, způsob — web scraping Apify Actors. Data z jobs.cz byly Apify laskavě nabídnutý a námi s vděčnosti přijaté ❤ (Pro zájemce — jak to chodí mezi Apify a Keboolou, nebo zde).
  2. Čištění a příprava dat. Úkol — odstranit duplicity, standardizovat názvy pozic a společnosti, zajistit konzistenci dat napříč různými zdroji. Pravidelně kontrolovat kvalitu dat a upravovat naše metody podle potřeby.❓
  3. Sestavení seznamu klíčových dovedností. Úkol — získaná data: analyzovat pracovní pozice a identifikovat klíčové dovednosti požadované zaměstnavateli; kurzy Czechitas: sestavit seznam dovednosti získaných během kurzů (údaje pochází z výstupů každého kurzu). Účel — dovednosti z kurzů porovnat s požadavky na pracovních pozicích.❓
  4. Finální příprava dat. Úkol — sjednotit tabulky, vytvořit strukturované tabulky s informacemi o pracovních pozicích, dovednostech a jejich kategorizaci.❓
  5. Práce v Tableau. Úkol — transfer dat z Kebooly, vytvořit filtry, ovládací prvky (buttons), promyslet uživatelské rozhraní včetně pozadí a dalších vizuálních komponent.❓

Použité nástroje. Keboola je hlavní komponentou celého projektu (SQL použijeme pro Snowflake Workspace a Transformace, Jupyter notebook — totéž pro Python). Na Vojtův podnět objevujeme v Keboole komponentu Generative AI, aktivně se učíme promt engeneeringu, zanedlouho zjistíme, že pro náš postup potřebujeme i něco dalšího. Na řádu přichází naprosto fascinující věci — embedding a vektorová databáze (Cohere, Pinecone).

Stručný slovníček pojmů:

Vnořování (embedding) — technika v oblasti strojového učení, která převádí data do vektorové reprezentace, čímž je promění na čísla.

Vektorová databáze databáze určená pro ukládání a práci s vektory, což jsou seznamy čísel s pevnou délkou, které reprezentují data jako body v multidimenzionálním prostoru. Umožňuje efektivní ukládání a vyhledávání vektorových reprezentací dat, vhodné pro úlohy strojového učení, jako je vyhledávání podobnosti, multimodální vyhledávání a doporučování.

Od začátku až do konce — Keboola Flow:

Výzvy, nástrahy, slepé uličky a konečná řešení 💡:

Obtížnost:

💥- nízká

💥💥- střední

💥💥💥- vysoká

  • Odstranění emoji a nadbytečných mezer. Zjistili jsme, že názvy pozic obsahují emoji, což překáželo v hledání duplicit a standardizování názvů pozic a společností. Po neuspokojivých pokusech zbavit se těchto znaků v SQL přišlo elegantní a stručné řešení v Python (Regular Expressions, neboli regex). 💥
  • Extrahování popisu pozice z html kódu, který byl součásti scraipovaného souboru. Zádrhel spočíval v nalezení místa, odkud v rozsáhlém html má BeautifulSoap začít svou práci. 💥
  • Tvorba krátkého popisu (All jobs — summary description), zařazení do hlavních kategorii (All jobs — categorize IT fields), úrovní (All jobs — level), zařazení do IT odvětvi (All jobs — IT or non IT) pomocí komponenty Generative AI v Keboole. 💥💥💥

Generative AI nabízí možnost volby z několika modelů, pracovaly jsme s modely gpt-3.5-turbo-0125, gpt-3.5-turbo-0301, gpt-3.5-turbo-16k a některými dalšími.

Hlavní problémy při práci s LLM v Keboola:

  1. Do pole s promptem lze zadat pouze jeden sloupec vstupních dat ([[INPUT_COLUMN]]), tj. pro porovnání bylo nutné vypsat celý seznam kategorii, úrovní atd.
  2. Pro dosažení optimálního výsledku jsme měnily prompty —velmi časově náročné; i malá změna mohla být doprovázená mnohém horšími nebo mnohém kvalitnějšími výsledky. Postřeh — požadavek na striktní dodržení určitého pokynu musí být zopakován a zdůrazněn v jednom promptu několikrát.
  3. Je nutno zohledňovat finanční stránku — použití modelu 3.5 je finančně mnohém výhodnější, než použití modelu 4.
  4. Problém — chyba 429, vznikla vždy, kdy vstupní soubor byl příliš velký, ve sloupci výstupních hodnot se mezi očekávanými výsledky objevovala tato chyba tehdy, kdy byl překročen limit tokenů.
Encountered OpenAIError: Error code: 429 - {'error': 
{'message': 'Rate limit reached for gpt-3.5-turbo-0125
in organization org-*** on tokens per min (TPM):
Limit 60000, Used 59406, Requested 1940.
Please try again in 1.346s.
Visit https://platform.openai.com/account/rate-limits to learn more.',
'type': 'tokens', 'param': None, 'code': 'rate_limit_exceeded'}}

Řešení — rozdělit vstupní soubor na menší části (po 50 řádcích), provedeno ve 4. kroku Keboola Flow (Split_all_jobs_cleaned). Problém — dělení souboru na části probíhalo iterovaně podle indexu, taktéž dynamický probíhala tvorba názvů souborů. V Python transformací je nutno zvolit výstupní soubor přesně, nelze zvolit pouze output složku, je to dáno způsobem práce se soubory (napřed se tvoří temporary soubor, který následně se zapisuje do předpřipraveného souboru; pokud takový není nalezen, vzniká chyba). Vznikla kolize mezi dynamickou tvorbou souborů a nutností dopředu definovat výstup. Řešení — omezit počet řádků vstupního souboru, přesně stanovit výstup. Důležitá poznámka — ačkoli při práci v prostředí Keboola spíše pracujeme s relativní adresou “out/tables/” nebo “in/tables/”, při tvorbě dynamických názvů souborů je potřeba pro zadání cílové složky použít absolutní adresu “/data/out/tables/”

Předpřipravené výstupní soubory

Příklady vytvořených promptů pro komponentu Generative AI:

Stručný popis pozice — summary. Zkoušením jsme došly k závěru, že délka a přesnost promptu v případě souhrnu textu nezaručuje kvalitnější výsledek. Stejně uspokojivého výsledku jsme dosáhly s kratším promptem.

#Zbytečně dlouhý a příliš podrobný prompt.

Read and evaluate the text of the job offer provided in the description.
After understanding the key details and requirements of the job,
compose a summary in English consisting of three to four concise
sentences.
This summary should encapsulate the main aspects of the job offer,
highlighting the primary responsibilities, qualifications,
and any unique benefits.

Text of offer is following: [[description]]

Example of output:
Summary:
#Krátký prompt, výsledkem kterého jsou (skutečně jsou, 
#což bylo zázrakem po naších zkušenostech s AI) tři věty s výstižným
#krátkým souhrnem inzerátu. Evidentně summary LLM zvládá velmi dobře.

Based on the following job description in [[description]],
create a brief three-sentence summary in English that captures
the most important aspects of the listing. Sure make it short as possible.

Zařazení inzerátů do předurčených úrovní. V tomto a dalších případech je potřeba vytvořit prompty, které přesně určuji a zdůrazňují problém, který má LLM vyřešit a jaké očekávané výsledky má vrátit.

#Příklad špatné formulace, do výsledků byly přidány vlastní vytvořené 
#kategorie nebo výsledek obsahoval větu, ne jedno požadované slovo.

According to [[description]] please assign it to Junior or Middle or
Senior level. Return only one of three options Junior, Middle, Senior.
#Formulace, která zaručí očekávané výsledky a eliminuje téměř na 100% 
#nevhodné.

Based on [[description]] select the most relevant level from this list:
[Junior, Middle, Senior]. Return only one of three options Junior, Middle,
Senior.
Example of output:
Junior
Do not add any additional text.

Zařazení inzerátu dle popisu do předdefinovaných hlavních kategorií.

#Verze promtu, se kterým výsledky nebyly uspokojívé, 
#zařazení do kategorií nebylo přesné, občas ve výsledku se objevily nově
#vytvořené kategorie nebo celá věta místo jediné kategorie.

Based on [[description]] assign appropriate fields from these categories:
[Development & Design, Data Analysis & Engineering,
IT Business & Transformation, Testing & Quality, Cybersecurity].
Ensure that the category is selected from the provided list and
do not invent new categories.

Do not add any additional text.

****
#Další verze, ačkoli obsahuje vzor výstupu, také neprošla:

Based on [[description]] select the most relevant category
from the following list:[Development & Design,
Data Analysis & Engineering, IT Business & Transformation,
Testing & Quality, Cybersecurity].
Ensure that the category is selected from the provided list and
do not invent new categories.
Example of output:
Testing & Quality
Do not add any additional text.
#Finální verze s nejvíce vyhovujícími výsledky:

Classify the given job description [[description]] by matching it
to one of these predefined categories: Development & Design,
Data Analysis & Engineering, IT Business & Transformation,
Testing & Quality, Cyber Security. If the description does not fit
any of these categories or if the classification certainty
is below 100%, the output should be ‘null’.

Instructions:

Only use the specified categories.
Do not introduce new categories.
Output only the category name or “null,” with no extra text.

Example of output:
Data Analysis & Engineering

Ensure do not add any additional text, only as example of output.
Make sure not to create new categories beyond the ones listed above.

Výpis požadovaných dovedností z popisu inzerátu.

Based on description of job offers give me required hard skills 
as list of single-word or phrase keywords in English.
Give me response as JSON array. Make sure you return valid JSON.

Text of offer is following: [[description]]
  • Zařazování dovedností do nadřazených kategorií. 💥💥💥(a ještě víc)

Koncept — vytvořit nadřazené kategorie na základě seznamu klíčových slov (opěrným bodem byl seznam dovedností, získaných v různých kurzech Czechitas), pomocí Generative AI provést kategorizaci ze sloupce “skill” do předdefinovaných kategorií.

Seznam dovedností Czechitas
  • Neúspěšný pokus o zařazení do kategorií pomocí komponenty Generative AI. Došly jsme k závěru, že je nutné vytvořit přesnější kategorie v menším počtu. Kategorie jsme navrhovaly intuitivně dle vlastních zkušenosti s oporou o nápovědu Chat GPT. Naprosto nevyhovující výsledky.
Categorize [[skill]] into one of the following categories: 
[AI, Data Analysis, Data Modelling, Big Data, SQL,
Visualization Tools, Web Analytics Tools, Programming languages,
Front-End, Git, Content Management Systems, UX, API Automation,
UI Automation, Exploratory Testing, Network, Application,
Security Protocols, Network Monitoring Tools, Security Systems,
Cybersecurity Management and Operations, Application and Network Security,
Operation Systems, Command Line Proficiency, Security Policies,
Microsoft 365, Salesforce, Snowflake, Keboola, Cloud Infrastructures].
Ensure that the category is selected from the provided list and do not
invent new categories. If the skill does not match any category in the
list, return "null".

Output:
Programming languages
Do not add any additional text.
  • Některé z dalších nepodařených pokusů o třídění do kategorií ve spolupráci s Chat GPT, Gemini, Bing Copilot. Každá verze byla testována v komponentě Generative AI. Ani v tomto případě výsledky nebyly podle očekávání.
  • Téměř finální verze kategorií, se kterou se pracovalo dál. Závěr — kategorie mají být od sebe pojmově a obsahově dostatečně vzdálené, aby LLM mohl provést správnou klasifikaci. Jakmile nějaké dvě kategorie jsou podobné, je vysoká pravděpodobnost, že zařazení neproběhne správně.
Artifical Inteligence, Programming Languages (e.g., Java, Python), 
Web Development (e.g., HTML, CSS), Data Engineering & Analysis (e.g., SQL,
Data Modelling), Automation & Testing (e.g., Selenium, API Automation),
Cyber Security (e.g., Firewall, Threat Intelligence),
Networking (e.g., TCP/IP, DNS),
Version Control & Collaboration (e.g., Git, Microsoft 365),
Big Data & Cloud (e.g., Apache Spark, Snowflake),
Visualization & Reporting (e.g., Power BI, Tableau),
Business & Productivity Tools (e.g., Microsoft 365, Salesforce),
Command Line & Scripting (e.g., Bash, PowerShell),
UX/UI Design (e.g., Canva, UX)

K prověření konceptu vytvořených kategorií jsme použily modelování v Cohere Embed, kde jsme mohly interaktivně sledovat vzájemné interakce mezi zadanými pojmy (Embed bere seznam vět a vrací seznam vektorů, což modelu umožňuje porovnávat jejich významy).

Porovnávání zadaných dovedností s hlavními skupinami

Vektorová databáze Pinecone. Nehledě na pojmově vymezený a odzkoušený seznam hlavních kategorií nedaří se provést správné zařazení dovedností pomocí Generative AI, a Vojta přichází s nápadem použít pro tento účel embedding a vektorovou databázi.

  • Tvorba seznamu kategorií s jejich názvy a definicemi. Poznámka — zjistili jsme, že definice nemůže být příliš obsáhlá, výsledné scóre je pak velmi vysoké, porovnání významů a zařazení do kategorie neproběhne s očekávaným výsledkem. Metodou pokus-omyl dotváříme seznam, provádíme drobné úpravy v názvech kategorií a jejích definic. Tato část kódu se provádí samostatně, není zahrnutá do Flow, slouží k vytvoření seznamu kategorií.
Ukázka první položky indexu “categories”
  • Kategorizace dovedností do vytvořených kategorií — Flow, krok č.8

SQL lahůdky:

  • Spojení zpracovaných dat (L2 Merge AI results), krok č.6 ve Flow💥💥

Odstranění duplicit pomocí řádkovaní položek na základě porovnaní “company” (názvu společnosti) a “positionName” (názvu pozice), duplicity vznikly z důvodu zveřejnění stejného inzerátu na různých portálech.

Provedení standardizace klasifikace po výstupu z Generative AI komponenty a podchycení drobných nesprávných výstupů.

  • Tvorba tabulek pro finální zpracování (L3 Creating tables), krok č.7 ve Flow. 💥💥

Použití funkce LATERAL FLATTEN (funkce ve Snowflake, která se používá k transformaci semi-strukturovaných dat (jako jsou JSON, VARIANT, OBJECT nebo ARRAY) do relačního formátu. Tato funkce umožňuje “rozložit” složité hodnoty do více řádků a vytvořit tak laterální pohled, což je v podstatě vložený pohled, který obsahuje korelaci odkazující na jiné tabulky, které mu předcházejí ve výrazu FROM), tvorba nové tabulky s odstraněním specifických chyb.

Vizualizace dat v Tableau.

  • Transfer dat z Kebooly do Tableau ➱ propojení tabulek ➱ nastavení základních filtrů v záložce Data Source (vyřazení nulových hodnot ze sloupců “Field”, “Parent Category”, vyřazení položek non IT z sloupce “industry”. 💥
Propojení tabulek v Tableau
  • Filtry s více možnostmi výběru podle úrovně (Junior, Middle, Senior), IT oborů (analýza dat, cyber security, web development, atd.), nadřazených IT kategorií a klíčových dovedností. 💥💥
  • Tvorba tlačítek, pozadí a dalších vizuálních prvků. 💥💥💥
  • Match Score (procento shody). 💥💥💥 podle následujícího vzorce: [WINDOW_SUM(COUNTD([Parent Category]))] / [SUM({ FIXED [Id Job Offer],[Position Name],[Company] : COUNTD([Parent Category]) })].

Zde představujeme prototyp interaktivního dashboardu, který umožňuje uživatelům filtrovat pracovní pozice podle potřeby. Uživatelé mohou zobrazit podrobnosti o nabízené pozici, krátký popis pozice a procento shody jejich dovedností s požadavky na pozici.

Verze (10. 06. 2024) na Tableau Public:

Závěr:

Zazvonil zvonec….a pohádce stále není konec.

Takto modifikované tradiční české přísloví, které se obvykle používá na konci pohádek a znamená, že příběh skončil, v našem pojetí znamená, že tento projekt má potenciál dalšího rozvoje, dále představujeme několik klíčových vizí, které mohou posloužit jako vodítko pro budoucí směřování a rozvoj našeho nástroje:

  • Integrace dalších zdrojů dat: rozšířit současnou datovou základnu o další relevantní portály s pracovními nabídkami nejen z České republiky, ale i z mezinárodního trhu.
  • Reálná data od zaměstnavatelů: navázat partnerství s firmami, které nám mohou poskytnout přímý přístup k jejich interním datům o náboru a požadovaných dovednostech.
  • Uživatelské rozhraní: neustále zlepšovat uživatelské rozhraní na základě zpětné vazby od uživatelů, aby bylo co nejvíce intuitivní a uživatelsky přívětivé.
  • Mobilní aplikace: vyvinout mobilní verzi dashboardu, aby uživatelé měli přístup k datům a analýzám kdykoliv a kdekoliv.
  • Rozmanitost oborů: rozšířit analýzu na různé profesní obory, aby byla naše platforma přínosná pro širší spektrum uživatelů.
  • Regionální specifika: přizpůsobit analýzu specifickým regionálním požadavkům, což pomůže uživatelům lépe porozumět lokálním trendům.
  • Vylepšení kategorií a podkategorií: pracovat na detailnějším rozdělení pracovních pozic podle odvětví, úrovně zkušeností a specifických dovedností. Tím zajistíme, že analýzy budou přesnější a uživatelé dostanou relevantnější doporučení.

Naše cesta od prvotního nápadu k funkčnímu prototypu v Tableau byla plná výzev, o kterých jsme ani nemohly tušit že přijdou. Také plná nových objevů a cenných zkušeností.

V rámci tohoto projektu jsme se zaměřily na analýzu pracovního trhu v IT sektoru. Využily jsme různé pokročilé nástroje a technologie, včetně:

  • Keboola pro datovou integraci a transformaci
  • Tableau pro vizualizaci dat
  • Generative AI pro analýzu a kategorizaci pracovních pozic
  • Vektorové databáze pro přesnější třídění dovedností a požadavků

Naučily jsme se pracovat s rozsáhlými datovými soubory, provádět web scraping, čistit a standardizovat data, a využívat pokročilé techniky strojového učení. Projekt byl prospěšný tím, že jsme se snažily vytvořit produkt a míru pro holky z Czechitas. Prozkoumaly jsme, jaké dovednosti ženy mohou získat z kurzů a aplikovaly jsme je ve svém projektu, který byl přizpůsobený potřebám absolventek Czechitas. Projekt byl celkově založen na zkoumání funkčnosti a praktického využití umělé inteligence.

Poděkování:

Tímto chceme poděkovat všem ochotným, chápajícím, trpělivým lidem, kteří nám věnovali svůj čas, nápady, znalosti a podporu:

Vojta Tůma, Daniel Slivka, Dominika Pípová, Patrícia Gogová, Tereza Fukátková, Martin Grossmann, Jirka Pešík, Jiří Macourek, Martina Gelnerová.

A také všem, kdo nás podporoval a koho jsme potkaly na této náročné cestě.

--

--