Skip to content
SabariLRMPublic
forked from sanjjiiev/RES-AI

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Β 
Β 

Latest commit

Β 

History

8 Commits

Folders and files

Repository files navigation

RES-AI β€” Secure Resume Intelligence System

Production-grade, fully local, open-source resume screening pipeline powered by GraphRAG, GLiNER, and Neo4j.

No cloud APIs. No data leaves your machine. Every decision is auditable.


What Is RES-AI?

RES-AI is a 5-phase AI pipeline that turns raw resume PDFs into a queryable knowledge graph in Neo4j, then ranks candidates against a job description using graph traversal and an optional local LLM (Ollama).

It was built specifically to solve three problems with traditional resume screening:

Problem How RES-AI Solves It
Bias from names, gender, location Microsoft Presidio scrubs all PII before any AI sees the data
Keyword-matching misses related skills GraphRAG traverses a skill taxonomy (FastAPI β†’ Python β†’ Backend)
Black-box AI decisions Every score is traceable to graph edges with confidence scores

Architecture β€” 5 Phases

PDF Resume
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PHASE 2 β€” Secure Ingestion  (main.py)                  β”‚
β”‚                                                         β”‚
β”‚  Docling ──► raw Markdown                               β”‚
β”‚      β”‚                                                  β”‚
β”‚  GLiNER ──► zero-shot NER ──► structured entities       β”‚
β”‚      β”‚           (Python, FastAPI, Blue Team …)         β”‚
β”‚      β”‚                                                  β”‚
β”‚  Presidio ──► PII redacted Markdown                     β”‚
β”‚      β”‚        (names, phones, emails, locations gone)   β”‚
β”‚      β”‚                                                  β”‚
β”‚  Neo4j ──► Candidate node + typed relationship edges    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PHASE 3 β€” GraphRAG & Knowledge Graph  (taxonomy.py)    β”‚
β”‚                                                         β”‚
β”‚  ESCO Skill Taxonomy seeded into Neo4j                 β”‚
β”‚  (FastAPI β†’ IS_FRAMEWORK_OF β†’ Python)                  β”‚
β”‚                                                         β”‚
β”‚  GraphRAGLinker connects candidate entities             β”‚
β”‚  to taxonomy nodes via SIMILAR_TO edges                 β”‚
β”‚                                                         β”‚
β”‚  Multi-hop queries: "find Python devs" matches          β”‚
β”‚  FastAPI, Django, PyTorch, Flask candidates too         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PHASE 4 β€” JD Evaluation  (evaluator.py)                β”‚
β”‚                                                         β”‚
β”‚  GLiNER parses job description β†’ required skill list   β”‚
β”‚  Neo4j graph ranks candidates by skill coverage        β”‚
β”‚  Optional: Ollama LLM writes narrative summaries        β”‚
β”‚  (DeepSeek-R1, Llama-3, or any local model)            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PHASE 5 β€” Enterprise API  (api.py)                     β”‚
β”‚                                                         β”‚
β”‚  FastAPI REST server with Swagger UI                   β”‚
β”‚  Audit logging to audit.log (every request)            β”‚
β”‚  Prompt injection guard on all JD inputs               β”‚
β”‚  File type + size validation on uploads                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tech Stack

Layer Technology Why
Document parsing Docling (IBM) Preserves tables, columns, headers in PDFs
Entity extraction GLiNER Zero-shot NER β€” no fine-tuning needed
PII redaction Microsoft Presidio Production-grade, used at Microsoft scale
Knowledge graph Neo4j Graph DB with Cypher query language
Skill taxonomy ESCO-inspired (built-in) 100+ skill relationships across 10 domains
LLM (optional) Ollama Fully local β€” DeepSeek-R1, Llama-3, etc.
REST API FastAPI Async, auto Swagger docs, production-ready
CLI argparse (built-in) No extra deps β€” python run.py ingest ...

File Structure

