Skip to content

Commit 238be51

Browse files
authored
Merge branch 'main' into add/cli-profiles
2 parents 6c6e015 + 7cb3f3e commit 238be51

9 files changed

Lines changed: 752 additions & 27 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
import React from 'react';
2+
3+
/**
4+
* Static diagram for the best-of-N self-verification fix:
5+
* one prompt → the TTS model draws several candidate takes →
6+
* ASR transcribes each → keep the take whose transcript matches the text.
7+
*
8+
* Theme-aware: strokes and text use `currentColor`, so it adapts to
9+
* light/dark mode. Pass/fail accents use fixed accessible green/red.
10+
*/
11+
export default function BestOfNDiagram(): JSX.Element {
12+
const ok = '#2e8b57';
13+
const bad = '#d9534f';
14+
15+
// y-centres for the three candidate rows
16+
const rows = [56, 130, 204];
17+
18+
return (
19+
<figure style={{ margin: '2rem 0' }}>
20+
<svg
21+
viewBox="0 0 760 260"
22+
role="img"
23+
aria-label="One prompt is sampled into several candidate takes; each is transcribed by ASR; the take whose transcript matches the text is kept."
24+
style={{
25+
width: '100%',
26+
height: 'auto',
27+
color: 'var(--ifm-font-color-base)',
28+
}}
29+
fill="none"
30+
>
31+
{/* Stage labels */}
32+
<g
33+
fontSize="12"
34+
fontWeight={600}
35+
textAnchor="middle"
36+
fill="currentColor"
37+
opacity={0.6}
38+
>
39+
<text x="70" y="20">
40+
Prompt
41+
</text>
42+
<text x="300" y="20">
43+
Sample N takes
44+
</text>
45+
<text x="500" y="20">
46+
Transcribe (ASR)
47+
</text>
48+
<text x="680" y="20">
49+
Keep the match
50+
</text>
51+
</g>
52+
53+
{/* Prompt / TTS model box */}
54+
<rect
55+
x="20"
56+
y="100"
57+
width="100"
58+
height="60"
59+
rx="8"
60+
stroke="currentColor"
61+
strokeWidth={1.5}
62+
/>
63+
<text
64+
x="70"
65+
y="126"
66+
fontSize="12"
67+
textAnchor="middle"
68+
fill="currentColor"
69+
>
70+
TTS model
71+
</text>
72+
<text
73+
x="70"
74+
y="144"
75+
fontSize="11"
76+
textAnchor="middle"
77+
fill="currentColor"
78+
opacity={0.6}
79+
>
80+
“…brown fox”
81+
</text>
82+
83+
{/* Fan-out arrows from model to each candidate */}
84+
{rows.map((y) => (
85+
<path
86+
key={`fan-${y}`}
87+
d={`M120 130 C 160 130, 170 ${y}, 200 ${y}`}
88+
stroke="currentColor"
89+
strokeWidth={1.25}
90+
opacity={0.5}
91+
/>
92+
))}
93+
94+
{/* Candidate takes (waveforms) + ASR transcripts + verdicts */}
95+
{[
96+
{ wave: 'flat', text: '(silence)', good: false },
97+
{ wave: 'speech', text: '“…brown fox”', good: true },
98+
{ wave: 'loop', text: '“fox fox fox”', good: false },
99+
].map((c, i) => {
100+
const y = rows[i];
101+
const accent = c.good ? ok : bad;
102+
// simple waveform glyphs
103+
const wave =
104+
c.wave === 'flat'
105+
? `M210 ${y} L290 ${y}`
106+
: c.wave === 'loop'
107+
? `M210 ${y} q10 -14 20 0 q10 14 20 0 q10 -14 20 0 q10 14 20 0`
108+
: `M210 ${y} q6 -16 12 0 q6 18 12 0 q6 -22 12 0 q6 14 12 0 q6 -10 12 0 q6 16 12 0`;
109+
return (
110+
<g key={`cand-${i}`}>
111+
{/* candidate take */}
112+
<rect
113+
x="200"
114+
y={y - 26}
115+
width="100"
116+
height="52"
117+
rx="8"
118+
stroke="currentColor"
119+
strokeWidth={1.25}
120+
opacity={0.8}
121+
/>
122+
<path
123+
d={wave}
124+
stroke={accent}
125+
strokeWidth={1.75}
126+
strokeLinecap="round"
127+
/>
128+
129+
{/* arrow candidate -> transcript */}
130+
<path
131+
d={`M300 ${y} L360 ${y}`}
132+
stroke="currentColor"
133+
strokeWidth={1.25}
134+
opacity={0.5}
135+
markerEnd="url(#arrow)"
136+
/>
137+
138+
{/* transcript box */}
139+
<rect
140+
x="360"
141+
y={y - 20}
142+
width="160"
143+
height="40"
144+
rx="8"
145+
stroke="currentColor"
146+
strokeWidth={1.25}
147+
opacity={0.8}
148+
/>
149+
<text
150+
x="440"
151+
y={y + 4}
152+
fontSize="12"
153+
textAnchor="middle"
154+
fill="currentColor"
155+
>
156+
{c.text}
157+
</text>
158+
159+
{/* verdict */}
160+
<text
161+
x="548"
162+
y={y + 6}
163+
fontSize="18"
164+
fontWeight={700}
165+
textAnchor="middle"
166+
fill={accent}
167+
>
168+
{c.good ? '✓' : '✗'}
169+
</text>
170+
</g>
171+
);
172+
})}
173+
174+
{/* arrow from the matching transcript to the kept take */}
175+
<path
176+
d={`M572 ${rows[1]} C 620 ${rows[1]}, 620 ${rows[1]}, 640 ${rows[1]}`}
177+
stroke={ok}
178+
strokeWidth={1.75}
179+
markerEnd="url(#arrowOk)"
180+
/>
181+
182+
{/* kept take box */}
183+
<rect
184+
x="640"
185+
y={rows[1] - 26}
186+
width="100"
187+
height="52"
188+
rx="8"
189+
stroke={ok}
190+
strokeWidth={1.75}
191+
/>
192+
<text
193+
x="690"
194+
y={rows[1] + 4}
195+
fontSize="12"
196+
fontWeight={600}
197+
textAnchor="middle"
198+
fill="currentColor"
199+
>
200+
clean take
201+
</text>
202+
203+
{/* arrowheads */}
204+
<defs>
205+
<marker
206+
id="arrow"
207+
viewBox="0 0 10 10"
208+
refX="8"
209+
refY="5"
210+
markerWidth="6"
211+
markerHeight="6"
212+
orient="auto-start-reverse"
213+
>
214+
<path d="M0 0 L10 5 L0 10 z" fill="currentColor" opacity={0.5} />
215+
</marker>
216+
<marker
217+
id="arrowOk"
218+
viewBox="0 0 10 10"
219+
refX="8"
220+
refY="5"
221+
markerWidth="7"
222+
markerHeight="7"
223+
orient="auto-start-reverse"
224+
>
225+
<path d="M0 0 L10 5 L0 10 z" fill={ok} />
226+
</marker>
227+
</defs>
228+
</svg>
229+
<figcaption
230+
style={{
231+
fontSize: '0.85rem',
232+
textAlign: 'center',
233+
opacity: 0.7,
234+
marginTop: '0.5rem',
235+
}}
236+
>
237+
Best-of-N self-verification: sample several takes for one prompt,
238+
transcribe each with ASR, and keep the take whose transcript matches the
239+
text. A prompt only fails if <em>every</em> take is broken.
240+
</figcaption>
241+
</figure>
242+
);
243+
}

0 commit comments

Comments
 (0)