A site service needs a prediction from one model. This is the data line: the request
crosses the message bus, is validated and routed inside the inference pipeline, is answered by
a model alias on Ray Serve, and comes back the same way. The bridge then records the
inference, and that record is what drift detection reads later.
A client sends a job to one model's address. Every model has its own UUID on the bus, set as seanerbus_uuid in its YAML. In request/reply mode — the one the stack runs — the bus routes by that UUID, not by the model name.
The bridge picks the handler for that model. At start-up it registered one handler per model UUID. The handler fixes the model, picks the alias — Production unless the job asks for another — and builds the features from the model's input schema.
The job enters the inference pipeline. The bridge posts it to /infer-pipeline/infer on Ray Serve over one shared HTTP client: 5 s to connect, 10 s to read, no retry at this hop.
The ingress validates the payload. An embedding and a node count are required. A malformed request gets a 422 here — a schema error, which is not treated as a model failure.
The feature transformer checks the embedding. It batches up to 32 requests or 50 ms to validate them together, confirms each embedding has 384 values, and keeps job and user IDs as metadata. After validation, every request is routed on its own.
The model router applies the traffic split. It reads the model's Production / Canary weights from the traffic rules, cached for 30 seconds. The split applies to traffic addressed to the model's default alias (Production), which is what bus jobs send: when a split names two or more aliases, the router picks one by weighted random choice. A request pinned to any other alias, such as Staging, gets that alias. Rules are matched case-insensitively, so a split set for JPCP applies to jpcp.
Ray Serve answers from its hot set. The alias resolves to a model already in memory, loaded from MLflow at start-up. Prediction runs on a pool of 4 workers with a 30 second limit.
The answer returns the same way. Model name, alias, version, MLflow run and prediction travel back to the client. On any error the reply carries an error message and a prediction of 0.0, so clients must check the message.
The bridge records the inference. In one background-thread hop, off its event loop: a drift snapshot of the prediction, the embedding's norm, mean and standard deviation, and an "inference served" event on the hash-chained audit trail.
Repeated failures ask for a retrain. The bridge tracks each model's failure rate over its last 50 requests. At 0.5 or above it asks the control plane to retrain, then waits out a 300 second cooldown.
Metrics and reloads run alongside. Ray Serve exports request counts and latency by model and alias. Every 60 seconds it asks MLflow whether an alias moved, and reloads that model without dropping traffic.
Direct HTTP calls skip the bus.exa predict, the dashboard and the agent call Ray Serve's API on port 18001. They get the same models, but their requests write no drift snapshots — drift detection sees bus traffic only.
exaservecheck# Ray Serve health and the loaded hot setexaserveinfer-check# one end-to-end request through the pipelineexaservetrafficJPCP--production90--canary10exadriftstatus# prediction drift, from the bridge's snapshotsexadriftinputstatus# input-embedding drift