---
title: "How do I add computed columns with LLM calls in Python?"
description: "Add computed columns with LLM calls in Python: assign chat_completions on the class so each new or changed row runs, then caches the result."
url: "https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls"
updated: "2026-10-14"
doc: "https://docs.pixeltable.com/datastore/computed-columns"
---

# How do I add computed columns with LLM calls in Python?

A computed column is a value produced by an expression or an LLM call when the row or its dependencies change, then cached. A declarative data pipeline is that schema: you name the columns, and the engine decides which rows run. Adding an LLM call is an assignment on the class, not a job you schedule around a table.

Updated: 2026-10-14
Part of [How do I ... in Python?](https://www.pixeltable.com/learn/how-to).

## Before you start

About 10 min.

- Python 3.11+
- pip install -U 'pixeltable[serve]'
- pxt init in the project root
- An OpenAI API key for gpt-4o-mini

## On this page

- [Before you start](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#before-you-start)
- [Start with the stored field the model will read](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#step-1)
- [Assign the LLM call on the class](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#step-2)
- [Chain another column on the cached output](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#step-3)
- [Comparison](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#comparison)
- [Where Pixeltable fits](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#where-pixeltable-fits)
- [Questions](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls#questions)

## 1. Start with the stored field the model will read {#step-1}

A computed column is an expression over other columns. The source text (or image, or document) is stored. The model output is derived.

```python
import pixeltable as pxt
from pixeltable.functions.openai import chat_completions

TableModel = pxt.model_base()

class Docs(TableModel, name='docs'):
    text: pxt.String
```

## 2. Assign the LLM call on the class {#step-2}

Computed fields are assignments, not annotations. chat_completions returns a response object; .choices[0].message.content is the string you cache. Insert a row and that expression runs. Edit the text and dependents of that row recompute.

```python
class Docs(TableModel, name='docs'):
    text: pxt.String
    summary = chat_completions(
        messages=[{'role': 'user', 'content': text}],
        model='gpt-4o-mini',
    ).choices[0].message.content
```

## 3. Chain another column on the cached output {#step-3}

A declarative data pipeline is a graph of these assignments. A second call can classify the summary. Unchanged rows keep both caches. You do not enqueue each step.

```python
class Docs(TableModel, name='docs'):
    text: pxt.String
    summary = chat_completions(
        messages=[{'role': 'user', 'content': text}],
        model='gpt-4o-mini',
    ).choices[0].message.content
    label = chat_completions(
        messages=[{
            'role': 'user',
            'content': 'Classify as bug, feature, or question. Reply with one word.\n\n' + summary,
        }],
        model='gpt-4o-mini',
    ).choices[0].message.content

# pxt schema update app.py docs -f
```

## Computed LLM columns versus a job around the table {#comparison}

|  | Computed column | A scheduled job |
| --- | --- | --- |
| You write | An assignment on the class | A worker that reads and writes rows |
| Runs when | The row or a dependency changes | A cron tick or a queue |
| Cache | Per row, with lineage | A column you overwrite by hand |
| Failure | That row, visible | A retry of the batch |

## Where Pixeltable fits {#where-pixeltable-fits}

In Pixeltable a computed column is an assignment on TableModel. chat_completions is one expression. Insert a row and the LLM runs; unchanged rows stay cached. That is a declarative data pipeline, not an Airflow task or a LangChain chain with no store. See Pixeltable vs LangChain and Pixeltable vs Supabase (edge functions are not this cache).

```python
import pixeltable as pxt
from pixeltable.functions.openai import chat_completions

TableModel = pxt.model_base()

class Docs(TableModel, name='docs'):
    text: pxt.String
    summary = chat_completions(
        messages=[{'role': 'user', 'content': text}],
        model='gpt-4o-mini',
    ).choices[0].message.content
```

## Concepts

- [What is a computed column?](https://www.pixeltable.com/learn/what-is-a-computed-column)
- [What is a declarative pipeline?](https://www.pixeltable.com/learn/what-is-a-declarative-pipeline)
- [What is an AI function?](https://www.pixeltable.com/learn/what-is-an-ai-function)

## Use case

- [Declarative AI Infrastructure: Define Pipelines, Not Plumbing](https://www.pixeltable.com/use-cases/declarative-ai-data-infrastructure)

## Questions {#questions}

### Is a computed column an edge function? {#faq-1}

No. An edge function runs on a request and does not cache per row by default. A computed column stores the result with the row and recomputes when dependencies change. Pixeltable vs Supabase covers Neon/Supabase functions.

### Does every insert call the model again for old rows? {#faq-2}

No. Unchanged rows keep their cached values. A new or edited source column recomputes dependents of that row. That is incremental computation.

### Can the LLM see an image or a document? {#faq-3}

Yes, if the provider UDF accepts that type. Text is chat_completions on a string. Gemini generate_content accepts an image and a prompt as contents. Use the UDF that matches the modality.

## Related

- [What is a computed column?](https://www.pixeltable.com/learn/what-is-a-computed-column)
- [What is a declarative pipeline?](https://www.pixeltable.com/learn/what-is-a-declarative-pipeline)
- [What is an AI function?](https://www.pixeltable.com/learn/what-is-an-ai-function)
- [Declarative data infrastructure](https://www.pixeltable.com/use-cases/declarative-ai-data-infrastructure)
- [How do I build an AI data pipeline in Python?](https://www.pixeltable.com/learn/how-to/build-an-ai-data-pipeline)
- [Pixeltable vs LangChain](https://www.pixeltable.com/compare/pixeltable-vs-langchain)
- [Pixeltable vs Supabase](https://www.pixeltable.com/compare/pixeltable-vs-supabase)
- [Computed columns](https://docs.pixeltable.com/datastore/computed-columns)
