kirschbaum-development/redactor-onnx
A Laravel package for redacting sensitive text using ONNX models, bringing local, privacy-friendly redaction to PHP apps so you can detect and mask data before storage or display.
This release turns the redactor into a self-contained package: the new onnx driver runs a token-classification model inside the PHP process via TransformersPHP, so there is no sidecar service to deploy, network-hop to, or health-check.
php -m | grep -i ffi
composer require codewithkyrian/transformers
On shared hosting or hardened images where ffi.enable is off, this driver will not work — plan for that early.onnx (alongside your model id and the label→entity mapping) and keep the previous driver in config as a fallback until you have parity.php artisan redactor:onnx:warm to your deploy/build step so the first user request never pays the download-and-load cost:
php artisan redactor:onnx:warm
BatchRecognizer, the interesting move is passing the whole payload through once rather than looping field by field — every prose value is classified in a single model call.Start in a queue job or an artisan command rather than a hot web endpoint, so you can measure latency and memory without user impact.
Batch at the payload boundary, not the field boundary. BatchRecognizer is the reason to adopt this driver. Instead of:
foreach ($payload as $key => $value) {
$payload[$key] = $redactor->redact($value); // N model calls
}
pass the payload and let the recogniser classify all prose values in one call. This is where the in-process driver wins over a sidecar: no per-value HTTP round trip, and the tokenizer batches across values.
Warm at build time, not boot time. Run redactor:onnx:warm in your Dockerfile or release script and keep the model cache directory on a persisted path (baked into the image, or a mounted volume). Warming in a service provider is a trap: every FPM worker pays it, and a cold container pays it per request.
Long-lived workers are your friend. Queue workers and Octane keep the model loaded across jobs, which amortises the load cost. Pair that with restarts on deploy so workers pick up a new model version.
Lean on the built-in windowing, but chunk deliberately where spans matter. Long texts are cut into windows at whitespace, which keeps you under token limits. For documents where redaction offsets are returned to a downstream consumer, pre-chunk on paragraph boundaries yourself so a span never straddles a cut.
Keep the label mapping in config, not code. Model labels are mapped to the entity names your profiles already use. Verify that mapping against your profiles explicitly — a renamed label that silently falls through to "unknown" means PII slips through unredacted while everything looks green.
Maintain driver parity in tests. Run the same fixtures through the sidecar and onnx drivers and diff the redacted output. This is the cheapest guard against a model swap quietly changing what gets redacted, and it makes the sidecar a genuine fallback rather than a dead config branch.
Isolate in a job for anything heavy. Redaction of a large payload is CPU-bound and single-threaded per process; a queued job with a timeout and a worker pool sized for memory (not just CPU) is the sane default.
HOME is invisible to www-data.memory_limit against measured RSS, not the model file size alone.BatchRecognizer, you can implement your own driver (regex for structured identifiers, a rules-based recogniser for account numbers) and compose it with the ONNX one — models are good at names and places, poor at checksummed formats. Run cheap deterministic recognisers first and send the model only what survives.How can I help you explore Laravel packages today?