Skip to main content

Behavioral integrity layer for AI systems during training and inference

Project description

signAI

Runtime behavioral integrity monitoring for PyTorch models.

signAI adds a small monitoring layer around training and inference so you can detect suspicious model behavior in real time — without exposing model weights, raw inputs, or gradients. The production layer supports:

  • Local artifact mode with no server
  • Daemon mode (localhost:7731, auto-discovered by the SDK)
  • Self-hosted server mode
  • Air-gapped private deployment mode

What signAI detects

signAI monitors a model's behavioral fingerprint rather than its accuracy. It catches anomalies such as:

  • distribution shift in inputs or activations
  • gradient manipulation and targeted poisoning during training
  • unexpected output distribution changes at inference time

Detection is based on a conditional behavioral model (CBM): for each operating state S, signAI learns the expected behavioral response Z and flags deviations.

What is in this repo

  • signai/core/: research and scoring core
  • signai/core/extractors/: S/Z feature extractors for classifiers, LLMs, and custom models
  • signai/core/detectors/: detector registry (Mahalanobis, neural, association)
  • signai/client/: production SDK
  • signai_server/: standalone REST server for hosted and self-hosted scoring

Install

SDK only, local mode:

pip install signai

SDK plus server dependencies:

pip install "signai[server]"

SDK plus server plus Postgres support:

pip install "signai[server,postgres]"

For local development in this repo:

python -m venv .venv
.venv\Scripts\activate
pip install -e ".[server]"

Quick Start

Local mode (any classifier)

from signai import monitor

m = monitor.attach(model, num_classes=10)
m.calibrate(clean_loader, device="cuda", phase="inference", calib_batches=200)
m.save("./integrity.json")

Load and score:

m = monitor.load(model, artifact="./integrity.json", device="cuda")

for x, y in test_loader:
    result = m.score_inference(x, y)
    if result.flagged:
        route_to_fallback(x)

LLM / large model quick start

For models above 200M parameters or HuggingFace generative models, use LLMExtractor and IntegrityMonitor directly:

from signai import IntegrityMonitor, LLMExtractor

extractor = LLMExtractor(llm)
m = IntegrityMonitor(llm, num_classes=None, extractor=extractor, detector_kind="v1")
m.calibrate_inference(clean_loader, calib_batches=200, device="cuda")
m.export_json("./integrity_llm.json")

Score LLM inference:

m = IntegrityMonitor(llm, num_classes=None, extractor=LLMExtractor(llm), detector_kind="v1")
m.import_json("./integrity_llm.json")

for batch in eval_loader:
    result = m.score_input(batch["input_ids"], None, device="cuda")

Remote mode

Start the server:

signai-server serve --host 0.0.0.0 --port 8000 --storage ./artifacts

Connect the SDK:

from signai import monitor

m = monitor.attach(
    model,
    num_classes=10,
    endpoint="http://localhost:8000",
    api_key="",
    monitor_id="demo-model",
    device="cuda",
)
m.calibrate(clean_loader, device="cuda", phase="inference", calib_batches=200)
m.save("./integrity.json")

Detector Kinds

signAI ships three detector algorithms. Choose by setting detector_kind:

Kind Algorithm Best for
"v1" Conditional Mahalanobis (sklearn) general purpose; fast; no GPU required
"nn" Neural conditional monitor complex activation geometry; higher accuracy
"assoc" Blockwise association neural monitor high-dimensional behavioral spaces

Use v1 as the default. Use nn or assoc when you need finer discrimination on complex models.

from signai import IntegrityMonitor, ClassificationExtractor

# Neural detector
m = IntegrityMonitor(
    model,
    num_classes=10,
    extractor=ClassificationExtractor(model),
    detector_kind="nn",
)

Extractor Kinds

signAI uses an extractor plugin system to support different model types. The right extractor is auto-selected when you use monitor.attach():

Extractor Auto-selected when Description
ClassificationExtractor ≤200M params, classification CNN/ViT classifier; tracks gradient geometry and activation depth
LLMExtractor >200M params or HF generative Per-module L2 norm delta tracking; constant memory

To override auto-selection:

from signai import IntegrityMonitor, LLMExtractor

# Force LLMExtractor on a model below the size threshold
m = IntegrityMonitor(model, extractor=LLMExtractor(model), detector_kind="v1")

To implement a custom extractor for a novel architecture:

from signai import SignatureExtractorBase
import numpy as np

