Responsible AI guardrails for LLM applications. Local-first, drop-in SDK.
Project description
lyzr-rai
Drop-in Responsible AI guardrails for LLM applications. Local-first Python SDK — no server, no API key, no telemetry.
from lyzr_rai import RAIClient, Check
client = RAIClient(checks=[
Check.secrets(),
Check.pii(),
Check.keywords(rules=[{"keyword": "confidential", "action": "block"}]),
])
result = client.check_input("Email john@acme.com about the confidential project")
print(result.blocked) # True — keyword 'confidential' triggered block
print(result.processed_text) # "Email [RAI_EMAIL_ADDRESS_1] about the confidential project"
Install
# Core checks: secrets, pii, keywords, openapi, sql
pip install lyzr-rai
# Add ML-backed checks: topics, toxicity, prompt injection, nsfw, gibberish
pip install lyzr-rai[ml]
| Check | Install | Notes |
|---|---|---|
secrets |
core | Regex (AWS, GitHub, OpenAI keys, etc.) |
pii |
core | Presidio — EMAIL, PHONE, SSN, CREDIT_CARD, etc. |
keywords |
core | Literal case-insensitive matching |
valid_openapi |
core | OpenAPI 3.x JSON/YAML validation |
valid_sql |
core | sqlglot syntax validation |
banned_topics |
[ml] |
Zero-shot classifier (deberta-v3-large) |
allowed_topics |
[ml] |
Same model; blocks if no allowed topic matches |
toxicity |
[ml] |
XLM-Roberta (EthicalEye) |
prompt_injection |
[ml] |
deberta-v3-base (ProtectAI). Input-direction only. |
nsfw |
[ml] |
NSFW text classifier |
gibberish |
[ml] |
Gibberish text detector |
Without
[ml], attempting to construct an ML check raises a clearImportErrorwith the install hint. Nothing is silently downloaded.With
[ml], model weights lazy-download from HuggingFace Hub on first use and cache to~/.cache/huggingface/hub/. Override the cache directory viaHF_HOME.
Concepts
Actions
Each detection check supports two actions: block (reject the input) and redact (replace the offending span with a token).
Tokens
Redacted spans are replaced with [RAI_<TYPE>_<N>]:
"Email me at john@acme.com" -> "Email me at [RAI_EMAIL_ADDRESS_1]"
The same value always reuses its token within a client's lifetime (deduplication):
r1 = client.check_input("john@acme.com") # -> [RAI_EMAIL_ADDRESS_1]
r2 = client.check_input("john@acme.com again") # -> [RAI_EMAIL_ADDRESS_1] again
Tokens are matched case-insensitively at unredact time — LLMs that "fix" casing don't break the round trip.
Pipeline
Checks run sequentially in registration order. Each check sees the text as mutated by upstream redaction. Results accumulate; the pipeline does not stop on the first block unless RAIClient(stop_on_block=True).
PII Redaction & De-redaction
The full round trip with an LLM:
from lyzr_rai import RAIClient, Check
client = RAIClient(checks=[Check.pii(), Check.secrets()])
# 1. Redact PII before sending to the LLM
user_msg = "Hi, I'm Alex Rivera. Email alex@example.com — my AWS key is AKIAIOSFODNN7EXAMPLE."
input_result = client.check_input(user_msg)
print(input_result.processed_text)
# "Hi, I'm [RAI_PERSON_1]. Email [RAI_EMAIL_ADDRESS_1] — my AWS key is [RAI_SECRET_AWS_KEY_1]."
# 2. Send the redacted text to the LLM
llm_response = call_my_llm(input_result.processed_text)
# "Sure, [RAI_PERSON_1]. I'll email [RAI_EMAIL_ADDRESS_1] with details."
# 3. Run output checks. Tokens are auto-restored at the end.
output_result = client.check_output(llm_response)
print(output_result.processed_text)
# "Sure, Alex Rivera. I'll email alex@example.com with details."
One client per conversation
Each RAIClient holds its own redaction state. Do not share clients across conversations — token [RAI_EMAIL_ADDRESS_1] from Alice's session would map back to Alice's email, even if Bob's session is the one calling check_output.
# Pattern A: new client per session
client = RAIClient(checks=[...])
# Pattern B: reset between sessions
shared_client.reset()
Manual unredact
If you bypass check_output (e.g. you don't need to scan the LLM output), call unredact() directly:
final = client.unredact(llm_response)
Unknown [RAI_*] tokens (LLM hallucinations) are left as-is.
Examples
Configure individual checks
client = RAIClient(checks=[
Check.secrets(action="block"),
Check.pii(
entities=["EMAIL_ADDRESS", "PHONE_NUMBER", "PERSON"],
actions={"PERSON": "block"}, # block on PERSON, redact others
default_action="redact",
custom=[
{"label": "ACCT-12345", "action": "redact", "replacement": "[ACCOUNT]"},
],
),
Check.keywords(rules=[
{"keyword": "confidential", "action": "block"},
{"keyword": "internal", "action": "redact", "replacement": "[INTERNAL]"},
]),
Check.valid_sql(),
])
ML checks
client = RAIClient(checks=[
Check.prompt_injection(threshold=0.85),
Check.toxicity(threshold=0.9),
Check.banned_topics(topics=["weapons", "self-harm"]),
Check.nsfw(validation_method="sentence"),
])
Inspecting results
result = client.check_input("...")
result.blocked # bool
result.block_reason # str | None
result.processed_text # str
result.warnings # list[str]
result.detections # dict[check_name, payload]
result.redaction_map # dict[original_value, token]
for check in result.checks:
print(check.name, check.duration_ms, check.detected, check.blocked)
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lyzr_rai-0.1.0.tar.gz.
File metadata
- Download URL: lyzr_rai-0.1.0.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f1ab91ec1ca6148da46c52668f74bca31798f298383cd62af906e570ab7d523
|
|
| MD5 |
c6eddb0793da1cb1f8210952cd56926c
|
|
| BLAKE2b-256 |
7db8cfccfdfdf87b0c0cff124056dab306bbba7c42d0614ecc03a88bfdfeed62
|
Provenance
The following attestation bundles were made for lyzr_rai-0.1.0.tar.gz:
Publisher:
publish.yml on NeuralgoLyzr/studio-srs-apis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lyzr_rai-0.1.0.tar.gz -
Subject digest:
3f1ab91ec1ca6148da46c52668f74bca31798f298383cd62af906e570ab7d523 - Sigstore transparency entry: 1433767655
- Sigstore integration time:
-
Permalink:
NeuralgoLyzr/studio-srs-apis@a116ca978e9c9c99d4b0aeda10f2fde1148719c2 -
Branch / Tag:
refs/heads/oss - Owner: https://github.com/NeuralgoLyzr
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a116ca978e9c9c99d4b0aeda10f2fde1148719c2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lyzr_rai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lyzr_rai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32badac7f38d7bb43512a52843454bd125b2c17b389d52403d3b2aef2850fdb2
|
|
| MD5 |
4c2ac5c1a3dc311135a94d014a94bfe7
|
|
| BLAKE2b-256 |
375f758847424fbab2d7a96f3997795266c07a3b707886fbe851e490302fe703
|
Provenance
The following attestation bundles were made for lyzr_rai-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on NeuralgoLyzr/studio-srs-apis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lyzr_rai-0.1.0-py3-none-any.whl -
Subject digest:
32badac7f38d7bb43512a52843454bd125b2c17b389d52403d3b2aef2850fdb2 - Sigstore transparency entry: 1433767718
- Sigstore integration time:
-
Permalink:
NeuralgoLyzr/studio-srs-apis@a116ca978e9c9c99d4b0aeda10f2fde1148719c2 -
Branch / Tag:
refs/heads/oss - Owner: https://github.com/NeuralgoLyzr
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a116ca978e9c9c99d4b0aeda10f2fde1148719c2 -
Trigger Event:
push
-
Statement type: