Inspiration

This data masking started out as a token savings project built off rtk. But then, I found a bug I wish I hadn't, I found out that rtk invents token savings and degrades LLM performance details. Their millions of token savings was too good to be true -- obviously -- or codex would've built that into their systems already.

So I pivoted to a compliance focused project to help my wife use AI safely when she works with patient data (as a family medicine doctor); where instead of clamping big chonky inputs into smaller ones, I'm masking Benson Wong into B***** W***** or a street address into [address1].

What it does

Finds PHI / PII and masks them so protected data is safe to use with public AI. It takes images, pdfs, or texts; and gives you a masked image, pdf, or text that you can safely put into AI; and when the AI answers by referring to B***** then you can come back and unmask your content allowing you to see the real content and not the AI.

How we built it

It has to work offline, so I went with tesseract and layers of regexes. I had gpt-5.6-luna crawl the ~46,000 names from this hackathon, and then some public registries for names and addresses to assure we can support the multicultural names and grammars far beyond my monolingual capabilities. I'm a big fan of WYSIWYG ui's so the OCR we use needs to be precise in the overlays, that's why we are still using tesseract -- really trying to get paddleocr to work but it's geometry is not the most compatible for WYSIWYG.

There was an unbelievable amount of mind numbing work, going through millions of records and making careful regexes and grammars -- only gpt-5.6-luna was suitable for this! And thanks to Tibo and the machine gun of usage resets, I was able to have the workers process precision name/address detection that no human should ever have to fine-tune.

Seriously, can you imagine reading and writing these for millions of records?

  `\\b(?:\\d{1,6}[-–]\\s*)?\\d{1,6}[A-Za-z
]{0,2}\\s+(?:${ADDRESS_NAME_SRC}\\s+${STRE
ET_SUFFIX_SRC}\\b|${STREET_PREFIX_SRC}\\s+
${ADDRESS_NAME_SRC}|${ADDRESS_NAME_SRC}(?=
,[ \\t]*(?:Rm\\.?|Room|Suite|Ste\\.?|Unit|
Apt\\.?|Floor|Fl\\.?|Bldg\\.?|Building|#[\
\p{L}\\p{N}]|\\d{1,2}(?:st|nd|rd|th)[\\t ]
+Floor))|${ADDRESS_NAME_SRC}(?=,[ \\t]*[\\
p{Lu}][\\p{Ll}])|${ADDRESS_NAME_SRC}(?=,[
\\t]*(?:[A-Z]{2,}|#[\\p{L}\\p{N}]{1,8}|\\d
{1,2}(?:st|nd|rd|th)[\\t ]+Floor)))` +
  `\\b(?:\\d{1,6}[-–]\\s*)?\\d{1,6}[A-Za-z
]{0,2}\\s+(?:${ADDRESS_NAME_SRC}\\s+${STRE
ET_SUFFIX_SRC}\\b|${STREET_PREFIX_SRC}\\s+
${ADDRESS_NAME_SRC}|${ADDRESS_NAME_SRC}(?=
,[ \\t]*(?:Rm\\.?|Room|Suite|Ste\\.?|Unit|
Apt\\.?|Floor|Fl\\.?|Bldg\\.?|Building|#[
]?[\\p{L}\\p{N}]|\\d{1,2}(?:st|nd|rd|th)[\
\t ]+Floor))|${ADDRESS_NAME_SRC}(?=,[ \\t]
*[\\p{Lu}][\\p{Ll}])|${ADDRESS_NAME_SRC}(?
=,[ \\t]*(?:[A-Z]{2,}|#[ ]?[\\p{L}\\p{N}]{
1,8}|\\d{1,2}(?:st|nd|rd|th)[\\t ]+Floor))
)`

Challenges we ran into

Offline OCR is not great, typo-tolerant detection is challenging, ocr-artifact-tolerant detection is even more challenging, multi-cultural PHI/PII means some names are words and some words are names, international address formats without triggering false positive matches on OCR noise. Intended users are very low tech and impatient, so a lot of talking to users was involved to make sure the ui is clear -- talking to people is physically and mentally taxing.

Accomplishments that we're proud of

Getting the full offline image/pdf automasking layer working, and it is working surprisingly well for detection and drawing/overlaying. Using public registry data to carefully support names/addresses while accidentally building a lead list. There are many little challenging scenarios that are hard to mention but each challenge felt great to properly and accurately solve, like OCR tolerant column detection where names or addresses might wrap or taking patterns of rows/columns to push name detection confidence just high enough to be useful.

What we learned

People fear AI while knowing they have to adapt and use it; so having tools that they can see and quickly understand helps them feel safe and protected, and gives them more control which also helps them feel safe. There is no feasible way to solve the thousands of tiny problems required to detect phi/pii offline without gpt-5.6-luna and it's ability to solve complex problems without breaking the bank.

What's next for PHI Mask

I want to bundle this into pre/post hooks to wrap agent harnesses but I'm not sure people would care, compliance is not the type of thing people impose for fun. So I will be trying to increase OCR accuracy (working around paddle geometry gaps) and hopefully getting more medical clinics / law firms using this and go from there.

Built With

Share this project:

Updates