You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The pipeline currently ends at a scorecard: per-category scores, evidence, bonus points, deductions, key strengths, and areas_for_improvement. It tells a candidate what is weak but never produces an actionable output — there is no way to get a concrete, improved version of their resume out of the tool.
As it stands a candidate must manually translate "Open Source: 8/35 — personal repos don't count" into better bullet points themselves. This request adds a final pipeline stage that generates a revamped resume (same structure and section format as the original) by rewriting weak sections into stronger, rubric-aligned content.
Expected behavior
After the evaluation results are printed, a new CLI flag (e.g. --rewrite) runs a rewrite stage that:
Takes the already-extracted, validated JSONResume data (never the raw PDF text) plus the role rubric and the evaluation output as input.
Rewrites each editable section (basics summary, work highlights, project description/highlights, skills keyword ordering) to better match what the role's rubric rewards — quantified achievements, technical skill visibility, surfaced links, achievement-over-duties language.
Never changes factual data: name, contact info, dates, company/institution names, URLs, education, and certificates are preserved exactly.
Emits a revamped JSONResume (same JSON Resume schema, validated by the existing JSONResume model), written to resume_revamped_<basename>.json, plus an optional Markdown render.
Optionally re-scores the revamped resume and prints a before/after delta so the improvement is measurable.
Proposed solution
Mirror the existing per-section extraction architecture rather than inventing a new one:
New module rewriter.py with a ResumeRewriter class that follows the exact pattern of ResumeEvaluator (evaluator.py): uses TemplateManager, initialize_llm_provider, and structured output via format=model.model_json_schema().
New templatesprompts/templates/resume_rewrite.jinja (and a rewrite system message), consistent with the existing per-section Jinja templates in prompts/templates/.
Section-by-section rewrite calls, one per editable section, each receiving (section data, role rubric from roles/<role>/role.json, and the evaluation's areas_for_improvement / deductions). Small prompts reduce hallucination and token cost — same reasoning that already drives per-section extraction in pdf.py.
Protected vs editable fields enforced in Python after the LLM call: a deterministic post-processor restores any drift on immutable fields (name, dates, URLs, etc.). The LLM only writes prose; Python enforces facts.
Grounding: rewrites are driven by the structured JSONResume and the role's criteria.jinja rubric. No metrics are fabricated — quantifiable results are only retained/emphasized when present in the source (e.g. GitHub stars, project counts); otherwise bullets stay honest.
Determinism controls: low temperature (0.1–0.3) for rewrite calls, JSON-schema structured output.
CLI wiring: --rewrite flag in score.py, default off so existing behavior is unchanged.
Why this approach (vs. alternatives)
Rewrite from raw PDF text in one giant LLM call. Rejected: high hallucination risk, no schema guarantee, and it re-does work the pipeline already did. This repo already extracted clean, validated JSON — reusing it grounds the rewrite and prevents the model from inventing facts.
Ask the LLM to both rewrite and fact-check itself. Rejected as the primary mechanism: self-verification is weak for this; a deterministic Python guard on protected fields is stronger and free. (An optional LLM-as-judge pass could be a follow-up.)
Design informed by ResumeFlow (arXiv 2402.06221), an LLM pipeline that extracts structured resume JSON, rewrites section-by-section, and preserves personal details untouched.
Testing per CONTRIBUTING.md: smoke test with a cached resume JSON asserting (a) JSONResume validates, (b) all protected fields are byte-identical to the source; plus real runs under Ollama (default local model) and Gemini with before/after score comparison.
Problem / Motivation
The pipeline currently ends at a scorecard: per-category scores, evidence, bonus points, deductions, key strengths, and
areas_for_improvement. It tells a candidate what is weak but never produces an actionable output — there is no way to get a concrete, improved version of their resume out of the tool.As it stands a candidate must manually translate "Open Source: 8/35 — personal repos don't count" into better bullet points themselves. This request adds a final pipeline stage that generates a revamped resume (same structure and section format as the original) by rewriting weak sections into stronger, rubric-aligned content.
Expected behavior
After the evaluation results are printed, a new CLI flag (e.g.
--rewrite) runs a rewrite stage that:JSONResumedata (never the raw PDF text) plus the role rubric and the evaluation output as input.summary, workhighlights, projectdescription/highlights, skills keyword ordering) to better match what the role's rubric rewards — quantified achievements, technical skill visibility, surfaced links, achievement-over-duties language.JSONResume(same JSON Resume schema, validated by the existingJSONResumemodel), written toresume_revamped_<basename>.json, plus an optional Markdown render.Proposed solution
Mirror the existing per-section extraction architecture rather than inventing a new one:
rewriter.pywith aResumeRewriterclass that follows the exact pattern ofResumeEvaluator(evaluator.py): usesTemplateManager,initialize_llm_provider, and structured output viaformat=model.model_json_schema().prompts/templates/resume_rewrite.jinja(and a rewrite system message), consistent with the existing per-section Jinja templates inprompts/templates/.roles/<role>/role.json, and the evaluation'sareas_for_improvement/ deductions). Small prompts reduce hallucination and token cost — same reasoning that already drives per-section extraction inpdf.py.JSONResumeand the role'scriteria.jinjarubric. No metrics are fabricated — quantifiable results are only retained/emphasized when present in the source (e.g. GitHub stars, project counts); otherwise bullets stay honest.--rewriteflag inscore.py, default off so existing behavior is unchanged.Why this approach (vs. alternatives)
Scope / non-goals for the first cut
Additional context
JSONResumevalidates, (b) all protected fields are byte-identical to the source; plus real runs under Ollama (default local model) and Gemini with before/after score comparison.