Skip to main content
Open in Kaggle  Open in Colab  Download Notebook
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.
Pixeltable’s fal.ai integration enables you to access fal.ai’s fast inference models via the fal.ai API.

Prerequisites

Important Notes

  • fal.ai usage may incur costs based on your fal.ai plan.
  • Be mindful of sensitive data and consider security measures when integrating with external services.
First you’ll need to install required libraries and enter a fal.ai API key.
%pip install -qU fal-client
import os
import getpass

if 'FAL_API_KEY' not in os.environ:
    os.environ['FAL_API_KEY'] = getpass.getpass('fal.ai API Key: ')
Now let’s create a Pixeltable directory to hold the tables for our demo.
import pixeltable as pxt

# Remove the 'fal_demo' directory and its contents, if it exists
pxt.drop_dir('fal_demo', force=True)
pxt.create_dir('fal_demo')
Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata
Created directory ‘fal_demo’.
<pixeltable.catalog.dir.Dir at 0x308076450>

Text-to-Image Generation with FLUX Schnell

Let’s start by using fal.ai’s FLUX Schnell model, which is optimized for fast image generation. We’ll create a table to store prompts and generated images.
from pixeltable.functions import fal

# Create a table for image generation
t = pxt.create_table('fal_demo.images', {'prompt': pxt.String})

# Add a computed column that calls the FLUX Schnell model
t.add_computed_column(
    response=fal.run(
        input={'prompt': t.prompt},
        app='fal-ai/flux/schnell'
    )
)
Created table ‘images’.
Added 0 column values with 0 errors.
No rows affected.
Now let’s insert some prompts and see the results:
# Insert a few prompts
t.insert([
    {'prompt': 'A serene mountain landscape at sunset with a crystal clear lake'},
    {'prompt': 'A friendly robot teaching a class of kittens to code'},
    {'prompt': 'An underwater city with bioluminescent architecture'}
])
Inserting rows into `images`: 3 rows [00:00, 251.91 rows/s]
Inserted 3 rows with 0 errors.
3 rows inserted, 6 values computed.
Let’s examine the structure of the response:
t.select(t.prompt, t.response).head(1)
We can see that fal.ai returns a JSON response with an images array. Each image has a url field. Let’s extract and display the images:
# Add a computed column to extract the image URL and convert it to an Image type
t.add_computed_column(image=t.response['images'][0]['url'].astype(pxt.Image))

# Display the prompts and images
t.select(t.prompt, t.image).head()
Added 3 column values with 0 errors.

Advanced Image Generation with Fast SDXL

fal.ai also offers Fast SDXL, which provides more control over image generation parameters. Let’s create a new table to explore these capabilities.
# Create a table with more parameters
sdxl_t = pxt.create_table(
    'fal_demo.sdxl_images',
    {
        'prompt': pxt.String,
        'negative_prompt': pxt.String,
        'steps': pxt.Int
    }
)

# Add a computed column with more parameters
sdxl_t.add_computed_column(
    response=fal.run(
        input={
            'prompt': sdxl_t.prompt,
            'negative_prompt': sdxl_t.negative_prompt,
            'image_size': 'square_hd',  # 1024x1024
            'num_inference_steps': sdxl_t.steps
        },
        app='fal-ai/fast-sdxl'
    )
)

# Extract the image
sdxl_t.add_computed_column(image=sdxl_t.response['images'][0]['url'].astype(pxt.Image))
Created table ‘sdxl_images’.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
No rows affected.
# Insert prompts with different parameters
sdxl_t.insert([
    {
        'prompt': 'A majestic lion in a savanna at golden hour, photorealistic',
        'negative_prompt': 'cartoon, illustration, drawing',
        'steps': 25
    },
    {
        'prompt': 'A futuristic cityscape with flying cars and neon lights',
        'negative_prompt': 'blurry, low quality',
        'steps': 30
    }
])
Inserting rows into `sdxl_images`: 2 rows [00:00, 863.56 rows/s]
Inserted 2 rows with 0 errors.
2 rows inserted, 8 values computed.
# Display the results
sdxl_t.select(sdxl_t.prompt, sdxl_t.image).head()

Generating Multiple Images per Prompt

You can also generate multiple variations of the same prompt in a single request:
# Create a table for multiple image generation
multi_t = pxt.create_table('fal_demo.multi_images', {'prompt': pxt.String})

# Generate 3 variations of each prompt
multi_t.add_computed_column(
    response=fal.run(
        input={
            'prompt': multi_t.prompt,
            'num_images': 3
        },
        app='fal-ai/flux/schnell'
    )
)

