Documentation Index
Fetch the complete documentation index at: https://docs.adaptive-ml.com/llms.txt
Use this file to discover all available pages before exploring further.
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 it defines the parameters your recipe requires and/or optional “knobs” you want to expose for other users to tweak.
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
judge_model_name: AdaptiveModel
max_length: int = 2048
# Logging parameters
log_interval: int = 100
save_interval: int = 1000
Using your configuration
Once you’ve defined a configuration class, you can use it in your recipe by passing it as an input argument to your @recipe_main function.
@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
Once you are done developing and you upload your recipe to the recipe library in your Adaptive Deployment, you’ll want to make it as easy as possible for yourself or team mates to reuse it in the future. Adaptive automatically converts your input configurations into self-documented and type-safe widgets in the UI (enforcing types in Python SDK as well).
See an example of a very simple recipe config as rendered in the UI (you will find out more in launch recipe):
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]