o2o-plagiarism-ai/scripts/validate_precedents.py

59 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""판례 JSONL 스키마와 사건번호/출처 중복을 검증한다."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
if __package__ in (None, ""):
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from app.engine.legal_risk import load_precedents
CASE_ID_RE = re.compile(r"^(?:19|20)?\d{2}[가-힣]{1,4}\d+$")
ALLOWED_WORK_TYPES = {"literary", "visual", "musical"}
ALLOWED_LEGAL_TAGS = {
"reproduction", "derivative_work", "public_transmission", "distribution",
"publication", "attribution", "integrity", "citation_missing", "false_authorship",
}
def validate_engine_labels(path: Path) -> None:
for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if not line.strip():
continue
row = json.loads(line)
case_id = str(row.get("case_id", ""))
if not CASE_ID_RE.fullmatch(case_id):
raise ValueError(f"{path}:{lineno} 사건번호 형식 오류: {case_id}")
work_types = set(row.get("work_types", []))
legal_tags = set(row.get("legal_tags", []))
criteria = row.get("criteria", [])
if unknown := work_types - ALLOWED_WORK_TYPES:
raise ValueError(f"{path}:{lineno} 미지원 저작물 유형: {sorted(unknown)}")
if unknown := legal_tags - ALLOWED_LEGAL_TAGS:
raise ValueError(f"{path}:{lineno} 미지원 법적 태그: {sorted(unknown)}")
if not legal_tags:
raise ValueError(f"{path}:{lineno} 법적 태그 없음: {case_id}")
if not work_types and not criteria:
raise ValueError(f"{path}:{lineno} 저작물 유형·판단 기준 없음: {case_id}")
def main() -> int:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("jsonl", type=Path)
args = p.parse_args()
precedents = load_precedents(args.jsonl)
validate_engine_labels(args.jsonl)
print(json.dumps({"valid": True, "precedent_count": len(precedents)}, ensure_ascii=False))
return 0
if __name__ == "__main__":
raise SystemExit(main())