Integration Guide
This guide demonstrates how to integrate the Fairness Pipeline Development Toolkit into various ML workflows, CI/CD pipelines, and production systems.
Table of Contents
Installation & Setup
Basic Installation
pip install fairpipe
With Optional Dependencies
For specific use cases, install additional features:
# For fairness-aware training
pip install fairpipe[training]
# For production monitoring
pip install fairpipe[monitoring]
# For external metric backends
pip install fairpipe[adapters]
# All features
pip install fairpipe[training,monitoring,adapters]
# For the REST API server
pip install fairpipe[api]
Verify Installation
import fairpipe
print(fairpipe.__version__) # Should match installed fairpipe (e.g. "0.8.0")
# Test CLI
import subprocess
subprocess.run(["fairpipe", "version"], check=True)
Integration Patterns
Standalone Fairness Validation
Use this pattern when you want to validate fairness of existing model predictions without modifying your training pipeline.
Use Case: Post-Training Validation
from fairpipe.io import load_data
from fairpipe.metrics import FairnessAnalyzer
# Load predictions — CSV or Parquet, auto-detected
df = load_data("predictions.csv") # or "predictions.parquet"
# Pass Series directly — no .to_numpy() needed
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df["y_pred"],
sensitive=df["gender"],
with_ci=True,
ci_level=0.95
)
# Check if fairness threshold is met
threshold = 0.05
if result.value <= threshold:
print(f"✅ Fairness check passed: DPD = {result.value:.4f}")
else:
print(f"❌ Fairness check failed: DPD = {result.value:.4f} (threshold: {threshold})")
print(f"95% CI: [{result.ci[0]:.4f}, {result.ci[1]:.4f}]")
Use Case: Batch Validation Script
#!/usr/bin/env python3
"""Validate fairness for multiple models."""
import sys
from fairpipe.io import load_data
from fairpipe.metrics import FairnessAnalyzer
def validate_model(predictions_path: str, threshold: float = 0.05) -> bool:
"""Validate fairness for a single model. Accepts .csv or .parquet paths."""
df = load_data(predictions_path)
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df["y_pred"],
sensitive=df["gender"],
with_ci=True,
)
passed = result.value <= threshold
print(f"Model: {predictions_path}")
print(f"DPD: {result.value:.4f} (threshold: {threshold})")
print(f"Status: {'✅ PASS' if passed else '❌ FAIL'}")
print()
return passed
if __name__ == "__main__":
predictions_files = sys.argv[1:]
all_passed = all(validate_model(f) for f in predictions_files)
sys.exit(0 if all_passed else 1)
Embedding in ML Pipelines
Use this pattern when you want to integrate fairness directly into your training and inference pipelines.
Use Case: scikit-learn Pipeline Integration
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from fairpipe.pipeline import InstanceReweighting
from fairpipe.training import ReductionsWrapper
# Option 1: Add fairness transformer to preprocessing
preprocessing_pipeline = Pipeline([
('scaler', StandardScaler()),
('reweigh', InstanceReweighting(sensitive="gender")),
])
# Option 2: Use fairness-aware training wrapper
fair_model = ReductionsWrapper(
LogisticRegression(),
constraint="demographic_parity",
eps=0.01
)
# Full pipeline
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
A_train = X_train["gender"] # Sensitive attribute
# Preprocess
X_train_transformed = preprocessing_pipeline.fit_transform(X_train)
X_test_transformed = preprocessing_pipeline.transform(X_test)
# Train with fairness constraints
fair_model.fit(X_train_transformed, y_train, sensitive_features=A_train)
# Predict
y_pred = fair_model.predict(X_test_transformed)
# Validate
from fairpipe.metrics import FairnessAnalyzer
analyzer = FairnessAnalyzer()
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=X_test["gender"].to_numpy()
)
print(f"Final DPD: {result.value:.4f}")
Use Case: PyTorch Training Integration
import torch
import torch.nn as nn
from fairpipe.training import (
FairnessRegularizerLoss,
LagrangianFairnessTrainer
)
# Define model
class MyModel(nn.Module):
def __init__(self, input_dim):
super().__init__()
self.fc = nn.Linear(input_dim, 1)
def forward(self, x):
return torch.sigmoid(self.fc(x))
model = MyModel(input_dim=10)
# Option 1: Use fairness regularizer in loss
criterion = FairnessRegularizerLoss(
base_loss=nn.BCELoss(),
eta=0.5,
sensitive_attribute=sensitive_train
)
# Training loop
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
optimizer.zero_grad()
predictions = model(X_train)
loss = criterion(predictions, y_train)
loss.backward()
optimizer.step()
# Option 2: Use Lagrangian trainer
trainer = LagrangianFairnessTrainer(
model=model,
fairness="demographic_parity",
dp_tol=0.02
)
trainer.train(X_train, y_train, sensitive_train)
Use Case: Custom Training Loop
from fairpipe.metrics import FairnessAnalyzer
from fairpipe.pipeline import build_pipeline, apply_pipeline, load_config
# Load configuration
config = load_config("pipeline.config.yml")
# Build and apply preprocessing pipeline
pipeline = build_pipeline(config)
X_transformed, metadata = apply_pipeline(pipeline, X)
# Train your model (any framework)
model = train_model(X_transformed, y)
# Validate fairness
analyzer = FairnessAnalyzer()
y_pred = model.predict(X_test_transformed)
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=X_test["gender"].to_numpy(),
with_ci=True
)
# Log results
print(f"Fairness metric: {result.value:.4f}")
print(f"95% CI: {result.ci}")
CI/CD Integration
Use this pattern to gate deployments based on fairness metrics.
Use Case: GitHub Actions
# .github/workflows/fairness-check.yml
name: Fairness Validation
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
fairness-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install toolkit
run: pip install fairpipe
- name: Run fairness validation
run: |
fairpipe validate \
--csv test_predictions.csv \
--y-true y_true \
--y-pred y_pred \
--sensitive gender \
--min-group-size 30 \
--with-ci \
--out artifacts/fairness_report.md
- name: Check fairness threshold
run: |
python -c "
import pandas as pd
from fairpipe.metrics import FairnessAnalyzer
df = pd.read_csv('test_predictions.csv')
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df['y_pred'].to_numpy(),
sensitive=df['gender'].to_numpy()
)
threshold = 0.05
if result.value > threshold:
print(f'❌ Fairness check failed: DPD = {result.value:.4f} > {threshold}')
exit(1)
else:
print(f'✅ Fairness check passed: DPD = {result.value:.4f}')
"
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: fairness-report
path: artifacts/fairness_report.md
Use Case: Performance Benchmarking in CI/CD
Add performance regression testing to your CI/CD pipeline:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
performance-benchmarks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -e .[dev]
- name: Run performance benchmarks
run: |
echo "Running performance benchmarks..."
python benchmarks/benchmark_metrics_100k.py > benchmark_metrics.txt 2>&1
python benchmarks/benchmark_pipeline.py > benchmark_pipeline.txt 2>&1
python benchmarks/benchmark_bootstrap.py > benchmark_bootstrap.txt 2>&1
- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: benchmark-results
path: |
benchmark_*.txt
- name: Check for performance regressions
run: |
# Extract timing information and compare against baselines
# Fail if performance degrades significantly (>20%)
python -c "
import re
import sys
# Example: Check if metrics benchmark exceeds threshold
with open('benchmark_metrics.txt') as f:
content = f.read()
# Add your performance regression checks here
print('Performance benchmarks completed')
"
Use Case: Automated Release Workflow
Automate releases with GitHub Actions:
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*.*.*' # Trigger on version tags
jobs:
build-and-publish:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write # For PyPI trusted publishing
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install build dependencies
run: |
pip install build twine
- name: Extract version from tag
id: version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build distribution packages
run: python -m build
- name: Check package
run: twine check dist/*
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: twine upload dist/*
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ steps.version.outputs.version }}
release_name: Release v${{ steps.version.outputs.version }}
body: |
Release v${{ steps.version.outputs.version }}
See CHANGELOG.md for details.
draft: false
prerelease: false
Use Case: pytest Integration
# tests/test_fairness.py
import pytest
import pandas as pd
from fairpipe.metrics import FairnessAnalyzer
from fairpipe.integration import assert_fairness
def test_model_fairness():
"""Test that model predictions meet fairness threshold."""
# Load test data
df = pd.read_csv("test_predictions.csv")
# Compute fairness metric
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df["y_pred"].to_numpy(),
sensitive=df["gender"].to_numpy(),
with_ci=True
)
# Assert fairness threshold
assert_fairness(
value=result.value,
threshold=0.05,
context="Demographic parity difference"
)
# Additional checks
assert result.ci is not None, "Confidence interval should be computed"
assert result.ci[1] < 0.10, "Upper CI should be below 10%"
@pytest.mark.parametrize("sensitive_attr", ["gender", "race"])
def test_multiple_attributes(sensitive_attr):
"""Test fairness across multiple sensitive attributes."""
df = pd.read_csv("test_predictions.csv")
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df["y_pred"].to_numpy(),
sensitive=df[sensitive_attr].to_numpy(),
with_ci=True
)
assert_fairness(result.value, threshold=0.05, context=sensitive_attr)
Run tests:
pytest tests/test_fairness.py -v
Use Case: Pre-commit Hook
# .pre-commit-hooks/fairness-check.py
#!/usr/bin/env python3
"""Pre-commit hook to check fairness of model predictions."""
import sys
import pandas as pd
from fairpipe.metrics import FairnessAnalyzer
def main():
predictions_path = "predictions.csv"
try:
df = pd.read_csv(predictions_path)
except FileNotFoundError:
print(f"⚠️ {predictions_path} not found, skipping fairness check")
return 0
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=df["y_pred"].to_numpy(),
sensitive=df["gender"].to_numpy()
)
threshold = 0.05
if result.value > threshold:
print(f"❌ Fairness check failed: DPD = {result.value:.4f} > {threshold}")
return 1
print(f"✅ Fairness check passed: DPD = {result.value:.4f}")
return 0
if __name__ == "__main__":
sys.exit(main())
Production Monitoring
Use this pattern to monitor fairness metrics in production systems.
Use Case: Real-Time Tracking
from fairpipe.monitoring import (
RealTimeFairnessTracker,
TrackerConfig,
ColumnMap
)
import pandas as pd
# Initialize tracker
tracker = RealTimeFairnessTracker(
TrackerConfig(
window_size=10_000,
min_group_size=30
),
artifacts_dir="artifacts/monitoring"
)
# Define column mapping
column_map = ColumnMap(
y_true="y_true",
y_pred="y_pred",
sensitive="gender"
)
# Process batches of predictions
def process_predictions_batch(batch_df: pd.DataFrame):
"""Process a batch of predictions and update fairness metrics."""
tracker.process_batch(batch_df, column_map)
# Get current metrics
metrics = tracker.get_current_metrics()
print(f"Current DPD: {metrics.get('demographic_parity_difference', 'N/A')}")
# In your inference service
while True:
batch = get_next_batch() # Your function to get predictions
process_predictions_batch(batch)
Use Case: Drift Detection
from fairpipe.monitoring import (
FairnessDriftAndAlertEngine,
DriftConfig
)
# Initialize drift detector
engine = FairnessDriftAndAlertEngine(
DriftConfig(
ks_threshold=0.05,
alert_on_drift=True
)
)
# Set reference metrics (from training/validation)
reference_metrics = {
"demographic_parity_difference": 0.03,
"equalized_odds_difference": 0.02
}
# Check for drift periodically
def check_drift(current_metrics: dict):
"""Check if current metrics have drifted from reference."""
alerts = engine.check_drift(reference_metrics, current_metrics)
if alerts:
for alert in alerts:
print(f"⚠️ Alert: {alert.message}")
# Send to alerting system (e.g., PagerDuty, Slack)
send_alert(alert)
return alerts
# In monitoring loop
current_metrics = compute_current_metrics() # Your function
alerts = check_drift(current_metrics)
Use Case: Dashboard Integration
from fairpipe.monitoring import (
FairnessReportingDashboard,
ReportConfig
)
# Initialize dashboard
dashboard = FairnessReportingDashboard(
ReportConfig(
metrics_dir="artifacts/monitoring",
update_interval=3600 # Update every hour
)
)
# Generate report
dashboard.generate_report(output_path="artifacts/fairness_dashboard.html")
# Or serve as web app (if using Streamlit/Dash)
# See apps/monitoring_streamlit_app.py for example
MLflow Integration
Use this pattern to log fairness metrics alongside model metrics in MLflow.
Use Case: Logging Workflow Results
from fairpipe.integration import (
execute_workflow,
log_workflow_results
)
from fairpipe.pipeline import load_config
import pandas as pd
# Load configuration and data
config = load_config("config.yml")
df = pd.read_csv("data.csv")
# Execute workflow
result = execute_workflow(
config=config,
df=df,
output_dir="artifacts/workflow",
min_group_size=30,
mlflow_experiment="fairness_workflow",
mlflow_run_name="run_001"
)
# Log results to MLflow (if not already logged)
log_workflow_results(
result=result,
experiment_name="fairness_workflow",
run_name="run_001"
)
Use Case: Custom MLflow Logging
import mlflow
from fairpipe.metrics import FairnessAnalyzer
from fairpipe.integration import log_fairness_metrics
# Start MLflow run
mlflow.start_run(run_name="fairness_evaluation")
# Compute fairness metrics
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=gender,
with_ci=True
)
# Log to MLflow
log_fairness_metrics(
metrics={
"demographic_parity_difference": result.value,
"dpd_ci_lower": result.ci[0],
"dpd_ci_upper": result.ci[1],
},
experiment_name="fairness_workflow"
)
mlflow.end_run()
Configuration Management
Configuration File Discovery
The toolkit supports automatic configuration file discovery:
from fairpipe.pipeline.config import find_config_file, load_config
# Find config file (checks environment variables and default locations)
config_path = find_config_file("config.yml")
if config_path:
config = load_config(config_path)
else:
# Use default or raise error
raise FileNotFoundError("Configuration file not found")
Environment-Based Configuration
import os
from fairpipe.pipeline.config import load_config
# Set configuration path via environment variable
os.environ["FAIRPIPE_CONFIG_PATH"] = "production_config.yml"
config = load_config(os.environ["FAIRPIPE_CONFIG_PATH"])
Programmatic Configuration
from fairpipe.pipeline.config import PipelineConfig, PipelineStep
# Create configuration programmatically
config = PipelineConfig(
sensitive=["gender", "race"],
pipeline=[
PipelineStep(
name="reweigh",
transformer="InstanceReweighting"
),
PipelineStep(
name="repair",
transformer="DisparateImpactRemover",
params={
"features": ["score"],
"sensitive": "gender",
"repair_level": 0.8
}
)
]
)
Environment Variables
The toolkit supports configuration via environment variables:
# Configuration file path
export FAIRPIPE_CONFIG_PATH="config.yml"
# Minimum group size
export FAIRPIPE_MIN_GROUP_SIZE=30
# MLflow experiment name
export FAIRPIPE_MLFLOW_EXPERIMENT="fairness_workflow"
Access in Python:
from fairpipe.config.env import (
FAIRPIPE_CONFIG_PATH,
FAIRPIPE_MIN_GROUP_SIZE,
FAIRPIPE_MLFLOW_EXPERIMENT,
get_env_int
)
# Get environment variables
config_path = os.getenv(FAIRPIPE_CONFIG_PATH, "config.yml")
min_group_size = get_env_int(FAIRPIPE_MIN_GROUP_SIZE, default=30)
Best Practices
1. Minimum Group Size
Always set an appropriate minimum group size based on your data:
# For small datasets
analyzer = FairnessAnalyzer(min_group_size=10)
# For large datasets (recommended)
analyzer = FairnessAnalyzer(min_group_size=30)
2. Confidence Intervals
Always compute confidence intervals for production use:
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True,
ci_level=0.95,
ci_samples=1000 # More samples = more accurate CI
)
3. Multiple Sensitive Attributes
Test fairness across all relevant sensitive attributes:
sensitive_attrs = ["gender", "race", "age_group"]
for attr in sensitive_attrs:
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=df[attr].to_numpy(),
with_ci=True
)
print(f"{attr}: DPD = {result.value:.4f}")
4. Intersectional Analysis
For intersectional fairness, use multiple attributes:
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=None, # Not used when intersectional=True
intersectional=True,
attrs_df=df[["gender", "race"]],
columns=["gender", "race"],
with_ci=True
)
5. Error Handling
Always handle edge cases:
from fairpipe.exceptions import (
MetricComputationError,
ConfigValidationError
)
try:
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True
)
if result.value is None or np.isnan(result.value):
print("⚠️ Insufficient data for fairness computation")
else:
print(f"DPD: {result.value:.4f}")
except MetricComputationError as e:
print(f"Error computing metric: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
6. Logging and Monitoring
Log fairness metrics for tracking over time:
import logging
from fairpipe.metrics import FairnessAnalyzer
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
analyzer = FairnessAnalyzer(min_group_size=30)
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True
)
logger.info(
f"Fairness metric computed: DPD={result.value:.4f}, "
f"CI=[{result.ci[0]:.4f}, {result.ci[1]:.4f}]"
)
Troubleshooting
Common Issues
1. “Insufficient data” or NaN results
Problem: Metric returns NaN or None
Solutions:
Reduce
min_group_size(but be cautious with small groups)Check data quality (missing values, incorrect group labels)
Use
nan_policy="include"if you want to include NaN values
analyzer = FairnessAnalyzer(
min_group_size=10, # Lower threshold
nan_policy="include" # Include NaN values
)
2. Backend not available
Problem: RuntimeError: Requested backend 'fairlearn' is not available
Solutions:
Install optional dependencies:
pip install fairpipe[adapters]Use
backend="native"(always available)Let toolkit auto-select:
backend=None
analyzer = FairnessAnalyzer(backend="native") # Always works
3. Configuration file not found
Problem: FileNotFoundError when loading config
Solutions:
Use absolute paths
Set
FAIRPIPE_CONFIG_PATHenvironment variableUse
find_config_file()to locate config
from fairpipe.pipeline.config import find_config_file
config_path = find_config_file("config.yml")
if config_path:
config = load_config(config_path)
4. Slow bootstrap CI computation
Problem: Computing confidence intervals takes too long
Solutions:
Reduce
ci_samples(default: 1000)Use
ci_method="percentile"instead of"bca"(faster)Disable CI for quick checks:
with_ci=False
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True,
ci_samples=500, # Fewer samples = faster
ci_method="percentile" # Faster method
)
Getting Help
Documentation: See API Reference for detailed API documentation
Examples: Check
demo_*.ipynbnotebooks in the repositoryIssues: Report issues on GitHub
REST API & Docker
The api extra exposes all fairpipe functionality over HTTP, enabling integration from any language or framework. It is also useful for interactive demos via Swagger UI.
Starting the Server
pip install fairpipe[api]
# Development (single worker, auto-reload)
fairpipe serve --reload
# Production-style (multiple workers)
fairpipe serve --host 0.0.0.0 --port 8000 --workers 4
On startup:
fairpipe API v0.8.0 running on http://127.0.0.1:8000
→ Swagger UI: http://127.0.0.1:8000/docs
→ ReDoc: http://127.0.0.1:8000/redoc
Docker
A Dockerfile and docker-compose.yml are provided at the repository root.
# Build and run
docker build -t fairpipe-api .
docker run -p 8000:8000 fairpipe-api
# Or with Compose
docker compose up
Pass environment variables to configure behaviour:
docker run -p 8000:8000 \
-e FAIRPIPE_MIN_GROUP_SIZE=30 \
fairpipe-api
Calling the API
Health check:
curl http://localhost:8000/health
Validate fairness:
curl -X POST http://localhost:8000/validate \
-H "Content-Type: application/json" \
-d '{
"y_pred": [1, 0, 1, 0, 1, 0],
"sensitive": ["A", "A", "A", "B", "B", "B"],
"threshold": 0.05,
"min_group_size": 1
}'
Run pipeline (file upload):
curl -X POST http://localhost:8000/pipeline \
-F "file=@data.csv;type=text/csv" \
-F 'config=sensitive: ["sensitive"]
pipeline:
- name: reweigh
transformer: "InstanceReweighting"
params: {}'
Run full workflow (file upload):
curl -X POST http://localhost:8000/workflow \
-F "file=@data.csv;type=text/csv" \
-F "min_group_size=30" \
-F "train_size=0.8" \
-F 'config=sensitive: ["sensitive"]
pipeline:
- name: reweigh
transformer: "InstanceReweighting"
params: {}
training:
method: "reductions"
target_column: "y"
params:
constraint: "demographic_parity"
eps: 0.05
fairness_metric: "demographic_parity_difference"
validation_threshold: 0.10'
Retrieve a stored result:
curl http://localhost:8000/results/<run_id>
Python Client Example
import requests
# Validate via HTTP
resp = requests.post("http://localhost:8000/validate", json={
"y_pred": [1, 0, 1, 0, 1, 0],
"sensitive": ["A", "A", "A", "B", "B", "B"],
"threshold": 0.05,
"min_group_size": 1,
})
body = resp.json()
print(f"passed={body['passed']}, DPD={body['metrics']['demographic_parity_difference']['value']}")
# Retrieve result later
run_id = body["run_id"]
result = requests.get(f"http://localhost:8000/results/{run_id}").json()
Using the App Factory Directly
For embedding the API inside an existing FastAPI or ASGI application:
from fairpipe.api.app import create_app
app = create_app()
# Mount under a prefix
from fastapi import FastAPI
root = FastAPI()
root.mount("/fairness", app)
Next Steps
Read the API Reference for complete API and REST endpoint documentation
Explore the demo notebooks (
demo_*.ipynb) for more examplesReview the README for quick start guide
Check ARCHITECTURE.md for design decisions