Quick Start | Documentation | CLI | Dashboard | llms-full.txt | Starter Kit | AI Coding Skill | Discord
Make Building Multimodal AI Data Apps Dead Simple
Pixeltable is the unified multimodal backend for AI data apps. One Python API: store media, run models, index embeddings, serve endpoints, and version everything in a single system instead of gluing together blob storage, a vector DB, an orchestrator, and edge functions. Chunking, embeddings, agents, and serving run from computed columns on insert, not glue scripts you maintain separately. Transactions, caching, retries, and observability are built in. Extend with @pxt.udf, @pxt.uda, and @pxt.query.
Core Capabilities
Expand any row for what Pixeltable replaces, a quick example, and doc links. Examples assume import pixeltable as pxt.
Store: unified multimodal interface
pxt.Image, pxt.Video, pxt.Audio, pxt.Document, pxt.Json: one table for structured and media data with destination= for S3, GCS, Azure, R2, and more. Not S3 + Postgres + boto3 sync.
t = pxt.create_table(
'media',
{
'img': pxt.Image,
'video': pxt.Video,
'audio': pxt.Audio,
'document': pxt.Document,
'metadata': pxt.Json,
},
)
Import / export: I/O without glue scripts
create_table(source=...), path/URL insert(), Hugging Face, export_parquet(), PyTorch, COCO, and more. Not per-format ETL scripts.
# Create a table from a file, URL, or Hugging Face dataset
pxt.create_table('app/data', source='data.csv')
pxt.create_table('app/reviews', source=hf_dataset)
# Append rows into an existing table from a path or URL
t.insert('s3://my-bucket/new_rows.parquet')
# Export to analytics/ML formats
pxt.io.export_parquet(t, 'data.parquet')
pytorch_ds = t.to_pytorch_dataset('pt') # PyTorch DataLoader ready
coco_path = t.to_coco_dataset() # COCO annotations
CSV import · Hugging Face · PyTorch export · ML data wrangling
Iterate: explode media into rows
create_view() with iterators splits documents into chunks, video into frames, audio into segments, and typed JSON lists into rows. Not FFmpeg/spaCy pipelines with child tables and foreign keys. For custom explode logic, use @pxt.iterator.
from pixeltable.functions.document import document_splitter
from pixeltable.functions.json import list_iterator
from pixeltable.functions.video import frame_iterator
# Document chunking with overlap
chunks = pxt.create_view(
'chunks',
docs,
iterator=document_splitter(
document=docs.doc,
separators='sentence,token_limit',
overlap=50,
limit=500,
),
)
# Video frame extraction
frames = pxt.create_view(
'frames',
videos,
iterator=frame_iterator(video=videos.video, fps=0.5),
)
# JSON list column: one row per element (typed pxt.Json column required)
items = pxt.create_view('items', t, iterator=list_iterator(t.tags))
Orchestrate: declarative computed columns
add_computed_column() runs incrementally on new or stale rows only. Built-ins cover media processing, embeddings, and 30+ providers. Not Airflow, full reprocesses, or custom retry glue.
# LLM provider
t.add_computed_column(
summary=openai.chat_completions(
messages=[{'role': 'user', 'content': t.text}],
model='gpt-4o-mini',
),
)
# Local model inference
t.add_computed_column(
classification=huggingface.vit_for_image_classification(t.image),
)
# Multimodal vision
t.add_computed_column(
description=openai.chat_completions(
messages=[
{
'role': 'user',
'content': [
{'type': 'text', 'text': 'Describe this image'},
{'type': 'image_url', 'image_url': t.image},
],
},
],
model='gpt-4o-mini',
),
)
Extend: your code, with cache and retry
@pxt.udf and @pxt.query with parallelize, cache, and retry. Not one-off handlers with no cache or retry.
@pxt.udf
def format_prompt(context: list, question: str) -> str:
return f'Context: {context}\nQuestion: {question}'
@pxt.query
def search_by_topic(topic: str):
return t.where(t.category == topic).select(t.title, t.summary)
Index: built-in vector search
add_embedding_index() stays in sync with table data. Combine .similarity() with .where() on metadata in one query — not a separate vector DB plus filter pipeline.
t.add_embedding_index(
'img',
embedding=clip.using(model_id='openai/clip-vit-base-patch32'),
)
sim = t.img.similarity(string='cat playing with yarn')
results = (
t.where(t.category == 'pets') # metadata filter in the same query
.order_by(sim, asc=False)
.select(t.img, t.category, score=sim)
.limit(10)
.collect()
)
Query & experiment: prototype to production in one line
.select() and .sample() to test UDFs ephemerally; same expression becomes add_computed_column() when ready. Not notebook experiments rewritten for production.
# Explore: filter, sample, apply UDFs ephemerally
results = (
t.where(t.score > 0.8)
.order_by(t.timestamp)
.select(t.image, score=t.score)
.limit(10)
.collect()
)
# Test on a sample (nothing stored, parallelized and cached)
t.sample(5).select(t.text, summary=summarize(t.text)).collect()
# Commit: same expression, full dataset, skips cached rows
t.add_computed_column(summary=summarize(t.text))
Agents & tools: tool calling and MCP
pxt.tools(), invoke_tools(), and MCP: LLMs choose what to invoke and Pixeltable stores results. Not LangChain loops and manual tool wiring.
mcp_tools = pxt.mcp_udfs('http://localhost:8000/mcp')
tools = pxt.tools(get_weather_udf, search_context_query, *mcp_tools)
t.add_computed_column(
tool_output=invoke_tools(tools, t.llm_tool_choice),
)
Serve: HTTP from schema
pxt serve from TOML or FastAPIRouter routes on the same app. Not hand-written FastAPI endpoints for every table operation.
# pyproject.toml
[[tool.pixeltable.service]]
name = "my-service"
modules = ["schema"]
[[tool.pixeltable.service.routes]]
type = "insert"
table = "myapp.docs"
path = "/ingest"
inputs = ["document"]
outputs = ["document", "summary"]
pxt serve my-service
from pixeltable.serving import FastAPIRouter
router = FastAPIRouter(prefix='/api', tags=['data'])
router.add_query_route(path='/search', query=search_documents)
router.add_insert_route(table, path='/upload', uploadfile_inputs=['image'])
Inspect & visualize: errors, tables, and pipelines
pxt errors and queryable errormsg per cell; pxt dashboard opens a local UI to browse tables, preview media, and trace column lineage. Not log scraping or opaque per-row failures.
pxt errors my_table # rows where a computed column failed
pxt dashboard # browse tables, preview media, pipeline graph
Table browser · media lightbox · column lineage · per-column errors · CSV export
Version: time travel
history(), revert(), and snapshot queries for time travel on every insert and schema change. Not DVC, MLflow, and backfill scripts.
t = pxt.get_table('my_table')
t.revert() # undo last modification
t.history() # list all versions
snapshot = pxt.get_table('my_table:472') # query a snapshot
Three deployment patterns (docs / starter kit):
| Pattern | What it is | You write |
|---|---|---|
| Full Backend | FastAPI + React web app | Python schema + endpoints + frontend |
| Batch Processing | Cron / queue / Cloud Run Job | Python script: ingest, compute, export_sql, exit |
| Declarative API | REST API from TOML config | pyproject.toml routes + pxt serve |
Installation
pip install pixeltable # SDK + CLI (pxt ls, rows, errors, …)
AI Agent Skill
Teach AI coding assistants (Cursor, Claude Code, Copilot, etc.). Learn more →
npx skills add pixeltable/pixeltable-skill
Start from a Template
Head start on a production-ready app: scaffold schema, routes, and deployment pattern in one command.
uvx pixeltable-new myapp
Default: declarative serving (schema.py + pyproject.toml → pxt serve). --backend for FastAPI + React; --batch for cron/queue scripts. Templates from the Starter Kit.
Quick Start
Define schema in Python, routes in TOML: a pxt.Video table, frame view, one computed column on the frame view, and a single insert endpoint.
# demo.py
import pixeltable as pxt
from pixeltable.functions.video import frame_iterator
videos = pxt.create_table('videos', {'video': pxt.Video, 'title': pxt.String}, if_exists='ignore')
frames = pxt.create_view('frames', videos, iterator=frame_iterator(videos.video, fps=1), if_exists='ignore')
frames.add_computed_column(thumb=frames.frame.thumbnail((320, 320)), if_exists='ignore')
# pyproject.toml
[[tool.pixeltable.service]]
name = "video-api"
modules = ["demo"]
[[tool.pixeltable.service.routes]]
type = "insert"
path = "/videos"
table = "videos"
inputs = ["video", "title"]
outputs = ["title"]
python demo.py # create tables, views, and computed columns
pxt serve video-api # start REST API from pyproject.toml (POST /videos insert route)
curl -X POST localhost:8000/videos -H 'Content-Type: application/json' \
-d '{"video": "https://raw.githubusercontent.com/pixeltable/pixeltable/release/docs/resources/bangkok.mp4", "title": "Bangkok"}' # insert video; triggers frame extraction + thumb
pxt rows frames -n 1 --cols pos,thumb # one frame row + computed thumbnail
See CLI serving.
Demo
See Pixeltable in action: table creation, computed columns, multimodal processing, and querying in a single workflow.
https://github.com/user-attachments/assets/b50fd6df-5169-4881-9dbe-1b6e5d06cede
Documentation
One schema for storage, orchestration, and retrieval. What is Pixeltable? · Deployment overview
| Topic | Guides |
|---|---|
| Schema & orchestration | Type system · Tables & data · Computed columns · Views · Iterators · Embedding indexes · Queries & expressions · Iterative workflow · Version control |
| Agents & serving | Agents & MCP · Tool calling · RAG pipeline · CLI & dashboard · UDFs · Built-ins · 30+ providers |
| Cloud & storage | Cloud storage (S3, GCS, Azure, R2, B2, Tigris) · Configuration · External files · Get started · Cloud services · Public datasets |
| Local & I/O | Storage architecture · CSV import · Hugging Face · PyTorch export · ML data wrangling · Sample apps · Colab tour |
Contributing
We love contributions! Whether it's reporting bugs, suggesting features, improving documentation, or submitting code changes, please check out our Contributing Guide and join our Discord Server.
License
Pixeltable is licensed under the Apache 2.0 License.