Spaces:
Sleeping
Sleeping
| # Talentry AI - System Architecture | |
| This document is the **engineer's guide** to Talentry AI. If you are reviewing | |
| the codebase at Stage 3 (reproduction) or Stage 5 (defend-your-work) of the | |
| Redrob × Hack2Skill - India Runs challenge, start here. | |
| --- | |
| ## 1. Goals and constraints | |
| The challenge ([`submission_spec.md` §3](../configs/submission_spec.txt)) | |
| imposes a hard envelope on the ranking step: | |
| | Constraint | Limit | | |
| | --------------------------- | --------------------------- | | |
| | Wall-clock runtime | **≤ 5 minutes** | | |
| | RAM | **≤ 16 GB** | | |
| | Compute | **CPU only** | | |
| | Network | **Off** (no LLM API calls) | | |
| | Disk (intermediate state) | **≤ 5 GB** | | |
| We additionally treat these *product* requirements as first-class: | |
| * **Explainability** - every score must be defensible at Stage 4 manual review. | |
| * **Reproducibility** - bit-for-bit reproducibility in a sandboxed Docker. | |
| * **Anti-trap robustness** - the dataset deliberately contains keyword | |
| stuffers, plain-language Tier-5s, behavioural twins, and ~80 honeypots. | |
| * **No hallucination in reasoning** - every reasoning string must reference | |
| only facts present in the candidate's own profile. | |
| --- | |
| ## 2. High-level architecture | |
| ``` | |
| ┌──────────────────────────────────────────────────────────────────────────┐ | |
| │ Talentry AI │ | |
| │ │ | |
| │ ┌──────────┐ ┌──────────────┐ ┌────────────────────────────┐ │ | |
| │ │ JD text │───▶│ JD Parser │───▶│ JobRequirements │ │ | |
| │ └──────────┘ │ (rules+lex) │ │ • role family, seniority │ │ | |
| │ └──────────────┘ │ • must / nice / disqual. │ │ | |
| │ │ • locations, behaviour │ │ | |
| │ └──────────────┬─────────────┘ │ | |
| │ │ │ | |
| │ ▼ │ | |
| │ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ | |
| │ │ candidates.jsonl │──▶│ Loader + models │──▶│ Feature builder │ │ | |
| │ └──────────────────┘ └──────────────────┘ │ (text_blob, │ │ | |
| │ │ role signals) │ │ | |
| │ └────────┬────────┘ │ | |
| │ │ │ | |
| │ ┌─────────────────────────────────────────────┴───────┐ │ | |
| │ ▼ ▼ │ | |
| │ ┌─────────────────┐ ┌────────────────────┐│ | |
| │ │ BM25 + TF-IDF │ hybrid semantic score │ Skill Evidence ││ | |
| │ │ hybrid index │─────────────────┐ │ (cluster, stuffer ││ | |
| │ └─────────────────┘ │ │ detection) ││ | |
| │ ▼ └────────┬───────────┘│ | |
| │ ┌────────────────────────┐ │ │ | |
| │ │ Scorer (5 weighted) │◀───────┘ │ | |
| │ │ + Behavioural × mul. │ │ | |
| │ │ − Honeypot penalty │ │ | |
| │ └──────────┬─────────────┘ │ | |
| │ ▼ │ | |
| │ ┌────────────────────────┐ │ | |
| │ │ Sort + Reasoning + CSV │ │ | |
| │ └──────────┬─────────────┘ │ | |
| │ ▼ │ | |
| │ submission.csv │ | |
| └──────────────────────────────────────────────────────────────────────────┘ | |
| ``` | |
| ### Module → file mapping | |
| | Module | File | | |
| | ---------------------------- | ---------------------------------------------------------- | | |
| | Domain models | `src/talentry/core/models.py` | | |
| | Tokeniser + synonyms | `src/talentry/nlp/tokenize.py` | | |
| | Domain lexicons | `src/talentry/nlp/lexicons.py` | | |
| | Candidate I/O | `src/talentry/io/candidates.py` | | |
| | Submission CSV writer | `src/talentry/io/submission.py` | | |
| | Per-candidate features | `src/talentry/features/builder.py` | | |
| | Skill evidence scoring | `src/talentry/features/skill_match.py` | | |
| | Behavioural multiplier | `src/talentry/signals/behavioural.py` | | |
| | Honeypot penalty | `src/talentry/signals/honeypot.py` | | |
| | Hybrid BM25+TF-IDF index | `src/talentry/ranker/semantic.py` | | |
| | JD parser | `src/talentry/ranker/jd_parser.py` | | |
| | Scoring formulae | `src/talentry/ranker/scorer.py` | | |
| | Reasoning composer | `src/talentry/ranker/reasoning.py` | | |
| | End-to-end pipeline | `src/talentry/ranker/engine.py` | | |
| | CLI | `src/talentry/cli/rank.py` | | |
| | HTTP API (FastAPI) | `src/talentry/api/server.py` | | |
| | React UI | `ui/talentry-space/` | | |
| --- | |
| ## 3. Why not dense embeddings? | |
| Reviewers will rightly ask: "this is a retrieval challenge - why not a | |
| sentence-transformer?" Three reasons: | |
| 1. **Budget.** Loading a 90 MB MiniLM and encoding 100K text blobs is right at | |
| the edge of the 5-minute CPU budget; once you add the per-row scoring, | |
| feature building, sort, and CSV write, you have no headroom for slow | |
| I/O on the Stage 3 sandbox. | |
| 2. **Dependency surface.** A serialised PyTorch model artifact is one more | |
| thing that can break reproduction; pure BM25 + TF-IDF reproduces from | |
| `pip install`-able libraries alone. | |
| 3. **Signal saturation.** BM25 saturates on rare-term overlap and TF-IDF | |
| smooths over phrasing - and that is exactly what this dataset rewards. | |
| Adding a dense model marginally improves recall on prose-only profiles | |
| but adds noise on the keyword surface where stuffers live. | |
| If we had two hours and a GPU per ranking call we would absolutely add a | |
| domain-fine-tuned reranker on the top 1000. We do not. | |
| --- | |
| ## 4. Composition formula | |
| ``` | |
| linear = 0.32·title_alignment | |
| + 0.22·semantic_fit | |
| + 0.28·skill_evidence | |
| + 0.12·experience_band | |
| + 0.06·location | |
| final = linear × behavioural_multiplier ∈ [0.55, 1.20] | |
| − honeypot_penalty ∈ [0, 0.50] | |
| (clipped to [-0.5, 1.5]) | |
| ``` | |
| Every constant is grounded in a specific line of the JD; see | |
| [`methodology.md`](methodology.md) for the rationale. | |
| --- | |
| ## 5. Determinism | |
| * Hot path uses no random state. | |
| * `reference_date` for behavioural recency is overridable for tests. | |
| * Sort tie-break: `candidate_id` ascending - matches the validator. | |
| * CSV writer enforces the exact validator invariants at write-time so any | |
| drift fails loudly in the CLI, never silently at upload. | |
| --- | |
| ## 6. Threat model - the four traps | |
| | Trap | Defence | | |
| | --------------------- | -------------------------------------------------------------- | | |
| | Keyword stuffer | Skill *evidence* (endorsements × duration × proficiency) | | |
| | Plain-language Tier 5 | BM25 over career-description text + role-family trajectory | | |
| | Behavioural twin | Behavioural multiplier in [0.55, 1.20] | | |
| | Honeypot | Honeypot penalty subtracts up to 0.50 | | |
| --- | |
| ## 7. Operational notes | |
| * CLI: `python -m talentry.cli.rank ...` (see `make submission`). | |
| * API: `talentry-serve` (or `make serve`) → `http://localhost:7860`. | |
| * UI: `make ui-dev` (`http://localhost:5173` with `/api` proxied). | |
| * Container: `make docker-build && make docker-run` - same image is pushed to | |
| the HuggingFace Space. | |