ergodicDocs
Products: switch from ergodic to another product
Get started

ReferenceWelt bridge

Welt bridge

Run Welt's hosted foundation models from ergodic. Import from ergodic.welt.

Welt hosts foundation models for tabular data. This optional module connects them to ergodic's discovery and estimation:

Install it with pip install "ergodic[welt]", which adds welt-client on Python 3.11 to 3.13 (welt-client does not support Python 3.14 yet). Every call here is a request to Welt and most are paid; nothing runs at import. The rest of ergodic never imports this module, welt or httpx, and makes no network calls.

Each function takes an optional client: a welt.Client you opened (it is used as is and never closed here). Without one, a short-lived welt.Client() is opened per call, reading the key from WELT_API_KEY or welt login.

Also exported from ergodic: discover.

WeltDecodeError#

python
class WeltDecodeError(
    model: str,
    decoder: str,
    error: Exception,
    result: Any,
    scores: pd.DataFrame | None,
) -> None

Decoding a paid Welt result's edge scores failed; the result is not lost.

ergodic checks every decoder setting before submitting, so this is rare. It carries the native result and its scores, which stay in your Welt workspace, so you can decode them again locally.

Attribute Description
model The Welt model id.
decoder The versioned decoder id that failed.
result The native welt.CausalResult.
scores Its edge-score matrix (rows the source, columns the target), or None if the scores themselves could not be read.

WeltGraphNotDAGError#

python
class WeltGraphNotDAGError(
    model: str,
    native_graph_type: str,
    result: Any = None,
    scores: pd.DataFrame | None = None,
) -> None

A Welt model's native graph is not a declared DAG, so ergodic refuses it.

ergodic converts only declared DAGs and never projects or relabels a directed graph as one. When the model is known to return such graphs, the refusal comes before anything is uploaded or paid for, and result is None. When a finished result turns out not to be a declared DAG, the paid result stays in your Welt workspace and this error carries it.

Attribute Description
model The Welt model id.
native_graph_type The model's native graph type, for example "directed".
result The native welt.CausalResult, or None if nothing was submitted.
scores Its edge-score matrix (rows the source, columns the target), or None if nothing was submitted.

WeltLearner#

python
class WeltLearner(
    model: str = 'tabicl-v2',
    task: str = 'regression',
    *,
    client: Any = None,
    max_fits: int | None = 10,
    configuration: str = 'default',
    seed: int = 0,
    timeout: float = 600.0,
) -> None

A Welt tabular model as an ergodic learner.

Use it wherever ergodic takes a learner, for example estimate_effect(graph, data, "X", "Y", strategy="dml", learner=WeltLearner("tabicl-v2")). A slot that needs probabilities (a propensity) takes a classification learner; pass a slot mapping such as {"outcome": WeltLearner(), "propensity": WeltLearner(task="classification")}.

Each fit uploads the training rows as a new Welt dataset and fits a predictor: one paid fit. Both stay in your Welt workspace afterwards; nothing here deletes them (welt.Client().predictors() and .datasets() list them). Each predict is a paid prediction, sent in batches no larger than the model's prediction-row limit. DML with n_folds=k fits 2 * k times.

A slot with no feature columns (an empty adjustment set) has nothing for a model to learn: its conditional mean is the training mean, or the class frequencies for classification. The learner fits that locally, with no upload, no paid fit and no charge to max_fits, and predictor_id_ is None.