crt/
β”œβ”€β”€ schema.py          # Shared ENTITY_SCHEMA β€” single source of truth
β”œβ”€β”€ main.py            # Phase 2: ingestion orchestrator
β”œβ”€β”€ taxonomy.py        # Phase 3: ESCO skill taxonomy + GraphRAG linker
β”œβ”€β”€ query_engine.py    # Phase 3: graph traversal query engine
β”œβ”€β”€ evaluator.py       # Phase 4: JD parser + candidate scorer
β”œβ”€β”€ api.py             # Phase 5: FastAPI REST server + audit logging
β”œβ”€β”€ run.py             # CLI entry point β€” all phases via subcommands
β”œβ”€β”€ requirements.txt   # All Python dependencies
└── .env.example       # Environment variable template

Prerequisites

Before installing, make sure you have:

  • Python 3.10+
  • Neo4j 5.x running locally (Docker is the easiest way)
  • Ollama (optional β€” only needed for LLM narrative summaries)

Start Neo4j with Docker

docker run -d \
  --name neo4j \
  -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/supersecretpassword \
  neo4j:5

Neo4j Browser will be at http://localhost:7474


Installation

# 1. Navigate to the project folder
cd "C:\Users\ssanj\OneDrive\Documents\HUB_2.0\RES-AI"

# 2. Activate your virtual environment
.\venv\Scripts\Activate

# 3. Install all dependencies
pip install -r crt\requirements.txt

# 4. Download the SpaCy English model (required by Presidio)
python -m spacy download en_core_web_lg

# 5. Set up environment variables
copy crt\.env.example crt\.env
# Open crt\.env and set your Neo4j password if different from default

Usage

All commands are run from inside the crt/ folder:

cd crt

Ingest a Single Resume (Phases 2 + 3)

python run.py ingest --resume "..\sample_resume\Resume.pdf"

What happens:

  1. PDF β†’ layout-aware Markdown (Docling)
  2. 12 entity categories extracted: Programming Language, Framework, Database, Cloud Platform, Security Tool, Soft Skill, Job Title, Degree, University, Certification, Years of Experience, Industry
  3. All PII (name, phone, email, location) redacted
  4. Candidate node + typed relationship edges written to Neo4j
  5. Skill taxonomy seeded and candidate linked to taxonomy graph
  6. Two output files saved: <ID>_safe.md and <ID>_entities.json

Options:

Flag Description
--resume FILE Path to a single PDF or DOCX
--folder DIR Process all PDFs in a folder (batch mode)
--force Re-ingest even if the same file was already processed
--no-taxonomy Skip Phase 3 taxonomy linking
--json Print result as JSON

Batch Ingest a Folder

python run.py ingest --folder "..\resumes_folder\"

Evaluate Candidates Against a Job Description (Phase 4)

python run.py evaluate --jd "Looking for a Python backend developer with FastAPI, PostgreSQL, Docker, and AWS experience."
# From a text file
python run.py evaluate --jd-file job_description.txt --top-n 5
# With Ollama LLM narrative summaries (requires Ollama running)
python run.py evaluate --jd "..." --llm

Sample output:

Rank  1 | CANDIDATE_A1B2C3D4E5F6  | score=8 | coverage=80%
         matched: Python, Fastapi, Postgresql, Docker
Rank  2 | CANDIDATE_G7H8I9J0K1L2  | score=5 | coverage=50%
         matched: Python, Aws

Search by Skill β€” GraphRAG Mode (Phase 3)

# Finds candidates who know Python OR anything in the Python ecosystem
python run.py search --skill Python

# Finds all cybersecurity candidates via taxonomy traversal
python run.py search --skill "Blue Team"

# Exact match only (no ecosystem traversal)
python run.py search --skill Python --no-ecosystem

Knowledge Graph Statistics

python run.py stats
========================================
RES-AI Knowledge Graph Stats
  Candidates      : 12
  Skill nodes     : 347
  Relationships   : 891
  Taxonomy nodes  : 108
========================================

Seed / Refresh the Skill Taxonomy

python run.py seed-taxonomy

Safe to run multiple times β€” all writes use MERGE (idempotent).


Start the REST API (Phase 5)

