synth-ai 0.1.9__py3-none-any.whl → 0.2.1.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- synth_ai/__init__.py +28 -2
- synth_ai/core/system.py +4 -0
- synth_ai/environments/__init__.py +35 -0
- synth_ai/environments/environment/__init__.py +1 -0
- synth_ai/environments/environment/artifacts/__init__.py +1 -0
- synth_ai/environments/environment/artifacts/base.py +50 -0
- synth_ai/environments/environment/core.py +22 -0
- synth_ai/environments/environment/db/__init__.py +1 -0
- synth_ai/environments/environment/db/sqlite.py +45 -0
- synth_ai/environments/environment/registry.py +24 -0
- synth_ai/environments/environment/resources/sqlite.py +46 -0
- synth_ai/environments/environment/results.py +1 -0
- synth_ai/environments/environment/rewards/__init__.py +1 -0
- synth_ai/environments/environment/rewards/core.py +28 -0
- synth_ai/environments/environment/shared_engine.py +26 -0
- synth_ai/environments/environment/tools/__init__.py +34 -0
- synth_ai/environments/examples/__init__.py +1 -0
- synth_ai/environments/examples/crafter_classic/__init__.py +8 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +58 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_browser.py +152 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +1194 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +51 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +872 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +1412 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/test_crafter_react_agent.py +1110 -0
- synth_ai/environments/examples/crafter_classic/config_logging.py +111 -0
- synth_ai/environments/examples/crafter_classic/engine.py +502 -0
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +63 -0
- synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +5 -0
- synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +74 -0
- synth_ai/environments/examples/crafter_classic/environment.py +255 -0
- synth_ai/environments/examples/crafter_classic/taskset.py +228 -0
- synth_ai/environments/examples/enron/agent_demos/test_synth_react.py +535 -0
- synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +156 -0
- synth_ai/environments/examples/enron/art_helpers/local_email_db.py +280 -0
- synth_ai/environments/examples/enron/art_helpers/types_enron.py +24 -0
- synth_ai/environments/examples/enron/engine.py +291 -0
- synth_ai/environments/examples/enron/environment.py +165 -0
- synth_ai/environments/examples/enron/taskset.py +112 -0
- synth_ai/environments/examples/enron/units/keyword_stats.py +111 -0
- synth_ai/environments/examples/enron/units/test_email_index.py +8 -0
- synth_ai/environments/examples/minigrid/__init__.py +48 -0
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_evaluation_framework.py +1188 -0
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_quick_evaluation.py +47 -0
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_react_agent.py +562 -0
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_trace_evaluation.py +220 -0
- synth_ai/environments/examples/minigrid/agent_demos/test_minigrid_react_agent.py +393 -0
- synth_ai/environments/examples/minigrid/engine.py +589 -0
- synth_ai/environments/examples/minigrid/environment.py +274 -0
- synth_ai/environments/examples/minigrid/environment_mapping.py +242 -0
- synth_ai/environments/examples/minigrid/puzzle_loader.py +416 -0
- synth_ai/environments/examples/minigrid/taskset.py +583 -0
- synth_ai/environments/examples/minigrid/units/test_action_behavior.py +226 -0
- synth_ai/environments/examples/minigrid/units/test_debug_messages.py +83 -0
- synth_ai/environments/examples/minigrid/units/test_exploration.py +120 -0
- synth_ai/environments/examples/minigrid/units/test_minigrid_engine.py +214 -0
- synth_ai/environments/examples/minigrid/units/test_minigrid_environment.py +238 -0
- synth_ai/environments/examples/minigrid/units/test_minigrid_environment_mapping.py +301 -0
- synth_ai/environments/examples/minigrid/units/test_minigrid_taskset.py +210 -0
- synth_ai/environments/examples/nethack/__init__.py +7 -0
- synth_ai/environments/examples/nethack/achievements.py +337 -0
- synth_ai/environments/examples/nethack/agent_demos/nethack_evaluation_framework.py +981 -0
- synth_ai/environments/examples/nethack/agent_demos/nethack_quick_evaluation.py +74 -0
- synth_ai/environments/examples/nethack/agent_demos/nethack_react_agent.py +832 -0
- synth_ai/environments/examples/nethack/agent_demos/test_nethack_react_agent.py +1112 -0
- synth_ai/environments/examples/nethack/engine.py +738 -0
- synth_ai/environments/examples/nethack/environment.py +255 -0
- synth_ai/environments/examples/nethack/helpers/__init__.py +42 -0
- synth_ai/environments/examples/nethack/helpers/action_mapping.py +301 -0
- synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +401 -0
- synth_ai/environments/examples/nethack/helpers/observation_utils.py +433 -0
- synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +201 -0
- synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +268 -0
- synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +308 -0
- synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +430 -0
- synth_ai/environments/examples/nethack/taskset.py +323 -0
- synth_ai/environments/examples/nethack/units/test_nethack_engine.py +277 -0
- synth_ai/environments/examples/nethack/units/test_nethack_environment.py +281 -0
- synth_ai/environments/examples/nethack/units/test_nethack_taskset.py +213 -0
- synth_ai/environments/examples/nethack/units/test_recording.py +307 -0
- synth_ai/environments/examples/red/__init__.py +7 -0
- synth_ai/environments/examples/red/agent_demos/__init__.py +1 -0
- synth_ai/environments/examples/red/agent_demos/test_synth_react.py +1471 -0
- synth_ai/environments/examples/red/config_logging.py +110 -0
- synth_ai/environments/examples/red/engine.py +693 -0
- synth_ai/environments/examples/red/engine_helpers/__init__.py +1 -0
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +28 -0
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +275 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +142 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +56 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +283 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +149 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +137 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +56 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +330 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +120 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +558 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +312 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +147 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +246 -0
- synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +367 -0
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +139 -0
- synth_ai/environments/examples/red/environment.py +235 -0
- synth_ai/environments/examples/red/taskset.py +77 -0
- synth_ai/environments/examples/red/test_fixes.py +125 -0
- synth_ai/environments/examples/red/test_fixes_mock.py +148 -0
- synth_ai/environments/examples/red/units/__init__.py +1 -0
- synth_ai/environments/examples/red/units/test_basic_functionality.py +97 -0
- synth_ai/environments/examples/red/units/test_button_press_requirements.py +217 -0
- synth_ai/environments/examples/red/units/test_engine.py +192 -0
- synth_ai/environments/examples/red/units/test_environment.py +455 -0
- synth_ai/environments/examples/red/units/test_exploration_strategy.py +227 -0
- synth_ai/environments/examples/red/units/test_integration.py +217 -0
- synth_ai/environments/examples/red/units/test_memory_extraction.py +111 -0
- synth_ai/environments/examples/red/units/test_menu_bug_reproduction.py +1100 -0
- synth_ai/environments/examples/red/units/test_movement_debug.py +255 -0
- synth_ai/environments/examples/red/units/test_pokemon_mcts_debug.py +163 -0
- synth_ai/environments/examples/red/units/test_pokemon_mcts_verbose.py +117 -0
- synth_ai/environments/examples/red/units/test_red_basic.py +145 -0
- synth_ai/environments/examples/red/units/test_red_comprehensive.py +323 -0
- synth_ai/environments/examples/red/units/test_retry_movement.py +195 -0
- synth_ai/environments/examples/red/units/test_reward_components.py +186 -0
- synth_ai/environments/examples/red/units/test_rom_integration.py +260 -0
- synth_ai/environments/examples/red/units/test_taskset.py +116 -0
- synth_ai/environments/examples/red/units/test_tree.py +448 -0
- synth_ai/environments/examples/sokoban/__init__.py +1 -0
- synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +900 -0
- synth_ai/environments/examples/sokoban/agent_demos/test_dspy_react.py +1 -0
- synth_ai/environments/examples/sokoban/agent_demos/test_sokoban_react_agent.py +498 -0
- synth_ai/environments/examples/sokoban/agent_demos/test_synth_lats.py +1 -0
- synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_locally.py +748 -0
- synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_service.py +296 -0
- synth_ai/environments/examples/sokoban/engine.py +675 -0
- synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +1 -0
- synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +656 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +17 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +3 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +129 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +370 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +331 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +305 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +66 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +114 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +122 -0
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +394 -0
- synth_ai/environments/examples/sokoban/environment.py +228 -0
- synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +438 -0
- synth_ai/environments/examples/sokoban/puzzle_loader.py +311 -0
- synth_ai/environments/examples/sokoban/taskset.py +425 -0
- synth_ai/environments/examples/sokoban/units/astar_common.py +94 -0
- synth_ai/environments/examples/sokoban/units/test_building_task_set.py +49 -0
- synth_ai/environments/examples/sokoban/units/test_false_positive.py +120 -0
- synth_ai/environments/examples/sokoban/units/test_simple_run_through_environment.py +119 -0
- synth_ai/environments/examples/sokoban/units/test_sokoban_environment.py +98 -0
- synth_ai/environments/examples/sokoban/units/test_tree.py +364 -0
- synth_ai/environments/examples/tictactoe/__init__.py +1 -0
- synth_ai/environments/examples/tictactoe/agent_demos/test_synth_react.py +266 -0
- synth_ai/environments/examples/tictactoe/agent_demos/test_tictactoe_react_agent.py +470 -0
- synth_ai/environments/examples/tictactoe/engine.py +368 -0
- synth_ai/environments/examples/tictactoe/environment.py +239 -0
- synth_ai/environments/examples/tictactoe/taskset.py +214 -0
- synth_ai/environments/examples/tictactoe/units/test_tictactoe_engine.py +393 -0
- synth_ai/environments/examples/tictactoe/units/test_tictactoe_environment.py +493 -0
- synth_ai/environments/examples/tictactoe/units/test_tictactoe_taskset.py +191 -0
- synth_ai/environments/examples/verilog/__init__.py +10 -0
- synth_ai/environments/examples/verilog/agent_demos/test_synth_react.py +520 -0
- synth_ai/environments/examples/verilog/engine.py +328 -0
- synth_ai/environments/examples/verilog/environment.py +349 -0
- synth_ai/environments/examples/verilog/taskset.py +418 -0
- synth_ai/environments/examples/verilog/units/test_verilog_engine.py +466 -0
- synth_ai/environments/examples/verilog/units/test_verilog_environment.py +585 -0
- synth_ai/environments/examples/verilog/units/test_verilog_integration.py +383 -0
- synth_ai/environments/examples/verilog/units/test_verilog_taskset.py +457 -0
- synth_ai/environments/reproducibility/core.py +42 -0
- synth_ai/environments/reproducibility/tree.py +364 -0
- synth_ai/environments/service/app.py +78 -0
- synth_ai/environments/service/core_routes.py +775 -0
- synth_ai/environments/service/external_registry.py +57 -0
- synth_ai/environments/service/registry.py +9 -0
- synth_ai/environments/stateful/__init__.py +1 -0
- synth_ai/environments/stateful/core.py +28 -0
- synth_ai/environments/stateful/engine.py +21 -0
- synth_ai/environments/stateful/state.py +7 -0
- synth_ai/environments/tasks/api.py +19 -0
- synth_ai/environments/tasks/core.py +78 -0
- synth_ai/environments/tasks/filters.py +39 -0
- synth_ai/environments/tasks/utils.py +89 -0
- synth_ai/environments/v0_observability/history.py +3 -0
- synth_ai/environments/v0_observability/log.py +2 -0
- synth_ai/lm/caching/constants.py +1 -0
- synth_ai/{zyk/lms → lm}/caching/ephemeral.py +4 -8
- synth_ai/{zyk/lms → lm}/caching/handler.py +15 -15
- synth_ai/{zyk/lms → lm}/caching/initialize.py +2 -4
- synth_ai/{zyk/lms → lm}/caching/persistent.py +4 -10
- synth_ai/{zyk/lms → lm}/config.py +2 -1
- synth_ai/{zyk/lms → lm}/constants.py +2 -2
- synth_ai/{zyk/lms → lm}/core/all.py +10 -10
- synth_ai/{zyk/lms → lm}/core/main.py +57 -33
- synth_ai/{zyk/lms → lm}/core/vendor_clients.py +12 -10
- synth_ai/lm/cost/monitor.py +1 -0
- synth_ai/lm/cost/statefulness.py +1 -0
- synth_ai/lm/provider_support/__init__.py +8 -0
- synth_ai/lm/provider_support/anthropic.py +945 -0
- synth_ai/lm/provider_support/openai.py +1115 -0
- synth_ai/lm/provider_support/suppress_logging.py +31 -0
- synth_ai/{zyk/lms → lm}/structured_outputs/handler.py +58 -80
- synth_ai/{zyk/lms → lm}/structured_outputs/inject.py +6 -20
- synth_ai/{zyk/lms → lm}/structured_outputs/rehabilitate.py +6 -12
- synth_ai/{zyk/lms → lm}/vendors/core/anthropic_api.py +21 -30
- synth_ai/{zyk/lms → lm}/vendors/core/gemini_api.py +37 -32
- synth_ai/{zyk/lms → lm}/vendors/core/mistral_api.py +19 -28
- synth_ai/{zyk/lms → lm}/vendors/core/openai_api.py +26 -36
- synth_ai/{zyk/lms → lm}/vendors/openai_standard.py +29 -33
- synth_ai/{zyk/lms → lm}/vendors/retries.py +1 -1
- synth_ai/lm/vendors/supported/__init__.py +0 -0
- synth_ai/{zyk/lms → lm}/vendors/supported/custom_endpoint.py +131 -118
- synth_ai/{zyk/lms → lm}/vendors/supported/deepseek.py +4 -8
- synth_ai/{zyk/lms → lm}/vendors/supported/grok.py +6 -8
- synth_ai/{zyk/lms → lm}/vendors/supported/groq.py +1 -1
- synth_ai/{zyk/lms → lm}/vendors/supported/ollama.py +2 -2
- synth_ai/{zyk/lms → lm}/vendors/supported/openrouter.py +18 -16
- synth_ai/{zyk/lms → lm}/vendors/supported/together.py +1 -1
- synth_ai/tracing/__init__.py +0 -0
- synth_ai/tracing/abstractions.py +224 -0
- synth_ai/tracing/base_client.py +91 -0
- synth_ai/tracing/client_manager.py +131 -0
- synth_ai/tracing/config.py +140 -0
- synth_ai/tracing/context.py +146 -0
- synth_ai/tracing/decorators.py +679 -0
- synth_ai/tracing/events/__init__.py +0 -0
- synth_ai/tracing/events/manage.py +147 -0
- synth_ai/tracing/events/scope.py +86 -0
- synth_ai/tracing/events/store.py +227 -0
- synth_ai/tracing/immediate_client.py +152 -0
- synth_ai/tracing/local.py +18 -0
- synth_ai/tracing/log_client_base.py +74 -0
- synth_ai/tracing/retry_queue.py +187 -0
- synth_ai/tracing/trackers.py +515 -0
- synth_ai/tracing/upload.py +504 -0
- synth_ai/tracing/utils.py +9 -0
- synth_ai/zyk/__init__.py +28 -2
- synth_ai-0.2.1.dev0.dist-info/METADATA +349 -0
- synth_ai-0.2.1.dev0.dist-info/RECORD +261 -0
- synth_ai/zyk/lms/caching/constants.py +0 -1
- synth_ai/zyk/lms/cost/monitor.py +0 -1
- synth_ai/zyk/lms/cost/statefulness.py +0 -1
- synth_ai-0.1.9.dist-info/METADATA +0 -37
- synth_ai-0.1.9.dist-info/RECORD +0 -50
- /synth_ai/{zyk/lms/__init__.py → environments/reproducibility/helpers.py} +0 -0
- /synth_ai/{zyk/lms/caching → lm}/__init__.py +0 -0
- /synth_ai/{zyk/lms/core → lm/caching}/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/caching/dbs.py +0 -0
- /synth_ai/{zyk/lms/cost → lm/core}/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/core/exceptions.py +0 -0
- /synth_ai/{zyk/lms/structured_outputs → lm/cost}/__init__.py +0 -0
- /synth_ai/{zyk/lms/vendors → lm/structured_outputs}/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/tools/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/tools/base.py +0 -0
- /synth_ai/{zyk/lms/vendors/core → lm/vendors}/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/vendors/base.py +0 -0
- /synth_ai/{zyk/lms/vendors/local → lm/vendors/core}/__init__.py +0 -0
- /synth_ai/{zyk/lms/vendors/supported → lm/vendors/local}/__init__.py +0 -0
- /synth_ai/{zyk/lms → lm}/vendors/local/ollama.py +0 -0
- {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/WHEEL +0 -0
- {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,416 @@
|
|
1
|
+
"""
|
2
|
+
MiniGrid Puzzle Loader
|
3
|
+
|
4
|
+
This module provides a comprehensive puzzle loading system for MiniGrid environments
|
5
|
+
with deterministic seed-based selection and difficulty filtering.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import logging
|
9
|
+
from dataclasses import dataclass, asdict
|
10
|
+
from typing import Dict, List, Optional, Tuple, Any
|
11
|
+
from synth_ai.environments.examples.minigrid.environment_mapping import ENVIRONMENT_MAPPING
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass
|
17
|
+
class MiniGridPuzzle:
|
18
|
+
"""Represents a single MiniGrid puzzle configuration."""
|
19
|
+
|
20
|
+
id: str
|
21
|
+
environment_name: str
|
22
|
+
difficulty: str
|
23
|
+
seed: int
|
24
|
+
grid_size: Tuple[int, int]
|
25
|
+
mission_description: str
|
26
|
+
|
27
|
+
# Environment features
|
28
|
+
has_key: bool = False
|
29
|
+
has_door: bool = False
|
30
|
+
has_lava: bool = False
|
31
|
+
has_multi_room: bool = False
|
32
|
+
num_objects: int = 0
|
33
|
+
|
34
|
+
# Difficulty metrics
|
35
|
+
complexity_score: float = 0.0
|
36
|
+
estimated_steps: int = 0
|
37
|
+
|
38
|
+
def to_dict(self) -> Dict[str, Any]:
|
39
|
+
"""Convert puzzle to dictionary."""
|
40
|
+
return asdict(self)
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
def from_dict(cls, data: Dict[str, Any]) -> "MiniGridPuzzle":
|
44
|
+
"""Create puzzle from dictionary."""
|
45
|
+
return cls(**data)
|
46
|
+
|
47
|
+
|
48
|
+
class MiniGridPuzzleLoader:
|
49
|
+
"""Manages loading and accessing MiniGrid puzzles with difficulty filtering."""
|
50
|
+
|
51
|
+
def __init__(self):
|
52
|
+
self.puzzles: Dict[str, List[MiniGridPuzzle]] = {}
|
53
|
+
self.all_puzzles: List[MiniGridPuzzle] = []
|
54
|
+
self._loaded = False
|
55
|
+
|
56
|
+
# Difficulty seed mappings based on user's detailed analysis
|
57
|
+
self.difficulty_seeds = {
|
58
|
+
"ultra_easy": [
|
59
|
+
0,
|
60
|
+
1,
|
61
|
+
2,
|
62
|
+
3,
|
63
|
+
4,
|
64
|
+
5,
|
65
|
+
7,
|
66
|
+
8,
|
67
|
+
9,
|
68
|
+
10,
|
69
|
+
12,
|
70
|
+
13,
|
71
|
+
14,
|
72
|
+
15,
|
73
|
+
16,
|
74
|
+
17,
|
75
|
+
18,
|
76
|
+
19,
|
77
|
+
20,
|
78
|
+
21,
|
79
|
+
22,
|
80
|
+
23,
|
81
|
+
],
|
82
|
+
"easy": [11, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34],
|
83
|
+
"medium": [35, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48, 49],
|
84
|
+
"hard": [6, 42, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
|
85
|
+
}
|
86
|
+
|
87
|
+
def load_puzzles(self) -> None:
|
88
|
+
"""Load all MiniGrid puzzles from the environment mapping."""
|
89
|
+
if self._loaded:
|
90
|
+
return
|
91
|
+
|
92
|
+
logger.info("Loading MiniGrid puzzles from environment mapping...")
|
93
|
+
|
94
|
+
# Clear existing data
|
95
|
+
self.puzzles.clear()
|
96
|
+
self.all_puzzles.clear()
|
97
|
+
|
98
|
+
# Initialize difficulty categories
|
99
|
+
for difficulty in self.difficulty_seeds.keys():
|
100
|
+
self.puzzles[difficulty] = []
|
101
|
+
|
102
|
+
# Load puzzles for each difficulty
|
103
|
+
for difficulty, seeds in self.difficulty_seeds.items():
|
104
|
+
for seed in seeds:
|
105
|
+
puzzle = self._create_puzzle_from_seed(seed, difficulty)
|
106
|
+
if puzzle:
|
107
|
+
self.puzzles[difficulty].append(puzzle)
|
108
|
+
self.all_puzzles.append(puzzle)
|
109
|
+
|
110
|
+
self._loaded = True
|
111
|
+
logger.info(
|
112
|
+
f"Loaded {len(self.all_puzzles)} MiniGrid puzzles across {len(self.puzzles)} difficulties"
|
113
|
+
)
|
114
|
+
|
115
|
+
def _create_puzzle_from_seed(self, seed: int, difficulty: str) -> Optional[MiniGridPuzzle]:
|
116
|
+
"""Create a puzzle from a seed and difficulty."""
|
117
|
+
if seed not in ENVIRONMENT_MAPPING:
|
118
|
+
logger.warning(f"Seed {seed} not found in environment mapping")
|
119
|
+
return None
|
120
|
+
|
121
|
+
env_name = ENVIRONMENT_MAPPING[seed]
|
122
|
+
puzzle_id = f"{difficulty}_{seed:03d}"
|
123
|
+
|
124
|
+
# Extract environment features
|
125
|
+
has_key = "DoorKey" in env_name or "Unlock" in env_name or "KeyCorridor" in env_name
|
126
|
+
has_door = "Door" in env_name or "Room" in env_name or "Unlock" in env_name
|
127
|
+
has_lava = "Lava" in env_name
|
128
|
+
has_multi_room = "MultiRoom" in env_name or "FourRooms" in env_name
|
129
|
+
|
130
|
+
# Estimate grid size from environment name
|
131
|
+
grid_size = self._estimate_grid_size(env_name)
|
132
|
+
|
133
|
+
# Count objects
|
134
|
+
num_objects = 0
|
135
|
+
if has_key:
|
136
|
+
num_objects += 1
|
137
|
+
if has_door:
|
138
|
+
num_objects += 1
|
139
|
+
if "Pickup" in env_name:
|
140
|
+
num_objects += 1
|
141
|
+
if "Fetch" in env_name:
|
142
|
+
if "N2" in env_name:
|
143
|
+
num_objects += 2
|
144
|
+
elif "N3" in env_name:
|
145
|
+
num_objects += 3
|
146
|
+
|
147
|
+
# Generate mission description
|
148
|
+
mission_description = self._generate_mission_description(
|
149
|
+
env_name, has_key, has_door, has_lava, has_multi_room
|
150
|
+
)
|
151
|
+
|
152
|
+
# Calculate complexity score
|
153
|
+
complexity_score = self._calculate_complexity_score(
|
154
|
+
grid_size, num_objects, has_key, has_door, has_lava, has_multi_room
|
155
|
+
)
|
156
|
+
|
157
|
+
# Estimate steps
|
158
|
+
estimated_steps = self._estimate_steps(grid_size, complexity_score)
|
159
|
+
|
160
|
+
return MiniGridPuzzle(
|
161
|
+
id=puzzle_id,
|
162
|
+
environment_name=env_name,
|
163
|
+
difficulty=difficulty,
|
164
|
+
seed=seed,
|
165
|
+
grid_size=grid_size,
|
166
|
+
mission_description=mission_description,
|
167
|
+
has_key=has_key,
|
168
|
+
has_door=has_door,
|
169
|
+
has_lava=has_lava,
|
170
|
+
has_multi_room=has_multi_room,
|
171
|
+
num_objects=num_objects,
|
172
|
+
complexity_score=complexity_score,
|
173
|
+
estimated_steps=estimated_steps,
|
174
|
+
)
|
175
|
+
|
176
|
+
def _estimate_grid_size(self, env_name: str) -> Tuple[int, int]:
|
177
|
+
"""Estimate grid size from environment name."""
|
178
|
+
if "5x5" in env_name:
|
179
|
+
return (5, 5)
|
180
|
+
elif "6x6" in env_name:
|
181
|
+
return (6, 6)
|
182
|
+
elif "8x8" in env_name:
|
183
|
+
return (8, 8)
|
184
|
+
elif "16x16" in env_name:
|
185
|
+
return (16, 16)
|
186
|
+
elif "FourRooms" in env_name:
|
187
|
+
return (19, 19)
|
188
|
+
elif "MultiRoom-N2" in env_name:
|
189
|
+
return (15, 15)
|
190
|
+
elif "MultiRoom-N4" in env_name:
|
191
|
+
return (19, 19)
|
192
|
+
elif "MultiRoom-N6" in env_name:
|
193
|
+
return (25, 25)
|
194
|
+
elif "LavaGapS5" in env_name:
|
195
|
+
return (5, 7)
|
196
|
+
elif "LavaGapS6" in env_name:
|
197
|
+
return (6, 8)
|
198
|
+
elif "LavaGapS7" in env_name:
|
199
|
+
return (7, 9)
|
200
|
+
elif "CrossingS9" in env_name:
|
201
|
+
return (9, 9)
|
202
|
+
elif "CrossingS11" in env_name:
|
203
|
+
return (11, 11)
|
204
|
+
else:
|
205
|
+
return (7, 7) # Default
|
206
|
+
|
207
|
+
def _generate_mission_description(
|
208
|
+
self, env_name: str, has_key: bool, has_door: bool, has_lava: bool, has_multi_room: bool
|
209
|
+
) -> str:
|
210
|
+
"""Generate mission description based on environment features."""
|
211
|
+
if "Empty" in env_name:
|
212
|
+
return "Navigate the grid to reach the goal"
|
213
|
+
elif "DoorKey" in env_name:
|
214
|
+
return "Find the key, unlock the door, and reach the goal"
|
215
|
+
elif "Unlock" in env_name:
|
216
|
+
return "Use keys to unlock doors and reach the goal"
|
217
|
+
elif "MultiRoom" in env_name:
|
218
|
+
return "Navigate through multiple rooms to reach the goal"
|
219
|
+
elif "LavaGap" in env_name:
|
220
|
+
return "Jump over lava gaps to reach the goal"
|
221
|
+
elif "LavaCrossing" in env_name:
|
222
|
+
return "Navigate through lava fields to reach the goal"
|
223
|
+
elif "Fetch" in env_name:
|
224
|
+
return "Pick up the required objects"
|
225
|
+
elif "PutNear" in env_name:
|
226
|
+
return "Pick up objects and place them near other objects"
|
227
|
+
elif "KeyCorridor" in env_name:
|
228
|
+
return "Navigate corridors with keys and doors"
|
229
|
+
elif "FourRooms" in env_name:
|
230
|
+
return "Navigate through four connected rooms to reach the goal"
|
231
|
+
else:
|
232
|
+
return "Complete the mission to reach the goal"
|
233
|
+
|
234
|
+
def _calculate_complexity_score(
|
235
|
+
self,
|
236
|
+
grid_size: Tuple[int, int],
|
237
|
+
num_objects: int,
|
238
|
+
has_key: bool,
|
239
|
+
has_door: bool,
|
240
|
+
has_lava: bool,
|
241
|
+
has_multi_room: bool,
|
242
|
+
) -> float:
|
243
|
+
"""Calculate complexity score based on environment features."""
|
244
|
+
width, height = grid_size
|
245
|
+
base_score = (width * height) / 100.0 # Normalized by grid size
|
246
|
+
|
247
|
+
# Add complexity for features
|
248
|
+
if has_key:
|
249
|
+
base_score += 0.5
|
250
|
+
if has_door:
|
251
|
+
base_score += 0.3
|
252
|
+
if has_lava:
|
253
|
+
base_score += 0.7
|
254
|
+
if has_multi_room:
|
255
|
+
base_score += 1.0
|
256
|
+
|
257
|
+
# Add complexity for objects
|
258
|
+
base_score += num_objects * 0.2
|
259
|
+
|
260
|
+
return base_score
|
261
|
+
|
262
|
+
def _estimate_steps(self, grid_size: Tuple[int, int], complexity_score: float) -> int:
|
263
|
+
"""Estimate number of steps required."""
|
264
|
+
width, height = grid_size
|
265
|
+
base_steps = width + height # Manhattan distance estimate
|
266
|
+
|
267
|
+
# Scale by complexity
|
268
|
+
estimated = int(base_steps * (1.0 + complexity_score))
|
269
|
+
|
270
|
+
return max(10, estimated) # Minimum 10 steps
|
271
|
+
|
272
|
+
def get_puzzles_by_difficulty(self, difficulty: str) -> List[MiniGridPuzzle]:
|
273
|
+
"""Get all puzzles for a specific difficulty level."""
|
274
|
+
if not self._loaded:
|
275
|
+
self.load_puzzles()
|
276
|
+
return self.puzzles.get(difficulty, [])
|
277
|
+
|
278
|
+
def get_puzzle_by_seed(self, difficulty: str, seed: int) -> Optional[MiniGridPuzzle]:
|
279
|
+
"""
|
280
|
+
Get a puzzle deterministically using a seed via modular arithmetic.
|
281
|
+
Same seed will always return the same puzzle for a given difficulty.
|
282
|
+
"""
|
283
|
+
puzzles = self.get_puzzles_by_difficulty(difficulty)
|
284
|
+
if not puzzles:
|
285
|
+
return None
|
286
|
+
|
287
|
+
# Use modular arithmetic to map seed to puzzle index
|
288
|
+
index = seed % len(puzzles)
|
289
|
+
return puzzles[index]
|
290
|
+
|
291
|
+
def get_puzzle_by_index(self, difficulty: str, index: int) -> Optional[MiniGridPuzzle]:
|
292
|
+
"""Get a puzzle by its index within a difficulty level."""
|
293
|
+
puzzles = self.get_puzzles_by_difficulty(difficulty)
|
294
|
+
if 0 <= index < len(puzzles):
|
295
|
+
return puzzles[index]
|
296
|
+
return None
|
297
|
+
|
298
|
+
def get_random_puzzle(self, difficulty: str) -> Optional[MiniGridPuzzle]:
|
299
|
+
"""Get a random puzzle from the specified difficulty."""
|
300
|
+
import random
|
301
|
+
|
302
|
+
puzzles = self.get_puzzles_by_difficulty(difficulty)
|
303
|
+
if not puzzles:
|
304
|
+
return None
|
305
|
+
return random.choice(puzzles)
|
306
|
+
|
307
|
+
def get_available_difficulties(self) -> List[str]:
|
308
|
+
"""Get list of available difficulty levels."""
|
309
|
+
return list(self.difficulty_seeds.keys())
|
310
|
+
|
311
|
+
def get_metadata_for_filtering(self) -> Dict[str, Any]:
|
312
|
+
"""Get metadata to help with filtering across environments."""
|
313
|
+
if not self._loaded:
|
314
|
+
self.load_puzzles()
|
315
|
+
|
316
|
+
return {
|
317
|
+
"environment_type": "minigrid",
|
318
|
+
"total_puzzles": len(self.all_puzzles),
|
319
|
+
"difficulties": self.get_available_difficulties(),
|
320
|
+
"difficulty_counts": {
|
321
|
+
difficulty: len(puzzles) for difficulty, puzzles in self.puzzles.items()
|
322
|
+
},
|
323
|
+
"features": {
|
324
|
+
"has_navigation": True,
|
325
|
+
"has_keys": True,
|
326
|
+
"has_doors": True,
|
327
|
+
"has_lava": True,
|
328
|
+
"has_multi_room": True,
|
329
|
+
"grid_based": True,
|
330
|
+
"puzzle_type": "navigation",
|
331
|
+
},
|
332
|
+
"difficulty_ranges": {
|
333
|
+
"ultra_easy": {"grid_size": (5, 7), "complexity": (0.0, 1.0), "environments": 22},
|
334
|
+
"easy": {"grid_size": (6, 15), "complexity": (1.0, 2.0), "environments": 12},
|
335
|
+
"medium": {"grid_size": (7, 21), "complexity": (2.0, 4.0), "environments": 14},
|
336
|
+
"hard": {"grid_size": (8, 37), "complexity": (4.0, 8.0), "environments": 12},
|
337
|
+
},
|
338
|
+
}
|
339
|
+
|
340
|
+
def get_total_puzzle_count(self) -> int:
|
341
|
+
"""Get total number of puzzles across all difficulties."""
|
342
|
+
if not self._loaded:
|
343
|
+
self.load_puzzles()
|
344
|
+
return len(self.all_puzzles)
|
345
|
+
|
346
|
+
def get_difficulty_counts(self) -> Dict[str, int]:
|
347
|
+
"""Get count of puzzles per difficulty level."""
|
348
|
+
if not self._loaded:
|
349
|
+
self.load_puzzles()
|
350
|
+
return {difficulty: len(puzzles) for difficulty, puzzles in self.puzzles.items()}
|
351
|
+
|
352
|
+
def filter_puzzles(self, **kwargs) -> List[MiniGridPuzzle]:
|
353
|
+
"""Filter puzzles by various criteria."""
|
354
|
+
if not self._loaded:
|
355
|
+
self.load_puzzles()
|
356
|
+
|
357
|
+
filtered = self.all_puzzles
|
358
|
+
|
359
|
+
# Filter by difficulty
|
360
|
+
if "difficulty" in kwargs:
|
361
|
+
filtered = [p for p in filtered if p.difficulty == kwargs["difficulty"]]
|
362
|
+
|
363
|
+
# Filter by features
|
364
|
+
if "has_key" in kwargs:
|
365
|
+
filtered = [p for p in filtered if p.has_key == kwargs["has_key"]]
|
366
|
+
if "has_door" in kwargs:
|
367
|
+
filtered = [p for p in filtered if p.has_door == kwargs["has_door"]]
|
368
|
+
if "has_lava" in kwargs:
|
369
|
+
filtered = [p for p in filtered if p.has_lava == kwargs["has_lava"]]
|
370
|
+
if "has_multi_room" in kwargs:
|
371
|
+
filtered = [p for p in filtered if p.has_multi_room == kwargs["has_multi_room"]]
|
372
|
+
|
373
|
+
# Filter by grid size
|
374
|
+
if "max_width" in kwargs:
|
375
|
+
filtered = [p for p in filtered if p.grid_size[0] <= kwargs["max_width"]]
|
376
|
+
if "max_height" in kwargs:
|
377
|
+
filtered = [p for p in filtered if p.grid_size[1] <= kwargs["max_height"]]
|
378
|
+
|
379
|
+
# Filter by complexity
|
380
|
+
if "max_complexity" in kwargs:
|
381
|
+
filtered = [p for p in filtered if p.complexity_score <= kwargs["max_complexity"]]
|
382
|
+
|
383
|
+
return filtered
|
384
|
+
|
385
|
+
|
386
|
+
# Global puzzle loader instance
|
387
|
+
_puzzle_loader: Optional[MiniGridPuzzleLoader] = None
|
388
|
+
|
389
|
+
|
390
|
+
def get_puzzle_loader() -> MiniGridPuzzleLoader:
|
391
|
+
"""Get the global puzzle loader instance."""
|
392
|
+
global _puzzle_loader
|
393
|
+
if _puzzle_loader is None:
|
394
|
+
_puzzle_loader = MiniGridPuzzleLoader()
|
395
|
+
return _puzzle_loader
|
396
|
+
|
397
|
+
|
398
|
+
# Convenience functions
|
399
|
+
def get_puzzles_by_difficulty(difficulty: str) -> List[MiniGridPuzzle]:
|
400
|
+
"""Convenience function to get puzzles by difficulty."""
|
401
|
+
return get_puzzle_loader().get_puzzles_by_difficulty(difficulty)
|
402
|
+
|
403
|
+
|
404
|
+
def get_puzzle_by_seed(difficulty: str, seed: int) -> Optional[MiniGridPuzzle]:
|
405
|
+
"""Convenience function to get a puzzle by seed."""
|
406
|
+
return get_puzzle_loader().get_puzzle_by_seed(difficulty, seed)
|
407
|
+
|
408
|
+
|
409
|
+
def get_puzzle_by_index(difficulty: str, index: int) -> Optional[MiniGridPuzzle]:
|
410
|
+
"""Convenience function to get a puzzle by index."""
|
411
|
+
return get_puzzle_loader().get_puzzle_by_index(difficulty, index)
|
412
|
+
|
413
|
+
|
414
|
+
def get_available_difficulties() -> List[str]:
|
415
|
+
"""Convenience function to get available difficulties."""
|
416
|
+
return get_puzzle_loader().get_available_difficulties()
|