Pixeltable
Pixeltable is the database, the orchestration, and the serving in one Python file. Tables
store the data, computed columns declare the transforms, embedding indexes make it
searchable, and FastAPIRouter exposes it over HTTP. Insert a row and the transforms run.
Install and first run
pip install -U 'pixeltable[serve]'
pxt init # mark this directory a project root
pxt service example --out app.py # write a working application file
pxt schema update app.py my_app # create the tables the models declare
pxt service update app.py my_app # serve this file's routes
pxt service list # print the assigned URL
pxt init is a prerequisite: pxt schema update refuses a file that sits under no project
root. schema update creates tables and does not start endpoints; service update starts
endpoints and does not create tables. Both prompt for confirmation unless you pass -f,
and exit 3 when run non-interactively without it.
The last argument (my_app) names a catalog inside Pixeltable. It is not a folder on disk.
The application file
import pixeltable as pxt
import pixeltable.functions as pxtf
from pixeltable.serving import FastAPIRouter
TableModel = pxt.model_base()
@pxt.udf
def excerpt(text: str, n: int = 12) -> str:
return text if len(text) <= n else f'{text[:n]}...'
class Docs(TableModel, name='docs'):
doc_id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True) # a generated key: provided automatically on insert
title: pxt.String
body: pxt.String | None
title_upper = pxtf.string.upper(title) # an assignment: computed on insert
summary = excerpt(title)
ingest = FastAPIRouter(name='ingest')
ingest.add_insert_route(
Docs, path='/docs', inputs=[Docs.title, Docs.body], outputs=[Docs.doc_id, Docs.title_upper, Docs.summary]
)
ingest.add_compute_route(Docs, path='/titles', inputs=[Docs.title], outputs=[Docs.title_upper])
An annotation (title: pxt.String) is a value you insert. An assignment
(title_upper = ...) is a computed column, recomputed on insert and on update. A
non-nullable annotated column that is a route input is a required field in the request
body:
curl -X POST http://127.0.0.1:<port>/docs \
-H 'Content-Type: application/json' \
-d '{"doc_id": 1, "title": "Hello", "body": "world"}'
# {"title_upper":"HELLO","summary":"Hello"}
Capabilities
- Multimodal columns:
pxt.Image, pxt.Video, pxt.Audio, pxt.Document, plus
pxt.String, pxt.Int, pxt.Float, pxt.Bool, pxt.Json, pxt.Array, timestamps.
- Computed columns call any UDF or provider function and run incrementally: only new
or changed rows compute.
- Views with iterators expand one row into many.
frame_iterator for video,
document_splitter for documents, audio_splitter, string_splitter, tile_iterator.
- Embedding indexes declared in
__indexes__; query with
column.similarity(string=...) or similarity(image=...).
- UDFs with
@pxt.udf, aggregates with @pxt.uda, reusable queries with @pxt.query.
- Serving:
add_insert_route, add_compute_route, add_update_route,
add_delete_route, add_query_route. FastAPIRouter subclasses
fastapi.APIRouter, so app.include_router(...) mounts it on an existing app.
- Providers: OpenAI, Anthropic, Gemini, Bedrock, Mistral, Together, Fireworks, Groq,
Replicate, Hugging Face, Ollama, vLLM, Voyage, Jina, and more under
pixeltable.functions.
Constraints
- Application code declares a
TableModel in app.py and creates it with
pxt schema update. It does not call pxt.create_table() or
add_embedding_index(); indexes belong in __indexes__.
- Notebooks, tests, and the REPL do use
pxt.create_table() and
add_embedding_index(). That is correct there and does not need a project file.
- Importing
app.py declares the models but does not attach them to tables. Call
TableModel.bind_all('<target>') before inserting or querying from plain Python.
- A UDF is referenced by the file path it is defined in. Moving or renaming that file
leaves the columns that call it unable to compute.
pxt service run always serves from the current process and cannot target Cloud.
Do not reach for
Chunking, retrieval, tool-calling, and orchestration are built in. Adding these fights
the model rather than helping it:
- LangChain, LlamaIndex, or Haystack for chunking, retrieval, or tool-calling
- A separate vector database; embedding indexes live on the table
- pandas as a working store; the table is the store
- A per-row
for loop calling a model; use a computed column
- A manual agent
while loop; model the agent as a table
Cloud
Pixeltable Cloud is in Limited Beta. Email contact@pixeltable.com if you are interested.
The same application file targets a hosted database with pxt db update,
pxt schema update, and pxt service update against a pxt://org:db target, once
PIXELTABLE_API_KEY is exported (API Keys, not toml api_key; Pixeltable never loads
.env itself, so source it first). Hosted tables already write media to
pxtfs://org:db/home; dest env vars are for local Pixeltable and bring-your-own buckets.
Provider keys go under Secrets / pxt secret.
Reference
1---2name: pixeltable-33description: Build multimodal AI applications with Pixeltable. One application file declares TableModel tables, computed columns, embedding indexes, and FastAPI routes; inserting a row runs the transforms. Use when building RAG, processing images, video, audio, or documents, or serving an API over that data. Do not use for general Python or direct PostgreSQL administration.4license: Apache-2.05---67# Pixeltable89Pixeltable is the database, the orchestration, and the serving in one Python file. Tables10store the data, computed columns declare the transforms, embedding indexes make it11searchable, and `FastAPIRouter` exposes it over HTTP. Insert a row and the transforms run.1213## Install and first run1415```bash16pip install -U 'pixeltable[serve]'17pxt init # mark this directory a project root18pxt service example --out app.py # write a working application file19pxt schema update app.py my_app # create the tables the models declare20pxt service update app.py my_app # serve this file's routes21pxt service list # print the assigned URL22```2324`pxt init` is a prerequisite: `pxt schema update` refuses a file that sits under no project25root. `schema update` creates tables and does not start endpoints; `service update` starts26endpoints and does not create tables. Both prompt for confirmation unless you pass `-f`,27and exit 3 when run non-interactively without it.2829The last argument (`my_app`) names a catalog inside Pixeltable. It is not a folder on disk.3031## The application file3233```python34import pixeltable as pxt35import pixeltable.functions as pxtf36from pixeltable.serving import FastAPIRouter3738TableModel = pxt.model_base()394041@pxt.udf42def excerpt(text: str, n: int = 12) -> str:43 return text if len(text) <= n else f'{text[:n]}...'444546class Docs(TableModel, name='docs'):47 doc_id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True) # a generated key: provided automatically on insert48 title: pxt.String49 body: pxt.String | None50 title_upper = pxtf.string.upper(title) # an assignment: computed on insert51 summary = excerpt(title)525354ingest = FastAPIRouter(name='ingest')55ingest.add_insert_route(56 Docs, path='/docs', inputs=[Docs.title, Docs.body], outputs=[Docs.doc_id, Docs.title_upper, Docs.summary]57)58ingest.add_compute_route(Docs, path='/titles', inputs=[Docs.title], outputs=[Docs.title_upper])59```6061An **annotation** (`title: pxt.String`) is a value you insert. An **assignment**62(`title_upper = ...`) is a computed column, recomputed on insert and on update. A63non-nullable annotated column that is a route input is a required field in the request64body:6566```bash67curl -X POST http://127.0.0.1:<port>/docs \68 -H 'Content-Type: application/json' \69 -d '{"doc_id": 1, "title": "Hello", "body": "world"}'70# {"title_upper":"HELLO","summary":"Hello"}71```7273## Capabilities7475- **Multimodal columns**: `pxt.Image`, `pxt.Video`, `pxt.Audio`, `pxt.Document`, plus76 `pxt.String`, `pxt.Int`, `pxt.Float`, `pxt.Bool`, `pxt.Json`, `pxt.Array`, timestamps.77- **Computed columns** call any UDF or provider function and run incrementally: only new78 or changed rows compute.79- **Views with iterators** expand one row into many. `frame_iterator` for video,80 `document_splitter` for documents, `audio_splitter`, `string_splitter`, `tile_iterator`.81- **Embedding indexes** declared in `__indexes__`; query with82 `column.similarity(string=...)` or `similarity(image=...)`.83- **UDFs** with `@pxt.udf`, aggregates with `@pxt.uda`, reusable queries with `@pxt.query`.84- **Serving**: `add_insert_route`, `add_compute_route`, `add_update_route`,85 `add_delete_route`, `add_query_route`. `FastAPIRouter` subclasses86 `fastapi.APIRouter`, so `app.include_router(...)` mounts it on an existing app.87- **Providers**: OpenAI, Anthropic, Gemini, Bedrock, Mistral, Together, Fireworks, Groq,88 Replicate, Hugging Face, Ollama, vLLM, Voyage, Jina, and more under89 `pixeltable.functions`.9091## Constraints9293- Application code declares a `TableModel` in `app.py` and creates it with94 `pxt schema update`. It does **not** call `pxt.create_table()` or95 `add_embedding_index()`; indexes belong in `__indexes__`.96- Notebooks, tests, and the REPL do use `pxt.create_table()` and97 `add_embedding_index()`. That is correct there and does not need a project file.98- Importing `app.py` declares the models but does not attach them to tables. Call99 `TableModel.bind_all('<target>')` before inserting or querying from plain Python.100- A UDF is referenced by the file path it is defined in. Moving or renaming that file101 leaves the columns that call it unable to compute.102- `pxt service run` always serves from the current process and cannot target Cloud.103104## Do not reach for105106Chunking, retrieval, tool-calling, and orchestration are built in. Adding these fights107the model rather than helping it:108109- LangChain, LlamaIndex, or Haystack for chunking, retrieval, or tool-calling110- A separate vector database; embedding indexes live on the table111- pandas as a working store; the table is the store112- A per-row `for` loop calling a model; use a computed column113- A manual agent `while` loop; model the agent as a table114115## Cloud116117Pixeltable Cloud is in Limited Beta. Email contact@pixeltable.com if you are interested.118The same application file targets a hosted database with `pxt db update`,119`pxt schema update`, and `pxt service update` against a `pxt://org:db` target, once120`PIXELTABLE_API_KEY` is exported (API Keys, not toml `api_key`; Pixeltable never loads121`.env` itself, so source it first). Hosted tables already write media to122`pxtfs://org:db/home`; dest env vars are for local Pixeltable and bring-your-own buckets.123Provider keys go under Secrets / `pxt secret`.124125## Reference126127- Documentation: https://docs.pixeltable.com/128- Quickstart: https://docs.pixeltable.com/overview/quick-start129- SDK reference: https://docs.pixeltable.com/sdk/latest/pixeltable130- Coding-agent skill: `npx skills add pixeltable/pixeltable-skill`