Python client
The official kaimei package: install it, configure it, and read what it returns.
#Install and configure
The client is on PyPI as kaimei and depends only on httpx. Extras pull in what the optional helpers need.
| Install | Adds |
|---|---|
pip install kaimei | The client. Every endpoint, pagination, retries, typed errors, notebook cards. |
pip install "kaimei[models]" | NumPy, for extracting and uploading fitted estimators and sending arrays as inputs. |
pip install "kaimei[images]" | NumPy and Pillow, for kaimei.images: load a photo at the model's size and render heatmaps. |
pip install matplotlib | Charts in kaimei.tabular, kaimei.images and kaimei.activations. |
Kaimei(...) arguments
Defaults to KAIMEI_API_KEY.
Defaults to KAIMEI_BASE_URL, then https://api.kaimei.ai. Point it at a self-hosted API.
Per request, seconds.
Retries for 429 (honouring Retry-After) and, for GET, HEAD and OPTIONS, for 502, 503 and 504 and connection errors. A POST that reached the server is never retried, so a slow batch is never logged twice.
Extra headers on every request.
client.health() checks the API is up. client.use_token(token) swaps the bearer token, which client.auth.login does for you. The client is a context manager and closes its connection pool on exit. Set KAIMEI_DASHBOARD_URL if your dashboard is self-hosted so notebook cards link to it; KAIMEI_DISPLAY=raw turns the cards off by default.
from kaimei import Kaimei
client = Kaimei() # KAIMEI_API_KEY from the environment
client = Kaimei(api_key="km_live_...", timeout=60)
client = Kaimei(api_key="km_test_...", base_url="http://localhost:8000") # self-hosted
print(client.health()) # {'status': 'ok', 'service': 'kaimei-api', 'version': '0.1.0', 'env': 'production'}
with Kaimei() as client:
for model in client.models.iterate():
print(model.slug, model.task, model.reference_rows){
"status": "ok",
"service": "kaimei-api",
"version": "0.1.0",
"env": "production"
}#Working with results
Every call returns an APIObject: the JSON the API sent, readable as attributes (explanation.top_features) or as a mapping (explanation["top_features"]). Nested objects wrap the same way; lists stay lists. Lists from the API come back as a Page with .data, .total, .has_more and auto_paging_iter(); every resource also has iterate(**filters) that follows the pages for you.
record.to_dict()andrecord.to_json()give the plain data.record.to_frame()gives the record's main table as a pandas DataFrame: one row per feature for an explanation (rank, feature, value, attribution, share, direction), the payload's table for an insight, the features of a model, one flattened row per item for a page.kaimei.display.rows(record)is the same without pandas.- In Jupyter, JupyterLab, VS Code and Colab, a record that ends a cell renders as a Kaimei card: the dashboard's colours and numbers, attribution bars, probabilities, the counterfactual, a heatmap for image explanations, insight charts. Cards are HTML and CSS only and follow the host's dark theme.
kaimei.set_display("raw")shows JSON instead;with kaimei.display.using("raw"):does it for one block;kaimei.display.html(record)returns a card's HTML for a report of your own.
explanation = client.explanations.create(model="credit-risk-v3", input=row, method="shap")
explanation.output["label"] # 'decline'
explanation["base_value"] # 0.4904...
explanation.top_features[0]["feature"] # 'debt_to_income'
explanation.to_frame()
# rank feature value attribution share direction
# 0 1 debt_to_income 0.38 0.079706 0.2107 positive
# 1 2 num_delinquencies 1 0.074840 0.1978 positive
# ...
page = client.explanations.list(model="credit-risk-v3", limit=50)
page.total, page.has_more # (16, False)
for item in page.auto_paging_iter():
...
import kaimei
kaimei.set_display("raw") # cells show JSON instead of cards#Exceptions
All exceptions derive from kaimei.KaimeiError and carry the API's type, code, param, status_code and details.
| Exception | Raised when |
|---|---|
AuthenticationError | 401: the key or token was rejected. |
PermissionDeniedError | 403: a session is required, the role is too low, or a quota is exhausted. PermissionError is an alias. |
NotFoundError | 404: no such object in your organization. |
RateLimitError | 429, after the automatic retries ran out. |
APIStatusError | Any other non-2xx response, and analyses.wait timing out (analysis_timeout). |
APIConnectionError | No usable response: connection refused, DNS, or a timeout. The message says whether the request was retried. |
StructureError | A fitted estimator could not be turned into a structure spec (unsupported_layers, numpy_required, …). |