One open role draws 200+ resumes in mixed formats. Recruiters spend a week reading; many qualified candidates get buried by skim-fatigue. Time-to-shortlist hurts hiring velocity.
The AI approach
Parse + score against the JD. NER pulls structured fields; LLM scores how well the resume matches the JD across must-haves and nice-to-haves; rules enforce eligibility floors.
The outcome
~5 min for 200
200 resumes → ranked Excel in ~5 min. Recruiter reads top 20 first, with the matching evidence already pulled.
Try itInput → Process → Output
Input — resume PDF (one of 200)
Anan Suwannakij
Senior Data Analyst · 7 yrs
anan.s@gmail.com · 089-***-1422 · Bangkok
Experience
Lead Data Analyst, ABC Retail (2022–) Built pricing dashboards in Power BI; led migration to Snowflake; mentored 4.
Data Analyst, XYZ Bank (2019–2022) SQL, Python, churn models, A/B testing.
Skills
SQL · Python (pandas, sklearn) · Power BI · dbt · Snowflake · A/B testing · stakeholder mgmt
Education
B.Eng. Industrial, Chula 2018 · GPA 3.42
Process — AI pipeline
1NER: name, dates, skillsReadPredictive
2LLM: structure to schemaReadGenerative
3Eligibility floor (rules)RulesSymbolic
4JD-fit score + evidenceWriteGenerative
Output — ranked shortlist (excerpt)
Click Run demo to parse the resume and rank the candidate against the JD.
X
shortlist_data_analyst.xlsx200 candidates · sorted by JD-fit
#
Name
Yrs
Top skills
JD-fit
Why
1
Anan Suwannakij
7
SQL · Python · Power BI · Snowflake
94
5/5 must-haves; led migration ↔ JD focus
2
Pim Charoenkul
5
SQL · dbt · Looker · Python
88
strong dbt; missing Power BI
3
Vorawit T.
9
SQL · Tableau · R · A/B
71
senior, but Tableau-only
4
Naphaphorn N.
3
SQL · Python · pandas
62
under 5y experience floor
5
Saran K.
2
Excel · SQL basics
38
missing 3/5 must-haves
fairness check · names redacted from scoring step200 in 4m 42s
Three AI types in this use case
SymbolicEligibility floor rules (years, location, lang); name-redaction guard during scoring.
PredictiveNER for name / dates / skills / education; resume layout parser; bias audit.
GenerativeLLM scores fit vs JD using a rubric prompt and writes the “Why” evidence line per candidate.
The stack
Parser · spaCy NER + custom resume model
Schema · LLM with Pydantic output
Floor rules · YAML config (years, location, lang)
Scorer · LLM + JD-as-rubric prompt
When this works
JD has explicit must-haves + nice-to-haves
Volume is high — ≥ 50 resumes / role
Recruiter reviews top-N, doesn't auto-reject
Bias controls are in place (name redaction, audit logs)
When it fails
JD is vague — score is mostly noise
Career-changer resumes — model anchors on past role
Auto-reject without human review — disparate impact risk
Resume parsing breaks on creative layouts (graphic CVs)