Skip to content

Commit 40dcf54

Browse files
feat(compare): one narrative paragraph per interactivity target with templated variety
compareTableNarrative now returns string[] — one paragraph per ssrRow (3 default targets, so 3 paragraphs per slug page). Each paragraph picks a template from a per-situation pool: - PER_DOLLAR_BOTH_TEMPLATES — 6 variants for the cost-only narrative - PER_DOLLAR_TIED_TEMPLATES — 3 variants for the near-tie case - PER_DOLLAR_ZERO_TEMPLATES — 2 variants for zero-cost edge case - PER_DOLLAR_SINGLE_TEMPLATES — 3 variants for one-GPU-only rows - FULL_BOTH_TEMPLATES — 6 variants for cost+throughput narrative - FULL_SINGLE_TEMPLATES — 3 variants for one-GPU-only rows in full mode Template selection is SSR-deterministic via pickRotated(pool, pageSeed, rowIndex): the per-page hash picks where to START in the rotation; rowIndex advances by 1 from there. Result: - Same page renders the same 3 paragraphs every request (SSR + hydration agree, crawlers see stable text) - Different pages start at different points in the rotation → catalog reads with variety - Within a page, the 3 paragraphs always use 3 *distinct* templates — rotation avoids the birthday-problem collisions that random sampling of 3 from 6 produces Page-client renders the paragraph array, with the "(default selection)" caveat appended only to the last paragraph so the block reads as one piece of prose instead of three separate footnotes. Verified live: /compare-per-dollar/deepseek-v4-b200-vs-mi355x renders three different templates at 17/30/42 tok/s/user; /compare-per-dollar/kimi-k26-mi300x-vs-mi355x starts at a different template and also rotates through three distinct ones at 21/28/36 tok/s/user. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 10473c3 commit 40dcf54

3 files changed

Lines changed: 362 additions & 99 deletions

File tree

packages/app/src/app/compare-per-dollar/[slug]/page-client.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ interface ComparePerDollarPageClientProps {
3131
defaultSequence: string | null;
3232
defaultPrecision: string | null;
3333
ssrTableData: SsrTableData;
34-
/** SSR-rendered plain-English summary of the dollar-per-million-tokens table
35-
* at the mid target. Null when there's no comparable data. */
36-
narrative: string | null;
34+
/** One SSR-rendered prose paragraph per interpolated-table row (default
35+
* interactivity target). Each paragraph picks a template variant
36+
* deterministically from the slug so prose stays stable across renders
37+
* but varies across pages in the catalog. Empty array when there's no
38+
* comparable data. */
39+
narrative: string[];
3740
aLabel: string;
3841
bLabel: string;
3942
aVendor: string;
@@ -138,18 +141,28 @@ export default function ComparePerDollarPageClient({
138141
</Link>
139142
.
140143
</p>
141-
{narrative && (
142-
<p
143-
className="mt-3 text-sm text-foreground/80 max-w-3xl"
144+
{narrative.length > 0 && (
145+
<div
146+
className="mt-3 flex flex-col gap-2 max-w-3xl"
144147
data-testid="compare-per-dollar-narrative"
145148
>
146-
{narrative}{' '}
147-
<span className="text-muted-foreground italic">
148-
(Numbers reflect the default {defaultSequence ?? 'sequence'} ·{' '}
149-
{defaultPrecision ?? 'precision'} selection for this URL — table and chart below
150-
update if you change sequence, precision, or model in the controls.)
151-
</span>
152-
</p>
149+
{narrative.map((para, i) => (
150+
<p key={i} className="text-sm text-foreground/80">
151+
{para}
152+
{i === narrative.length - 1 && (
153+
<>
154+
{' '}
155+
<span className="text-muted-foreground italic">
156+
(Numbers reflect the default {defaultSequence ?? 'sequence'} ·{' '}
157+
{defaultPrecision ?? 'precision'} selection for this URL — table and
158+
chart below update if you change sequence, precision, or model in the
159+
controls.)
160+
</span>
161+
</>
162+
)}
163+
</p>
164+
))}
165+
</div>
153166
)}
154167
{(aCostPerGpuHr > 0 || bCostPerGpuHr > 0) && (
155168
<p

packages/app/src/app/compare/[slug]/page-client.tsx

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ interface ComparePageClientProps {
3434
defaultSequence: string | null;
3535
defaultPrecision: string | null;
3636
ssrTableData: SsrTableData;
37-
/** SSR-rendered plain-English summary of the interpolated table (mid-target
38-
* operating point + headline ratio). Null when there's no comparable data. */
39-
narrative: string | null;
37+
/** One SSR-rendered prose paragraph per interpolated-table row (default
38+
* interactivity target). Each paragraph picks a template variant
39+
* deterministically from the slug so prose stays stable across renders
40+
* but varies across pages in the catalog. Empty array when there's no
41+
* comparable data. */
42+
narrative: string[];
4043
aLabel: string;
4144
bLabel: string;
4245
aVendor: string;
@@ -115,18 +118,25 @@ export default function ComparePageClient({
115118
</Link>
116119
.
117120
</p>
118-
{narrative && (
119-
<p
120-
className="mt-3 text-sm text-foreground/80 max-w-3xl"
121-
data-testid="compare-narrative"
122-
>
123-
{narrative}{' '}
124-
<span className="text-muted-foreground italic">
125-
(Numbers reflect the default {defaultSequence ?? 'sequence'} ·{' '}
126-
{defaultPrecision ?? 'precision'} selection for this URL — table and chart below
127-
update if you change sequence, precision, or model in the controls.)
128-
</span>
129-
</p>
121+
{narrative.length > 0 && (
122+
<div className="mt-3 flex flex-col gap-2 max-w-3xl" data-testid="compare-narrative">
123+
{narrative.map((para, i) => (
124+
<p key={i} className="text-sm text-foreground/80">
125+
{para}
126+
{i === narrative.length - 1 && (
127+
<>
128+
{' '}
129+
<span className="text-muted-foreground italic">
130+
(Numbers reflect the default {defaultSequence ?? 'sequence'} ·{' '}
131+
{defaultPrecision ?? 'precision'} selection for this URL — table and
132+
chart below update if you change sequence, precision, or model in the
133+
controls.)
134+
</span>
135+
</>
136+
)}
137+
</p>
138+
))}
139+
</div>
130140
)}
131141
<p className="mt-2 text-sm">
132142
<Link

0 commit comments

Comments
 (0)