Skip to main content

Official Python client for peyeeye.ai — PII redaction & rehydration for LLM prompts.

Project description

peyeeye

PyPI version Python versions License: MIT

Official Python client for peyeeye.ai — redact PII on the way into your LLM prompts and rehydrate it on the way out.

pip install peyeeye

Python 3.9+. Single runtime dependency: httpx. Fully type-hinted (py.typed).

Quickstart

import os
from peyeeye import Peyeeye
from anthropic import Anthropic

peyeeye = Peyeeye(api_key=os.environ["PEYEEYE_KEY"])
claude = Anthropic()

with peyeeye.shield() as shield:
    safe = shield.redact("Hi, I'm Ada, ada@a-e.com")
    reply = claude.messages.create(
        model="claude-sonnet-*",
        max_tokens=256,
        messages=[{"role": "user", "content": safe}],
    )
    print(shield.rehydrate(reply.content[0].text))

shield() opens a session, redacts, and cleans up on exit. Inside the block, the same real value always maps to the same token — Ada Lovelace is always [PERSON_1] — and tokens never leak across sessions.

Low-level calls

Skip the shield helper when you need more control:

r = peyeeye.redact("Card: 4242 4242 4242 4242")
# r.redacted    → "Card: [CARD_1]"
# r.session     → "ses_…"
# r.entities    → [DetectedEntity(token="[CARD_1]", type="CARD", span=(6, 25), confidence=0.99)]

clean = peyeeye.rehydrate("Confirmation for [CARD_1].", session=r.session)
# clean.text → "Confirmation for 4242 4242 4242 4242."

Stateless sealed mode

Pass stateless=True and peyeeye never stores the mapping — the redact response carries a sealed skey_… blob you hand back to rehydrate. Nothing lives on the server between calls.

with peyeeye.shield(stateless=True) as shield:
    safe = shield.redact("Email ada@a-e.com")
    clean = shield.rehydrate("Reply: [EMAIL_1]")
    # shield.rehydration_key is the skey_... blob, if you need to persist it

Or with raw calls:

r = peyeeye.redact("Email ada@a-e.com", session="stateless")
# r.rehydration_key → "skey_…"
clean = peyeeye.rehydrate("[EMAIL_1] received.", session=r.rehydration_key)

Streaming rehydration

When piping an LLM token stream straight to a user, naive rehydration breaks on mid-token boundaries. rehydrate_chunk() buffers partial tokens across chunks; call flush() once upstream closes.

with peyeeye.shield() as shield:
    safe = shield.redact(prompt)
    for chunk in your_llm_stream(safe):
        sys.stdout.write(shield.rehydrate_chunk(chunk))
    sys.stdout.write(shield.flush())

Never call flush() while the stream is still delivering chunks — you'll emit a half-formed placeholder.

Streaming redact (SSE)

For the /v1/redact/stream endpoint (Build plan and higher):

for event in peyeeye.redact_stream(["Hi, I'm Ada", " — card 4242 4242 4242 4242"]):
    if event.event == "session":
        session_id = event.data["session"]
    elif event.event == "redacted":
        print(event.data["text"])
    elif event.event == "done":
        print("chars:", event.data["chars"])

Custom detectors

peyeeye.create_entity(
    id="ORDER_ID",
    kind="regex",
    pattern=r"#A-\d{6,}",
    examples=["#A-884217", "#A-007431"],
    confidence_floor=0.9,
)

# dry-run a pattern before saving
peyeeye.test_pattern(pattern=r"#A-\d{6,}", text="ref #A-884217 and #A-1")
#   → TestPatternResponse(count=1, matches=[PatternMatch(value="#A-884217", ...)])

# inspect / update / retire
peyeeye.list_entities()
peyeeye.update_entity("ORDER_ID", enabled=False)
peyeeye.delete_entity("ORDER_ID")

# starter templates (Twilio SIDs, Stripe keys, AWS access keys, etc.)
for tpl in peyeeye.entity_templates():
    print(tpl.id, tpl.pattern)

Sessions

peyeeye.get_session("ses_…")       # SessionInfo
peyeeye.delete_session("ses_…")    # drop immediately

Errors

Every non-2xx response raises PeyeeyeError with .code, .status, .message, and .request_id. 429 and 5xx responses are retried with exponential backoff (Retry-After honoured); terminal errors raise immediately.

from peyeeye import PeyeeyeError

try:
    peyeeye.redact("…")
except PeyeeyeError as e:
    if e.code == "rate_limited":
        ...
    elif e.code == "forbidden":
        ...
    else:
        raise

Configuration

Peyeeye(
    api_key="pk_live_…",
    base_url="https://api.peyeeye.ai",
    timeout=30.0,
    max_retries=3,
)

For CI / air-gapped use, Peyeeye(transport=httpx.MockTransport(handler)) lets you mount a mock transport without monkey-patching.

Method reference

Method HTTP Purpose
peyeeye.redact(text, ...) POST /v1/redact Redact PII; returns token stream + session.
peyeeye.rehydrate(text, session=...) POST /v1/rehydrate Substitute tokens back. Accepts ses_… or skey_….
peyeeye.redact_stream(chunks, ...) POST /v1/redact/stream (SSE) Stream-safe redact.
peyeeye.get_session(id) GET /v1/sessions/{id} Inspect mapping metadata.
peyeeye.delete_session(id) DELETE /v1/sessions/{id} Evict a session.
peyeeye.list_entities() GET /v1/entities Built-ins + your custom detectors.
peyeeye.create_entity(...) POST /v1/entities Custom detector.
peyeeye.update_entity(id, ...) PATCH /v1/entities/{id} Toggle / tweak.
peyeeye.delete_entity(id) DELETE /v1/entities/{id} Retire.
peyeeye.test_pattern(pattern, text) POST /v1/entities/test Dry-run a regex.
peyeeye.entity_templates() GET /v1/entities/templates Starter patterns.

Full request / response schemas: https://peyeeye.ai/docs.

Using this SDK from an AI coding assistant

Drop these into your agent's context. Each snippet is self-contained and compiles as-is.

# Install
# pip install peyeeye

from peyeeye import Peyeeye, PeyeeyeError
import os

client = Peyeeye(api_key=os.environ["PEYEEYE_KEY"])  # or explicit base_url

# Round-trip: redact → call LLM → rehydrate (session-scoped)
with client.shield() as shield:
    safe = shield.redact("Hi, I'm Ada, ada@a-e.com")
    # ... send `safe` to the LLM, get `reply` back ...
    out = shield.rehydrate(reply)

# Stateless (zero server-side state; key is yours to persist)
with client.shield(stateless=True) as shield:
    safe = shield.redact("...")
    key = shield.rehydration_key  # skey_...
    clean = shield.rehydrate("[EMAIL_1] confirmed.")

# Low-level one-shot
r = client.redact("Card 4242 4242 4242 4242")
clean = client.rehydrate("Receipt: [CARD_1].", session=r.session)

# Error handling
try:
    client.redact(text)
except PeyeeyeError as e:
    # e.code ∈ {"rate_limited","forbidden","invalid_request","server_error", ...}
    # e.status, e.message, e.request_id
    raise

Endpoint envelope: all requests use Authorization: Bearer <api_key> against https://api.peyeeye.ai/v1/*. Errors follow {code, message, request_id} and surface as PeyeeyeError. Responses are plain JSON (dataclasses via from_dict).

Do: reuse one Peyeeye(...) per process; call .close() or use it as a context manager at shutdown. Don't: open a new client per request, call flush() mid-stream, or parse skey_ blobs yourself — the API opens them.

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

peyeeye-1.0.3.tar.gz (18.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

peyeeye-1.0.3-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file peyeeye-1.0.3.tar.gz.

File metadata

  • Download URL: peyeeye-1.0.3.tar.gz
  • Upload date:
  • Size: 18.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for peyeeye-1.0.3.tar.gz
Algorithm Hash digest
SHA256 4f2e26811910fd9e8fdb3bf1c3ae5d45468068e50f21de66df7b6e13fd4d6caa
MD5 c111f3902378b58feaa21ffad514b1a6
BLAKE2b-256 bebb9e22bd85c9f93358cedde77c51f5c53d0bdbd22a2313ada3f73a70186fd1

See more details on using hashes here.

Provenance

The following attestation bundles were made for peyeeye-1.0.3.tar.gz:

Publisher: publish.yml on peyeeye/peyeeye-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file peyeeye-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: peyeeye-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for peyeeye-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 854ef8af4120a39371e5b2530b139837cbc5b5775cf88360793da56452dce176
MD5 7b7a9e611d1d109e27b97a8df8c03018
BLAKE2b-256 aa8e30e082c167e221b8230b178e6d3afebaf633f2483cea7d0b4332444ba9a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for peyeeye-1.0.3-py3-none-any.whl:

Publisher: publish.yml on peyeeye/peyeeye-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page