# Extract the first image (you could create columns for all three)
multi_t.add_computed_column(image_1=multi_t.response['images'][0]['url'].astype(pxt.Image))
multi_t.add_computed_column(image_2=multi_t.response['images'][1]['url'].astype(pxt.Image))
multi_t.add_computed_column(image_3=multi_t.response['images'][2]['url'].astype(pxt.Image))
Created table ‘multi_images’.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
No rows affected.
# Insert a prompt
multi_t.insert([{'prompt': 'A steampunk mechanical butterfly on a brass flower'}])
Inserting rows into `multi_images`: 1 rows [00:00, 486.80 rows/s]
Inserted 1 row with 0 errors.
1 row inserted, 5 values computed.
# Display all three variations
multi_t.select(multi_t.image_1, multi_t.image_2, multi_t.image_3).head()

Using Higher Quality Models

For higher quality generation, you can use models like fal-ai/flux/dev which produce better results but take more time:
# Create a table using FLUX Dev
dev_t = pxt.create_table('fal_demo.flux_dev', {'prompt': pxt.String})

# Use FLUX Dev model for higher quality
dev_t.add_computed_column(
    response=fal.run(
        input={'prompt': dev_t.prompt},
        app='fal-ai/flux/dev'
    )
)

dev_t.add_computed_column(image=dev_t.response['images'][0]['url'].astype(pxt.Image))
Created table ‘flux_dev’.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
No rows affected.
# Insert a prompt (note: FLUX Dev may take longer but produces higher quality results)
dev_t.insert([{'prompt': 'A highly detailed oil painting of a wizard casting a spell in an ancient library'}])
Inserting rows into `flux_dev`: 1 rows [00:00, 527.72 rows/s]
Inserted 1 row with 0 errors.
1 row inserted, 3 values computed.
# Display the result
dev_t.select(dev_t.prompt, dev_t.image).head()

Exploring Available Models

fal.ai offers a wide variety of models. Here are some popular ones you can try:

Image Generation Models

  • fal-ai/flux/schnell - Fast FLUX model for quick image generation
  • fal-ai/flux/dev - Higher quality FLUX model (slower)
  • fal-ai/fast-sdxl - Fast Stable Diffusion XL
  • fal-ai/stable-diffusion-v3-medium - Stable Diffusion 3 Medium

Other Models

  • fal-ai/fast-lightning-sdxl - Ultra-fast SDXL variant
  • fal-ai/recraft-v3 - Recraft V3 for design-focused generation
To use a different model, simply change the app parameter in your fal.run() call.

Working with Batch Processing

Pixeltable’s computed columns make it easy to process multiple images in batch. Let’s create a larger dataset:
# Create a batch processing table
batch_t = pxt.create_table('fal_demo.batch', {'category': pxt.String, 'description': pxt.String})

# Create a prompt by combining category and description
batch_t.add_computed_column(
    prompt=pxt.functions.string.format('A {} that is {}', batch_t.category, batch_t.description)
)

# Generate images
batch_t.add_computed_column(
    response=fal.run(
        input={'prompt': batch_t.prompt},
        app='fal-ai/flux/schnell'
    )
)

batch_t.add_computed_column(image=batch_t.response['images'][0]['url'].astype(pxt.Image))
Created table ‘batch’.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
Added 0 column values with 0 errors.
No rows affected.
# Insert a batch of prompts
batch_t.insert([
    {'category': 'landscape', 'description': 'peaceful and zen-like'},
    {'category': 'portrait', 'description': 'mysterious and ethereal'},
    {'category': 'abstract art', 'description': 'colorful and energetic'},
    {'category': 'architecture', 'description': 'modern and minimalist'},
    {'category': 'animal', 'description': 'cute and fluffy'}
])
Inserting rows into `batch`: 5 rows [00:00, 1024.65 rows/s]
Inserted 5 rows with 0 errors.
5 rows inserted, 30 values computed.
# View all results
batch_t.select(batch_t.category, batch_t.description, batch_t.image).show()

Tips and Best Practices

  1. Rate Limiting: fal.ai has rate limits. Pixeltable respects these limits by default. You can configure custom rate limits in your Pixeltable config.
  2. Model Selection:
    • Use flux/schnell for fast prototyping and when speed is critical
    • Use flux/dev when you need higher quality and can afford longer generation times
    • Use fast-sdxl for a good balance of speed and quality
  3. Prompt Engineering: Good prompts lead to better results. Be specific and descriptive.
  4. Negative Prompts: Use negative prompts to exclude unwanted elements from your images.
  5. Caching: Pixeltable automatically caches results, so re-running the same prompt won’t incur additional costs.

Learn More

If you have any questions, don’t hesitate to reach out on our Discord community!