컴플라이언스 분류기 스포크 — 배선은 있는데 판정이 없다

무엇을

POST /hub/compliance-checks 뒤에 붙는 실제 판정 스포크를 만든다. 지금은 501 이다 — w6-compliance-pipeline이 경로만 깔아 뒀다.

왜 지금까지 없었나

STATE.md 「지금 막혀 있는 것」 — ai/apps/compliance/ 미생성 · 6주차 · 류준. 8주 마일스톤 6주차 목표가 「생성 + 컴플라이언스」다.

재현율 우선이다

검수 기준 재현율 ≥0.90 · 정밀도 ≥0.60. 순서가 있다 — 애매하면 잡는다. 정밀도를 올리려고 재현율을 깎지 않는다.

501 을 빈 목록으로 바꾸지 않는다

파이프라인 티켓이 적어 둔 그대로다 — 빈 목록을 돌려주면 탐지가 죽은 것이 「깨끗하다」로 읽힌다. 스포크가 없으면 501 을 유지한다.

부록 A-1 — 등급·점수를 만들지 않는다

응답 필드는 call_id·segment_id·findings 셋뿐이고, 그 계약을 테스트가 고정하고 있다. 스포크가 등급을 계산해도 실어 보낼 자리가 없다 — 그대로 둔다.

발견이 없는 것은 「잡힌 것이 없음」이지 「안전함」이 아니다. 재현율 0.90 은 10건 중 1건은 놓친다는 뜻이다.

완료 조건


2026-09-15 — 규칙 v1 로 501 을 걷었다. 분류기는 아니다

무엇을 만들었나 — 분류기가 아니라 규칙이다

완료 조건은 「분류기」인데 규칙으로 만들었다. 기획서 2.4절이 정한 방식은 KcELECTRA 파인튜닝이지만 학습 데이터가 없다(골든셋 컴플라이언스 라벨은 양성 14·음성 6 — 채점용이다). 학습은 정성윤 님 개인 PC 몫이기도 하다. C-6 콜 가드와 같은 길로 규칙 v1 을 먼저 두고, 분류기가 오면 어댑터를 갈아끼운다.

ai/apps/compliance/domain/value_objects/rules.py   조항별 규칙표 — MANUAL 1.1·1.2·1.3·1.4·1.6·3.1·4.1·4.3
ai/apps/compliance/domain/services/detector.py      판정(요청 동사·건강 문맥·의무/부정 예외·대리 신청 안내 누락)
ai/apps/compliance/adapter/outbound/rule_compliance_adapter.py   CompliancePort — rule_code · phrase · alternative_source 만
ai/provider.py build_compliance_provider · server/main.py _wire_compliance (설정 조건 없음 — 콜 가드와 같다)

실측

측정일 2026-09-15 · 커밋 38f2fc3-dirty
① 골든셋 v1-150 컴플라이언스 20건(양성 14 · 음성 6)
   ELASTICSEARCH_URL=http://localhost:9200 .venv/bin/python scripts/run_eval.py
   [compliance] 재현율 1.0 · 정밀도 1.0 · tp 14 · fp 0 · fn 0

② AI Hub 민원 질의응답 validation · 다산콜센터 · 실제 상담사 발화 9,881건 (라벨 없음)
   .venv/bin/python scripts/measure_compliance_real_agents.py --split {dev|test}
   대화셋 번호 끝자리 홀짝으로 반씩 — dev 4,929건 · test 4,952건

                         걸린 발화
   첫 판 · 전체           165건 (1.67%)   ← 가르기 전. 158건이 C-1 금액 규칙
   고친 뒤 · dev(본 절반)   4건 (0.08%)
   고친 뒤 · test(안 본 절반) 2건 (0.04%)   택시비 예상 금액 2건

⚠ ① 은 상한이다 — 성능이 아니다

규칙을 골든셋 문장을 본 뒤에 썼다. 문구를 옮기지 않고 조항 갈래로 일반화했고 테스트는 같은 갈래의 다른 문장으로 짰지만, 1.0 은 자기충족이다. C-6 콜 가드의 「⚠ 자기충족 — 상한이지 성능 아님」과 같은 경고를 붙인다.

② 가 말하는 것과 말하지 않는 것

남는 것