cv-matcher

workflowv1.0.0

Fully offline AI-powered CV / Job Description matching pipeline using Ollama for LLM inference.

Install

kdeps registry install cv-matcher

Then run locally:

kdeps exec cv-matcher

Configure LLM provider in ~/.kdeps/config.yaml (created automatically on first run).

README

CV Matcher Example — Offline Edition

AI-powered CV / Job Description matching pipeline built with kdeps. Runs entirely offline using Ollama for both LLM inference and text embeddings — no cloud API keys required.

For each CV + JD pair the workflow:

  1. Parses both documents (PDF, DOCX, JSON, TXT, or URL via scraper)
  2. Extracts structured data and skills with llama3.2 (local Ollama LLM)
  3. Indexes skill embeddings into a SQLite vector DB with nomic-embed-text (local Ollama embedding model, cached)
  4. Scores the match by skill category (software_dev, platform, cloud, data, ml_ai, general)
  5. If the overall score exceeds the threshold:
    • Generates a motivation letter and a tailored CV
    • Renders a full match-report PDF
    • Uploads the PDF to S3 (presigned URL) and/or Google Drive (optional)
    • Appends a row to an existing Google Sheet via a Python inline script (optional)
    • Emails the distribution list with an HTML summary and the PDF attachment (optional)
  6. Returns a structured JSON result via apiResponse

Also serves an interactive web UI at GET / — open it in your browser to submit CVs and JDs without writing any curl commands.


Prerequisites

Tool / ServiceRequired for
Ollama + llama3.2LLM extraction, scoring, letter generation
Ollama + nomic-embed-textOffline skill embeddings
wkhtmltopdfPDF generation (generate-report-pdf step)
SMTP serverEmail distribution (send-email step, optional)
Google Cloud service accountGoogle Sheets append (append-sheet step, optional)
S3 presigned URLS3 upload (upload-s3 step, optional)
Google OAuth2 tokenGDrive upload (upload-gdrive step, optional)

Install Ollama and pull models

# Install Ollama: https://ollama.com/download
ollama pull llama3.2
ollama pull nomic-embed-text

Install wkhtmltopdf

# macOS
brew install wkhtmltopdf

# Debian / Ubuntu
apt install wkhtmltopdf

Usage

Start the kdeps server:

kdeps run examples/cv-matcher/workflow.yaml

The server listens on port 16399.

Web UI (browser)

Open http://localhost:16399/ in your browser.

Fill in the CV and JD file paths, click Analyze Match, and the results panel renders inline — match score, category breakdown, matched skills table, missing skills, and PDF output paths.

API (curl)

curl -X POST http://localhost:16399/match \
  -H "Content-Type: application/json" \
  -d '{
    "cv_path": "/data/candidates/jane-smith.pdf",
    "jd_path": "/data/jobs/senior-backend-engineer.pdf"
  }'

Request body

{
  "cv_path": "/path/to/candidate.pdf",
  "cv_type": "pdf",
  "jd_path": "/path/to/job-description.pdf",
  "jd_type": "pdf",
  "distribution_list": ["hr@example.com", "hiring-manager@example.com"],
  "s3_presigned_url": "https://bucket.s3.amazonaws.com/upload?...",
  "gdrive_token": "ya29...",
  "gdrive_folder_id": "1AbCdEf...",
  "sheets_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
  "sheets_tab": "Matches"
}
FieldTypeRequiredDescription
cv_pathstringyesLocal file path or URL to the CV
cv_typestringnopdf, docx, json, txt, url (default: pdf)
jd_pathstringyesLocal file path or URL to the job description
jd_typestringnoSame options as cv_type
distribution_list[]stringnoEmail recipients for the match summary
s3_presigned_urlstringnoS3 PUT presigned URL for the match-report PDF
gdrive_tokenstringnoGoogle OAuth2 bearer token for Drive upload
gdrive_folder_idstringnoGoogle Drive folder ID to upload into
sheets_idstringnoGoogle Spreadsheet ID to append a match row
sheets_tabstringnoSheet/tab name (default: Matches)

Response

{
  "candidate": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone": "+31612345678"
  },
  "position": {
    "title": "Senior Backend Engineer",
    "company": "TechCorp",
    "contact_name": "Jane Recruiter",
    "contact_email": "jane@techcorp.com"
  },
  "match": {
    "overall_score": 0.87,
    "is_match": true,
    "category_scores": {
      "software_dev": 0.92,
      "platform": 0.85,
      "cloud": 0.80,
      "data": 0.75,
      "ml_ai": 0.0,
      "security": 0.0,
      "general": 0.60
    },
    "matched_skills": [
      {"jd_skill": "Python", "cv_skill": "Python", "similarity": 1.0, "cv_duration_months": 38}
    ],
    "missing_skills": ["Kubernetes"],
    "summary": "Strong match — 8 of 10 required skills present, 3+ years Python."
  },
  "outputs": {
    "report_pdf": "/tmp/kdeps-cv-matcher/report_Jane_Smith_TechCorp.pdf",
    "tailored_cv": "/tmp/kdeps-cv-matcher/cv_Jane_Smith_TechCorp.pdf",
    "file_link": "",
    "sheet_updated": false,
    "email_sent": false
  }
}

Environment Variables

VariableDescription
SMTP_HOSTSMTP server hostname (default: smtp.gmail.com)
SMTP_USERSMTP authentication username
SMTP_PASSSMTP authentication password
SMTP_FROMSender address (defaults to SMTP_USER)
GOOGLE_SA_JSONPath to Google Cloud service-account JSON key file
GOOGLE_SPREADSHEET_IDFallback spreadsheet ID if not in request body

Pipeline Steps

StepResource typeDescription
scrape-cvscraperDownload / read the CV file
scrape-jdscraperDownload / read the JD file
extract-cvchat (ollama/llama3.2)Extract name, work history, skills from CV
extract-jdchat (ollama/llama3.2)Extract required / preferred / nice-to-have skills from JD
embed-cv-skillsembedding (ollama/nomic-embed-text)Index CV skills into SQLite vector DB
embed-jd-skillsembedding (ollama/nomic-embed-text)Index JD skills into SQLite vector DB
compute-matchchat (ollama/llama3.2)Score the CV against the JD by skill category
generate-letterchat (ollama/llama3.2)Write a personalised motivation letter (skipped when no match)
generate-tailored-cvchat (ollama/llama3.2)Produce a CV tailored to the job description (skipped when no match)
generate-report-pdfpdfRender the full match report as a PDF
upload-s3httpClientPUT the PDF to an S3 presigned URL (optional)
upload-gdrivehttpClientPOST the PDF to Google Drive REST API (optional)
append-sheetpythonAppend a result row to a Google Sheet (optional)
send-emailemailEmail the distribution list with HTML summary + PDF (optional)
web-uiapiResponseServes HTML web UI (GET /) or JSON result (POST /match)

Skill categories

CategoryExamplesWeight
software_devPython, Go, Java, C++, TypeScript1.0
platformDocker, Kubernetes, Terraform, Ansible0.9
cloudAWS, GCP, Azure, Cloudflare0.9
dataSQL, Spark, Kafka, dbt, Airflow0.85
ml_aiPyTorch, TensorFlow, scikit-learn, LLMs0.85
securityOWASP, penetration testing, SIEM0.8
generalJira, Confluence, MS Office, Slack0.5

Match threshold: overall_score >= 0.65.


Differences from cv-matcher-online

cv-matcher (this example)cv-matcher-online
LLMOllama / llama3.2 (local)Anthropic / claude-haiku
EmbeddingsOllama / nomic-embed-text (local)OpenAI / text-embedding-3-small
API keys neededNoneANTHROPIC_API_KEY, OPENAI_API_KEY
Web UIYes — GET /No
Internet requiredNo (AI only)Yes

Versions

VersionPublishedStatus
1.0.04/11/2026active

Details

Author
kdeps
License
Apache-2.0
Latest Version
1.0.0
Published
4/11/2026

Tags

cvaimatching