What runs where
Redact is three processes on one computer. The browser opens the file, rasterizes each page to a PNG, and shows the review workspace. It never sees model weights. The local service (npm run qvac:service) is a small Node HTTP server bound to 127.0.0.1.
It owns the QVAC SDK, loads the two models once, and turns one page into OCR blocks and suggestions.
The QVAC worker is a separate process the SDK starts.
It runs the native engines: an OCR pipeline for reading and a llama.cpp-based engine for Laya, the decision model.
The SDK talks to it over local IPC.
See How it works for QVAC’s own description.
What “local” buys
No document byte leaves the machine during analysis. You can check this rather than trust it: the macOS offline run denies the process any non-localhost network and still produces suggestions (Lesson 10). Local also means no per-page cost, no account, and no service that can change its model or retention policy under you. The model version is whatever your lockfile and cache say.What it costs
On an Apple Silicon Mac with 36 GB of memory:npm ciinstalls about 2.8 GB of dependencies with@qvac/sdk0.22.- The OCR and decision models add about 550 MB on first use.
- OCR takes 20 to 30 seconds per page; Laya’s decisions add under a second.
- Pages are analysed one at a time, so a 25-page PDF can take more than ten minutes.
Lifecycle matters more locally
A hosted API hides model loading. Locally it is your problem. The service loads each model on first use and keeps it in memory; loading is where the first-run download happens. On shutdown it callsunloadModel and close so the worker exits cleanly instead of leaving native memory behind.
QVAC’s Lifecycle page describes these calls.
The same thinking explains why the service, not the browser, holds the SDK.
The native engines need a Node process with file system access, and keeping them behind one long-lived process means each model loads once instead of once per page.