gapguide-api / apps /accounts /ner /lexical.py
arifRB's picture
Deploy GapGuide backend (Docker)
ffd36e0 verified
Raw
History Blame Contribute Delete
1.47 kB
"""Layer 0/floor: lexical catalog matching.
This wraps the existing pdfplumber-free matching logic from the MVP so the
dispatcher can treat it uniformly with the other layers. Unlike the four
ML layers, this one is always safe — it has no heavy deps and only touches
the DB's Skill catalog.
Kept separate from ``resume_parser`` so the dispatcher can invoke it as
a layer alongside the others rather than having a special-case code path.
"""
from __future__ import annotations
from . import NerLayer
class LexicalLayer(NerLayer):
name = "lexical"
def predict(self, text: str) -> dict[str, float]:
if not text.strip():
return {}
# Reuse the existing implementation so behaviour stays identical.
from apps.accounts.resume_parser import _candidate_matches
from apps.skills.models import Skill
skills = list(Skill.objects.all().only("id", "skill_name"))
hits = _candidate_matches(text, skills)
# _candidate_matches returns {skill_id: {confidence, proficiency, matched_span}}
# — the dispatcher works with {name: confidence}, so remap.
by_id = {s.id: s.skill_name for s in skills}
out: dict[str, float] = {}
for skill_id, data in hits.items():
name = by_id.get(skill_id)
if name:
out[name] = float(data["confidence"])
return out
def available(self) -> bool:
return True
layer = LexicalLayer()