class MyExtractor(SignatureExtractorBase):
    def prepare(self, example_batch): ...
    def reset_state(self): ...
    def extract_training(self, logits, loss) -> tuple[np.ndarray, np.ndarray]: ...
    def extract_inference(self, x, y, device="cpu", use_sensitivity=True) -> tuple[np.ndarray, np.ndarray]: ...

Deployment Modes

1. Local artifact

m = monitor.load(model, artifact="./integrity.json")

2. Daemon (localhost:7731)

The SDK auto-discovers a running signai-server on localhost:7731. No endpoint config needed:

m = monitor.attach(model, num_classes=10)  # connects to daemon if running

3. Self-hosted

m = monitor.load(
    model,
    endpoint="http://signai.internal:8000",
    api_key="...",
    monitor_id="my-model",
)

4. Air-gapped

m = monitor.load(
    model,
    endpoint="http://10.0.1.5:8000",
    api_key="...",
    monitor_id="my-model",
)

Training Loop Integration

First calibrate for the training phase — optimizer and criterion are required:

from signai import monitor
import torch

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
criterion = torch.nn.CrossEntropyLoss()

m = monitor.attach(model, num_classes=10)
m.calibrate(
    train_loader,
    device="cpu",
    phase="training",
    optimizer=optimizer,
    criterion=criterion,
)
m.save("./integrity_train.json")

Then score each training step after optimizer.step():

m = monitor.load(model, artifact="./integrity_train.json", device="cpu")

for x, y in train_loader:
    optimizer.zero_grad()
    logits = model(x)
    loss = criterion(logits, y)
    loss.backward()
    optimizer.step()

    result = m.score_training(logits, loss)
    if result.flagged:
        quarantine_update(result)

Inference Loop Integration

from signai import monitor

m = monitor.load(model, artifact="./integrity.json", device="cuda")

for x, y in test_loader:
    result = m.score_inference(x, y)
    if result.flagged:
        route_to_fallback(x)

Public API

Top-level exports from signai:

Symbol Description
monitor.attach(model, num_classes, ...) Create a new monitor
monitor.load(model, artifact, ...) Load from artifact or remote
Monitor Monitor class with calibrate, save, score_inference, score_training
MonitorResult Score result dataclass
IntegrityMonitor Advanced: unified monitor with extractor + detector_kind params
SignatureExtractorBase Advanced: ABC for custom extractor plugins
ClassificationExtractor Classifier extractor (CNN, ViT, HF classification)
LLMExtractor LLM extractor (generative transformers, >200M param models)

Run The Server

CLI

signai-server serve \
  --host 0.0.0.0 \
  --port 8000 \
  --storage ./artifacts \
  --store-backend file

Shortcut through the main CLI:

signai serve --host 0.0.0.0 --port 8000 --storage ./artifacts

Docker

docker build -t signai .
docker run -p 8000:8000 -v %cd%\artifacts:/data signai

docker-compose

docker compose up --build

Licensing

All usage requires a license key. A bundled trial key is active on fresh installs — no purchase needed to get started.

signai apply-key sk_...    # activate or renew a key
signai status              # show seat, plan, features, expiry, usage

Visit https://umarjanjua.github.io/signai/ to purchase or renew.

API Summary

Server endpoints:

  • GET /health
  • POST /v1/artifacts
  • GET /v1/artifacts/{monitor_id}
  • DELETE /v1/artifacts/{monitor_id}
  • POST /v1/score/inference
  • POST /v1/score/training
  • POST /v1/score/batch
  • POST /v1/calibrate/start
  • POST /v1/calibrate/push
  • POST /v1/calibrate/commit
  • GET /v1/history/{monitor_id}
  • POST /v1/notify/configure
  • GET /v1/audit/export
  • GET /v1/status
  • GET /v1/monitors
  • POST /v1/license

Model Support

Framework Status
PyTorch (CNN, ViT, ResNet, etc.) ✅ Supported
HuggingFace Transformers (BERT, GPT, LLaMA, etc.) ✅ Supported
Custom PyTorch architectures via extractor plugin ✅ Supported
TensorFlow / Keras Planned
JAX / Flax Planned
ONNX Planned
XGBoost / LightGBM / CatBoost Planned
PyG / DGL (graph neural networks) Planned

Privacy Model

signAI is built so that privacy is enforced structurally:

  • feature extraction runs on the customer machine
  • remote scoring receives only s and z float vectors (compact; typically <100 bytes per score call)
  • the server discards raw vectors after scoring
  • only {ts, score, flagged, phase} is stored in history
  • model weights, raw inputs, and gradients never leave the customer machine

Documentation

Development

Run the targeted test suite:

python -m pytest tests\test_imports.py tests\test_local_backend.py tests\test_monitor.py tests\test_server.py

Run the end-to-end and security test suite (isolated — does not touch ~/.signai):

python scripts\test_e2e.py

Licensing System

signAI uses Ed25519 asymmetric key signing. Keys are offline-verifiable — no network call on validation.

Key format: sk_<base64url(json_payload)>.<base64url(ed25519_sig)>

Payload fields: seat_id, email, plan, features[], model_limit, history_days, issued_at, expires_at

Enforcement: two checkpoints — signai/licensing.py (SDK client) and signai_server/usage.py (daemon). Both embed the public key as a hardcoded constant; the SIGNAI_PUBLIC_KEY_B64 env var is intentionally ignored (P0 bypass fix).

Clock integrity: both checkpoints carry a monotonic date ratchet (last_checked / last_validated). The effective date is max(today, last_recorded) — setting the system clock backwards has no effect on trial or key expiry.

Trial: 3 days from first install, tracked in ~/.signai/install.json.

Key Generation

Keys are generated via GitHub Actions only — the private key never leaves the keygen environment:

Actions → Generate License Key → Run workflow

For local testing with an ephemeral keypair:

python scripts\keygen.py genkeypair
python scripts\keygen.py generate --seat alice@acme.com --email alice@acme.com --plan individual --duration-days 30
python scripts\keygen.py verify sk_...

SIGNAI_PRIVATE_KEY_B64 must be set for generate. Never commit it.

Fulfillment

Automated: fulfill-orders.yml polls Stripe every 5 minutes, generates keys, and emails customers.

Manual fallback: see FULFILLMENT.md.

Stripe setup (one-time):

set STRIPE_SECRET_KEY=sk_live_...
python scripts\setup_stripe.py --update-index

GitHub Secrets required in the keygen environment: STRIPE_SECRET_KEY, SIGNAI_PRIVATE_KEY_B64, SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, NOTIFY_EMAIL. Add the STRIPE_PAYMENT_LINK_IDS environment variable printed by the setup script.

Release

Wheels are built via Cython + cibuildwheel on GitHub Actions — Python source is compiled into .so/.pyd binaries before publishing to PyPI. No source code ships in the wheel.

Tag a release: git tag v0.x.y && git push origin v0.x.y

The publish.yml workflow handles PyPI upload and Docker push to GHCR automatically.

License

Commercial license required. The private key and source code are confidential — do not share outside the team.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

signai_sdk-0.4.14-cp313-cp313-win_amd64.whl (5.5 MB view details)

Uploaded CPython 3.13Windows x86-64

signai_sdk-0.4.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

signai_sdk-0.4.14-cp313-cp313-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

signai_sdk-0.4.14-cp313-cp313-macosx_10_13_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

signai_sdk-0.4.14-cp312-cp312-win_amd64.whl (5.5 MB view details)

Uploaded CPython 3.12Windows x86-64

signai_sdk-0.4.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

signai_sdk-0.4.14-cp312-cp312-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

signai_sdk-0.4.14-cp312-cp312-macosx_10_13_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

signai_sdk-0.4.14-cp311-cp311-win_amd64.whl (5.5 MB view details)

Uploaded CPython 3.11Windows x86-64

signai_sdk-0.4.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

signai_sdk-0.4.14-cp311-cp311-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

signai_sdk-0.4.14-cp311-cp311-macosx_10_9_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

signai_sdk-0.4.14-cp310-cp310-win_amd64.whl (5.5 MB view details)

Uploaded CPython 3.10Windows x86-64

