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 unknown = set(decision.matched_precedent_ids) - allowed
if unknown: if unknown:
raise ValueError(f"LLM이 제공되지 않은 판례 ID를 반환함: {sorted(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: if decision.verdict == "likely" and not decision.matched_precedent_ids:
raise ValueError("침해 의심 의견에는 근거 판례 ID가 최소 1개 필요합니다") raise ValueError("침해 의심 의견에는 근거 판례 ID가 최소 1개 필요합니다")
merged_missing = tuple(dict.fromkeys([ merged_missing = tuple(dict.fromkeys([
@ -217,6 +215,7 @@ class LegalRiskEngine:
"judgment_method": "llm", "judgment_method": "llm",
"llm_verdict": decision.verdict, "llm_verdict": decision.verdict,
"llm_confidence": decision.confidence, "llm_confidence": decision.confidence,
# 모델 출력과 관계없이 서비스의 사람 검토 안전장치는 항상 유지한다.
"llm_review_required": True, "llm_review_required": True,
"llm_matched_precedent_ids": decision.matched_precedent_ids, "llm_matched_precedent_ids": decision.matched_precedent_ids,
"supporting_reasons": decision.supporting_reasons, "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 from app.engine.legal_risk import LegalJudgeDecision, LegalJudgeInput
PROMPT_VERSION = "legal-judge-v2" PROMPT_VERSION = "legal-judge-v3"
class _JudgeOutput(BaseModel): class _JudgeOutput(BaseModel):
@ -22,7 +22,7 @@ class _JudgeOutput(BaseModel):
supporting_reasons: list[str] supporting_reasons: list[str]
counter_reasons: list[str] counter_reasons: list[str]
missing_factors: list[str] missing_factors: list[str]
review_required: bool review_required: Literal[True]
SYSTEM_PROMPT = """당신은 대한민국 저작권 판례 비교 검토 보조자다. SYSTEM_PROMPT = """당신은 대한민국 저작권 판례 비교 검토 보조자다.
@ -37,6 +37,7 @@ insufficient_evidence는 탐지된 표현 증거나 관련 판례가 부족해
유사도 점수는 침해 확률이 아니다. 보호되는 표현, 의거관계, 권리 귀속 및 유사도 점수는 침해 확률이 아니다. 보호되는 표현, 의거관계, 권리 귀속 및
이용허락 사실이 없으면 missing_factors에 명시한다. 이용허락 사실이 없으면 missing_factors에 명시한다.
근거와 반대 근거는 검토자가 확인할 수 있는 짧은 사실 문장으로 작성한다. 근거와 반대 근거는 검토자가 확인할 수 있는 짧은 사실 문장으로 작성한다.
review_required는 항상 true로 반환한다.
""" """

View File

@ -7,7 +7,7 @@
1. 등록 코퍼스에서 유사 문서와 증거 구간을 찾는다. 1. 등록 코퍼스에서 유사 문서와 증거 구간을 찾는다.
2. `LegalRiskEngine`이 저작물 유형과 법적 태그로 등록 판례 Top 5를 고른다. 2. `LegalRiskEngine`이 저작물 유형과 법적 태그로 등록 판례 Top 5를 고른다.
3. GPT Judge가 탐지 증거와 Top 5 판례만 비교한다. 3. GPT Judge가 탐지 증거와 Top 5 판례만 비교한다.
4. 서버가 Structured Outputs 스키마, 판례 ID, `review_required=true`를 검증한다. 4. 서버가 Structured Outputs 스키마와 판례 ID를 검증하고, 사람 검토가 해제되지 않도록 `review_required=true`를 강제한다.
5. 호출 실패·형식 오류·미등록 판례 ID가 있으면 규칙 기반 결과로 복귀한다. 5. 호출 실패·형식 오류·미등록 판례 ID가 있으면 규칙 기반 결과로 복귀한다.
GPT는 전체 판례 545건을 한 번에 받지 않으며 법률상 침해를 확정하지 않는다. 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 "") 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( result = LegalRiskEngine([_case()], judge=_FakeJudge(review_required=False)).assess(
max_similarity=0.9, max_similarity=0.9,
coverage=0.5, coverage=0.5,
longest_span=200, longest_span=200,
legal_tags=["reproduction"], legal_tags=["reproduction"],
) )
assert result.judgment_method == "rule_fallback" assert result.judgment_method == "llm"
assert result.llm_review_required is None assert result.llm_review_required is True
def test_likely_judgment_without_precedent_id_falls_back(): def test_likely_judgment_without_precedent_id_falls_back():