"""Test ATS recovery when the LLM produces a weak/sparse v2 output (mimics real production).""" import os, sys, io, pdfplumber sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') def read_pdf(p): text = '' with pdfplumber.open(p) as pdf: for page in pdf.pages: t = page.extract_text() if t: text += t + '\n' return text orig = read_pdf(r'C:\Users\Nxtwave\Desktop\resume\Saiteja_Tirunagari_Resume A 26 - Copy.pdf') from src.resume_customizer import ResumeCustomizer, _read_docx_text from src.ats_scorer import score_resume from src.resume_parser import ResumeParser rc = ResumeCustomizer.__new__(ResumeCustomizer) rc.resume_text = orig rc.output_dir = 'data/output/resumes/_weak_llm_test' os.makedirs(rc.output_dir, exist_ok=True) rc.fast_model_cfg = None parser = ResumeParser.__new__(ResumeParser) parser.pdf_path = '' contact = parser.get_contact_info(orig) # Simulate a WEAK LLM that follows v1 schema (older model) — most production runs # look like this: just summary + a flat experience_bullets dict, no rewritten_bullets def weak_llm_v1(jd_label, summary_text): return { "professional_summary": summary_text, # v1 schema — backwards compat path "core_competencies": ["Product Strategy", "Roadmap Planning", "A/B Testing"], "experience_bullets": { "internal_product_manager": [ "Led NIAT Application Portal revamp", "Built AI chatbot funnel", "Drove payment conversion optimization", ], }, "key_achievements": ["141,269 verified leads", "+35.87 pp payment lift"], } jds = [ ("Airtel PM", "tests/fixtures/jds/airtel_pm.txt"), ("Sumo Logic PM", "tests/fixtures/jds/sumo_logic_pm.txt"), ("EdgeVerve PM", "tests/fixtures/jds/edgeverve_pm.txt"), ("Aditya Birla APM", "tests/fixtures/jds/aditya_birla_apm.txt"), ] print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') print(f'{"JD":<22} {"Before inj":<14} {"After inj":<14} {"Missing":<6}') print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') for label, jd_path in jds: with open(jd_path, encoding='utf-8') as f: jd = f.read() # Weak LLM with a minimal summary weak_summary = ( f"Product Manager with 5+ years of experience driving 0-1 product " f"development in fast-paced startups." ) cust = weak_llm_v1(label, weak_summary) filepath = os.path.join(rc.output_dir, f'{label.replace(" ", "_")}.docx') job = {'title': 'PM', 'company': label, 'relevance_score': 7} rc._write_docx(filepath, job, cust, contact) # Score before injection r_before = score_resume(_read_docx_text(filepath), jd) # Apply injection rc._inject_missing_keywords(filepath, jd) # Score after injection r_after = score_resume(_read_docx_text(filepath), jd) print(f'{label:<22} {r_before["ats_score"]:>3}/100 ({r_before["jd_match_score"]}%kw) ' f'{r_after["ats_score"]:>3}/100 ({r_after["jd_match_score"]}%kw) ' f'{len(r_after["missing_kw"]):<6}') print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') print('\nNote: "Before inj" = weak v1-schema LLM result (typical production case)') print(' "After inj" = after the new aggressive keyword injection into summary')