Welt Python SDK
From a DataFrame to a prediction. Use familiar Classifier and Regressor
estimators backed by durable predictors in your private Welt workspace.
Install welt-client, import welt. Python 3.11–3.13.
Start here · Guides · Reference · Models and limits
Install
python -m pip install "welt-client[parquet]"
Run welt login and approve your workspace in the browser. This saves a private,
origin-bound credential for later Python sessions. In a notebook, connect once:
from welt import Client
client = Client().connect()
Open its printed verification link on your own computer if Python is remote.
Python connection stays in this process; use save=True explicitly to persist it.
Constructors never open a browser. Explicit keys and WELT_API_KEY still work and
have precedence over connected/saved credentials. Connection guide.
Modelling and research downloads may consume workspace credits. Check Workspace → Billing for available credits, pending reservations and spend caps before running the examples. Usage and recovery explains accounting; payments and account changes require browser authorization.
Learn with real data
Download Iris from our research inventory, look at the table, split train/test, fit a classifier, predict unseen rows, and measure the result:
from pathlib import Path
from tempfile import mkdtemp
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
from welt import Client, Classifier
# 1. Get a real table from Welt's research inventory.
dataset_id = "asset-d839644b6de36fc5cafdda18c5daeca3"
path = Path(mkdtemp(prefix="welt-iris-")) / "iris.parquet"
client = Client()
info = client.research_dataset(dataset_id)
print("Dataset:", info["name"])
client.download_research_dataset(dataset_id, path)
data = pd.read_parquet(path)
target = "target" # The outcome column in this table.
# 2. Look at the rows before modelling.
print(data.head())
print("Rows and columns:", data.shape)
data.info()
print(data[target].value_counts())
# 3. Set aside test rows before fitting; never train on their answers.
train, test = train_test_split(
data, test_size=0.2, random_state=9, stratify=data[target])
query = test.drop(columns=target)
y_test = test[target]
print("Training rows:", len(train), "— Test rows:", len(test))
# 4. Create a model and train it on the training table.
model = Classifier(model="tabicl-v2", random_state=9)
model.fit(train, target=target)
# 5. Predict the held-out rows, without passing their target column.
predictions = model.predict(query)
print(pd.DataFrame({"actual": y_test.to_numpy(), "predicted": predictions}).head())
# 6. Compare predictions with the answers we kept aside.
print("Test accuracy:", accuracy_score(y_test, predictions))
print(classification_report(y_test, predictions, zero_division=0))
print("Keep this predictor ID:", model.predictor_id_)
Accuracy and per-class precision/recall/F1 describe your held-out run, not a
promised benchmark score. Start explains each step and teaches
numeric predictions with real Yacht data. fit uploads only your training rows;
your workspace retains the resulting dataset and predictor for reuse.
Research metadata and one-step loading
Keep the catalogue detail (schema, column descriptions and provenance)
beside a download with metadata=True, or load a table directly with the
research extra (pip install "welt-client[research]"):
saved = client.download_research_dataset(
dataset_id, path.with_name("iris-2.parquet"), metadata=True)
# saved.path, saved.metadata_path ("iris-2.parquet.metadata.json"), saved.metadata
data, meta = client.load_research_dataset(dataset_id, metadata=True)
print(meta.name, meta.column_descriptions)
Without metadata=True the download returns its local path. Omitting version
selects the currently published file; the SDK verifies its size and checksum.
load_research_dataset removes its temporary file after loading. See
Research datasets.
The released client includes sync/async resources, resumable file uploads, durable
batch jobs, workspace selection and native causal objects. Estimator CSV/Parquet
convenience reads load files into memory; Client.upload_file uses upload sessions
and supports recovery with a retained upload ID. Available formats, models, tasks
and limits depend on the connected server. Inspect its catalogue before executing.
Each TabICLv2, Kumo Tabular Medium, TabDPT 1.3 and Mitra-v2 classification and regression
profile has measured shapes: TabICLv2 and Kumo Tabular Medium up to 8,000 training rows × 20
features (or 4,000 × 40, 2,000 × 80), Mitra-v2 up to 4,000 × 20, TabDPT 1.3 up to 500 × 20.
Direct predictions take up to 100 rows per call, and classification up to 10 classes.
Client().models() reports the current limits. Capabilities explains scope.
A local wait timeout leaves server work running. Reconnect by its job ID rather
than fitting again; recovery describes typed failures,
authentication, cancellation and retry behavior. Probabilities are not calibrated
coverage. ArrowFM, CDFM and AVICI discovery preserve native graph and score semantics;
causal conversion is restricted to declared native DAGs
and needs the welt-client[ergodic] extra; ergodic then identifies
and estimates effects locally. The complete all-model catalogue remains gated.
Examples and development
Runnable script · Jupyter notebooks · Research datasets · Contributing
uv sync --frozen
uv run --frozen pytest -q
uv build
Offline tests patch HTTP transport outside user examples; they neither contact the hosted service nor measure foundation-model quality. Notebook sources have cleared outputs; clean-wheel execution and bounded authorized live acceptance are separate evidence. CI requires no private backend, credentials or checkpoints.
Agent workflows, workspace selection and the released command reference: CLI.
Explicit hidden-model runs
client.model("chronos-2") inspects an explicit hidden ID while
client.models() keeps the main catalogue. client.submit_model_run(payload, idempotency_key="your-key") returns a durable Job; job.result() returns the
native task result. AsyncClient has matching methods. The payload follows the
API's tabular support/query, causal table or univariate forecasting contract;
check the model metadata for enabled tasks, limits, readiness and workspace access.
from welt import Client
client = Client()
job = client.submit_model_run({
"model_id": "chronos-2", "task": "univariate_forecasting",
"series": {"values": [float(i) for i in range(48)],
"start": "2026-01-01T00:00:00Z", "frequency_seconds": 3600},
"horizon": 12,
}, idempotency_key="forecast-example-1")
result = job.result()
print(result["predictions"])
CLI equivalents: welt models get chronos-2, welt run --input request.json,
welt jobs wait JOB_ID. Use welt model-runs delete JOB_ID --yes or
client.delete_model_run(id) to explicitly remove a terminal run's input/result.
Deleting keeps the idempotency/usage record; a new run needs a fresh key. Native
model libraries remain server-side. Restricted models need an internal testing
workspace; hidden status alone does not grant execution access. TabSTAR's trained
state stays alive for the single run, and these runs do not publish reusable
support-only fitted predictors. LimiX query splitting can change its transductive
results. API errors, cancellation and timeouts retain existing typed semantics.
Compare models with cross-validation
client.evaluate(data, "target", task="classification") cross-validates every
eligible model (or up to 8 you name with models=[...]) on the same seeded folds and
returns an Evaluation: summary() is the leaderboard against a baseline, folds()
and predictions() are DataFrames, show() displays the HTML report in Jupyter and
report_link() creates a signed link anyone holding it can open for up to seven days.
evaluation.fit() then fits the chosen model on the full dataset. It requires SDK 0.12
or later and a server release with evaluations; an older server raises NotFoundError with
code="evaluations_unavailable". Evaluations guide.
Forecast time series
Forecast(model="chronos-2") forecasts one series or a long-format panel with
Chronos-2. Fit with time, an optional id column, one or more target columns, and
past_covariates, future_covariates and categorical drivers; then call
forecast(horizon, future=known_future_table). One request covers every series and
target, and to_frame() returns one row per series, target and step with the median
and q_<level> quantiles. Limits come from the model's published envelopes
(client.model("chronos-2")["forecast_envelopes"]), and from the forecasting release a
forecast is priced at the prediction rate per token: Σ (history rows + horizon) ×
(targets + covariates), rounded up.
Quantiles are not calibrated intervals; crossed native quantiles are sorted and
counted in rearranged_steps. Panels and covariates need SDK 0.14 and a server with
the forecasting task. History and future can also be workspace dataset IDs; tables are
sent inline, never uploaded automatically, and bodies above 10 MiB are refused before
sending. client.delete_forecast(id) removes a finished forecast's input and result.
The univariate predict API from SDK 0.11 stays supported.
Forecast(model="timestral-209m") (or timestral-28m), listed after Chronos-2, uses the same
calls and price but forecasts one series per request: SDK 0.14.1 refuses a panel before sending
with unsupported_capability, so fit and forecast each series separately. Timestral weights:
2026 - Mistral AI, Modified MIT licence (Timestral-209M,
Timestral-28M) (forecast with Timestral).
Forecast guide ·
tutorial notebook ·
Use Chronos-2 inside ergodic's backtest and reconcile:
https://docs.ergodic.dev/forecast-with-welt.html
Metadata
Release files for welt-client 0.15.0
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 | |
|---|---|---|---|---|
| welt_client-0.15.0.tar.gz | 442.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| welt_client-0.15.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 522.4 kB
Release files / welt_client-0.15.0.tar.gz
| Download URL | welt_client-0.15.0.tar.gz |
|---|---|
| Size | 442.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
95d00910dc1fba59cdb13a2c52a2b66a9d110b93e905999751d46f739a3f9977
|
|
BLAKE2b-256 checksum How to use checksums |
c118de60a661d37bf54f5a92e7ae1df4159d89b1f08425e24c40072e33db2477
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.16
|
Release files / welt_client-0.15.0-py3-none-any.whl
| Download URL | welt_client-0.15.0-py3-none-any.whl |
|---|---|
| Size | 80.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e711ffd9a94a829b5d7ab8ff8317facad9dbb74eebbbeabd705dc42a0e7d93e0
|
|
BLAKE2b-256 checksum How to use checksums |
fed290c4ca72e782992d55a84e31213d77d6ebd49f5f811ee426488250d07f1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.16
|
Security for welt-client 0.15.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.