Skip to content

fix(routing): calibrate quality dial against real mix crossovers#479

Merged
steventohme merged 2 commits into
mainfrom
steven/router-dial-equalization
Jun 22, 2026
Merged

fix(routing): calibrate quality dial against real mix crossovers#479
steventohme merged 2 commits into
mainfrom
steven/router-dial-equalization

Conversation

@steventohme

Copy link
Copy Markdown
Collaborator

Problem

Reported by a user testing the quality-vs-price dial: 50/50 routes essentially the same mix as 20/80 — both land on the two cheapest models, with nothing in between, and the mix only "wakes up" near the top of the slider.

The dispersion-bend dial from #476 bent a per-cluster alpha by quality dispersion and remapped it onto a cost band. That trimmed the outer flat regions (the all-cheapest floor and the saturated ceiling) but not interior ones. On the deployed bundle the routed mix is identical across alpha ≈ 0.45–0.62, so the dial still showed one frozen mix from ~20% to ~55%. The bend is computed blind to where crossovers actually sit, so it structurally can't remove an interior dead zone.

Fix

Calibrate the dial against the bundle's actual routing behavior. At scorer build, sweep a uniform alpha 0→1, score every cluster centroid through the same blend as live routing, and record the alpha at which the routed mix (the multiset of per-cluster winners) changes. Those breakpoints — ascending, first pinned to 0, last to 1 — are placed at equal dial spacing and interpolated by dialToAlpha. Equal dial travel then crosses an equal number of mix changes, so every part of the slider moves the mix.

This subsumes the dispersion bend (uniform alpha already routes high-dispersion clusters to quality earlier), so the per-cluster dispersion-rank + cost-band machinery is removed. The Alpha sledgehammer (eval/debug header) path is unchanged.

Result (deployed v0.68, projected $/1k input)

dial before after
0% cheapest 100% gemini-3.1-flash-lite ($0.10)
20% all-cheapest flash-lite + gemini-3.5-flash mix ($0.33)
50% same as 20% gemini-3.1-pro 38% dominant ($1.16)
75% still mostly cheap gemini-3.1-pro 100% ($2.00)
100% opus best-per-cluster: 62% opus / 38% gemini-3.1-pro ($3.88)

Cost now rises smoothly and monotonically across the whole slider; the endpoints stay honest (all-cheapest / best-per-cluster).

Tests

  • dialToAlpha: endpoints pin, monotone, interpolates between breakpoints, identity fallback with no calibration.
  • computeDialCalibration: ascending, endpoint-pinned, multiple interior breakpoints on the real bundle.
  • RoutingDistribution: no dead zone (no long run of identical adjacent mixes), and the 50% dial routes a materially pricier mix than the 20% dial (the reported symptom, as a regression guard).

🤖 Generated with Claude Code

…ling dead zones

The QualityBias dial (#476) bent a per-cluster alpha by quality dispersion
and remapped it onto a cost band. That removed the *outer* flat regions but
not interior ones: on the deployed bundle the routed mix is identical across
alpha ~0.45-0.62, so the dial still showed the same model mix from ~20% all
the way to ~55% ("50/50 looks exactly like 20/80"). The bend operates blind
to where crossovers actually are, so it can't fix an interior dead zone.

Replace it with a per-bundle calibration. At scorer build, sweep a uniform
alpha 0->1, scoring every cluster centroid through the live blend, and record
the alpha at which the routed mix (multiset of per-cluster winners) changes.
Those breakpoints — ascending, first pinned to 0, last to 1 — are placed at
equal dial spacing and interpolated, so equal dial travel crosses an equal
number of mix changes. Every part of the slider now does something.

On v0.68 the projected cost now rises smoothly $0.10 -> $3.88 per 1k input
across the dial: t=0 is 100% cheapest, t=0.5 is gemini-3.1-pro-dominant, t=1
is the best-per-cluster mix (62% opus / 38% gemini-3.1-pro). The endpoints
stay honest (all-cheapest / best-per-cluster); only the path between them is
recalibrated.

Removes the now-unused dispersion-rank + cost-band machinery. The Alpha
sledgehammer (eval/debug header) path is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Reviews (1): Last reviewed commit: "fix(routing): calibrate quality dial aga..." | Re-trigger Greptile

Comment thread internal/router/cluster/scorer.go Outdated
Comment thread internal/router/cluster/distribution_test.go
…zone test

PR review (greptile):
- computeDialCalibration now skips an empty argmax winner, matching
  RoutingDistribution's accounting, so a cluster flipping between "" and a
  real model can't inject a phantom dial breakpoint.
- The mid-vs-low regression test now requires the 0.2 dial point to be
  present, so the assertion can't silently degrade to a no-op if the grid
  changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@steventohme
steventohme merged commit ed35c1c into main Jun 22, 2026
10 checks passed
@steventohme
steventohme deleted the steven/router-dial-equalization branch June 22, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant