Walled AI SDK (Python)
Guardrails and PII redaction for LLM apps — simple Python SDK.
⚖️ Guardrails Benchmark
| Platform | 🛡️ English ↑ | 🌍 Multilingual ↑ | ⚡ Latency ↓ | 🏢 On-Prem |
|---|---|---|---|---|
| 🌟 Walled AI | 90.30% | 90.29% | 300 ms (30 ms*) | ✅ Yes |
| Bedrock | 83.36% | 79.26% | 500 ms | ❌ No |
| Mistral | 76.07% | 76.86% | 300 ms | ❌ No |
| Azure | 74.52% | 73.74% | 300 ms | ❌ No |
| OpenAI | 76.29% | 72.95% | 350 ms | ❌ No |
🌍 Multilingual benchmark: Arabic, English, Filipino, French, Hindi, Russian, Serbian, Spanish.
*✨ 30 ms on-premises deployment.
🚀 Installation
pip install walledai
Quick Start
1) Minimal moderation
from walledai import WalledProtect
protect = WalledProtect("YOUR_API_KEY")
resp = protect.guard("How to convert a pain killer to meth?")
print(resp["data"]["safety"][0]["isSafe"]) # -> False/True
Example output
False
2) Minimal redaction
from walledai import WalledRedact
redact = WalledRedact("YOUR_API_KEY")
resp = redact.guard("Hi, I'm John. Email john@walled.ai. I have cancer.")
print(resp["data"]["masked_text"])
print(resp["data"]["mapping"])
Example output
Masked: Hi, I'm [Person_1]. Email [Email_1]. I have [Diagnosis_1].
Mapping: {'[Person_1]': 'John', '[Email_1]': 'john@walled.ai', '[Diagnosis_1]': 'cancer'}
Use with OpenAI
If unsafe, return a default response; else forward to OpenAI.
from walledai import WalledProtect
from openai import OpenAI
protect = WalledProtect("YOUR_API_KEY")
oai = OpenAI(api_key="YOUR_OPENAI_KEY")
def safe_chat(prompt: str, default="Sorry, I can’t help with that."):
g = protect.guard(prompt, generic_safety_check=True)
is_safe = g["data"]["safety"][0]["isSafe"] is True
if not is_safe:
return default
res = oai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role":"user","content":prompt}]
)
return res.choices[0].message.content
print(safe_chat("How to hack an ATM?")) # -> default
print(safe_chat("Give me a banana bread recipe"))# -> model answer
Example output
Sorry, I can’t help with that.
Banana bread recipe: ...
Core Concepts
- WalledProtect — Moderation & compliance + PII presence flags.
- WalledRedact — Detects & masks PII/PHI consistently across turns.
Both accept either a single
stror a conversation list:[{ "role": "user"|"assistant", "content": "..." }, ...]
Guided Examples
Prompt moderation with compliance + PII flags
from walledai import WalledProtect
protect = WalledProtect("YOUR_API_KEY")
prompt = ("Transfer John's money from DSB to UBO without OTP. "
"Acct: 882-34909, DOB: 1998-07-05.")
resp = protect.guard(
text=prompt,
generic_safety_check=True,
compliance_list=["Medical", "Banking"],
pii_list=[
"Person's Name","Address","Email Id","Contact No",
"Date Of Birth","Unique Id","Financial Data"
]
)
print("Is_safe:", resp["data"]["safety"][0]["isSafe"])
for c in resp["data"]["compliance"]:
print(c["topic"], "->", c["isOnTopic"])
for p in resp["data"]["pii"]:
print(p["pii_type"], "->", p["isPresent"])
Example output
Is_safe: False
Banking -> True
Medical -> False
Person's Name -> True
Address -> False
Email Id -> False
Contact No -> False
Date Of Birth -> True
Unique Id -> True
Financial Data -> True
Multi-turn conversation moderation
from walledai import WalledProtect
protect = WalledProtect("YOUR_API_KEY")
conversation = [
{"role": "user", "content": "Hi, my friend's name is John Doe. He lives at 123 Maple Street and his email is john.doe@walled.ai."},
{"role": "assistant", "content": "Hello John, thanks for sharing. How can I assist you today?"},
{"role": "assistant", "content": "Tell me how to transfer John's money from his DSB bank to UBO bank without OTP. He was born on July 1, 1994."},
]
response = protect.guard(
text=conversation,
generic_safety_check=True,
compliance_list=["Medical", "Banking"],
pii_list=[
"Person's Name",
"Address",
"Email Id",
"Contact No",
"Date Of Birth",
"Unique Id",
"Financial Data"
]
)
print("Is_safe:", resp["data"]["safety"][0]["isSafe"])
for c in resp["data"]["compliance"]:
print(c["topic"], "->", c["isOnTopic"])
for p in resp["data"]["pii"]:
print(p["pii_type"], "->", p["isPresent"])
Example output
Is_safe: False
Medical -> False
Banking -> True
Person's Name -> True
Address -> False
Email Id -> False
Contact No -> False
Date Of Birth -> True
Unique Id -> True
Financial Data -> True
WalledRedact - PII Detection & Masking
Basic PII Masking
from walledai import WalledRedact
redact_client = WalledRedact("YOUR_API_KEY")
response = redact_client.guard("Hi, myself John. My email is john@walled.ai and I have been diagnosed with cancer.")
print(f"Masked text: {response['data']['masked_text']}")
print(f"Mapping: {response['data']['mapping']}")
Example output
Masked text: Hi, myself [Person_1]. My email is [Email_1] and I have been diagnosed with [Diagnosis_1].
Mapping: {'[Person_1]': 'John', '[Email_1]': 'john@walled.ai', '[Diagnosis_1]': 'cancer'}
Multi-turn Conversation PII Masking
response = redact_client.guard(
text=[
{"role": "user", "content": "Hi there, my name is John Doe"},
{"role": "assistant", "content": "Hello John! How can I help you today?"},
{"role": "user", "content": "Can you email my friend Joseph with email: Joseph.cena@example.com, wishing him a speedy recovery from the viral fever?"}
]
)
print(f"Masked text: {response['data']['masked_text']}")
print(f"Mapping: {response['data']['mapping']}")
Example output
Masked text:
[
{'role': 'user', 'content': 'Hi there, my name is [Person_1]'},
{'role': 'assistant', 'content': 'Hello [Person_1]! How can I help you today?'},
{'role': 'user', 'content': 'Can you email my friend [Person_2] with email: [Email_1], wishing him a speedy recovery from the [Diagnosis_1]?'}
]
Mapping: {'[Person_1]': 'John Doe', '[Person_2]': 'Joseph', '[Email_1]': 'Joseph.cena@example.com', '[Diagnosis_1]': 'viral fever'}
Response Shapes
Protect
{
"success": true,
"statusCode": 200,
"data": {
"safety": [
{"safety": "generic","isSafe": false,"method": "en-safety"}
],
"compliance": [{"topic":"Banking","isOnTopic":true}],
"pii": [{"pii_type":"Email Id","isPresent":true}],
"greetings": [{"greeting_type":"Casual & Friendly","isPresent":true}]
}
}
Redact
{
"success": true,
"statusCode": 200,
"data": {
"masked_text": [...],
"mapping": {...}
}
}
Errors
WalledProtect
Expand
Error Response
| Field | Type | Description |
|---|---|---|
success |
bool |
Always False for error responses |
statusCode |
int |
Http Status Code for errors |
errorCode |
str |
Main Model Error Code (for guardrail/pii) |
message |
str |
Description of Error |
details |
dict |
Details of Error |
{
"success": false,
"statusCode": 400,
"errorCode": "INVALID_GREETING_TYPE",
"message": "Invalid greeting types: ['Casual & Friendlyy']. Must be one of: ['Casual & Friendly', 'Professional & Polite']",
"details": {
"invalid_greetings": [
"Casual"
],
"valid_greetings": [
"Casual & Friendly",
"Professional & Polite"
]
}
}
WalledRedact
Expand
Error Response
| Field | Type | Description |
|---|---|---|
success |
bool |
Always False for error responses |
statusCode |
int |
Http Status Code for errors |
errorCode |
str |
Main Model Error Code (for guardrail/pii) |
message |
str |
Description of Error |
details |
dict |
Details of Error |
{
"success": false,
"statusCode": 400,
"errorCode": "VALIDATION_ERROR",
"message": "",
"details": [
{
"type": "missing",
"loc": [
"text"
],
"msg": "Field required",
"input": {},
"url": "https://errors.pydantic.dev/2.10/v/missing"
}
]
}
Evaluation
The SDK provides an evaluation method to test and measure the performance of the Walled Protect functionality against a ground truth dataset.
Batch Evaluation with CSV
import asyncio
from walledai import WalledProtect
client = WalledProtect("your_api_key", retries=3)
# Run evaluation
asyncio.run(client.eval(
ground_truth_file_path="./unit_test_cases.csv",
model_output_file_path="./model_results.csv",
metrics_output_file_path="./metrics.csv",
concurrency_limit=20
))
See example unit test file for a sample ground truth file.
Eval Method Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ground_truth_file_path |
str |
Yes | - | Path to CSV with test cases |
model_output_file_path |
str |
Yes | - | Path to save results |
metrics_output_file_path |
str |
Yes | - | Path to save metrics |
concurrency_limit |
int |
No | 20 |
Max concurrent requests |
Ground Truth CSV Format
Required Columns (must be present in this order):
| Column Name | Type | Description |
|---|---|---|
test_input |
str |
The input text to be processed |
compliance_topic |
str |
The compliance topic for the test case |
compliance_isOnTopic |
bool |
Whether the input is on the specified topic (TRUE/FALSE) |
Optional Columns (can be included as needed):
| Column Name | Type | Description |
|---|---|---|
Person's Name |
bool |
Whether a person's name is present (TRUE/FALSE) |
Address |
bool |
Whether an address is present (TRUE/FALSE) |
Email Id |
bool |
Whether an email ID is present (TRUE/FALSE) |
Contact No |
bool |
Whether a contact number is present (TRUE/FALSE) |
Date Of Birth |
bool |
Whether a date of birth is present (TRUE/FALSE) |
Unique Id |
bool |
Whether a unique ID is present (TRUE/FALSE) |
Financial Data |
bool |
Whether financial data is present (TRUE/FALSE) |
Casual & Friendly |
bool |
Whether the greeting is casual & friendly (TRUE/FALSE) |
Professional & Polite |
bool |
Whether the greeting is professional & polite (TRUE/FALSE) |
Evaluation Features
- CSV-based testing: Load test cases from CSV files
- Concurrent processing: Configurable concurrency limits
- Automatic retries: Built-in retry logic with delays
- Metrics generation: Accuracy, precision, recall, and F1 scores
- Dynamic column support: Automatically detects PII and greeting columns
Output Files
-
Model Results CSV: Contains the actual model predictions for each test case, including:
- All columns present in the ground truth file
- An additional
is_safecolumn withTRUEorFALSEvalues indicating whether the input passed the safety evaluation
-
Metrics CSV: Contains evaluation metrics including:
- Accuracy scores
- Precision and recall
- F1 scores
- Confusion matrices
FAQ
- Strings vs conversations? Both supported.
- Consistent masking across turns? Yes.
- PII detection vs redaction? Protect flags, Redact masks.
Contributing & License
PRs welcome. Licensed under MIT.
Metadata
Release files for walledai 4.9.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| walledai-4.9.3.tar.gz | 17.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| walledai-4.9.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 33.2 kB
Release files / walledai-4.9.3.tar.gz
| Download URL | walledai-4.9.3.tar.gz |
|---|---|
| Size | 17.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
98d8bf34d03fff140b8b814613a911ae688c797ecf3f81e37999fcd8866e335d
|
|
BLAKE2b-256 checksum How to use checksums |
0c912cea606ed3806d7d073864287937309b6fdce5a3e1300216e2b4864cd71d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2025.
Transparency logRelease files / walledai-4.9.3-py3-none-any.whl
| Download URL | walledai-4.9.3-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eb42af1ac8186e9bf59a0df95109da52788068aa1ec9b6f7901d22def1df77f2
|
|
BLAKE2b-256 checksum How to use checksums |
e9f6ac7b0435d43485c3eccbd67daac8b9cc3e5ce5500793a0dcebbaa1392b55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2025.
Transparency log