Type
refactor
Problem
PromptRenderer.render emits classes in the order names → terms → phrases, so
the highest-value content sits at the front of every rendered prompt.
Whisper conditions on the prompt through the <|startofprev|> channel
immediately preceding <|startoftranscript|>, and content nearest that boundary
is widely reported to carry outsized influence. OpenAI's reference decoder makes
the same judgement structurally — when an over-long initial_prompt must be
truncated it keeps the tail:
# whisper/decoding.py, DecodingTask._get_initial_tokens
tokens = [self.tokenizer.sot_prev] + prompt_tokens[-(self.n_ctx // 2 - 1):] + tokens
So the renderer currently puts the names — the exact content a context directory
exists to inject — in the position with the least conditioning weight, in every
prompt, not only when truncation happens.
Background
#164 reversed the engine-side clamp (design D4) to keep the prefix, because the
old suffix-keeping clamp dropped names outright on overflow. That fixed the
outright-drop, but it fixed it on the content-priority axis while the recency
argument lives on the position axis. Four independent review lenses judged D4 in
#164's verify round 1; none argued for reverting it, and three independently
derived the same durable remedy, which is also what PipelineWiringTests.swift
already says in a comment but does not implement:
reorder the renderer so the highest-value items land at the tail, not re-flip
the clamp against its own priority ordering
Expected
Highest-value items land nearest the decode boundary and survive truncation.
Concretely: renderer emits phrases → terms → names (or otherwise places names
last), while the clamp keeps whichever end now holds the names.
Both mechanisms then agree, and the context-calibration spec sentence "the
clamp SHALL preserve the highest-priority items" stays satisfied.
Notes
Type
refactor
Problem
PromptRenderer.renderemits classes in the order names → terms → phrases, sothe highest-value content sits at the front of every rendered prompt.
Whisper conditions on the prompt through the
<|startofprev|>channelimmediately preceding
<|startoftranscript|>, and content nearest that boundaryis widely reported to carry outsized influence. OpenAI's reference decoder makes
the same judgement structurally — when an over-long
initial_promptmust betruncated it keeps the tail:
So the renderer currently puts the names — the exact content a context directory
exists to inject — in the position with the least conditioning weight, in every
prompt, not only when truncation happens.
Background
#164 reversed the engine-side clamp (design D4) to keep the prefix, because the
old suffix-keeping clamp dropped names outright on overflow. That fixed the
outright-drop, but it fixed it on the content-priority axis while the recency
argument lives on the position axis. Four independent review lenses judged D4 in
#164's verify round 1; none argued for reverting it, and three independently
derived the same durable remedy, which is also what
PipelineWiringTests.swiftalready says in a comment but does not implement:
Expected
Highest-value items land nearest the decode boundary and survive truncation.
Concretely: renderer emits phrases → terms → names (or otherwise places names
last), while the clamp keeps whichever end now holds the names.
Both mechanisms then agree, and the
context-calibrationspec sentence "theclamp SHALL preserve the highest-priority items" stays satisfied.
Notes
it deserves a measurement rather than another reasoned flip: WER/CER on
proper-noun-bearing audio, current order vs. reordered.
context-calibrationdelta spec's worked example ("鄭澈, Che, benchmark-driven, CoreML") pins the current order and would need updating.trade-off; this is the resolution.