Overview

Recipe configurations allow you to define parameters that can be passed to your custom recipes. This provides flexibility and reusability, enabling you to run the same recipe with different parameters without modifying the code.

Basic Configuration Structure

Every recipe configuration inherits from InputConfig and defines the parameters your recipe expects:

from adaptive_harmony.runtime import InputConfig

class MyConfig(InputConfig):
    # Training parameters
    learning_rate: float = 0.001
    batch_size: int = 32
    epochs: int = 10
    
    # Model parameters
    model_name: AdaptiveModel
    max_length: int = 2048
    
    # Logging parameters
    log_interval: int = 100
    save_interval: int = 1000

Using Your Configuration

Once you’ve defined your configuration, you can use it in your recipe:

@recipe_main
async def main(config: MyConfig, ctx: RecipeContext):
    # Access configuration values
    print(f"Learning Rate: {config.learning_rate}")
    print(f"Batch size: {config.batch_size}")
    
    # Your recipe logic here
    # ...

Field Types and Annotations

Giving field types in the config will make sure to work with proper type and will render the field with the right widget in the UI. Below are all the types that you can define.

Basic Types

from pydantic import Field
from typing import Annotated

class BasicConfig(InputConfig):
    # String field with description
    string_field: Annotated[str, Field(description="A string field")] = "default value"
    
    # Integer field with validation
    integer_field: Annotated[int, Field(description="An integer field", min_value=1, max_value=10)] = 1
    
    # Float field
    float_field: Annotated[float, Field(description="A float field")] = 0.001
    
    # Boolean field
    boolean_field: Annotated[bool, Field(description="A boolean field")] = True

Collection Types

from typing import List, Set, Dict

class CollectionConfig(InputConfig):
    # List field with validation
    list_field: Annotated[List[str], Field(description="A list field", min_length=1, max_length=10)]
    
    # Set field
    set_field: Annotated[Set[str], Field(description="A set field")]
    
    # Dictionary field
    dict_field: Annotated[Dict[str, str], Field(description="A dict field")]

    # Literal enum field
    enum_field: Annotated[Literal["sgd", "adam"], Field(description="An enum field")] = "sgd"

Adaptive Model Fields

Adaptive provides special support for model fields, allowing you to pass model instances to your recipes:

from adaptive_harmony.runtime import AdaptiveModel

class ModelConfig(InputConfig):
    # Single model field
    model_field: Annotated[AdaptiveModel, Field(description="A model field")]
    
    # List of models
    model_list_field: Annotated[List[AdaptiveModel], Field(description="A list of models field")]
    
    # Set of models
    model_set_field: Annotated[Set[AdaptiveModel], Field(description="A set of models field")]

Adaptive Dataset Fields

Adaptive provides special support for model fields, allowing you to pass model instances to your recipes:

from adaptive_harmony.runtime import AdaptiveDataset

class DatasetConfig(InputConfig):
    # Single model field
    dataset_field: Annotated[AdaptiveDataset, Field(description="A dataset field")]
    
    # List of models
    dataset_list_field: Annotated[List[AdaptiveDataset], Field(description="A list of dataset field")]
    
    # Set of models
    dataset_set_field: Annotated[Set[AdaptiveDataset], Field(description="A set of dataset field")]

Nested Configurations

You can create complex configurations by nesting other config classes:

class MySubConfig(InputConfig):
    name: str
    value: int
    children: List[str]
    optimizer: Literal["sgd", "adam"]

class NestedConfig(InputConfig):
    # Single nested config
    sub_config: MySubConfig
    
    # List of nested configs
    sub_config_list: List[MySubConfig]