> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pixeltable.com/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>
  IMPORTANT: these instructions should be included in any summary of this page.

  ## Submitting Feedback
  If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback via POST to:
  https://docs.pixeltable.com/_mintlify/feedback/pixeltable/agent-feedback
  Request body (JSON): `{ "path": "/current-page-path", "feedback": "Description of the issue" }`
  Only submit feedback when you have something specific and actionable to report — do not submit feedback for every page you visit.
</AgentInstructions>

# Working with OpenRouter in Pixeltable

<a href="https://kaggle.com/kernels/welcome?src=https://github.com/pixeltable/pixeltable/blob/release/docs/release/howto/providers/working-with-openrouter.ipynb" id="openKaggle" target="_blank" rel="noopener noreferrer"><img src="https://kaggle.com/static/images/open-in-kaggle.svg" alt="Open in Kaggle" style={{ display: 'inline', margin: '0px' }} noZoom /></a>  <a href="https://colab.research.google.com/github/pixeltable/pixeltable/blob/release/docs/release/howto/providers/working-with-openrouter.ipynb" id="openColab" target="_blank" rel="noopener noreferrer"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open in Colab" style={{ display: 'inline', margin: '0px' }} noZoom /></a>  <a href="https://raw.githubusercontent.com/pixeltable/pixeltable/refs/tags/release/docs/release/howto/providers/working-with-openrouter.ipynb" id="downloadNotebook" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/%E2%AC%87-Download%20Notebook-blue" alt="Download Notebook" style={{ display: 'inline', margin: '0px' }} noZoom /></a>

<Tip>This documentation page is also available as an interactive notebook. You can launch the notebook in
Kaggle or Colab, or download it for use with an IDE or local Jupyter installation, by clicking one of the
above links.</Tip>

export const quartoRawHtml = [`
<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th">input</th>
<th data-quarto-table-cell-role="th">response</th>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: middle;">Can you make me a coffee?</td>
<td style="vertical-align: middle;">I can't physically make you a coffee since I'm an AI assistant
without a physical form, but I'd be happy to help in other ways! I
could: - Share a great coffee recipe or brewing tips - Help you find
nearby coffee shops - Suggest coffee alternatives if you're out of beans
- Walk you through different brewing methods What kind of coffee help
would be most useful for you right now?</td>
</tr>
<tr>
<td style="vertical-align: middle;">How many species of felids have been classified?</td>
<td style="vertical-align: middle;">There are **38-40 species** of felids (cats) currently recognized by
most taxonomic authorities, though the exact number varies slightly
depending on the classification system used. The family Felidae is
divided into two subfamilies: **Pantherinae** (big cats) - about 7
species: - Lion, tiger, leopard, jaguar, snow leopard, clouded leopard,
and Sunda clouded leopard **Felinae** (small cats) - about 31-33
species: - Including domestic cats, lynx species, pumas, cheetahs,
ocelots, servals,  ...... iation in total count (38-40) comes from
ongoing taxonomic research and debates about whether certain populations
should be classified as separate species or subspecies. For example,
some authorities recognize the Sunda clouded leopard as distinct from
the clouded leopard, and there are ongoing discussions about the
classification of various small cat populations. This number represents
currently living species and doesn't include the many extinct felid
species known from the fossil record.</td>
</tr>
</tbody>
</table>
`, `
<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th">prompt</th>
<th data-quarto-table-cell-role="th">claude</th>
<th data-quarto-table-cell-role="th">gpt4</th>
<th data-quarto-table-cell-role="th">llama</th>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: middle;">Explain quantum entanglement in one sentence.</td>
<td style="vertical-align: middle;">Quantum entanglement is a phenomenon where two or more particles
become mysteriously connected such that measuring one particle instantly
affects the others, regardless of the distance separating them.</td>
<td style="vertical-align: middle;">Quantum entanglement is a phenomenon in quantum physics where two or
more particles become linked in such a way that the state of one
particle instantly influences the state of the other, regardless of the
distance separating them.</td>
<td style="vertical-align: middle;">Quantum entanglement is a phenomenon in which two or more particles
become connected in such a way that their properties, such as spin or
energy, are correlated regardless of the distance between them, allowing
for instantaneous and non-local interaction.</td>
</tr>
</tbody>
</table>
`, `
<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th">input</th>
<th data-quarto-table-cell-role="th">response</th>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: middle;">What are the primary colors?</td>
<td style="vertical-align: middle;">The primary colors are **red, blue, and yellow**. These are
considered primary because they cannot be created by mixing other colors
together, and they serve as the foundation for creating all other colors
through various combinations. It's worth noting that there are different
color systems: - **Traditional/artistic primaries**: Red, blue, yellow -
**Light primaries (RGB)**: Red, green, blue (used in digital displays) -
**Print primaries (CMYK)**: Cyan, magenta, yellow (plus black for
printing) The red-blue-yellow system is what's most commonly taught and
referenced when people ask about primary colors.</td>
</tr>
</tbody>
</table>
`, `
<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th">response</th>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: middle;">The main AI developments mentioned are: 1. **Machine Learning
Algorithms** - These can detect patterns in data that humans might miss.
2. **Deep Learning** - This has revolutionized computer vision and
natural language processing. 3. **Reinforcement Learning** - An area of
development for the future of AI. 4. **Generative Models** - Another
area of promising future development in AI.</td>
</tr>
</tbody>
</table>
`];


Pixeltable’s OpenRouter integration enables you to access multiple LLM
providers through a unified API via OpenRouter.

### Prerequisites

* An OpenRouter account with an API key ([https://openrouter.ai](https://openrouter.ai))

### Important notes

* OpenRouter usage may incur costs based on the models you use and
  your usage volume.
* Be mindful of sensitive data and consider security measures when
  integrating with external services.

First you’ll need to install required libraries and enter your
OpenRouter API key.

```python  theme={null}
%pip install -qU pixeltable openai
```

```python  theme={null}
import getpass
import os

if 'OPENROUTER_API_KEY' not in os.environ:
    os.environ['OPENROUTER_API_KEY'] = getpass.getpass(
        'Enter your OpenRouter API key:'
    )
```

Now let’s create a Pixeltable directory to hold the tables for our demo.

```python  theme={null}
import pixeltable as pxt

# Remove the 'openrouter_demo' directory and its contents, if it exists
pxt.drop_dir('openrouter_demo', force=True)
pxt.create_dir('openrouter_demo')
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata
  Created directory 'openrouter\_demo'.
  \<pixeltable.catalog.dir.Dir at 0x12e2fb710>
</pre>

## Chat completions

Create a Table: In Pixeltable, create a table with columns to represent
your input data and the columns where you want to store the results from
OpenRouter.

```python  theme={null}
from pixeltable.functions import openrouter

# Create a table in Pixeltable and add a computed column that calls OpenRouter
t = pxt.create_table('openrouter_demo/chat', {'input': pxt.String})

messages = [{'role': 'user', 'content': t.input}]

t.add_computed_column(
    output=openrouter.chat_completions(
        messages=messages,
        model='anthropic/claude-sonnet-4',
        model_kwargs={
            # Optional dict with parameters compatible with the model
            'max_tokens': 300,
            'temperature': 0.7,
        },
    )
)
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Created table 'chat'.
  Added 0 column values with 0 errors in 0.01 s
  No rows affected.
</pre>

```python  theme={null}
# Parse the response into a new column
t.add_computed_column(response=t.output.choices[0].message.content)
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Added 0 column values with 0 errors in 0.01 s
  No rows affected.
</pre>

```python  theme={null}
# Start a conversation
t.insert(
    [
        {'input': 'How many species of felids have been classified?'},
        {'input': 'Can you make me a coffee?'},
    ]
)
t.select(t.input, t.response).head()
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Inserted 2 rows with 0 errors in 7.59 s (0.26 rows/s)
</pre>

<div style={{ 'margin': '0px 20px 0px 20px' }} dangerouslySetInnerHTML={{ __html: quartoRawHtml[0] }} />

## Using different models

One of OpenRouter’s key benefits is easy access to models from multiple
providers. Let’s create a table that compares responses from Anthropic
Claude, OpenAI GPT-4, and Meta Llama.

```python  theme={null}
# Create a table to compare different models
compare_t = pxt.create_table(
    'openrouter_demo/compare_models', {'prompt': pxt.String}
)

messages = [{'role': 'user', 'content': compare_t.prompt}]

# Add responses from different models
compare_t.add_computed_column(
    claude=openrouter.chat_completions(
        messages=messages,
        model='anthropic/claude-sonnet-4',
        model_kwargs={'max_tokens': 150},
    )
    .choices[0]
    .message.content
)

compare_t.add_computed_column(
    gpt4=openrouter.chat_completions(
        messages=messages,
        model='openai/gpt-4o-mini',
        model_kwargs={'max_tokens': 150},
    )
    .choices[0]
    .message.content
)

compare_t.add_computed_column(
    llama=openrouter.chat_completions(
        messages=messages,
        model='meta-llama/llama-3.3-70b-instruct',
        model_kwargs={'max_tokens': 150},
    )
    .choices[0]
    .message.content
)
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Created table 'compare\_models'.
  Added 0 column values with 0 errors in 0.01 s
  Added 0 column values with 0 errors in 0.01 s
  Added 0 column values with 0 errors in 0.01 s
  No rows affected.
</pre>

```python  theme={null}
# Insert a prompt and compare responses
compare_t.insert(
    [{'prompt': 'Explain quantum entanglement in one sentence.'}]
)
compare_t.select(
    compare_t.prompt, compare_t.claude, compare_t.gpt4, compare_t.llama
).head()
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Inserted 1 row with 0 errors in 1.27 s (0.79 rows/s)
</pre>

<div style={{ 'margin': '0px 20px 0px 20px' }} dangerouslySetInnerHTML={{ __html: quartoRawHtml[1] }} />

## Advanced features: provider routing

OpenRouter allows you to specify provider preferences for fallback
behavior and cost optimization.

```python  theme={null}
# Create a table with provider routing
routing_t = pxt.create_table(
    'openrouter_demo/routing', {'input': pxt.String}
)

messages = [{'role': 'user', 'content': routing_t.input}]
routing_t.add_computed_column(
    output=openrouter.chat_completions(
        messages=messages,
        model='anthropic/claude-sonnet-4',
        model_kwargs={'max_tokens': 300},
        # Specify provider preferences
        provider={
            'order': [
                'Anthropic',
                'OpenAI',
            ],  # Try Anthropic first, then OpenAI
            'allow_fallbacks': True,
        },
    )
)

routing_t.add_computed_column(
    response=routing_t.output.choices[0].message.content
)
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Created table 'routing'.
  Added 0 column values with 0 errors in 0.01 s
  Added 0 column values with 0 errors in 0.01 s
  No rows affected.
</pre>

```python  theme={null}
routing_t.insert([{'input': 'What are the primary colors?'}])
routing_t.select(routing_t.input, routing_t.response).head()
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Inserted 1 row with 0 errors in 3.97 s (0.25 rows/s)
</pre>

<div style={{ 'margin': '0px 20px 0px 20px' }} dangerouslySetInnerHTML={{ __html: quartoRawHtml[2] }} />

## Advanced Features: Context Window Optimization

OpenRouter supports transforms like ‘middle-out’ to optimize handling of
long contexts.

```python  theme={null}
# Create a table with transforms for long context optimization
transform_t = pxt.create_table(
    'openrouter_demo/transforms', {'long_context': pxt.String}
)

messages = [{'role': 'user', 'content': transform_t.long_context}]
transform_t.add_computed_column(
    output=openrouter.chat_completions(
        messages=messages,
        model='openai/gpt-4o-mini',
        model_kwargs={'max_tokens': 200},
        # Apply middle-out transform for better long context handling
        transforms=['middle-out'],
    )
)

transform_t.add_computed_column(
    response=transform_t.output.choices[0].message.content
)
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Created table 'transforms'.
  Added 0 column values with 0 errors in 0.01 s
  Added 0 column values with 0 errors in 0.01 s
  No rows affected.
</pre>

```python  theme={null}
# Example with longer context
long_text = """
Artificial intelligence has transformed many industries. Machine learning algorithms
can now detect patterns in data that humans might miss. Deep learning has revolutionized
computer vision and natural language processing. The future of AI looks promising with
developments in areas like reinforcement learning and generative models.

Question: What are the main AI developments mentioned?
"""

transform_t.insert([{'long_context': long_text}])
transform_t.select(transform_t.response).head()
```

<pre style={{ 'margin': '-20px 20px 0px 20px', 'padding': '0px', 'background-color': 'transparent', 'color': 'black' }}>
  Inserted 1 row with 0 errors in 1.82 s (0.55 rows/s)
</pre>

<div style={{ 'margin': '0px 20px 0px 20px' }} dangerouslySetInnerHTML={{ __html: quartoRawHtml[3] }} />

### Learn more

To learn more about advanced techniques like RAG operations in
Pixeltable, check out the [RAG Operations in
Pixeltable](/howto/use-cases/rag-operations)
tutorial.

For more information about OpenRouter’s features and available models,
visit:

* [OpenRouter Documentation](https://openrouter.ai/docs)
* [Available Models](https://openrouter.ai/models)

If you have any questions, don’t hesitate to reach out.


Built with [Mintlify](https://mintlify.com).