Title tier of relevance_score accepts token containment
Live case: the job titled "Generative Engineer" sourced a pool titled "Generative AI Engineer" -- the exact phrase never occurs in that title, so every genuine match fell through to the scattered 35 tier and the whole pool compressed into the 40s. A current title containing every job-title token now earns the full 55. The headline tier stays phrase-only so keyword-stuffed headlines still cap at the 35 tier. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>pull/29/head
parent
031261f179
commit
cec3be73fb
|
|
@ -418,11 +418,17 @@ def _match_tokens(*texts) -> set[str]:
|
|||
def relevance_score(job: dict, profile: dict) -> int:
|
||||
"""0-100 job-fit rank for sorting, computed when a profile is persisted.
|
||||
|
||||
Deterministic and free. Title component: the job title as an exact PHRASE
|
||||
in the person's current title scores 55, in their headline 45; scattered
|
||||
Deterministic and free. Title component: a current title CONTAINING every
|
||||
job-title token scores 55 — containment, not exact phrase, because job
|
||||
titles rarely reappear verbatim ("Generative Engineer" vs the pool's
|
||||
"Generative AI Engineer"; seen live: the phrase rule dropped every real
|
||||
match to the scattered tier and compressed the whole pool into the 40s).
|
||||
The job title as an exact phrase in the headline scores 45; scattered
|
||||
token overlap caps at 35 — a keyword-stuffed headline ("AI/ML Engineer |
|
||||
Python | FastAPI | ...") must not outrank someone whose title IS the job
|
||||
title, which is exactly what token overlap alone did on live data.
|
||||
title, which is exactly what token overlap alone did on live data. The
|
||||
headline tier stays phrase-only for the same reason: stuffed headlines
|
||||
contain every token of every hot title.
|
||||
|
||||
Skills component (up to 45): GRADED token overlap between the content
|
||||
words of the job's requirements + optional skills and the person's
|
||||
|
|
@ -432,16 +438,20 @@ def relevance_score(job: dict, profile: dict) -> int:
|
|||
whole live pool on exactly 60.
|
||||
"""
|
||||
job_title = _clean_phrase(job.get("title"))
|
||||
job_title_tokens = set(job_title.split())
|
||||
title_text = _clean_phrase(profile.get("current_title"))
|
||||
headline_text = _clean_phrase(profile.get("headline"))
|
||||
if job_title and job_title in title_text:
|
||||
if job_title and job_title_tokens <= set(title_text.split()):
|
||||
title_component = 55.0
|
||||
elif job_title and job_title in headline_text:
|
||||
title_component = 45.0
|
||||
else:
|
||||
title_tokens = set(job_title.split())
|
||||
role_tokens = set(title_text.split()) | set(headline_text.split())
|
||||
ratio = len(title_tokens & role_tokens) / len(title_tokens) if title_tokens else 0.0
|
||||
ratio = (
|
||||
len(job_title_tokens & role_tokens) / len(job_title_tokens)
|
||||
if job_title_tokens
|
||||
else 0.0
|
||||
)
|
||||
title_component = 35 * ratio
|
||||
|
||||
job_tokens = _match_tokens(
|
||||
|
|
|
|||
|
|
@ -404,7 +404,25 @@ def test_headline_phrase_scores_below_title_phrase():
|
|||
scattered = plugins.relevance_score(job, {"current_title": "Engineer", "headline": "Agentic AI | Python"})
|
||||
assert in_title == 55
|
||||
assert in_headline == 45
|
||||
assert scattered == 35 # both tokens present but never as the phrase
|
||||
assert scattered == 35 # tokens split across title and headline never combine
|
||||
|
||||
|
||||
def test_title_containment_scores_like_an_exact_title():
|
||||
# Live case: job "Generative Engineer", pool titled "Generative AI
|
||||
# Engineer" — the exact phrase never occurs, so every genuine match fell
|
||||
# to the scattered 35 tier and the whole pool compressed into the 40s.
|
||||
job = {"title": "Generative Engineer", "requirements": [], "optional_skills": []}
|
||||
interleaved = plugins.relevance_score(job, {"current_title": "Generative AI Engineer"})
|
||||
senior = plugins.relevance_score(job, {"current_title": "Senior Generative AI Engineer"})
|
||||
assert interleaved == 55
|
||||
assert senior == 55
|
||||
# Containment applies to the TITLE only: the same tokens scattered across
|
||||
# a keyword-stuffed headline still cap at the 35 tier.
|
||||
stuffed = plugins.relevance_score(
|
||||
job,
|
||||
{"current_title": "Developer", "headline": "Generative AI | Engineer | Python"},
|
||||
)
|
||||
assert stuffed == 35
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- detail extraction
|
||||
|
|
|
|||
Loading…
Reference in New Issue