signai_sdk-0.4.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (14.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

signai_sdk-0.4.14-cp310-cp310-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

signai_sdk-0.4.14-cp310-cp310-macosx_10_9_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

File details

Details for the file signai_sdk-0.4.14-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 1bd0b26d76de38d4d5b5b97edbe84e6ace4988061989953e4a876dd6dae3294d
MD5 0e1dc7afab276dd017bab08cfddd066b
BLAKE2b-256 08ce28fdeaf7ff974cb03d25e3c8c0b1ceac3a0e39e899ff69c5d61c2d755e21

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bbf9918df26531063e90641eeed65075cfc2b193af1ff3a7e4ceeed935de7397
MD5 23328eee0dfb0a6011776012a37cabc1
BLAKE2b-256 1b2840ba9886bf34a3cda698b975ba086b9385330445ae266ed7f38e328209f1

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3963033a1ba12d171f9e70cdd87f13de08066e01b866ab7c059f76d41f880b0e
MD5 ceebd7fcb3b6d751d6af97e32cce2c32
BLAKE2b-256 5b4460e519b1a74f14da110d56f8b1c7817bc3b4e25f419bc93f1d3982023ade

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 30576a1bd3084b5f185b921de7f05eab2175a8b005387a0b7c1d2ddef5d02d56
MD5 0b8ce642946669c08f27e5bb569644b0
BLAKE2b-256 8c1da86e29d443e250519692deca4116b1c696c8da6afc92ec0d82cedeb6c080

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 6306b61dbf6e64e8bef9ebfd0600c1bd0c08fe76ba5d93164ffa7f692ce9ccbe
MD5 badbec7330dd03e11daae4c1ebd17437
BLAKE2b-256 425d220dcf58082581a5560032b0db47e59e93e16bde5ba11170e511f752e0d7

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4aab0463469c0a63a73f40f708c41aa75518645e704ada7bc69015e49798d601
MD5 1121c5181957db098ca531ce83546ae9
BLAKE2b-256 b4cb10fd64977b910ce2ca720387b2272bf8de9b7f82171a3c1c36f8cf10a3c8

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5348b6421baaa30300e759022e740e0c01f3614f97af0ccf34b2b9daf1928de0
MD5 ed790557f5061177607237d7c718bc72
BLAKE2b-256 bd090e47604f47b40fb72e8aab44311fd32593b67faf8f7a612f5bf39b39e9b9

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 c11fe22d6049f1b47117cd656fa85d6676573bd6f38868bd2c6d69ffc35218da
MD5 cd8d004c15816df7547188b362de1674
BLAKE2b-256 1738b18cd0f5c433abbd28c236d6406297d877222acf753f24fcb0967d68b7e7

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 65ca1323b7a393ae70ef325a9e823903d9fcad83b05ee05c9528e4d335e16b7e
MD5 0423dcbcae834b8fcabe7fa41a57d502
BLAKE2b-256 f082483ae95c4c4e37b84d6e44413060a6d5076d571b1bce971ddd9e6c1f20bf

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 18d839bc0a21887d5ffd151fafcaf526c121e9e6f99b56f119e80d367779b609
MD5 ac8f8b9ea22b9791a0e3df4eea962e7e
BLAKE2b-256 4f8ce06fa4c1473490277436b3a82906907102504d73fc23cf0d92e3704d8f3f

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e49c191ed732880e784548632db9fcda1403071a4ad568d5199f76a4cc416c08
MD5 ce70a081aae36066bfc327446d4ede73
BLAKE2b-256 da4ec455d6dbd297b290345326a6f1d3d5db120887501b34ef37a977d410d8f3

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 2a07fb4293cd7d8ec060535bc7453e048cef8c950fce312cba6917209c686e36
MD5 cd7262ee5b06dc47f2977427fc82eed2
BLAKE2b-256 225bfcf8c13d81e1caa6f86573907a8483aa7d993ef613810e0f4ff8aeb55c10

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 5283f4ed006ca35333311d67abe5a5fa3dd78e490d606f045ac766420801256d
MD5 7922c4ea12ab285672e9c42b6c86052a
BLAKE2b-256 558e48a5b6f7c9f558ab4288005952fc6b564613f0290116d98218a1df929c72

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d41511e80d9d670aefc8f3ca79c997ef1887e67bba79de5a6c12d49416638951
MD5 19d820c938fa7605231adbd03faf87c9
BLAKE2b-256 d85431a1c663d61a73de87c2f9d27fb3aabf91a6a9f57d5e504e33bdc1e563b6

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 29157b3c1d6b2eedceefd050b15156626b7cd89d4a49f6b809ca3abd75b861ee
MD5 b88500ea17394b8c3127fed1ed0a656c
BLAKE2b-256 2ab2a589eef9ff33576b4a38646c3aa7027327b103da76d554e6a3822a74d9a2

See more details on using hashes here.

File details

Details for the file signai_sdk-0.4.14-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for signai_sdk-0.4.14-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 69239f36fbd73165577028cdafd6bffb2fbe142b05758f2497e081dc6d039b73
MD5 a6f47ce33002989df636a51b6028c327
BLAKE2b-256 3bdb67b4bfb877c8f92720d53730dedab2b303157be2458656017bc3f102fb45

See more details on using hashes here.

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