python run.py serve
# Dev mode with hot-reload:
python run.py serve --reload

Open http://localhost:8000/docs for the full interactive Swagger UI.

API Endpoints

Method Endpoint Description
GET /health Liveness probe
GET /stats Knowledge graph statistics
POST /ingest Upload a resume (multipart/form-data)
GET /candidates List all candidates
GET /candidates/{id} Full candidate profile
GET /query/skill/{name} Find candidates by skill (GraphRAG)
POST /query/skills Find candidates matching ALL listed skills
GET /query/security Find Blue Team / SOC candidates
POST /evaluate Rank candidates against a JD

Neo4j Graph β€” Useful Queries

Open http://localhost:7474 and run these in the Cypher browser:

-- See the full graph
MATCH (c:Candidate)-[r]->(n) RETURN c, r, n

-- See one candidate's complete profile
MATCH (c:Candidate {id: 'CANDIDATE_XXXX'})-[r]->(n) RETURN c, r, n

-- Find all Python developers (ecosystem traversal)
MATCH (root:ProgrammingLanguage {name: 'Python'})
MATCH (related)-[:IS_FRAMEWORK_OF|IS_LIBRARY_OF*1..2]->(root)
WITH collect(related.name) + ['Python'] AS ecosystem
MATCH (c:Candidate)-[r]->(n) WHERE n.name IN ecosystem
RETURN DISTINCT c.id, collect(n.name) AS matched_skills

-- Rank candidates by skill count
MATCH (c:Candidate)-[r]->(n)
RETURN c.id, count(n) AS skill_count, collect(n.name)[..5] AS sample_skills
ORDER BY skill_count DESC

-- See the skill taxonomy
MATCH (child)-[r]->(parent)
WHERE child.taxonomy = true
RETURN child.name, type(r), parent.name
LIMIT 50

-- Check schema constraints
SHOW CONSTRAINTS

Environment Variables

Copy .env.example to .env and edit:

Variable Default Description
NEO4J_URI bolt://localhost:7687 Neo4j bolt connection
NEO4J_USER neo4j Neo4j username
NEO4J_PASSWORD supersecretpassword Neo4j password
TARGET_RESUME (path) Default resume for python main.py
GLINER_MODEL urchade/gliner_medium-v2.1 GLiNER model name
NER_THRESHOLD 0.40 Confidence threshold for entity extraction
MAX_UPLOAD_MB 20 API upload size limit
OLLAMA_URL http://localhost:11434 Ollama server URL
OLLAMA_MODEL deepseek-r1:8b Local LLM model for summaries

Security Features (Phase 5)

  • PII Redaction β€” names, phones, emails, URLs, locations removed before graph storage
  • Dynamic Allow-list β€” technical terms (e.g. "Python", "Firebase") are protected from being redacted by Presidio
  • SHA-256 Deduplication β€” same resume won't be processed twice unless --force is used
  • Prompt Injection Guard β€” API rejects JD text containing patterns like "ignore previous instructions"
  • Audit Logging β€” every API request logged to audit.log with timestamp, endpoint, client IP, status code, and response time
  • File Validation β€” only .pdf and .docx accepted, with configurable size limit

Roadmap (from RES-AI.docx)

Phase Status
Phase 1 β€” Infrastructure (Docker, Neo4j, Ollama) βœ… Manual setup (see Prerequisites)
Phase 2 β€” Secure Ingestion (Docling + GLiNER + Presidio + Neo4j) βœ… Complete
Phase 3 β€” GraphRAG & Skill Taxonomy βœ… Complete
Phase 4 β€” JD Evaluation (GLiNER + graph scoring + Ollama) βœ… Complete
Phase 5 β€” FastAPI + Audit Logging βœ… Complete
Next β€” Next.js Dashboard (visual skill graph) πŸ”œ Planned
Next β€” ELK Stack / Splunk SIEM integration πŸ”œ Planned
Next β€” DSPy BootstrapFewShot optimizer with golden examples πŸ”œ Planned

License

Private / Internal Use. All data processed locally β€” no external API calls.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages