Test Profile Configuration
Pipelex uses a flexible test profile system to control which AI models are included in parametrized tests. This allows developers to quickly iterate with a small set of models during development, while still being able to run comprehensive tests across all available models.
Overview
The test profile system consists of:
- Profile definitions in
.pipelex-dev/test_profiles.toml - Model collections organized by provider/type
- A preprocessing command that generates fixture files
- Make targets for easy regeneration
Quick Start
# Regenerate test fixtures with default (dev) profile
make regenerate-test-models
# Regenerate with a specific profile
make regenerate-test-models TEST_PROFILE=full
make regenerate-test-models TEST_PROFILE=coverage
make regenerate-test-models TEST_PROFILE=ci
Profile Configuration File
The configuration lives in .pipelex-dev/test_profiles.toml:
################################################################################
# Collections - Reusable lists of models/backends
################################################################################
[collections.backends]
all = ["pipelex_gateway", "anthropic", "openai", "google", ...]
[collections.llm]
anthropic = ["claude-3-haiku", "claude-4-opus", "claude-4.5-sonnet", ...]
openai = ["gpt-4o-mini", "gpt-4o", "gpt-5", ...]
google = ["gemini-2.5-flash", "gemini-2.5-pro", ...]
[collections.img_gen]
openai = ["gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5"]
fal = ["flux-pro", "flux-2", "flux-2-pro"]
[collections.extract]
from_pdf = ["pypdfium2-extract-pdf", "docling-extract-text", "mistral-ocr", ...]
from_image = ["docling-extract-text", "mistral-ocr", "deepseek-ocr", ...]
################################################################################
# Profiles
################################################################################
[profiles.dev]
description = "Quick dev testing with fast and cheap models"
backends = ["pipelex_gateway", "internal"]
llm_models = ["claude-4.5-haiku", "gpt-4o-mini", "gemini-2.5-flash-lite"]
img_gen_models = ["gpt-image-1-mini"]
extract_models = ["@from_pdf"]
[profiles.full]
description = "All available models"
include_all = true
Model List Syntax
The profile system supports several powerful syntax options for specifying models:
| Syntax | Description | Example |
|---|---|---|
"model-name" |
Specific model (direct reference) | "gpt-4o-mini" |
@collection |
All models from a named collection | "@anthropic", "@from_pdf" |
backend:* |
All models from a specific backend | "openai:*" |
pattern* |
Glob pattern matching | "claude-4*", "gpt-*" |
* |
All available models | "*" |
!pattern |
Exclude models matching pattern | "!*-codex" |
Examples
# Use all Anthropic models from the collection
llm_models = ["@anthropic"]
# Use all Claude 4.5 models (glob pattern)
llm_models = ["claude-4.5-*"]
# Use all GPT models except codex variants
llm_models = ["gpt-*", "!*-codex", "!*-codex-*"]
# Combine collection reference with specific models
llm_models = ["@anthropic", "gpt-4o-mini", "gemini-2.5-flash"]
# Use all models from the openai backend
llm_models = ["openai:*"]
# Use all backends
backends = ["@all"]
Built-in Profiles
dev (default)
Quick development testing with fast, cheap models from key providers.
[profiles.dev]
backends = ["pipelex_gateway", "internal"]
llm_models = ["claude-4.5-haiku", "gpt-4o-mini", "gemini-2.5-flash-lite"]
img_gen_models = ["gpt-image-1-mini"]
extract_models = ["@from_pdf"]
ci
Minimal set for CI pipelines - no actual inference.
[profiles.ci]
backends = ["azure_openai"]
llm_models = ["gpt-4o-mini"]
img_gen_models = []
extract_models = []
coverage
One model per backend for coverage testing.
[profiles.coverage]
backends = ["anthropic", "openai", "google", "mistral", "internal"]
llm_models = ["claude-4.5-haiku", "gpt-4o-mini", "gemini-2.5-flash-lite", "mistral-large"]
img_gen_models = ["gpt-image-1", "nano-banana"]
extract_models = ["pypdfium2-extract-pdf"]
full
All available models from all backends.
[profiles.full]
include_all = true
all_backends
Test select models across all backends.
[profiles.all_backends]
backends = ["@all"]
llm_models = ["claude-4.5-haiku", "gpt-4o-mini", "gemini-2.5-flash-lite"]
img_gen_models = ["gpt-image-1-mini"]
extract_models = ["@from_pdf"]
How It Works
1. Model Discovery
The preprocessing command discovers available models from:
- Backend TOML files in
pipelex/backends/*.toml - Pipelex Gateway remote configuration
2. Profile Resolution
When you run make regenerate-test-models TEST_PROFILE=dev:
- Collections are loaded from
[collections.*]sections - The specified profile is loaded from
[profiles.dev] - Model specifiers are resolved:
@collection_nameexpands to the collection's modelsbackend:*expands to all models from that backend- Glob patterns (
claude-*) are matched against known models - Exclusions (
!pattern) are removed
- Results are filtered by allowed backends
3. Fixture Generation
The resolved model/backend pairs are written to:
tests/integration/pipelex/fixtures/_generated_model_sets.py
This file contains:
LLM_MODEL_BACKEND_PAIRS: list[tuple[str, str]] = [
("claude-4.5-haiku", "pipelex_gateway"),
("gpt-4o-mini", "pipelex_gateway"),
...
]
IMG_GEN_MODEL_BACKEND_PAIRS: list[tuple[str, str]] = [...]
EXTRACT_MODEL_BACKEND_PAIRS: list[tuple[str, str]] = [...]
CLI Command
For more control, use the CLI directly:
# Preview what would be generated
pipelex-dev preprocess-test-models --profile dev
# Generate fixtures
pipelex-dev preprocess-test-models --generate-fixtures --profile dev
# Output full availability JSON
pipelex-dev preprocess-test-models --output-json --profile full
# Quiet mode (minimal output)
pipelex-dev preprocess-test-models --generate-fixtures --profile dev --quiet
Adding a New Profile
-
Add your profile to
.pipelex-dev/test_profiles.toml:[profiles.my_profile] description = "My custom profile for X testing" backends = ["anthropic", "openai"] llm_models = ["claude-4.5-*", "gpt-4o-mini"] img_gen_models = [] extract_models = [] -
Regenerate fixtures:
make regenerate-test-models TEST_PROFILE=my_profile
Adding Models to Collections
When new models become available, add them to the appropriate collection:
[collections.llm]
# Add new model to existing manufacturer collection
anthropic = [
"claude-3-haiku",
"claude-4.5-sonnet",
"claude-5-opus", # New model
]
Collections serve as documentation of available models and can be referenced in any profile.
Local Overrides
For personal customizations that shouldn't be committed to the repository, create a .pipelex-dev/test_profiles_override.toml file. This file is gitignored and will be deep-merged on top of the base configuration.
This is useful for:
- Testing with specific models not in standard profiles
- Creating personal profiles tailored to your development workflow
- Temporarily modifying collections without affecting the team
Example Override File
# .pipelex-dev/test_profiles_override.toml
# Add a personal profile
[profiles.my_local]
description = "My local testing profile"
backends = ["pipelex_gateway"]
llm_models = ["claude-4.5-sonnet", "gpt-4o"]
img_gen_models = []
extract_models = []
# Override an existing profile
[profiles.dev]
llm_models = ["claude-4.5-opus"] # I prefer testing with opus locally
# Extend a collection
[collections.llm]
my_favorites = ["claude-4.5-sonnet", "gpt-4o", "gemini-2.5-pro"]
After creating or modifying your override file, regenerate fixtures:
make regenerate-test-models TEST_PROFILE=my_local
Team Collaboration
Since the override file is gitignored, each developer can maintain their own testing preferences without conflicts. The base .pipelex-dev/test_profiles.toml remains the shared source of truth for CI and team workflows.
Best Practices
- Use
devprofile during development - Fast iteration with minimal API calls - Use
coverageprofile for PR testing - Ensures all backends work - Use
fullprofile sparingly - Only when testing model-specific behavior - Use glob patterns for model families -
claude-4.5-*catches all 4.5 variants
Troubleshooting
No models in profile
If a profile shows 0 models, check:
- The specified models exist in the backend configurations
- The backends list includes backends that have those models
- Collection names are spelled correctly (case-sensitive)
Empty list vs missing key
llm_models = []- No LLM models included- Key not present - All LLM models from allowed backends included
Glob patterns not matching
Glob patterns use fnmatch syntax:
*matches any characters?matches single character- Patterns are case-sensitive