Tool-life forecast · trained and verified
What a model would do here — and what it would not be allowed to
ZenFactory works rule-based. Machine learning here is not a rebuild but a plug: the docking point is built and tested, and since 24 August 2026 the first model has been sitting in it — zf-standzeit, trained on 89 blade lives from our own historian. It proposes nothing; it merely knows earlier. This page shows what of it is measured and what remains illustration — plus four instances that can say no to a model too, without a line of it being changed.
The view
Shown on the band saw in cutting, because that is where the most interesting case lies: this machine has no manipulated variable. A model cannot adjust anything here — it can only know earlier what will happen anyway.
Site 1 · Cutting · Saw blade
Tool-life forecast
Cuts since blade change
300
of 380 nominal — tool life per nameplate
Motor current
15,3 A
fresh blade 11.5 A · threshold 15.8 A
Change expected in
42 ± 12
cuts, about 32 min of plant time
Model quality
± 7,9
cuts — the resolution of the line. 0.9 was measured; see below for why the larger number is the honest one.
Motor current over the blade’s tool life
SAEGE01 · OperationalData.MotorCurrentThe model reads nothing that is not already in the twin: motor current, cut time, remaining-life display, miscut rate. The benefit is not the curve but the lead time — a blade change takes a quarter of an hour, and planned it costs less than when it surprises you.
Observation without a rule
no proposalR01 · heat-up phase 9 % longer than in the last 40 comparable batches, at an unchanged setpoint.
- Expected
- 18.4 min
- Measured
- 20.1 min
- Outside since
- 6 batches
No rule set covers this. That is why it appears as an observation for maintenance — and not as a proposal in the control loop.
Model card
trained- Name
- zf-standzeit
- Version
- 0.1.0
- Feature
- Motor current, nothing else
- Learned on
- 89 blades · 4,854 examples
- Verified on
- 30 held-out blades
- Mean error
- 0.9 cuts
- Resolution of the line
- 7.9 cuts
No longer a placeholder: the values are in ml/zf-standzeit.json and come from the run of 24 August 2026. Version and quality measure go into the same chain as any intervention as provenance — otherwise it could not later be said which state supported a decision.
Proposal from the model
awaiting approvalST020 · feed
0,96 → 1,02
- Forecast
- +9.4 parts/h
- Noise band
- ± 6.1 parts/h
- Gate
- assumed
Generated by the model, but in the same format as a proposal from the rule set: limited step, forecast as a number, trial run afterwards.
Rejected by the gate
2 reasonsCNC03 · feed
1,00 → 1,11
- Step size
- 0,11 > 0,08
- Last change
- 9 min ago
- Gate
- rejected
The gate does not check where a proposal comes from. A model gets the same limits as a rule — and the same rationale when it exceeds them.
Where the model docks on
The model replaces nothing. It sits alongside the rule set and produces the same kind of finding — everything after that stays as it is. The socket for it is built; what was missing is the plug.
That is the real statement: the value of the existing architecture is that it does not have to take a learning component on trust. Forecast, gate, approval, trial run, watchdog and ledger are already there — and they do not ask where a proposal comes from. As of this version that is no longer only stated here but sits in loop/adapter.py.
- M
Monitor
unchangedReads the AAS twin, time-weighted. The same source from which the model would also draw its features.
- +
Adapter
built, emptyThe docking point exists: an adapter is anything that masters beurteile(Beobachtung, Schwellen) and returns a finding or None. A model would be a service that serves exactly that — it writes nowhere and calls nothing. It is plugged in at loop/analyze.py, where the rule set is already chosen today.
- A
Assess and plan
unchangedThe finding becomes a limited proposal with a predicted effect. Whether the finding came from a rule or a model changes nothing about that.
- 1
The gate
unchangedLimits, step size, minimum confidence, observation period, spacing, repeat lockout. A YAML file that also applies to model proposals.
- 2
The human
unchangedApproval required. A model does not shift this threshold — it would first have to earn it over weeks of confirmed forecasts, just as the rules did.
- 3
Trial run and watchdog
unchangedThe measured effect decides, not the predicted one. Whatever delivers less than announced goes back — even if a model proposed it.
- K
Ledger
one more fieldEvery proposal carries its provenance in the evidence: rule or the adapter’s name@version. It is written by the loop, not by the adapter — whoever may write down their own provenance will at some point write down the wrong one. That is the only change to the chain of evidence, and it is the reason why it can later be said which version was responsible for what.
The contract
in the repositoryThree sentences, and they stand as code, not as intent: an adapter answers an observation with a finding — or with None, and then the rule answers. If it fails, that costs one cycle and not the plant. And it gets no special rights: its finding goes through the same gate, the same approval and the same trial run.
# loop/adapter.py — what an adapter must be able to do class Befundgeber(Protocol): name: str fassung: str def beurteile(b, schwellen) -> Befund | None: ... # loop/analyze.py — the order is the whole promise befund = adapter.beurteile(b, schwellen) # if it returns None or fails: befund = regelwerk.beurteile(b, schwellen) # the rule answers # plug in without changing a line ZENFACTORY_ADAPTER=LINIE_A=pruefstecker # and prove that the socket holds .venv/bin/python -m pytest tests/test_loop.py -k adapter 9 passed
The Prüfstecker (test plug) is not a model and does not pass itself off as one. It is the counterpart of the test plug in a network socket: it hands the plant rule’s verdict back under its own name and with dampened confidence. That lets you show at the meeting that a finding comes through the adapter, appears in the ledger with its provenance and is treated by the gate like any other — without a physics having to be invented anywhere for it.
What the model really says today
The model has existed since 24 August 2026. It is not a neural network, it needs no GPU and not a single additional library — it is a straight line through a point cloud, calculated in pure Python.
# .venv/bin/python ml/train_standzeit.py --tage 2 Model remaining cuts = 1286.9 - 78.6 · current[A] Learned on 89 blades, 4,854 examples Verified on 30 held-out blades, 1,647 examples Error 0.9 cuts on average (mean alone: 96.2) Resolution 7.9 cuts per 0.1 A step — the limit of the line # .venv/bin/python ml/train_standzeit.py --jetzt 20:59:26 Motor current 13.3 A Remaining life 241 cuts Model zf-standzeit@0.1.0
One feature
Motor current only
Wear and remaining life are available in the simulation — the model never gets to see either. On a 1998 saw they do not exist, and a model that only looks good at the meeting because it already knows the answer is worthless.
The labels
Arrive on their own
Every blade change labels its own history retroactively: at cut 300 there were still 80 to go, and that is known afterwards. 119 completed blade lives in 34 hours — the most expensive part of an AI project falls away here.
The limit
7.9 cuts per step
The current arrives in steps of 0.1 A over Modbus. One step is 7.9 cuts — this forecast can never get better than that on this line, whatever method is behind it.
A classification nobody else supplies: The 0.9 cuts apply to a clean signal. On the replica plant the current follows the wear exactly — without scatter from material, feed or temperature. How much of that is left on a machine with real noise, we have measured rather than left open:
What remains when the signal scatters
The saw can put scatter on the motor current — two thirds as a material batch that carries over sixty cuts, one third as measurement noise. Out of the box this is switched off, so that the other numbers on these pages match the pure formula. When it is switched on, the same model is retrained at each level and verified on held-out blades:
| Scatter on the current | Mean error | 80 % band | Mean alone |
|---|---|---|---|
| off | 2,0 | −3 to +3 | 94,9 |
| 1 % | 6,6 | −11 to +10 | 94,8 |
| 2 % | 12,8 | −22 to +18 | 94,8 |
| 5 % | 29,7 | −51 to +43 | 94,8 |
| 10 % | 50,6 | −86 to +77 | 94,8 |
All in cuts, 28 blade lives per level, current rounded to 0.1 A. Recompute with scripts/sweep_streuung.py.
Five percent scatter is not a large number on a band saw — a different material batch shifts the current slightly, by a third of an ampere. There the forecast lies at ±30 cuts instead of ±1. That is still three times better than the mean, but it is no longer an appointment you plan to the day — it is a shift. This number belongs in a quotation, not the 0.9.
Where the data would come from
For a tool-life forecast the historian is enough: wear curves arise by themselves, every blade change is an example with a known outcome. For a model that proposes manipulated variables it looks different. Its labels would be the verdicts from the evidence ledger — and so far there are too few.
| What is there | Volume | Good for |
|---|---|---|
| Wear curves Motor current, cut time, miscuts per blade | ongoing | Tool-life forecast. Arises without any effort, outcome always known. |
| Historised KPIs every change a row, since the start | ongoing | Anomaly detection. Needs no labels, only enough normal operation. |
| Assessed attempts Proposal, forecast, measured effect, verdict | 59 | Too little for a manipulated-variable model. 15 confirmed, 44 rolled back — as a training set these are individual cases. |
Prerequisite 1
Effect must be separable from noise
Today output fluctuates at an unchanged manipulated variable by ±14 % on the line, ±25 % at the filling line, ±77 % at the reactors. A model learns the noise from that first. The paired comparison against an unchanged sister unit is therefore not a side project but the precondition.
Prerequisite 2
Enough attempts, and from operation
59 assessed attempts are a good track record and a poor training set. They grow only in live operation — and each one costs a trial run of two to six hours of plant time.
Prerequisite 3
Fallback to the rule
If the model service fails or delivers nonsense, the loop must keep running — with the rule set that exists anyway. A model may be a supplement, not a dependency. That is the only one of the four prerequisites already fulfilled: failure, silence and nonsense from an adapter are one test each, and all three end at the rule set.
Sequence
First where nobody adjusts anything
Tool life and anomaly are pure observation: being wrong costs attention, not scrap. The start belongs there — and not at the manipulated variable of a running plant.
The status in three sentences. The docking point is built and secured: contract, fallback to the rule, provenance in the ledger, plus tests for failure, silence and wrong answers. The model is trained and captures the saw’s physics; it delivers findings for maintenance and adjusts nothing because this machine has no manipulated variable. It learned on the replica plant — when used on your machine it is retrained on your data, and the measurement for that runs exactly as it does here.