theanswer / view_model.py
Norod78's picture
v2 RAG client: playground layout, 09-28 styling
1e1b8a7 verified
Raw History Blame Contribute Delete
2.92 kB
"""Map v2 API JSON to ViewData. This is the only module that reads API field names.
Contract (v2/playground/README.md "Response contract"): status, answer, claims[]
{text, quote, slug, verified, mm:ss, ...}, triage[] {slug, label, reason}, warnings[],
plus the public API's episodes {slug: {title, date, url}}. Unknown fields are ignored.
"""
from __future__ import annotations
from dataclasses import dataclass
STATUSES = ("answered", "partial", "not_in_podcast", "false_premise", "refused", "error")
@dataclass(frozen=True)
class EpisodeView:
slug: str
title: str
date: str
url: str
@dataclass(frozen=True)
class ClaimView:
text: str
quote: str
verified: bool
episode: EpisodeView
timestamp: str
@dataclass(frozen=True)
class TriageView:
episode: EpisodeView
label: str
reason: str
@dataclass(frozen=True)
class ViewData:
status: str
answer_markdown: str
claims: tuple[ClaimView, ...]
sources: tuple[EpisodeView, ...] # cited episodes, first-cited order, unique
triage: tuple[TriageView, ...]
warnings: tuple[str, ...]
@property
def is_error(self) -> bool:
return self.status == "error"
def _s(value: object) -> str:
return value if isinstance(value, str) else ""
def map_api_response(data: object) -> ViewData:
if not isinstance(data, dict):
return ViewData("error", "", (), (), (), ())
status = _s(data.get("status"))
if status not in STATUSES:
status = "error"
raw_eps = data.get("episodes") if isinstance(data.get("episodes"), dict) else {}
def episode(slug: str) -> EpisodeView:
meta = raw_eps.get(slug) if isinstance(raw_eps.get(slug), dict) else {}
return EpisodeView(slug, _s(meta.get("title")), _s(meta.get("date")), _s(meta.get("url")))
claims: list[ClaimView] = []
for item in data.get("claims") if isinstance(data.get("claims"), list) else []:
if not isinstance(item, dict):
continue
claims.append(ClaimView(
text=_s(item.get("text")), quote=_s(item.get("quote")),
# Only an explicit true counts as verified.
verified=item.get("verified") is True,
episode=episode(_s(item.get("slug"))), timestamp=_s(item.get("mm:ss")),
))
sources: dict[str, EpisodeView] = {}
for claim in claims:
if claim.episode.slug:
sources.setdefault(claim.episode.slug, claim.episode)
triage = tuple(
TriageView(episode(_s(t.get("slug"))), _s(t.get("label")), _s(t.get("reason")))
for t in (data.get("triage") if isinstance(data.get("triage"), list) else []) if isinstance(t, dict)
)
warnings = tuple(str(w) for w in (data.get("warnings") if isinstance(data.get("warnings"), list) else []) if str(w).strip())
return ViewData(status, _s(data.get("answer")), tuple(claims), tuple(sources.values()), triage, warnings)