dp-zp-agent/tools/answers/answer_format.py

46 lines
1.4 KiB
Python

"""Validate JSON without inventing facts or repairing values from benchmark gold."""
import json
import re
from typing import Literal
from pydantic import BaseModel, ConfigDict
class Claim(BaseModel):
model_config = ConfigDict(extra="forbid", strict=True)
person: str
title: str | None = None
year: int | None = None
start_year: int | None = None
keyword: str | None = None
category: str | None = None
document_author: str | None = None
record_id: str | None = None
work_type: str | None = None
work_label: str | None = None
class Answer(BaseModel):
model_config = ConfigDict(extra="forbid", strict=True)
answer: str
status: Literal["ok", "no_answer", "ambiguous", "error"]
claims: list[Claim]
source_urls: list[str]
count: int | None = None
def parse_answer(text: str) -> tuple[dict, bool]:
try:
data = json.loads(text.strip())
normalized = False
except json.JSONDecodeError:
# Exactly one complete JSON fence can be unwrapped. Never replace quotes,
# append missing braces, extract fragments or silently alter assertions.
blocks = re.findall(r"```(?:json)?\s*\n([\s\S]*?)```", text, flags=re.IGNORECASE)
if len(blocks) != 1:
raise
data = json.loads(blocks[0].strip())
normalized = True
parsed = Answer.model_validate(data)
return parsed.model_dump(exclude_none=True), normalized