The learner and its clones share one budget of max_fits fits. It caps paid fits only, not predictions: each fit is followed by one prediction call per batch of held-out rows (DML on 8,000 rows with five folds and a 100-row limit makes about 160). Fits take no row weights, so supports_sample_weight is False and ergodic refuses this learner in a weighted slot (the R-learner's final) before fitting anything.

Parameter Description
model Any Welt classification or regression model id; none is checked here. The default follows what Welt serves: "tabicl-v2" is available today, while "tabpfn-3.5-fast" is still planned. See which models run now, with their row, column and prediction limits, with [(m["id"], p["task"], p["limits"]) for m in welt.Client().models() for p in m["task_profiles"] if p["execution_available"]], welt models list on the command line, or the Models page of the Welt SDK docs.
task "regression" or "classification". Only a classification learner has predict_proba.
client A welt.Client to use as is, shared with every clone. None opens a short-lived welt.Client() per request.
max_fits The most paid fits this learner and its clones may make together; None removes the cap. The default 10 covers DML with five folds. Predictions are not counted.
configuration The Welt model configuration.
seed The fit seed Welt records with each predictor.
timeout Seconds to wait for each fit or pending prediction. A timeout leaves the job running in Welt.
Attribute Description
predictor_id_ The fitted Welt predictor's id; None after a no-feature (local) fit.
model_version_ The exact model version Welt fitted; None after a no-feature fit.
classes_ The class labels, sorted (classification only).
supports_sample_weight Always False; read by ergodic's weighted slots.

WeltLearner.get_params#

python
def WeltLearner.get_params(deep: bool = True) -> dict[str, Any]

The constructor arguments, as scikit-learn's get_params returns them.

Parameter Description
deep Accepted for scikit-learn compatibility; there are no nested estimators.

Returns: A dict of every constructor argument.

WeltLearner.set_params#

python
def WeltLearner.set_params(**params: Any) -> Self

Set constructor arguments; a new max_fits starts a fresh budget.

Parameter Description
**params Constructor arguments by name.

Returns: This learner.

Raises Description
ValueError A name is not a constructor argument, or a value is invalid.

WeltLearner.fits_used#

python
property WeltLearner.fits_used: int

Paid fits made so far by this learner and its clones together.

WeltLearner.fit#

python
def WeltLearner.fit(
    X: npt.NDArray[np.float64],
    y: npt.NDArray[np.float64],
    sample_weight: npt.NDArray[np.float64] | None = None,
) -> Self

Fit a Welt predictor on these rows: one paid fit.

Parameter Description
X The feature matrix, one row per unit. With no columns the fit is the local training mean (or class frequencies) and costs nothing.
y The target, one value per row: numbers for regression, labels for classification.
sample_weight Must be None. Welt fits take no row weights, and a weight is never silently dropped.

Returns: This learner, fitted.

Raises Description
ValueError sample_weight was given, X has no rows, or y does not match X. Nothing is uploaded.
RuntimeError The shared max_fits budget is spent.

WeltLearner.predict#

python
def WeltLearner.predict(X: npt.NDArray[np.float64]) -> npt.NDArray[Any]

Predict with the fitted Welt predictor: one paid prediction per batch.

Parameter Description
X Rows with the same columns as the fit.

Returns: Numbers in the target's units for regression, class labels for classification.

WeltLearner.predict_proba#

python
property WeltLearner.predict_proba: Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]

Class probabilities, one column per class in classes_ order.

Only a classification learner has this; ergodic reads its presence to tell a classifier from a regressor.

Raises Description
AttributeError The learner's task is regression.

discover#

python
def discover(
    data: TabularData,
    model: str = 'arrow',
    *,
    seed: int = 0,
    timeout: float = 600.0,
    knowledge: DomainKnowledge | None = None,
    decoder: str | Decoder | None = None,
    client: Any = None,
) -> DiscoveryResult

Learn a DAG with a Welt causal discovery model.

Uploads the dataset's variables (continuous, no missing values), runs one discovery job and waits for it. This is one paid Welt job; the uploaded dataset and the native result stay in your workspace until you delete them. ergodic.discover(data, method="welt:<model>") calls this.

Welt's models and limits come from its catalogue (welt.Client().models()). Today arrow declares native DAGs. cdfm and avici return native directed graphs that may hold cycles or reciprocal edges, so they are refused with WeltGraphNotDAGError before anything is uploaded or paid for (the catalogue's stated graph type wins over that built-in list). A result that is still not a declared DAG is refused too, with the paid result attached.

decoder= opts into local decoding. The run then accepts any model, reads the native edge scores (rows the source, columns the target) as EdgeProbabilities of kind "independent" (each score a separate directed-edge marginal, uncalibrated) with the Welt provenance, and decodes them with decode(). The returned graph is that decoded DAG, not the model's native graph, and its diagnostics say so. For the greedy decoder without an explicit threshold, the model's native threshold is used when Welt records one (decoder.parameters.threshold: 0.5 for AVICI, the adaptive threshold for CDFM), so greedy keeps what the model's own rule keeps and only drops edges that close a cycle or a reciprocal pair. On a DAG model (arrow) the decoder replaces the native DAG with one decoded from the same scores, read the same independent way. Any other choice can be made locally, with no new run, from result.diagnostics["edge_probabilities"]. Every decoder setting, the max_nodes cap against the data's variable count included, and the knowledge are checked before anything is uploaded; if decoding still fails after the paid run, WeltDecodeError carries the native result and its scores.

