fix: 판례 판단 시 사람 검토 안전장치 강제

This commit is contained in:
hbyang 2026-08-18 11:46:46 +09:00
parent 3debc884c1
commit 91e356e4c1
4 changed files with 8 additions and 8 deletions

View File

@ -203,8 +203,6 @@ class LegalRiskEngine:
unknown = set(decision.matched_precedent_ids) - allowed
if unknown:
raise ValueError(f"LLM이 제공되지 않은 판례 ID를 반환함: {sorted(unknown)}")
if not decision.review_required:
raise ValueError("LLM legal judge는 사람 검토를 해제할 수 없습니다")
if decision.verdict == "likely" and not decision.matched_precedent_ids:
raise ValueError("침해 의심 의견에는 근거 판례 ID가 최소 1개 필요합니다")
merged_missing = tuple(dict.fromkeys([
@ -217,6 +215,7 @@ class LegalRiskEngine:
"judgment_method": "llm",
"llm_verdict": decision.verdict,
"llm_confidence": decision.confidence,
# 모델 출력과 관계없이 서비스의 사람 검토 안전장치는 항상 유지한다.
"llm_review_required": True,
"llm_matched_precedent_ids": decision.matched_precedent_ids,
"supporting_reasons": decision.supporting_reasons,

View File

@ -10,7 +10,7 @@ from pydantic import BaseModel, ConfigDict, Field
from app.engine.legal_risk import LegalJudgeDecision, LegalJudgeInput
PROMPT_VERSION = "legal-judge-v2"
PROMPT_VERSION = "legal-judge-v3"
class _JudgeOutput(BaseModel):
@ -22,7 +22,7 @@ class _JudgeOutput(BaseModel):
supporting_reasons: list[str]
counter_reasons: list[str]
missing_factors: list[str]
review_required: bool
review_required: Literal[True]
SYSTEM_PROMPT = """당신은 대한민국 저작권 판례 비교 검토 보조자다.
@ -37,6 +37,7 @@ insufficient_evidence는 탐지된 표현 증거나 관련 판례가 부족해
유사도 점수는 침해 확률이 아니다. 보호되는 표현, 의거관계, 권리 귀속
이용허락 사실이 없으면 missing_factors에 명시한다.
근거와 반대 근거는 검토자가 확인할 있는 짧은 사실 문장으로 작성한다.
review_required는 항상 true로 반환한다.
"""

View File

@ -7,7 +7,7 @@
1. 등록 코퍼스에서 유사 문서와 증거 구간을 찾는다.
2. `LegalRiskEngine`이 저작물 유형과 법적 태그로 등록 판례 Top 5를 고른다.
3. GPT Judge가 탐지 증거와 Top 5 판례만 비교한다.
4. 서버가 Structured Outputs 스키마, 판례 ID, `review_required=true`를 검증한다.
4. 서버가 Structured Outputs 스키마와 판례 ID를 검증하고, 사람 검토가 해제되지 않도록 `review_required=true`를 강제한다.
5. 호출 실패·형식 오류·미등록 판례 ID가 있으면 규칙 기반 결과로 복귀한다.
GPT는 전체 판례 545건을 한 번에 받지 않으며 법률상 침해를 확정하지 않는다.

View File

@ -104,15 +104,15 @@ def test_llm_hallucinated_precedent_id_falls_back_to_rules():
assert "GPT" not in (result.judge_note or "")
def test_llm_cannot_disable_human_review():
def test_server_keeps_human_review_even_if_judge_returns_false():
result = LegalRiskEngine([_case()], judge=_FakeJudge(review_required=False)).assess(
max_similarity=0.9,
coverage=0.5,
longest_span=200,
legal_tags=["reproduction"],
)
assert result.judgment_method == "rule_fallback"
assert result.llm_review_required is None
assert result.judgment_method == "llm"
assert result.llm_review_required is True
def test_likely_judgment_without_precedent_id_falls_back():