Resource Requests
Resource requests example.
Example: resource_requests.py.
Run it
python examples/resource_requests.py
from __future__ import annotations
import asyncio
from pathlib import Path
import numpy as np
import pandas as pd
from flux import ExecutionContext
from flux.domain.resource_request import ResourceRequest
from flux.task import task
from flux.utils import to_json
from flux.workflow import workflow
@task
async def load_dataset(file_path: str) -> pd.DataFrame:
"""Load a dataset from a CSV file or create a sample dataframe if file doesn't exist."""
print(f"Loading dataset from {file_path}")
if not Path(file_path).exists():
print(f"File {file_path} not found. Creating a sample dataframe instead.")
# Create a sample dataframe with numeric features and a target column
np.random.seed(42) # For reproducibility
sample_size = 100
df = pd.DataFrame(
{
"feature1": np.random.normal(0, 1, sample_size),
"feature2": np.random.normal(5, 2, sample_size),
"feature3": np.random.uniform(0, 10, sample_size),
"categorical": np.random.choice(["A", "B", "C"], sample_size),
"target": np.random.randint(0, 2, sample_size), # Binary classification target
},
)
return df
return pd.read_csv(file_path)
@task
async def preprocess_data(df: pd.DataFrame) -> pd.DataFrame:
"""Preprocess the dataset (normalize, handle missing values, etc.)."""
print("Preprocessing data...")
# Simulate CPU-intensive preprocessing
await asyncio.sleep(1)
# Normalize numerical features
for col in df.select_dtypes(include=[np.number]).columns:
if col != "target":
df[col] = (df[col] - df[col].mean()) / df[col].std()
return df
@task
async def split_train_test(
df: pd.DataFrame,
test_size: float = 0.2,
) -> tuple[pd.DataFrame, pd.DataFrame]:
"""Split the dataset into training and testing sets."""
print(f"Splitting dataset with test_size={test_size}")
# Simple split based on random indices
msk = np.random.rand(len(df)) < (1 - test_size)
train = df[msk]
test = df[~msk]
return train, test
@task
async def train_model(train_df: pd.DataFrame) -> dict:
"""Train a simple model on the dataset."""
print("Training model (simulating GPU usage)...")
# Simulate GPU-intensive model training
await asyncio.sleep(3)
return {
"model_type": "simple_classifier",
"accuracy": 0.85 + np.random.random() * 0.1,
"training_time": 3.0,
"model_size": "10MB",
}
@task
async def evaluate_model(model: dict, test_df: pd.DataFrame) -> dict:
"""Evaluate the trained model on test data."""
print("Evaluating model...")
# Simulate model evaluation
await asyncio.sleep(1)
return {
**model,
"test_accuracy": model["accuracy"] - 0.05 + np.random.random() * 0.1,
"precision": 0.83 + np.random.random() * 0.1,
"recall": 0.81 + np.random.random() * 0.1,
}
@task
async def generate_visualizations(df: pd.DataFrame, model_results: dict) -> dict:
"""Generate visualizations of the data and model results."""
print("Generating visualizations...")
# Simulate visualization generation
await asyncio.sleep(2)
return {
"plots_generated": 5,
"data_summary": {
"shape": df.shape,
"columns": df.columns.tolist(),
"numeric_stats": df.describe().to_dict(),
},
"model_performance": model_results,
}
# Data processing workflow with CPU and memory requirements
@workflow.with_options(
name="data_processing_workflow",
requests=ResourceRequest(
cpu=4,
memory="8Gi",
packages=["pandas>=1.3.0", "numpy"],
),
)
async def data_processing_workflow(ctx: ExecutionContext[dict[str, str]]):
"""Process data with specific CPU and memory requirements."""
df = await load_dataset(ctx.input["data_path"])
processed_df = await preprocess_data(df)
train_df, test_df = await split_train_test(processed_df)
return {
"train_data": train_df,
"test_data": test_df,
"data_stats": {
"total_rows": len(df),
"train_rows": len(train_df),
"test_rows": len(test_df),
},
}
# Model training workflow with GPU requirements
@workflow.with_options(
name="model_training_workflow",
requests=ResourceRequest.with_gpu(1),
)
async def model_training_workflow(ctx: ExecutionContext[dict]):
"""Train ML model with GPU requirements."""
train_df = ctx.input["train_data"]
test_df = ctx.input["test_data"]
model = await train_model(train_df)
evaluation = await evaluate_model(model, test_df)
return evaluation
# Visualization workflow with specific package requirements
@workflow.with_options(
name="visualization_workflow",
requests=ResourceRequest.with_packages(
["matplotlib>=3.5.0", "seaborn>=0.11.0"],
),
)
async def visualization_workflow(ctx: ExecutionContext[dict]):
"""Generate visualizations with specific package requirements."""
df = pd.concat([ctx.input["train_data"], ctx.input["test_data"]])
model_results = ctx.input["model_results"]
visualizations = await generate_visualizations(df, model_results)
return visualizations
if __name__ == "__main__": # pragma: no cover
input_data = {
"data_path": "examples/data/sample.csv",
}
data_ctx = data_processing_workflow.run(input_data)
print(data_ctx.to_json())
model_ctx = model_training_workflow.run(data_ctx.output)
print(model_ctx.to_json())
viz_input = {**data_ctx.output, "model_results": model_ctx.output}
viz_ctx = visualization_workflow.run(viz_input)
print(viz_ctx.to_json())
print(
to_json(
{
"data_stats": data_ctx.output["data_stats"],
"model_performance": model_ctx.output,
"visualizations": viz_ctx.output,
},
),
)
Last verified against Flux 0.56.0.