diff --git a/app/engine/ai_detector.py b/app/engine/ai_detector.py index 7585672..19c2916 100644 --- a/app/engine/ai_detector.py +++ b/app/engine/ai_detector.py @@ -953,7 +953,8 @@ class AiGenerationDetector: "없습니다. scripts/calibrate_ai_detector_cuts.py 로 컷을 산출하세요." ) else: - note = ( + scope_note = self.artifact.notes.strip() if self.artifact else "" + note = scope_note or ( "AI 생성 '의심도'이며 확정 판정이 아닙니다. 대필·윤문된 원고는 " "높게 나올 수 있으므로 반드시 사람 검토를 거치세요." ) diff --git a/scripts/train_ai_detector.py b/scripts/train_ai_detector.py index eb926da..181fac1 100644 --- a/scripts/train_ai_detector.py +++ b/scripts/train_ai_detector.py @@ -33,6 +33,7 @@ from __future__ import annotations import argparse import json import logging +import re import sys from collections import Counter from pathlib import Path @@ -219,6 +220,10 @@ def main() -> int: "돌려 성능 차이를 반드시 비교할 것.", ) ap.add_argument("--trained-at", default="", help="아티팩트에 기록할 학습 시각 문자열") + ap.add_argument( + "--training-scope", default="unspecified", + help="학습한 AI 생성기/도메인 범위. 운영 응답에 한계로 노출", + ) args = ap.parse_args() try: @@ -371,8 +376,10 @@ def main() -> int: logger.info("confusion(test): %s", metrics["test"]["confusion_matrix"]) suffix = "-nolen" if zeroed else "" + scope_slug = re.sub(r"[^a-zA-Z0-9._-]+", "-", args.training_scope).strip("-") model_version = ( f"{args.model}{suffix}-{FEATURE_SET_VERSION}" + f"-{scope_slug or 'unspecified'}" f"-auroc{metrics['test']['auroc']:.3f}" ) payload = { @@ -388,8 +395,9 @@ def main() -> int: "trained_at": args.trained_at, "sklearn_version": sklearn.__version__, "notes": ( - "AI 생성 '의심도' 모델. 확정 판정이 아니며 사람 검토 보조용. " - "임계값은 target FPR 기준으로 산출됨." + f"학습 범위: {args.training_scope}. 이 범위 밖 생성 모델에 대한 " + "일반화는 검증되지 않았습니다. AI 생성 '의심도'이며 확정 판정이 " + "아니고 사람 검토 보조용입니다. 임계값은 target FPR 기준으로 산출됐습니다." ), }