Skip to main content

language: ko license: other license_name: schift-2.0 license_link: LICENSE library_name: transformers pipeline_tag: token-classification tags:

  • pii
  • korean
  • ner
  • privacy
  • token-classification datasets:
  • custom

schift-ko-pii-v6

34.1M parameter Korean PII detector built on a dual-path LoRA encoder.

The 0.4.0 release keeps the v6 detector contract and adds an optional, typed selective-adoption flow for structured and contextual categories. The base install does not install ko-pii; install the extended extra only when those additional deterministic categories are needed.

Release status

This source tree prepares schift-ko-pii 0.4.0. The previously published baseline was 0.3.3. The Cloud Run ONNX service under services/pii is a separate deployment lane; this package does not bundle its ONNX artifacts.

Quick start

pip install schift-ko-pii

The original detector API remains available:

from schift_ko_pii import detect

spans = detect("피고 김민수의 전화번호는 010-1234-5678이다.")
# [
#   {"start": 3, "end": 6, "label": "private_person", ...},
#   {"start": 14, "end": 27, "label": "private_phone", ...},
# ]

For a typed operational result, use the selective-adoption flow:

from schift_ko_pii import AnalysisConfig, ProcessingMode, analyze_text

result = analyze_text(
    "피고 김민수의 전화번호는 010-1234-5678이다.",
    config=AnalysisConfig(mode=ProcessingMode.PERMISSIVE),
)

# The result contains typed detections, policy actions, BLOCK-only masking,
# counts, and a metadata-only review queue. It has no separate source-text
# field; its policy text can still preserve REVIEW/ALLOW spans for operators.
print(result.summary)
print(result.masking.masked_text)
print(result.review_items())

Selective-adoption flow

The public workflow is deliberately ordered:

detect -> assess -> BLOCK-only masking -> review queue

analyze_text() or analyze() runs detection, sends non-sensitive detection metadata to assess(), and masks only spans whose action is Action.BLOCK. Action.REVIEW detections remain unmasked and are represented by ReviewItem values in PiiResult.review_queue; callers can create a typed FeedbackPatch with propose_feedback_patch() without persisting raw PII. Action.ALLOW detections are retained in the typed result but are not masked. The resulting masking.masked_text is therefore a policy output, not a safe untrusted-egress string: use a caller-owned all-span redaction step before sending it to logs, external APIs, or other untrusted surfaces.

Detector confidence and operational risk are separate. ProcessingMode sets the action thresholds:

Mode BLOCK threshold REVIEW threshold
AUDIT never blocks all detections are allowed for audit output
PERMISSIVE CRITICAL risk at score >= 0.95 HIGH risk at score >= 0.70
STRICT MEDIUM risk at score >= 0.70 LOW risk at score >= 0.50
BALANCED HIGH risk at score >= 0.80 MEDIUM risk at score >= 0.60
PARANOID LOW risk at score >= 0.50 all lower-risk detections

PERMISSIVE is an action-policy choice, not a change to the v6 detector's score_threshold. Use AnalysisConfig.score_threshold separately when configuring detection.

Extended profiles (opt-in)

pip install "schift-ko-pii[extended]"

The optional adapter is enabled per request:

from schift_ko_pii import AnalysisConfig, analyze_text

result = analyze_text(
    "사업자등록번호 104-81-49532, 직책 팀장",
    config=AnalysisConfig(extended=True, extended_profile="contextual"),
)

extended_profile="structured" adopts deterministic identifier and anchor categories such as business/corporate registration numbers, medical insurance and prescription identifiers, PNU, postal code, fax, employee, document, petition, and drug IDs. extended_profile="contextual" includes that structured set plus contextual attributes such as nationality, birth date, education, major, position, age, height, and weight.

The taxonomy registry is exposed through LABELS, STRUCTURED_UPSTREAM_LABELS, CONTEXTUAL_UPSTREAM_LABELS, EXCLUDED_UPSTREAM_LABELS, lookup_label(), label_for_upstream(), and upstream_labels_for_profile(). The adapter excludes categories already owned by the v6 detector or current Schift postprocessing, including person, address, phone, email, existing structured identifiers, URLs, IPs, and legal case references. Existing v6 spans win overlaps, except a generic account_number span may be refined by a more specific extended label.

Masking boundaries

Masking is request-local and occurs only after policy assessment. Select a MaskingStrategy in AnalysisConfig or call mask_text() directly with typed MaskSpan values:

  • TOKEN: replace with a stable label token such as [PII_PHONE_1].
  • REDACT: replace with [REDACTED].
  • PARTIAL: retain a small leading/trailing portion for recognition.
  • HASHED: replace with a deterministic local SHA-256 digest.

These strategies are output transformations, not custody. No strategy stores a reverse map, restores source values, or talks to Vault. Central Vault custody, retention, tenant isolation, KMS, and audit requirements remain a separate caller-side project.

Documents and the document-helper boundary

Document APIs accept already extracted text and provenance, not files:

from schift_ko_pii import (
    ExtractedPageInput,
    analyze,
    from_pages,
)

document = from_pages(
    (
        ExtractedPageInput(page_num=1, text="첫 페이지", source="helper"),
        ExtractedPageInput(page_num=2, text="둘째 페이지", source="helper"),
    ),
    source_id="doc-123",
)
result = analyze(document)

from_text(), from_pages(), and from_document_helper() build the typed text-only envelope. DocumentInput preserves the concatenated text and page boundaries; SourceSpan and PageSpan preserve character offsets and page provenance. scan_document() is the convenience scan over that envelope.

The package does not parse HWP/HWPX, DOCX, XLSX, PDF, or other file formats. Use the document-helper service (or another caller-owned parser) to produce a text-only envelope, then pass it to this package. Do not treat the envelope as file storage or a Vault integration.

Postprocessing and legacy API

Postprocessing is enabled by default for detect(). It applies Korean-specific structured-ID validation, checksum checks where applicable, context-aware span merging, and false-positive suppression for legal case numbers and statute references. The legacy detect() path preserves original input text by default; pass normalize=True when you want NFKC-normalized model input and source-offset remapping. The typed analyze()/analyze_text() flow enables that normalization by default. Pass postprocess=False for encoder heads only (person, address, and organization).

Existing root exports remain available: detect, mask, apply, assess, detect_extended, detect_extended_entities, Action, ProcessingMode, RiskLevel, and ExtendedDependencyError.

For compatibility, AnonymizationResult is an alias of PiiResult, and both anonymize_text and anonymize are aliases of analyze_text. They do not introduce a second execution path.

API (free)

For production use without managing model files:

from schift import Schift

client = Schift(api_key="...")  # free at schift.io
result = client.pii.redact("김민수의 전화번호는 010-1234-5678입니다.")

Labels

The stable local taxonomy is available as immutable TaxonomyEntry values in LABELS. Common labels include:

Label Description Examples
private_person Person names 김민수, 황보영희, Lee Jenny
private_phone Phone numbers 010-1234-5678, 02-1234-5678
private_email Email addresses user@example.com
private_address Street/postal addresses 서울특별시 강남구 테헤란로 521
private_date Dates 2024년 3월 15일, 2024-03-15
private_url URLs and IP addresses instagram.com/user, 192.168.1.1
account_number Structured account/identity surfaces 850205-1234567, M12345678
secret Secrets, API keys, passwords

Benchmark

The benchmark suite is included under benchmark/.

python benchmark/run_benchmark.py
python benchmark/run_benchmark.py --postprocess
python benchmark/run_benchmark.py --hf-model LiquidAI/LFM2.5-Encoder-350M-PII-Detector

Model details

  • Checkpoint: schift-io/schift-ko-pii-v6
  • Architecture: dual-path LoRA encoder with person, address, and organization heads
  • Training: LoRA adapter on Korean legal/financial/admin examples
  • Format: safetensors release source
  • Inference: custom transformers/PyTorch dual-path loader
  • Max length: 512 tokens
  • Tagging scheme: O/B/I/E/S

License

Schift License v2.0 — Apache 2.0 base with a revenue threshold. Free for everyone under $10M annual revenue. Research, education, and non-profit use always permitted. Companies above the threshold: contact hello@schift.io.

Citation

@software{schift_ko_pii_2026,
  author = {Schift Inc.},
  title = {schift-ko-pii: Korean PII Detection Model},
  year = {2026},
  url = {https://huggingface.co/schift-io/schift-ko-pii-v6},
}

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

schift_ko_pii-0.5.1.tar.gz (86.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

schift_ko_pii-0.5.1-py3-none-any.whl (45.5 kB view details)

Uploaded Python 3

File details

Details for the file schift_ko_pii-0.5.1.tar.gz.

File metadata

  • Download URL: schift_ko_pii-0.5.1.tar.gz
  • Upload date:
  • Size: 86.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.12

File hashes

Hashes for schift_ko_pii-0.5.1.tar.gz
Algorithm Hash digest
SHA256 0aeae6f58246dee6d2369a794534d453800352ab052a9f137813450df52bf936
MD5 e7c181d8c9171350aad928070e340e81
BLAKE2b-256 d2fe94bf16d1699b9fcd5d51ac016f80c00dfe5d75739593b7effdf061debd91

See more details on using hashes here.

File details

Details for the file schift_ko_pii-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: schift_ko_pii-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 45.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.12

File hashes

Hashes for schift_ko_pii-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dd28a205d1885b0233568102128ea71525a4a11c77c5249ad47783dc12bf5625
MD5 99c120a8eb9fa06b11a4cdaa8cbe2fe6
BLAKE2b-256 5d52ba08df7b976cd8e12b08c4054508acb4f90a1477d08389f47732d3b06616

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.0

2 files

0.5.2

2 files

This release

0.5.1 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page