Parameter Description
data Observational rows; every variable must be continuous and complete.
model The Welt causal discovery model id, for example "arrow".
seed The run's seed, recorded in the result's provenance.
timeout Seconds to wait for the job. A timeout leaves the job running in Welt; reconnect with welt.Client().job(job_id).
knowledge Must be None without a decoder (Welt discovery takes no constraints yet). With a decoder it constrains the local decoding only; Welt still runs unconstrained. It is checked before anything is uploaded.
decoder None (native DAGs only), a decoder id such as "greedy", or a Decoder with its settings (a sampler needs Decoder("pair_sampler", samples=..., seed=...)).
client A welt.Client to use as is; None opens a short-lived one.

Returns: A DiscoveryResult whose graph is the native DAG with every variable, method is "welt:<model>", and whose diagnostics hold the Welt provenance: welt_job_id, welt_result_id, welt_dataset_id, welt_model, welt_model_version, welt_configuration_version, welt_decoder, welt_seed and welt_scores (the native edge scores as a dataframe, rows the source and columns the target; not calibrated confidence). With a decoder it is a DecodeResult (still a DiscoveryResult, method "welt:<model>") whose graph is the decoded DAG; diagnostics add the decode labels (decoded True, native False, decoder, parameters, threshold_source, rejected_cycles, note, ...), welt_native_graph_type, welt_native_edges (the native directed edges as pairs) and edge_probabilities.

Raises Description
TypeError data is not tabular.
WeltDecodeError Decoding failed after the paid run; the error carries the result and its scores.
ValueError knowledge was given without a decoder (or names unknown variables or a confounded pair), the decoder settings are invalid or its max_nodes is below the variable count, or a variable is not continuous or has missing values. Nothing is uploaded.
WeltGraphNotDAGError The model's native graph is not a declared DAG, either known before submitting (nothing is paid) or found in the result.

load_research_dataset#

python
def load_research_dataset(
    dataset_id: str,
    *,
    version: str | None = None,
    types: Mapping[str, VariableType | str | Ordinal] | None = None,
    exclude: Iterable[str] | None = None,
    categorical_threshold: int = 10,
    client: Any = None,
) -> TabularData

Load a dataset from Welt's research catalogue as tabular data.

Welt verifies the download's size and checksum and reads it into a dataframe; ergodic then infers the schema as tabular() does. Each download is billed per dataset (see Welt's pricing). Reading Parquet content needs pyarrow: pip install "welt-client[research]".

Parameter Description
dataset_id The research dataset's id, from client.research_datasets().
version A content version to pin; None takes the current one.
types Per-column type overrides, as in tabular().
exclude Columns to keep but not treat as variables.
categorical_threshold Integer columns with at most this many distinct values are read as categorical, with a warning.
client A welt.Client to use as is; None opens a short-lived one.

Returns: The table as TabularData.

upload_dataset#

python
def upload_dataset(
    data: TabularData,
    *,
    target: str | None = None,
    name: str = 'ergodic dataset',
    client: Any = None,
) -> dict[str, Any]

Upload a tabular dataset to your Welt workspace.

The upload holds the dataset's variables in their column order; excluded columns stay local. Values go up as they are stored (categories as their labels, missing values as empty cells). Uploading is free, and the dataset stays in the workspace until you delete it with client.delete_dataset(id).

Parameter Description
data The rows to upload.
target A variable to mark as the prediction target, for a later fit or evaluation. None uploads a target-free table, which is what causal discovery needs.
name The dataset name shown in Welt.
client A welt.Client to use as is; None opens a short-lived one.

Returns: The Welt dataset record, with its "id".

Raises Description
TypeError data is not a TabularData.
ValueError target is not one of the variables, or a cell is not a number or a string.
Suggest an edit
Documentation

Search ergodic 0.2.1

Search ergodic by task, function or error.