dpowale/GLiNER-MultiLingual-PII_PHI

3

stars

39

commits

Python

primary language

Feb 2, 2026

updated

README

GLiNER MultiLingual PII/PHI Extraction Service

Introduction

GLiNER (Generalist Model for Named Entity Recognition) is a zero-shot NER model that can identify any entity type described in plain text at inference time. The urchade/gliner_multi_pii-v1 model is fine-tuned specifically to detect PII & PHI across multiple languages.

Why GLiNER over LLMs for NER?

  • ⚑ Efficiency - ~300M parameters vs LLMs' 7B-175B+. Runs on modest CPUs/GPUs with low latency for real-time, high-volume processing.
  • πŸ’° Cost - No expensive A100/H100 GPUs or per-token API costs. Handles long documents predictably as an encoder-based model.
  • 🎯 Precision - Span-based extraction returns exact character offsets from the source text. No hallucinations, no "cleaned up" outputs, thus guarantees the exact string as it appears.
  • πŸ”’ Privacy - Lightweight model to run entirely on-premise. Data never leaves your infrastructure, avoiding GDPR/HIPAA compliance issues with LLM providers.
  • πŸ“‹ Structured Output - Natively returns entity text, label, and start/end indices. No complex prompting or "instructor" libraries needed.

Features

  • 🌍 Multilingual Support - English, French, German, Spanish, and Italian
  • πŸ” 50+ Entity Types - Person, email, phone, SSN, address, medical conditions, etc.
  • ⚑ Fast API - RESTful endpoints with automatic documentation
  • 🎨 Streamlit UI - UI to test entity detection and adjust confidence levels for testing
  • πŸ–₯️ Cross-Platform - Setup works on Windows, Linux, and macOS

Supported Entity Types

CategoryEntity Types
Personalperson, date_of_birth
Contactemail, phone_number, mobile_phone_number, fax_number, address
Financialcredit_card_number, credit_card_cvv, bank_account_number, iban, transaction_number
Government IDssocial_security_number, passport_number, driver_license_number, tax_identification_number, national_id_number, identity_card_number, cpf
Medicalmedical_condition, medication, health_insurance_id_number, medical_record_number
Travelflight_number, passport_expiration_date, vehicle_registration_number, license_plate_number
Digitalemail_address, ip_address, username, password, social_media_handle, digital_signature
Otherorganization, insurance_number, student_id_number, security_code, landline_phone_number

Quick Start

A FastAPI service for extracting from text using the GLiNER Multi-PII Model.

Step 1: Setup Clone the Repo
git clone <repository-url> GLiNER_MultiLingual_PII_PHI
cd GLiNER_MultiLingual_PII_PHI
Install uv (if not installed)

Windows (PowerShell):

pip install uv

Linux/macOS:

curl -LsSf https://astral.sh/uv/install.sh | sh

Or with pip:

pip install uv
Create Virtual Environment

Windows:

uv venv
.venv\Scripts\activate

Linux/macOS:

uv venv
source .venv/bin/activate
Install Dependencies
uv pip install -r requirements.txt
πŸ“ Project Structure
GLiNER_MultiLingual_PII_PHI/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main_service.py          # FastAPI service
β”‚   └── streamlit_app.py         # Streamlit web UI for testing
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ data_gen.py              # Dataset generation script
β”‚   β”œβ”€β”€ medical_phi_dataset.json # Medical PHI evaluation data
β”‚   β”œβ”€β”€ mixed_language_dataset.json # Multilingual evaluation data
β”‚   β”œβ”€β”€ ner_evaluation_dataset.json # NER evaluation dataset
β”‚   β”œβ”€β”€ structured_pii_phi.csv   # Structured CSV evaluation data
β”‚   └── travel_pii_dataset.json  # Travel PII evaluation data
β”œβ”€β”€ evals/
β”‚   β”œβ”€β”€ evaluation.py            # Evaluation script
β”‚   β”œβ”€β”€ evaluation_service.py    # NER evaluation service
β”‚   └── evaluation_report.json   # Generated evaluation report
β”œβ”€β”€ tests/
β”‚   └── test_extraction.py       # Pytest test cases
β”œβ”€β”€ screenshots/                 # UI screenshots
β”œβ”€β”€ requirements.txt             # Python dependencies
β”œβ”€β”€ README.md                    # This file
└── .venv/                       # Virtual environment
Step 2: Service Details and Testing Start the Service ```bash python src/main_service.py ```

Or with uvicorn directly:

cd src && uvicorn main_service:app --host 127.0.0.1 --port 8000 --reload

You should see:

INFO:     Loading GLiNER PII model...
INFO:     Model loaded successfully
INFO:     Uvicorn running on http://127.0.0.1:8000
INFO:     Application startup complete.
Test the Service

Option A: Open API Docs in Browser

http://127.0.0.1:8000/docs

Option B: Test with curl (Linux/macOS/Windows)

# Health check
curl http://127.0.0.1:8000/health

# Extract PII
curl -X POST "http://127.0.0.1:8000/extract" \
  -H "Content-Type: application/json" \
  -d '{"text":"John Smith email is john@test.com and phone is 555-123-4567"}'

Option C: Test with PowerShell (Windows)

# Health check
Invoke-RestMethod -Uri "http://127.0.0.1:8000/health"

# Extract PII
$body = '{"text":"John Smith email is john@test.com and phone is 555-123-4567"}'
Invoke-RestMethod -Uri "http://127.0.0.1:8000/extract" -Method Post -Body $body -ContentType "application/json"

Option D: Streamlit Web UI

For an interactive web interface, run the Streamlit app:

# Make sure the FastAPI service is running first, then:
python -m streamlit run src/streamlit_app.py

Open http://localhost:8501 in your browser.

πŸ”Œ API Endpoints
MethodEndpointDescription
GET/API info
GET/healthHealth check
GET/entitiesList supported entity types
GET/docsSwagger UI documentation
POST/extractExtract PII entities from text
Step 3: API Details & Example Request/Response

Request:

{
  "text": "Contact John Smith at john.smith@email.com or call 555-123-4567",
  "threshold": 0.5
}

Response:

{
  "entities": [
    {"text": "John Smith", "label": "person", "start": 8, "end": 18, "score": 0.98},
    {"text": "john.smith@email.com", "label": "email", "start": 22, "end": 42, "score": 0.99},
    {"text": "555-123-4567", "label": "phone number", "start": 51, "end": 63, "score": 0.96}
  ],
  "text": "Contact John Smith at john.smith@email.com or call 555-123-4567",
  "entity_count": 3,
  "entity_types": {"person": 1, "email": 1, "phone number": 1}
}
πŸ€– Model Information

Cache Location:

OSPath
WindowsC:\Users\<username>\.cache\huggingface\hub\models--urchade--gliner_multi_pii-v1
Linux~/.cache/huggingface/hub/models--urchade--gliner_multi_pii-v1
macOS~/.cache/huggingface/hub/models--urchade--gliner_multi_pii-v1
πŸ”§ Troubleshooting
IssueSolution
Model not loadedWait for startup to complete or check disk space
Connection refusedEnsure service is running on port 8000
Import errorRun uv pip install -r requirements.txt
CUDA out of memoryModel runs on CPU by default
Permission denied (Linux)Run chmod +x or check file permissions
uv not foundRestart terminal after installing uv
βš™οΈ Environment Variables (Optional)
# Set custom Hugging Face cache directory
export HF_HOME=/path/to/cache  # Linux/macOS
set HF_HOME=C:\path\to\cache   # Windows

# Disable symlinks (Windows - fixes download errors)
set HF_HUB_DISABLE_SYMLINKS_WARNING=1
🐳 Docker (Optional)
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install uv && uv pip install --system -r requirements.txt

COPY main_service.py .
EXPOSE 8000

CMD ["uvicorn", "main_service:app", "--host", "0.0.0.0", "--port", "8000"]

Build and run:

docker build -t gliner-pii .
docker run -p 8000:8000 gliner-pii
Step 4: Run Tests
# Activate virtual environment
# Windows:
.venv\Scripts\activate
# Linux/macOS:
source .venv/bin/activate

# Run all tests
python -m pytest tests/test_extraction.py -v

# Run specific test class
python -m pytest tests/test_extraction.py::TestPersonExtraction -v

# Run multilingual tests
python -m pytest tests/test_extraction.py::TestMultilingualParagraphs -v

# Run with short traceback
python -m pytest tests/test_extraction.py -v --tb=short
Step 5: Start Streamlit UI

The Streamlit app provides an interactive interface for testing the PII extraction service:

Features

  • Service Health Check - Real-time connection status to the FastAPI backend
  • Configurable Threshold - Slider to adjust detection sensitivity (0.0-1.0)
  • Entity Type Selection - Choose specific PII/PHI types or select all
  • Sample Texts - Pre-loaded examples (Medical Record, Financial Document, Business Contact, International Document)
  • Results Display - Summary metrics, entity breakdown, and detailed entity list with confidence scores
  • Highlighted Text View - Visual color-coded highlighting of detected entities
  • Raw JSON Output - Expandable section with the full API response

Running the Streamlit App

Windows:

# Terminal 1: Start FastAPI service
python src/main_service.py

# Terminal 2: Start Streamlit app
python -m streamlit run src/streamlit_app.py

Linux/macOS:

# Terminal 1: Start FastAPI service
source .venv/bin/activate
python src/main_service.py

# Terminal 2: Start Streamlit app
source .venv/bin/activate
python -m streamlit run src/streamlit_app.py

Screenshot

Streamlit PII Extraction UI

The UI includes:

  • Left panel: Input text area with sample text selector
  • Right panel: Extraction results with entity details
  • Bottom: Highlighted text with color-coded entities and legend

To add the screenshot: Run the Streamlit app, take a screenshot, and save it as screenshots/streamlit_app.png

Evals & Data Generation Tool

Performance by Language

NER evaluation dataset (360 samples) shows strong multilingual performance:

LanguageSamplesPositiveNegativePrecisionRecallF1 Score
Portuguese6050100.89340.94120.9167
French6050100.86870.95030.9077
Spanish6050100.86430.94510.9029
English6050100.87130.92630.8980
Italian6050100.84160.94440.8901
German6050100.81730.89940.8564

Overall: Precision: 0.8594 | Recall: 0.9345 | F1 Score: 0.8954

Running Evaluation There are two evaluation scripts with different purposes:
  • evaluation_service.py β†’ Creates detailed evaluation_report.json with language breakdowns and failure analysis
  • evaluation.py β†’ Creates per-dataset predictions_*.csv and predictions_*.json files in data/predicted_output/ with raw predictions
# Run the main evaluation script (generates prediction files for all datasets)
python evals/evaluation.py

# Run the NER evaluation service with detailed report
python evals/evaluation_service.py --dataset data/ner_evaluation_dataset.json --output evals/evaluation_report.json --verbose
Datasets Generation

This project includes tools for generating synthetic test datasets.

Data Generation (data_gen.py)

Generate synthetic multilingual NER datasets for testing PII/PHI extraction.

Features:

  • 30 template variations per language for diverse sentence structures
  • 50 positive samples per language (sentences with PII entities)
  • 10 negative samples per language (clean sentences without PII)
  • 30 entity types with realistic synthetic data
  • Automatic position tracking for entity spans

Usage:

python data/data_gen.py

Output: ner_evaluation_dataset.json with 360 samples (300 positive, 60 negative)

Dataset Format:

{
  "language": "English",
  "text": "Patient John Doe, born 15/03/1985, diagnosed with Diabetes Type 2...",
  "entities": [
    {"text": "John Doe", "label": "person", "start": 8, "end": 16},
    {"text": "15/03/1985", "label": "date_of_birth", "start": 23, "end": 33},
    {"text": "Diabetes Type 2", "label": "medical_condition", "start": 50, "end": 65}
  ]
}
DatasetExamplesDescription
Structured CSV50Comma-separated PII/PHI records
Medical PHI60Clinical/healthcare scenarios (6 languages)
NER Evaluation (Original)360Multilingual baseline (300 positive, 60 negative)
Mixed Language51Code-switching multilingual text (2-6 languages per example)
Travel PII60Air/water/land travel with passport, driver's license, visa
1. Structured CSV (F1: 0.855) βœ… Best
LabelTPFPFNPrecisionRecallF1
person50001.0001.0001.000
address50001.0001.0001.000
phone_number50200.9621.0000.980
email50500.9091.0000.952
date_of_birth43071.0000.8600.925
medical_condition47930.8390.9400.887
medication403100.9300.8000.860
national_id_number40461.0000.0800.148
2. Medical PHI (F1: 0.763)
LabelTPFPFNPrecisionRecallF1
organization5710120.8510.8260.838
location323120.9140.7270.810
person9524220.7980.8120.805
date250131.0000.6580.794
medication16540.7620.8000.780
medical_condition3621160.6320.6920.661
3. NER Evaluation - Original (F1: 0.709)
LabelTPFPFNPrecisionRecallF1
medical_condition42001.0001.0001.000
medication42001.0001.0001.000
address54100.9821.0000.991
date_of_birth40021.0000.9520.976
transaction_number35110.9720.9720.972
passport_number40220.9520.9520.952
credit_card_number35510.8750.9720.921
fax_number36700.8371.0000.911
flight_number35770.8330.8330.833
person1637050.7000.9700.813
bank_account_number17710.7080.9440.810
iban12061.0000.6670.800
mobile_phone_number310171.0000.6460.785
credit_card_cvv221140.9570.6110.746
social_security_number223260.8800.4580.603
national_id_number2422120.5220.6670.585
organization518090.3890.8500.534
license_plate_number114190.7330.3670.489
vehicle_registration_number818220.3080.2670.286
student_id_number00360.0000.0000.000
4. Mixed Language (F1: 0.633)
LabelTPFPFNPrecisionRecallF1
passport_number10001.0001.0001.000
medical_condition8001.0001.0001.000
tax_identification_number3001.0001.0001.000
driver_license_number2001.0001.0001.000
phone_number21100.9551.0000.977
email12100.9231.0000.960
organization11011.0000.9170.957
date_of_birth130141.0000.4810.650
transaction_number3041.0000.4290.600
flight_number5340.6250.5560.588
person3123230.5740.5740.574
address110181.0000.3790.550
medication3660.3330.3330.333
credit_card_number2550.2860.2860.286
5. Travel PII (F1: 0.442)
LabelTPFPFNPrecisionRecallF1
phone_number12001.0001.0001.000
mobile_phone_number6001.0001.0001.000
email7001.0001.0001.000
passport_expiration_date7001.0001.0001.000
insurance_number6001.0001.0001.000
credit_card_number11200.8461.0000.917
passport_number28330.9030.9030.903
driver_license_number13360.8120.6840.743
bank_account_number3031.0000.5000.667
person3624240.6000.6000.600
organization1814150.5620.5450.554
identity_card_number5091.0000.3570.526
vehicle_registration_number41220.2500.6670.364
flight_number51370.2780.4170.333
date_of_birth80491.0000.1400.246
address02950.0000.0000.000
transaction_number00110.0000.0000.000
πŸ“ˆ Entity Performance Across Datasets
Entity TypeStructured CSVMedical PHINER OriginalMixed LangTravel PII
person1.0000.8050.8130.5740.600
address1.000-0.9910.5500.000
phone_number0.980--0.9771.000
email0.952--0.9601.000
passport_number--0.9521.0000.903
medical_condition0.8870.6611.0001.000-
medication0.8600.7801.0000.333-
βœ… Best Performing Entity Types
  • βœ… phone_number / email - Highly reliable across all contexts
  • βœ… passport_number - Strong performance (0.90+)
  • βœ… medical_condition - Excellent in medical/structured contexts
⚠️ Challenging Entity Types
  • ⚠️ person - Variable performance (0.57-1.00) depending on context
  • ⚠️ address - Poor in travel context, excellent in structured data
  • ❌ student_id_number - Not recognized by model
  • ❌ transaction_number - Inconsistent across datasets
🚨 Known Limitations
  1. Organization over-detection: Model tends to identify non-organization text as organizations
  2. Student ID not recognized: Model doesn't support student_id_number label
  3. Address extraction in travel: Struggles with complex international addresses
  4. ID format confusion: Various national ID formats get misclassified

License

MIT License

References

Contributors

dpowale

39 commits

dpowale/GLiNER-MultiLingual-PII_PHI

3

stars

39

commits

Python

primary language

Feb 2, 2026

updated

README

GLiNER MultiLingual PII/PHI Extraction Service

Introduction

GLiNER (Generalist Model for Named Entity Recognition) is a zero-shot NER model that can identify any entity type described in plain text at inference time. The urchade/gliner_multi_pii-v1 model is fine-tuned specifically to detect PII & PHI across multiple languages.

Why GLiNER over LLMs for NER?

  • ⚑ Efficiency - ~300M parameters vs LLMs' 7B-175B+. Runs on modest CPUs/GPUs with low latency for real-time, high-volume processing.
  • πŸ’° Cost - No expensive A100/H100 GPUs or per-token API costs. Handles long documents predictably as an encoder-based model.
  • 🎯 Precision - Span-based extraction returns exact character offsets from the source text. No hallucinations, no "cleaned up" outputs, thus guarantees the exact string as it appears.
  • πŸ”’ Privacy - Lightweight model to run entirely on-premise. Data never leaves your infrastructure, avoiding GDPR/HIPAA compliance issues with LLM providers.
  • πŸ“‹ Structured Output - Natively returns entity text, label, and start/end indices. No complex prompting or "instructor" libraries needed.

Features

  • 🌍 Multilingual Support - English, French, German, Spanish, and Italian
  • πŸ” 50+ Entity Types - Person, email, phone, SSN, address, medical conditions, etc.
  • ⚑ Fast API - RESTful endpoints with automatic documentation
  • 🎨 Streamlit UI - UI to test entity detection and adjust confidence levels for testing
  • πŸ–₯️ Cross-Platform - Setup works on Windows, Linux, and macOS

Supported Entity Types

CategoryEntity Types
Personalperson, date_of_birth
Contactemail, phone_number, mobile_phone_number, fax_number, address
Financialcredit_card_number, credit_card_cvv, bank_account_number, iban, transaction_number
Government IDssocial_security_number, passport_number, driver_license_number, tax_identification_number, national_id_number, identity_card_number, cpf
Medicalmedical_condition, medication, health_insurance_id_number, medical_record_number
Travelflight_number, passport_expiration_date, vehicle_registration_number, license_plate_number
Digitalemail_address, ip_address, username, password, social_media_handle, digital_signature
Otherorganization, insurance_number, student_id_number, security_code, landline_phone_number

Quick Start

A FastAPI service for extracting from text using the GLiNER Multi-PII Model.

Step 1: Setup Clone the Repo
git clone <repository-url> GLiNER_MultiLingual_PII_PHI
cd GLiNER_MultiLingual_PII_PHI
Install uv (if not installed)

Windows (PowerShell):

pip install uv

Linux/macOS:

curl -LsSf https://astral.sh/uv/install.sh | sh

Or with pip:

pip install uv
Create Virtual Environment

Windows:

uv venv
.venv\Scripts\activate

Linux/macOS:

uv venv
source .venv/bin/activate
Install Dependencies
uv pip install -r requirements.txt
πŸ“ Project Structure
GLiNER_MultiLingual_PII_PHI/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main_service.py          # FastAPI service
β”‚   └── streamlit_app.py         # Streamlit web UI for testing
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ data_gen.py              # Dataset generation script
β”‚   β”œβ”€β”€ medical_phi_dataset.json # Medical PHI evaluation data
β”‚   β”œβ”€β”€ mixed_language_dataset.json # Multilingual evaluation data
β”‚   β”œβ”€β”€ ner_evaluation_dataset.json # NER evaluation dataset
β”‚   β”œβ”€β”€ structured_pii_phi.csv   # Structured CSV evaluation data
β”‚   └── travel_pii_dataset.json  # Travel PII evaluation data
β”œβ”€β”€ evals/
β”‚   β”œβ”€β”€ evaluation.py            # Evaluation script
β”‚   β”œβ”€β”€ evaluation_service.py    # NER evaluation service
β”‚   └── evaluation_report.json   # Generated evaluation report
β”œβ”€β”€ tests/
β”‚   └── test_extraction.py       # Pytest test cases
β”œβ”€β”€ screenshots/                 # UI screenshots
β”œβ”€β”€ requirements.txt             # Python dependencies
β”œβ”€β”€ README.md                    # This file
└── .venv/                       # Virtual environment
Step 2: Service Details and Testing Start the Service ```bash python src/main_service.py ```

Or with uvicorn directly:

cd src && uvicorn main_service:app --host 127.0.0.1 --port 8000 --reload

You should see:

INFO:     Loading GLiNER PII model...
INFO:     Model loaded successfully
INFO:     Uvicorn running on http://127.0.0.1:8000
INFO:     Application startup complete.
Test the Service

Option A: Open API Docs in Browser

http://127.0.0.1:8000/docs

Option B: Test with curl (Linux/macOS/Windows)

# Health check
curl http://127.0.0.1:8000/health

# Extract PII
curl -X POST "http://127.0.0.1:8000/extract" \
  -H "Content-Type: application/json" \
  -d '{"text":"John Smith email is john@test.com and phone is 555-123-4567"}'

Option C: Test with PowerShell (Windows)

# Health check
Invoke-RestMethod -Uri "http://127.0.0.1:8000/health"

# Extract PII
$body = '{"text":"John Smith email is john@test.com and phone is 555-123-4567"}'
Invoke-RestMethod -Uri "http://127.0.0.1:8000/extract" -Method Post -Body $body -ContentType "application/json"

Option D: Streamlit Web UI

For an interactive web interface, run the Streamlit app:

# Make sure the FastAPI service is running first, then:
python -m streamlit run src/streamlit_app.py

Open http://localhost:8501 in your browser.

πŸ”Œ API Endpoints
MethodEndpointDescription
GET/API info
GET/healthHealth check
GET/entitiesList supported entity types
GET/docsSwagger UI documentation
POST/extractExtract PII entities from text
Step 3: API Details & Example Request/Response

Request:

{
  "text": "Contact John Smith at john.smith@email.com or call 555-123-4567",
  "threshold": 0.5
}

Response:

{
  "entities": [
    {"text": "John Smith", "label": "person", "start": 8, "end": 18, "score": 0.98},
    {"text": "john.smith@email.com", "label": "email", "start": 22, "end": 42, "score": 0.99},
    {"text": "555-123-4567", "label": "phone number", "start": 51, "end": 63, "score": 0.96}
  ],
  "text": "Contact John Smith at john.smith@email.com or call 555-123-4567",
  "entity_count": 3,
  "entity_types": {"person": 1, "email": 1, "phone number": 1}
}
πŸ€– Model Information

Cache Location:

OSPath
WindowsC:\Users\<username>\.cache\huggingface\hub\models--urchade--gliner_multi_pii-v1
Linux~/.cache/huggingface/hub/models--urchade--gliner_multi_pii-v1
macOS~/.cache/huggingface/hub/models--urchade--gliner_multi_pii-v1
πŸ”§ Troubleshooting
IssueSolution
Model not loadedWait for startup to complete or check disk space
Connection refusedEnsure service is running on port 8000
Import errorRun uv pip install -r requirements.txt
CUDA out of memoryModel runs on CPU by default
Permission denied (Linux)Run chmod +x or check file permissions
uv not foundRestart terminal after installing uv
βš™οΈ Environment Variables (Optional)
# Set custom Hugging Face cache directory
export HF_HOME=/path/to/cache  # Linux/macOS
set HF_HOME=C:\path\to\cache   # Windows

# Disable symlinks (Windows - fixes download errors)
set HF_HUB_DISABLE_SYMLINKS_WARNING=1
🐳 Docker (Optional)
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install uv && uv pip install --system -r requirements.txt

COPY main_service.py .
EXPOSE 8000

CMD ["uvicorn", "main_service:app", "--host", "0.0.0.0", "--port", "8000"]

Build and run:

docker build -t gliner-pii .
docker run -p 8000:8000 gliner-pii
Step 4: Run Tests
# Activate virtual environment
# Windows:
.venv\Scripts\activate
# Linux/macOS:
source .venv/bin/activate

# Run all tests
python -m pytest tests/test_extraction.py -v

# Run specific test class
python -m pytest tests/test_extraction.py::TestPersonExtraction -v

# Run multilingual tests
python -m pytest tests/test_extraction.py::TestMultilingualParagraphs -v

# Run with short traceback
python -m pytest tests/test_extraction.py -v --tb=short
Step 5: Start Streamlit UI

The Streamlit app provides an interactive interface for testing the PII extraction service:

Features

  • Service Health Check - Real-time connection status to the FastAPI backend
  • Configurable Threshold - Slider to adjust detection sensitivity (0.0-1.0)
  • Entity Type Selection - Choose specific PII/PHI types or select all
  • Sample Texts - Pre-loaded examples (Medical Record, Financial Document, Business Contact, International Document)
  • Results Display - Summary metrics, entity breakdown, and detailed entity list with confidence scores
  • Highlighted Text View - Visual color-coded highlighting of detected entities
  • Raw JSON Output - Expandable section with the full API response

Running the Streamlit App

Windows:

# Terminal 1: Start FastAPI service
python src/main_service.py

# Terminal 2: Start Streamlit app
python -m streamlit run src/streamlit_app.py

Linux/macOS:

# Terminal 1: Start FastAPI service
source .venv/bin/activate
python src/main_service.py

# Terminal 2: Start Streamlit app
source .venv/bin/activate
python -m streamlit run src/streamlit_app.py

Screenshot

Streamlit PII Extraction UI

The UI includes:

  • Left panel: Input text area with sample text selector
  • Right panel: Extraction results with entity details
  • Bottom: Highlighted text with color-coded entities and legend

To add the screenshot: Run the Streamlit app, take a screenshot, and save it as screenshots/streamlit_app.png

Evals & Data Generation Tool

Performance by Language

NER evaluation dataset (360 samples) shows strong multilingual performance:

LanguageSamplesPositiveNegativePrecisionRecallF1 Score
Portuguese6050100.89340.94120.9167
French6050100.86870.95030.9077
Spanish6050100.86430.94510.9029
English6050100.87130.92630.8980
Italian6050100.84160.94440.8901
German6050100.81730.89940.8564

Overall: Precision: 0.8594 | Recall: 0.9345 | F1 Score: 0.8954

Running Evaluation There are two evaluation scripts with different purposes:
  • evaluation_service.py β†’ Creates detailed evaluation_report.json with language breakdowns and failure analysis
  • evaluation.py β†’ Creates per-dataset predictions_*.csv and predictions_*.json files in data/predicted_output/ with raw predictions
# Run the main evaluation script (generates prediction files for all datasets)
python evals/evaluation.py

# Run the NER evaluation service with detailed report
python evals/evaluation_service.py --dataset data/ner_evaluation_dataset.json --output evals/evaluation_report.json --verbose
Datasets Generation

This project includes tools for generating synthetic test datasets.

Data Generation (data_gen.py)

Generate synthetic multilingual NER datasets for testing PII/PHI extraction.

Features:

  • 30 template variations per language for diverse sentence structures
  • 50 positive samples per language (sentences with PII entities)
  • 10 negative samples per language (clean sentences without PII)
  • 30 entity types with realistic synthetic data
  • Automatic position tracking for entity spans

Usage:

python data/data_gen.py

Output: ner_evaluation_dataset.json with 360 samples (300 positive, 60 negative)

Dataset Format:

