mlodaAPI
The mlodaAPI class serves as the primary interface for interacting with the core system, streamlining the setup and execution of computational workflows
Major components (and steps)
-
Configuration
Initialize the mloda with features, compute frameworks, and other settings to configure your environment.
-
Engine Setup
Create an execution plan by setting up the engine, which orchestrates the computation based on the defined features and configurations.
-
Runner Setup
Prepare the runner that will execute the plan, ensuring that all components are ready for computation.
-
Run Engine Computation
Apply the runner to execute the computations based on the prepared execution plan, managing the lifecycle of the computational process.
This means, depending on your needs, you can run them all at once (batch run) or split them up, e.g. for realtime needs (inference). For incremental result delivery see Streaming.
Configuration for mlodaAPI
- requested_features: Specify the features to process (as names, Feature objects, or a Features container).
- compute_frameworks (optional): Limit the compute frameworks using framework types or names.
- links (optional): Define dataset merging links with Link objects.
- data_access_collection (optional): Provide data sources for feature identification.
Runner & Execution Configuration
- function_extender (optional): Add function extenders to customize computations.
- parallelization_modes (optional): Choose between sync, threading, or multiprocessing modes. (Default: sync)
- flight_server (optional): Specify a flight server for multiprocessing only.
- column_ordering (optional): Control the ordering of result columns.
Accepts
"alphabetical"(sort columns A-Z) or"request_order"(preserve the order features were requested). Default:None(no guaranteed order).
from mloda.user import mloda
api_data = {"SampleData": {"FeatureA": [1], "FeatureB": [2], "FeatureC": [3]}}
# Alphabetical ordering
result = mloda.run_all(
["FeatureC", "FeatureA", "FeatureB"],
compute_frameworks=["PandasDataFrame"],
api_data=api_data,
column_ordering="alphabetical" # Result columns: FeatureA, FeatureB, FeatureC
)
# Preserve request order
result = mloda.run_all(
["FeatureC", "FeatureA", "FeatureB"],
compute_frameworks=["PandasDataFrame"],
api_data=api_data,
column_ordering="request_order" # Result columns: FeatureC, FeatureA, FeatureB
)
Two-Phase Execution: prepare() + run()
For realtime or inference scenarios, split configuration from execution.
prepare() builds the execution plan once; run() executes it with fresh data each time.
from mloda.user import mloda
# 1. Prepare once, with a representative shape of the data
session = mloda.prepare(
["col__mean_aggr"],
compute_frameworks=["PandasDataFrame"],
api_data={"MyKey": {"col": [0.0]}},
)
# 2. Run multiple times with different data
result_1 = session.run(api_data={"MyKey": {"col": [1.0, 2.0]}})
result_2 = session.run(api_data={"MyKey": {"col": [3.0, 4.0]}})
run() also accepts an artifacts parameter for switching between artifact
save and load modes across calls. See Artifacts for details.
run_all() is equivalent to prepare() followed by a single run().
stream_all() is equivalent to prepare() followed by a single stream_run().
For per-group streaming with plan reuse, call session.stream_run() instead of session.run() -- it yields each feature group's result as it completes. See Streaming for details.
Plugin Discovery
mloda provides functions to discover and inspect available plugins. Import them from mloda.steward:
from mloda.steward import (
get_feature_group_docs,
get_compute_framework_docs,
get_extender_docs,
resolve_feature,
)
resolve_feature
Resolve a single feature name (or a Feature) to its matching FeatureGroup without running the request, reporting failures in result.error instead of raising. It takes feature (str | Feature) positionally plus keyword-only options, plugin_collector, feature_group, links, data_access_collection, and compute_frameworks, and returns a ResolvedFeature (8 fields, including candidates, error, supported_compute_frameworks, subtype).
from mloda.steward import resolve_feature
result = resolve_feature("my_feature_name")
if result.feature_group:
print(f"Resolved to: {result.feature_group.__name__}")
else:
print(f"Error: {result.error}")
See Discover Plugins for the full signature, every ResolvedFeature field, and worked examples (options-gated groups, scoping, broken framework declarations). resolve_feature is exported from mloda.provider, mloda.user, and mloda.steward; the ResolvedFeature return type is exported from mloda.steward.
explain and resolved_plan
The runtime counterpart to resolve_feature: mlodaAPI.explain(...) builds the execution plan for a request without running it, and session.resolved_plan() returns the same records for a prepared session (before or after run()). Both return a list[PlanStep] in execution-plan order. Every explain parameter after features is keyword-only.
explain re-resolves the plan from scratch. It answers "what would this request resolve to", it is not a record of a prior run_all execution. For the plan of a run that actually happened, use the return value directly: run_all returns a RunResult (a list with a read-only plan property) and stream_all returns a ResultStream (generator-compatible, plan available before consuming). One planning pass serves both the results and the plan, unlike explain, which re-resolves.
from mloda.user import mloda
sales_data = {"SalesData": {"sales": [10.0, 20.0, 30.0]}}
results = mloda.run_all(["sales__mean_aggr"], compute_frameworks=["PandasDataFrame"], api_data=sales_data)
for step in results.plan:
print(step.step_kind, step.feature_names)
To match a run_all resolution, pass the same parallelization_modes: run_all defaults to {ParallelizationMode.SYNC}, prepare/explain default to None, and compute frameworks are filtered by mode.
from mloda.user import mloda
# "sales" arrives through api_data here; in your own request it can come from any FeatureGroup.
for step in mloda.explain(["sales__mean_aggr"], compute_frameworks=["PandasDataFrame"], api_data=sales_data):
print(step.step_kind, step.feature_names, step.feature_group_name, step.compute_framework_name)
Returns: PlanStep dataclass (frozen) with fields:
- step_kind (
Literal["compute", "join", "transform"]). - feature_names (
tuple[str, ...]): Features computed by a compute step, empty otherwise. This includes engine-injected features (link index features, global-filter features); use the requested/injected split below to tell them apart. - requested_feature_names (
tuple[str, ...]): The user-requested subset offeature_nameson a compute step, empty for join and transform steps. - injected_feature_names (
tuple[str, ...]): The engine-injected/dependency remainder offeature_nameson a compute step, empty for join and transform steps. - feature_group (
type[FeatureGroup] | None): Resolved FeatureGroup; the destination for a transform step; the link's declared left side for a join. - compute_framework (
type[ComputeFramework] | None): Selected ComputeFramework; the destination for a transform step; the merge destination for a join. - source_feature_group / source_compute_framework: Origin of a transform step. For a join: the link's declared right side, and the framework merged in.
- join_type (
str | None): The link's join type ("inner","left", ...) for a join step, None otherwise. - join_destination_side (
Literal["left", "right"] | None): the declared side that holds the merge destination, for a join step; None otherwise. - join_inverted (
bool | None, property):join_destination_side == "right", None without a side. - join_token (
UUID | None): the join's completion token, the uuid the scheduler tracks, for a join step; None otherwise. Excluded from equality (fresh per planning run). - declared_left_frameworks / declared_right_frameworks (
tuple[type[ComputeFramework], ...]): the compute frameworks each declared side's parent features declared as candidates, sorted by class name, for a join step; empty otherwise, and empty when the plan recorded no candidates for the side. APPEND/UNION sides carry only the index-bearing parent. - feature_group_name / compute_framework_name / source_feature_group_name / source_compute_framework_name (
str | None): Class names of the above, None when unset. - declared_left_framework_names / declared_right_framework_names (
tuple[str, ...]): class names of the two tuples above, same order.
Join semantics: for a join step the *_feature_group fields are the link's declared left/right sides, while compute_framework/source_compute_framework are the merge destination and the framework merged in, which may belong to the declared right side. join_destination_side is resolved from the two declared sides' framework candidates for every join type except APPEND and UNION, which always report "left"; a right join queues its destination on the declared right side, so it reports "right" in the common case.
How the engine tracks request provenance
The requested/injected split above is derived from a per-feature flag, not from re-matching names against the request.
Feature.initial_requested_data(bool, defaultFalse) marks a feature that the user asked for directly. It also decides which features come back in the run result, which is why a FeatureGroup may set it on a feature it created itself.mlodaAPI._process_featuressets it toTrueon every feature of the incoming request, before resolution. Features created during resolution (input features of a FeatureGroup, link index features, global-filter features) keep theFalsedefault, unless a FeatureGroup opts one in explicitly:input_featuresmay construct aFeaturewithinitial_requested_data=Trueto surface it in the results, and then it counts as requested in the split too.FeatureSet.get_initial_requested_features()returns the sorted, deduplicated names of the flagged features in that set.PlanStep.requested_feature_namesis that accessor's output for a compute step's FeatureSet;injected_feature_namesis the rest offeature_names. Both are sorted, so they do not follow the order offeature_names, and both are empty on join and transform steps, which carry no FeatureSet.
from mloda.user import mloda
for step in mloda.explain(["sales__mean_aggr"], compute_frameworks=["PandasDataFrame"], api_data=sales_data):
print(step.requested_feature_names, step.injected_feature_names)
diagnose and resolution_report
diagnose and resolution_report() are the non-raising counterparts to explain and resolved_plan(): where the plan-based pair returns PlanStep records, these return the resolution facts a failing request would otherwise raise.
mlodaAPI.diagnose(features, ...) runs the whole-request preflight without raising and returns a single ResolutionDiagnosis. It takes the same arguments as explain (every parameter after features is keyword-only). On success its records equal session.resolution_report() and complete is True; on a resolution failure it carries the records resolved before the failing feature plus feature_name, failed_result, and message; on an environment or config failure (redefinition conflict, framework-declaration error, compute-framework pin) it returns records=[], complete=False, and only message.
session.resolution_report() returns the list[ResolutionRecord] captured while prepare() planned the request, one per feature, available before or after run().
from mloda.user import mlodaAPI
diagnosis = mlodaAPI.diagnose(["sales__mean_aggr"], compute_frameworks=["PandasDataFrame"])
if diagnosis.complete:
for record in diagnosis.records:
print(record.feature_name, record.requested)
else:
print(diagnosis.feature_name, diagnosis.message)
When the same request is run rather than diagnosed, the failure raises FeatureResolutionError (below).
Resolution result types
Import the typed resolution surfaces from mloda.provider (also re-exported from mloda.user and mloda.steward):
from mloda.provider import FeatureResolutionError, ResolutionDiagnosis, ResolutionRecord
FeatureResolutionError(aValueErrorsubclass): raised during planning (mlodaAPI(...)/prepare()/run_all()) when a feature does not resolve to exactly one FeatureGroup. Attributes:feature_name(str),result(EvaluationResult, the captured per-candidate elimination facts),partial_records(tuple[ResolutionRecord, ...], features resolved before the failure, capped at the last 1000). Because it subclassesValueError, existingexcept ValueErrorhandlers keep working; catchFeatureResolutionErrorto read the attributes. See Feature Group Resolution Errors.ResolutionDiagnosis(frozen dataclass): the return value ofdiagnose, never raised. Fields:records(list[ResolutionRecord]),complete(bool),feature_name(str | None),failed_result(EvaluationResult | None),message(str | None).ResolutionRecord(frozen dataclass): one per feature, returned insideresolution_report(),ResolutionDiagnosis.records, andFeatureResolutionError.partial_records; never raised. Fields:feature_name(str),requested(bool),result(EvaluationResult).
EvaluationResult is the captured matcher outcome carried by the fields above; it is defined in mloda.core.prepare.resolution_types and is not part of the public __init__ exports.
get_feature_group_docs
Get documentation for feature groups with optional filtering.
from mloda.steward import get_feature_group_docs
# Get all feature groups
all_fgs = get_feature_group_docs()
# Filter by name
fgs = get_feature_group_docs(name="timestamp")
# Filter by compute framework
fgs = get_feature_group_docs(compute_framework="PandasDataFrame")
Parameters:
- name (
str, optional): Filter by name (case-insensitive partial match). - search (
str, optional): Search in description (case-insensitive partial match). - compute_framework (
str | Type[ComputeFramework], optional): Filter by compute framework. - version_contains (
str, optional): Filter by version substring.
Returns: List[FeatureGroupInfo] sorted by name.
get_compute_framework_docs
Get documentation for compute frameworks with optional filtering.
from mloda.steward import get_compute_framework_docs
# List every framework (is_available flags whether its backend library is installed)
frameworks = get_compute_framework_docs()
# Only frameworks whose backend library is installed
available_frameworks = get_compute_framework_docs(available_only=True)
Parameters:
- name (
str, optional): Filter by name (case-insensitive partial match). - search (
str, optional): Search in description (case-insensitive partial match). - available_only (
bool, defaultFalse): By default all frameworks are listed (withis_availableas the flag); setavailable_only=Trueto filter to available frameworks only.
Returns: List[ComputeFrameworkInfo] sorted by name.
get_extender_docs
Get documentation for extenders with optional filtering.
from mloda.steward import get_extender_docs
# Get all extenders
extenders = get_extender_docs()
# Filter by wrapped function type
extenders = get_extender_docs(wraps="formula")
Parameters:
- name (
str, optional): Filter by name (case-insensitive partial match). - search (
str, optional): Search in description (case-insensitive partial match). - wraps (
str, optional): Filter by wrapped function type (case-insensitive exact match).
Returns: List[ExtenderInfo] sorted by name.