feat: Add Resume Parser to Personalize Ollama Cold Email Generation#86
Open
DivyanshiVats13 wants to merge 3 commits into
Open
feat: Add Resume Parser to Personalize Ollama Cold Email Generation#86DivyanshiVats13 wants to merge 3 commits into
DivyanshiVats13 wants to merge 3 commits into
Conversation
- Add resume_parser.py to extract skills, experience and role from PDF/text resumes - Update ollama_client.py to accept optional candidate context for personalized prompts - Update generator.py to pass candidate context to Ollama - Update main.py with /resume endpoint and optional resume fields in /generate - Add test_resume_parser.py with 9 unit tests all passing - Add RESUME_PARSER_EXAMPLES.md with before/after email examples - Update requirements.txt with pdfplumber and python-multipart - Update README.md with new files and mark roadmap item as complete
|
@DivyanshiVats13 is attempting to deploy a commit to the Vaibhav Sharma's projects Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements the resume parsing module mentioned in the project roadmap. The current email pipeline generates observation sentences about the company's product but has no knowledge of who is actually applying. Two different candidates applying to the same job get the exact same email.
This PR fixes that by adding an optional resume upload flow that extracts the candidate's skills, experience, and role — then passes that context to the Ollama prompt so the generated sentence connects the candidate's background to the company's product.
Problem (from the codebase)
Looking at the existing ollama_client.py:
generate_observation(product_description)
The function only takes product_description as input. There is no candidate information passed to the LLM at all. The system prompt tells Ollama to write about the company — but nothing about the person applying.
Result:
Solution
Added a lightweight, regex-based resume parser that:
background — generating a personalized observation sentence
The existing /generate flow is completely unchanged when no resume
is provided — full backward compatibility maintained.
Files Changed
New Files
email-generator-service/resume_parser.py
Lightweight regex-based parser. No heavy NLP dependencies.
Extracts skills from a known list of 50+ tech keywords,
experience using multiple regex patterns including casual phrasing,
and job title using common engineering title patterns.
email-generator-service/test_resume_parser.py
9 unit tests covering skill extraction, experience detection,
role detection, edge cases (empty resume, minimal resume),
and prompt snippet generation. All 9 passing.
email-generator-service/RESUME_PARSER_EXAMPLES.md
Detailed before/after examples showing exactly how the
Ollama-generated sentence changes when candidate context
is provided.
Modified Files
email-generator-service/ollama_client.py
Updated generate_observation() to accept optional
candidate_context parameter. When provided, uses an enriched
system prompt that connects candidate background to company
product. When not provided, behavior is identical to before.
email-generator-service/generator.py
Updated generate_email() to accept optional candidate_context
parameter and pass it through to ollama_client.
email-generator-service/main.py
Added POST /resume endpoint for resume upload and parsing.
Added optional candidate_skills, candidate_role,
candidate_experience fields to GenerateRequest model.
email-generator-service/requirements.txt
Added pdfplumber>=0.11.0 and python-multipart>=0.0.9
README.md
Updated project structure, marked roadmap item as complete,
added pdfplumber to tech stack table.
Before / After
Before (without resume)
Ollama prompt: "In one sentence, write something specific about
this company's product: {product_description}"
Generated: "Your distributed caching layer's sub-millisecond
latency is genuinely impressive."
Only about the company. Nothing about the candidate.
After (with resume)
Ollama prompt: "Candidate background: Role: Senior Backend Engineer
| Experience: 5+ years | Skills: python, fastapi, docker.
In one sentence, write something specific about how this candidate's
background connects to this company's product: {product_description}"
Generated: "As a Senior Backend Engineer with 5 years building
FastAPI microservices, your distributed caching approach is exactly
the infrastructure challenge I have been solving in production."
Connects candidate directly to the company's product.
Test Results
pytest email-generator-service/test_resume_parser.py -v
test_skills_extracted_correctly PASSED
test_experience_extracted_correctly PASSED
test_role_extracted_correctly PASSED
test_minimal_resume_still_works PASSED
test_empty_resume_returns_empty_context PASSED
test_no_experience_returns_none PASSED
test_prompt_snippet_not_empty PASSED
test_prompt_snippet_empty_for_empty PASSED
test_candidate_context_is_empty_check PASSED
9 passed in 0.13s
Implementation Notes
Following the maintainer's guidance:
Closes #69