Belay · findings · October 2026

On-device AI first, the cloud only when unsure: what it saves, and when it's also more accurate

Belay runs an AI task on a small model in the browser and sends the input to a cloud model only when the small model's confidence is below a threshold. We calibrated that threshold on four real tasks against three cloud models, priced every cloud call from its measured token usage, and checked every result on held-out data.

The short version

  1. A calibrated cascade can be more accurate than the cloud model alone, not just cheaper. On ticket triage, an on-device model plus Claude Opus 5.5 scored 97.3% on held-out data against 94.3% for Claude alone, for about half the cloud bill. It happened with every cloud model we tried on triage and moderation.
  2. Calibrate against the cloud's accuracy, not a fixed number. A 95% target let the cascade trade accuracy for savings on a task where the cloud reached 99%.
  3. Which cloud model you escalate to matters as much as the cascade. The same classification cost $15, $172 or $1,582 per million runs, depending on the model.
  4. When the local model knows nothing the cloud doesn't, the cascade only saves money. On intent detection it kept about a third of the runs on device at the cloud's accuracy, give or take one example.
  5. A local model that learns from the cloud's answers takes over narrow tasks. Starting from nothing, it answered 86% of 1,500 support messages on the device at 99.7% accuracy, and it kept escalating where it couldn't tell. Details · demo.
  6. For generation, the judge is the bottleneck. Gemini Nano extracted calendar events reasonably well, but no confidence signal we tried could tell its right answers from its wrong ones well enough to keep many on device.

Accuracy against cost

Each line goes from a cloud model on its own (hollow dot) to the same cloud behind Belay (filled dot): the on-device model answers when it is confident enough, the cloud model answers the rest. Up is more accurate, left is cheaper. Accuracy is the held-out estimate (five-fold cross-validation); cost is per million runs, at list prices.

The cost axis is logarithmic and shared; each task has its own accuracy axis. Intent detection's Jev → Claude chain is in the table below. Jev answers choice and yes/no questions only, so it has no event-extraction point. With 300 examples (240 for extraction), one percentage point is three examples (2.4).

What we learned

1. The cascade can beat the cloud, because the local model is sometimes right where the cloud is wrong

A cascade can only be as accurate as its two models allow. It gains accuracy when, among the runs it keeps on device, the local model is right where the cloud model is wrong more often than the reverse. On ticket triage, the local model (Laya, an open classification model running in the browser) was right on 93% of messages on its own, and almost always right when it was very sure. The 141 messages it answered at confidence ≥ 0.984 included 10 that Claude got wrong and none that Claude got right and Laya didn't.

Held out, the triage cascade gained 3.0 points over Claude, 3.3 over Gemini 3.8 Flash and 2.7 over Jev, while cutting each one's bill by 52–61%. On content moderation it gained 0.7–2.3 points and cut the bill by 78–82%.

2. Calibrate against the cloud, not against a number

Our first calibrations used a fixed 95% accuracy target. On intent detection, Claude alone reached 99.3%, so the threshold that "met the target" kept 87% of runs on a less accurate local model: cheaper than the cloud, and worse. That is not what anyone wants from a cascade. Belay's default target is now 'cloud', the cloud model's own accuracy on your data: the cheapest threshold that loses nothing. 'max' picks the most accurate threshold, which is what the examples here use.

3. The choice of cloud model moves the bill by two orders of magnitude

Every cloud call was priced from the tokens it actually used. Per million classifications:

Because Jev reports its own confidence, it can be a cascade tier too. For intent detection, Jev first and Claude only when Jev is under 0.8 confident scored 99.7%, as accurate as Claude, for $71 per million runs instead of $2,301. Adding a third tier everywhere (on-device → Jev → Claude) helped less: on triage it reached 95.3% for $99, between Laya → Jev (95.0%, $8) and Laya → Claude (97.3%, $967). Jev's confidence doesn't pick out the runs where Claude would do better.

A cheaper cloud model shrinks what a cascade can save in dollars, not in share: Laya kept 72% of triage runs on device in front of Gemini and saved 61% of its bill.