{
  "language": "English",
  "text": "Patient John Doe, born 15/03/1985, diagnosed with Diabetes Type 2...",
  "entities": [
    {"text": "John Doe", "label": "person", "start": 8, "end": 16},
    {"text": "15/03/1985", "label": "date_of_birth", "start": 23, "end": 33},
    {"text": "Diabetes Type 2", "label": "medical_condition", "start": 50, "end": 65}
  ]
}
DatasetExamplesDescription
Structured CSV50Comma-separated PII/PHI records
Medical PHI60Clinical/healthcare scenarios (6 languages)
NER Evaluation (Original)360Multilingual baseline (300 positive, 60 negative)
Mixed Language51Code-switching multilingual text (2-6 languages per example)
Travel PII60Air/water/land travel with passport, driver's license, visa
1. Structured CSV (F1: 0.855) βœ… Best
LabelTPFPFNPrecisionRecallF1
person50001.0001.0001.000
address50001.0001.0001.000
phone_number50200.9621.0000.980
email50500.9091.0000.952
date_of_birth43071.0000.8600.925
medical_condition47930.8390.9400.887
medication403100.9300.8000.860
national_id_number40461.0000.0800.148
2. Medical PHI (F1: 0.763)
LabelTPFPFNPrecisionRecallF1
organization5710120.8510.8260.838
location323120.9140.7270.810
person9524220.7980.8120.805
date250131.0000.6580.794
medication16540.7620.8000.780
medical_condition3621160.6320.6920.661
3. NER Evaluation - Original (F1: 0.709)
LabelTPFPFNPrecisionRecallF1
medical_condition42001.0001.0001.000
medication42001.0001.0001.000
address54100.9821.0000.991
date_of_birth40021.0000.9520.976
transaction_number35110.9720.9720.972
passport_number40220.9520.9520.952
credit_card_number35510.8750.9720.921
fax_number36700.8371.0000.911
flight_number35770.8330.8330.833
person1637050.7000.9700.813
bank_account_number17710.7080.9440.810
iban12061.0000.6670.800
mobile_phone_number310171.0000.6460.785
credit_card_cvv221140.9570.6110.746
social_security_number223260.8800.4580.603
national_id_number2422120.5220.6670.585
organization518090.3890.8500.534
license_plate_number114190.7330.3670.489
vehicle_registration_number818220.3080.2670.286
student_id_number00360.0000.0000.000
4. Mixed Language (F1: 0.633)
LabelTPFPFNPrecisionRecallF1
passport_number10001.0001.0001.000
medical_condition8001.0001.0001.000
tax_identification_number3001.0001.0001.000
driver_license_number2001.0001.0001.000
phone_number21100.9551.0000.977
email12100.9231.0000.960
organization11011.0000.9170.957
date_of_birth130141.0000.4810.650
transaction_number3041.0000.4290.600
flight_number5340.6250.5560.588
person3123230.5740.5740.574
address110181.0000.3790.550
medication3660.3330.3330.333
credit_card_number2550.2860.2860.286
5. Travel PII (F1: 0.442)
LabelTPFPFNPrecisionRecallF1
phone_number12001.0001.0001.000
mobile_phone_number6001.0001.0001.000
email7001.0001.0001.000
passport_expiration_date7001.0001.0001.000
insurance_number6001.0001.0001.000
credit_card_number11200.8461.0000.917
passport_number28330.9030.9030.903
driver_license_number13360.8120.6840.743
bank_account_number3031.0000.5000.667
person3624240.6000.6000.600
organization1814150.5620.5450.554
identity_card_number5091.0000.3570.526
vehicle_registration_number41220.2500.6670.364
flight_number51370.2780.4170.333
date_of_birth80491.0000.1400.246
address02950.0000.0000.000
transaction_number00110.0000.0000.000
πŸ“ˆ Entity Performance Across Datasets
Entity TypeStructured CSVMedical PHINER OriginalMixed LangTravel PII
person1.0000.8050.8130.5740.600
address1.000-0.9910.5500.000
phone_number0.980--0.9771.000
email0.952--0.9601.000
passport_number--0.9521.0000.903
medical_condition0.8870.6611.0001.000-
medication0.8600.7801.0000.333-
βœ… Best Performing Entity Types
  • βœ… phone_number / email - Highly reliable across all contexts
  • βœ… passport_number - Strong performance (0.90+)
  • βœ… medical_condition - Excellent in medical/structured contexts
⚠️ Challenging Entity Types
  • ⚠️ person - Variable performance (0.57-1.00) depending on context
  • ⚠️ address - Poor in travel context, excellent in structured data
  • ❌ student_id_number - Not recognized by model
  • ❌ transaction_number - Inconsistent across datasets
🚨 Known Limitations
  1. Organization over-detection: Model tends to identify non-organization text as organizations
  2. Student ID not recognized: Model doesn't support student_id_number label
  3. Address extraction in travel: Struggles with complex international addresses
  4. ID format confusion: Various national ID formats get misclassified

License

MIT License

References

Contributors

dpowale

39 commits

Languages

Python

100.0%