From f62cc786ede9bf9b5c2dd283e3cc18a99b9f608f Mon Sep 17 00:00:00 2001 From: Tyler Riccardi <247895347+tylrcc@users.noreply.github.com> Date: Wed, 11 Nov 2026 22:35:20 +0000 Subject: [PATCH] docs: add executable quickstart notebook with Colab badges examples/quickstart.ipynb runs the quickstart end to end with its outputs kept: install tabctx[standalone,tabicl,client], start python -m tabctx.serve in the background (TABCTX_BACKEND=tabicl), fit credit-g with TabctxClassifier and predict, fit a regressor and show predict_quantiles, then list and delete the contexts and stop the server. An Open in Colab badge linking to the notebook is added to the README Quickstart section and to docs/getting-started/quickstart.md. --- README.md | 6 +- docs/getting-started/quickstart.md | 6 +- examples/quickstart.ipynb | 457 +++++++++++++++++++++++++++++ 3 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 examples/quickstart.ipynb diff --git a/README.md b/README.md index f002986..d74d67e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,11 @@ own GPUs. ## Quickstart -Run a server on your laptop (CPU works; it uses the GPU if there is one): +[](https://colab.research.google.com/github/VectorInstitute/tabctx/blob/main/examples/quickstart.ipynb) + +Run the whole quickstart in your browser with the +[notebook](examples/quickstart.ipynb), or on your laptop (CPU works; it +uses the GPU if there is one): ```bash pip install "tabctx[standalone,tabicl,client]" diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index f619dc5..45cbcfa 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -1,8 +1,12 @@ # Quickstart +[](https://colab.research.google.com/github/VectorInstitute/tabctx/blob/main/examples/quickstart.ipynb) + Run a tabctx server on your laptop, fit a real dataset and predict against it. A CPU is enough; the server uses a GPU if it finds one. -tabctx needs Python 3.12 or newer. +tabctx needs Python 3.12 or newer. Prefer a notebook? The +[quickstart notebook](https://github.com/VectorInstitute/tabctx/blob/main/examples/quickstart.ipynb) +runs this whole page end to end. ## 1. Install and start a server diff --git a/examples/quickstart.ipynb b/examples/quickstart.ipynb new file mode 100644 index 0000000..d0b4e50 --- /dev/null +++ b/examples/quickstart.ipynb @@ -0,0 +1,457 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cfe05809", + "metadata": {}, + "source": [ + "# tabctx quickstart\n", + "\n", + "Fit a table once, keep it as a cached *context* on a server, and predict against it with a scikit-learn-style API. This notebook runs the whole flow end to end: install, start a server (CPU is fine), classify, regress with prediction quantiles, and manage contexts." + ] + }, + { + "cell_type": "markdown", + "id": "4eb6943b", + "metadata": {}, + "source": [ + "## 1. Install" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "ac7b3069", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:32:10.461627Z", + "iopub.status.busy": "2026-11-11T22:32:10.461448Z", + "iopub.status.idle": "2026-11-11T22:32:14.363213Z", + "shell.execute_reply": "2026-11-11T22:32:14.362009Z" + } + }, + "outputs": [], + "source": [ + "!pip install -q \"tabctx[standalone,tabicl,client]\"" + ] + }, + { + "cell_type": "markdown", + "id": "409f9924", + "metadata": {}, + "source": [ + "## 2. Start a server\n", + "\n", + "The server hosts the TabICL model. The first start downloads the TabICLv2 weights (BSD-3, no account needed). We start it in the background and wait until it answers." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "069dd645", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:32:14.366317Z", + "iopub.status.busy": "2026-11-11T22:32:14.366064Z", + "iopub.status.idle": "2026-11-11T22:33:44.642958Z", + "shell.execute_reply": "2026-11-11T22:33:44.642469Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'data': [{'id': 'tabicl-v2', 'object': 'model', 'default': True}]}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import json\n", + "import os\n", + "import subprocess\n", + "import sys\n", + "import time\n", + "import urllib.request\n", + "\n", + "env = {**os.environ, \"TABCTX_BACKEND\": \"tabicl\"}\n", + "server = subprocess.Popen(\n", + " [sys.executable, \"-m\", \"tabctx.serve\"],\n", + " env=env,\n", + " stdout=subprocess.DEVNULL,\n", + " stderr=subprocess.DEVNULL,\n", + ")\n", + "\n", + "models = None\n", + "for _ in range(180):\n", + " try:\n", + " with urllib.request.urlopen(\"http://127.0.0.1:8000/v1/models\", timeout=2) as resp:\n", + " models = json.load(resp)\n", + " break\n", + " except Exception:\n", + " time.sleep(5)\n", + "\n", + "assert models is not None, \"server did not come up\"\n", + "models" + ] + }, + { + "cell_type": "markdown", + "id": "2b5d87c9", + "metadata": {}, + "source": [ + "## 3. Fit once, predict many (classification)\n", + "\n", + "`fit` sends the table to the server, which encodes it into a cached context. Every later `predict` / `predict_proba` reuses that context." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f2c406ce", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:33:44.728917Z", + "iopub.status.busy": "2026-11-11T22:33:44.728571Z", + "iopub.status.idle": "2026-11-11T22:34:44.680054Z", + "shell.execute_reply": "2026-11-11T22:34:44.678987Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "context id: sklearn-93906881b2b76a20dd1a638b8bf37862\n" + ] + } + ], + "source": [ + "from sklearn.datasets import fetch_openml\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "from tabctx import TabctxClassifier, TabctxClient\n", + "\n", + "X, y = fetch_openml(\"credit-g\", version=1, as_frame=True, return_X_y=True)\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)\n", + "\n", + "client = TabctxClient(\"http://127.0.0.1:8000\")\n", + "clf = TabctxClassifier(client=client)\n", + "clf.fit(X_train, y_train)\n", + "print(\"context id:\", clf.dataset_id_)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fde60009", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:34:44.699083Z", + "iopub.status.busy": "2026-11-11T22:34:44.698816Z", + "iopub.status.idle": "2026-11-11T22:34:52.212283Z", + "shell.execute_reply": "2026-11-11T22:34:52.210403Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "accuracy: 0.772\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[0.7023325 , 0.29766747],\n", + " [0.05054151, 0.94945848],\n", + " [0.04760469, 0.95239532],\n", + " [0.26294938, 0.73705065],\n", + " [0.39968097, 0.60031903]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(\"accuracy:\", clf.score(X_test, y_test))\n", + "clf.predict_proba(X_test[:5])" + ] + }, + { + "cell_type": "markdown", + "id": "9d7973c2", + "metadata": {}, + "source": [ + "## 4. Regression with prediction quantiles\n", + "\n", + "`TabctxRegressor.predict_quantiles` returns predictive quantiles for each row, not just a point estimate. (The diabetes dataset ships with scikit-learn, so this cell needs no download.)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "06969f36", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:34:52.215051Z", + "iopub.status.busy": "2026-11-11T22:34:52.214816Z", + "iopub.status.idle": "2026-11-11T22:35:02.351567Z", + "shell.execute_reply": "2026-11-11T22:35:02.350755Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "context id: sklearn-aea702693a87d2751cc473edb459f246\n" + ] + }, + { + "data": { + "text/plain": [ + "array([164.15979004, 143.35258484, 152.58087158, 130.20314026,\n", + " 195.56369019])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.datasets import load_diabetes\n", + "\n", + "from tabctx import TabctxRegressor\n", + "\n", + "data = load_diabetes(as_frame=True)\n", + "Xr, yr = data.data, data.target\n", + "Xr_train, Xr_test = Xr.iloc[:-100], Xr.iloc[-100:]\n", + "yr_train, yr_test = yr.iloc[:-100], yr.iloc[-100:]\n", + "\n", + "reg = TabctxRegressor(client=client)\n", + "reg.fit(Xr_train, yr_train)\n", + "print(\"context id:\", reg.dataset_id_)\n", + "reg.predict(Xr_test[:5])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a01752e5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-11-11T22:35:02.353893Z", + "iopub.status.busy": "2026-11-11T22:35:02.353630Z", + "iopub.status.idle": "2026-11-11T22:35:02.958799Z", + "shell.execute_reply": "2026-11-11T22:35:02.957944Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
| \n", + " | q5 | \n", + "q50 | \n", + "q95 | \n", + "
|---|---|---|---|
| 0 | \n", + "69.302078 | \n", + "160.332001 | \n", + "269.507080 | \n", + "
| 1 | \n", + "55.275356 | \n", + "138.298859 | \n", + "248.152664 | \n", + "
| 2 | \n", + "62.262737 | \n", + "149.525345 | \n", + "253.321518 | \n", + "
| 3 | \n", + "52.836693 | \n", + "122.921402 | \n", + "230.515656 | \n", + "
| 4 | \n", + "94.553528 | \n", + "195.324875 | \n", + "295.893463 | \n", + "