4. When the local model has no edge, you save money and that's it

On intent detection, Laya was right on every message it was sure about, but so was every cloud model. The cascade kept about a third of the runs on device at the cloud's accuracy, and on held-out folds it lost one example in 300 against each cloud. That's the honest result for a task the cloud already gets right: a 30–37% smaller bill with each single cloud model, and data that stays on the device for a third of your users' requests.

5. Generation: the on-device model was fine, the judge wasn't

Belay also runs generation tasks: an on-device LLM writes structured output, and a judge model scores it. We extracted a calendar event (name, date, time, person, place) from 240 voice-assistant requests with Gemini Nano through Chrome's Prompt API. Nano got 50.8% fully right, Claude 68.3% and Gemini 3.8 Flash 67.5% (the annotations are somewhat noisy, which caps everyone).

The hard part was knowing which of Nano's answers to trust:

For this task, a cheaper cloud model saves more than the cascade: Gemini 3.8 Flash cost $294 per million runs against $4,031 for Claude, within a point of its accuracy. Gemma 4 in Chrome is the next local model to try; it needs a GPU, which our test machine didn't have.

6. The labels are not the truth either

On content moderation (Civil Comments), Claude called 87 of 300 comments toxic; the labels say 150. The dataset counts a comment as toxic when half its raters did, which includes sharp but civil criticism. Both LLMs read "rude enough to make someone leave the discussion" as a stricter bar and scored 76.0%. Jev, a classifier, matched the labels better. Gemini also declined one comment outright (PROHIBITED_CONTENT), which counts as a cloud error. A calibration measures agreement with your labels, so write the task's question to match them.

7. The report tells you how to fix the task

The first ticket-triage calibration had 88.0% local accuracy. The report's "confident local mistakes" table was mostly customer claims routed to account. Adding "claims against the company" to the feedback option's description raised local accuracy to 93.0%. (We chose that change by looking at the same examples, so treat the gain as optimistic.)

8. Built-in AI under automation works, with some effort

Calibration runs the same browser code the app ships, in a real Chrome driven by Playwright. Getting Chrome's built-in models to download and run there took branded Google Chrome (not Chromium or Chrome for Testing), removing several of Playwright's default switches, loading extensions through the DevTools protocol, and a flag to run Gemini Nano on the CPU. The details are in ADR 0002.

A local model that learns from the cloud

Every escalation pays for a cloud answer, and a fixed on-device model throws it away. @swissspidy/belay-learn keeps it: its local model is a small embedding model in the page (bge-small-en-v1.5, 34 MB) plus a classifier trained on the cloud's answers to earlier escalations and on users' corrections. It starts by sending everything to the cloud and needs it less the longer it runs. Its confidence is recalibrated on its own record as it learns, so the threshold keeps meaning "at least this likely right". Watch it learn ticket triage in your browser.

We streamed 1,000–1,500 held-out inputs per task through it, one at a time, at threshold 0.9, with 5% of confident runs still sent to the cloud as a check. The cloud is simulated with the datasets' labels, so these numbers are the classifier's, not a cloud model's.

Each point covers 100 inputs. Starting from nothing, with an always-right teacher. The last panel is the content-moderation stream sorted by label: civil comments first, then toxic ones.

The guide explains how it works and how to use it; the design is in ADR 0004 and ADR 0005, and scripts/learn-simulate.mjs reproduces these numbers.

All results

Accuracy and cost with Belay are held out (five-fold cross-validation). "On device" is the share of runs the local model answers. ★ marks the cloud each example uses by default.

Method

Caveats

Try it

The library and the calibration CLI are on npm:

npm install @swissspidy/belay-core @swissspidy/belay-web
npm install --save-dev @swissspidy/belay-calibrate playwright-core

The README shows how to define a task and calibrate it on your own labeled examples.

@swissspidy/belay-learn adds a local model that learns from the cloud's answers. Watch it learn ticket triage in your browser.