Metadata-Version: 2.4
Name: membrane-ai
Version: 3.1.6
Summary: Enterprise AI privacy middleware — reversible PII anonymization.
Author-email: Membrane Open Source <oss@membrane.dev>
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110.0
Requires-Dist: uvicorn[standard]>=0.29.0
Requires-Dist: openai>=1.14.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: presidio-analyzer>=2.2.0
Requires-Dist: spacy>=3.7.0
Provides-Extra: dev
Requires-Dist: pytest>=8.1.0; extra == "dev"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.21.0; extra == "anthropic"
Dynamic: license-file

<div align="center">

# Membrane

**Enterprise AI Privacy Middleware — Reversible PII Anonymization for LLM Calls**

[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![FastAPI](https://img.shields.io/badge/FastAPI-0.100+-009688.svg)](https://fastapi.tiangolo.com)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

*Strip PII before it hits the LLM. Restore it when it comes back. Even when the LLM paraphrases.*

</div>

---

## 🛑 The Problem

You want to use LLMs on sensitive data — patient records, customer emails, financial documents — but you can't send PII to external APIs. Masking is easy. **Unmasking is hard**, especially when the LLM rewrites your text:

```
You send:    "<PERSON_1> emailed the clinic"
LLM returns: "The patient contacted the clinic"   ← placeholder GONE
```

Most anonymization tools permanently lose context here. Membrane doesn't.

## 📦 Installation

Install Membrane directly via pip:

```bash
pip install membrane-ai
```

## 🚀 Quick Start (Python SDK)

Membrane is designed to wrap entirely around your existing prompts. You just pass in the raw text, and Membrane handles PII detection, context preservation, secure sending, and rehydration internally.

```python
from membrane import TrustLayer

# Works with openai, anthropic, gemini, ollama, or mock.
# Model specifies the exact AI model (e.g., gpt-4o, claude-3-opus, gemini-2.5-flash).
layer = TrustLayer(provider="openai", model="gpt-4o", api_key="sk-your-key-here")

# Send raw, un-anonymized PII straight to the layer
response = layer.call("My name is John Doe and my SSN is 123-45-6789. Please draft an email to john@example.com.")

# The data sent to OpenAI looked like this:
print(response["anonymized_prompt"])
# -> "My name is <PERSON_1> and my SSN is <SSN_1>. Please draft an email to <EMAIL_1>."

# The response returned from Membrane to you looks like this:
print(response["final_response"])
# -> "Here is the email draft for John Doe..."
```

### Supported Providers
To securely route your traffic, initialize `TrustLayer` with any of these providers:
- `provider="openai"` (Requires `OPENAI_API_KEY`)
- `provider="anthropic"` (Requires `ANTHROPIC_API_KEY`)
- `provider="gemini"` (Requires `GEMINI_API_KEY`)
- `provider="ollama"` (Set `api_base="http://localhost:11434/v1"` usually pointing to local vLLM)
- `provider="mock"` (Default, skips API and mimics an LLM response safely locally)

*Note: You can override the default AI model for any provider by passing `model="your-model-name"` directly into the `TrustLayer()` constructor.*

---

## 🧠 How It Works (Entity Alignment)

```
Input → Presidio NER → Tokenize + Track → LLM → Alignment → Rehydrate → Output
              │              │                        │            │
         confidence     ±5 word              identity          3-phase
          scores       context              restoration      replacement
```

**The key differentiator: Entity Alignment.** When the LLM paraphrases away a placeholder, Membrane uses alias dictionaries + contextual sentence tracking to deterministically restore the original identity using a local alignment confidence score.

---

## 🌐 Running as a standalone API Service

If you aren't doing Python development and want to run Membrane as a standalone backend microservice, it comes bundled with an enterprise-ready FastAPI instance.

```bash
git clone https://github.com/rishabh-oberoi/Membrane.git
cd Membrane
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python -m spacy download en_core_web_sm

# Start the server
uvicorn membrane.main:app --reload --port 8000
```

### Making an API Call
```bash
curl -X POST http://localhost:8000/secure-llm-call \
  -H "Content-Type: application/json" \
  -d '{"prompt": "John Doe emailed john@example.com."}'
```

---

## ⚙️ Configuration
You can configure Membrane by setting standard environment variables before creating the `TrustLayer`.

| Variable | Default | Description |
|----------|---------|-------------|
| `TRUST_ENABLE_PRESIDIO` | `true` | Presidio NER; `false` = regex fallback only |
| `TRUST_LLM_PROVIDER` | `mock` | The AI provider to route calls to |
| `TRUST_LLM_MODEL` | `None` | Override the default model (e.g., `gpt-4o`) |
| `TRUST_STRICT_MODE` | `true` | Prepend placeholder preservation instructions |
| `TRUST_MAX_RETRIES` | `1` | Retry if the LLM destroys placeholders |
| `TRUST_MIN_CONFIDENCE` | `0.4` | Detection confidence threshold |
| `TRUST_CONTEXT_WINDOW` | `5` | Words of context captured per entity |

## License

[MIT](LICENSE)
