PIIPS (PII Protection Service) is a Flask-based API that provides PII anonymization and de-anonymization using Presidio and integrates with Ollama for processing anonymized data.
- Detects PII (Personally Identifiable Information) in text.
- Anonymizes PII by replacing it with unique placeholders.
- Sends anonymized text to an LLM via Ollama.
- De-anonymizes responses to restore original PII values.
- Provides configurable options (e.g., showing LLM’s internal thought process).
git clone https://github.com/yourusername/PIIPS.git
cd PIIPSEnsure you have Conda installed, then create and activate a new environment:
conda create -n piips_env python=3.10 -y
conda activate piips_envpip install -r requirements.txtOllama provides local execution of LLMs. Install it using:
- Linux/macOS
curl -fsSL https://ollama.com/install.sh | sh- Windows: Download and install from Ollama's official website.
Then, start the Ollama server:
ollama serveBy default, PIIPS is set to use DeepSeek 7B (deepseek-r1:7b).
To use a any model, download it via Ollama:
ollama pull <model-name>Modify piips.py to use your downloaded model. Update this line:
LLM_MODEL = "deepseek-r1:7b"python piips.pyBy default, the server runs on port 3000.
Endpoint: GET /health
Description: Checks if the server is running.
Response:
"PII Protection Server is up"Endpoint: POST /anonymize
Description: Detects and anonymizes PII in a given text.
📤 Request:
{
"text": "John Doe lives in New York and his phone number is 123-435-6789."
}📥 Response:
{
"items": [
{
"end": 82,
"entity_type": "PHONE_NUMBER",
"operator": "custom",
"start": 63,
"text": "<PHONE_NUMBER_8579>"
},
{
"end": 38,
"entity_type": "LOCATION",
"operator": "custom",
"start": 23,
"text": "<LOCATION_8676>"
},
{
"end": 13,
"entity_type": "PERSON",
"operator": "custom",
"start": 0,
"text": "<PERSON_6480>"
}
],
"text": "<PERSON_6480> lives in <LOCATION_8676> and his phone number is <PHONE_NUMBER_8579>."
}Endpoint: POST /deanonymize
Description: Replaces placeholders in text with original values.
📤 Request:
{
"text": "<PERSON_5678> lives in <LOCATION_1234>.",
"deanonymizers": {
"<PERSON_5678>": "John Doe",
"<LOCATION_1234>": "New York"
}
}📥 Response:
{
"text": "John Doe lives in New York."
}Endpoint: POST /pii-guard-llm
Description: Anonymizes PII, sends it to an LLM, and de-anonymizes the response.
The show_thinking parameter controls whether the response from the LLM includes its internal reasoning, which appears inside ... tags. Some language models, particularly reasoning models, "think" to themselves before formulating a response. This self-reflection is included in the output as a separate section enclosed in tags.
📤 Request:
{
"text": "John Doe lives in New York and his phone number is 123-435-6789. Summarize the information provided to you in a table.",
"show_thinking": false
}📥 Sample Response (Anonymized & Processed by LLM, then De-Anonymized):
{
"text": "Here is the summarized information in a table:
| PERSON | LOCATION | PHONE Number |
|-------------|------------------------------------|-----------------------------------|
| John Doe | New York | 123-435-6789 |
Note: The phone number placeholder is represented as `123-435-6789` in the table, and the full phone number provided was `123-435-6789`."
}📝 Notes:
- If
"show_thinking": true(default behavior), the response will include the LLM's reasoning (<think>...</think>) if the model outputs such information. Setting"show_thinking": falsewill remove the LLM's reasoning and only provide the final reponse (as seen in the example above). - Anonymized text is processed by an LLM (e.g., deepseek-r1:7b) before being de-anonymized back to the original context.
- The server defaults to port 3000.
- Modify LLM_MODEL in piips.py to use a different LLM.
- By default, GPU acceleration for Ollama is turned on:
os.environ["OLLAMA_CUDA"] = "1"