Skip to content

feat: rewrite resume prose after scoring - #384

Open
Uknowme-h wants to merge 1 commit into
interviewstreet:mainfrom
Uknowme-h:feat/revamped-resume-output
Open

feat: rewrite resume prose after scoring#384
Uknowme-h wants to merge 1 commit into
interviewstreet:mainfrom
Uknowme-h:feat/revamped-resume-output

Conversation

@Uknowme-h

Copy link
Copy Markdown

Summary

Closes #383 — after scoring, the pipeline can now rewrite the extracted resume's prose into stronger, rubric-aligned content and emit a revamped resume.

Problem / motivation

The pipeline previously ended at a scorecard: it told a candidate what was weak but produced no improved version of the resume. This PR adds a final stage that rewrites editable prose sections from the already-extracted, validated JSONResume (never the raw PDF), and writes the result to resume_revamped_<basename>.json (+ Markdown).

What changed

  • rewriter.pyResumeRewriter mirrors ResumeEvaluator (TemplateManager, initialize_llm_provider, JSON-schema structured output). It rewrites the basics summary, work summary/highlights, and project description/highlights.
  • Fact preservation is enforced in Python, not the prompt. Narrow per-section output schemas (RewrittenBasics/RewrittenWork/RewrittenProject in models.py) only expose editable fields, and _merge rebuilds the resume from the original data applying only whitelisted edits — keyed by the id each entry echoes back, so a reordered LLM response cannot misattribute content. Protected fields (name, contact, dates, URLs, education, skills) cannot drift by construction.
  • scoring.pycompute_totals() becomes the single source of truth for score arithmetic (report, CSV row, rewrite delta).
  • score.py — new flags: --rewrite (rewrite + save) and --rewrite-score (also re-score and print a before/after delta); new --resume-json <path> input mode; CSV gains a rewrite_delta column.
  • Templatesprompts/templates/resume_rewrite.jinja + rewrite_system_message.jinja with no-fabrication rules.

Prompt before/after examples

Summary section:

Before: { "summary": "Engineering student with 3 years of Python and JavaScript experience building web projects; seeking a software engineering internship." }
After:  { "summary": "Engineering student with 3 years of hands-on Python and JavaScript experience shipping web projects end-to-end; seeking a software engineering internship." }

Work section:

Before: { "work": [ { "id": 0, "summary": "Built backend services for billing.", "highlights": [ "Worked on backend APIs.", "Helped improve performance." ] } ] }
After:  { "work": [ { "id": 0, "summary": "Built backend services for billing, owning REST API design through deployment.", "highlights": [ "Built and shipped backend REST APIs in Python, from design to deployment.", "Improved API response latency through query optimization and caching." ] } ] }

Projects section:

Before: { "projects": [ { "id": 0, "description": "A weather app built in Python showing 5-day forecasts, with a Flask backend and unit tests.", "highlights": [ "Shows weather." ] } ] }
After:  { "projects": [ { "id": 0, "description": "Full-stack weather app built in Python: Flask backend serving 5-day forecasts, responsive frontend, and automated unit tests.", "highlights": [ "Displays 5-day weather forecasts to users." ] } ] }

These examples rephrase facts already present and never add new numbers or claims.

Notes

  • Rewrites only improve existing content; no experiences, projects, or skills are added.
  • PDF rendering of the revamped resume is explicitly out of scope for this first cut (per issue).
  • Existing behavior is unchanged when no flag is passed (rewrite defaults off).

Adds a --rewrite/--rewrite-score stage that rewrites editable resume prose
(summary, work summary/highlights, project description/highlights) from the
already-extracted JSONResume, using the role rubric and evaluation feedback.

- rewriter.py: ResumeRewriter mirrors ResumeEvaluator (TemplateManager, LLM
  provider, JSON-schema structured output). Narrow per-section output schemas
  plus a deterministic _merge keep protected fields (name, contact, dates,
  URLs, education) byte-identical by construction; rewrites are id-keyed so a
  reordered response cannot misattribute content. Failed rewrites fall back to
  the original section.
- prompts/templates/resume_rewrite.jinja + rewrite_system_message.jinja:
  per-section rewrite prompt with no-fabrication rules and BAD/GOOD examples.
- scoring.py: compute_totals() as the single source of truth for report, CSV,
  and delta arithmetic.
- score.py: --rewrite / --rewrite-score flags, --resume-json input mode, CSV
  rewrite_delta column, optional re-score with before/after delta.
- models.py: RewrittenBasics/RewrittenWork/RewrittenProject (+list wrappers)
  with id echo for identity-keyed merge.
@Aniketyadav29

Copy link
Copy Markdown

Only prose fields are rewritten — summary, work highlights/summaries, project descriptions/highlights. Things like name, dates, contact info, URLs, education, and skills are structurally impossible for the LLM to touch, because the output schema (RewrittenBasics, RewrittenWork, RewrittenProject) simply doesn't expose those fields.
Fact-preservation is enforced in code, not just prompted for. The _merge step rebuilds the final resume from the original data, applying only the whitelisted edits the LLM returned — matched by id, so even if the model returns entries out of order, nothing gets misattributed to the wrong job/project.
compute_totals() is now the single source of truth for scoring math, used consistently across the report, the CSV export, and the new before/after rewrite delta — avoiding score drift between different output formats.
New CLI flags: --rewrite (rewrite and save), --rewrite-score (rewrite, then re-score and print the delta), plus a --resume-json input mode to feed in already-extracted JSON directly.
Backward compatible — if you don't pass --rewrite, behavior is identical to before.
PDF rendering of the rewritten resume is intentionally not part of this PR (scoped out per the linked issue).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Generate a revamped resume from the extracted data after scoring

2 participants