rahul24raj's picture
Upload folder using huggingface_hub
585cd37 verified
"""12 task scenarios for the Fish Farm environment.
Easy (3): Single-concern, short episodes, forgiving thresholds
Medium (4): Multi-concern, events, cascading risks
Hard (3): Full lifecycle, compound events, multi-objective optimization
Extreme (2): Everything at once, frontier-model difficulty
Each task dict contains:
- initial_conditions: starting state overrides
- events: scheduled Event objects
- episode_hours: max episode length
- reward_weights: per-component weights for reward calculation
- grader: name of grading function
- description: natural language task briefing for the agent
- difficulty: easy/medium/hard/extreme
"""
from typing import Any, Dict, List
from .engine.events import Event
def _make_tasks() -> Dict[str, Dict[str, Any]]:
return {
# =====================================================================
# EASY TASKS — Single concern, learn one control at a time
# =====================================================================
"feeding_basics": {
"difficulty": "easy",
"episode_hours": 7 * 24,
"description": (
"You manage a healthy tilapia tank for 7 days. Your goal: feed the fish "
"to achieve steady growth without overfeeding. Fish start at 50g, target 55g+. "
"Keep FCR below 2.0. Zero fish should die from starvation or overfeeding."
),
"initial_conditions": {
"weight_g": 50.0, "population": 5000, "temp": 30.0,
"DO": 7.0, "TAN": 0.1, "pH": 7.5, "day_of_year": 90,
},
"events": [],
"reward_weights": {"growth": 0.5, "fcr": 0.3, "survival": 0.2},
"grader": "feeding_grader",
"target_weight": 55.0,
},
"oxygen_management": {
"difficulty": "easy",
"episode_hours": 3 * 24,
"description": (
"It's a hot week (air temp 35C). Dissolved oxygen is dropping. "
"Your job: keep DO above 5.0 mg/L at all times using the aerator. "
"Fish are already stocked at moderate density. Score based on "
"minimum DO maintained and time spent in safe zone."
),
"initial_conditions": {
"weight_g": 100.0, "population": 4000, "temp": 32.0,
"DO": 6.0, "TAN": 0.3, "pH": 7.5, "day_of_year": 180,
"base_air_temp": 35.0,
},
"events": [],
"reward_weights": {"do_stability": 0.5, "do_risk": 0.2, "efficiency": 0.3},
"grader": "oxygen_grader",
},
"water_quality_balance": {
"difficulty": "easy",
"episode_hours": 7 * 24,
"description": (
"Manage all water quality parameters simultaneously: keep DO > 5, "
"ammonia (UIA) < 0.05, pH 6.5-8.5, temperature 27-32C. "
"You have full control: feeding, aeration, heater, water exchange. "
"Score = time-averaged water quality composite score."
),
"initial_conditions": {
"weight_g": 80.0, "population": 5000, "temp": 29.0,
"DO": 7.0, "TAN": 0.2, "pH": 7.5, "day_of_year": 100,
},
"events": [],
"reward_weights": {"water_quality": 0.8, "efficiency": 0.2},
"grader": "water_quality_grader",
},
# =====================================================================
# MEDIUM TASKS — Multi-concern, events, cascading risks
# =====================================================================
"temperature_stress": {
"difficulty": "medium",
"episode_hours": 5 * 24,
"description": (
"ALERT: A heat wave is hitting. Air temperature will reach 38C for "
"3 days starting hour 24. You must manage water temperature using "
"heater (cooling mode), reduce feeding (fish eat less in heat), and "
"increase aeration (warm water holds less oxygen). "
"Goal: Keep fish alive and growing through the crisis."
),
"initial_conditions": {
"weight_g": 120.0, "population": 8000, "temp": 30.0,
"DO": 7.0, "TAN": 0.2, "pH": 7.5, "day_of_year": 200,
"base_air_temp": 33.0,
},
"events": [
Event(type="heat_wave", trigger_hour=24, severity=0.7,
duration_hours=72, description="HEAT WAVE: Air temp reaching 38C"),
],
"reward_weights": {"survival": 0.4, "growth": 0.3, "water_quality": 0.3},
"grader": "stress_survival_grader",
},
"ammonia_crisis": {
"difficulty": "medium",
"episode_hours": 3 * 24,
"description": (
"EMERGENCY: The biofilter has partially failed (50% capacity). "
"Ammonia is rising. You must: reduce feeding immediately, increase "
"water exchange, maintain aeration. Goal: prevent ammonia (UIA) from "
"reaching lethal levels (>0.6 mg/L) while keeping fish alive."
),
"initial_conditions": {
"weight_g": 150.0, "population": 7000, "temp": 30.0,
"DO": 6.5, "TAN": 1.5, "pH": 7.8, "day_of_year": 150,
},
"events": [
Event(type="equipment_failure", trigger_hour=0, severity=0.5,
duration_hours=48, description="BIOFILTER FAILURE: 50% capacity",
equipment="biofilter"),
],
"reward_weights": {"ammonia_control": 0.4, "survival": 0.4, "efficiency": 0.2},
"grader": "ammonia_crisis_grader",
},
"disease_outbreak": {
"difficulty": "medium",
"episode_hours": 10 * 24,
"description": (
"Fish are showing signs of stress — sluggish feeding, elevated mortality. "
"A disease may be developing. Watch for: increasing mortality, "
"feeding refusal, and behavioral changes. If you detect disease, "
"apply treatment ('antibiotics'). Also manage water quality to "
"reduce stress. Goal: contain the outbreak with <10% total mortality."
),
"initial_conditions": {
"weight_g": 200.0, "population": 6000, "temp": 31.0,
"DO": 6.0, "TAN": 0.5, "pH": 7.6, "day_of_year": 120,
},
"events": [
Event(type="disease", trigger_hour=12, severity=0.4,
duration_hours=0, description="Disease pathogen introduced"),
],
"reward_weights": {"survival": 0.4, "treatment_timing": 0.3, "water_quality": 0.3},
"grader": "disease_grader",
},
"growth_optimization": {
"difficulty": "medium",
"episode_hours": 14 * 24,
"description": (
"Optimize fish growth over 2 weeks. Fish start at 80g, target 120g+. "
"Balance aggressive feeding (faster growth) against water quality "
"degradation (ammonia, DO). Achieve the best FCR possible while "
"maximizing weight gain. Minimize mortality."
),
"initial_conditions": {
"weight_g": 80.0, "population": 6000, "temp": 30.0,
"DO": 7.0, "TAN": 0.1, "pH": 7.5, "day_of_year": 90,
},
"events": [],
"reward_weights": {"growth": 0.4, "fcr": 0.3, "survival": 0.2, "water_quality": 0.1},
"grader": "growth_optimization_grader",
"target_weight": 120.0,
},
# =====================================================================
# HARD TASKS — Full lifecycle, compound events, multi-objective
# =====================================================================
"full_growout": {
"difficulty": "hard",
"episode_hours": 60 * 24,
"description": (
"Complete grow-out cycle: take fish from 20g fingerlings to market "
"weight (400g+). Manage all systems over 60 days. Random weather, "
"possible disease, possible equipment issues. Score on: final weight, "
"survival rate, FCR, and profit. Decide when to harvest for max value."
),
"initial_conditions": {
"weight_g": 20.0, "population": 7000, "temp": 28.0,
"DO": 7.5, "TAN": 0.05, "pH": 7.5, "day_of_year": 60,
},
"events": [],
"reward_weights": {"profit": 0.3, "growth": 0.25, "survival": 0.25, "fcr": 0.1, "water_quality": 0.1},
"grader": "full_growout_grader",
"target_weight": 400.0,
},
"storm_response": {
"difficulty": "hard",
"episode_hours": 5 * 24,
"description": (
"SEVERE STORM WARNING: A major storm hits at hour 24. Effects: "
"temperature drops 8C, power outage for 12 hours (aerators, heater, "
"biofilter ALL down), high winds. After power returns, biofilter "
"needs 24 hours to recover. Your job: maximize survival through the crisis. "
"Pre-position your systems before the storm hits."
),
"initial_conditions": {
"weight_g": 200.0, "population": 8000, "temp": 30.0,
"DO": 7.5, "TAN": 0.2, "pH": 7.5, "day_of_year": 180,
},
"events": [
Event(type="storm", trigger_hour=24, severity=0.9,
duration_hours=48, description="SEVERE STORM: Temp -8C, high winds"),
Event(type="power_outage", trigger_hour=24, severity=1.0,
duration_hours=12, description="POWER OUTAGE: All equipment offline"),
Event(type="equipment_failure", trigger_hour=36, severity=0.7,
duration_hours=24, description="BIOFILTER RECOVERY: Reduced capacity post-storm",
equipment="biofilter"),
],
"reward_weights": {"survival": 0.6, "water_quality": 0.3, "efficiency": 0.1},
"grader": "storm_grader",
},
"multi_objective": {
"difficulty": "hard",
"episode_hours": 30 * 24,
"description": (
"Multi-objective challenge: simultaneously maximize profit, maintain "
"fish welfare (stress < 0.3), and minimize environmental impact "
"(water discharge quality). Score is the product of all three objectives — "
"neglecting any one dimension tanks your score. "
"Fish start at 100g in a moderately stocked tank."
),
"initial_conditions": {
"weight_g": 100.0, "population": 8000, "temp": 29.0,
"DO": 7.0, "TAN": 0.2, "pH": 7.5, "day_of_year": 100,
},
"events": [],
"reward_weights": {"profit": 0.33, "welfare": 0.34, "environment": 0.33},
"grader": "multi_objective_grader",
},
# =====================================================================
# EXTREME TASKS — Everything at once, frontier-model difficulty
# =====================================================================
"catastrophe_prevention": {
"difficulty": "extreme",
"episode_hours": 14 * 24,
"description": (
"CRITICAL SITUATION: Multiple simultaneous challenges. "
"Day 1: Algae bloom developing (DO supersaturation then crash). "
"Day 3: Equipment degradation (aerator at 60% capacity). "
"Day 5: Disease outbreak detected. "
"Day 7: Market price drops 40%. "
"Day 10: Feed delivery delayed (inventory running low). "
"Prevent mass mortality, optimize harvest timing despite falling prices, "
"manage disease while resources are constrained. "
"This task separates frontier models from basic agents."
),
"initial_conditions": {
"weight_g": 250.0, "population": 7000, "temp": 31.0,
"DO": 8.0, "TAN": 0.4, "pH": 7.8, "day_of_year": 200,
},
"events": [
Event(type="algae_bloom", trigger_hour=12, severity=0.6,
duration_hours=48, description="ALGAE BLOOM: DO swinging wildly"),
Event(type="equipment_failure", trigger_hour=72, severity=0.4,
duration_hours=96, description="AERATOR DEGRADED: 60% capacity",
equipment="aerator"),
Event(type="disease", trigger_hour=120, severity=0.5,
duration_hours=0, description="DISEASE DETECTED: Mortality rising"),
Event(type="price_change", trigger_hour=168, severity=0.4,
duration_hours=168, description="MARKET CRASH: Fish price -40%",
price_multiplier=0.6),
Event(type="feed_shortage", trigger_hour=240, severity=0.7,
duration_hours=48, description="FEED DELAYED: Inventory critical"),
],
"reward_weights": {"survival": 0.3, "profit": 0.25, "water_quality": 0.2,
"disease_control": 0.15, "timing": 0.1},
"grader": "catastrophe_grader",
},
"season_management": {
"difficulty": "extreme",
"episode_hours": 90 * 24,
"description": (
"Full 90-day season. Fish from 10g to market weight. "
"Seasonal temperature changes (summer peak). Random storms, "
"random disease. Feed inventory must be managed (deliveries "
"every 14 days). Decide optimal harvest timing — market price "
"fluctuates weekly. Score = ROI (profit / total investment). "
"The best agents will achieve >50% ROI."
),
"initial_conditions": {
"weight_g": 10.0, "population": 10000, "temp": 27.0,
"DO": 7.5, "TAN": 0.05, "pH": 7.5, "day_of_year": 60,
},
"events": [],
"reward_weights": {"roi": 0.4, "growth": 0.2, "survival": 0.2, "fcr": 0.1, "welfare": 0.1},
"grader": "season_grader",
},
}
TASKS = _make_tasks()
def get_task(task_id: str) -> Dict[str, Any]:
if task_id not in TASKS:
raise ValueError(f"Unknown task_id: {task_id}. Available: {list(TASKS.keys())}")
return TASKS[task_id]
def list_all_tasks() -> List[Dict[str, str]]:
return [
{
"task_id": tid,
"difficulty": task["difficulty"],
"description": task["description"],
"episode_hours": task["episode_hours"],
}
for tid, task in TASKS.items()
]