Zero-shot tabular machine learning inside DuckDB — classification, regression, synthetic-data generation and imputation with real tabular foundation models (Mitra, TabPFN v2/2.5/3, TabICL, Orion-BiX, TabFM) on ONNX Runtime, no training loop
Installing and Loading
INSTALL anofox_tabfm FROM community;
LOAD anofox_tabfm;
Example
-- Fetch a real tabular foundation model once (Mitra, Apache-2.0, ~300 MB,
-- no license gate). Cached under ~/.cache/anofox-tabfm and reused after.
INSTALL httpfs; LOAD httpfs; -- weights are fetched over HTTPS
CALL tabfm_download('classification', model := 'mitra');
-- Label a few rows; leave the ones you want scored as NULL. The model reads
-- the labelled rows as in-context examples and predicts the rest — no training.
CREATE TABLE iris AS SELECT * FROM VALUES
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(4.9, 3.0, 1.4, 0.2, 'setosa'),
(7.0, 3.2, 4.7, 1.4, 'versicolor'),
(6.4, 3.2, 4.5, 1.5, 'versicolor'),
(6.3, 3.3, 6.0, 2.5, 'virginica'),
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.0, 3.6, 1.4, 0.2, NULL), -- predict me
(6.5, 3.0, 5.8, 2.2, NULL) -- and me
AS t(sepal_len, sepal_wid, petal_len, petal_wid, species);
SELECT petal_len, petal_wid, yhat AS predicted_species, yhat_score
FROM tabfm_classify('iris', 'species', model := 'mitra')
WHERE species IS NULL;
About anofox_tabfm
anofox_tabfm embeds real tabular foundation models — TabPFN-style in-context learners — into DuckDB, so tabular classification and regression become a single SQL statement. There is no training loop, no Python, and no MLOps: the model reads your labelled rows as context and predicts the rest.
Built-in models
Seven models ship in the extension and are selected with model := (or a
SET anofox_tabfm_default_model once per session):
- mitra — AWS AutoGluon (Apache-2.0), no license gate, ~300 MB. A great default.
- tabpfn-v2 — Prior Labs (Apache-2.0, attribution).
- tabicl-v2 — Inria (BSD-3-Clause).
- orion-bix — Lexsi Labs (MIT), no license gate. Classification only.
- tabpfn-v2-5 — Prior Labs TabPFN 2.5. Non-commercial: the weights and their outputs may not be used for commercial or production purposes.
- tabpfn-v3 — Prior Labs TabPFN 3. Non-commercial: testing, evaluation and internal benchmarking only.
- tabfm-v1 — Google TabFM (non-commercial, gated; ~6.6 GB).
SELECT model, license, commercial FROM tabfm_list_models() reports each
model's license and whether it is commercially usable — worth checking
before shipping anything built on one.
Only weight-free computation graphs are bundled — no model weights are
distributed with the extension. You download the weights yourself from
Hugging Face into a local cache (~/.cache/anofox-tabfm), and for a gated
model you first accept its license
(SET anofox_tabfm_accept_hf_license = true). Repositories that Hugging Face
itself gates additionally need a token, supplied with a standard DuckDB
secret:
CREATE SECRET hf (TYPE http, BEARER_TOKEN 'hf_xxx', SCOPE 'https://huggingface.co');
Bring your own model
Register any compatible model entirely from SQL — no external JSON manifest.
Weights can be .safetensors or a native PyTorch .ckpt (read without Python):
CALL tabfm_register_model(
id := 'my-model',
classification_graph := 'model.onnx',
classification_weights := 'model.safetensors',
license := 'apache-2.0');
Synthetic data and imputation
The same in-context engine also runs backwards: instead of predicting one column, it models the whole table as a joint distribution and samples from it.
SELECT * FROM tabfm_generate('customers', 500); -- 500 synthetic rows
CREATE TABLE clean AS SELECT * FROM tabfm_impute('raw'); -- fill every NULL
Generation works column by column, each column sampled conditioned on the ones already generated (the chain rule), so the relationships between columns survive — not just each column's marginal. It needs only classification weights, so it works with every model above, including classification-only ones.
tabfm_impute is the deterministic sibling: it takes the conditional best
estimate rather than sampling, so continuous fills keep full precision and
non-NULL cells are never modified.
On the Prior Labs breast-cancer benchmark (30 features), a classifier given
only synthetic in-context examples scores 97.8% on held-out real rows
against 98.3% for the real training data, preserving correlation structure at
0.97 across all 435 feature pairs. Correlations are somewhat attenuated by the
quantile binning used for continuous columns — see docs/GENERATE.md in the
repository for what the method does and does not preserve. It is not a
differential-privacy mechanism.
Inference
Runs on ONNX Runtime, statically linked into the extension (CPU execution provider). CUDA and ROCm/MIGraphX flavors exist in the source tree for self-builds; this community build ships the portable CPU flavor.
Surface
tabfm_classify/tabfm_regress— zero-shot predict (a single table with NULL targets, or a separatetest :=set)tabfm_generate/tabfm_impute— synthesize rows from a table's joint distribution, or fill its NULL cellstabfm_predict,tabfm_predict_by,tabfm_predict_agg,tabfm_predict_wintabfm_register_model/tabfm_unregister_model— pure-SQL model registrationtabfm_download/tabfm_models/tabfm_list_models/tabfm_load/tabfm_unload/tabfm_remove— all acceptmodel :=tabfm_devices— discover CPU/GPU execution providersSET anofox_tabfm_*settings (default model, license gate, cache dir, threads, device, tracing)
Full function names are anofox_tabfm_* with short tabfm_* aliases. See the
project repository for the full
SQL API and examples.
Added Functions
| function_name | function_type | description | comment | examples |
|---|---|---|---|---|
| __anofox_tabfm_generate_agg | aggregate | NULL | NULL | |
| __anofox_tabfm_impute_agg | aggregate | NULL | NULL | |
| __anofox_tabfm_predict_agg | aggregate | NULL | NULL | |
| __anofox_tabfm_predict_win | aggregate | NULL | NULL | |
| anofox_tabfm_classify | table_macro | Zero-shot tabular classification with the TabFM foundation model. Uses the labelled rows of data as in-context examples to score the rows whose target is NULL (single-relation form) or every row of the test relation (train/test form). Returns one row per scored row with yhat, yhat_score, is_training and (detail mode) a proba MAP. Optional features restricts the feature columns; opts is a MAP of options (seed, softmax_temperature, output_mode, …). |
NULL | [SELECT age, plan, yhat, yhat_score FROM tabfm_classify('customers', 'churned') WHERE churned IS NULL;] |
| anofox_tabfm_devices | table | List the inference devices this build can see (device_id, ep, name, arch, vram, driver, usable). The cpu row always exists; GPU rows appear only in the matching flavor (cuda/rocm) and report usable=false when a device is present but unsupported. | NULL | [SELECT * FROM tabfm_devices();] |
| anofox_tabfm_download | table | Download the TabFM model weights for a task ('classification' or 'regression') from Hugging Face into the local cache. Requires SET anofox_tabfm_accept_hf_license = true. Returns one row per file (file, url, bytes, status). | NULL | [CALL tabfm_download('classification');] |
| anofox_tabfm_generate | table_macro | Generate synthetic rows from the joint distribution of data using a tabular foundation model. Factorizes the table column by column (the chain rule) and samples each column conditioned on the ones already generated, so correlations between columns are preserved rather than each column being drawn independently. Returns n rows with the same columns as data plus synthetic_id. Continuous columns are sampled via quantile bins, so values stay inside the observed range. Costs one model call per column, run sequentially. Options: seed, temperature (higher = more diverse), bins, column_order, model. |
NULL | [SELECT * FROM tabfm_generate('customers', 100);] |
| anofox_tabfm_gpu_precompile | table | Warm the GPU path for a task by compiling the model for a shape bucket ahead of the first predict (on ROCm this builds and caches the .mxr program; a no-op cost on CPU/CUDA). Returns task, rows, features, device, status. | NULL | [CALL tabfm_gpu_precompile('classification', 1000, 50);] |
| anofox_tabfm_impute | table_macro | Fill the NULL cells of data with a tabular foundation model, conditioning each missing value on the other columns of its row. Returns the same columns as data, with non-NULL cells untouched, so it round-trips: CREATE TABLE clean AS SELECT * FROM tabfm_impute('raw'). Unlike tabfm_generate this does not sample — it takes the conditional best estimate (classification argmax, regression point estimate), so continuous columns keep full precision. Optional columns restricts which columns are filled; opts accepts seed, rounds (MICE-style refinement sweeps), model. |
NULL | [SELECT * FROM tabfm_impute('customers', columns := ['income']);] |
| anofox_tabfm_list_models | table | List every model in the registry (built-ins + user manifests), downloaded or not: model, family, capabilities, license, commercial, size regime (max_rows/features/classes), downloaded. | NULL | [SELECT * FROM tabfm_list_models();] |
| anofox_tabfm_load | table | Eagerly load a downloaded TabFM model for a task into memory so the first predict is warm (otherwise the model loads lazily on first use). | NULL | [CALL tabfm_load('classification');] |
| anofox_tabfm_models | table | List the TabFM models known to the local cache (model, task, revision, path, bytes, loaded, license). | NULL | [SELECT * FROM tabfm_models();] |
| anofox_tabfm_register_model | table | Register a model in SQL (no manifest file). Named args: id, classification_graph / regression_graph (path or url to the weight-free ONNX graph), classification_weights / regression_weights, tensor_map (or classification_tensor_map / regression_tensor_map), weights_repo, license, commercial, gate_setting, preprocessing_profile, max_rows / max_features / max_classes. Then use model := ' |
NULL | [CALL tabfm_register_model(id := 'my', classification_graph := '/p/g.onnx', classification_weights := '/p/w.safetensors', tensor_map := '/p/map.json', license := 'apache-2.0');] |
| anofox_tabfm_regress | table_macro | Zero-shot tabular regression with the TabFM foundation model. Uses the rows of data with a known numeric target as in-context examples to predict the target for rows where it is NULL (single-relation form) or every row of the test relation (train/test form). Returns one row per scored row with yhat (yhat_score is NULL for regression). Optional features restricts the feature columns; opts is a MAP of options. |
NULL | [SELECT * FROM tabfm_regress('sold_homes', 'price', test := 'listings');] |
| anofox_tabfm_remove | table | Delete a downloaded TabFM model's weights from the local cache (by task, optionally a specific revision). | NULL | [CALL tabfm_remove('classification');] |
| anofox_tabfm_unload | table | Unload a loaded TabFM model from memory (all models if no task is given), freeing its RAM/VRAM. | NULL | [CALL tabfm_unload('classification');] |
| anofox_tabfm_unregister_model | table | Remove a model registered with tabfm_register_model. Returns model, status. | NULL | [CALL tabfm_unregister_model('my_model');] |
| tabfm_classify | table_macro | Zero-shot tabular classification with the TabFM foundation model. Uses the labelled rows of data as in-context examples to score the rows whose target is NULL (single-relation form) or every row of the test relation (train/test form). Returns one row per scored row with yhat, yhat_score, is_training and (detail mode) a proba MAP. Optional features restricts the feature columns; opts is a MAP of options (seed, softmax_temperature, output_mode, …). |
NULL | [SELECT age, plan, yhat, yhat_score FROM tabfm_classify('customers', 'churned') WHERE churned IS NULL;] |
| tabfm_devices | table | List the inference devices this build can see (device_id, ep, name, arch, vram, driver, usable). The cpu row always exists; GPU rows appear only in the matching flavor (cuda/rocm) and report usable=false when a device is present but unsupported. | NULL | [SELECT * FROM tabfm_devices();] |
| tabfm_download | table | Download the TabFM model weights for a task ('classification' or 'regression') from Hugging Face into the local cache. Requires SET anofox_tabfm_accept_hf_license = true. Returns one row per file (file, url, bytes, status). | NULL | [CALL tabfm_download('classification');] |
| tabfm_generate | table_macro | Generate synthetic rows from the joint distribution of data using a tabular foundation model. Factorizes the table column by column (the chain rule) and samples each column conditioned on the ones already generated, so correlations between columns are preserved rather than each column being drawn independently. Returns n rows with the same columns as data plus synthetic_id. Continuous columns are sampled via quantile bins, so values stay inside the observed range. Costs one model call per column, run sequentially. Options: seed, temperature (higher = more diverse), bins, column_order, model. |
NULL | [SELECT * FROM tabfm_generate('customers', 100);] |
| tabfm_gpu_precompile | table | Warm the GPU path for a task by compiling the model for a shape bucket ahead of the first predict (on ROCm this builds and caches the .mxr program; a no-op cost on CPU/CUDA). Returns task, rows, features, device, status. | NULL | [CALL tabfm_gpu_precompile('classification', 1000, 50);] |
| tabfm_impute | table_macro | Fill the NULL cells of data with a tabular foundation model, conditioning each missing value on the other columns of its row. Returns the same columns as data, with non-NULL cells untouched, so it round-trips: CREATE TABLE clean AS SELECT * FROM tabfm_impute('raw'). Unlike tabfm_generate this does not sample — it takes the conditional best estimate (classification argmax, regression point estimate), so continuous columns keep full precision. Optional columns restricts which columns are filled; opts accepts seed, rounds (MICE-style refinement sweeps), model. |
NULL | [SELECT * FROM tabfm_impute('customers', columns := ['income']);] |
| tabfm_list_models | table | List every model in the registry (built-ins + user manifests), downloaded or not: model, family, capabilities, license, commercial, size regime (max_rows/features/classes), downloaded. | NULL | [SELECT * FROM tabfm_list_models();] |
| tabfm_load | table | Eagerly load a downloaded TabFM model for a task into memory so the first predict is warm (otherwise the model loads lazily on first use). | NULL | [CALL tabfm_load('classification');] |
| tabfm_models | table | List the TabFM models known to the local cache (model, task, revision, path, bytes, loaded, license). | NULL | [SELECT * FROM tabfm_models();] |
| tabfm_register_model | table | Register a model in SQL (no manifest file). Named args: id, classification_graph / regression_graph (path or url to the weight-free ONNX graph), classification_weights / regression_weights, tensor_map (or classification_tensor_map / regression_tensor_map), weights_repo, license, commercial, gate_setting, preprocessing_profile, max_rows / max_features / max_classes. Then use model := ' |
NULL | [CALL tabfm_register_model(id := 'my', classification_graph := '/p/g.onnx', classification_weights := '/p/w.safetensors', tensor_map := '/p/map.json', license := 'apache-2.0');] |
| tabfm_regress | table_macro | Zero-shot tabular regression with the TabFM foundation model. Uses the rows of data with a known numeric target as in-context examples to predict the target for rows where it is NULL (single-relation form) or every row of the test relation (train/test form). Returns one row per scored row with yhat (yhat_score is NULL for regression). Optional features restricts the feature columns; opts is a MAP of options. |
NULL | [SELECT * FROM tabfm_regress('sold_homes', 'price', test := 'listings');] |
| tabfm_remove | table | Delete a downloaded TabFM model's weights from the local cache (by task, optionally a specific revision). | NULL | [CALL tabfm_remove('classification');] |
| tabfm_unload | table | Unload a loaded TabFM model from memory (all models if no task is given), freeing its RAM/VRAM. | NULL | [CALL tabfm_unload('classification');] |
| tabfm_unregister_model | table | Remove a model registered with tabfm_register_model. Returns model, status. | NULL | [CALL tabfm_unregister_model('my_model');] |
Overloaded Functions
This extension does not add any function overloads.
Added Types
This extension does not add any types.
Added Settings
| name | description | input_type | scope | aliases |
|---|---|---|---|---|
| anofox_tabfm_accept_hf_license | Accept the upstream model license (tabfm-non-commercial-v1.0: non-commercial use, no redistribution). Downloads of Google-licensed weights fail without this. | BOOLEAN | GLOBAL | [] |
| anofox_tabfm_cache_dir | Weight cache root directory (default ~/.cache/anofox-tabfm) | VARCHAR | GLOBAL | [] |
| anofox_tabfm_cpu_prepack | Enable ONNX Runtime weight prepacking on the CPU EP: faster matmuls at ~+16% resident memory. | BOOLEAN | GLOBAL | [] |
| anofox_tabfm_default_model | Default model id for tabfm_classify/regress/download/… when model := is not given. '' = resolve to the single-file manifest model, else the sole registered model. | VARCHAR | GLOBAL | [] |
| anofox_tabfm_device | Execution device: auto|cpu|cuda|rocm|coreml ('migraphx' alias). Each flavor errors helpfully on devices it does not carry. | VARCHAR | GLOBAL | [] |
| anofox_tabfm_ep_path | Directory with ONNX Runtime provider / plugin-EP shared libraries | VARCHAR | GLOBAL | [] |
| anofox_tabfm_gpu_precision | MIGraphX compile precision on the ROCm GPU: bf16|fp16|fp32. bf16 (default) runs ~2x faster than fp32 on RDNA4 and halves VRAM/.mxr, keeping fp32's exponent range; fp32 is the accuracy reference. | VARCHAR | GLOBAL | [] |
| anofox_tabfm_max_features | Maximum feature columns per predict call | BIGINT | GLOBAL | [] |
| anofox_tabfm_max_rows | Maximum rows per predict call or group | BIGINT | GLOBAL | [] |
| anofox_tabfm_mxr_source | Directory holding precompiled MIGraphX .mxr programs (offline/CI/shared cache). Before compiling a shape-bucket (~27 min on ROCm), a matching ' |
VARCHAR | GLOBAL | [] |
| anofox_tabfm_threads | ONNX Runtime intra-op thread count for CPU inference | BIGINT | GLOBAL | [] |
| anofox_tabfm_trace_level | Diagnostic verbosity: error|warn|info|debug|trace | VARCHAR | GLOBAL | [] |
| anofox_telemetry_enabled | Enable or disable anonymous usage telemetry | BOOLEAN | GLOBAL | [] |
| anofox_telemetry_key | PostHog API key for telemetry | VARCHAR | GLOBAL | [] |
| datazoo_banner | Show the DataZoo feedback banner when an extension is loaded in an interactive terminal (at most once a day per extension). | BOOLEAN | GLOBAL | [] |