Decorators
feature
feature(_cls: type[T] | Callable[[Model], FeatureResult | BaseModel | object] | None = None, *, feature_id: str | None = None, feature_registry: Registry[BaseFeature] = Provide[RegistryContainer.feature_registry]) -> Callable[[type[T] | Callable[[Model], FeatureResult | BaseModel | object]], type[BaseFeature[FeatureResult]] | type[T]] | type[BaseFeature[FeatureResult]] | type[T]
feature(
_cls: type[T],
*,
feature_id: str | None = None,
feature_registry: Registry[BaseFeature] = Provide[
RegistryContainer.feature_registry
],
) -> type[T]
Register a class or function as a feature.
The decorated class must be a subclass of the BaseFeature protocol, or a decorated
function will be automatically wrapped as a BaseFeature subclass.
Parameters:
-
_cls(type[T], default:None) –The class to be decorated. If None, returns a decorator function.
-
feature_id(str | None, default:None) –Set a custom ID for the feature. If not provided, the ID will be generated automatically from the module and class/function name. It's recommended to not set this parameter.
-
feature_registry((Registry[BaseFeature], injected), default:Provide[feature_registry]) –The registry where the feature will be registered. Injected by dependency container.
Returns:
-
Callable[[type[T]], type[T]] | type[T]–Either the decorated class/function or a decorator function.
Examples:
Decorate a class as a feature:
>>> from luna_bench.base_components import BaseFeature
>>> from luna_model import Model
>>> from pydantic import BaseModel
>>>
>>> @feature
... class MyFeature(BaseFeature):
... def run(self, model: Model) -> BaseModel:
... # Extract and return feature data
... return {"feature_value": 42}
Decorate a function as a feature:
>>> @feature
... def image_dimensions(model: Model) -> dict:
... # Extract image dimensions from model
... return {"width": 640, "height": 480}
Use a custom feature ID:
algorithm
algorithm(_cls: type[T] | Callable[[Model], Solution] | None = None, *, algorithm_id: str | None = None, algorithm_sync_registry: Registry[BaseAlgorithmSync] = Provide[RegistryContainer.algorithm_sync_registry], algorithm_async_registry: Registry[BaseAlgorithmAsync[Any]] = Provide[RegistryContainer.algorithm_async_registry]) -> Callable[[type[T] | Callable[[Model], Solution]], type[T] | type[BaseAlgorithmSync]] | type[T] | type[BaseAlgorithmSync]
Register a class or function as an algorithm.
The decorated class must be a subclass of BaseAlgorithmSync or
BaseAlgorithmAsync. When decorating a function, it is wrapped in a
dynamic class and registered with the background task queue.
metric
metric(_cls: type[BaseMetric[Any]] | Callable[[Solution, FeatureResultContainer], MetricResult | float | int] | list[type[BaseFeature[Any]]] | tuple[type[BaseFeature[Any]], ...] | type[BaseFeature[Any]] | None = None, *, metric_id: str | None = None, metric_registry: Registry[BaseMetric] = Provide[RegistryContainer.metric_registry]) -> Callable[[type[T] | Callable[[Solution, FeatureResultContainer], MetricResult | float | int]], type[T] | type[BaseMetric[MetricResult]]] | type[T] | type[BaseMetric[MetricResult]]
metric(
_cls: type[T],
*,
metric_id: str | None = None,
metric_registry: Registry[BaseMetric[Any]] = Provide[
RegistryContainer.metric_registry
],
) -> type[T]
metric(
_cls: Callable[
[Solution, FeatureResultContainer],
MetricResult | float | int,
],
*,
metric_id: str | None = None,
metric_registry: Registry[BaseMetric[Any]] = Provide[
RegistryContainer.metric_registry
],
) -> type[BaseMetric[MetricResult]]
metric(
_cls: type[BaseFeature[Any]],
*,
metric_id: str | None = None,
metric_registry: Registry[BaseMetric[Any]] = Provide[
RegistryContainer.metric_registry
],
) -> Callable[
[
type[BaseMetric[Any]]
| Callable[
[Solution, FeatureResultContainer],
MetricResult | float | int,
]
],
type[BaseMetric[Any]] | type[BaseMetric[MetricResult]],
]
metric(
_cls: list[type[BaseFeature[Any]]]
| tuple[type[BaseFeature[Any]], ...],
*,
metric_id: str | None = None,
metric_registry: Registry[BaseMetric[Any]] = Provide[
RegistryContainer.metric_registry
],
) -> Callable[
[
type[BaseMetric[Any]]
| Callable[
[Solution, FeatureResultContainer],
MetricResult | float | int,
]
],
type[BaseMetric[Any]] | type[BaseMetric[MetricResult]],
]
metric(
_cls: None = None,
*,
metric_id: str | None = None,
metric_registry: Registry[BaseMetric[Any]] = Provide[
RegistryContainer.metric_registry
],
) -> Callable[
[
type[T]
| Callable[
[Solution, FeatureResultContainer],
MetricResult | float | int,
]
],
type[T] | type[BaseMetric[MetricResult]],
]
Register a class or function as a metric component.
This decorator handles both class-based metrics (inheriting from BaseMetric) and
function-based metrics. When you decorate a function, it's automatically wrapped in a
BaseMetric subclass. You can also declare feature dependencies that your metric
needs to compute its result.
Parameters:
-
_cls(type[BaseMetric[Any]] | Callable[[Solution, FeatureResultContainer], MetricResult | float | int] | list[type[BaseFeature[Any]]] | tuple[type[BaseFeature[Any]], ...] | type[BaseFeature[Any]] | None, default:None) –The metric to register. Can be:
- A class inheriting from
BaseMetric(bare@metric) - A function taking (solution, feature_results) and returning float/int/MetricResult
- A single
BaseFeaturetype (becomes a dependency) - A list or tuple of
BaseFeaturetypes (dependencies)
When dependencies are passed, the decorator returns a decorator function that expects a metric class or function as its argument. In mose cases you don't need to set this field at all.
- A class inheriting from
-
metric_id(str | None, default:None) –Custom identifier for this metric in the registry. If omitted, an ID is auto-generated from the module and class/function name.
-
metric_registry(Registry[BaseMetric], default:Provide[metric_registry]) –The registry where this metric will be stored. Injected by the container. You do not need to set it.
Returns:
-
type[T] | type[BaseMetric[MetricResult]] | Callable–The registered metric class, or a decorator if dependencies were specified.
Notes
When decorating a function, the return type can be:
floatorint: automatically wrapped in aMetricResultMetricResult: returned as-is
The decorated function's signature is validated to ensure it matches the expected (solution, feature_results) parameters.
Examples:
Basic metric from a class:
>>> from luna_bench.base_components import BaseMetric
>>> from luna_model import Solution
>>> from luna_bench.base_components.data_types.feature_results import FeatureResults
>>> from luna_bench.types import MetricResult
>>>
>>> @metric
... class SolutionQuality(BaseMetric):
... def run(self, solution: Solution, feature_results: FeatureResults) -> MetricResult:
... ...
... return MetricResult(result=26.11)
Basic metric from a function:
>>> @metric
... def solve_time(solution: Solution, feature_results: FeatureResultContainer) -> float:
... return 26.11
Metric that depends on a feature:
>>> from luna_bench.base_components import BaseFeature
>>>
>>> @metric(Feature1)
... def feature_based_metric(solution: Solution, feature_results: FeatureResultContainer) -> float:
... return 26.11
Metric depending on multiple features:
plot
plot(required_components: type[BasePlot] | Callable[[BenchmarkResultContainer], None] | list[type[_REQUIRED_TYPES]] | tuple[type[_REQUIRED_TYPES], ...] | type[_REQUIRED_TYPES] | None = None, *, plot_id: str | None = None, plot_registry: Registry[BasePlot] = Provide[RegistryContainer.plot_registry]) -> Callable[[type[BasePlot] | Callable[[BenchmarkResultContainer], None]], type[BasePlot]] | type[BasePlot]
plot(
required_components: type[BasePlot],
*,
plot_id: str | None = None,
plot_registry: Registry[BasePlot] = Provide[
RegistryContainer.plot_registry
],
) -> type[BasePlot]
plot(
required_components: Callable[
[BenchmarkResultContainer], None
],
*,
plot_id: str | None = None,
plot_registry: Registry[BasePlot] = Provide[
RegistryContainer.plot_registry
],
) -> type[BasePlot]
plot(
required_components: type[_REQUIRED_TYPES],
*,
plot_id: str | None = None,
plot_registry: Registry[BasePlot] = Provide[
RegistryContainer.plot_registry
],
) -> Callable[
[
type[BasePlot]
| Callable[[BenchmarkResultContainer], None]
],
type[BasePlot],
]
plot(
required_components: list[type[_REQUIRED_TYPES]]
| tuple[type[_REQUIRED_TYPES], ...],
*,
plot_id: str | None = None,
plot_registry: Registry[BasePlot] = Provide[
RegistryContainer.plot_registry
],
) -> Callable[
[
type[BasePlot]
| Callable[[BenchmarkResultContainer], None]
],
type[BasePlot],
]
Register a class or function as a plot component.
This decorator registers visualization components that consume benchmark results. You can
register a class inheriting from BasePlot or wrap a function that handles the plotting
logic. Plots can declare dependencies on specific metrics or features they need to function.
Parameters:
-
required_components(type[BasePlot] | Callable[[BenchmarkResultContainer], None] | list[type[_REQUIRED_TYPES]] | tuple[type[_REQUIRED_TYPES], ...] | type[_REQUIRED_TYPES] | None, default:None) –The plot to register or its dependencies. Can be:
- A class inheriting from
BasePlot(bare@plot) - A function taking benchmark_results and returning None
- A single
BaseMetricorBaseFeaturetype (becomes a dependency) - A list or tuple of
BaseMetricand/orBaseFeaturetypes (dependencies)
When dependencies are passed, the decorator returns a decorator function that expects a plot class or function as its argument.
- A class inheriting from
-
plot_id(str | None, default:None) –Custom identifier for this plot in the registry. If omitted, an ID is auto-generated from the module and class/function name.
-
plot_registry(Registry[BasePlot], default:Provide[plot_registry]) –The registry where this plot will be stored. Injected by the container. You do not need to set it.
Returns:
-
type[BasePlot] | Callable–The registered plot class, or a decorator if dependencies were specified.
Notes
When decorating a function, it will be wrapped in a BasePlot subclass automatically.
The function receives the full BenchmarkResults object and is responsible for
extracting the data it needs to render the plot.
Examples:
Basic plot from a class:
>>> from luna_bench.custom import BasePlot, BenchmarkResults
>>>
>>> @plot
... class MyPlot(BasePlot):
... def run(self, benchmark_results: BenchmarkResults) -> None:
... # Plot or visualization the data
Basic plot from a function:
>>> @plot
... def quick_plot(benchmark_results: BenchmarkResultContainer) -> None:
... # Plot or visualization the data
Plot that depends on a specific metric:
>>> from luna_bench.metrics import Runtime
>>>
>>> @plot(Runtime)
... class RuntimeVisualization(BasePlot):
... def run(self, benchmark_results: BenchmarkResultContainer) -> None:
... # Plot or visualization the data
Plot that depends on multiple metrics: