Jupyter job-title validation workbench: multi-signal input, VALID/INVALID + confidence, ESCO/O*NET/UK SOC/India NCO neighbours, looping practice sequences.
  • Python 78.2%
  • Jupyter Notebook 21.4%
  • Makefile 0.4%
Find a file
brahm ed336d02fe Add a Jupyter job-title validation workbench.
Practice B2B title cleaning like a chord progression: multi-field input,
VALID/INVALID with confidence, ESCO/O*NET/UK SOC/India NCO neighbours,
rule + n-gram explanations, looping sequences, and a from-scratch notebook
with Mac replication placeholders.
2026-08-19 17:49:31 +00:00
data Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
docs Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
notebooks Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
results Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
scripts Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
src/jtv_workbench Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
tests Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
.gitignore Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
LICENSE Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
Makefile Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
README.md Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
requirements.txt Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00
START-HERE.md Add a Jupyter job-title validation workbench. 2026-08-19 17:49:31 +00:00

Job title validation workbench

Public: https://git.binary.ovh/brahm/job-title-workbench

A Jupyter workbench for practicing B2B contact-data job-title validation the same way a musician practices a chord progression: load a sequence, loop it at a tempo, highlight the active title, edit the progression, correct a row, and see why the engine called it valid or invalid.

This is a notebook, not a web app. You read the code in the cell, then the output under it. Fork it. Change a rule. Swap the embedder. Score your own CSV. The from-scratch notebook is empty on purpose.

What it does

Surface What you get
Multi-field input job title (required) + optional company, country, first name, last name, email
Binary verdict VALID / INVALID plus a confidence score (distance from the 0.5 boundary)
Taxonomies nearest matches from ESCO, O*NET, UK SOC 2020, India NCO-2015
Explanation triggered rules + char n-gram cosine + shared n-grams + multi-signal consistency
Presets common valid titles, common junk, noisy/borderline rows
Batch / “tempo” loop a sequence, adjustable titles-per-minute, highlighted active row
Edits rewrite the sequence as CSV; override a single rows verdict

It does not tell you whether this person holds this job at this company today. That is a registry question. This workbench answers is this string a plausible job title, and do the other fields on the row collide with it?

5 minutes

git clone https://git.binary.ovh/brahm/job-title-workbench.git
cd job-title-workbench
python3 -m venv .venv
source .venv/bin/activate          # Mac/Linux
pip install -r requirements.txt
export PYTHONPATH=src
python tests/test_engine.py
python scripts/smoke.py
python -m jtv_workbench.cli "Chief Executive Officer" --country GB
jupyter lab notebooks/00-start-here.ipynb

On a Mac, follow docs/MAC.md instead — same steps, with Homebrew / Apple Silicon placeholders.

Notebooks

Notebook Role
notebooks/00-start-here.ipynb Orientation, smoke scores, then the live workbench
notebooks/01-how-it-works.ipynb The engine in the open: normalize → rules → taxonomies → n-grams → fusion
notebooks/02-from-scratch.ipynb Empty functions, # >>> YOUR CODE HERE, compare against the reference

How scoring works

contact fields
    │
    ├─ rules (hard structural fails, soft linguistic fails)
    ├─ char 3-gram TF-IDF cosine vs ESCO / O*NET / UK SOC / India NCO
    └─ consistency (title vs company, country, name, email)
            │
            ▼
     fused score in [0, 1]
     VALID if ≥ 0.5 else INVALID
     confidence = |score  0.5| × 2

Hard fails (empty, email-in-title, placeholder, title-equals-company, …) clip the fused score to ≤ 0.18, so junk cannot be rescued by a lucky n-gram overlap.

The embedder is not a neural net. It is character 3-grams with IDF weights so you can print the shared grams that made two strings look close. That is the point of a practice workbench. On a Mac you can drop in sentence-transformers — there is a placeholder cell for it.

Weights live in src/jtv_workbench/score.py as WEIGHTS. Change them in the notebook and re-score. They are not calibrated probabilities.

Data

Curated slices, vendored so the notebooks run offline:

File Slice Licence / source
data/taxonomies/esco.json 1,699 English ESCO occupations CC BY 4.0, European Commission
data/taxonomies/onet.json 1,016 O*NET-SOC titles (db 30.3) CC BY 4.0, U.S. DOL/ETA
data/taxonomies/uk_soc.json SOC 2020 unit groups (practice slice) OGL v3.0, ONS
data/taxonomies/india_nco.json NCO-2015 unit groups (ISCO-08 aligned slice) Govt of India classification titles

These are not the full official files. A 251k-entry lexicon still only resolved 32.9% of real titles in the sibling job-title-validation project. Nearest-neighbour hits here are “what official title is this closest to?”, not “therefore valid”.

To replace a slice with an official download, see scripts/fetch_taxonomies.py (URLs are marked PLACEHOLDER — confirm them on the authority site; some are portals, not direct files).

Layout

notebooks/          the thing you open
src/jtv_workbench/  the same engine, importable
data/               taxonomies, presets, names
scripts/            smoke + official-file placeholders
tests/              assertions the from-scratch notebook can fail against
docs/MAC.md         Mac replication
docs/FROM-SCRATCH.md
results/            smoke output committed so you can compare

Honest limits

  • Binary VALID/INVALID is a practice UI. Production contact-trust systems keep a three-way VALID / REVIEW / INVALID so weak evidence is not forced into a false accept. Low confidence here is that REVIEW band.
  • Char n-gram cosine ranks strings. It is not mmBERT. A measured neural nearest-neighbour baseline (0.959 acc on O*NET vs curated negatives) lives in ml-tutorials.
  • Occupational surnames (Baker, Cook, Taylor) are genuinely ambiguous. The engine uses role-heads + the contacts own name when supplied; it will still get some of these wrong. That is the drill.
  • No registry lookup. A well-formed fake executive passes.