Spaces:
Running
Running
| /** | |
| * Rule-based plain-language summaries for the policy-mode views. | |
| * | |
| * Pure templating — no live LLM calls. Each function takes a structured | |
| * data object (model summary, eval summary, signal block) and returns | |
| * either a single sentence or a small struct of paragraph fragments. | |
| * | |
| * Templating rules of thumb: | |
| * - Lead with the headline (numbers / coverage), then the caveat. | |
| * - Pick exactly one phrasing per branch — readers should never see | |
| * two stitched-together fragments that mean the same thing. | |
| * - "Not specified" sentinels collapse silently (caller decides whether | |
| * to render the row at all). | |
| */ | |
| import type { ModelSummaryCore, BenchmarkEvaluation, MetricConfig } from "@/lib/benchmark-schema" | |
| import type { BenchmarkEvalSummary } from "@/lib/eval-processing" | |
| import type { ProvenanceSummary, ReproducibilitySummary, ComparabilitySummary } from "@/lib/backend-artifacts" | |
| import { formatTagLabel } from "@/lib/benchmark-tags" | |
| // --------------------------------------------------------------------------- | |
| // Sentence-list helpers (kept tiny & pure — no JSX, no React) | |
| // --------------------------------------------------------------------------- | |
| /** Oxford-comma list with "and". `["a","b","c"]` → `"a, b, and c"`. */ | |
| export function listAnd(items: readonly string[]): string { | |
| if (items.length === 0) return "" | |
| if (items.length === 1) return items[0] | |
| if (items.length === 2) return `${items[0]} and ${items[1]}` | |
| return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}` | |
| } | |
| /** Plural-aware count phrase. `(1, "result")` → `"1 result"`. */ | |
| export function pluralize(count: number, singular: string, plural?: string): string { | |
| return `${count.toLocaleString()} ${count === 1 ? singular : plural ?? `${singular}s`}` | |
| } | |
| /** | |
| * Categories the EvalCards taxonomy can express. We compare against this | |
| * canonical list to surface what *isn't* reported, not just what is. | |
| * | |
| * Sourced from data/benchmarks/categories.json — top-level tags that the | |
| * derivedTag pipeline produces. We list the headliners only; obscure | |
| * categories ("multilingual_general", "video_understanding") aren't | |
| * useful as gap-callouts on a policy summary. | |
| */ | |
| export const HEADLINE_POLICY_CATEGORIES = [ | |
| "general", | |
| "knowledge", | |
| "logical_reasoning", | |
| "applied_reasoning", | |
| "mathematics", | |
| "coding", | |
| "agentic", | |
| "safety", | |
| "multilingual_general", | |
| "multimodal", | |
| ] as const | |
| /** | |
| * Map a derivedTag category into a small bucket of "policy-relevant" | |
| * groupings, so e.g. logical_reasoning + applied_reasoning collapse to | |
| * "Reasoning" for a non-technical reader. Returns null when the input is | |
| * neither headlinable nor in the policy bucket map. | |
| */ | |
| const POLICY_BUCKETS: Record<string, string> = { | |
| general: "General capability", | |
| knowledge: "Knowledge", | |
| logical_reasoning: "Reasoning", | |
| applied_reasoning: "Reasoning", | |
| commonsense_reasoning: "Reasoning", | |
| mathematics: "Math", | |
| coding: "Coding", | |
| software_engineering: "Coding", | |
| agentic: "Agentic", | |
| safety: "Safety", | |
| multilingual_general: "Multilingual", | |
| multimodal: "Multimodal", | |
| } | |
| /** Group categories into ~6 policy-readable buckets. */ | |
| export function bucketCategories(tags: readonly string[]): string[] { | |
| const seen = new Set<string>() | |
| const out: string[] = [] | |
| for (const tag of tags) { | |
| const bucket = POLICY_BUCKETS[tag] | |
| if (bucket && !seen.has(bucket)) { | |
| seen.add(bucket) | |
| out.push(bucket) | |
| } | |
| } | |
| return out | |
| } | |
| const HEADLINE_BUCKET_LIST = ["General capability", "Knowledge", "Reasoning", "Math", "Coding", "Agentic", "Safety"] as const | |
| /** Buckets we'd expect a frontier general-purpose model to report on. */ | |
| function expectedBuckets(): readonly string[] { | |
| return HEADLINE_BUCKET_LIST | |
| } | |
| // --------------------------------------------------------------------------- | |
| // MODEL view — produces the Measures / Caveat / Coverage / Reporting block. | |
| // --------------------------------------------------------------------------- | |
| export interface ModelPolicySummary { | |
| /** "Reported across N benchmarks in K categories." */ | |
| scopeSentence: string | |
| /** "Coverage spans Reasoning, Knowledge, and Agentic." (or null when there's only one category) */ | |
| coverageSentence: string | null | |
| /** "No Safety or Math evaluations have been reported." Returns null when nothing material is missing. */ | |
| gapSentence: string | null | |
| /** "Reported by Anthropic (the developer) and one independent third party." */ | |
| reportingSentence: string | |
| /** "How this model was prompted is documented for X of Y reported scores." or null when fully documented / no data. */ | |
| reproducibilitySentence: string | null | |
| /** "Comparing scores directly is limited because reporting setups differ." or null. */ | |
| comparabilitySentence: string | null | |
| /** "Independently verified across N benchmarks." used as the optional headline tag. */ | |
| verificationLabel: string | null | |
| } | |
| interface ModelPolicyInputs { | |
| /** Accepts any ModelSummaryCore-shaped object — the model page passes | |
| * either the family summary or a selected variant. We only read the | |
| * signal-summary blocks plus `total_evaluations`. */ | |
| summary: ModelSummaryCore | |
| /** Pre-computed third-party tally from caller (cheap to compute, but | |
| * caller already has it in benchmark-detail). */ | |
| thirdPartyEvaluations: number | |
| /** Denominator for the third-party share. MUST be counted from the same | |
| * population as `thirdPartyEvaluations` (the caller's flattened evaluation | |
| * list), not the warehouse's distinct `total_evaluations` — those have | |
| * different grains, which made the share exceed 100%. */ | |
| reportedEvaluationCount: number | |
| organizationCount: number | |
| organizationNames: string[] | |
| /** Distinct benchmark count derived from group reduction. */ | |
| benchmarkCount: number | |
| /** Categories actually reported, derived-tag form (snake_case). */ | |
| reportedCategories: readonly string[] | |
| } | |
| export function buildModelPolicySummary({ | |
| summary, | |
| thirdPartyEvaluations, | |
| reportedEvaluationCount, | |
| organizationCount, | |
| organizationNames, | |
| benchmarkCount, | |
| reportedCategories, | |
| }: ModelPolicyInputs): ModelPolicySummary { | |
| const totalEvals = summary.total_evaluations | |
| // Denominator for the third-party share, counted from the same population as | |
| // the numerator so the ratio stays within 0–100%. Falls back to totalEvals | |
| // only if the caller passed nothing. | |
| const thirdPartyBase = reportedEvaluationCount > 0 ? reportedEvaluationCount : totalEvals | |
| const repro = summary.reproducibility_summary | |
| const reproGap = repro?.has_reproducibility_gap_count ?? 0 | |
| const reproTotal = repro?.results_total ?? totalEvals | |
| const provenance = summary.provenance_summary | |
| const comparability = summary.comparability_summary | |
| // ── 1. Scope ──────────────────────────────────────────────────────────── | |
| const scopeSentence = | |
| benchmarkCount === 0 | |
| ? "No benchmark evaluations have been reported for this model." | |
| : `Reported across ${pluralize(benchmarkCount, "benchmark")}` + | |
| (totalEvals > benchmarkCount | |
| ? ` (${pluralize(totalEvals, "result")} total).` | |
| : ".") | |
| // ── 2. Coverage / Gap (the "missing categories" piece the user wanted) ── | |
| const reportedBuckets = bucketCategories(reportedCategories) | |
| let coverageSentence: string | null = null | |
| let gapSentence: string | null = null | |
| if (reportedBuckets.length > 1) { | |
| coverageSentence = `Coverage spans ${listAnd(reportedBuckets)}.` | |
| } else if (reportedBuckets.length === 1) { | |
| coverageSentence = `Coverage is concentrated in ${reportedBuckets[0]} only.` | |
| } | |
| if (reportedBuckets.length > 0) { | |
| const reportedSet = new Set(reportedBuckets) | |
| const missing = expectedBuckets().filter((b) => !reportedSet.has(b)) | |
| // Only flag a gap when there's a meaningful absence — at least one | |
| // category reported AND at least one common bucket missing. We cap the | |
| // list at three to stay readable. | |
| if (missing.length > 0 && missing.length < expectedBuckets().length) { | |
| const head = missing.slice(0, 3) | |
| const trail = missing.length > 3 ? ` (and ${missing.length - 3} other categories)` : "" | |
| gapSentence = | |
| head.length === 1 | |
| ? `No ${head[0]} evaluations have been reported.` | |
| : `No ${listAnd(head)} evaluations have been reported${trail}.` | |
| } | |
| } | |
| // ── 3. Reporting (provenance) ─────────────────────────────────────────── | |
| const firstPartyOnly = | |
| provenance?.first_party_only_groups != null && provenance.total_groups > 0 | |
| ? provenance.first_party_only_groups === provenance.total_groups | |
| : null | |
| const allThirdParty = thirdPartyBase > 0 && thirdPartyEvaluations === thirdPartyBase | |
| const noThirdParty = thirdPartyEvaluations === 0 && thirdPartyBase > 0 | |
| const lead = organizationNames[0] | |
| let reportingSentence: string | |
| if (organizationCount === 0) { | |
| reportingSentence = "No reporting organization is recorded." | |
| } else if (organizationCount === 1 && lead) { | |
| reportingSentence = allThirdParty | |
| ? `Tested independently by ${lead} (a third party, not the model's developer).` | |
| : noThirdParty | |
| ? `Reported only by ${lead}; no independent third-party scores are available.` | |
| : `Reported by ${lead}.` | |
| } else if (lead) { | |
| const others = organizationCount - 1 | |
| reportingSentence = allThirdParty | |
| ? `Tested independently by ${lead} and ${pluralize(others, "other organization")}.` | |
| : noThirdParty | |
| ? `Reported by ${lead} and ${pluralize(others, "other organization")}, but no independent third-party scores are available.` | |
| : `Reported by ${lead} and ${pluralize(others, "other organization")}.` | |
| } else { | |
| reportingSentence = `Reported by ${pluralize(organizationCount, "organization")}.` | |
| } | |
| // ── 4. Reproducibility gap (plain language, no field names) ──────────── | |
| let reproducibilitySentence: string | null = null | |
| if (reproTotal > 0) { | |
| if (reproGap === 0) { | |
| reproducibilitySentence = "How this model was prompted during testing is documented for every reported score." | |
| } else if (reproGap === reproTotal) { | |
| reproducibilitySentence = | |
| "How this model was prompted during testing is not documented. Scores cannot be independently re-run as reported." | |
| } else { | |
| const documented = reproTotal - reproGap | |
| const pct = Math.round((documented / reproTotal) * 100) | |
| reproducibilitySentence = `Prompting setup is documented for ${pct}% of reported scores (${documented} of ${reproTotal}); the rest are missing enough detail to be re-run as-is.` | |
| } | |
| } | |
| // ── 5. Comparability caveat (no field names) ────────────────────────── | |
| let comparabilitySentence: string | null = null | |
| if (comparability) { | |
| const variantHits = comparability.variant_divergent_count | |
| const crossPartyHits = comparability.cross_party_divergent_count | |
| const noCrossPartyChecks = comparability.groups_with_cross_party_check === 0 | |
| if (variantHits === 0 && crossPartyHits === 0 && !noCrossPartyChecks) { | |
| comparabilitySentence = "Where multiple reports are available, scores agree closely across setups and reporters." | |
| } else if (variantHits > 0 && crossPartyHits > 0) { | |
| comparabilitySentence = `Scores diverge across reporting setups in ${pluralize(variantHits, "case")} and across different reporters in ${pluralize(crossPartyHits, "case")}; some apparent score gaps may reflect setup choices rather than capability.` | |
| } else if (variantHits > 0) { | |
| comparabilitySentence = `Scores diverge across reporting setups in ${pluralize(variantHits, "case")}; apparent score gaps may partly reflect those setup choices.` | |
| } else if (crossPartyHits > 0) { | |
| comparabilitySentence = `Different reporters disagree on ${pluralize(crossPartyHits, "score")}; treat headline numbers as a range rather than a single value.` | |
| } else if (noCrossPartyChecks) { | |
| comparabilitySentence = "No third-party reports are available to cross-check the developer's numbers." | |
| } | |
| } else if (firstPartyOnly === true) { | |
| comparabilitySentence = "Only the model's developer has reported these scores; cross-party comparison is not possible." | |
| } | |
| // ── 6. Verification headline ───────────────────────────────────────── | |
| let verificationLabel: string | null = null | |
| if (allThirdParty && thirdPartyBase > 0) { | |
| verificationLabel = "100% third party" | |
| } else if (thirdPartyEvaluations > 0 && thirdPartyBase > 0) { | |
| const pct = Math.min(100, Math.round((thirdPartyEvaluations / thirdPartyBase) * 100)) | |
| verificationLabel = `${pct}% third party` | |
| } else if (noThirdParty) { | |
| verificationLabel = "Developer-reported only" | |
| } | |
| return { | |
| scopeSentence, | |
| coverageSentence, | |
| gapSentence, | |
| reportingSentence, | |
| reproducibilitySentence, | |
| comparabilitySentence, | |
| verificationLabel, | |
| } | |
| } | |
| // --------------------------------------------------------------------------- | |
| // EVAL view — produces single-sentence narrative for each of the four | |
| // interpretive signals (used by the policy-mode panel renderers). | |
| // --------------------------------------------------------------------------- | |
| export interface EvalPolicySignals { | |
| metricSentence: string | |
| reproducibilitySentence: string | null | |
| provenanceSentence: string | null | |
| comparabilitySentence: string | null | |
| } | |
| export function buildEvalPolicySignals(summary: BenchmarkEvalSummary): EvalPolicySignals { | |
| const cfg = summary.metric_config | |
| const metricSentence = formatMetricSentence(cfg) | |
| const reproducibilitySentence = formatReproducibilitySentence(summary.reproducibility_summary) | |
| const provenanceSentence = formatProvenanceSentence(summary) | |
| const comparabilitySentence = formatComparabilitySentence(summary.comparability_summary) | |
| return { | |
| metricSentence, | |
| reproducibilitySentence, | |
| provenanceSentence, | |
| comparabilitySentence, | |
| } | |
| } | |
| function formatMetricSentence(cfg: MetricConfig): string { | |
| const lower = cfg.lower_is_better | |
| const min = cfg.min_score | |
| const max = cfg.max_score | |
| const direction = lower | |
| ? "Lower scores indicate better performance" | |
| : "Higher scores indicate better performance" | |
| // Only mention the scale when both ends are documented and look like a | |
| // tidy interval. Otherwise the sentence collapses to direction-only. | |
| if (typeof min === "number" && typeof max === "number" && max > min) { | |
| if (min === 0 && max === 1) return `${direction}, on a 0 to 1 scale.` | |
| if (min === 0 && max === 100) return `${direction}, on a 0 to 100 scale.` | |
| return `${direction}, on a ${min} to ${max} scale.` | |
| } | |
| return `${direction}.` | |
| } | |
| function formatReproducibilitySentence(repro?: ReproducibilitySummary): string | null { | |
| if (!repro || repro.results_total === 0) return null | |
| const total = repro.results_total | |
| const gap = repro.has_reproducibility_gap_count | |
| if (gap === 0) { | |
| return "How models were prompted during testing is documented for every reported score." | |
| } | |
| if (gap === total) { | |
| return "How models were prompted during testing is not documented. Scores cannot be independently re-run as reported." | |
| } | |
| const documented = total - gap | |
| const pct = Math.round((documented / total) * 100) | |
| return `Prompting setup is documented for ${pct}% of reported scores (${documented} of ${total}).` | |
| } | |
| function formatProvenanceSentence(summary: BenchmarkEvalSummary): string | null { | |
| const prov: ProvenanceSummary | undefined = summary.provenance_summary | |
| if (!prov) { | |
| // Fall back to coarser ratio when the summary isn't attached. | |
| if (summary.third_party_ratio === 0) { | |
| return "These scores were reported only by the model developers themselves." | |
| } | |
| if (summary.third_party_ratio === 1) { | |
| return "These scores were reported by independent third parties, not the model developers." | |
| } | |
| return null | |
| } | |
| const total = prov.total_groups | |
| if (total === 0) return null | |
| const firstPartyOnly = prov.first_party_only_groups | |
| const multi = prov.multi_source_groups | |
| if (firstPartyOnly === total) { | |
| return "Every reported score on this benchmark comes only from the model's own developer; no independent third-party numbers are available." | |
| } | |
| if (firstPartyOnly === 0 && multi === 0) { | |
| return "All reported scores come from independent third parties rather than the model developers." | |
| } | |
| if (multi > 0) { | |
| const pctMulti = Math.round((multi / total) * 100) | |
| return `${pctMulti}% of reported scores have been corroborated by more than one reporting organization.` | |
| } | |
| return null | |
| } | |
| function formatComparabilitySentence(comp?: ComparabilitySummary): string | null { | |
| if (!comp || comp.total_groups === 0) return null | |
| const variant = comp.variant_divergent_count | |
| const crossParty = comp.cross_party_divergent_count | |
| const noCrossPartyChecks = comp.groups_with_cross_party_check === 0 | |
| if (variant === 0 && crossParty === 0 && !noCrossPartyChecks) { | |
| return "Where multiple reports exist, the scores agree closely; direct comparison across reports is reasonable." | |
| } | |
| if (variant > 0 && crossParty > 0) { | |
| return "These scores have been reported under different setups and by different organizations, which may explain some of the variation seen across reports." | |
| } | |
| if (variant > 0) { | |
| return "These scores have been reported under different evaluation setups, which may explain some of the variation across reports." | |
| } | |
| if (crossParty > 0) { | |
| return "Different organizations have reported notably different numbers for the same model on this benchmark." | |
| } | |
| if (noCrossPartyChecks) { | |
| return "No independent third-party reports are available to cross-check the developer's numbers." | |
| } | |
| return null | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Helpers used by the existing policySummary lede in benchmark-detail.tsx, | |
| // re-exported so the inline copy can be replaced. | |
| // --------------------------------------------------------------------------- | |
| /** | |
| * Pull derived-tag categories off a flat list of evaluations. Useful when the | |
| * caller already has the per-result entries grouped in the page. | |
| */ | |
| export function collectReportedCategoriesFromEvals( | |
| evaluations: readonly BenchmarkEvaluation[], | |
| resolveCategory: (e: BenchmarkEvaluation) => string | null | undefined | |
| ): string[] { | |
| const seen = new Set<string>() | |
| const out: string[] = [] | |
| for (const evaluation of evaluations) { | |
| const cat = resolveCategory(evaluation) | |
| if (!cat) continue | |
| if (!seen.has(cat)) { | |
| seen.add(cat) | |
| out.push(cat) | |
| } | |
| } | |
| return out | |
| } | |
| /** "Reasoning, Knowledge, Agentic" — for compact category badge rows. */ | |
| export function formatPolicyBucketsCompact(tags: readonly string[]): string { | |
| return bucketCategories(tags).join(" · ") | |
| } | |
| /** Pretty-print a derivedTag for the rare case the policy bucket falls | |
| * through (we still want a friendly word, not snake_case). */ | |
| export function formatTagAsPolicyLabel(tag: string): string { | |
| return formatTagLabel(tag) | |
| } | |