Data as of Sep 19, 2026 · Based on 297 AI responses from ChatGPT Search and Google AI Mode · See how Parse measures this
For recruiting teams needing full transparency, Brainner,
Skima AI, and
Equip provide auditability by prioritizing explainable logic and rule-based screening over opaque neural networks. is a consistent choice for its ability to function as an extension of the hiring team through custom criteria, while other options like offer open-source transparency for teams seeking complete control over their evaluation process.
Brands AI recommends here
Named in 21% of answers
Brainner is specifically designed to replace mysterious filtering with human-based, rule-driven screening. It allows recruiters to set custom requirements and receive clear justifications for candidate rankings during evaluation.
Named in 13% of answers
Named in 12% of answers
Named in 12% of answers
Building an **auditable, transparent resume screener** without black-box neural networks means relying on **deterministic, rule-based logic** and **explainable scoring matrices** . Instead of a deep learning model outputting a mysterious probability, every point awarded or deducted must trace back to a specific rule…
Building an auditable, transparent resume screener without black-box neural networks means relying on deterministic, rule-based logic and explainable scoring matrices . Instead of a deep learning model outputting a mysterious probability, every point awarded or deducted must trace back to a specific rule or keyword match.
Here is a blueprint and architecture for a completely transparent, auditable resume screening system.
pdfminer or regex ) mapped to a hardcoded dictionary."Python", "SQL").(Jan|February|20\d{2})\s*[-–]\s*(Present|Current|20\d{2})).required_skills = ["python", "sql", "git"] for skill in required_skills: if skill in resume_text_lower: score += 10 audit_log.append({"rule": f"has_required_skill_{skill}", "points": 10}) else: audit_log.append({"rule": f"missing_required_skill_{skill}", "points": 0})
Use code with caution.
4. **The Audit Trail Generator**
- Output a structured audit report for every applicant. For compliance (like EEOC or OFCCP regulations), store the exact JSON audit log alongside the candidate profile. A human reviewer can look at the log and instantly see: *"Candidate received 40/50 points because they matched X, Y, Z, but failed rule W."*
### Recommended Open-Source Tools & Libraries
- *Text Extraction:* Python's pdfminer.six or `pypdf` for reliable, deterministic text extraction without hidden ML steps.
- *Regex & Logic:* Standard Python `re` module for explicit pattern matching and constraint enforcement.
- *Data Structuring:* Use `pydantic` to enforce strict schemas for your job requisition criteria and candidate evaluation logs.
If you'd like, we can dive deeper into:
- How to write a **deterministic date-calculator** to accurately parse years of experience without AI.
- Structuring the **JSON audit schema** for compliance reporting.
Let me know which part of the pipeline you want to **build out next**.
No sources cited
Yes. A good fit is an **evidence-based, rule-driven resume screener** rather than an ML ranking model. NIST specifically identifies rule-based models, decision trees, generalized linear models, and similar inherently interpretable approaches as options for explainable systems, and notes that explainable systems are…
Yes. A good fit is an evidence-based, rule-driven resume screener rather than an ML ranking model.
NIST specifically identifies rule-based models, decision trees, generalized linear models, and similar inherently interpretable approaches as options for explainable systems, and notes that explainable systems are easier to document, debug, monitor, and audit.
Pipeline:
Extract only job-relevant fields:
skills
years/months of experience
certifications
education
job titles
employment dates
relevant projects
Use deterministic parsers, dictionaries, regular expressions, and explicitly maintained synonym tables.
Don't infer personality, "culture fit," socioeconomic status, age, gender, or similar attributes.
REQUIRED:
Python >= 2 years
SQL >= 1 year
Bachelor's degree OR equivalent documented experience
PREFERRED:
AWS
Docker
Healthcare experience
For example:
score =
40 × required_skill_coverage
+ 25 × relevant_experience
+ 15 × preferred_skill_coverage
+ 10 × certification_match
+ 10 × education_match
Every coefficient is explicitly configured rather than learned from historical hiring decisions. 5. Decision bands
Meets requirementsNeeds human reviewDoes not meet stated requirementsImportantly, don't automatically equate a low score with "bad candidate." The system should report which stated requirements were and weren't evidenced. 6. Audit record
Store something like:
{
"candidate_id": "C-10482",
"job_id": "ENG-27",
"ruleset_version": "2026-09-18-v3",
"decision": "human_review",
"score": 72,
"evidence": [
{
"criterion": "Python >= 2 years",
"result": "pass",
"evidence": "Python — 2022-2025",
"source_location": "resume:p2"
},
{
"criterion": "AWS",
"result": "not_found",
"source_location": null
}
],
"timestamp": "..."
}
That gives an auditor the ability to reconstruct exactly why the system produced its output, including the resume evidence and the version of the rules that was active at the time.
The last point matters: an interpretable model can still produce discriminatory outcomes. U.S. employment-discrimination protections apply when AI is used in recruiting and screening, and federal guidance specifically discusses resume keyword screening and other AI-assisted hiring practices.
I'd give the system four artifacts for every screening decision:
1. Job specification
The exact requirements used.
2. Ruleset
Human-readable rules such as:
R17:
IF skill = "Python"
AND documented_experience >= 24 months
THEN Python_requirement = PASS
3. Evidence report
Exactly where each conclusion came from.
4. Decision log
Who/what ran the screen, ruleset version, timestamp, output, and any subsequent human override.
Also maintain a versioned change history for the scoring rules. NIST's AI Risk Management Framework emphasizes accountability, transparency, explainability, interpretability, and ongoing risk management, which maps well onto this architecture.
If you're building this yourself, I'd use:
Python + deterministic extraction + PostgreSQL + a version-controlled YAML/JSON ruleset + a small web UI.
You don't actually need "AI" for the core decision engine. You can make the system sophisticated while keeping the final decision function completely inspectable.
If you'd like, I can also design the actual screener—including the database schema, scoring/rules engine, audit-log format, and a working Python implementation.
Yes. If **auditability is a hard requirement**, I would avoid neural-network résumé ranking entirely and build a **deterministic, rule-based screener**. ## Recommended architecture **1. Parse résumés into structured facts**
Yes. If auditability is a hard requirement, I would avoid neural-network résumé ranking entirely and build a deterministic, rule-based screener.
1. Parse résumés into structured facts
Use conventional, inspectable techniques:
JavaScript → JavaScript, B.S. → Bachelor's2. Define a job-specific scoring rubric
For example:
| Criterion | Points | Evidence |
|---|---|---|
| 3+ years Python | +20 | Employment/project dates |
| PostgreSQL experience | +15 | Explicit résumé mention |
| Bachelor's degree | +10 | Education section |
| AWS certification | +10 | Certification section |
| Relevant industry experience | +15 | Employer/role history |
| Less than 2 years total experience | −15 | Calculated |
| Required certification absent | Reject | Explicit rule |
The important part is that every point has a human-readable rule.
3. Produce an audit record for every candidate
Instead of merely returning score = 73, return something like:
Candidate: 1842
Score: 73
Decision: REVIEW
Evidence:
+20 Python >= 3 years
Evidence: "Software Engineer, Python — Jan 2022–Jun 2025"
+15 PostgreSQL
Evidence: "PostgreSQL" in Technical Skills
+10 Bachelor's degree
Evidence: "B.S. Computer Science, UCLA"
+10 AWS certification
Evidence: "AWS Certified Developer"
+15 Relevant industry experience
Evidence: "FinTech platform engineer, 2023–2025"
-0 Experience requirement satisfied
Rule set: SWE-2026-09-01
Parser version: 2.4.1
That makes it possible to reconstruct exactly why the system reached its result.
I'd use three outcomes rather than automatically rejecting people:
Critically, "no evidence found" should not automatically mean "doesn't have the skill." A résumé may simply omit it. That is one reason a review state is valuable.
Don't use names, photographs, age indicators, graduation dates, gendered language, addresses, or other proxies for protected characteristics in the scoring rules. The EEOC states that employment decisions cannot discriminate based on protected characteristics, and notes that algorithmic tools can create screening problems for applicants with disabilities.
You can separately retain legally appropriate demographic information for post-hoc fairness auditing, with access controls, rather than feeding it into the candidate score.
Keep immutable/versioned records of:
Then you can answer questions such as:
"Why did candidate 1842 fail?" and:
"What would have happened if we used last month's rules?" That is substantially stronger than trying to explain a black-box model after the fact. NIST specifically emphasizes explainability, documentation, monitoring, and defined human oversight in trustworthy AI practices.
You don't actually need "AI" for the core screener:
┌──────────────────┐
Résumé ────────────►│ Document parser │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Structured facts │
└────────┬─────────┘
│
▼
┌──────────────────┐
Job requirements ──►│ Rule engine │
└────────┬─────────┘
│
┌─────────┴─────────┐
▼ ▼
Score Explanation
│ │
└─────────┬─────────┘
▼
PASS / REVIEW / FAIL
A straightforward implementation could use Python + PostgreSQL + JSON rule definitions, with the rules stored as version-controlled configuration rather than buried in application code.
For example:
rules:
- id: python_experience
requirement: "Python >= 3 years"
type: minimum_duration
skill: python
minimum_years: 3
points: 20
- id: bachelors
requirement: "Bachelor's degree"
type: education_level
minimum: bachelors
points: 10
- id: postgres
requirement: "PostgreSQL"
type: skill_present
skill: postgresql
points: 15
- id: required_certification
requirement: "AWS certification"
type: certification_present
certification: aws
mandatory: true
This gives you a system where the rules are inspectable, deterministic, testable, versionable, and explainable.
If you tell me your hiring use case (e.g. software engineers, nurses, salespeople, warehouse workers) and whether you want a prototype, production architecture, or actual Python code, I can design the screener end-to-end.
To build an auditable, completely transparent resume screener without black-box neural networks, you need a **Deterministic Rule-Based Matching Engine**. Instead of relying on embeddings or probabilistic Large Language Models (LLMs), this architecture relies on a **Boolean logic tree, weighted keyword matrices, and…
To build an auditable, completely transparent resume screener without black-box neural networks, you need a Deterministic Rule-Based Matching Engine.
Instead of relying on embeddings or probabilistic Large Language Models (LLMs), this architecture relies on a Boolean logic tree, weighted keyword matrices, and exact pattern matching (Regex) . Every score produced can be traced back to an exact line of text and a hard-coded rule.
pypdf or pdfminer.six.Here is a functional, auditable, rule-based resume screening script written in Python. It does not use any machine learning libraries; every decision is mathematically transparent and inspectable.
python``` import re import json
JOB_RUBRIC = { "role_title": "Senior Python Engineer", "must_have_keywords": ["python", "django", "sql"], "nice_to_have_keywords": ["docker", "kubernetes", "aws", "redis"], "disqualifying_keywords": ["php", "wordpress"], # Hard exclusion triggers "min_years_experience": 5, "weights": { "must_have": 20, # points per match "nice_to_have": 5, # points per match "experience_year": 3 # points per validated year } }
def extract_years_of_experience(text): # Deterministic regex to find patterns like "5+ years", "3-5 years experience" matches = re.findall(r'(\d+)+?\s*(?:to\s*\d+)?\s*years?', text.lower()) if matches: return max(map(int, matches)) return 0
def screen_resume(resume_text, rubric): text_lower = resume_text.lower() audit_trail = { "score": 0, "status": "ACCEPTED", "matched_must_haves": [], "missing_must_haves": [], "matched_nice_to_haves": [], "triggered_disqualifiers": [], "experience_detected": 0, "reasoning": [] }
# Check 1: Disqualifiers (Hard Stop)
for bad_word in rubric["disqualifying_keywords"]:
if bad_word in text_lower:
audit_trail["triggered_disqualifiers"].append(bad_word)
audit_trail["status"] = "REJECTED"
audit_trail["reasoning"].append(f"Disqualified due to presence of forbidden term: '{bad_word}'")
if audit_trail["status"] == "REJECTED":
return audit_trail
# Check 2: Must-Have Keywords
for kw in rubric["must_have_keywords"]:
if kw in text_lower:
audit_trail["matched_must_haves"].append(kw)
audit_trail["score"] += rubric["weights"]["must_have"]
audit_trail["reasoning"].append(f"+{rubric['weights']['must_have']} pts: Found mandatory keyword '{kw}'")
else:
audit_trail["missing_must_haves"].append(kw)
audit_trail["reasoning"].append(f"0 pts: Missing mandatory keyword '{kw}'")
# Check 3: Nice-to-Have Keywords
for kw in rubric["nice_to_have_keywords"]:
if kw in text_lower:
audit_trail["matched_nice_to_haves"].append(kw)
audit_trail["score"] += rubric["weights"]["nice_to_have"]
audit_trail["reasoning"].append(f"+{rubric['weights']['nice_to_have']} pts: Found bonus keyword '{kw}'")
# Check 4: Experience extraction
years = extract_years_of_experience(resume_text)
audit_trail["experience_detected"] = years
exp_points = years * rubric["weights"]["experience_year"]
audit_trail["score"] += exp_points
audit_trail["reasoning"].append(f"+{exp_points} pts: Detected {years} years of experience ({rubric['weights']['experience_year']} pts/year)")
return audit_trail
sample_resume = """ Jane Doe - Senior Software Engineer Summary: 6 years of experience building scalable backend architectures. Skills: Expert in Python, Django, PostgreSQL, and Docker. Familiar with AWS. """
result = screen_resume(sample_resume, JOB_RUBRIC) print(json.dumps(result, indent=2))
Use code with caution.
### Why this satisfies Audit & Compliance Requirements
- **Zero Hallucination:** If a skill isn't character-matched in the string, it receives zero points.
- **Inspectable Weights:** A compliance officer or hiring manager can pull the exact JSON file (`JOB_RUBRIC` ) to see how points are assigned.
- **Reproducible Results:** Running the same resume against the same rule set 1,000 times will yield the exact same numerical score and audit trail down to the decimal.
- **No Black Box Liability:** Complies with strict AI transparency laws (like the EU AI Act or NYC Local Law 144) because the scoring logic is plain boolean arithmetic.
Would you like to expand this system to handle **synonym dictionaries** (e.g., mapping "postgres" to "sql") or format this into a **complete command-line utility** that processes a batch of PDFs?
No sources cited
Yes. I’d build it as a **rules-first, evidence-based resume screener**, not as a neural-network classifier. The core design would be: 1. **Parse the resume into structured facts**
Yes. I’d build it as a rules-first, evidence-based resume screener, not as a neural-network classifier.
The core design would be:
For example:
Required Python experience >= 3 years +30
Required SQL experience +20
Relevant bachelor's degree +10
Cloud experience +15
Relevant management experience +10
Industry certification +5
-----------------------------------------------
Maximum 90
No embeddings, LLM judgment, neural ranking, or opaque learned score is necessary. 4. Require evidence for every point
Instead of:
Candidate score: 78 produce:
78/90
- Python: 4.2 years — +30
- SQL: 5.1 years — +20
- AWS: explicitly listed — +15
- Bachelor's degree — +10
- Certification not found — +0
- Management experience: 2 years — +3/10 This makes the result independently reproducible.
I'd have the system output something like:
ELIGIBILITY: PASS
SCORE: 78/90
CONFIDENCE: HIGH
EVIDENCE:
Python >= 3 years PASS
SQL experience PASS
AWS experience PASS
Bachelor's degree PASS
MISSING / AMBIGUOUS:
Certification NOT FOUND
Management experience 2 years
DECISION:
Advance to human review
"Not found" should not automatically mean "doesn't have it." That's an important auditability distinction.
Resume PDF/DOCX
│
▼
Text extraction
│
▼
Structured fact extraction
│
▼
Normalized candidate record
│
▼
Deterministic eligibility rules
│
▼
Weighted scoring
│
├──────────────► Evidence report
│
├──────────────► Audit log
│
└──────────────► Human review queue
The only potentially probabilistic component I'd consider is document parsing, and even there I'd favor conventional extraction plus explicit pattern/rule matching wherever practical. The scoring and decision layer should remain deterministic.
For every screening decision, store:
That lets you answer:
"Why was candidate 1842 rejected?" with an actual chain of evidence rather than "the model predicted 0.23."
This aligns well with NIST's emphasis on transparency, explainability, documentation, validation, and ongoing measurement.
An interpretable algorithm isn't automatically a fair hiring algorithm. The criteria themselves need to be job-related and validated. EEOC guidance notes that selection procedures producing adverse impact may need to be modified or justified through job-related validity/business necessity.
I'd therefore explicitly prohibit the screener from using things such as:
I'd also audit outcomes across relevant demographic groups where lawful and appropriate. The EEOC specifically warns that algorithmic employment tools can screen out applicants with disabilities and recommends safeguards and accommodation processes.
A straightforward implementation could use:
PyMuPDF / python-docx for document extractionYou don't actually need "AI" for the core screening logic.
If you want, I can build you a working Python implementation of this screener, including the resume parser, YAML rule format, deterministic scoring engine, evidence/audit log, and a sample web interface.
Building an **auditable, transparent resume screener** without black-box neural networks means relying on **explainable, deterministic rules and keyword/phrase matching** (often enhanced with classic TF-IDF or explicit BM25 scoring rather than deep embeddings). Here is a blueprint and a working Python-based…
Building an auditable, transparent resume screener without black-box neural networks means relying on explainable, deterministic rules and keyword/phrase matching (often enhanced with classic TF-IDF or explicit BM25 scoring rather than deep embeddings).
Here is a blueprint and a working Python-based architecture for a fully transparent, rule-based resume screener.
pypdf or pdfplumber.Here is a lightweight, auditable script using a rule configuration.
python``` import re
JOB_CRITERIA = { "required_skills": ["python", "sql", "git"], "optional_skills": ["docker", "kubernetes", "aws"], "min_years_experience": 3, "disqualifying_terms": ["unauthorized_word_example"] }
def extract_years_of_experience(text): # Deterministic regex to find patterns like "3 years", "5+ years experience" matches = re.findall(r'(\d+)+?\s*years?', text, re.IGNORECASE) if matches: return max(int(m) for m in matches) return 0
def audit_resume(resume_text, criteria): text_lower = resume_text.lower() audit_log = {} score = 0
# Check disqualifiers
for term in criteria["disqualifying_terms"]:
if term in text_lower:
return {"status": "Rejected", "reason": f"Matched disqualifying term: {term}", "score": 0}
# Check Required Skills (Pass/Fail gate)
missing_required = [skill for skill in criteria["required_skills"] if skill not in text_lower]
audit_log["missing_required_skills"] = missing_required
if missing_required:
return {
"status": "Rejected",
"reason": f"Missing required skills: {missing_required}",
"audit_log": audit_log,
"score": 0
}
# Score Required Skills
score += len(criteria["required_skills"]) * 20
# Score Optional Skills
matched_optional = [skill for skill in criteria["optional_skills"] if skill in text_lower]
score += len(matched_optional) * 10
audit_log["matched_optional_skills"] = matched_optional
# Check Experience
years_exp = extract_years_of_experience(resume_text)
audit_log["detected_years_experience"] = years_exp
if years_exp < criteria["min_years_experience"]:
return {
"status": "Rejected",
"reason": f"Experience ({years_exp} yrs) is below minimum required ({criteria['min_years_experience']} yrs)",
"audit_log": audit_log,
"score": score
}
score += 20
return {
"status": "Approved for Review",
"reason": "Met all required gates and minimum experience.",
"audit_log": audit_log,
"score": score
}
sample_resume = "Experienced software engineer with 4 years of experience using Python, SQL, and Git. Familiar with Docker." result = audit_resume(sample_resume, JOB_CRITERIA) print(result)
Use code with caution.
### Why this satisfies Auditability
- **Zero Latent Spaces:** No vector embeddings or weights to interpret; logic executes via explicit boolean conditions and arithmetic.
- **Traceable Logs:** Every rejection cites the exact constraint failed (e.g., *“Missing required skill: sql”*).
- **Version Control Ready:** Because rules live in flat JSON/YAML files, compliance teams can diff changes to hiring criteria over time via Git.
If you want to build this out, tell me:
- What **file formats** do you need to support (PDF, DOCX, TXT)?
- Do you want to use a **relational database** to store the audit trail?
No sources cited
Yes. If your priority is **auditability over predictive complexity**, I’d build the screener as a **deterministic, rules-based scoring system** rather than a neural-network résumé ranker. That approach also fits well with the EEOC’s guidance to define objective, job-related qualification standards and apply them…
Yes. If your priority is auditability over predictive complexity, I’d build the screener as a deterministic, rules-based scoring system rather than a neural-network résumé ranker.
That approach also fits well with the EEOC’s guidance to define objective, job-related qualification standards and apply them consistently, while monitoring whether selection criteria disproportionately exclude protected groups.
For each role, define:
Example:
| Criterion | Type | Points |
|---|---|---|
| 3+ years Python experience | Required | 25 |
| SQL experience | Required | 15 |
| AWS experience | Preferred | 10 |
| Bachelor's degree | Preferred | 5 |
| Relevant management experience | Preferred | 15 |
| Relevant industry experience | Preferred | 10 |
| Quantified project achievements | Preferred | 10 |
| Relevant certification | Preferred | 5 |
| Total | 95 |
Importantly, don't let the model invent criteria from the résumé.
The résumé parser can use conventional NLP techniques:
For example:
"Developed REST APIs in Python and Flask for 4 years" could produce:
python:
evidence = "Python and Flask"
duration = 4 years
source = resume.page_1.experience[2]
confidence = 1.0
No neural embedding is required.
Instead of:
Candidate score: 87.3 produce:
SCORE: 82 / 95
+25 Python ≥3 years
Evidence: Acme Corp, 2021–2025
Rule: PYTHON_3YR_V1
+15 SQL experience
Evidence: "PostgreSQL, SQL Server"
Rule: SQL_REQUIRED_V1
+10 AWS
Evidence: "AWS EC2, S3, Lambda"
Rule: AWS_PREFERRED_V1
+15 Management experience
Evidence: Managed team of 6 engineers
Rule: MANAGEMENT_V1
+10 Industry experience
Evidence: Healthcare software, 2022–2025
Rule: INDUSTRY_V1
+5 Certification
Evidence: AWS Solutions Architect
Rule: CERTIFICATION_V1
-0 Bachelor's degree
Not found
DECISION: ADVANCE
THRESHOLD: 70
A reviewer should be able to reconstruct the decision without trusting the software.
NIST specifically identifies accountability, transparency, explainability, interpretability, and fairness as characteristics of trustworthy AI, and notes that explainable systems are easier to debug, monitor, document, audit, and govern.
Don't score or infer things such as:
You can maintain a separate, access-controlled dataset for aggregate fairness auditing where legally appropriate, but it should not be an input to the candidate score.
The EEOC specifically notes that information such as race, sex, national origin, age, and religion is generally irrelevant to determining whether someone is qualified.
For every screening decision, retain:
candidate_id
job_id
timestamp
resume_hash
ruleset_version
criteria_version
extracted_evidence
individual_scores
total_score
decision
threshold
reviewer_override
override_reason
Also version everything:
JOB-ENG-042-v3
RULESET-v17
TAXONOMY-v8
SCORER-v12
That lets you answer:
"Why was Jane rejected on March 3?" with the exact résumé, rules, evidence, and thresholds that produced the decision—not today's version of the algorithm.
I'd make the system a decision-support tool, not an autonomous hiring system:
Résumé
↓
Deterministic parser
↓
Structured candidate facts
↓
Explicit job criteria
↓
Rules engine
↓
Score + evidence
↓
Human review
↓
Hiring decision
A particularly useful feature is a "show me why" button that displays the exact résumé passages supporting every positive or negative criterion.
Run the same ruleset over historical/applicant data and measure selection rates across relevant groups, where legally permissible.
You want to detect things like:
Criterion: Bachelor's degree
Pass rate:
Group A: 74%
Group B: 49%
Potential disparity: investigate
That doesn't automatically mean the criterion is unlawful or invalid. The next question is whether the criterion is genuinely job-related and necessary. The EEOC advises employers to analyze job duties and competencies, establish objective job-related standards, and examine whether criteria disproportionately exclude groups.
A straightforward implementation could be:
pypdf / python-docx for document extractionspaCy or simple regex/rule processing for NLPYou can even make the core scorer something as transparent as:
score = sum(
criterion.points
for criterion in criteria
if criterion.is_satisfied(candidate)
)
The important part isn't sophisticated AI; it's well-defined criteria, evidence provenance, versioning, reproducibility, and human review.
NIST's current AI Risk Management Framework emphasizes continuous governance, measurement, and management of system risks, which maps nicely onto this architecture.
If you're building this as an actual product, I can also lay out a complete technical specification—including the database schema, rules DSL, scoring algorithm, audit-log format, API endpoints, and reviewer UI—using only interpretable/non-neural methods.
"Why was Jane rejected on March 3?" with the exact résumé, rules, evidence, and thresholds that produced the decision—not today's version of the algorithm.
I'd make the system a decision-support tool, not an autonomous hiring system:
Résumé
↓
Deterministic parser
↓
Structured candidate facts
↓
Explicit job criteria
↓
Rules engine
↓
Score + evidence
↓
Human review
↓
Hiring decision
A particularly useful feature is a "show me why" button that displays the exact résumé passages supporting every positive or negative criterion.
Run the same ruleset over historical/applicant data and measure selection rates across relevant groups, where legally permissible.
You want to detect things like:
If you'd like, I can: - Write a **Python implementation** of a rule-based matching and scoring script. - Detail how to structure the **JSON audit log** for compliance tracking.
If you'd like, I can:
Let me know how you'd like to proceed with the design.
No sources cited
Yes. If your priority is **auditability over predictive sophistication**, I’d build the screener as a **transparent, rules-based scoring system** rather than a neural-network résumé ranker. ### Recommended design Use a pipeline like:
Yes. If your priority is auditability over predictive sophistication, I’d build the screener as a transparent, rules-based scoring system rather than a neural-network résumé ranker.
Use a pipeline like:
For example:
Score =
40 × required_skill_match
+ 25 × relevant_experience
+ 15 × certification_match
+ 10 × education_match
+ 10 × preferred_skill_match
Better still, make each component independently inspectable:
Python: +10 (required)
SQL: +10 (required)
4 years exp: +20
AWS cert: +10
Bachelor's: +10
-------------------
Total: 60/100
No embeddings, neural-network ranking, personality inference, facial analysis, or opaque "candidate quality" score. 4. Generate an explanation with every decision
The system should be able to answer:
Why was Candidate A scored 72? with something like:
+20 — 4 years relevant experience
+10 — Python
+10 — SQL
+10 — AWS certification
+15 — Bachelor's degree
- 5 — only partial match for required healthcare experience
That gives you an actual audit trail rather than merely claiming that the system is explainable.
A hand-written rules engine can still discriminate. For example, a blanket bachelor's-degree requirement could disproportionately exclude certain groups without being necessary for the job. EEOC guidance specifically notes that screening criteria with disparate impact need to be job-related and consistent with business necessity.
So I'd add a separate fairness/audit layer that periodically examines selection rates across legally relevant demographic groups, where collecting that information is lawful and appropriate. Protected characteristics should be segregated from the scoring data, rather than fed into the screener. The EEOC specifically describes separating race information from qualification information when applicant-flow monitoring is needed.
Also provide a human-review/accommodation path. The EEOC warns that algorithmic tools can unintentionally screen out people with disabilities and says employers may need to provide reasonable accommodation or an alternative assessment.
You don't need machine learning at all:
python-docx, or a conventional PDF parserFor example:
job: software_engineer
version: 12
criteria:
- id: python
type: required_skill
weight: 20
evidence:
- python
- django
- flask
- id: sql
type: required_skill
weight: 15
- id: experience
type: relevant_years
weight: 30
thresholds:
2: 15
3: 20
5: 30
- id: aws
type: preferred_skill
weight: 10
This is particularly attractive for auditability because the model isn't the decision-maker—the published rules are.
NIST's AI Risk Management Framework emphasizes accountability, transparency, explainability, reliability, privacy, and fairness as characteristics of trustworthy AI, which maps nicely onto this architecture.
If you tell me what kind of roles you're screening for and roughly how many résumés you process per month, I can design the actual screener architecture, scoring schema, database model, and audit report format.
Building an auditable, transparent resume screener without black-box neural networks requires a **rule-based, deterministic pipeline** . By avoiding deep learning or LLM "black boxes," every screening decision can be traced back to an explicit business rule, keyword match, or logic gate. Here is a blueprint and…
Building an auditable, transparent resume screener without black-box neural networks requires a rule-based, deterministic pipeline . By avoiding deep learning or LLM "black boxes," every screening decision can be traced back to an explicit business rule, keyword match, or logic gate.
Here is a blueprint and architecture for a fully auditable, explainable resume screener.
Core Architecture
pdfplumber or python-docx.Instead of hidden weights, your screening logic lives in a version-controlled YAML file. Any changes to criteria require a git commit, ensuring full traceability.
yaml``` job_title: "Senior Backend Engineer" minimum_experience_years: 5 required_skills:
Use code with caution.
2. Deterministic Screening Engine (Python)
The logic uses regular expressions and explicit string matching. No probabilistic scoring or embeddings are involved.
python```
import re
def extract_years_of_experience(text):
# Matches patterns like "5+ years", "3-5 years experience"
matches = re.findall(r'(\d+)\+?\s*(?:to|-)?\s*(\d+)?\s*years?', text, re.IGNORECASE)
if not matches:
return 0
# Take the highest number found as a conservative heuristic, or parse explicitly
nums = [int(m[0]) for m in matches if m[0].isdigit()]
return max(nums) if nums else 0
def screen_resume(resume_text, config):
audit_trail = {}
# 1. Check Required Skills (Exact / Case-insensitive substring match)
missing_required = []
for skill in config["required_skills"]:
found = re.search(r'\b' + re.escape(skill) + r'\b', resume_text, re.IGNORECASE)
audit_trail[f"skill_{skill}"] = bool(found)
if not found:
missing_required.append(skill)
# 2. Check Experience
parsed_exp = extract_years_of_experience(resume_text)
exp_pass = parsed_exp >= config["minimum_experience_years"]
audit_trail["experience_parsed_years"] = parsed_exp
audit_trail["experience_criteria_met"] = exp_pass
# 3. Overall Decision Logic
passed = (len(missing_required) == 0) and exp_pass
return {
"status": "PASS" if passed else "FAIL",
"missing_required_skills": missing_required,
"audit_trail": audit_trail
}
Use code with caution.
Every candidate profile processed returns a human-readable audit dictionary that can be stored in a flat JSON/CSV file:
json``` { "candidate_id": "1042", "status": "FAIL", "missing_required_skills": ["Docker"], "audit_trail": { "skill_Python": true, "skill_SQL": true, "skill_Docker": false, "experience_parsed_years": 6, "experience_criteria_met": true } }
Use code with caution.
Recommended Open-Source Tooling
- - Text Extraction: Use pdfplumber GitHub for precise text and layout extraction from PDFs.
- - Logic & Validation: Use Pydantic to enforce strict schemas on your job requirement configuration files so malformed rules can never slip through.
- - Workflow Orchestration: Use standard Python scripts tracked in a Git repository so every change to the scoring logic has a complete history.
Would you like me to expand on **how to handle semantic variations** (like matching "JS" to "JavaScript") deterministically using explicit alias dictionaries, or do you need help structuring the **database schema** for storing these audit logs?
No sources cited