Spaces:
Sleeping
Sleeping
File size: 5,557 Bytes
b0e9d71 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | """
Verify the new systemic keyword extraction works on ALL 7 JDs (4 tuned + 3 new)
without per-JD noise tuning.
The 3 "new" JDs (Navi, zenda, generic_pm) have NEVER been used to tune the
noise filter. If they score well, the systemic approach works.
"""
import os, sys, io, shutil
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
src_pdf = r'C:\Users\Nxtwave\Desktop\resume\Saiteja_Tirunagari_Resume A 26 - Copy.pdf'
dst_pdf = 'data/resume/resume.pdf'
os.makedirs(os.path.dirname(dst_pdf), exist_ok=True)
if not os.path.exists(dst_pdf):
shutil.copyfile(src_pdf, dst_pdf)
# Use the same backfill / pitch / weave flow as production
from src.resume_customizer import ResumeCustomizer, _read_docx_text
from src.llm_client import LLMClient
from src.ats_scorer import score_resume, extract_jd_keywords
def make_weak_response(resume_dict, job_title, company):
"""Worst-case production LLM: 2 roles, no pitch, 3 bullets each."""
return {
"name": resume_dict["name"],
"contact": resume_dict["contact"],
"summary": (
"Product Manager with 5+ years of experience driving product development "
"in fast-paced startups. Built funnel optimization and AI-powered features "
"that scaled to 140,000+ users with measurable business impact."
),
"roles": [
{
"title": resume_dict["roles"][0]["title"],
"company": resume_dict["roles"][0]["company"],
"location": resume_dict["roles"][0]["location"],
"dates": resume_dict["roles"][0]["dates"],
"bullets": [
"Led NIAT Application Portal revamp scaling to 141,269 verified leads",
"Drove payment conversion lift of +35.87 percentage points",
"Built AI chatbot generating 6,776 leads",
],
},
{
"title": resume_dict["roles"][1]["title"],
"company": resume_dict["roles"][1]["company"],
"location": resume_dict["roles"][1]["location"],
"dates": resume_dict["roles"][1]["dates"],
"bullets": [
"Managed 20 customer-success specialists covering 40,000 customers",
"Maintained refund rate below 5% and satisfaction above 95%",
],
},
],
"achievements": [
"Scaled to 141,269 verified leads",
"Lifted payment conversion +35.87 pp",
],
"education": resume_dict["education"],
}
_original_v4 = LLMClient.tailor_resume_v4
def _mocked_v4(self, cfg, resume_dict, jd_text, job_title, company, assessment):
return make_weak_response(resume_dict, job_title, company)
LLMClient.tailor_resume_v4 = _mocked_v4
rc = ResumeCustomizer.__new__(ResumeCustomizer)
rc.llm = LLMClient.__new__(LLMClient)
rc.resume_text = ''
rc.output_dir = 'data/output/resumes/_systemic_test'
os.makedirs(rc.output_dir, exist_ok=True)
rc.fast_model_cfg = {"model": "fake", "api_key": "fake", "base_url": "https://fake"}
rc._pending_summary_inject = []
print('━' * 86)
print(f'{"JD (tuned)":<32} {"ATS":>5} {"JD-match":>10} {"Words":>6} {"JD-kw":>6}')
print('━' * 86)
# Group 1: JDs I've tuned the noise filter for
tuned = [
('airtel_pm', 'Product Manager', 'Airtel'),
('sumo_logic_pm', 'Product Manager', 'Sumo Logic'),
('edgeverve_pm', 'Product Manager', 'EdgeVerve'),
('aditya_birla_apm', 'Associate Product Manager', 'Aditya Birla Capital'),
]
# Group 2: NEW JDs — never used to tune anything
new_jds = [
('navi_pm', 'Product Manager', 'Navi'),
('zenda_apm', 'Associate Product Manager', 'zenda'),
('generic_pm_3_7yrs', 'Product Manager', 'Generic'),
]
for jd_file, role, company in tuned:
with open(f'tests/fixtures/jds/{jd_file}.txt', encoding='utf-8') as f:
jd = f.read()
job = {"title": role, "company": company, "description": jd, "_raw_assessment": {}}
filepath = os.path.join(rc.output_dir, f'{company.replace(" ", "_")}.docx')
result = rc._generate_resume_v4(job, cfg=rc.fast_model_cfg, filepath=filepath)
if not result:
print(f'{(company):<32} FAILED')
continue
text = _read_docx_text(result)
r = score_resume(text, jd)
print(f'{company:<32} {r["ats_score"]:>4} {r["matched_count"]}/{r["total_jd_kw"]:<3} {r["word_count"]:>5} {r["total_jd_kw"]:>4}')
print()
print(f'{"JD (NEW — never seen)":<32} {"ATS":>5} {"JD-match":>10} {"Words":>6} {"JD-kw":>6}')
print('-' * 86)
for jd_file, role, company in new_jds:
with open(f'tests/fixtures/jds/{jd_file}.txt', encoding='utf-8') as f:
jd = f.read()
job = {"title": role, "company": company, "description": jd, "_raw_assessment": {}}
filepath = os.path.join(rc.output_dir, f'{company.replace(" ", "_")}_{jd_file}.docx')
result = rc._generate_resume_v4(job, cfg=rc.fast_model_cfg, filepath=filepath)
if not result:
print(f'{(company):<32} FAILED')
continue
text = _read_docx_text(result)
r = score_resume(text, jd)
print(f'{company:<32} {r["ats_score"]:>4} {r["matched_count"]}/{r["total_jd_kw"]:<3} {r["word_count"]:>5} {r["total_jd_kw"]:>4}')
print('━' * 86)
print('\nThe NEW JDs simulate production new-job behavior. If they score ~the')
print('same as the tuned JDs, the systemic extraction works without per-JD')
print('blocklist tuning.')
|