Back to Blog
EngineeringAIInfrastructure
•
October 27, 2026
•
16 min read

"Predictable, Not Broken: Inside Cereby's ML Infrastructure"

The lab, the test sets, the guards and the release path behind the two models Cereby runs itself, and the X-ray that opened one of them up


Here is the synthetic paragraph our last two posts opened with. Cereby's AI detector scores it 100, and on the detector's raw scale, the log-odds behind that score, it sits at 9.62:

Regular exercise offers numerous benefits for both physical and mental health. It strengthens the heart, improves circulation, and helps maintain a healthy weight. In addition, physical activity releases endorphins, which can reduce stress and improve overall mood. Experts recommend at least 150 minutes of moderate activity each week, such as brisk walking or cycling. Making exercise a consistent habit is one of the most effective ways to support long-term well-being.

We misspelled "walking" as "wakling": 9.60. We doubled a "to": 9.56. Across 114 real AI paragraphs, one grammar error that LanguageTool confirmed moved the log-odds by a median of 0.23, and not one paragraph reached the Human band. Swapping straight apostrophes for curly ones moved them almost four times as far.

Our detector barely notices mistakes. What it measures is how predictable the words are. Sorted by how surprised a small language model is by each word, the most predictable fifth of 2,698 paragraphs had 28 in the Human band; the least predictable fifth had 375.

That corrects our last post, A Perfect Zero in Broken English, which said this detector "rewards text that is a little broken". Broken English does score human, but because it is unpredictable; the errors themselves carry almost none of the effect.

This post is about the ML infrastructure behind the two models Cereby runs itself, the AI detector behind every scan and the small rewrite model behind the humanizer: a lab that reproduces production exactly, test sets graded once, slow judges distilled into fast guards, a release path that checks a hash at every step, and, new this week, the X-ray that found the result above.


A copy that agrees to the last point

Every number in this post comes from a copy of production that runs on a laptop, and a copy is only useful if it agrees with the original. The lab's parity check replays every text we have a production score for. Of 472 texts on record, all 455 that fit in one detector window scored exactly what production had recorded, with no verdict flipped. The other 17, long enough to span several windows, matched in 9; their production scores predate a change to how the server splits long text, so the lab reports them and does not gate on them.

The laptop also runs the detector on its GPU for the search loops that need speed. Across the same 472 texts, the largest difference between the GPU and the CPU the server uses was 0.0000173 in probability, and no rounded score changed. Reported numbers still come from the CPU path, as production computes them:

The lab also refuses to be anything but a copy. Its scripts throw on any detector address that is not the laptop's own, so a grading run cannot quietly score against production. Every model it loads is pinned to an exact revision, and all of its state lives outside the repository, so several agents can work in separate checkouts without deleting each other's weights.

Graded once, on texts nobody trained on

The test sets are the other half of an honest number. The lab built them once, deterministically, from a public dataset: 300 AI texts for development and 300 for test, a third each short, medium and long, with no near copy of any training text, and a hash on every row and file. Development texts are for iterating; the test set is graded once per system and reported, not tuned. That rule is a convention rather than code, and the run directory shows it held: across two rounds, exactly two runs ever touched the test set, the old humanizer and the one we shipped.

Comparisons are paired: on the same 300 texts, an exact McNemar test asks whether the texts where one system won and the other lost lean one way more than chance allows, and every rate carries a 95% interval. That is how the round-two release could claim meaning kept on 299 of 300 test texts (98.1% to 99.9%) against the old humanizer's 15, and also how it had to admit that the other half of its plan failed: 0 texts reached the Human band, against 40. We shipped it anyway, as a choice for correct text over a better score.

Slow judges, fast guards

The best graders are too slow to ship. The lab judges meaning with a large natural-language-inference model (one that reads two texts and says whether the first implies the second), run in both directions, and judges readability with a large model trained on CoLA, a public set of sentences labelled acceptable or not. Held to the server's CPU budget, even a mid-size meaning model took 3.2 seconds per candidate, and the engine considers several candidates per paragraph.

So the lab distils its judges into guards. The large grader labels a few hundred real rewrite pairs; every small model we can afford then runs through the production guard code across a grid of thresholds, scored on how many of the grader's failures it catches, how many good rewrites it wrongly rejects, and what each check costs:

