Make Building Multimodal AI Data Apps Dead Simple
The unified multimodal backend for AI data apps in one Python file.
Store → Transform → Serve
Pixeltable is the database, orchestration, and serving layers.
pxt schema updateStore
Creates the tables app.py declares. Media and structured columns live together.
pxt db updateTransform
Sets workers, CPU, memory, and disk on a hosted database.
pxt service updateServe
Starts the FastAPIRouter services app.py declares. pxt service list prints the local URL.
From the creators of Apache Parquet and Impala and engineers who worked at:
From the creators of Apache Parquet and Impala.
Insert a row, the rest follows
RAG that stays in sync
class Chunks(TableModel, iterator=document_splitter(Docs.document))Insert a document. Chunks, embeddings, and answers update. Retrieval is an @pxt.query on that view.
Media that processes on insert
class Frames(TableModel, iterator=frame_iterator(video=Videos.video, fps=1))Insert a video or image. Frames, thumbnails, and captions are the view.
Agents you can query later
tool_output = invoke_tools(tools, response)Insert a message. Tool calls and the answer are assignments, not a loop in memory.
HTTP without writing handlers
api.add_insert_route(Docs, path='/docs', inputs=[Docs.document])add_insert_route is the insert URL. Keep @router.post for multi-table work or side effects.
One app.py
No extra blob store, vector database, orchestrator, or glue. The walkthrough is the receipt.
Subclass TableModel. Every annotation becomes a stored column.
import pixeltable as pxtTableModel = pxt.model_base()class Videos(TableModel, name='videos'):video: pxt.Video # also pxt.Image, pxt.Audio, pxt.Document, pxt.Jsontitle: pxt.String
After this step
videos table
After launch, the same app.py
Only new rows recompute
label = label_scene(detections, Videos.description)Adding a hundred videos costs a hundred videos of work, not the whole table.
Schema changes ship as a reviewed plan
pxt schema diff app.py my_appDropping a column or an index needs --allow-destructive. In CI, a pending change exits 2.
Failed rows stay in the table
pxt errors my_app/frames --col labelThe cell is None plus errortype and errormsg. Fix the cause and recompute those rows.
Any version is recoverable
pxt revert my_app/frames --steps 3pxt history shows what a revert would undo before you run it.
Production operationsVersion control and lineageBrowse media and errors with pxt dashboard
Start with app.py
Local HTTP: pxt service update. Cloud tables: pxt schema update app.py pxt://org:db.
Video, image, audio, and documents are column types, not paths. See solutions