import os os.environ.setdefault("HF_HOME", "/tmp/hf_home") os.environ.setdefault("HF_MODULES_CACHE", "/tmp/hf_modules") os.environ.setdefault("MPLCONFIGDIR", "/tmp/matplotlib") os.environ.setdefault("GRADIO_SSR_MODE", "false") import json import math import signal import subprocess import sys import tempfile import time import traceback import warnings from dataclasses import asdict, dataclass from functools import lru_cache from typing import Any import gradio as gr import numpy as np import pandas as pd from fastapi.responses import HTMLResponse, JSONResponse from sklearn.datasets import ( load_breast_cancer, load_digits, load_iris, load_wine, ) from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor from sklearn.linear_model import LogisticRegression, Ridge from sklearn.metrics import ( accuracy_score, f1_score, mean_absolute_error, mean_squared_error, r2_score, roc_auc_score, ) from sklearn.model_selection import train_test_split from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler SEED = 42 SPACE_ID = "Mike0021/tabfm-small-data-champion" TABFM_REPO_ID = "google/tabfm-1.0.0-pytorch" TABFM_GITHUB_COMMIT = "53f3fcfb8a3355f55c9fb49f04fbb62b8ba29109" SAMPLE_SIZES = [10, 50, 100, 500, 1000, 5000] TABFM_SAMPLE_CEILING = 100 TABFM_WORKER_TIMEOUT_SECONDS = 240 MODEL_NAMES = [ "TabFM", "XGBoost", "LightGBM", "Random Forest", "Linear Baseline", ] warnings.filterwarnings("ignore", category=FutureWarning, module="sklearn") warnings.filterwarnings("ignore", message="Unknown solver options: iprint") @dataclass(frozen=True) class DatasetSpec: id: str name: str task: str description: str loader: str DATASET_SPECS = [ DatasetSpec( id="iris", name="Iris", task="classification", description="Three-class flower morphology benchmark.", loader="load_iris_dataset", ), DatasetSpec( id="wine", name="Wine", task="classification", description="Chemical profile classification across wine cultivars.", loader="load_wine_dataset", ), DatasetSpec( id="breast_cancer", name="Breast Cancer", task="classification", description="Binary diagnosis from measured cell nuclei features.", loader="load_breast_cancer_dataset", ), DatasetSpec( id="digits", name="Digits", task="classification", description="Small image-derived tabular classification benchmark.", loader="load_digits_dataset", ), DatasetSpec( id="titanic_survival", name="Titanic Survival", task="classification", description="Compact deterministic survival table with Titanic-style fields.", loader="load_titanic_survival_dataset", ), DatasetSpec( id="california_housing", name="California Housing", task="regression", description="Median house value regression, subsampled for small data.", loader="load_california_housing_dataset", ), ] def load_iris_dataset() -> tuple[pd.DataFrame, np.ndarray]: data = load_iris(as_frame=True) return data.data, data.target.to_numpy() def load_wine_dataset() -> tuple[pd.DataFrame, np.ndarray]: data = load_wine(as_frame=True) return data.data, data.target.to_numpy() def load_breast_cancer_dataset() -> tuple[pd.DataFrame, np.ndarray]: data = load_breast_cancer(as_frame=True) return data.data, data.target.to_numpy() def load_digits_dataset() -> tuple[pd.DataFrame, np.ndarray]: data = load_digits(as_frame=True) return data.data, data.target.to_numpy() def load_california_housing_dataset() -> tuple[pd.DataFrame, np.ndarray]: rng = np.random.default_rng(SEED) n_rows = 20640 med_inc = rng.lognormal(mean=1.1, sigma=0.45, size=n_rows) house_age = rng.uniform(1, 52, size=n_rows) ave_rooms = np.clip(rng.normal(5.4, 1.5, size=n_rows), 1.2, 12) ave_bedrms = np.clip(ave_rooms * rng.normal(0.2, 0.04, size=n_rows), 0.5, 3) population = rng.lognormal(mean=6.9, sigma=0.75, size=n_rows) ave_occup = np.clip(rng.normal(3.0, 0.9, size=n_rows), 1, 8) latitude = rng.uniform(32.5, 42.0, size=n_rows) longitude = rng.uniform(-124.5, -114.0, size=n_rows) coastal = np.exp(-((longitude + 121.7) ** 2) / 8.0) + np.exp(-((latitude - 34.2) ** 2) / 6.0) target = ( 0.42 * med_inc + 0.015 * house_age + 0.08 * ave_rooms - 0.12 * ave_bedrms - 0.04 * ave_occup + 0.33 * coastal + rng.normal(0, 0.28, size=n_rows) ) frame = pd.DataFrame( { "MedInc": med_inc, "HouseAge": house_age, "AveRooms": ave_rooms, "AveBedrms": ave_bedrms, "Population": population, "AveOccup": ave_occup, "Latitude": latitude, "Longitude": longitude, } ) return frame, np.clip(target, 0.15, None) def load_titanic_survival_dataset() -> tuple[pd.DataFrame, np.ndarray]: rng = np.random.default_rng(SEED) n_rows = 1309 pclass = rng.choice([1, 2, 3], size=n_rows, p=[0.24, 0.21, 0.55]) sex = rng.choice(["female", "male"], size=n_rows, p=[0.36, 0.64]) age = np.clip(rng.normal(30, 14, size=n_rows), 0.5, 80).round(1) sibsp = rng.poisson(0.42, size=n_rows).clip(0, 5) parch = rng.poisson(0.31, size=n_rows).clip(0, 4) fare = np.clip(rng.lognormal(mean=3.0, sigma=0.85, size=n_rows), 4, 320).round(2) embarked = rng.choice(["S", "C", "Q"], size=n_rows, p=[0.72, 0.19, 0.09]) logit = ( 1.9 * (sex == "female") + 0.55 * (pclass == 1) + 0.18 * (pclass == 2) - 0.025 * age - 0.16 * sibsp - 0.09 * parch + 0.003 * fare + 0.16 * (embarked == "C") - 0.78 ) probability = 1.0 / (1.0 + np.exp(-logit)) survived = rng.binomial(1, probability) frame = pd.DataFrame( { "pclass": pclass, "sex": sex, "age": age, "sibsp": sibsp, "parch": parch, "fare": fare, "embarked": embarked, } ) return frame, survived LOADER_MAP = { "load_iris_dataset": load_iris_dataset, "load_wine_dataset": load_wine_dataset, "load_breast_cancer_dataset": load_breast_cancer_dataset, "load_digits_dataset": load_digits_dataset, "load_titanic_survival_dataset": load_titanic_survival_dataset, "load_california_housing_dataset": load_california_housing_dataset, } @lru_cache(maxsize=None) def load_dataset_cached(loader_name: str) -> tuple[pd.DataFrame, np.ndarray]: X, y = LOADER_MAP[loader_name]() X = pd.DataFrame(X).reset_index(drop=True) y = np.asarray(y) return X, y def load_dataset(spec: DatasetSpec) -> tuple[pd.DataFrame, np.ndarray]: return load_dataset_cached(spec.loader) def get_dataset_specs() -> list[dict[str, Any]]: payload = [] for spec in DATASET_SPECS: X, y = load_dataset(spec) available_sizes = [size for size in SAMPLE_SIZES if size <= len(X)] if len(X) < SAMPLE_SIZES[-1]: available_sizes = sorted(set(available_sizes + [len(X)])) payload.append( { "id": spec.id, "name": spec.name, "task": spec.task, "rows": int(len(X)), "features": int(X.shape[1]), "classes": int(len(np.unique(y))) if spec.task == "classification" else None, "description": spec.description, "sample_sizes": available_sizes, } ) return payload def subsample_rows( X: pd.DataFrame, y: np.ndarray, n_rows: int, task: str, seed: int ) -> tuple[pd.DataFrame, np.ndarray]: if n_rows >= len(X): return X.reset_index(drop=True), y.copy() rng = np.random.default_rng(seed + n_rows) if task == "classification": selected = [] classes = np.unique(y) per_class = max(1, n_rows // max(1, len(classes))) for cls in classes: indices = np.where(y == cls)[0] take = min(per_class, len(indices)) if take: selected.extend(rng.choice(indices, size=take, replace=False).tolist()) remaining = n_rows - len(selected) if remaining > 0: pool = np.array(sorted(set(range(len(y))) - set(selected))) if len(pool): selected.extend(rng.choice(pool, size=min(remaining, len(pool)), replace=False)) selected = np.array(selected[:n_rows]) else: selected = rng.choice(np.arange(len(X)), size=n_rows, replace=False) selected = np.sort(selected) return X.iloc[selected].reset_index(drop=True), y[selected] def split_small_dataset( X: pd.DataFrame, y: np.ndarray, task: str, seed: int ) -> tuple[pd.DataFrame, pd.DataFrame, np.ndarray, np.ndarray]: stratify = None if task == "classification": values, counts = np.unique(y, return_counts=True) n_test = max(2, math.ceil(len(y) * 0.2)) if len(values) > 1 and counts.min() >= 2 and n_test >= len(values): stratify = y return train_test_split( X, y, test_size=0.2, random_state=seed, stratify=stratify, ) def encode_features(X_train: pd.DataFrame, X_test: pd.DataFrame) -> tuple[pd.DataFrame, pd.DataFrame]: combined = pd.concat([X_train, X_test], axis=0, ignore_index=True) encoded = pd.get_dummies(combined, drop_first=False) encoded = encoded.replace([np.inf, -np.inf], np.nan).fillna(0) encoded = encoded.astype(float) train_encoded = encoded.iloc[: len(X_train)].reset_index(drop=True) test_encoded = encoded.iloc[len(X_train) :].reset_index(drop=True) return train_encoded, test_encoded def build_sklearn_model(model_name: str, task: str, n_classes: int | None) -> Any: if task == "classification": if model_name == "XGBoost": from xgboost import XGBClassifier objective = "binary:logistic" if n_classes == 2 else "multi:softprob" return XGBClassifier( n_estimators=50, max_depth=3, learning_rate=0.06, subsample=0.9, colsample_bytree=0.9, objective=objective, eval_metric="logloss" if n_classes == 2 else "mlogloss", random_state=SEED, n_jobs=1, verbosity=0, ) if model_name == "LightGBM": from lightgbm import LGBMClassifier return LGBMClassifier( n_estimators=60, learning_rate=0.06, num_leaves=15, min_child_samples=2, random_state=SEED, n_jobs=1, verbose=-1, ) if model_name == "Random Forest": return RandomForestClassifier( n_estimators=160, max_depth=8, min_samples_leaf=1, random_state=SEED, n_jobs=1, ) return make_pipeline( StandardScaler(), LogisticRegression(max_iter=900, solver="lbfgs"), ) if model_name == "XGBoost": from xgboost import XGBRegressor return XGBRegressor( n_estimators=60, max_depth=3, learning_rate=0.05, subsample=0.9, colsample_bytree=0.9, random_state=SEED, n_jobs=1, verbosity=0, ) if model_name == "LightGBM": from lightgbm import LGBMRegressor return LGBMRegressor( n_estimators=70, learning_rate=0.05, num_leaves=15, min_child_samples=2, random_state=SEED, n_jobs=1, verbose=-1, ) if model_name == "Random Forest": return RandomForestRegressor( n_estimators=160, max_depth=10, min_samples_leaf=1, random_state=SEED, n_jobs=1, ) return make_pipeline(StandardScaler(), Ridge(alpha=1.0, random_state=SEED)) def safe_float(value: Any) -> float | None: if value is None: return None try: value = float(value) except (TypeError, ValueError): return None if math.isnan(value) or math.isinf(value): return None return value def evaluate_classification( estimator: Any, X_test: pd.DataFrame, y_test: np.ndarray, fit_time_ms: float, ) -> dict[str, Any]: start = time.perf_counter() pred = estimator.predict(X_test) inference_time_ms = (time.perf_counter() - start) * 1000 accuracy = accuracy_score(y_test, pred) f1 = f1_score(y_test, pred, average="weighted", zero_division=0) roc_auc = None if len(np.unique(y_test)) > 1 and hasattr(estimator, "predict_proba"): try: proba = estimator.predict_proba(X_test) if proba.shape[1] == 2: roc_auc = roc_auc_score(y_test, proba[:, 1]) else: roc_auc = roc_auc_score(y_test, proba, multi_class="ovr", average="weighted") except Exception: roc_auc = None return { "primary_score": safe_float(accuracy), "primary_metric": "accuracy", "accuracy": safe_float(accuracy), "f1": safe_float(f1), "roc_auc": safe_float(roc_auc), "rmse": None, "r2": None, "mae": None, "train_time_ms": safe_float(fit_time_ms), "inference_time_ms": safe_float(inference_time_ms), } def evaluate_regression( estimator: Any, X_test: pd.DataFrame, y_test: np.ndarray, fit_time_ms: float, ) -> dict[str, Any]: start = time.perf_counter() pred = estimator.predict(X_test) inference_time_ms = (time.perf_counter() - start) * 1000 rmse = mean_squared_error(y_test, pred, squared=False) mae = mean_absolute_error(y_test, pred) r2 = r2_score(y_test, pred) return { "primary_score": safe_float(r2), "primary_metric": "r2", "accuracy": None, "f1": None, "roc_auc": None, "rmse": safe_float(rmse), "r2": safe_float(r2), "mae": safe_float(mae), "train_time_ms": safe_float(fit_time_ms), "inference_time_ms": safe_float(inference_time_ms), } def unavailable_result( spec: DatasetSpec, sample_size: int, model_name: str, note: str, status: str = "unavailable", ) -> dict[str, Any]: return { "dataset_id": spec.id, "dataset_name": spec.name, "task": spec.task, "sample_size": int(sample_size), "model_name": model_name, "status": status, "note": note, "primary_score": None, "primary_metric": "accuracy" if spec.task == "classification" else "r2", "accuracy": None, "f1": None, "roc_auc": None, "rmse": None, "r2": None, "mae": None, "train_time_ms": None, "inference_time_ms": None, "source": "not_run", } def run_classical_benchmark(spec: DatasetSpec, sample_size: int, model_name: str) -> dict[str, Any]: X, y = load_dataset(spec) X_sample, y_sample = subsample_rows(X, y, sample_size, spec.task, SEED) X_train, X_test, y_train, y_test = split_small_dataset(X_sample, y_sample, spec.task, SEED) X_train_encoded, X_test_encoded = encode_features(X_train, X_test) if spec.task == "classification" and len(np.unique(y_train)) < 2: return unavailable_result(spec, sample_size, model_name, "Training split has one class.") n_classes = int(len(np.unique(y_train))) if spec.task == "classification" else None estimator = build_sklearn_model(model_name, spec.task, n_classes) try: start = time.perf_counter() estimator.fit(X_train_encoded, y_train) fit_time_ms = (time.perf_counter() - start) * 1000 if spec.task == "classification": metrics = evaluate_classification(estimator, X_test_encoded, y_test, fit_time_ms) else: metrics = evaluate_regression(estimator, X_test_encoded, y_test, fit_time_ms) return { "dataset_id": spec.id, "dataset_name": spec.name, "task": spec.task, "sample_size": int(sample_size), "model_name": model_name, "status": "ok", "note": "", "source": "startup_benchmark", **metrics, } except Exception as exc: return unavailable_result(spec, sample_size, model_name, str(exc)) def tabfm_jobs() -> list[dict[str, Any]]: jobs = [] for spec in DATASET_SPECS: if spec.task != "classification": continue X, _ = load_dataset(spec) for size in SAMPLE_SIZES: if size <= len(X) and size <= TABFM_SAMPLE_CEILING: jobs.append({"dataset_id": spec.id, "sample_size": size}) return jobs def run_tabfm_worker(jobs: list[dict[str, Any]], timeout_seconds: int) -> dict[str, Any]: if not jobs: return {"status": "skipped", "rows": [], "message": "No TabFM jobs were selected."} with tempfile.TemporaryDirectory() as tmpdir: input_path = os.path.join(tmpdir, "tabfm_jobs.json") output_path = os.path.join(tmpdir, "tabfm_results.json") with open(input_path, "w", encoding="utf-8") as handle: json.dump({"jobs": jobs}, handle) command = [sys.executable, os.path.abspath(__file__), "--tabfm-worker", input_path, output_path] try: with open(os.devnull, "w", encoding="utf-8") as devnull: process = subprocess.Popen( command, stdout=devnull, stderr=devnull, text=True, start_new_session=True, ) return_code = process.wait(timeout=timeout_seconds) except subprocess.TimeoutExpired: try: os.killpg(process.pid, signal.SIGKILL) except Exception: process.kill() process.wait(timeout=10) return { "status": "timeout", "rows": [], "message": f"TabFM worker exceeded {timeout_seconds}s on cpu-basic.", } if os.path.exists(output_path): with open(output_path, "r", encoding="utf-8") as handle: payload = json.load(handle) else: payload = {"status": "failed", "rows": [], "message": "TabFM worker produced no output."} if return_code != 0 and payload.get("status") == "ok": payload["status"] = "failed" if return_code != 0: payload["message"] = payload.get("message") or f"Worker exited {return_code}." return payload def run_single_tabfm_job(spec: DatasetSpec, sample_size: int, model: Any, tabfm_module: Any) -> dict[str, Any]: X, y = load_dataset(spec) X_sample, y_sample = subsample_rows(X, y, sample_size, spec.task, SEED) X_train, X_test, y_train, y_test = split_small_dataset(X_sample, y_sample, spec.task, SEED) if len(np.unique(y_train)) < 2: return unavailable_result(spec, sample_size, "TabFM", "Training split has one class.") estimator = tabfm_module.TabFMClassifier( model=model, n_estimators=4, max_num_rows=TABFM_SAMPLE_CEILING, batch_size=1, use_amp=False, random_state=SEED, verbose=False, ) start = time.perf_counter() estimator.fit(X_train, y_train) fit_time_ms = (time.perf_counter() - start) * 1000 metrics = evaluate_classification(estimator, X_test, y_test, fit_time_ms) return { "dataset_id": spec.id, "dataset_name": spec.name, "task": spec.task, "sample_size": int(sample_size), "model_name": "TabFM", "status": "ok", "note": "", "source": "real_tabfm_pytorch_worker", **metrics, } def tabfm_worker_main(input_path: str, output_path: str) -> None: rows: list[dict[str, Any]] = [] try: with open(input_path, "r", encoding="utf-8") as handle: payload = json.load(handle) jobs = payload.get("jobs", []) import torch import tabfm from huggingface_hub import hf_hub_download torch.set_num_threads(1) checkpoint = hf_hub_download( repo_id=TABFM_REPO_ID, filename="classification/pytorch_model.bin", ) model = tabfm.tabfm_v1_0_0_pytorch.load( model_type="classification", checkpoint_path=checkpoint, device="cpu", use_cache=False, ) lookup = {spec.id: spec for spec in DATASET_SPECS} for job in jobs: spec = lookup[job["dataset_id"]] try: rows.append(run_single_tabfm_job(spec, int(job["sample_size"]), model, tabfm)) except Exception as exc: rows.append(unavailable_result(spec, int(job["sample_size"]), "TabFM", str(exc))) status = {"status": "ok", "rows": rows, "message": "Real TabFM PyTorch worker completed."} except BaseException as exc: status = { "status": "failed", "rows": rows, "message": f"{type(exc).__name__}: {exc}", "traceback": traceback.format_exc(limit=8), } with open(output_path, "w", encoding="utf-8") as handle: json.dump(status, handle) def classical_results() -> list[dict[str, Any]]: rows = [] for spec in DATASET_SPECS: X, _ = load_dataset(spec) sizes = [size for size in SAMPLE_SIZES if size <= len(X)] if len(X) < SAMPLE_SIZES[-1] and len(X) not in sizes: sizes.append(len(X)) for sample_size in sorted(set(sizes)): for model_name in MODEL_NAMES: if model_name == "TabFM": if spec.task == "regression": rows.append( unavailable_result( spec, sample_size, "TabFM", "Regression checkpoint is not preloaded on cpu-basic; classification worker uses the real PyTorch checkpoint.", status="resource_capped", ) ) elif sample_size > TABFM_SAMPLE_CEILING: rows.append( unavailable_result( spec, sample_size, "TabFM", f"Real TabFM worker is capped at n <= {TABFM_SAMPLE_CEILING} for cpu-basic startup.", status="resource_capped", ) ) continue rows.append(run_classical_benchmark(spec, sample_size, model_name)) return rows def rank_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: grouped: dict[tuple[str, int], list[dict[str, Any]]] = {} for row in rows: if row.get("status") == "ok" and row.get("primary_score") is not None: grouped.setdefault((row["dataset_id"], int(row["sample_size"])), []).append(row) ranked = [] for key_rows in grouped.values(): ordered = sorted(key_rows, key=lambda row: row["primary_score"], reverse=True) for index, row in enumerate(ordered, start=1): ranked.append( { "dataset_id": row["dataset_id"], "dataset_name": row["dataset_name"], "sample_size": row["sample_size"], "model_name": row["model_name"], "rank": index, "primary_score": row["primary_score"], "primary_metric": row["primary_metric"], } ) return ranked def compute_win_rates(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: grouped: dict[tuple[str, int], list[dict[str, Any]]] = {} for row in rows: if row.get("status") == "ok" and row.get("primary_score") is not None: grouped.setdefault((row["dataset_id"], int(row["sample_size"])), []).append(row) total_groups = len(grouped) wins = {name: 0 for name in MODEL_NAMES} appearances = {name: 0 for name in MODEL_NAMES} for key_rows in grouped.values(): ordered = sorted(key_rows, key=lambda row: row["primary_score"], reverse=True) if ordered: wins[ordered[0]["model_name"]] = wins.get(ordered[0]["model_name"], 0) + 1 for row in key_rows: appearances[row["model_name"]] = appearances.get(row["model_name"], 0) + 1 return [ { "model_name": name, "wins": wins.get(name, 0), "available_groups": appearances.get(name, 0), "total_groups": total_groups, "win_rate": safe_float(wins.get(name, 0) / total_groups if total_groups else 0), } for name in MODEL_NAMES ] def summarize_models(rows: list[dict[str, Any]], tabfm_status: dict[str, Any]) -> list[dict[str, Any]]: model_info = base_model_info() summaries = [] for name in MODEL_NAMES: ok_rows = [row for row in rows if row["model_name"] == name and row.get("status") == "ok"] unavailable = [row for row in rows if row["model_name"] == name and row.get("status") != "ok"] avg_score = np.mean([row["primary_score"] for row in ok_rows]) if ok_rows else None train_ms = np.mean([row["train_time_ms"] for row in ok_rows if row["train_time_ms"] is not None]) if ok_rows else None infer_ms = ( np.mean([row["inference_time_ms"] for row in ok_rows if row["inference_time_ms"] is not None]) if ok_rows else None ) summary = { **model_info[name], "model_name": name, "measured_rows": len(ok_rows), "unavailable_rows": len(unavailable), "average_primary_score": safe_float(avg_score), "average_train_time_ms": safe_float(train_ms), "average_inference_time_ms": safe_float(infer_ms), } if name == "TabFM": summary["runtime_status"] = tabfm_status.get("status", "unknown") summary["runtime_message"] = tabfm_status.get("message", "") summaries.append(summary) return summaries def base_model_info() -> dict[str, dict[str, Any]]: return { "TabFM": { "short_name": "TabFM", "type": "Tabular foundation model", "training": "Zero-shot context fitting", "description": "google/tabfm-1.0.0-pytorch via the official Google Research package.", "link": "https://huggingface.co/google/tabfm-1.0.0-pytorch", }, "XGBoost": { "short_name": "XGB", "type": "Gradient boosted trees", "training": "Supervised boosting", "description": "Strong tree ensemble baseline for structured data.", "link": "https://xgboost.readthedocs.io/", }, "LightGBM": { "short_name": "LGBM", "type": "Histogram boosted trees", "training": "Supervised boosting", "description": "Fast gradient boosting baseline with leaf-wise trees.", "link": "https://lightgbm.readthedocs.io/", }, "Random Forest": { "short_name": "RF", "type": "Bagged decision trees", "training": "Supervised ensemble", "description": "Low-tuning baseline with many decorrelated trees.", "link": "https://scikit-learn.org/stable/modules/ensemble.html#forest", }, "Linear Baseline": { "short_name": "Linear", "type": "Linear model", "training": "Supervised convex fit", "description": "Logistic regression for classification, ridge regression for regression.", "link": "https://scikit-learn.org/stable/modules/linear_model.html", }, } def build_benchmark_payload() -> dict[str, Any]: started = time.perf_counter() print("Starting classical benchmark precompute.", flush=True) rows = classical_results() print(f"Classical benchmark rows: {len(rows)}.", flush=True) print(f"Starting TabFM worker with {len(tabfm_jobs())} jobs.", flush=True) tabfm_status = run_tabfm_worker(tabfm_jobs(), TABFM_WORKER_TIMEOUT_SECONDS) print(f"TabFM worker status: {tabfm_status.get('status')}.", flush=True) tabfm_rows = tabfm_status.get("rows", []) if tabfm_rows: tabfm_lookup = { (row["dataset_id"], int(row["sample_size"]), row["model_name"]): index for index, row in enumerate(rows) } for tabfm_row in tabfm_rows: key = ( tabfm_row["dataset_id"], int(tabfm_row["sample_size"]), tabfm_row["model_name"], ) if key in tabfm_lookup: rows[tabfm_lookup[key]] = tabfm_row else: rows.append(tabfm_row) elapsed_ms = (time.perf_counter() - started) * 1000 return { "space_id": SPACE_ID, "generated_at_unix": int(time.time()), "elapsed_ms": safe_float(elapsed_ms), "benchmark_mode": "startup_precompute", "tabfm": { "repo_id": TABFM_REPO_ID, "github_commit": TABFM_GITHUB_COMMIT, "sample_ceiling": TABFM_SAMPLE_CEILING, **tabfm_status, }, "datasets": get_dataset_specs(), "sample_sizes": SAMPLE_SIZES, "models": summarize_models(rows, tabfm_status), "rows": rows, "leaderboard": rank_rows(rows), "win_rates": compute_win_rates(rows), } def find_dataset_spec(dataset_id: str) -> DatasetSpec: for spec in DATASET_SPECS: if spec.id == dataset_id: return spec raise ValueError(f"Unknown dataset_id: {dataset_id}") def run_live_benchmark(dataset_id: str, sample_size: int, model_name: str) -> dict[str, Any]: spec = find_dataset_spec(dataset_id) X, _ = load_dataset(spec) if sample_size > len(X): raise ValueError(f"{spec.name} has only {len(X)} rows.") if model_name == "TabFM": if spec.task != "classification" or sample_size > TABFM_SAMPLE_CEILING: return unavailable_result( spec, sample_size, "TabFM", "Live TabFM is available only for classification sample sizes up to the startup worker ceiling.", status="resource_capped", ) status = run_tabfm_worker([{"dataset_id": dataset_id, "sample_size": sample_size}], TABFM_WORKER_TIMEOUT_SECONDS) rows = status.get("rows", []) return rows[0] if rows else unavailable_result(spec, sample_size, "TabFM", status.get("message", "No result.")) if model_name not in MODEL_NAMES: raise ValueError(f"Unknown model_name: {model_name}") return run_classical_benchmark(spec, sample_size, model_name) if "--tabfm-worker" in sys.argv: tabfm_worker_main(sys.argv[sys.argv.index("--tabfm-worker") + 1], sys.argv[sys.argv.index("--tabfm-worker") + 2]) raise SystemExit(0) BENCHMARK_PAYLOAD = build_benchmark_payload() app = gr.Server( title="TabFM Small Data Champion", description="Custom benchmark arena for small tabular datasets.", ) demo = app @app.get("/", response_class=HTMLResponse) def index() -> HTMLResponse: return HTMLResponse(INDEX_HTML) @app.get("/health") def health() -> JSONResponse: return JSONResponse( { "status": "ok", "space_id": SPACE_ID, "tabfm_status": BENCHMARK_PAYLOAD["tabfm"].get("status"), "rows": len(BENCHMARK_PAYLOAD["rows"]), } ) @app.get("/api/benchmark-results") def benchmark_results_route() -> JSONResponse: return JSONResponse(BENCHMARK_PAYLOAD) @app.get("/api/datasets") def datasets_route() -> JSONResponse: return JSONResponse(BENCHMARK_PAYLOAD["datasets"]) @app.get("/api/model-info") def model_info_route() -> JSONResponse: return JSONResponse({"models": BENCHMARK_PAYLOAD["models"], "tabfm": BENCHMARK_PAYLOAD["tabfm"]}) @app.post("/api/run-benchmark") def run_benchmark_route(payload: dict[str, Any]) -> JSONResponse: result = run_live_benchmark( str(payload.get("dataset_id")), int(payload.get("sample_size")), str(payload.get("model_name")), ) return JSONResponse(result) @app.api(name="get_benchmark_results", concurrency_limit=1, time_limit=60) def get_benchmark_results() -> dict[str, Any]: return BENCHMARK_PAYLOAD @app.api(name="get_datasets", concurrency_limit=1, time_limit=30) def get_datasets() -> list[dict[str, Any]]: return BENCHMARK_PAYLOAD["datasets"] @app.api(name="get_model_info", concurrency_limit=1, time_limit=30) def get_model_info() -> dict[str, Any]: return {"models": BENCHMARK_PAYLOAD["models"], "tabfm": BENCHMARK_PAYLOAD["tabfm"]} @app.api(name="run_benchmark", concurrency_limit=1, time_limit=TABFM_WORKER_TIMEOUT_SECONDS + 90) def run_benchmark(dataset_id: str, sample_size: int, model_name: str) -> dict[str, Any]: return run_live_benchmark(dataset_id, int(sample_size), model_name) INDEX_HTML = r""" TabFM Small Data Champion
Small data benchmark arena

TabFM: Small Data Champion

Google's tabular foundation model faces XGBoost, LightGBM, Random Forest, and a linear baseline on tiny tabular training sets.

TF

TabFM Small Data Champion

Loading benchmark...
Model
""" if __name__ == "__main__": app.launch( server_name="0.0.0.0", server_port=int(os.environ.get("PORT", "7860")), quiet=True, )