Noo88ear's picture
πŸš€ Initial deployment of Multi-Agent Job Application Assistant
7498f2c
from __future__ import annotations
from typing import List, Tuple, Set
from .text import extract_keywords_from_text
def allowed_keywords_from_profile(skills: List[str], experiences: List) -> Set[str]:
allowed = set(s.lower() for s in skills)
for e in experiences:
for t in getattr(e, "technologies", []) or []:
allowed.add(str(t).lower())
for a in getattr(e, "achievements", []) or []:
for k in extract_keywords_from_text(a, top_k=5):
allowed.add(k.lower())
return allowed
def clamp_to_allowed_keywords(text: str, allowed: Set[str]) -> Tuple[str, List[str]]:
used = []
# Retain only keywords that are allowed
kws = extract_keywords_from_text(text, top_k=80)
for k in kws:
if k.lower() in allowed:
used.append(k)
return text, used
def detect_contradictions(resume_text: str, letter_text: str, allowed: Set[str]) -> List[str]:
# Simple heuristic: keywords in letter not in resume nor allowed -> potential contradiction
resume_k = set(k.lower() for k in extract_keywords_from_text(resume_text, top_k=100))
letter_k = set(k.lower() for k in extract_keywords_from_text(letter_text, top_k=100))
issues = []
for k in letter_k:
if k not in resume_k and k not in allowed:
issues.append(k)
return issues
def coverage_score(text: str, target_keywords: List[str]) -> float:
if not target_keywords:
return 1.0
lower = text.lower()
hits = sum(1 for k in target_keywords if k.lower() in lower)
return hits / max(1, len(target_keywords))
def conciseness_score(text: str, max_chars: int) -> float:
# 1.0 if within limit; decay if exceeded
if len(text) <= max_chars:
return 1.0
return max(0.0, 1.0 - (len(text) - max_chars) / (max_chars * 0.5))