The meaning guard we shipped catches 87% of the meaning changes the large grader finds, at about a quarter of a second, and wrongly rejects 32% of good rewrites. The readability guard catches 93% of the rewrites that read worse, in under a tenth of a second, and wrongly rejects 67% of the good ones. Those false-reject rates would sink a grader. In a guard they are cheap, because a rejection only means a paragraph stays as the student wrote it, and the grid makes that trade an explicit decision.

Every file has a checksum

A model reaches students in four steps, and each refuses to continue on a mismatch. Promotion hashes the trained file and both guard models and writes the hashes and every threshold into one file in the repository. Upload copies them to the server and hashes them again there. The deploy script builds the new image, runs the test suite inside it (including tests that load the real models and check, for instance, that the meaning guard rejects a rewrite that invents a subject), and checks every hash before it touches anything that is running:

The smoke test goes through the same front door users do, including a request in the old format that must still get an answer in exactly the old shape, since the app keeps calling it until the flag moves. Any failure after the roll restores the previous image and configuration on its own. The last step is in the app: a flag decides which pipeline students get, so a model can sit on the server, deployed and tested, while nobody uses it, and rolling back is unsetting one variable and redeploying.

What the detector was listening to

All of that machinery treats the detector as a fixed referee. Round two reached its Human band mostly with broken English, so before spending days training a model against it, we wanted to know what it responds to. We own its weights, so we could look inside rather than guess.

The X-ray scores 2,728 paragraphs in ten groups: AI answers, human writing from six sources (Wikipedia, news and student essays among them), the lab's broken search rewrites, and both humanizers' output. It reads them four ways, and three of its numbers, with the threshold for each verdict, were written down before anything ran:

Breaking it on purpose. The cleanest test is causal: take a paragraph, add an error, re-score. The lab added deterministic errors (a swapped pair of letters, a dropped article, broken agreement, a doubled word) and kept a variant only when LanguageTool confirmed the new mistake:

Edit to an AI paragraphParagraphsMedian change in log-oddsReached the Human band
One confirmed grammar error114-0.230
Two confirmed errors55-0.640
Straight apostrophes made curly68-0.840
Contractions ("do not" to "don't")118+0.090

The top of the scale is 5.3, and these paragraphs start at a median of 8.6, so none of this comes close. On Wikipedia paragraphs the detector calls AI the pattern held: one error moved them 0.33, curly apostrophes 1.96. A typographic habit outweighs a grammar mistake several times over.

What does move it. Predictability. A small language model reads each paragraph and records how surprised it is by every word, the quantity researchers call perplexity. AI answers sit at a median of 1.9 in its units, the six human sources between 3.2 and 3.9, and the broken search rewrites 3.0, between the two. Sorted into fifths by that number, the share of paragraphs in the Human band climbs at every step:

Perplexity alone explains 41% of the variation in the detector's log-odds across these paragraphs. Adding every error and readability measure on top of it raises that to 48%; adding style instead raises it to 58%.

Word by word. Deleting each word of 441 paragraphs in turn and re-scoring shows which words carry the verdict. Casual intensifiers push toward human: "really", "pretty", "probably", "personally", "mostly". Explanatory words push toward AI: "important", "however", "example", "allows", "consider". In the broken search rewrites, the words LanguageTool flags make up about 1% of the text and carry 2% of what pushes it toward human. In most of those paragraphs, they carry none.

Inside the model. The detector turns each paragraph into a vector of 768 numbers and reads its verdict from that. One direction in that space holds 56% of the variation among our paragraphs, and it runs from AI answers at one end to the human writing the detector scores lowest at the other, with Wikipedia and news near the middle. A simple probe can partly find "this paragraph has a grammar error" in the same vectors (an AUC of 0.72), but its direction is almost exactly at right angles to the verdict's (a cosine of 0.014). The broken search rewrites sit next to the dataset's casual human writing, almost five times closer to it than to Wikipedia.

Here is the paragraph from the top, taken apart with integrated gradients, a standard way to split a model's score among its input words, measured against the same paragraph with every word hidden. The input and its variants are synthetic; every number is what the detector returned:

