""" Simulate a WEAK LLM v4 output (sparse bullets, missing recruiter pitch) and verify the new aggressive bullet weaving lifts each JD to 90%+. Models what production looks like when smaller LLMs don't follow the v4 prompt precisely — exactly the user's reported issue (70-80% on new jobs). """ 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) from src.resume_parser_v2 import parse_resume_pdf_cached from src.resume_renderer import render_resume_docx from src.resume_model import Resume, Role, Education from src.ats_scorer import score_resume, extract_jd_keywords, _kw_in_text from src.resume_customizer import ResumeCustomizer, _read_docx_text base = parse_resume_pdf_cached(dst_pdf) def make_weak_llm_output(role: str, company: str) -> Resume: """ Mimic a TYPICAL production LLM output: reasonable-length bullets, generic phrasing, missing recruiter pitch, no specific JD keyword weaving. This matches what the user observed (70-80% on new jobs). """ return Resume( name=base.name, contact=base.contact, summary=( f"Product Manager with 5+ years of experience driving product development in fast-paced " f"EdTech and AI startups. Built funnel optimization tools and AI-powered features that " f"scaled to 140,000+ users and contributed to 2x revenue growth. Deep expertise in " f"conversational AI, OCR automation, A/B testing, and cross-functional delivery. Combines " f"data-driven decision-making with user-centric design to ship measurable outcomes." ), roles=[ Role( title=base.roles[0].title, company=base.roles[0].company, location=base.roles[0].location, dates=base.roles[0].dates, bullets=[ "Led end-to-end revamp of the NIAT Application Portal — a unified digital funnel covering landing pages, OTP login, payment, slot booking, exam, and report flow integrated with CRM and payment systems", "Scaled to 141,269 OTP-verified leads with 97% personal-details completion and 95% exam-attendance rate across 23,983 attendees", "Drove payment conversion lift of +35.87 percentage points (27.37% to 63.24%) through coupon-based urgency logic and A/B experimentation", "Built AI chatbot generating 6,776 leads and 113 enrollments via stage-wise decision trees with CRM-integrated nudges", "Optimized landing-page funnel achieving 38.02% Visit-to-OTP conversion on highest-intent campaigns through experimentation framework", "Reduced lead leakage by 25% and increased sales-qualified leads by 18% through CRM automation and event tracking", ], ), Role( title=base.roles[1].title, company=base.roles[1].company, location=base.roles[1].location, dates=base.roles[1].dates, bullets=[ "Managed 20 customer-success specialists covering 40,000 customers; maintained refund rate below 5% and satisfaction above 95%", "Played 0-to-1 role in Xplore Experiment and Social Emotional Learning pilot projects alongside product and engineering teams", "Sustained 95%+ Monthly Recurring Revenue from existing EMI customers through proactive retention strategies", ], ), Role( title=base.roles[2].title, company=base.roles[2].company, location=base.roles[2].location, dates=base.roles[2].dates, bullets=[ "Increased user retention by 8% by redesigning the onboarding process using UX research and user-centric principles", "Conducted extensive A/B testing and UX research to identify pain points and refine features", "Mentored students through their academic journey using multi-channel communication and performance dashboards", ], ), Role( title=base.roles[3].title, company=base.roles[3].company, location=base.roles[3].location, dates=base.roles[3].dates, bullets=[ "Launched EdTech app portfolio of 275 apps with 3 million+ cumulative downloads", "Drove user acquisition through Google Ads, LinkedIn, and paid social channels", "Built performance-driven culture focused on conversion optimization and data-driven decision-making", ], ), ], achievements=[ "Scaled NIAT Application Portal to 141,269 OTP-verified leads with ₹1,120+ Cr annual pipeline", "Lifted payment conversion +35.87 percentage points via CRM-integrated experimentation", "Reduced OCR processing cost by 97.5% (₹4 to ₹0.10 per page) through automation", ], education=base.education, ) jd_focus = { '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'), } out_dir = 'data/output/resumes/_weave_test' os.makedirs(out_dir, exist_ok=True) rc = ResumeCustomizer.__new__(ResumeCustomizer) rc.resume_text = '' rc._pending_summary_inject = [] print('━' * 78) print(f'{"JD":<48} {"BeforeWeave":>11} {"AfterWeave":>10} {"FinalATS":>9}') print('━' * 78) for jd_file, (role, company) in jd_focus.items(): with open(f'tests/fixtures/jds/{jd_file}.txt', encoding='utf-8') as f: jd = f.read() tailored = make_weak_llm_output(role, company) # Score before weaving (just from the weak LLM bullets) docx_pre = os.path.join(out_dir, f'{company.replace(" ", "_")}_PRE.docx') render_resume_docx(tailored, docx_pre) r_pre = score_resume(_read_docx_text(docx_pre), jd) # Run aggressive bullet weaving jd_kw = extract_jd_keywords(jd) flat = tailored.to_flat_text().lower() missing = [k for k in jd_kw if not _kw_in_text(k, flat)] missing = [k for k in missing if len(k) >= 3 and not (len(k) >= 5 and k.endswith(("at", "iz", "ic")))] rc._weave_keywords_into_bullets(tailored, missing, jd) # Score after bullet weaving docx_mid = os.path.join(out_dir, f'{company.replace(" ", "_")}_WOVEN.docx') render_resume_docx(tailored, docx_mid) r_mid = score_resume(_read_docx_text(docx_mid), jd) # Apply summary injection for any leftover keywords rc._inject_missing_keywords(docx_mid, jd) r_final = score_resume(_read_docx_text(docx_mid), jd) print(f'{(role + " @ " + company):<48} {r_pre["ats_score"]:>10} {r_mid["ats_score"]:>9} {r_final["ats_score"]:>7}') print('━' * 78) print('Note: "BeforeWeave" = weak LLM v4 output simulating production case.') print(' "AfterWeave" = after aggressive bullet weaving.') print(' "FinalATS" = after summary injection for stragglers.')