I've been using gptel
since the beginning of the AI craze. It's, in my
opinion, a work of art. However, manually checking and replacing names, phone
numbers, and project details is both annoying and unreliable. For people who use
LLM daily, an automated desensitization could save a lot of time.
Several weeks ago, after reading a news report about ChatGPT calling a user by his real name 1, I was freaked out and finally decided to take some time to implement myself a function to automate desensitization. After a few weeks of use, I found it works without major problems. The process is straightforward: it first checks if the text being sent to an LLM contains any strings matching pre-defined sensitive information. If it does, it asks whether you want to halt the request or mask the information. In the latter case, it sends the desensitized data and restore the placeholder with predefined restoring strings after receiving the LLM's response.
In the rest of this blog, I'll briefly explain the process and how you can adapt it for your own use.
Define the patterns of sensitive informations
Sensitive information contains three components: the information you want to
hide (the pattern), the placeholder that will be visible to LLMs, and the
restoring string that replaces the placeholder when you get a response from an
LLM. These components comprise a triplet, which should be stored in a list,
like the llm:sensitive-list
variable shown below:
|
|
Thank you for leaving a comment if you have any idea about desensitizing API keys
You can decide to use plain text as the pattern, like "Albert Einstein", or use regular expression. Besides the inconvenience of defining multiple patterns for a name, using plain text actually comes with an advantage: performance. This is also the reason why I prefer using plain text patterns to mask API keys: defining a regex for API keys is easy, but Emacs processing the regex is extremely costly if still possible, no need to mention how many false alarms it produces.
I intentionally made placeholders in the pattern of “person-name-x9Pf” or “phone-number-w9rD”, since in this way most LLMs will still understand what is happening in the conversation, without knowing any concrete personal information. The only thing you need to take care of is try to append a random string at the end of each placeholder, instead of using strings like “a-person-name”, so that both you and your LLM won't mix the names up.
The filter function
The task left to the filter function, llm:filter-sensitive-info
, is to simply check the patterns defined in the sensitive information list.
It was inspired by this reply to an issue post on gptel's github repo:
|
|
After defining the filter function, just don't forget to add it to the hook gptel-prompt-filter-hook
.
The restoring function
By implementing the llm:sensitive-list
and llm:filter-sensitive-info
, you already made sure that no information in the black list will go out of your computer. But it will be annoying if LLM's responses are full of “person-name-x9Pf”, right?
The aim of the restoring function is to restore placeholders back to the actual information, taking place in your computer.
By using the following function, the restored text are those defined in the third component in llm:sensitive-list
.
Again, after defining the function, remember to add it to the hook gptel-post-response-functions
.
|
|
The complete codes
Voilà! That's about all that I wanted to share. You can just copy the following code and adapt llm:sensitive-list
for your own needs. Thanks for reading, and happy Emacs-ing!
|
|