Qombra Python SDK
Programmatic access to Qombra: dataset statistics, AI-guided preprocessing (QAgent, an AI system whose responses are generated by a language model), Model training (QBrain), inference, zero-shot time series forecasting, and SHAP explainability.
pip install qombra
The qombra package is the supported way to use the Qombra API: it handles authentication, dataframe
transport, and long-running jobs for you. Requires Python ≥ 3.10; works with pandas DataFrames throughout.
All usage counts toward your account's usage limits.
Authentication
Two ways in, for the two ways people use the API. Both send the same bearer credential and reach the same endpoints; they differ only in how long the credential lives and where it comes from.
Interactive: Token through qombra.login()
Opens a browser window where you sign in on the Qombra web app and approve the SDK session. The resulting token is kept in your OS keyring, is valid for 12 hours, and is stored server-side only as a hash.
import qombra
qombra.login() # browser opens; approve → "logged in as you@corp.com, expires at …"
… # work
qombra.logout() # end the session server-side + clear the keyring
- Scoped sessions:
with qombra.Qombra() as client: …; leaving thewithblock closes the session and ends it server-side. - No browser (SSH, CI):
qombra.login(headless=True)prints the consent URL and prompts for the code shown after approval. - Expiry: after 12 hours calls raise
AuthenticationError; just re-runqombra.login().
Production: Access through API key
A scheduled retrain or an inference service cannot open a browser every twelve hours. An API key never expires: it works until you revoke it, and needs no sign-in. Create one in the Qombra app under Account → API keys, then put it in your deployment's environment:
export QOMBRA_API_KEY=qbk_…
import qombra
preds = qombra.predict(model_id, new_rows) # no login() call
- Shown once. The key appears exactly once, at creation; the server keeps only a hash of it. Store it in your secret manager.
- Rotation is deliberate: create a new key, deploy it, then revoke the old one. Each key's last-used time is listed, so an unused one is easy to spot.
- Revoke in the same panel; the key stops working immediately.
close()never revokes an API key, so ending awithblock cannot take your service offline. - Same account, same limits: usage through a key counts exactly as it does interactively.
Quickstart
import pandas as pd
import qombra
qombra.login()
df = pd.read_csv("customers.csv")
report = qombra.analyze(df) # dataset statistics
result = qombra.preprocessing(df, "drop outliers in price") # AI preprocessing
model = qombra.fit(result.df, target="churn_30d") # trained by QBrain
preds = model.predict(new_rows) # inference
print(model.explain()) # SHAP bar chart
# later, in a new Python session, no retraining:
model = qombra.Model.from_id("<model.id>")
preds = model.predict(more_rows)
run = qombra.auto_run(df, "Which customers will churn soon?") # full pipeline in one call
print(run.answer) # "142 customers are at risk of churning."
qombra.logout()
Async usage
From qombra 0.5.0, asyncio applications (web services, agents, anything running an event loop) can
use AsyncQombra. It mirrors the whole client surface as coroutines, so
uploads and job polling yield to the event loop instead of blocking it:
import qombra
async with qombra.AsyncQombra() as client: # or AsyncQombra(api_key=...)
model = await client.fit(train_df, target="churn_30d")
preds = await model.predict(new_rows) # an AsyncModel, awaitable too
fc = await client.forecast(sales, target="units", horizon=14, id_column="store")
Endpoints, credentials, parameters, validation, retries, timeouts, warnings, result types and metering are
identical to the sync client, so everything documented below applies unchanged; only the waiting differs.
qombra.login() itself stays synchronous (it drives a browser round-trip): run it before entering the
event loop, or pass api_key=. Cancelling the task awaiting fit() / forecast() /
auto_run() sends the same best-effort server-side cancel as Ctrl+C does in the sync client.
fit() is exactly
what a script wants, and there is no event loop to keep responsive.Functions
Module-level functions share one default client; the Qombra class offers the
same methods on an explicit, closable session. Long-running calls (preprocessing, fit,
predict, forecast, explain, auto_run) block while a server-side job
runs and take a timeout (seconds); on JobTimeoutError the job continues server-side; models
still land in your account, and a finished forecast or auto-run can be collected with
forecast_result(job_id) / auto_run_result(job_id).
qombra.login(base_url=None, *, headless=False, open_browser=True, timeout=180.0) → TokenInfo
qombra.logout(base_url=None) → None
Open the browser to sign in, and hand the session back when you are done.
Parameters
- base_url str = None
- API base URL override. Defaults to the Qombra production API.
- headless bool = False
- No browser available (SSH, CI): print the consent URL and prompt for the code shown after approval.
- open_browser bool = True
- Set False to print the URL instead of opening a window; the local callback still runs.
- timeout float = 180.0
- Seconds to wait for the browser round-trip.
Returns
- TokenInfo
- The session that was opened. The token is stored in your OS keyring and valid for 12 hours; every later call
picks it up automatically.
.email·.expires_at
Raises
- LoginDeniedError
- You clicked Deny on the consent page.
- LoginTimeoutError
- The browser flow did not finish within
timeout. - AuthenticationError
- The sign-in could not be completed.
- NetworkError
- The server could not be reached.
Notes
logout() ends the session server-side and clears the keyring; it is safe to call when not logged in,
and it never touches a production API key. For unattended systems, skip login() entirely and set
QOMBRA_API_KEY; see Production use.
qombra.analyze(df, excluded_columns=None) → AnalysisReport sync
Get statistics and data-quality warnings for a dataframe.
Parameters
- df DataFrame
- The data to analyze. The SDK uploads a sample of up to 1000 rows with the fewest NaN values, keeping their original order.
- excluded_columns list[str] = None
- Columns to leave out of the analysis.
Returns
- AnalysisReport
- Per-column statistics and histograms, MIC correlations between columns, and quality warnings (PII-like,
constant, ID-like, class imbalance, duplicate rows).
.features·.correlations·.warnings·.summary·.duplicates·.imbalances
Raises
- ValidationError
- The dataframe is empty or cannot be serialized (e.g. mixed-type object columns).
- AuthenticationError
- Not logged in, or the 12-hour session expired.
qombra.preprocessing(df, instruction, *, timeout=1500.0) → PreprocessingResult job
Clean and reshape a dataframe with QAgent, following your instruction in plain language. The result is directly usable with qombra.fit, i.e. QBrain.
Parameters
- df DataFrame
- The raw data.
- instruction str
- What to do, in plain language, e.g.
"drop duplicate rows and one-hot encode region". - timeout float = 1500.0
- Client-side wait limit in seconds. Expect minutes; the work continues server-side either way.
Returns
- PreprocessingResult
- A model-ready dataframe: leakage columns dropped, very-high-cardinality categoricals capped, and non-feature
columns (identifiers, raw dates) removed, so it can go straight into fit. Printed to the
console on completion and stored in your account.
.df·.summary·.warnings·.actions_taken·.excluded_columns·.job_id
Raises
- JobFailedError
- Preprocessing failed server-side;
.codesays why. - JobTimeoutError
timeoutelapsed; the job keeps running and its result lands in your account.- QuotaExceededError
- Chat-message or output-token quota exhausted.
Notes
The agent's work is charged to your account's LLM output-token limit, and the call also spends
one chat message, the same budget the web app's chat consumes. A single call is charged once, no matter how many
stages it runs internally. See qombra.whoami() for what is left.
Example
result = qombra.preprocessing(df, "drop outliers in price and one-hot encode region")
print(result.excluded_columns) # ['passenger_id', 'signup_ts']
model = qombra.fit(result.df, target="churn_30d")
qombra.fit(df, target, *, metric=None, effort=None, finetuning=None, timeout=10800.0) → Model job
Train a QBrain model to predict one column, and get back a handle to it.
Parameters
- df DataFrame
- Training data including the target column. Rows whose target is missing are excluded from fitting automatically; they become the model's instant predictions.
- target str
- Name of the column to predict. Classification or regression is decided by the engine from the column itself.
- metric str | None = None
- Evaluation metric the engine optimizes and reports on. Unset keeps the task default
(accuracy for classification, MAPE for regression). Setting it explicitly may weaken imbalance mitigation
as the system will always stick to the selected metric and therefore does not fine-tune with balanced metrics.
Classification:
accuracy·roc_auc·f1_micro·log_loss·qwk. Regression:mape·rmse·rmsle·mae·median_ae·smape. The metric must fit the task the engine infers from the target column; a mismatch fails the training job with the reason. - effort str | None = None
- Compute budget for the run. Also accepts
auto(derived from data size); unset keeps the server's default.Effort Trade-off lowFor fast iteration. mediumFor simpler everyday tasks. Good trade-off between runtime/cost and performance. highHigh performance, still a good trade-off between runtime/cost and performance. maxUsually only limited increments in performance over highat significantly higher cost. For use-cases where even tiny increments in performance yield significant returns. - finetuning bool | None = None
Trueadditionally fine-tunes QBrain on your training data. The fine-tuned model is only kept if it scores better on held-out data, so the result is never worse than without it, but training takes longer. Not available for targets with more than 10 classes.- timeout float = 10800.0
- Client-side wait limit in seconds. Defaults to three hours; the server itself trains for up to five.
A run that outlives the wait raises
JobTimeoutErrorwhile the server finishes it, and the model lands in your account as usual. Passtimeout=18000to always end the call with a model. Training that reaches the server's five-hour cap does not fail: the best model reached by then is returned with.truncatedset.
Returns
- Model
- A handle to the trained model. The model itself stays on the server and is addressed by its id, so you can
reconstruct it in any later session with
Model.from_id(...). If training ran into the server's time limit it does not fail: the model reflects the best state reached by then,.truncatedis true and aUserWarningis emitted; a re-run with a lowereffortmay finish, one with more time may do better. Iffinetuningwas requested but could not run, the model is trained without it:.finetuning_skippedholds the reason and aUserWarningis emitted..predict(df)·.explain()·.instant_predictions·.metrics·.truncated·.finetuning_skipped·.id
Raises
- ValidationError
- The target column is missing, too few rows carry a target value, or
metric/effortis not one of the values above, orfinetuningis not a boolean. - QuotaExceededError
- Analysis quota exhausted.
- JobFailedError
- Training failed server-side (including a
metricthat does not fit the inferred task). - JobTimeoutError
timeoutelapsed; training continues server-side and the model lands in your account.
Example
model = qombra.fit(train_df, target="churn_30d")
# a rare positive class: rank by ROC AUC, spend more compute
model = qombra.fit(train_df, target="churn_30d", metric="roc_auc", effort="high")
# squeeze out more: fine-tune QBrain on your data
model = qombra.fit(train_df, target="churn_30d", finetuning=True)
print(model.metrics["test_metric"]) # 0.87
predictions = model.predict(new_rows)
Notes
Training runs on QBrain, Qombra's proprietary tabular foundation model. This is the same engine behind every prediction in the web app. No manual model selection or tuning is needed.
Each call counts toward your analysis quota.
qombra.predict(model_or_id, df, *, return_probabilities=False) → pandas.Series | pandas.DataFrame sync
Predict on new samples with a trained model.
Parameters
- model_or_id Model | str
- A model object, or the id string of one.
- df DataFrame
- Rows to score. Columns are aligned to training automatically: extras are ignored, missing feature columns are treated as NaN (with a warning), and a target column, if present, is dropped. Predict in batches for very large frames.
- return_probabilities bool = False
- Classification models only. Also return the class probabilities behind each prediction.
Returns
- pandas.Series
- One prediction per input row, named
"<target>_prediction"and aligned todf.index, so it can be assigned straight back onto your dataframe. - pandas.DataFrame
- With
return_probabilities=True: aligned todf.index, with"<target>_prediction"and one"<target>_proba_<class>"column per class. The probabilities of a row sum to 1.
Raises
- ValidationError
- The dataframe shares no columns with the model's training features, or
return_probabilitieswas requested for a regression model (code="probabilities_unavailable"). - NotFoundError
- The model does not exist for this account (e.g. it was deleted).
Example
new_rows["churn_risk"] = qombra.predict(model, new_rows)
# identical to model.predict(new_rows)
# Classification: labels plus one probability column per class
probs = qombra.predict(model, new_rows, return_probabilities=True)
probs[["churn_prediction", "churn_proba_yes"]].head()
qombra.forecast(df, target, horizon, *, timestamp_column="timestamp", id_column=None, future=None, freq=None, quantiles=(0.05, 0.5, 0.95), groups=None, non_negative=False, timeout=8100.0) → Forecast job
qombra.forecast_result(job_id) → Forecast sync
Forecast univariate or multivariate time series ahead. The model is zero-shot, so there is nothing to train and no model to keep, hence no model ID is returned.
Parameters
- df DataFrame
- History in long format: one row per observation with a timestamp column, the target column(s),
and optionally an id column (one series per distinct id) and further columns, which are used as
past covariates. Timestamps may be datetimes, dates or date strings; gaps are filled and duplicate
timestamps collapsed (last one wins). Series shorter than 3 observations are skipped and reported in
.warnings. - target str | list[str]
- Numeric column(s) to forecast. Several targets are forecast jointly per series; see the note below.
- horizon int
- Steps ahead, in the data's own frequency (at most 1,024).
- timestamp_column str = "timestamp"
- Name of the time column.
- id_column str | None = None
- Column identifying each series. Leave unset for a single series.
- future DataFrame | None = None
- Known future values of covariates (prices, promotions, holidays): the id and timestamp columns plus the
covariate columns, one row per series per forecast step, starting right after each series' last observation.
Every covariate here must also exist in
df; columns ofdfthat are absent here are treated as past-only. - freq str | None = None
- Pandas frequency alias
(
"D","h","W-MON","MS", …). Inferred per series when unset; pass it when the data is too gappy to infer from. - quantiles sequence[float] = (0.05, 0.5, 0.95)
- Prediction-interval levels to return next to the point forecast: any number of values between 0.01 and 0.99; 0.5 is always included. Each level adds a column to the result, so many levels count against the forecast-values limit below.
- groups dict[str, list] | None = None
{"north": ["s1", "s2"], …}: series in a group inform each other's forecast, which helps related series with short histories. Unset, every series is forecast independently. Requiresid_column.- non_negative bool = False
- Floor the forecast and every quantile at 0 (counts, demand).
- timeout float = 8100.0
- Client-side wait limit in seconds, sized to outlive the server's worst case (queueing plus the run) so the default wait always ends with a result.
Returns
- Forecast
.frameis long over series, target and timestamp: the id column (if any), the timestamp column,target,forecast(the median) and oneforecast_qXXcolumn per requested quantile..wide()pivots it to timestamps × series..frame·.wide()·.warnings·.horizon·.freq·.job_id
Raises
- ValidationError
- Before anything runs: a missing column (
missing_column), a non-numeric target (invalid_target_dtype), a numeric timestamp column (invalid_timestamps), afutureframe that does not cover every series and step (future_misaligned), or a request above the limits below (horizon_too_long,too_many_series,too_many_columns,too_many_points,too_many_output_values). - QuotaExceededError
- Hourly prediction/forecast limit reached (details carry
retry_after_sec). - JobFailedError
- The engine refused the data once it looked at it:
irregular_timestamps(no single regular frequency; passfreq),no_usable_series,unsupported_covariate(a date-typed covariate),unknown_series/overlapping_groups; orengine_unavailablewhen no capacity is free; retry later. - JobTimeoutError
timeoutelapsed; the job continues server-side. Collect it later withqombra.forecast_result(e.job_id).
Example
# sales.csv: store, date, units, price, promo (one row per store and day)
fc = qombra.forecast(sales, target="units", horizon=14,
timestamp_column="date", id_column="store",
future=planned_prices, # store, date, price, promo for the next 14 days
groups={"north": ["s1", "s2", "s3"]},
non_negative=True)
fc.frame.head() # store, date, target, forecast, forecast_q05, forecast_q50, forecast_q95
fc.wide() # one column per store, one row per forecast day
fc.wide(quantile=0.95) # the upper band
print(fc.warnings)
Notes
Forecasting runs on QBrain, zero-shot: the engine reads each series' history directly, so there is no training step, no model id, and nothing to delete afterwards. Each call counts toward the hourly prediction/forecast limit and spends no analysis or token quota.
Covariates can be numeric or categorical (strings, booleans); date-typed covariates are rejected; derive features from them instead. All targets of a series share the same covariates and are forecast jointly. If a covariate applies to only one target, model that target as its own series (its own id) instead; it then gets its own covariates but is forecast independently of the others, since information is shared only within a series or a group.
Quantile levels off the engine's native grid are interpolated between the neighbouring native levels. Timezone-aware timestamps are converted to UTC. Each series' history is truncated to its most recent 8,192 steps.
| Limit per call | Value |
|---|---|
| Series (distinct ids) | 10,000 |
| Value columns per series (targets + covariates) | 100 |
| Horizon | 1,024 steps |
| Data points (history rows × value columns, after truncation) | 20,000,000 |
| Forecast values (series × horizon × targets × (1 + quantile levels)) | 10,000,000 |
qombra.explain(model_or_id, df=None, *, timeout=900.0) → Explanation job
Find out which features drive a model's predictions.
Parameters
- model_or_id Model | str
- A model object, or the id string of one.
- df DataFrame = None
- Rows to explain: the first 200, in the order sent (a warning says so when more are sent). Omitted, a representative sample of the model's training data is used, with a fixed random seed so repeated calls agree.
- timeout float = 900.0
- Client-side wait limit in seconds.
Returns
- Explanation
- SHAP values per feature, plus a console bar chart when printed.
print(...)·.mean_abs_shap·.to_frame()·.relationships·.base_value
Raises
- JobFailedError
- SHAP computation failed server-side.
- JobTimeoutError
timeoutelapsed; the job keeps running server-side.- NotFoundError
- The model does not exist for this account.
qombra.auto_run(df, prompt, *, timeout=7200.0) → AutoRunResult job
qombra.auto_run_result(job_id) → AutoRunResult sync
Hand your data and a question to the agent, and get the answer back: a one-sentence answer, the predictions, the quality metric and the driving factors. This runs the full data science workflow as a data scientist would: Data cleaning & pre-processing, model training and prediction as well as explainability. It works for predictive, time-series and causal questions alike.
Parameters
- df DataFrame | list | dict
- The raw data; preprocessing is part of the run. One dataframe, or up to 5 related
ones as a list or a
{"name": df}dict (100,000 rows in total, 500 columns each); the dict names are shown to the agent, which helps it relate the tables. - prompt str
- What to analyze or predict, in plain language.
- timeout float = 7200.0
- Client-side wait limit in seconds.
Runs typically take 3-10 minutes, depending on task complexity and dataset size.
Returns
- AutoRunResult
- The answer plus everything behind it, with a ready-to-use model when one was trained.
.answer·.predictions·.accuracy·.driving_factors·.model
Raises
- JobFailedError
- The run stalled or produced no model or estimate; the partial report is on the exception's
.result. - JobTimeoutError
timeoutelapsed; the run continues server-side. Collect it later withqombra.auto_run_result(job_id).- QuotaExceededError
- Analysis, chat-message, or output-token quota exhausted.
Example
run = qombra.auto_run(df, "Which customers will churn soon?")
print(run.answer) # "142 customers are at risk of churning."
run.predictions.to_csv("at_risk.csv") # the rows the model predicted for
print(run.accuracy, run.accuracy_metric)
print(run.driving_factors[:3]) # top SHAP features
qombra.list_models(created_via="sdk") → list[ModelInfo]
qombra.delete_model(model_or_id) → None
qombra.list_preprocessing_results() → list[PreprocessingResultInfo]
qombra.delete_preprocessing_result(job_id) → None
See what is stored in your account, and remove what you no longer need.
Parameters
- created_via str = "sdk"
- Which models to list:
"sdk"for models you trained through this package,"web"for those trained in the web app,"all"for both. - model_or_id Model | str
- The model to delete.
- job_id str
- The stored preprocessing result to delete:
results[i].job_id.
Returns
- list[ModelInfo]
- Newest first. An ordinary list that renders as a table when displayed; index and iterate it as usual, and use
models[i].model_idfor the full id. Long listings show the newest entries, an ellipsis, and the oldest one; the list itself always holds every row. - None
- Deletion is permanent (model files and stored result dataframes included) and does not refund quota.
Raises
- NotFoundError
- No such model or result for this account.
- ValidationError
created_viais not one of the three accepted values.
Example
>>> qombra.list_models(created_via="all")
2 models in your account
# id target task model metric train test rows created
─ ───────── ───────────── ────────────── ─────── ──────── ───── ───── ─────── ────────────────
0 0624f7fb… Final_Outcome classification qbrain accuracy 0.985 1.000 132/34 2026-08-17 19:07
1 ab12cd34… Survived classification qbrain accuracy 0.891 0.816 712/179 2026-08-24 11:12
qombra.whoami() → dict sync
Check who you are signed in as and what quota is left.
Returns
- dict
{"email", "expires_at", "limits": {"remaining_analyses", "remaining_chat_messages", "remaining_output_tokens"}}. A limit ofNonemeans unlimited. Also the cheapest way to confirm your session still works before starting a long run.
Classes
qombra.Qombra(base_url=None, api_key=None, timeout=30.0)
An explicit, closable session: the same calls as the module-level functions, scoped to a
with block.
Parameters
- base_url str = None
- API base URL override.
- api_key str = None
- Explicit credential (a production API key or a session token) skipping the environment and keyring lookup.
- timeout float = 30.0
- Default per-request timeout in seconds. Uploads and long operations use larger internal limits.
Methods
- analyze · preprocessing · fit
predict · forecast · explain · auto_run - Identical to the module-level functions, bound to this session.
- list_models · delete_model
list_preprocessing_results - Inventory management; see list_* / delete_*.
- whoami() → dict
- Account email, session expiry, and remaining quota.
- close(revoke=True)
- Revoke the token server-side and clear the keyring.
revoke=Falseonly closes the connection pool and keeps the token usable.
Example
qombra.login()
with qombra.Qombra() as client:
model = client.fit(train_df, target="churn")
print(client.whoami())
# leaving the block revokes the token; the session is closed for good
Notes
Credential resolution order: the api_key argument → QOMBRA_API_KEY → the OS
keyring written by login(). The same slot takes either kind, so interactive and
production code differ only in where the credential comes from.
Calls block the calling thread while they wait; in an asyncio application use AsyncQombra instead.
qombra.AsyncQombra(base_url=None, api_key=None, timeout=30.0)
The asyncio counterpart of Qombra: the same calls as coroutines,
scoped to an async with block. Parameters as for Qombra.
Methods
- await analyze · preprocessing · fit
predict · forecast · explain · auto_run - Identical to the functions above (same parameters, result types, warnings and errors), awaited instead of blocking. Calls that return a model handle return an AsyncModel.
- await list_models · delete_model · stop
forecast_result · auto_run_result · whoami · … - Every other method mirrors the sync client one-to-one.
- await aclose(revoke=True)
- Close the session; called automatically when the
async withblock ends. Samerevokesemantics asQombra.close(): a production API key is never revoked.
Example
async with qombra.AsyncQombra() as client:
model = await client.fit(train_df, target="churn")
print(await client.whoami())
# leaving the block closes the session
Notes
Available from qombra 0.5.0. Credential resolution is identical to
Qombra; qombra.login() stays synchronous; run it before entering the
event loop, or pass api_key=. Cancelling the task awaiting fit() /
forecast() / auto_run() sends the same best-effort server-side cancel as Ctrl+C does
in the sync client.
qombra.Model
A trained QBrain model living on the Qombra server. An instance doesn't contain the model itself but a reference to it.
A Model instance can be re-created using the model id (see below).
Attributes
- id str
- Stable model id. Pass it to
Model.from_id(...)in any later session. - target_column str
- The column this model predicts.
- task_type str
"classification"or"regression", decided by the engine from the target column.- model_type str
- The model behind this fit:
"qbrain"for anything trained through this package. - feature_columns list[str]
- Columns used at training time; prediction aligns incoming data to these.
- metrics dict
train_metric/test_metricwith their*_metric_name,n_train_samples,n_test_samples,training_time_sec, andmode_collapse(true when the model predicted a single class for everything).- truncated bool
- True when training reached the server's time limit and the model reflects the best state reached by
then (also shown in the model's
repr). A re-run may do better. - instant_predictions DataFrame
- The predictions training made automatically for rows whose target was missing:
training_row(position in the training data), the feature columns, and<target>_prediction. Empty when no targets were missing. Fetched on first access, then cached. - created_at · created_via str
- When it was trained, and whether through the SDK or the web app.
Methods
- Model.from_id(model_id) → Model
- Reconstruct a model in a new session, no retraining.
- predict(df, return_probabilities=False) → Series | DataFrame
- Score new rows, optionally with class probabilities; see predict.
- explain(df=None) → Explanation
- Feature attributions; see explain.
Example
model = qombra.Model.from_id("<model_id>") # any later session
preds = model.predict(new_rows)
print(model.explain())
qombra.AsyncModel
The model handle returned by AsyncQombra: a Model with the same attributes, whose server-reaching members are coroutines.
Methods
- await AsyncModel.from_id(model_id, client) → AsyncModel
- Reconstruct a model in a new session. Unlike
Model.from_id, the AsyncQombra client is required; there is no module-level default async client. Equivalent toawait client.model(model_id). - await predict(df) → Series
- Score new rows; see predict.
- await explain(df=None) → Explanation
- Feature attributions; see explain.
- await instant_predictions() → DataFrame
- The predictions training made for rows whose target was missing; a method here, not a property as on Model, since a property cannot be awaited. Fetched on first call, then cached.
qombra.PreprocessingResult
What preprocessing() did, and the dataframe it produced.
Attributes
- df DataFrame
- The model-ready data: leakage and non-feature columns removed, ready for fit.
- summary str
- What was done, in prose.
- warnings list[str]
- Issues raised during preprocessing.
- actions_taken list[str]
- The individual cleaning and merging steps, in order.
- excluded_columns list[str]
- Non-feature columns removed from
df; keep them from your original dataframe if you need to join predictions back to source rows. - job_id str
- Handle for delete_preprocessing_result().
Notes
print(result) renders the summary, actions, warnings, and resulting shape; done automatically when
preprocessing finishes.
qombra.Forecast
What forecast() produced.
Attributes
- frame DataFrame
- Long format: the id column (when one was given), the timestamp column,
target,forecast(the median) and oneforecast_qXXcolumn per requested quantile (forecast_q05for 0.05,forecast_q02_5for 0.025). - horizon int · freq str
- Steps forecast and the frequency the engine resolved (e.g.
"D"). - quantiles list[float]
- The levels present in
frame, always including 0.5. - n_series int · n_skipped int
- Series forecast, and series skipped for having too little history.
- warnings list[str]
- What was fixed on the way: duplicates dropped, gaps filled, series skipped or truncated, groups chunked.
- job_id str
- Handle for forecast_result().
Methods
- wide(target=None, quantile=None) → DataFrame
- Timestamps × series for one target (the only/first one by default): the point forecast, or the given quantile level.
Notes
print(forecast) gives series, steps, frequency and any warnings.
qombra.AnalysisReport
What analyze() found in your data.
Attributes
- features list[dict]
- Per-column type, statistics, and histogram.
- correlations list[dict]
- MIC correlation per column pair:
{col1, col2, value}. - warnings list[dict]
- Quality issues:
{column, issue, severity, hint}. - summary dict
- Row, column, and per-type counts.
- duplicates dict
- Duplicate-row count and rate.
- imbalances list[dict]
- Binary columns with a very small minority class.
- n_rows_analyzed int
- Size of the analyzed sample.
qombra.Explanation
Which features drive a model's predictions, and in which direction.
Attributes
- mean_abs_shap Series
- Mean |SHAP| per feature, sorted: the headline importance ranking.
- relationships list[str]
- Human-readable direction hints, e.g. "sqft up → price up".
- feature_names list[str]
- Features in the order the value matrices use.
- shap_values · feature_values list[list[float]]
- Raw per-sample attributions and the feature values they belong to.
- base_value float
- The model's expected output before any feature contribution.
- n_samples int
- How many rows were explained.
Methods
- to_frame() → DataFrame
- SHAP values as a dataframe, one row per explained sample.
Example
>>> print(model.explain())
Feature importance (mean |SHAP|), task: regression, target: price
sqft_living ████████████████████████ 0.4123
grade █████████████ 0.2210
lat ███████ 0.1187
base value: 540123.4
qombra.AutoRunResult
The answer an auto_run() produced, with everything behind it.
Attributes
- answer str
- A one-sentence answer to the prompt, e.g. "142 customers are at risk of churning."
- predictions DataFrame | None
- The rows the model predicted for (for a forecast, the forecast rows);
Nonewhen the run had nothing to predict. - accuracy · accuracy_metric
- The model's test score and the metric it is measured in, picked per task
(e.g.
accuracyfor classification,R2for regression, backtestMAPEfor forecasts).Nonefor causal runs. - driving_factors list[dict]
- Top features by mean absolute SHAP,
[{"feature", "importance"}, ...]. Empty when unavailable (e.g. time-series forecasts). - effect dict | None
- For causal questions only: the estimated effect with
point,ci_low/ci_high,p_value,confidence_gradeand the refutation-test tally. - confirmed_target str
- The column the agent settled on predicting.
- use_case_type str
- How the agent classified the problem (
tabular,time_series,causal). - model Model | None
- Ready to predict with when training succeeded;
Nonefor causal and zero-shot time-series runs. - n_predictions · warnings · job_id
- Row count behind
predictions, non-fatal degradations, and the job handle. - details dict
- The full run report (phases, turns, raw metrics, token usage, timing); populated for staff accounts and in dev mode, otherwise empty.
Notes
print(run) gives a one-glance summary: the answer, the metric, and the top drivers.
qombra.ModelInfo · qombra.PreprocessingResultInfo · qombra.TokenInfo
Lightweight rows returned inside the table-rendering lists (see list_models) and by login().
Attributes
- ModelInfo
model_id,target_column,task_type,model_type,metrics,created_at,created_via.- PreprocessingResultInfo
job_id,summary,n_rows,n_cols,created_at,has_data.- TokenInfo
token,expires_at,email.
Errors
Everything raised by the package derives from qombra.QombraError, so one
except qombra.QombraError catches it all; catch subclasses for targeted handling:
try:
model = qombra.fit(df, target="revenue")
except qombra.AuthenticationError:
qombra.login() # 12h session expired; sign in again, then retry
except qombra.QuotaExceededError as e:
print("usage limit reached:", e) # check qombra.whoami()["limits"]
except qombra.ValidationError as e:
print("bad input:", e.code, e) # machine code + human message
except qombra.JobTimeoutError as e:
print("still running server-side, job:", e.job_id)
| Exception | Raised when |
|---|---|
AuthenticationError | No token, or it expired / was revoked. Subclasses: LoginDeniedError (Deny clicked in the browser), LoginTimeoutError (consent flow timed out). |
QuotaExceededError | An account usage limit is exhausted (analyses, chat messages, output tokens). |
RateLimitedError | Too many requests in a short window; retry later. |
ValidationError | Invalid input: carries a machine-readable .code (e.g. missing_target, insufficient_rows, no_overlapping_features, unsupported_column_type, future_misaligned) and .details. Subclass PayloadTooLargeError: the upload is too large; reduce or batch it. |
NotFoundError | The model / stored result does not exist for this account (e.g. deleted). |
JobFailedError | A server-side run failed: .code (e.g. preprocessing_failed, training_failed, auto_run_failed, irregular_timestamps, engine_unavailable, job_lost after a server restart: retry), .job_id, and any partial .result. |
JobTimeoutError | Your client-side timeout elapsed; the job keeps running server-side (.job_id). |
NetworkError ServerError | Server unreachable / unexpected server failure. Read-style requests are retried automatically before this surfaces. |
Data format & metering
- Dataframes travel as parquet with plain scalar columns only: numbers, booleans, strings, dates,
timestamps, decimals; pandas categoricals are fine. Nested or binary columns are rejected with
unsupported_column_type; mixed-typeobjectcolumns should be cast (e.g.df[col].astype(str)) before upload. - Uploads are size-capped and calls are rate-limited; an oversized upload raises
PayloadTooLargeError(reduce or batch it) and rapid-fire calls raiseRateLimitedError. Row order is preserved end-to-end. - Metering: every call is charged to the same account limits the web app uses:
preprocessingspends LLM output tokens (the AI agent's work) plus one chat message, and is billed once per call however many stages it runs internally.fitcreates one analysis, counted against your analysis limit. QBrain is not an LLM, so training spends no output tokens.auto_runspends all three: one analysis, plus the chat messages and output tokens the agent consumes across the run.analyze,predict,forecast,explainand the listing calls spend no quota; they are rate-limited instead (predictandforecastshare one hourly limit).
qombra.whoami().