Add a New Generation Strategy¶
How to add a new generation strategy to the Backend API. A generation strategy defines how a specific type of image generation is orchestrated — from receiving the API request to dispatching compute tasks.
Architecture Overview¶
The generation pipeline follows a layered architecture:
API Route
└─▶ GenerationWorkflowService
└─▶ IGenerationWorkflow
└─▶ GenerationService
└─▶ IGenerationStrategy ◀── you implement this
Key files:
| File | Purpose |
|---|---|
core/app/models/generation.py:49-58 |
GenerationStrategy enum (8 values) |
core/app/services/generation/strategies/igeneration_strategy.py:13-38 |
IGenerationStrategy protocol |
core/app/services/generation/strategies/__init__.py:25-36 |
Strategy registry list |
core/app/services/generation/strategies/generation_service.py:23-29 |
Strategy selection logic |
core/app/services/generation/strategies/base_generation_strategy.py |
Concrete example (BaseGenerationStrategy) |
core/app/api/routes/generations.py |
API routes (POST / at L225, specialized routes) |
Step 1: Add the Enum Value¶
Add your new strategy to the GenerationStrategy enum:
# core/app/models/generation.py
class GenerationStrategy(str, Enum):
BASE = "base"
EDIT = "edit"
VIDEO = "video"
# ... existing values ...
YOUR_STRATEGY = "your_strategy" # ← add here
This value is stored in the database and used as the discriminator throughout the pipeline.
Step 2: Implement the Strategy Class¶
Create a new file for your strategy that implements the IGenerationStrategy protocol:
# core/app/services/generation/strategies/your_strategy.py
from core.app.services.generation.strategies.igeneration_strategy import (
IGenerationStrategy,
)
from core.app.models.generation import GenerationStrategy
class YourStrategy(IGenerationStrategy):
"""Handles generation for your new strategy type."""
def strategy(self) -> GenerationStrategy:
"""Return the strategy enum value this class handles."""
return GenerationStrategy.YOUR_STRATEGY
async def create(self, ...) -> Generation:
"""Validate inputs and persist the generation record.
This is called when the API receives a generation request.
Perform any strategy-specific validation here before saving.
"""
# 1. Validate strategy-specific inputs
# 2. Create the Generation record
# 3. Return the persisted generation
...
async def generate(self, ...) -> Generation:
"""Execute the generation — typically by dispatching compute tasks.
This is called after create() to actually start the work.
"""
# 1. Build task parameters for the compute server
# 2. Create compute task(s) via the task service
# 3. Update generation status
# 4. Return the updated generation
...
Use BaseGenerationStrategy at core/app/services/generation/strategies/base_generation_strategy.py as a reference for the full method signatures and patterns.
Protocol, Not ABC
IGenerationStrategy is a Protocol class. You don't inherit from it — you just implement the same method signatures. Python's structural subtyping handles the rest.
Step 3: Register the Strategy¶
Add your strategy to the strategies list so GenerationService can discover it:
# core/app/services/generation/strategies/__init__.py
from .your_strategy import YourStrategy
strategies: list[IGenerationStrategy] = [
BaseGenerationStrategy(),
# ... existing strategies ...
YourStrategy(), # ← add here
]
GenerationService iterates this list at generation_service.py:23-29 to match the incoming GenerationStrategy enum value to the correct handler.
Step 4: Add an API Route (If Needed)¶
If your strategy needs a dedicated endpoint (like /generations/edit or /generations/video), add a route:
# core/app/api/routes/generations.py
@router.post("/your-strategy", response_model=GenerationPublic)
async def create_your_strategy_generation(
data: YourStrategyGenerationCreate,
generation_workflow: GenerationWorkflowServiceDep,
) -> Generation:
"""Create a generation using the your_strategy strategy."""
return await generation_workflow.create_and_generate(
data=data,
strategy=GenerationStrategy.YOUR_STRATEGY,
)
If your strategy works through the generic POST / endpoint (L225), you can skip this step — just make sure the request body includes strategy: "your_strategy".
Step 5: Create the Compute Task Type¶
Most generation strategies dispatch work to the Compute Server. If your strategy requires a new task type, follow the Add a Task Type tutorial.
If you're reusing an existing task type (e.g., the standard generation task), you just need to pass the correct parameters when creating the task in your generate() method.
Checklist¶
- Enum value added to
GenerationStrategy - Strategy class implements
strategy(),create(),generate() - Strategy registered in
strategies/__init__.py - API route added (if needed)
- Compute task type created or reused
- Tests cover create and generate flows
- Database migration created (if schema changes needed)
See Also¶
- Design Patterns -- Layered architecture and factory patterns used by the strategy pipeline
- Add a New Task Type -- Creating the compute server task type dispatched by your strategy