34M parameter Korean PII detector — 3x smaller, beats the 111M v4.
Hybrid detection: the model handles person names and addresses, the SDK postprocessor handles structured patterns (phone numbers, ID numbers, dates, URLs). 136 MB, CPU-only.
Benchmark (benchmark_v2, 253 cases)
Compared against every public Korean PII model on HuggingFace (as of Aug 2026).
Model
Params
F1
P
R
OpenMed-PII-Korean-NomicMed-Large
395M
0.041
0.029
0.071
OpenMed-PII-Korean-QwenMed-XLarge
600M
0.084
0.061
0.138
LFM2.5-Encoder-350M-PII
350M
0.254
0.207
0.328
FrameByFrame/korean-pii-e5-base
~110M
0.435
0.319
0.684
seungkukim/korean-pii-masking-v2
~110M
0.553
0.672
0.470
vmaca123/korean-pii-ner-v3
~125M
0.569
0.810
0.439
schift-ko-pii-v4
111M
0.702
0.602
0.842
schift-ko-pii-v5
34M
0.823
0.812
0.834
All models evaluated raw (no postprocessing) except v4/v5 which use the SDK postprocessor (regex for structured patterns). v5 with postprocess disabled scores F1=0.578 (P=0.847, R=0.439) — still competitive, and the hybrid approach pushes it to #1.
Not included: bbanany/qwen25-3b-korean-pii-* (3B CausalLM, binary PII/NOT_PII classifier on pre-extracted spans — different task, not NER), upgle/bert-pii-korean and alphagyuu/* (no model weights uploaded), psh3333/* (gated), mncai/* (broken config).
v5 is 3x smaller than v4 and scores higher on the harder benchmark.
Raw model (no postprocess)
Model
Params
raw F1
raw P
raw R
LFM2.5-350M-PII
350M
0.254
0.207
0.328
schift-ko-pii-v4
111M
0.702
0.602
0.842
schift-ko-pii-v5
34M
0.578
0.847
0.439
v5 raw recall is low because the model only predicts private_person and private_address. All other categories (phone, email, dates, IDs) are handled by the regex postprocessor — by design, not by limitation.
Category breakdown (benchmark_v1, 93 cases)
Category
v5 (34M)
v4 (111M)
LFM2.5 (350M)
Person (standard)
1.00
1.00
0.67
Person (rare surnames)
1.00
1.00
0.60
Person (short names)
1.00
1.00
0.57
Address (urban)
1.00
1.00
0.67
Address (rural)
1.00
1.00
0.60
Phone (via postprocess)
0.86
0.86
0.92
Vehicle plate
1.00
1.00
0.00
Date (Korean)
1.00
1.00
0.00
Resident ID
1.00
1.00
0.75
Installation
pip install schift-ko-pii
Usage
1. Basic detection
python
1from schift_ko_pii import detect
23# Raw model output (person + address only)4spans = detect("피고 김민수의 전화번호는 010-1234-5678이다.")5for s in spans:6print(f" [{s['id']}] {s['label']}: {s['text']} (score: {s['score']})")7# [person_1] private_person: 김민수 (score: 0.99)89# With postprocessing — adds regex-based detection for phone, ID, dates, etc.10spans = detect("피고 김민수의 전화번호는 010-1234-5678이다.", postprocess=True)11# [person_1] private_person: 김민수12# [phone_1] phone_number: 010-1234-5678
2. Mask and review
python
1from schift_ko_pii import mask
23result = mask(4"피의자 김철수(주민번호 850205-1234567)가 피해자 박영희에게 "5"서울특별시 강남구 테헤란로 521에서 금 3,000만원을 전달하였다.",6 postprocess=True7)89print(result["masked"])10# 피의자 [사람1](주민번호 [주민번호1])가 피해자 [사람2]에게11# [주소1]에서 금 3,000만원을 전달하였다.1213# Entity map — review what was detected14for e in result["entities"]:15print(f" {e['id']:>15}: {e['text']}")16# person_1: 김철수17# resident_id_1: 850205-123456718# person_2: 박영희19# address_1: 서울특별시 강남구 테헤란로 521
3. Selective replacement
python
1from schift_ko_pii import mask,apply23text =("계약자 남궁혜진(010-9876-5432)의 거주지 "4"부산광역시 해운대구 우동 1414번지 마린시티 102동 305호에서 "5"참고인 Mike Johnson을 면담하였다.")67result = mask(text, postprocess=True)89# User reviews and decides what to redact10redacted =apply(text, result["entities"],{11"person_1":"○○○",# 남궁혜진 → ○○○12"person_2":"외국인A",# Mike Johnson → 외국인A13"phone_1":"010-****-****",14# address_1 intentionally left unmasked15})16print(redacted)17# 계약자 ○○○(010-****-****)의 거주지18# 부산광역시 해운대구 우동 1414번지 마린시티 102동 305호에서19# 참고인 외국인A을 면담하였다.
4. Bulk masking (replace all with ***)
python
1from schift_ko_pii import mask,apply23text ="피해자 이도(여권 M12345678)는 서울 서초구 반포대로 58에 거주한다."4result = mask(text, postprocess=True)56# Replace everything with ***7clean =apply(text, result["entities"])8# 피해자 ***(여권 ***)는 ***에 거주한다.
1from schift_ko_pii import mask,apply23withopen("document.txt")as f:4 text = f.read()56result = mask(text, postprocess=True)78# Show what was found9print(f"Found {len(result['entities'])} PII entities:")10for e in result["entities"]:11print(f" {e['id']}: {e['text']}")1213# Redact all and save14clean =apply(text, result["entities"])15withopen("document_redacted.txt","w")as f:16 f.write(clean)
API (free, no model download needed)
python
1from schift import Schift
23client = Schift(api_key="...")# free at schift.io4result = client.pii.redact("김민수의 전화번호는 010-1234-5678입니다.")5# Postprocessing is always enabled on the API.
Labels
Label
Description
Detected by
Examples
private_person
Person names (Korean, Hanja, foreign)
Model
김민수, 남궁혜진, Mike Johnson, 田中太郎
private_address
Street/postal addresses
Model
서울특별시 강남구 테헤란로 521
phone_number
Phone numbers
Postprocess (regex)
010-1234-5678, 02-1234-5678
resident_id
Resident registration numbers
Postprocess (regex + checksum)
850205-1234567
account_number
Bank accounts, passport, vehicle plates, business IDs
Schift License v2.0 — Apache 2.0 base with revenue threshold.
Free for everyone under $10M annual revenue. Research, education, and non-profit always permitted.
Citation
bibtex
1@software{schift_ko_pii_v5_2026,
2 author = {Schift Inc.},
3 title = {schift-ko-pii-v5: 34M Korean PII Detection Model},
4 year = {2026},
5 url = {https://huggingface.co/schift-io/schift-ko-pii-v5},
6}