input (synthetic)          "Regular exercise offers numerous benefits ... long-term well-being."
log-odds                   9.62  (score 100)
every word hidden          -2.50

by sentence                1  -0.08   "Regular exercise offers numerous benefits..."
                           2  +2.12   "It strengthens the heart, improves circulation..."
                           3  +5.04   "In addition, physical activity releases endorphins..."
                           4  +1.13   "Experts recommend at least 150 minutes..."
                           5  +4.04   "Making exercise a consistent habit..."
toward AI                  endorphins, being, addition, offers, releases
toward human               Regular, It

one typo ("wakling")       9.60
one doubled word           9.56

the search's broken rewrite    -6.99  (score 0)
  plus one typo                -7.26

The third sentence, the one with "In addition" and "which can reduce stress and improve overall mood", carries more than a third of the distance from the hidden paragraph on its own. The misspelled "wakling" came out at +0.39: if anything, the typo pushed toward AI.

The rule written in advance had three outcomes. "Fluency detector" needed one error to move the log-odds by 2 or more; it moved 0.23. "Learnable style" needed clean paragraphs to be separable by features a rewrite can change, at an AUC of at least 0.80 (1.0 is perfect, 0.5 is chance), and pooled they were, at 0.95. That overstates it: the clean paragraphs on each side mostly came from different sources, and among human-written paragraphs alone it falls to 0.76.

So can a rewrite move along the predictability axis without breaking anything? A last check, added after the first three were read and labelled exploratory, took the round-one model's 960 rewrites of 60 AI paragraphs and kept the 40 that pass every guard and grader. All 40 are less predictable than their source and all 40 score lower, by a median of 1.3; 13 dropped by 2 or more. Within the six paragraphs with at least three clean rewrites, the less predictable one usually scored lower (a median rank correlation of -0.57). A small sample, pointing one way: there is clean room to move, and a trainer rewarded by the detector's log-odds has something to learn. None of the 40 reached the Human band, so the room is real and still short of the target.

Boring failures

The perplexity run that sat still. The first run of the perplexity step sat for 44 minutes at a third of one CPU core and printed nothing. It asked the language model for a score over its whole vocabulary at every position of eight padded paragraphs at once, gigabytes per batch, and the laptop spent its time moving memory. Smaller batches stalled again at paragraph 1,200. One paragraph at a time, with the vocabulary step taken 256 positions at a time, finished all 2,728 in under ten minutes, and each step now saves its output, so the next stall costs one step, not four.

The blank page that read as AI. Integrated gradients walks from a blank paragraph to the real one. Our first blank was all padding tokens, and the detector scored that empty page at 5.9, firmly AI; the walk also turned too sharply for evenly spaced steps, and even at 256 the pieces missed the whole by 41%. A blank of mask tokens scored -2.5, and unevenly spaced steps cut the miss to about 1% on the example above. Across hundreds of paragraphs it still failed on 30 of the first 50 at a step count we could afford, so the aggregate numbers use deletion, which adds up by construction.

The hashes nobody compares. Every run records the hash of the test set it read, and no code compares it with the manifest. "Frozen" has been true so far because nothing changed the files, not because anything would have stopped it.

Smaller ones: the human side of the public dataset arrives tokenized, with spaces inside "do n't" and "it 's" in 170 of its 200 held-out human texts and in none of the AI test texts, a tell the lab removes before scoring; and doubling the attribution batch size for speed stalled that run exactly the way perplexity had.

What this taught us

A model you own is a model you can question. A three-minute experiment that added confirmed errors to real paragraphs answered what two rounds of searching against the detector had only suggested, and it corrected a sentence we had already published.

The first correlation finds the source before the signal. Clean paragraphs separated at 0.95 until we noticed that the two sides mostly came from different places; among human writing alone the number was 0.76.

Instruments need checks of their own. The completeness check on integrated gradients caught a blank page the detector read as AI, and the parity check is why the lab's scores can stand in for production's.

What's next

The X-ray's call is to train against the detector after all, with its log-odds as the reward and the meaning and readability guards as hard limits, and to grade the result on a second detector it never trained against, so the model learns to sound less predictable rather than to exploit one model's habits. The run records need to check the test-set hash, not just store it. And the 17 long texts whose production scores predate the windowing change need fresh scores, so that parity covers long text too.