promptstat / ui /scoring /interface.py
xxixx1028's picture
Deploy PromptStat — UI shell + MiniCPM4.1-8B + 4-LoRA hybrid (Modal)
dc9f530 verified
Raw
History Blame Contribute Delete
1.69 kB
"""The scorer interface — the single seam between the UI and any scoring backend.
A `Scorer` turns a `ParsedExport` into a `ScoreResult` (5 axis scores 0-10, critical-type
counts, per-axis confidence, evidence quotes, tips, one improvement line). `score_to_card`
maps that result onto the UI's `CardData`. The real ML model implements `Scorer.score` with
the same signature; nothing in the UI changes.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Protocol
from ..data import AXES, Axis, CardData, CriticalBreakdown
from ..parsing import ParsedExport
@dataclass
class AxisScore:
name: str
score: float # 0-10
confidence: str # high | medium | low
evidence: list[str]
tip: str
@dataclass
class ScoreResult:
axes: list[AxisScore]
critical_counts: dict[str, int] # skepticism, source_req, rebuttal, verify, re_ask
improvement: str
class Scorer(Protocol):
def score(self, parsed: ParsedExport, progress=None) -> ScoreResult:
...
def score_to_card(result: ScoreResult, name: str) -> CardData:
"""Adapt a backend-agnostic ScoreResult into the UI's CardData."""
c = result.critical_counts
return CardData(
name=(name or "").strip() or "Anonymous",
axes=[Axis(a.name, round(a.score, 1), a.confidence, a.evidence, a.tip) for a in result.axes],
critical=CriticalBreakdown(
skepticism=c.get("skepticism", 0),
source_req=c.get("source_req", 0),
rebuttal=c.get("rebuttal", 0),
verify=c.get("verify", 0),
re_ask=c.get("re_ask", 0),
),
improvement=result.improvement,
)