/ Модель

Характеристики

Контекст
131 072 токена
Параметры
145 млн
Лицензия
Apache 2.0
Архитектура
openai_privacy_filter · MoE
Базовая модель
privacy-filter
Опубликована
27 апр 2026

privacy-filter-korean

Разметка токеновТекст → label6 профессий

Корейская LoRA-версия OpenAI Privacy Filter находит и размечает персональные данные в тексте для последующего маскирования.

202скачиваний за 30 дней3лайкавеса обновлены28 мая 2026

Бенчмарки

Как модель справилась с задачами пользователей ailist и что о ней публикуют открытые лидерборды

Публичные оценки

Из открытых лидербордов. Сравнивайте результаты одного теста при одинаковых условиях — отсутствие оценки не значит, что модель хуже.

В подключённых источниках результатов для этой модели пока нет.

Что умеет модель

Описание составлено по карточке модели и метаданным Hugging Face

FrameByFrame подготовили корейскую LoRA-дообученную версию OpenAI Privacy Filter для обнаружения фрагментов с персональными данными. Модель размечает текст по токенам, выдавая метки BIOES для девяти категорий, включая имена, адреса, телефоны, URL и электронную почту; предсказания можно преобразовать в символьные диапазоны для последующего маскирования. В карточке указаны архитектура sparse MoE, 145,4 млн параметров в репозитории и контекст 131 072 токена.

Базовая модель описана как имеющая 1,5 млрд параметров и 50 млн активных параметров; LoRA применена только к проекциям внимания, основная модель заморожена. Модель предназначена прежде всего для корейского текста, также приведён пример для английского. На корейском тестовом наборе KDPII показаны улучшения F1 для телефонов, URL и электронной почты относительно базовой модели. Для загрузки требуются Transformers 5.x из исходного кода и trust_remote_code=True. Лицензия — Apache-2.0.

Сценарии применения

  • поиск имён и псевдонимов в корейском тексте
  • обнаружение корейских адресов для маскирования
  • извлечение телефонов из текстов и форм
  • поиск электронных адресов и URL в документах
  • подготовка текстов к обезличиванию

Ограничения

Имена иностранных лиц распознаются хуже из-за ограниченного обучающего материала; псевдонимы могут классифицироваться как имена. Компоненты адресов выдаются отдельными диапазонами, а для загрузки требуются Transformers 5.x из исходного кода и trust_remote_code=True.

Для каких профессий подходит6

Разделы каталога профессий, в задачах которых используется эта модель

Все профессии

Также подходит для

Карточка модели

README от автора на Hugging Face, как он его опубликовал

Открыть на Hugging Face

Privacy Filter — Korean

Korean fine-tune of OpenAI Privacy Filter for span-level PII detection. Adapted via LoRA on attention projections only — the base's sparse-MoE backbone (1.5B / 50M active params) is kept frozen.

Open Test Notebook — load the model and run all examples interactively.

Capabilities

CategoryDescriptionExample
private_personPersonal name (Korean / Western / handles)김민수, John Smith
private_addressPhysical / postal address서울특별시 강남구 테헤란로 123
private_phonePhone number010-1234-5678
private_emailEmail addressminsu@example.com
private_dateBirthday / personally-identifying date1985년 3월 12일
private_urlPersonal URLgithub.com/minsu
account_numberBank, card, RRN, passport, etc.110-234-567890
personal_handleUsername / handle@minsu_dev
ip_addressIP address192.168.1.5

Benchmark Results

Held-out KDPII Korean PII test set, span-level F1:

labelopenai/privacy-filterfine-tunedΔ
private_phone0.651.00+0.35
private_url0.211.00+0.79
private_email0.861.00+0.14
account_number0.310.98+0.67
private_date0.000.90+0.90
private_address0.000.78+0.78
private_person0.060.69+0.63
Overall——+0.58

Quick Start

Install

⚠️ Requires transformers 5.x (currently dev / from source). The openai_privacy_filter architecture is not in any stable 4.x PyPI release. If you pip install transformers and load this model, you'll see KeyError: 'openai_privacy_filter'.

pip install --upgrade "git+https://github.com/huggingface/transformers.git" peft torch safetensors accelerate

The --upgrade flag is critical — without it, pip install is silently no-op when an older transformers is already present.

After installing, restart your Python runtime / kernel so the new transformers replaces any version pre-loaded into the process. Sanity-check:

python -c "from transformers.models.auto.configuration_auto import CONFIG_MAPPING_NAMES; assert 'openai_privacy_filter' in CONFIG_MAPPING_NAMES, 'openai_privacy_filter missing — re-install transformers from source and restart runtime'"

If you're using Colab, the test notebook handles this automatically (auto-restart).

Load Model

from transformers import AutoTokenizer, AutoModelForTokenClassification
import torch

MODEL_ID = "FrameByFrame/privacy-filter-korean"

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
model = AutoModelForTokenClassification.from_pretrained(
    MODEL_ID, trust_remote_code=True, torch_dtype=torch.bfloat16
)
model.eval()
if torch.cuda.is_available():
    model.cuda()

trust_remote_code=True is required because Privacy Filter ships a custom OpenAIPrivacyFilterForTokenClassification class (gpt-oss-style sparse MoE).

Inference

The model emits per-token BIOES labels. The helper below decodes them into character-offset spans with simple constrained logic:

def extract_pii(text: str, max_length: int = 512):
    enc = tokenizer(
        text,
        truncation=True,
        max_length=max_length,
        return_offsets_mapping=True,
        return_tensors="pt",
    )
    offsets = enc.pop("offset_mapping")[0].tolist()
    enc = {k: v.to(model.device) for k, v in enc.items()}
    with torch.no_grad():
        logits = model(**enc).logits
    pred_ids = logits.argmax(-1)[0].tolist()
    id2label = model.config.id2label

    spans = []
    active = None  # (label, start, end)
    for tok_idx, lid in enumerate(pred_ids):
        label = id2label[int(lid)]
        if label == "O":
            if active is not None:
                spans.append(active); active = None
            continue
        prefix, cat = label.split("-", 1)
        c_start, c_end = offsets[tok_idx]
        if prefix == "S":
            if active is not None: spans.append(active); active = None
            spans.append((cat, c_start, c_end))
        elif prefix == "B":
            if active is not None: spans.append(active)
            active = (cat, c_start, c_end)
        elif prefix in ("I", "E"):
            if active and active[0] == cat:
                active = (active[0], active[1], c_end)
            else:
                if active is not None: spans.append(active); active = None
                if prefix == "E":
                    spans.append((cat, c_start, c_end))
    if active is not None:
        spans.append(active)

    return [
        {"label": cat, "start": s, "end": e, "text": text[s:e].strip()}
        for cat, s, e in spans
        if text[s:e].strip()
    ]

Test

Korean: name + phone + email

>>> extract_pii("김민수의 전화번호는 010-1234-5678이고 이메일은 minsu@example.com입니다.")
[
  {"label": "private_person", "start": 0, "end": 3, "text": "김민수"},
  {"label": "private_phone",  "start": 12, "end": 25, "text": "010-1234-5678"},
  {"label": "private_email",  "start": 33, "end": 50, "text": "minsu@example.com"},
]

Korean: address + name

>>> extract_pii("서울특별시 강남구 테헤란로 123에 사는 박지영씨에게 연락주세요.")
[
  {"label": "private_address", "start": 0, "end": 5, "text": "서울특별시"},
  {"label": "private_address", "start": 6, "end": 9, "text": "강남구"},
  {"label": "private_address", "start": 10, "end": 17, "text": "테헤란로 123"},
  {"label": "private_person",  "start": 22, "end": 25, "text": "박지영"},
]

Note: the model follows KDPII's address convention where each toponym component is its own span. Most downstream redaction systems concatenate adjacent address spans.

Korean: form-style document

>>> extract_pii('''고객 정보
... 이름: 이수진
... 생년월일: 1985년 3월 12일
... 주소: 부산광역시 해운대구 우동 1457
... 연락처: 010-9876-5432''')
[
  {"label": "private_person",  ..., "text": "이수진"},
  {"label": "private_date",    ..., "text": "1985년 3월 12일"},
  {"label": "private_address", ..., "text": "부산광역시"},
  {"label": "private_address", ..., "text": "해운대구"},
  {"label": "private_address", ..., "text": "우동 1457"},
  {"label": "private_phone",   ..., "text": "010-9876-5432"},
]

English: account + email

>>> extract_pii("Wire to acct 110-234-567890, contact minsu@example.com")
[
  {"label": "account_number", "start": 13, "end": 26, "text": "110-234-567890"},
  {"label": "private_email",  "start": 36, "end": 53, "text": "minsu@example.com"},
]

Redaction

Wrap the spans into a redactor:

def redact(text: str, mask: str = "[REDACTED]") -> str:
    spans = extract_pii(text)
    spans.sort(key=lambda s: s["start"], reverse=True)
    out = text
    for s in spans:
        out = out[: s["start"]] + f"[{s['label'].upper()}]" + out[s["end"]:]
    return out

>>> redact("김민수님의 번호는 010-1234-5678입니다.")
"[PRIVATE_PERSON]님의 번호는 [PRIVATE_PHONE]입니다."

Output Schema

Each detected entity is one dict:

fielddescription
labelOne of the 9 categories above
startCharacter offset start (inclusive)
endCharacter offset end (exclusive)
textThe matched substring

Training Details

Base modelopenai/privacy-filter (sparse MoE, 1.5B total / 50M active params, 128 experts top-4)
MethodLoRA r=16, alpha=32, dropout=0.05 on attention projections (q/k/v/o_proj); classifier head fully trainable; everything else frozen
Trainable params~614k (~0.04% of the model)
DatasetsKDPII (Korean, ~53k records, deterministic 5/5/90 test/val/train), korean_rrn_synthetic (train only)
OptimizerAdamW, lr=5e-4, cosine schedule, warmup 0.1
Batch64 per device × 2 GPUs = 128 effective
Epochs10, early stopping on eval_span_f1 (patience 3)
Sequence length512
Precisionbf16 mixed (saved as bf16 safetensors after merge_and_unload)
Hardware2× NVIDIA RTX A5000 (24 GB each)
Final eval span F10.848 (validation)

For full reproduction details, see TRAINING.md.

Known Limitations

  • private_person residual error is dominated by KDPII's PS_NICKNAME policy. ~40% of remaining person errors are online-handle-style strings (e.g., 탕비실맥심킹, 퍼터요정) that KDPII labels as PS_NICKNAME → private_person. Downstream redaction is unaffected; classification systems may want to post-classify handles separately.
  • Foreign names (Western, Japanese, Arabic transliterations) detected at lower rates due to limited training exposure.
  • private_address boundaries follow KDPII's split convention (each toponym component is a separate span). Production redactors typically concatenate adjacent address spans during post-processing.
  • Raw model output may have leading/trailing whitespace in span offsets; the extract_pii helper above strips them via text.strip() on the slice.

License

Apache 2.0 (inherited from base OpenAI Privacy Filter).

Citation

If you use this model:

@misc{framebyframe-privacy-filter-korean-2026,
  title  = {Privacy Filter Korean: LoRA fine-tune of OpenAI Privacy Filter for Korean PII},
  author = {Mariappan, Vijayachandran},
  year   = {2026},
  url    = {https://huggingface.co/FrameByFrame/privacy-filter-korean}
}

Как запустить

На своей GPU в ailist. Цена — по текущим предложениям провайдеров

GPU в ailist

Универсальный рантайм · token-classification

Можно запустить

Подбираем GPU…

Класс архитектуры
OpenAIPrivacyFilterForTokenClassification
Ревизия весов
e370608

0 моделей