Manufacturing AI Operational Requirements
A conveyor belt will not wait for an AI response. Shop-floor manufacturing AI requires three essentials: <50ms inference, offline operation, and drift detection.
Achieving Low-Latency Inference
import onnxruntime as ort
import numpy as np
import time
class FastInference:
def __init__(self, model_path: str):
opts = ort.SessionOptions()
opts.intra_op_num_threads = 4
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
self.sess = ort.InferenceSession(model_path, sess_options=opts)
self.inp = self.sess.get_inputs()[0].name
# : JIT file
dummy = np.zeros((1, 128), dtype=np.float32)
for _ in range(10):
self.sess.run(None, {self.inp: dummy})
def predict(self, features: np.ndarray) -> dict:
t0 = time.perf_counter()
out = self.sess.run(None, {self.inp: features})
return {
"value": float(out[0][0]),
"latency_ms": (time.perf_counter() - t0) * 1000
}Improving Throughput with Batch Processing
Batch inference increases throughput 10–20× compared to single-sample inference.
import asyncio
from collections import deque
class BatchInference:
def __init__(self, model, batch_size=32, max_wait_ms=10):
self.model = model
self.batch_size = batch_size
self.max_wait = max_wait_ms / 1000
self.queue = deque()
asyncio.create_task(self._loop())
async def predict(self, features):
fut = asyncio.Future()
self.queue.append((features, fut))
return await fut
async def _loop(self):
while True:
await asyncio.sleep(self.max_wait)
if not self.queue:
continue
batch, futs = [], []
while self.queue and len(batch) < self.batch_size:
f, fut = self.queue.popleft()
batch.append(f)
futs.append(fut)
results = self.model.predict_batch(np.stack(batch))
for fut, res in zip(futs, results):
fut.set_result(res)Predictive Maintenance: Isolation Forest
from sklearn.ensemble import IsolationForest
import joblib
#
clf = IsolationForest(n_estimators=100, contamination=0.01, random_state=42)
clf.fit(normal_sensor_data)
joblib.dump(clf, "pdm_model.pkl")
def score(reading: np.ndarray) -> dict:
s = clf.decision_function(reading.reshape(1, -1))[0]
return {
"score": float(s),
"is_anomaly": s < -0.1,
"severity": "HIGH" if s < -0.3 else "MEDIUM" if s < -0.1 else "NORMAL"
}Model Drift Detection
When the production environment changes (season, raw materials, equipment aging), model performance degrades.
from scipy.stats import ks_2samp
class DriftDetector:
def __init__(self, reference: np.ndarray, threshold: float = 0.05):
self.ref = reference
self.thr = threshold
def check(self, current: np.ndarray) -> list:
drifted = []
for i in range(self.ref.shape[1]):
_, p = ks_2samp(self.ref[:, i], current[:, i])
if p < self.thr:
drifted.append(f"feature_{i}")
if drifted:
print(f" : {drifted}")
self._trigger_retrain()
return drifted
def _trigger_retrain(self):
import requests
requests.post(os.environ["RETRAIN_WEBHOOK_URL"])Operational Metrics
| Metric | Target | Alert Threshold |
|---|---|---|
| Inference latency P99 | < 50ms | > 100ms |
| Anomaly detection precision | > 0.90 | < 0.80 |
| Drift detection interval | 24 hours | Exceeds 72 hours |
| Retraining interval | At least once a month | Less than once a quarter |
This three-part series completes the full industrial AI integration lifecycle (gateway → pipeline → model operations).
When an Edge Model Swap Fails: Cause, Reproduction, Verification, Recovery
In a hybrid setup the most common incident is not inference itself but a new model pushed from the cloud that only fails on some edge nodes.
Causes
- Runtime mismatch: the ONNX opset exported in the cloud is not supported by an older ONNX Runtime on the edge
- Corrupted or partial download: after a network drop there is no retry/verify step, so a truncated file gets loaded
- Hardware differences: nodes on the same line may or may not have a GPU/NPU, so the execution provider (CUDA vs CPU) changes and latency spikes
Reproduce and verify
# 1) Integrity: compare with the hash published by the cloud pipeline
sha256sum /opt/models/current/model.onnx
# 2) Runtime version and execution providers
python3 -c "import onnxruntime as ort; print(ort.__version__, ort.get_available_providers())"
# 3) Model opset
python3 -c "import onnx; m=onnx.load('/opt/models/current/model.onnx'); print([(o.domain,o.version) for o in m.opset_import])"A hash mismatch points to transfer, an opset above the runtime's supported range points to export settings, and a missing CUDA provider points to drivers or packages.
Recovery: A/B slots
Keep /opt/models/a and /opt/models/b and switch only the current symlink. Switch with ln -sfn /opt/models/b /opt/models/current only after a smoke inference on sample input and a p99 latency check pass on the new slot; on failure, point the link back to return to the previous model immediately.
Prevention
- Roll out one node → one line → whole plant, with latency and false-alarm rate as gates at each stage.
- Ship a manifest with the artifact (opset, minimum runtime version, hash) and have the agent check it before loading.
Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us
This article has no recorded human check (date and scope) yet.
Comments
Be the first to comment.