Skip to content

Skills Analyzer

SkillsAnalyzer

SkillsAnalyzer(semantic_matcher=None)

Analyzer for matching skills between job requirements and resume.

Matches required and preferred skills from job descriptions against resume skills using multiple strategies: 1. Exact matching (normalized, case-insensitive) 2. Fuzzy string matching (ratio >= 85%) 3. Semantic similarity (if semantic_matcher provided, threshold >= 0.7)

Attributes:

Name Type Description
semantic_matcher

Optional semantic matcher for ML-powered similarity. If provided, enables semantic skills matching.

Example
# Basic analyzer
analyzer = SkillsAnalyzer()

# With semantic matching
from at_scorer.ml import SemanticMatcher, EmbeddingModel
model = EmbeddingModel()
matcher = SemanticMatcher(model)
analyzer = SkillsAnalyzer(semantic_matcher=matcher)

score, matched, missing, preferred = analyzer.analyze(
    resume_skills, required_skills, preferred_skills
)

Initialize the skills analyzer.

Parameters:

Name Type Description Default
semantic_matcher SemanticMatcher | None

Optional semantic matcher for ML-powered similarity.

None
Source code in at_scorer/analyzers/skills.py
def __init__(self, semantic_matcher: SemanticMatcher | None = None):
    """Initialize the skills analyzer.

    Args:
        semantic_matcher: Optional semantic matcher for ML-powered similarity.
    """
    self.semantic_matcher = semantic_matcher

Functions

analyze
analyze(resume_skills, required, preferred=None)

Analyze skills matching between resume and job requirements.

Calculates a score based on required skills (80% weight) and preferred skills (20% weight). Required skills are mandatory, while preferred skills provide bonus points.

Parameters:

Name Type Description Default
resume_skills Iterable[str]

Skills listed in the resume.

required
required Iterable[str]

Required skills from the job description.

required
preferred Iterable[str] | None

Preferred (nice-to-have) skills from the job description.

None

Returns:

Type Description
tuple[float, list[str], list[str], list[str]]

Tuple containing: - score: Float between 0.0 and 1.0 (weighted: 80% required, 20% preferred) - matched_skills: List of all matched skills (required + preferred) - missing_required: List of required skills not found - matched_preferred: List of preferred skills that were matched

Source code in at_scorer/analyzers/skills.py
def analyze(
    self,
    resume_skills: Iterable[str],
    required: Iterable[str],
    preferred: Iterable[str] | None = None,
) -> tuple[float, list[str], list[str], list[str]]:
    """Analyze skills matching between resume and job requirements.

    Calculates a score based on required skills (80% weight) and preferred
    skills (20% weight). Required skills are mandatory, while preferred
    skills provide bonus points.

    Args:
        resume_skills: Skills listed in the resume.
        required: Required skills from the job description.
        preferred: Preferred (nice-to-have) skills from the job description.

    Returns:
        Tuple containing:
            - score: Float between 0.0 and 1.0 (weighted: 80% required, 20% preferred)
            - matched_skills: List of all matched skills (required + preferred)
            - missing_required: List of required skills not found
            - matched_preferred: List of preferred skills that were matched
    """
    required_list = [normalize_text(s) for s in required if s]
    preferred_list = [normalize_text(s) for s in (preferred or []) if s]
    resume_list = deduplicate_preserve_order(normalize_text(s) for s in resume_skills if s)

    matched_required: list[str] = []
    missing_required: list[str] = []
    matched_preferred: list[str] = []

    for req in required_list:
        match = self._skill_present(req, resume_list)
        if match:
            matched_required.append(match)
        else:
            missing_required.append(req)

    for pref in preferred_list:
        match = self._skill_present(pref, resume_list)
        if match:
            matched_preferred.append(match)

    required_score = len(matched_required) / (len(required_list) or 1)
    preferred_score = (
        len(matched_preferred) / (len(preferred_list) or 1) if preferred_list else 0
    )
    score = 0.8 * required_score + 0.2 * preferred_score if preferred_list else required_score
    combined_matches = matched_required + matched_preferred
    return score, combined_matches, missing_required, matched_preferred