Architectural Breakdown: I Asked AI to Improve My Resume. It Started Asking Me for Numbers Instead. A developer built a production-grade resume optimization framework that forces every resume bullet into a structured, numeric format before any language model processes it, arguing that prose-only prompts yield generic output. The system defines a ResumeBullet dataclass capturing action verb, metric type, before/after values, timeframe and context, then applies a deterministic four-dimension scoring function covering quantification strength, verb specificity, temporal precision and impact scope ahead of the LLM stage. Most people treat AI resume tools like a magic wand. They paste their draft, hit generate, and hope for better phrasing. But when you actually push a language model into doing meaningful optimization work, it quickly becomes clear that prose alone is insufficient. The model starts asking for quantitative signals because that is what it needs to make decisions that matter. This realization changed how I approach automated resume optimization entirely. What follows is not a beginner's tutorial. It is a production-grade framework for building a system that forces your resume through real metrics before any AI touches it. A standard prompt looks something like this: DON'T do this - pure text input leads to generic output response = client.chat.completions.create model="gpt-4o", messages= {"role": "user", "content": "Improve my resume bullet points."} The output will always be vague advice wrapped in corporate language. Phrases like "synergized cross-functional teams" or "spearheaded initiative" are exactly the kind of noise that makes resumes unreadable to both humans and applicant tracking systems. Without numbers anchoring each claim, the model has no signal to ground its improvements. The shift happens when you force every resume bullet into a structured numeric format before it ever reaches the language model: python from dataclasses import dataclass from typing import Optional @dataclass class ResumeBullet: action verb: str "Led", "Built", "Reduced" metric type: str "percentage", "absolute", "ratio" value before: Optional float baseline measurement value after: Optional float outcome measurement timeframe: Optional str "Q3 2024", "6 months" context: str the what and why @property def has numbers self - bool: A bullet without quantification should be flagged before any LLM processing begins return self.value before is not None and self.value after is not None @property def impact ratio self - Optional float : if not self.has numbers: return None return self.value after - self.value before / abs self.value before This structure forces a painful but necessary step: you must extract or estimate the real numbers behind every claim. That exercise alone improves your resume more than any AI paraphrase ever could. Once you have quantified bullets, you can build a deterministic scoring function that runs before the LLM stage: php import json def calculate bullet score bullet: ResumeBullet - dict: """ Produces a composite score from four independent dimensions. Higher scores indicate stronger, more credible accomplishments. """ scores = {} Dimension 1: Quantification strength if bullet.has numbers: scores "quantification" = min bullet.impact ratio 10, 100 else: scores "quantification" = 0 No numbers means this slot is empty Dimension 2: Action verb specificity strong verbs = { "built": 90, "architected": 95, "designed": 85, "reduced": 88, "optimized": 82, "launched": 78, "led": 70, "managed": 55, "helped": 30 } scores "verb strength" = strong verbs.get bullet.action verb.lower , 40 Dimension 3: Time-bound credibility score time = 50 if bullet.timeframe else 0 if bullet.timeframe and "quarter" in bullet.timeframe.lower : score time = 70 if bullet.timeframe and "month" in bullet.timeframe.lower : score time = 85 scores "temporal precision" = score time Dimension 4: Scale of impact scale scores = {"team": 50, "department": 70, "company": 90, "individual": 30} scores "scope score" = scale scores.get bullet.context.split 0 .lower , 40 composite = sum scores.values / len scores return {"scores": scores, "composite": round composite, 1 } This pipeline gives you something most resume tools never provide: a transparent audit trail showing exactly which bullet points are weak and why. Here is the architecture that actually works in practice: php def optimize resume stage one raw bullets: list dict - list ResumeBullet : """ STAGE 1: Structural enforcement. Converts freeform bullets into quantified objects. Rejects or flags any bullet missing hard numbers. """ structured = for raw in raw bullets: bullet = ResumeBullet action verb=raw.get "verb", "" , metric type=raw.get "type", "" , value before=raw.get "before" , value after=raw.get "after" , timeframe=raw.get "timeframe" , context=raw.get "context", "" if not bullet.has numbers: Flag for manual review instead of silently proceeding print f" FLAG Needs quantification: {bullet.context}" structured.append bullet return structured def optimize resume stage two bullets: list ResumeBullet , client, job description: str - list str : """ STAGE 2: LLM rewriting. The model now has concrete numbers to preserve and emphasize. It rephrases around the data instead of inventing fluff. """ prompt = f""" Optimize these quantified resume bullets for ATS readability. Job description: {job description} RULES: 1. NEVER remove or soften existing numbers 2. Replace weak verbs with specific action terms 3. Keep each bullet under 2 lines 4. Front-load the metric whenever possible Bullets: { f"{b.action verb} | {b.value before} → {b.value after} | {b.context}" for b in bullets } Return ONLY the optimized bullets as a JSON array. """ response = client.chat.completions.create model="claude-sonnet-4-20250514", messages= {"role": "user", "content": prompt} , temperature=0.3 Low temperature preserves factual accuracy return json.loads response.choices 0 .message.content When I ran this two-stage system against my own resume, the results were startling. Stage One flagged seven out of eleven bullets as missing hard numbers. Some of those gaps were honest oversights. Others were deliberate choices I had made because quantifying felt harder than writing. The model did not need to invent metrics. It needed the original data point to exist in the first place. Once those numbers were present, Stage Two produced dramatically different quality output. The AI stopped padding language and started sharpening it. Example transformation with actual numbers before = "Improved API response times significantly" after optimized = "Reduced p99 API latency from 840ms to 120ms by implementing Redis caching layer and query batch optimization" The second bullet is objectively better because it preserves the signal. AI amplifies signal. It cannot create it from silence. The lesson extends far beyond resume writing. Any time you ask an AI to improve something, the quality of your output is bounded by the quality of your structured input. Garbage in produces polished garbage. Numbers in produces sharper output. Start by auditing every claim on your resume against this simple question: can I attach a measurable number to this statement? If the answer is no, you have found the exact bullet point that is weakening your entire document. Fix it there first. Then let the AI handle the language. The system below captures the full pipeline end to end: python def full resume pipeline bullets: list dict , job desc: str, client - dict: """ Complete optimization pipeline from raw input to scored output. """ stage one = optimize resume stage one bullets scores = calculate bullet score b for b in stage one Filter out bullets scoring below 40 before sending to LLM qualified = b for b, s in zip stage one, scores if s "composite" = 40 low scoring = b for b, s in zip stage one, scores if s "composite" < 40 stage two = optimize resume stage two qualified, client, job desc return { "qualified bullets": stage two, "flagged for review": b.context for b in low scoring , "score summary": {s "composite" for s in scores} } Quantify first. Optimize second. The order matters more than most people realize. What is one bullet point on your resume right now that feels impactful but cannot survive being checked against a number?