Ładowanie...
Ładowanie...
Produkcyjny data product: od scraperów przez normalizację i deduplikację, po AI enrichment i wyszukiwanie wektorowe. Self-hosted, ~25k ofert, 7 źródeł.
Scrapery Python (7×) ↓ surowy JSON PostgreSQL — bronze (raw, niezmienione) ↓ dbt run silver (normalizacja, walidacja, dedup fingerprint) ↓ gold.ai_job_summaries (AI summary, role_tags, embeddings) ↓ Next.js App Router — SSR + REST API (/api/jobs) ↓ pgvector — semantic search (cosine similarity) ↓ Użytkownik — filtry, AI insights, podobne oferty
Polski rynek ofert IT jest rozproszony po 7+ job boardach. Każdy portal ma własny format danych, własne nazewnictwo technologii, własną strukturę wynagrodzeń. Kandydat szukający pracy musi przeglądać je osobno, tracąc czas na duplikaty i niespójne filtry.
Celem było: jedna wyszukiwarka z ujednoliconymi filtrami, deduplikacją między źródłami i jakością danych na poziomie umożliwiającym AI enrichment.
7 scraperów (JustJoin.it, NoFluffJobs, Pracuj.pl, BulldogJob, SolidJobs, RocketJobs, LinkedIn) uruchamianych co ~30 minut przez APScheduler w Dockerze.
Surowe dane przechodzą przez warstwę silver zbudowaną w dbt. Każda transformacja jest testem danych — jeśli `accepted_values` się nie zgadza, build nie przejdzie.
-- accepted_values na exp_level
tests:
- accepted_values:
values: ['junior', 'mid', 'senior', 'lead', 'c-level']
severity: warnTa sama oferta pojawia się na wielu portalach jednocześnie. Bez deduplikacji użytkownik widzi tę samą pozycję 3–4 razy z różnymi danymi.
Opis HR jest często rozwodniony i trudny do szybkiej oceny. AI analizuje tekst i generuje zwięzłe podsumowanie techniczne z perspektywy inżyniera.
Klasyczne wyszukiwanie po słowach kluczowych nie rozumie intencji. Zapytanie "backend Python mikrousługi" nie znajdzie oferty z "Python, FastAPI, distributed systems".
services: jobpulse_db: # PostgreSQL + pgvector jobpulse_scheduler: # Python scrapery + ETL jobpulse_embed: # Embeddings worker jobpulse_web_blue: # Next.js (blue-green deploy) jobpulse_web_green: # Next.js (blue-green deploy) jobpulse_adminer: # DB admin