Add an LLM fact-check pass over the generated briefing
After summarisation the report is verified against the collected payload (numbers, directions, unsupported claims) by a second LLM call with a Verification JSON schema. Major issues trigger one revision and a re-check; minor-only verdicts are normalized to ok. Failures never block delivery. The verdict is stored in the result JSON and shown on the dashboard (badge + 검증 메모). Disable with US2KR_VERIFY_ENABLED. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,6 +164,48 @@ def _bullets(items: list[str]) -> list[str]:
|
||||
return [f"- {item}" for item in items] or ["(없음)"]
|
||||
|
||||
|
||||
VERIFY_SYSTEM_PROMPT: str = """당신은 미국 시장 브리핑의 팩트체커입니다. 브리핑 초안이 함께 제공된 원본 데이터와
|
||||
모순되지 않는지만 검사합니다. 문체·구성·의견은 평가하지 않습니다.
|
||||
|
||||
## 검사 규칙
|
||||
1. 판단 근거는 사용자 메시지에 제공된 데이터(시세·히스토리 노트·뉴스·경제지표·실적)뿐입니다.
|
||||
당신의 배경지식이나 최신 시황과 달라 보여도, 제공된 데이터와 일치하면 문제가 아닙니다.
|
||||
2. major: 브리핑의 숫자가 데이터와 다르거나(반올림 오차 ±0.05는 허용), 상승/하락 방향이 반대이거나,
|
||||
데이터에 없는 숫자·사건을 사실처럼 서술한 경우.
|
||||
3. minor: 뉴스 헤드라인만으로 확인되지 않는 인과관계를 단정, 제공된 표기와 다른 종목명, 모호하지만
|
||||
틀렸다고 단정할 수 없는 서술.
|
||||
4. 각 이슈의 claim에는 브리핑 원문을 그대로 인용하고, problem에는 데이터의 실제 값과 함께 한 문장으로
|
||||
설명합니다.
|
||||
5. major 이슈가 하나도 없으면 ok=true 입니다. 사소한 트집을 만들지 말고, 문제가 없으면 빈 issues로
|
||||
반환합니다.
|
||||
6. 출력은 지정된 JSON 스키마만 반환합니다. 스키마 밖 텍스트·설명·코드 펜스를 추가하지 않습니다.
|
||||
"""
|
||||
|
||||
REVISE_INSTRUCTION: str = (
|
||||
"위 브리핑 초안에서 아래 검증 이슈가 발견되었습니다. 제공된 원본 데이터에 맞게 해당 서술만 고치고,"
|
||||
" 문제없는 부분은 그대로 유지하여 동일한 JSON 스키마로 전체 브리핑을 다시 출력하세요."
|
||||
" 설명 없이 JSON 객체 하나만 출력합니다.\n\n검증 이슈:\n"
|
||||
)
|
||||
|
||||
|
||||
def build_verify_message(payload: MarketPayload, report: Report) -> str:
|
||||
"""User message for the fact-check pass: the payload serialisation plus the draft report."""
|
||||
return (
|
||||
build_user_message(payload)
|
||||
+ "\n## 검증 대상 브리핑 초안 (JSON)\n"
|
||||
+ report.model_dump_json(indent=2)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
|
||||
def format_issues(issues: list) -> str:
|
||||
"""Issues -> numbered plain-text block for the revise instruction."""
|
||||
lines = []
|
||||
for i, issue in enumerate(issues, 1):
|
||||
lines.append(f"{i}. [{issue.severity}] 서술: {issue.claim}\n 문제: {issue.problem}")
|
||||
return "\n".join(lines) or "(없음)"
|
||||
|
||||
|
||||
def build_user_message(payload: MarketPayload) -> str:
|
||||
"""Serialise the payload into a deterministic Korean text block for the user message."""
|
||||
out: list[str] = []
|
||||
|
||||
Reference in New Issue
Block a user