File size: 7,492 Bytes
8e3dfba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""
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.')