A confidence cascade lets the fast model decide and sends a call to a second model only when the first is unsure. The whole mechanism fits on a page:
def should_escalate(primary: Decision, threshold: float) -> bool:
conf = primary.confidence
return primary.error_kind is not None or conf is None or conf < threshold
class CascadeDecider:
def __init__(self, primary, fallback, threshold):
self.primary, self.fallback, self.threshold = primary, fallback, threshold
def decide(self, question, input):
first = self.primary.decide(question, input)
if not should_escalate(first, self.threshold):
return first
second = self.fallback.decide(question, input)
# if the fallback failed but the primary answered, keep the primary's answer
use = first if (first.error_kind is None and second.error_kind) else second
use.latency_ms = first.latency_ms + second.latency_ms # escalated calls pay twice
use.cost_usd = first.cost_usd + second.cost_usd
return use
Two details are worth copying. A primary failure always escalates, and an escalated call pays for both models in cost and latency, so report it that way. The threshold should come from labelled validation data, not a guess.
Now the honest caveat. In our benchmark, with Jev first and a small chat model as the fallback, the cascade barely helped: only 5.4%, 0.2% and 0% of calls escalated at the thresholds we would pick, and pushing the threshold higher dragged accuracy toward the fallback’s. A cascade only pays when the fallback is stronger than the primary, and ours was not. Test it with a stronger fallback on your own data before you build around it. If the primary and fallback are equally accurate, skip the cascade and keep the primary.