🇷🇺 Русская версия · this is the main README
A Telegram bot that screens a batch of resumes against a job description using an LLM, and hands the recruiter back a ranked, color-coded Excel report — no manual reading of every CV.
A hiring manager sends the job requirements plus a batch of candidate resumes (PDF/DOCX) to the bot. The bot extracts the text, scores every candidate against the requirements with an LLM, and replies with a single spreadsheet: candidates ranked by score, color-coded <50 / 50–80 / 80–100, each with a short rationale.
![]() |
![]() |
![]() |
![]() |
- Telegram-native workflow — no separate web UI; the whole flow (submit job requirements → upload resumes → run → get report) happens in a chat.
- PDF & DOCX support — text extraction handled by dedicated libraries (
pdfplumber,python-docx), not the LLM — work that can be solved algorithmically is solved algorithmically. - Structured LLM scoring — each candidate gets a 0–100 score plus a short rationale, returned as structured JSON.
- Ensemble scoring for reliability — every candidate is scored by 3 independent LLM passes; the final score is their average, and the final rationale is synthesized from all three in a 4th call. This exists specifically to counter LLM answer non-determinism observed during field testing.
- Fail-fast per candidate — if any pass fails validation, that candidate is reported as unscored rather than silently guessing; the rest of the batch keeps processing.
- Privacy by design — nothing is persisted between runs. Resumes, extracted text, and scores live only in a temp directory for the duration of one run and are deleted immediately after the report is delivered. No database, no history, no personal data storage.
- Whitelist access control — only Telegram user IDs on an explicit allowlist can use the bot.
- Resilient to network hiccups — a failed file download or a network blip on bot startup is handled gracefully instead of crashing the whole run.
- Step navigation —
/backand/restartlet the user correct a mistake mid-flow without starting over from scratch.
Job requirements + resume batch (Telegram)
│
▼
intake — whitelist check, batch size / file size / format guards
│
▼
extraction — PDF/DOCX → plain text
│
▼
scoring — LLM scores candidate vs. requirements (×3 passes + synthesis)
│
▼
report — ranked, color-coded Excel workbook
│
▼
Delivered back to the requester in the same chat
Candidates that fail any step (unreadable file, failed scoring) are listed at the bottom of the report with the reason, instead of silently disappearing from the batch.
Requires Python ≥3.14 and uv.
uv sync
cp .env.example .env # then fill in the values below
uv run python -m resume_screening| Variable | Purpose |
|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from @BotFather (required) |
SCREENING_WHITELIST_IDS |
Comma-separated Telegram user IDs allowed to use the bot |
ANTHROPIC_API_KEY |
Anthropic API key (required) |
SCREENING_LANGUAGE |
Bot interface and report language: en (default) or ru |
.env is git-ignored and is never committed — see .gitignore.
uv sync --extra dev
uv run pytest95 unit tests cover intake guards, extraction, scoring (with a fake LLM client — no network/API key needed), report building, and the Telegram handlers, using dependency injection throughout so the pipeline logic is testable without mocking Telegram or Anthropic directly.
/start— the bot checks the sender against the whitelist.- Send one message with the job requirements text.
- Send resume files (PDF/DOCX), one at a time or as a group, and wait for the bot to acknowledge all of them.
/run— starts screening and returns the Excel report.
If the batch fails validation (see Limitations), the bot replies with the list of reasons and keeps the files it already accepted — you can fix the batch and send /run again without re-uploading everything.
- Python 3.14, uv for dependency management
- aiogram 3 — Telegram bot framework (FSM-based conversation flow)
- Anthropic API (
anthropicSDK) — candidate scoring pdfplumber,python-docx— resume text extractionopenpyxl— ranked, color-coded Excel report generationpytest,pytest-asyncio— test suite
- One run handles one job posting and its batch of resumes.
- Up to 50 files per batch, 10 MB per file.
- Supported formats: PDF and DOCX only.
- Access is whitelist-only — no role-based authorization.
- No persistence by design: nothing survives past report delivery (see "Key features").
resume_screening/
intake.py — request intake: whitelist check, batch limits
extraction.py — PDF/DOCX text extraction
scoring.py — candidate scoring via the Anthropic API (ensemble of 3 passes)
report.py — ranked, color-coded Excel report assembly
pipeline.py — orchestrates intake → extraction → scoring → report
config.py — configuration loading from environment variables
bot.py — Telegram handlers (aiogram)
__main__.py — entry point: python -m resume_screening
tests/ — unit tests (pytest)



