How it works
- You record what happened to judged documents: labelled examples, results that come later, or outcomes that rules make from your own writes.
- Brussle keeps each outcome beside the exact answer it measures: its document revision, judgment version and engine version.
- Each night Brussle fits a correction for each judgment version and engine epoch, and tests it on held-out outcomes: outcomes that the fit did not use. A fit is one correction, with an id you can list, compare and pin.
- A new fit replaces the one your answers read only when it is clearly better.
- Brussle applies the fit when an answer is read. A new fit updates every answer without judging anything again.
What changes in an answer
When a fit uses enough outcomes and beats the raw numbers, each answer gets acalibrated object beside the engine’s numbers:
- The engine’s
p,distandscorenever change.calibratedsits beside them, with the fields of the answer’s type:pfor abool;value,distandescape_pfor achoice;scoreanddistfor ascore. intervalis the 95% interval of the corrected number. See how sure a corrected number is.stageisearlyorfull(see when you get a correction).outcomesis how many outcomes the fit uses.fit,runandpinnedname the fit that made the number, the run the answer was read with, and whether the fit is pinned.prior, on anearlyfit, says how much of the correction is your own outcomes’. See below 100 outcomes.from_previous_epoch: truemeans the engine changed and the answer reads the previous epoch’s fit until the new one has its own. See when the engine changes.extrapolated: truemeans the raw value is outside the range the fit was made on: below the lowest or above the highest raw value among its outcomes. For achoiceorscore, the raw value is the probability of the most probable option or level. The corrected number is then a guess from the edge of what the fit has seen. Post outcomes for documents like this one.calibratedis absent while there is no fit. It is notnull.
Which number your thresholds and queries read
Every reader uses the number that the answer shows. The readers are thresholds, filters, ranking, subscriptions, relations and groups.- A judgment without features: readers use the engine’s numbers, never
calibrated. A new fit never moves a document across a threshold without your action. To act on corrected numbers, pick a threshold on the engine’spwith the threshold recommender, which measures it against your outcomes, or readcalibratedin your own code. - A judgment with features: the answer’s own numbers are the corrected ones (
p; ordist,escape_p,valueandscore), andrawholds the engine’s. Readers act on them. A new fit can move documents across a threshold, and on achoiceit can change which option or candidate is picked. - A composite: it has no
calibratedobject. Itspcomes from weights that Brussle fits on your labels in each calibration run, so a new set of weights movesp, and with it thresholds, filters, ranking and subscriptions.GETshows nofit_changedwarning for a composite. The result is usually close to calibrated, but not always: check the reliability curve in its report.
When you get a correction
Brussle makes a separate fit for each judgment version and each engine epoch. A different question, or a different engine behaviour, needs a different correction.stage is a summary of how settled the fit is. Whatever the stage, automate on the interval, never on the number alone.
At least 15 of each kind
50 outcomes are not enough alone. An epoch also needs outcomes on both sides:bool: at least 15trueand at least 15false.choiceandscore: at least two different values, with 15 outcomes each. The fit does not need every option, because most options are rare. It needs to see the engine’s top answer both right and wrong.
true, the “best” correction says that everything is probable, which is wrong for every document where the event did not happen. Until an epoch has both kinds, it gets no correction, and the report says why:
Below 100 outcomes
From 50 outcomes a judgment gets a correction. Three rules keep it safe while your outcomes are few.- It starts from the engine’s own numbers. The correction is part your outcomes and part the engine’s numbers taken at their word. Your share is
prior.weight, on each corrected answer and in the report: half at 50 outcomes, two thirds at 100, 86% at 300. It grows with each outcome, so the correction moves away from the engine’s numbers only as fast as your outcomes support. From 1,000 outcomes the correction is your outcomes’ alone, andprioris absent.prior.kindisidentity, the engine’s own numbers, orpoolon a template’s tenant, which leans on its template’s pool instead (see per-customer corrections). - It must win clearly. Below 100 outcomes, each outcome is scored by a fit made without its document, and the correction must beat the raw numbers by more than one standard error of the difference. When it wins by less, the report’s
not_fittediswithin_noise, withgain_standard_errors: calibration is working, and not yet sure. Answers stay raw until it is. From 100 outcomes, any win applies. - A judgment with features waits for 100. Its thresholds, filters and readers act on its
p. Below 100 outcomes its fit is reported and never applied:pstays the engine’s, andnot_fittedisreaders_need_full.
prior.weight grows with your outcomes. Each correction’s interval is never narrower than your own outcomes support: the engine’s numbers make the correction more careful, never more certain.
Only when it beats the raw numbers
Brussle applies a fit only when it does better than the engine’s own numbers on held-out outcomes. Each outcome is scored by log loss against a fit made without that outcome. When the raw numbers score as well or better, the fit is not applied. Answers have nocalibrated object, and the report’s not_fitted says raw_better, with both results in held_out. Your answers stay raw and do not get the noise of a fit.
The held-out test also gives the Brier score of both, beside log loss and calibration error (raw_brier, calibrated_brier). The Brier score is the mean squared gap between the number and what happened, from 0 to 1, lower is better. For a choice or score, it is the sum of the squared gaps over the options, halved, so a choice of two options reads as a yes-or-no judgment does. Brussle still chooses a fit on log loss alone.
How sure a corrected number is
Each corrected number hasinterval, {"lower", "upper"}: its 95% interval. It says how sure the correction is, from the outcomes the fit uses. The recommender’s interval and the lift’s interval are 95% too.
- Where it is.
calibrated.intervalis on the number the object shows:pfor abool,escape_pfor achoice,scorefor ascore. On a judgment with features,fit.intervalis on the same number, at the answer’s own features. - It always contains the number. A probability’s interval stays between 0 and 1. A score’s stays between the lowest and highest level.
- More outcomes make it narrower. Each fit uses all the outcomes so far, so the interval usually narrows from one fit to the next. When a night keeps the current fit, its numbers stay the same and its interval is measured again on all the outcomes so far. It is wider for raw values far from most of the fit’s outcomes.
- From 1,000 outcomes, it is the interval of the outcomes near this value. At
stage: fullthe correction follows your outcomes value by value. Where few outcomes are near, the interval is wide, sometimes wider than theearlyfit’s interval was at the same value. The report’sbandshows where. - Labelling-queue labels count as the labels that they are, not as the traffic that they stand for. A few labels with a large weight give a wide interval.
- Outcomes that run against the engine. The correction never reverses the engine’s order. When higher raw numbers came true less often, the corrected number is the share of events among all the outcomes, and the interval is the interval of that share.
- With
extrapolated: truethe interval is still there, wider at the edges. But the correction itself is a guess there, and the interval does not know that. - On a template’s tenant, the interval is never narrower than the tenant’s own outcomes support. See per-customer corrections.
intervalisnullfor a fit made before fits recorded their intervals (2026-10-13). The next nightly run adds it, whether it replaces the fit or keeps it.
- How much the engine’s answer varies from one call to the next. The engine’s raw number has its own variation; each engine’s page under engines describes it.
- That what happens will fall inside it. It says how much your outcomes support the correction. It does not show whether your outcomes are a reviewed sample (read the report’s
warnings), or whether the engine changed (see epochs).
Automate on the bound
Automate on the interval, never on the number alone, whatever the stage. To act on high numbers, useinterval.lower. To act on low numbers, use interval.upper. To act when the probability is 0.8 or more, act when interval.lower is 0.8 or more, not when p is.
On a judgment with features, queries and subscriptions filter and rank on answers.<j>.interval.lower and answers.<j>.interval.upper, the bounds of fit.interval. This query finds the payments whose probability of settling their invoice is 0.8 or more with 95% confidence, the surest first:
- A document whose
pis the engine’s has no interval, so the filter does not select it.["answers.invoice_settlement.interval.lower", "Exists", false]selects those documents. - On a judgment without features, these fields are
invalid_request, because readers use the engine’s numbers there. Readcalibrated.intervalin your own code, or pick a threshold with the recommender and read it with its interval. - The bounds change when a new fit uses more outcomes. A query reads the current bounds at once. A subscription checks its filter again when the fit changes (a new
fit.id). Bounds that narrow under the same fit reach it at the document’s next evaluation.
What the correction can and cannot do
- It is not fine-tuning. The engine’s weights never change. The fit corrects the number the engine gives, from your outcomes and, if the judgment has them, your features.
- It makes probabilities agree with your outcomes. After the correction, a stated 0.9 came true about 90% of the time on your held-out outcomes. The report shows both, before and after.
- It does not change the order of documents, for a judgment without features. A higher raw probability always maps to an equal or higher corrected one, so the correction cannot make the engine better at telling probable documents from improbable ones. If the right documents are not near the top of the raw ranking, try a narrower question, a different context recipe or counts as features, and measure again. With features, the order can change: your numbers sit beside the engine’s answer.
- It cannot separate documents with the same
p, for a judgment without features. Jev, for example, givespin steps of 0.01 (each engine’s page under engines says how its probabilities come). The correction gives eachpone corrected value, so a threshold selects all of these documents or none. With features, documents with the samepusually have different features, and get different values. - It can change a yes or no at 0.5. Accuracy before and after can differ. The report shows both.
- It is only as good as the outcomes. Outcomes from one kind of document, or one part of the range, give a correction that is right there and a guess elsewhere. The report’s
not_fitted,coverageandwarningssay when. - It is only as current as its last fit. A fit made before answers changed can be wrong for the new answers. See when answers are corrected.
When answers are corrected
Sometimes Brussle judges answers again to correct them, for example after a fault on our side made a judgment read too few related documents. You are not billed for these answers. Each corrected answer is a new evaluation, and the document’s history keeps the earlier one.- Outcomes measure the corrected answer. An outcome that joined the earlier answer joins the corrected one from then on, also when the document changed after the outcome, and, with a horizon, when the correction comes while the earlier answer’s window is open. A correction made after that window closed opens the next window, as any new answer does.
- The report changes at once.
rawandcalibrateduse the corrected answers from your next request. - The fit changes at the next run, which starts within a few minutes after the correction ends. The current fit was made on the replaced answers, so it can trust the corrected ones too much or too little. A judgment with no outcomes has no fit to change.
- The report warns until then. Each epoch whose fit used answers judged again since with different inputs has
inputs_changed_since_fit, whosecountis the number of the fit’s outcomes that now join a new answer. The same warning shows when other answers the fit used were judged again with different inputs at the same revision. It clears at the next fit. To fit at once, select Fit now or callPOST /namespaces/{ns}/judgments/{name}/calibration/fit(fitCalibration,fit_calibration).