How Posting Keywords Are Matched Against Extracted PDF Text with Synonym Handling
The AI job search workflow validates CV coverage by extracting PDF text with pdftotext, then matching posting keywords against the content in three states—covered, synonym-only, or missing—using a static synonym map to handle industry term variations while respecting the posting's original language.
The MadsLorentzen/ai-job-search repository automates job application workflows by verifying that generated CVs contain required posting keywords. This verification process extracts text from PDF resumes and performs intelligent matching against job requirements, including explicit handling of technical synonyms and language-specific considerations.
PDF Text Extraction Pipeline
The matching process begins with extracting clean text from the generated CV PDF. In tools/verify_pdf.py, the system runs the pdftotext command with the -layout flag to preserve whitespace and formatting during extraction.
from tools.verify_pdf import run_tool
pdf_path = "cv/main_company.tex.pdf"
pdf_text = run_tool(["pdftotext", "-layout", pdf_path, "-"])
The -layout flag ensures that the extracted text maintains the original document structure, enabling reliable string searching against the posting's keyword list.
Three-Tier Keyword Matching Logic
Once the PDF text is extracted, the system compares it against the posting's keyword list through a hierarchical matching process defined in the knowledge-base files. Each keyword is evaluated against three possible match states.
Exact Match Detection (Covered)
The primary validation performs a case-insensitive string search for the exact keyword as it appears in the job posting. If keyword.lower() exists in pdf_text.lower(), the system marks the term as covered. According to the CV-template guidelines in .claude/skills/job-application-assistant/05-cv-templates.md, exact matches are preferred because "ATS matching is often literal."
Synonym-Only Fallback
When the exact keyword is not found, the system consults a static synonym map stored in the skill-definition files under .claude/skills/. This dictionary maps common industry terms to their accepted variants—for example, "machine learning" maps to ["ml", "machine‑learning"], and "software engineer" maps to ["developer", "programmer"].
If a synonym is detected in the PDF text while the exact term is absent, the system marks the keyword as synonym-only. This status indicates that the concept is present but expressed using different terminology.
Language-Aware Validation
The matching logic respects the language of the posting as documented in CLAUDE.md (lines 135-138) and .claude/commands/apply.md (lines 244-251). When validating a Danish posting against an English CV, the system searches for Danish keywords in the extracted text. If the concept is covered only in English, it is marked as synonym-only with a note indicating the language difference, ensuring accurate coverage reporting across multilingual applications.
Implementation Code and File Structure
The following Python implementation demonstrates the complete matching routine used in the verification workflow:
# Example of a simple keyword‑matching routine with synonym handling
keyword_map = {
"machine learning": ["ml", "machine‑learning"],
"software engineer": ["developer", "programmer"],
# … add more pairs as needed …
}
def match_keyword(keyword, text):
# Exact match (case‑insensitive)
if keyword.lower() in text.lower():
return "covered"
# Synonym‑only match
for syn in keyword_map.get(keyword, []):
if syn.lower() in text.lower():
return "synonym‑only"
return "missing"
# Iterate over posting keywords
posting_keywords = ["Machine Learning", "Software Engineer", "Docker"]
results = {}
for kw in posting_keywords:
results[kw] = match_keyword(kw, pdf_text)
print(results)
# {'Machine Learning': 'covered', 'Software Engineer': 'synonym‑only', 'Docker': 'missing'}
Key Files in the Repository
tools/verify_pdf.py– Extracts PDF text usingpdftotext -layoutand provides base verification utilities.CLAUDE.md– Documents the verification checklist and the synonym-only policy for keyword coverage (lines 135-138)..claude/skills/job-application-assistant/05-cv-templates.md– Details the keyword-matching process and the preference for exact terms over synonyms..claude/commands/apply.md– Provides the concrete reporting format for keyword coverage, including how to handle language differences (lines 244-251).
Summary
- PDF extraction relies on
pdftotext -layoutintools/verify_pdf.pyto generate searchable plain text from CV documents. - Three match states classify keywords as covered (exact), synonym-only (mapped term), or missing (not found).
- Synonym handling uses a static dictionary in
.claude/skills/to recognize industry term variations like "ML" for "machine learning." - Language awareness ensures Danish posting keywords are matched against Danish text, with English equivalents marked as synonym-only when applicable.
Frequently Asked Questions
How does the system extract text from PDF files?
The system uses the pdftotext command-line utility with the -layout flag via tools/verify_pdf.py. This preserves the document's whitespace and formatting, producing reliable plain text that supports accurate case-insensitive keyword searching without losing structural context.
What happens when a keyword is found only as a synonym?
When the exact keyword is absent but a mapped synonym is present in the PDF text, the system marks the entry as synonym-only. This indicates that the underlying concept is covered in the CV, but the terminology differs from the posting's exact requirement—a distinction that is explicitly noted in the verification report to guide potential CV refinements.
How does the matching logic handle multilingual job postings?
The system matches keywords in the posting's original language. For Danish postings, it searches for Danish terms in the extracted text. If the CV contains only the English equivalent of a Danish keyword, the system marks it as synonym-only and notes the language difference, as specified in .claude/commands/apply.md (lines 244-251).
Where is the synonym mapping defined?
The synonym dictionary is stored in static skill-definition files under the .claude/skills/ directory. This mapping contains common industry equivalences (such as "machine learning" ↔ "ML") and is consulted during the comparison phase only after exact keyword matching fails.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →