콘텐츠로 이동

토큰 분류와 스팬 추출

mlxcel은 두 종류의 토큰 단위 출력 모델을 오프라인으로 실행하며, 각각 별도의 서브명령어를 사용합니다:

형태 서브명령어 레이블 출력
토큰 분류 mlxcel tag 체크포인트가 고정(id2label, BIO 또는 BIOES) 태깅된 문자 스팬과 텍스트의 마스킹된 사본
스팬 추출 mlxcel extract 요청마다 선택(--labels, --labels-json, --classify) 레이블을 키로 하는 스팬 목록, 또는 태스크마다 클래스 하나

두 형태가 분리된 이유는 입력이 다르기 때문입니다. 레이블이 고정된 분류기에 요청 레이블을 넘기면 그 레이블을 조용히 무시할 수밖에 없습니다. 체크포인트를 다른 서브명령어에 넘기면 올바른 서브명령어를 안내하는 메시지와 함께 실패합니다.

두 형태 모두 HTTP로 제공되지 않습니다. 참조 구현인 mlx-vlm이 이들을 위한 경로를 정의하지 않으므로 맞춰야 할 업스트림 스키마가 없습니다.

지원 패밀리

패밀리 감지 종류 디코딩
BERT / XLM-RoBERTa 토큰 분류기 model_type이 bert, xlm-roberta, xlm_roberta이고 architectures[0]이 ForTokenClassification으로 끝나며 id2label이 비어 있지 않음 bert_token_classifier 토큰별 argmax
OpenAI Privacy Filter model_type이 openai_privacy_filter이고 id2label이 비어 있지 않음 openai_privacy_filter 제약된 BIOES Viterbi(기본값), --argmax 지정 시 토큰별 argmax
GLiNER2.5 스팬 추출기 model_type이 gliner2 또는 gliner2_5이거나, 아키텍처 이름이 Gliner2ForSchemaExtraction 또는 BoundaryExtractor인 경우 gliner2_5 공유 후보 풀에 대한 시그모이드 스팬 점수, 레이블별로 겹침 해소

감지는 config.json만 읽으며 생성, 임베딩, 재순위화 디스패치와 분리되어 있습니다. mlxcel embed는 BertForTokenClassification 체크포인트를 여전히 BERT 임베더로 로드하고, mlxcel generate는 토큰 분류기를 mlxcel tag를 안내하는 메시지와 함께 거부합니다.

mlxcel tag

mlxcel tag -m nativ-community/rampart-mlx-fp16 --keep CITY,STATE,ZIP_CODE \
  "I'm Sarah Connor, 1984 Cyberdyne Ave, Los Angeles CA 90012, sarah@sky.net"
mlxcel tag -m mlx-community/openai-privacy-filter-bf16 "Alice Smith can be reached at alice@example.com."
플래그 설명
-m, --model <PATH_OR_REPO_ID> 체크포인트 디렉터리 또는 HuggingFace repo-id이며, mlxcel generate -m과 같은 방식으로 해석하고 다운로드합니다.
TEXT 태깅할 텍스트. -이면 stdin에서 읽습니다.
--argmax 기본 디코더가 Viterbi인 체크포인트에서 토큰별 디코딩을 강제합니다.
--replacement <STR> 가려진 각 스팬을 플레이스홀더 대신 이 문자열로 바꿉니다.
--keep <L1,L2> spans에는 보고하지만 redacted_text에는 남겨 두는 엔터티 레이블. 알 수 없는 레이블은 무시합니다.
--operating-point <NAME> Viterbi로 디코딩하는 체크포인트의 캘리브레이션 운영점(기본값 default).
--models-dir <PATH> repo-id 해석에 사용할 모델 저장소 루트.

JSON 문서는 stdout으로, 한 줄 요약(스팬 수, 종류, model_type)은 stderr로 출력됩니다:

{
  "text": "Alice Smith can be reached at alice@example.com.",
  "spans": [
    {"label": "private_person", "start": 0, "end": 11, "text": "Alice Smith", "placeholder": "<PRIVATE_PERSON>"},
    {"label": "private_email", "start": 30, "end": 47, "text": "alice@example.com", "placeholder": "<PRIVATE_EMAIL>"}
  ],
  "redacted_text": "<PRIVATE_PERSON> can be reached at <PRIVATE_EMAIL>."
}

마스킹되는 것은 redacted_text뿐입니다. text와 모든 spans[].text에는 원래 값이 그대로 들어 있으므로, 출력이 신뢰된 컨텍스트를 벗어날 때는 redacted_text만 전달하십시오.

긴 텍스트는 절대 잘리지 않습니다. 토크나이저는 문자 오프셋을 보고해야 하며, ID는 모델의 컨텍스트 크기 단위 윈도로 나누고 체크포인트의 특수 토큰으로 감싼 뒤 점수를 매기고 디코딩하여 이어 붙입니다. 문자 범위는 오프셋에서 앞뒤 공백을 잘라 얻으며, 윈도 경계에서 나뉜 단어도 하나의 스팬을 이룹니다. 오프셋은 Python 문자열 인덱싱과 마찬가지로 text에 대한 유니코드 스칼라 인덱스입니다.

플레이스홀더는 <에 레이블을 대문자로 바꾼 값(영숫자가 아닌 문자가 연속된 부분은 모두 _로 치환)을 붙이고 >를 더한 것입니다. --replacement가 이를 재정의합니다.

OpenAI Privacy Filter

openai/privacy-filter는 1.4B 파라미터 양방향 sparse-MoE 인코더로, BIOES 레이블로 PII를 태깅합니다. mlxcel은 업스트림 설정 그대로 mlxcel tag와 같은 파이프라인으로 실행합니다. 윈도는 128000 토큰이고, 특수 토큰과 단어 그룹화를 사용하지 않습니다.

기본 디코더는 BIOES 격자 위의 제약된 Viterbi 경로이므로, 출력에 스팬 빌더가 고쳐야 할 레이블 경로가 생기지 않습니다. --argmax는 토큰별 독립 디코딩으로 전환합니다.

체크포인트의 viterbi_calibration.json에는 이름이 붙은 운영점이 있을 수 있으며, 각 운영점은 격자 전이에 더하는 로그 영역 바이어스 여섯 개의 집합입니다. --operating-point가 그중 하나를 선택합니다. 배포된 체크포인트는 모든 바이어스가 0인 default 운영점 하나만 제공하며, 이 플래그는 Viterbi로 디코딩하지 않는 체크포인트에서는 거부됩니다.

mlxcel extract

mlxcel extract -m fastino/gliner2.5-small-v1 --labels company,person,location \
  --include-confidence --include-spans "Apple hired Sam in New York."
mlxcel extract -m fastino/gliner2.5-small-v1 \
  --classify '{"sentiment": ["positive", "neutral", "negative"]}' "The launch was excellent."

--labels, --labels-json, --classify 중 정확히 하나가 필요합니다.

플래그 기본값 설명
-m, --model <PATH_OR_REPO_ID> 필수 GLiNER2.5 체크포인트.
--labels <L1,L2> - 쉼표로 구분한 엔터티 레이블.
--labels-json <JSON> - 레이블 맵. 값은 설명 문자열 또는 null입니다.
--classify <JSON> - 분류 태스크. {"<task>": [labels]} 형식 또는 labels, prompt, label_descriptions, multi_label, threshold를 가진 객체입니다.
--threshold <F> 0.5 최소 엔터티 점수이며 멀티 레이블 임계값의 기본값입니다.
--include-confidence 꺼짐 각 스팬의 신뢰도를 출력에 추가합니다.
--include-spans 꺼짐 각 스팬의 시작과 끝 오프셋을 추가합니다.
--max-len <N> 체크포인트 값 GLiNER2.5 전용. 가장 긴 텍스트 윈도이며 1..=32768 범위의 정수입니다.
--word-splitter <whitespace\|char> whitespace GLiNER2.5 전용. char는 공백이 아닌 문자마다 단어를 하나씩 나누며, CJK처럼 단어 사이를 띄우지 않는 문자 체계에 사용합니다.
--models-dir <PATH> 전역 저장소 repo-id를 해석할 모델 저장소 루트(환경 변수 MLXCEL_MODELS_DIR).

엔터티 출력은 {"entities": {"<label>": [...]}}이며, 요청한 레이블마다 키가 하나씩 요청 순서대로 들어갑니다. --classify는 {"<task>": "<label>"}를 출력하고, 멀티 레이블 태스크에서는 레이블 목록을 출력합니다.