feat: personalize scoring and add skills radar
This commit is contained in:
@@ -29,10 +29,13 @@ IT_TITLE_TERMS = (
|
||||
"bi analyst",
|
||||
"system engineer",
|
||||
"systems engineer",
|
||||
"system network engineer",
|
||||
"system administrator",
|
||||
"systeembeheer",
|
||||
"infrastructure engineer",
|
||||
"infrastructuur engineer",
|
||||
"network engineer",
|
||||
"network administrator",
|
||||
"network architect",
|
||||
"netwerkbeheer",
|
||||
"netwerk engineer",
|
||||
@@ -44,6 +47,10 @@ IT_TITLE_TERMS = (
|
||||
"information security",
|
||||
"informatiebeveiliging",
|
||||
"workplace engineer",
|
||||
"endpoint engineer",
|
||||
"microsoft 365 engineer",
|
||||
"m365 engineer",
|
||||
"intune engineer",
|
||||
"modern workplace",
|
||||
"digital workplace",
|
||||
"service desk",
|
||||
@@ -51,6 +58,8 @@ IT_TITLE_TERMS = (
|
||||
"helpdesk",
|
||||
"support engineer",
|
||||
"support specialist",
|
||||
"it technician",
|
||||
"pc technician",
|
||||
"application lead",
|
||||
"application engineer",
|
||||
"application manager",
|
||||
@@ -106,6 +115,48 @@ IT_TITLE_TERMS = (
|
||||
"test automation",
|
||||
)
|
||||
|
||||
# These engineering titles occur both in IT and in unrelated technical sectors. They are
|
||||
# accepted only when the title supplies the role context and the description independently
|
||||
# supplies a strong IT signal. A description signal by itself remains insufficient.
|
||||
CONTEXTUAL_IT_TITLE_TERMS = (
|
||||
"field engineer",
|
||||
"field service engineer",
|
||||
"implementation engineer",
|
||||
"implementation consultant",
|
||||
"service engineer",
|
||||
)
|
||||
|
||||
IT_DESCRIPTION_TERMS = (
|
||||
"microsoft 365",
|
||||
"m365",
|
||||
"windows server",
|
||||
"active directory",
|
||||
"entra id",
|
||||
"intune",
|
||||
"autopilot",
|
||||
"exchange online",
|
||||
"sharepoint",
|
||||
"vmware",
|
||||
"proxmox",
|
||||
"hyper-v",
|
||||
"networking",
|
||||
"netwerkbeheer",
|
||||
"tcp/ip",
|
||||
"vlan",
|
||||
"vpn",
|
||||
"dhcp",
|
||||
"dns",
|
||||
"firewall",
|
||||
"switches",
|
||||
"routers",
|
||||
"workstations",
|
||||
"desktops",
|
||||
"laptops",
|
||||
"voip",
|
||||
"3cx",
|
||||
"powershell",
|
||||
)
|
||||
|
||||
# These phrases can contain IT vocabulary while describing commercial, recruitment,
|
||||
# or educational-design work. They therefore override positive title signals.
|
||||
NON_IT_TITLE_TERMS = (
|
||||
@@ -126,8 +177,16 @@ def _term_pattern(term: str) -> str:
|
||||
|
||||
IT_TITLE_PATTERN = "(?:" + "|".join(_term_pattern(term) for term in IT_TITLE_TERMS) + ")"
|
||||
NON_IT_TITLE_PATTERN = "(?:" + "|".join(_term_pattern(term) for term in NON_IT_TITLE_TERMS) + ")"
|
||||
CONTEXTUAL_IT_TITLE_PATTERN = (
|
||||
"(?:" + "|".join(_term_pattern(term) for term in CONTEXTUAL_IT_TITLE_TERMS) + ")"
|
||||
)
|
||||
IT_DESCRIPTION_PATTERN = (
|
||||
"(?:" + "|".join(_term_pattern(term) for term in IT_DESCRIPTION_TERMS) + ")"
|
||||
)
|
||||
_IT_TITLE_RE = re.compile(IT_TITLE_PATTERN, re.IGNORECASE)
|
||||
_NON_IT_TITLE_RE = re.compile(NON_IT_TITLE_PATTERN, re.IGNORECASE)
|
||||
_CONTEXTUAL_IT_TITLE_RE = re.compile(CONTEXTUAL_IT_TITLE_PATTERN, re.IGNORECASE)
|
||||
_IT_DESCRIPTION_RE = re.compile(IT_DESCRIPTION_PATTERN, re.IGNORECASE)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -137,7 +196,7 @@ class ItRelevanceAssessment:
|
||||
reason: str
|
||||
|
||||
|
||||
def assess_it_relevance(title: str) -> ItRelevanceAssessment:
|
||||
def assess_it_relevance(title: str, description: str = "") -> ItRelevanceAssessment:
|
||||
normalized_title = normalize_token(title)
|
||||
blocked_signal = _NON_IT_TITLE_RE.search(normalized_title)
|
||||
if blocked_signal:
|
||||
@@ -157,6 +216,23 @@ def assess_it_relevance(title: str) -> ItRelevanceAssessment:
|
||||
signals=signals[:4],
|
||||
reason="IT-signaal in functietitel: " + ", ".join(signals[:4]),
|
||||
)
|
||||
contextual_title = _CONTEXTUAL_IT_TITLE_RE.search(normalized_title)
|
||||
if contextual_title:
|
||||
description_signal = _IT_DESCRIPTION_RE.search(normalize_token(description))
|
||||
if description_signal:
|
||||
return ItRelevanceAssessment(
|
||||
relevant=True,
|
||||
signals=(contextual_title.group(0), description_signal.group(0)),
|
||||
reason=(
|
||||
"IT-context bevestigd via ambigue functietitel en vacaturetekst: "
|
||||
f"{contextual_title.group(0)}, {description_signal.group(0)}."
|
||||
),
|
||||
)
|
||||
return ItRelevanceAssessment(
|
||||
relevant=False,
|
||||
signals=(),
|
||||
reason="Ambigue technische functietitel zonder aantoonbare IT-context.",
|
||||
)
|
||||
return ItRelevanceAssessment(
|
||||
relevant=False,
|
||||
signals=(),
|
||||
@@ -175,6 +251,10 @@ def profile_requires_it_focus(profile: SearchProfile) -> bool:
|
||||
|
||||
def it_relevance_query(prefix: str = "") -> Q:
|
||||
"""Return the database equivalent of the conservative title-led classifier."""
|
||||
return Q(**{f"{prefix}original_title__iregex": IT_TITLE_PATTERN}) & ~Q(
|
||||
clear_title = Q(**{f"{prefix}original_title__iregex": IT_TITLE_PATTERN})
|
||||
contextual_title = Q(**{f"{prefix}original_title__iregex": CONTEXTUAL_IT_TITLE_PATTERN}) & Q(
|
||||
**{f"{prefix}description_text__iregex": IT_DESCRIPTION_PATTERN}
|
||||
)
|
||||
return (clear_title | contextual_title) & ~Q(
|
||||
**{f"{prefix}original_title__iregex": NON_IT_TITLE_PATTERN}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user