aither
Python SDK for the aither platform - contextual intelligence and model observability.
Features
- Zero-code logging: Wrap any model and predictions are logged automatically
- Framework support: sklearn, pytorch, tensorflow, tinygrad, transformers
- Smart sampling: Captures sample + metadata from features (never blocks inference)
- Label correlation: Track ground truth with trace ID correlation
- Non-blocking: Background worker handles all API communication
Installation
pip install aither
Quick Start
import aither
from sklearn.ensemble import RandomForestClassifier
# Initialize
aither.init() # Uses AITHER_API_KEY env var
# Train your model
model = RandomForestClassifier().fit(X_train, y_train)
# Wrap it - predictions are now logged automatically
tracked = aither.wrap(model, name="fraud_detector")
# Use normally
predictions = tracked.predict(X_test)
# Get trace_id for label correlation
trace_id = tracked.last_trace_id
Supported Frameworks
| Framework | Example |
|---|---|
| sklearn | aither.wrap(RandomForestClassifier(), name="clf") |
| pytorch | aither.wrap(MyNet(), name="net") |
| tensorflow | aither.wrap(keras_model, name="tf_model") |
| tinygrad | aither.wrap(tinygrad_model, name="tiny") |
| transformers | aither.wrap(pipeline("sentiment"), name="sentiment") |
Also works with sklearn-compatible libraries: xgboost, lightgbm, catboost.
Configuration
Environment Variables
export AITHER_API_KEY="aith_your_api_key"
export AITHER_BASE_URL="https://aither.computer" # optional
Explicit Initialization
aither.init(
api_key="aith_your_api_key",
base_url="https://aither.computer",
flush_interval=1.0,
batch_size=100,
)
API Reference
aither.wrap(model, name, **options) - Recommended
Wrap a model for automatic prediction logging.
tracked = aither.wrap(
model, # Any ML model
name="fraud_detector", # Required: model identifier
version="1.2.3", # Optional: model version
environment="production", # Optional: deployment env
sample_rows=5, # Max rows to sample (default: 5)
sample_columns=10, # Max columns to sample (default: 10)
features_fn=custom_extractor, # Custom feature extraction
)
# Use the wrapped model normally
result = tracked.predict(X)
result = tracked(X) # Also works
probs = tracked.predict_proba(X) # Also tracked
# Access trace_id for label correlation
trace_id = tracked.last_trace_id
all_trace_ids = tracked.trace_ids # All predictions
# Access underlying model
tracked.model # Original model
tracked.classes_ # Passthrough to model attributes
aither.log_prediction(...) - Manual Control
For custom pipelines or when you need full control:
trace_id = aither.log_prediction(
model_name="my_pipeline",
features={"amount": 150.0, "country": "US"},
prediction=0.87,
version="1.2.3",
environment="production",
)
aither.log_label(trace_id, label)
Log ground truth for a prediction:
aither.log_label(trace_id=trace_id, label=1)
@aither.track(name) - Decorator
For functions instead of model objects:
@aither.track("my_function")
def predict(features):
return model.predict(features)
result = predict(X)
trace_id = aither.last_trace_id()
Feature Extraction
Wrapped models automatically extract features with smart sampling:
# Input: pandas DataFrame with 50,000 rows, 100 columns
# What gets logged:
{
"sample": [
{"col1": 1.5, "col2": "A", ...}, # 5 rows
...
],
"_meta": {
"type": "pandas.DataFrame",
"shape": [50000, 100],
"columns": ["col1", "col2", ...],
"dtypes": {"col1": "float64", ...},
"truncated": True
}
}
Supported types:
- numpy arrays
- pandas DataFrames/Series
- polars DataFrames/Series
- torch Tensors
- tensorflow Tensors
- dicts (common in transformers)
- lists
Custom extraction:
def my_extractor(X):
return {"shape": X.shape, "mean": X.mean()}
tracked = aither.wrap(model, name="m", features_fn=my_extractor)
Usage Patterns
Basic Model Wrapping
import aither
from sklearn.ensemble import RandomForestClassifier
aither.init()
model = RandomForestClassifier().fit(X_train, y_train)
tracked = aither.wrap(model, name="churn_predictor", version="1.0")
predictions = tracked.predict(X_test)
PyTorch Model
import aither
import torch
aither.init()
class MyNet(torch.nn.Module):
def forward(self, x):
return self.layers(x)
model = MyNet()
tracked = aither.wrap(model, name="my_net")
# Both work:
output = tracked(input_tensor)
output = tracked.predict(input_tensor)
Ground Truth Correlation
# At prediction time
predictions = tracked.predict(X)
trace_ids = tracked.trace_ids # List of all trace IDs
# Store trace_ids with your predictions
save_to_db(prediction_ids, trace_ids)
# Later, when ground truth is known
for pred_id, trace_id in load_from_db():
actual = get_actual_outcome(pred_id)
aither.log_label(trace_id, actual)
FastAPI Integration
import aither
from fastapi import FastAPI
aither.init()
model = aither.wrap(load_model(), name="api_model")
app = FastAPI()
@app.post("/predict")
async def predict(data: dict):
prediction = model.predict(data)
return {
"prediction": prediction,
"trace_id": model.last_trace_id
}
@app.post("/label")
async def label(trace_id: str, actual: int):
aither.log_label(trace_id, actual)
return {"status": "ok"}
@app.on_event("shutdown")
async def shutdown():
aither.close()
Management API
The SDK provides namespaces for managing your organization, API keys, and user account.
import aither
aither.init()
# Organization info
org = aither.org.get()
print(org.name, org.plan)
# Usage stats for current billing period
usage = aither.org.usage()
print(f"API calls: {usage.api_calls}")
# Current user
me = aither.user.me()
print(me.email)
# API key management (requires admin scope)
keys = aither.api_keys.list()
new_key = aither.api_keys.create(name="Production", scopes=["read", "write"])
aither.api_keys.revoke(key_id="...")
Why .get() instead of direct attributes?
You might wonder why aither.org.get().name instead of just aither.org.name. This is intentional:
-
Network calls are explicit -
.get()makes it clear you're making an HTTP request. Hidden network calls on attribute access would be surprising and expensive. -
Caching semantics are clear - The returned
Organizationis a point-in-time snapshot. You control when to refresh by calling.get()again. -
Error handling is predictable - Exceptions from HTTP failures occur at the
.get()call site, not on attribute access.
# Recommended: fetch once, use the snapshot
org = aither.org.get()
print(f"{org.name} on {org.plan} plan")
# Compare states over time
org_before = aither.org.get()
# ... make changes ...
org_after = aither.org.get()
if org_before.plan != org_after.plan:
print("Plan changed!")
Data Format
The SDK uses OTLP (OpenTelemetry Protocol) to send predictions as spans with ml.* attributes:
| Attribute | Description |
|---|---|
ml.model.name |
Model identifier |
ml.model.version |
Model version |
ml.features |
JSON-encoded feature sample + metadata |
ml.prediction |
JSON-encoded prediction |
ml.label |
Ground truth value |
ml.environment |
Deployment environment |
License
MIT
Metadata
Release files for aither 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| aither-0.2.1.tar.gz | 130.7 kB | With provenance | Details for aither-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| aither-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for aither-0.2.1-py3-none-any.whl |
Total release size: 156.2 kB
Release files / aither-0.2.1.tar.gz
| Download URL | aither-0.2.1.tar.gz |
|---|---|
| Size | 130.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d4accdc5a4296ee8ce7814a05ade3f86f81071b9dcd219e06339c1786834cd57
|
|
BLAKE2b-256 checksum How to use checksums |
dd96be8a7f5a1e75f71c9476e111106bf81cacf55c73f3e2762c8609f6ac6a9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Jan 31, 2026.
Transparency logRelease files / aither-0.2.1-py3-none-any.whl
| Download URL | aither-0.2.1-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
01a804530fd83323b9238efcf8ee682996565fe68fc8d570a4281f71d9e580dc
|
|
BLAKE2b-256 checksum How to use checksums |
9736b8119c6c40fc450e1a7ea313f4bdb0aca48a780ed4b9e3891451ec47aca2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Jan 31, 2026.
Transparency logSecurity for aither 0.2.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for aither-0.2.1.tar.gz
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 Jan 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.