Bibliothèque Python
pip install spavik # avec pandas : pip install "spavik[pandas]"from spavik import Spavik
spavik = Spavik() # lit SPAVIK_API_KEY
model = spavik.train("churn.csv", target="churn") # gratuit
print(model.predict({"plan": "pro", "seats": 12}))Deux choses à savoir avant le premier appel : votre clé, et le nom de la colonne à prédire. Le reste, la bibliothèque s'en occupe.
Les opérations
Celles qui portent un identifiant de modèle vivent sur l'objet Model, pour que personne n'ait à recopier un mdl_... à la main.
| Appel | Coût |
|---|---|
spavik.validate(data, target=...) | gratuit |
spavik.train(data, target=...) | gratuit |
spavik.backtest(data, target=..., horizon=...) | gratuit |
spavik.forecast(data, target=..., horizon=...) | horizon x séries |
spavik.models() | gratuit |
spavik.usage() | gratuit |
model.predict(rows) | les crédits du moteur par ligne, 1 sur le moteur par défaut |
model.submit_outcomes(outcomes) | gratuit |
model.performance(days=30) | gratuit |
model.refresh() | gratuit |
model.predictions(limit=50) | gratuit |
model.archive(), spavik.archive(model_id) | gratuit |
spavik.restore(model_id) | gratuit |
models() est un itérateur : la pagination se fait toute seule. Un modèle connaît son engine, sa target et ses features, les colonnes que predict attend.
Vérifier avant d'entraîner, ou avant de payer
validate() rend ce que l'entraînement dirait d'une table, plus un essai du moteur qui ne conserve rien : un verdict et la première chose à corriger. backtest() fait de même pour une série, en rejouant son historique face à la simple répétition de la dernière période, sans rendre de prévision. Les deux sont gratuits.
rapport = spavik.validate("churn.csv", target="churn")
rapport["trial"]["verdict"] # {'level': 'usable', 'message': 'Accuracy of 0.83, against 0.50 for the majority class.'}
rapport["hint"] # la première chose à corriger, ou None
essai = spavik.backtest("ventes.csv", target="ventes", horizon=7)
essai["backtest"]["verdict"] # {'level': 'no_signal', 'message': '...'}
essai["backtest"]["by_window"] # une note par période rejouéeweak sur une validation veut dire que la note est trop belle : une colonne est probablement remplie après l'événement que vous prédisez. Retirez-la plutôt que d'entraîner.
Archiver et restaurer
Les plans limitent le nombre de modèles actifs. archive() arrête un modèle et libère sa place ; tout est conservé, et spavik.restore(model_id) le remet en service. La restauration prend l'identifiant, pas le modèle : un modèle archivé ne se lit pas avec model(), l'API répond MODEL_ARCHIVED.
model.archive()
for m in spavik.models(status="archived"):
print(m.id, m.name)
spavik.restore(model.id)La suppression définitive n'est pas dans la bibliothèque.
Vos données, telles qu'elles sont
Vous n'avez rien à convertir. train, predict et forecast acceptent indifféremment :
spavik.train(df, target="churn") # un DataFrame pandas
spavik.train("data/churn.csv", target="churn") # un chemin de fichier
spavik.train([{"plan": "pro", "churn": 0}], ...) # une liste de dictionnairesCSV ou JSON, séparé par des virgules ou des points-virgules, avec ou sans guillemets : la bibliothèque s'adapte, et rend aux nombres leur type au passage.
Ce qui est refusé avant d'être envoyé
La bibliothèque a vos données sous la main, l'API pas encore. Quatre refus sont donc prononcés sur votre machine, sans appel réseau et sans rien dépenser.
spavik.train(huit_lignes, target="churn")
# SpavikDataError: training needs at least 10 rows, 8 provided. Nothing was sent.
spavik.train(df, target="churn_90d")
# SpavikDataError: the target column 'churn_90d' is missing from the data.
# Columns found: plan, seats, tickets_90d, churn. Did you mean 'churn'?
spavik.forecast(trois_points, target="ventes", horizon=14)
# SpavikDataError: the series has 3 point(s) for a horizon of 14. A series shorter
# than its horizon yields nothing usable: provide at least 14 points,
# preferably several times more.
model.submit_outcomes([{"request_id": "...", "outcome": 1}])
# SpavikDataError: 1 outcome(s) out of 1 have no 'actual' field, the value actually
# observed. Fields found on the first: request_id, outcome.Les messages sont en anglais, la langue de l'API, et identiques mot pour mot dans la bibliothèque JavaScript : une suite de conformité rejoue le même scénario sur les deux, et sur le serveur MCP.
Les erreurs
Une classe par famille, portant chacune le code machine, le détail renvoyé par l'API, le statut HTTP et le request_id. C'est ce dernier qu'il faut citer si vous ouvrez un ticket.
from spavik import SpavikCreditsExhausted
try:
model.predict(rows)
except SpavikCreditsExhausted as exc:
print(exc.code, exc.balance, exc.request_id)| Classe | Dans quel cas |
|---|---|
SpavikDataError | refus prononcé en local, rien n'a été envoyé |
SpavikAuthError | clé absente, invalide, ou insuffisante pour la route |
SpavikCreditsExhausted | solde trop bas, porte balance et required |
SpavikValidationError | l'API refuse la requête telle qu'elle est formée |
SpavikNotFound | la ressource n'existe pas dans ce workspace |
SpavikConflict | rejeu, traitement déjà en cours, rien à intégrer |
SpavikRateLimited | trop d'appels sur une courte période |
SpavikUnavailable | une dépendance manque ou sort de veille |
SpavikTransportError | panne réseau, ou réponse qui n'est pas du JSON |
Des états normaux, pas des erreurs
model.refresh() renvoie None lorsqu'il n'y a rien à intégrer, et model.performance() renvoie None lorsque le journal analytique n'est pas en place. Ni l'un ni l'autre ne vous oblige à écrire un bloc try.
En asynchrone
Mêmes noms, mêmes refus, mêmes résultats.
from spavik import AsyncSpavik
async with AsyncSpavik() as spavik:
model = await spavik.train("churn.csv", target="churn")
print(await model.predict(rows))Les tentatives suivantes
Uniquement sur les erreurs qui peuvent changer d'avis : 429, 5xx et pannes réseau. Jamais sur une 4xx. La clé d'idempotence est rejouée à l'identique, donc une nouvelle tentative ne facture pas une seconde fois.
Spavik(max_retries=1) # aucune nouvelle tentative
Spavik(backoff=lambda n: n * 1.0) # attente linéaireWebhooks
from spavik.webhooks import verifier
evenement = verifier(request.body, request.headers, secret)Passez les octets reçus tels quels : un corps analysé puis réécrit ne produit plus la même signature.
Comprendre ce qui se passe
SPAVIK_LOG=debug python mon_script.py
spavik POST /v1/models idem=a3f1b2c4 15.81s 201 req_atZusk... cle=sk-spv-api-bm7...Tr9xLa clé est masquée dans la trace.
Délais d'attente par défaut
| Opération | Délai |
|---|---|
train, refresh | 120 s |
forecast | 60 s |
backtest | 60 s |
validate | 120 s |
predict, submit_outcomes, performance | 30 s |
models, usage, predictions | 15 s |
Ces délais sont larges à dessein : un entraînement demande une quinzaine de secondes, et le moteur met une dizaine de secondes à répondre lorsqu'il sort de veille.