Skip to main content

CipherExplain SDK — register models and get encrypted SHAP explanations via the CipherExplain API

Project description

CipherExplain Python SDK

Register your own models and get encrypted SHAP explanations via the CipherExplain API.

PyPI Python License: AGPL v3 Downloads

Install

pip install cipherexplain

Dependencies installed automatically: httpx, numpy, scikit-learn.

Optional: local FHE mode

For client-side CKKS encryption (fhe_mode='ckks') install the fhe extra:

pip install 'cipherexplain[fhe]'

This adds OpenFHE so the SDK can encrypt inputs locally and decrypt results without the server ever seeing plaintext.

Quick start

from cipherexplain_sdk import CipherExplainClient, extract_spec

client = CipherExplainClient(api_key="vb_...")

# 1. Train locally — nothing leaves your machine
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
model  = LogisticRegression().fit(scaler.fit_transform(X_train), y_train)

# 2. Extract weights only (no pickle, no training data)
spec = extract_spec(model, "my_model", feature_names=["age", "income", "score"],
                    scaler=scaler)

# 3. Register with the API
client.register(spec)

# 4. Get SHAP explanations — pass raw values, scaler is applied server-side
result = client.explain_raw("my_model", x_raw)
print(result["shap_values"])    # per-feature attributions
print(result["prediction"])     # 0.0–1.0 probability

Supported model types

Tree ensembles (new)

RandomForestClassifier, GradientBoostingClassifier, DecisionTreeClassifier — and their regressor variants — are now fully supported. Use serialize_model from cipherexplain_eval to build the registration payload:

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.preprocessing import StandardScaler
import cipherexplain_eval as ce

# Train locally
rf = RandomForestClassifier(n_estimators=100).fit(X_train, y_train)

# Serialize to JSON (no pickle, no training data)
payload = ce.serialize_model(
    rf,
    feature_names=["age", "income", "score"],
    model_id="my_rf",
)

# Register with the API (use the raw API or SDK client)
client.register(payload)

# Explain — fhe_mode is ignored for tree models, plaintext KernelSHAP runs
result = client.explain("my_rf", x)
print(result["shap_values"])

GradientBoostingClassifier works the same way — serialize_model captures the learning rate and initial estimator needed for correct probability reconstruction.

Linear classifiers

Weights serialised to JSON — model must be described by a coefficient matrix and intercept vector.

Framework How
sklearn LogisticRegression extract_spec(model, ...)
sklearn LinearSVC extract_spec(model, ...)
Any sklearn-compatible object with coef_ / intercept_ extract_spec(model, ...)
PyTorch nn.Linear extract_spec(layer, ...)
PyTorch pure-linear nn.Sequential extract_spec(seq, ...)
TensorFlow / Keras Dense (no activation) from_weights(layer.get_weights()[0].T, layer.get_weights()[1], ...)
JAX / statsmodels / R / anything else from_weights(coef, intercept, ...)

All supported model types

model_type Class SHAP method
logistic_regression sklearn.LogisticRegression KernelSHAP (FHE-simulated)
linear_svc sklearn.LinearSVC KernelSHAP (FHE-simulated)
decision_tree sklearn.DecisionTreeClassifier/Regressor KernelSHAP (plaintext)
random_forest sklearn.RandomForestClassifier/Regressor KernelSHAP (plaintext)
gradient_boosting sklearn.GradientBoostingClassifier/Regressor KernelSHAP (plaintext)

TensorFlow / Keras example

from cipherexplain_sdk import from_weights

# Keras model with a single Dense output layer
import numpy as np
w, b = keras_model.layers[-1].get_weights()  # w shape: (n_features, n_classes)
spec = from_weights(
    coef=w.T,          # transpose to (n_classes, n_features)
    intercept=b,
    model_id="keras_model",
    feature_names=[...],
    classes=[0, 1],
)
client.register(spec)

JAX / statsmodels / R example

from cipherexplain_sdk import from_weights

# Pass coefficient array and intercept directly
spec = from_weights(
    coef=[[0.42, -0.17, 0.93]],   # shape (1, n_features) for binary
    intercept=[-0.31],
    model_id="my_model",
    feature_names=["f1", "f2", "f3"],
    classes=[0, 1],
    scaler_mean=[0.0, 0.0, 0.0],  # optional: embed scaler for /explain_raw
    scaler_scale=[1.0, 1.0, 1.0],
)
client.register(spec)

Client reference

client = CipherExplainClient(api_key="vb_...", base_url="https://cipherexplain.vaultbytes.com")

Model management

Method Description
client.register(spec) Register a model (spec from extract_spec or from_weights)
client.list_models() List all models available to your key
client.delete(model_id) Delete a registered model and free its slot

Slot limits: free = 1 model · developer = 10 · enterprise = unlimited

Explanations

Method Description
client.explain(model_id, features) SHAP explanation — features must be pre-scaled
client.explain_raw(model_id, features) SHAP explanation — raw values, auto-scaled server-side

Both return:

{
    "prediction": 0.74,          # model probability
    "base_rate": 0.31,           # baseline (training set average)
    "shap_values": [...],        # per-feature attribution (sum ≈ prediction - base_rate)
    "feature_names": [...],
    "metadata": {...}
}

Reports & account

Method Description
client.report(benchmark_data) Generate PDF audit report — returns raw bytes, save as .pdf
client.usage() Monthly quota: used / remaining for explain and oracle
client.rotate_key() Issue new key, deactivate current. Models migrate automatically.
client.health() API health check — no key required
client.load_demo_model() Load the demo credit model (credit_model)

Generating a PDF audit report

import json

# Load benchmark results from the FHE Testing Oracle
with open("oracle_benchmark.json") as f:
    benchmark = json.load(f)

pdf_bytes = client.report(benchmark)

with open("audit_report.pdf", "wb") as f:
    f.write(pdf_bytes)

Requires Developer or Enterprise tier.

Key rotation

result = client.rotate_key()
print(result["new_key"])         # vb_... — save this immediately
print(result["models_migrated"]) # all your models move automatically

# Your old key is now inactive — create a new client
client = CipherExplainClient(api_key=result["new_key"])

Error handling

All methods raise httpx.HTTPStatusError on API errors. Check exc.response.status_code:

import httpx

try:
    client.register(spec)
except httpx.HTTPStatusError as exc:
    if exc.response.status_code == 401:
        print("Missing X-API-Key")
    elif exc.response.status_code == 403:
        print("Invalid key or tier restriction (e.g. PDF reports need Developer+)")
    elif exc.response.status_code == 404:
        print("Model not found")
    elif exc.response.status_code == 409:
        print("Model ID already registered — delete it first or use a different ID")
    elif exc.response.status_code == 422:
        print("Validation error:", exc.response.json()["detail"])
    elif exc.response.status_code == 429:
        print("Quota exceeded — model slot limit or monthly call limit reached")
    else:
        raise

Tier limits

Free Developer Enterprise
SHAP API calls / month 50 5,000 50,000
Oracle runs / month 3 500 5,000
Model slots 1 10 Unlimited
PDF audit reports Yes Yes

Get an API key

vaultbytes.com/cipherexplain

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

cipherexplain-0.5.1.tar.gz (63.5 kB view details)

Uploaded Source

Built Distribution

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

cipherexplain-0.5.1-py3-none-any.whl (69.5 kB view details)

Uploaded Python 3

File details

Details for the file cipherexplain-0.5.1.tar.gz.

File metadata

  • Download URL: cipherexplain-0.5.1.tar.gz
  • Upload date:
  • Size: 63.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for cipherexplain-0.5.1.tar.gz
Algorithm Hash digest
SHA256 ced2e8bcdfdb9b9a655db1dddd92ece82a5090a8ecbfcd437f5dff4a6df128c2
MD5 cd170ba239acf92fb0a4d508c43dea36
BLAKE2b-256 9f5ff04fd48eb3885d6dff8128eac2e79b4c30f062b6a00daf05d8e468efc9ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for cipherexplain-0.5.1.tar.gz:

Publisher: workflow.yml on VaultBytes/CipherExplain

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

File details

Details for the file cipherexplain-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: cipherexplain-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 69.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for cipherexplain-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2100debc8dd9c5b5c5fe3c5b0ddc5fccc7a67d6a2baaea19c6e0553fa8c94a14
MD5 e0470bb22f01bf2924c238eb6cf3c8ac
BLAKE2b-256 92ef6ed830d435ddaa53134bf2d8c6cadbf7f4a7c7fe82bc4e943dcddd4e5b30

See more details on using hashes here.

Provenance

The following attestation bundles were made for cipherexplain-0.5.1-py3-none-any.whl:

Publisher: workflow.yml on VaultBytes/CipherExplain

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