OpenAI dropped Privacy Filter on the Hub this week: an open-source PII detector that runs a single forward pass over 128k tokens and tags eight categories of personally identifiable information. It’s a 1.5B-parameter model with only 50M active parameters, Apache 2.0 licensed, and it claims state-of-the-art on the PII-Masking-300k benchmark. I spent a few hours building with it, and I came away impressed—but not for the reasons you might expect.
The model itself is solid. It handles private_person, private_address, private_email, private_phone, private_url, private_date, account_number, and secret. The 128k context window means you can throw a whole contract or chat export at it without chunking, which is the main reason most PII tools feel clunky. No stitching, no offset mismatches. Just one pass and clean BIOES-decoded spans.
But the real story here is how the Gradio team wired up the backend. All three apps I built—Document Privacy Explorer, Image Anonymizer, and SmartRedact Paste—use gradio.Server under the hood, and that’s where the magic is. If you’ve ever tried to build a custom frontend for a Gradio model, you know the pain: you either fight with Blocks or you write a separate FastAPI app and lose the queueing, GPU allocation, and client SDK. gr.Server lets you keep the Gradio infrastructure while serving a hand-authored HTML/JS frontend.
Document Privacy Explorer
Drop in a PDF or DOCX, and the app reads the document back with every PII span highlighted by category. There’s a sidebar filter to toggle categories on and off, and a summary dashboard up top showing counts per category. The reading experience feels like a real document—serif body, clean layout—not like a form.
The model runs once over the entire text. The spans come back with exact character offsets, so highlighting lines up perfectly with the rendered text. No chunking, no weird boundary artifacts.
What gr.Server does here is let me serve the reader view as a single HTML file and expose the model behind one queued endpoint. The decorator @server.api(name=”analyze_document”) plugs the handler into Gradio’s queue, so concurrent uploads serialize properly, @spaces.GPU composes correctly on ZeroGPU, and the same endpoint works from both the browser and gradio_client with no duplicated code. The browser calls it with the Gradio JS client, same endpoint, no extra routing.
This is higher than I expected. I’ve built similar tools before with FastAPI + Celery, and the boilerplate is absurd. Here, one decorator handles everything.
Image Anonymizer
Upload a screenshot—Slack thread, receipt, Stripe dashboard—and get it back with black bars over names, emails, and account numbers. The bars are editable: you can toggle entire categories on and off, drag individual bars to reposition them, or draw new ones by hand for anything the model missed. Then export the result as a PNG at natural resolution, no server round-trip.
The backend runs Tesseract OCR to get per-word bounding boxes, reconstructs the full text with a char-offset-to-box map, runs Privacy Filter once over the whole text, and looks up detected character spans against the word map to produce pixel rectangles per line.
gr.ImageEditor supports layered annotation and would have been a reasonable starting point, but the workflow I wanted—per-bar category metadata, toggle all bars in a category at once, client-side PNG export—was cleaner to build on a custom canvas. gr.Server hands back pixel rectangles from one queued endpoint and lets the canvas own everything else. The frontend invokes it with client.predict(“/anonymize_screenshot”, { image: handle_file(file) }), same pattern as the document app.
SmartRedact Paste
This one is deceptively simple. Paste sensitive text, get a public URL that serves the redacted version, and a private reveal link that shows the original. No accounts, no storage beyond what’s in the URL itself.
The model runs once on paste, generates the redacted text and the span data, and the server stores nothing. The public URL encodes the redacted version; the private link encodes the original with a random token. Both are served as static HTML with no server-side rendering after creation.
This approach has been tried before—pastebin clones, encrypted paste services—but the PII redaction angle is new. The 128k context means even long documents fit in one pass, and the single-endpoint pattern from gr.Server makes the whole thing fit in about 80 lines of Python.
What I actually think
Privacy Filter is a good model. The 128k context is the killer feature, and the permissive license means you can actually deploy it. But the Gradio integration is what makes these apps practical. The @server.api decorator pattern is genuinely clever—it gives you queue serialization, GPU allocation, and client SDK compatibility without forcing you into the Blocks paradigm.
The trade-off is that you need to write your own frontend. If you’re comfortable with HTML/CSS/JS, that’s fine. If you’re not, you’ll spend more time on the frontend than the backend. But for anyone who’s built a real product around a Gradio model, this is the missing piece.
The Image Anonymizer has a rough edge: OCR quality depends heavily on the screenshot. Low-res images or unusual fonts produce garbage boxes. The model itself is fine, but the pipeline is only as good as Tesseract. I’d love to see a vision-based PII detector that works directly on images, but that’s a different problem.
All three apps are on the Hub. Try them, fork them, break them. The code is short enough to read in one sitting.
Comments (0)
Login Log in to comment.
Be the first to comment!