synth-ai 0.2.4.dev4__py3-none-any.whl → 0.2.4.dev6__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.
Files changed (123) hide show
  1. synth_ai/environments/examples/__init__.py +1 -0
  2. synth_ai/environments/examples/crafter_classic/__init__.py +8 -0
  3. synth_ai/environments/examples/crafter_classic/config_logging.py +111 -0
  4. synth_ai/environments/examples/crafter_classic/debug_translation.py +0 -0
  5. synth_ai/environments/examples/crafter_classic/engine.py +579 -0
  6. synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +63 -0
  7. synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +5 -0
  8. synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +74 -0
  9. synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +266 -0
  10. synth_ai/environments/examples/crafter_classic/environment.py +364 -0
  11. synth_ai/environments/examples/crafter_classic/taskset.py +233 -0
  12. synth_ai/environments/examples/crafter_classic/trace_hooks_v3.py +229 -0
  13. synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +298 -0
  14. synth_ai/environments/examples/crafter_custom/__init__.py +4 -0
  15. synth_ai/environments/examples/crafter_custom/crafter/__init__.py +7 -0
  16. synth_ai/environments/examples/crafter_custom/crafter/config.py +182 -0
  17. synth_ai/environments/examples/crafter_custom/crafter/constants.py +8 -0
  18. synth_ai/environments/examples/crafter_custom/crafter/engine.py +269 -0
  19. synth_ai/environments/examples/crafter_custom/crafter/env.py +266 -0
  20. synth_ai/environments/examples/crafter_custom/crafter/objects.py +418 -0
  21. synth_ai/environments/examples/crafter_custom/crafter/recorder.py +187 -0
  22. synth_ai/environments/examples/crafter_custom/crafter/worldgen.py +119 -0
  23. synth_ai/environments/examples/crafter_custom/dataset_builder.py +373 -0
  24. synth_ai/environments/examples/crafter_custom/environment.py +312 -0
  25. synth_ai/environments/examples/crafter_custom/run_dataset.py +305 -0
  26. synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +156 -0
  27. synth_ai/environments/examples/enron/art_helpers/local_email_db.py +280 -0
  28. synth_ai/environments/examples/enron/art_helpers/types_enron.py +24 -0
  29. synth_ai/environments/examples/enron/engine.py +291 -0
  30. synth_ai/environments/examples/enron/environment.py +165 -0
  31. synth_ai/environments/examples/enron/taskset.py +112 -0
  32. synth_ai/environments/examples/minigrid/__init__.py +48 -0
  33. synth_ai/environments/examples/minigrid/engine.py +589 -0
  34. synth_ai/environments/examples/minigrid/environment.py +274 -0
  35. synth_ai/environments/examples/minigrid/environment_mapping.py +242 -0
  36. synth_ai/environments/examples/minigrid/puzzle_loader.py +416 -0
  37. synth_ai/environments/examples/minigrid/taskset.py +583 -0
  38. synth_ai/environments/examples/nethack/__init__.py +7 -0
  39. synth_ai/environments/examples/nethack/achievements.py +337 -0
  40. synth_ai/environments/examples/nethack/engine.py +738 -0
  41. synth_ai/environments/examples/nethack/environment.py +255 -0
  42. synth_ai/environments/examples/nethack/helpers/__init__.py +42 -0
  43. synth_ai/environments/examples/nethack/helpers/action_mapping.py +301 -0
  44. synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +401 -0
  45. synth_ai/environments/examples/nethack/helpers/observation_utils.py +433 -0
  46. synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +201 -0
  47. synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +268 -0
  48. synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +308 -0
  49. synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +430 -0
  50. synth_ai/environments/examples/nethack/taskset.py +323 -0
  51. synth_ai/environments/examples/red/__init__.py +7 -0
  52. synth_ai/environments/examples/red/config_logging.py +110 -0
  53. synth_ai/environments/examples/red/engine.py +693 -0
  54. synth_ai/environments/examples/red/engine_helpers/__init__.py +1 -0
  55. synth_ai/environments/examples/red/engine_helpers/memory_map.py +28 -0
  56. synth_ai/environments/examples/red/engine_helpers/reward_components.py +275 -0
  57. synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +142 -0
  58. synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +56 -0
  59. synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +283 -0
  60. synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +149 -0
  61. synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +137 -0
  62. synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +56 -0
  63. synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +330 -0
  64. synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +120 -0
  65. synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +558 -0
  66. synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +312 -0
  67. synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +147 -0
  68. synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +246 -0
  69. synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +367 -0
  70. synth_ai/environments/examples/red/engine_helpers/state_extraction.py +139 -0
  71. synth_ai/environments/examples/red/environment.py +235 -0
  72. synth_ai/environments/examples/red/taskset.py +77 -0
  73. synth_ai/environments/examples/sokoban/__init__.py +1 -0
  74. synth_ai/environments/examples/sokoban/engine.py +675 -0
  75. synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +1 -0
  76. synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +656 -0
  77. synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +17 -0
  78. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +3 -0
  79. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +129 -0
  80. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +370 -0
  81. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +331 -0
  82. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +305 -0
  83. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +66 -0
  84. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +114 -0
  85. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +122 -0
  86. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +394 -0
  87. synth_ai/environments/examples/sokoban/environment.py +228 -0
  88. synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +438 -0
  89. synth_ai/environments/examples/sokoban/puzzle_loader.py +311 -0
  90. synth_ai/environments/examples/sokoban/taskset.py +425 -0
  91. synth_ai/environments/examples/tictactoe/__init__.py +1 -0
  92. synth_ai/environments/examples/tictactoe/engine.py +368 -0
  93. synth_ai/environments/examples/tictactoe/environment.py +239 -0
  94. synth_ai/environments/examples/tictactoe/taskset.py +214 -0
  95. synth_ai/environments/examples/verilog/__init__.py +10 -0
  96. synth_ai/environments/examples/verilog/engine.py +328 -0
  97. synth_ai/environments/examples/verilog/environment.py +349 -0
  98. synth_ai/environments/examples/verilog/taskset.py +418 -0
  99. synth_ai/environments/examples/wordle/__init__.py +29 -0
  100. synth_ai/environments/examples/wordle/engine.py +391 -0
  101. synth_ai/environments/examples/wordle/environment.py +154 -0
  102. synth_ai/environments/examples/wordle/helpers/generate_instances_wordfreq.py +75 -0
  103. synth_ai/environments/examples/wordle/taskset.py +222 -0
  104. synth_ai/environments/service/app.py +8 -0
  105. synth_ai/environments/service/core_routes.py +38 -0
  106. synth_ai/learning/prompts/banking77_injection_eval.py +163 -0
  107. synth_ai/learning/prompts/hello_world_in_context_injection_ex.py +201 -0
  108. synth_ai/learning/prompts/mipro.py +273 -1
  109. synth_ai/learning/prompts/random_search.py +247 -0
  110. synth_ai/learning/prompts/run_mipro_banking77.py +160 -0
  111. synth_ai/learning/prompts/run_random_search_banking77.py +305 -0
  112. synth_ai/lm/injection.py +81 -0
  113. synth_ai/lm/overrides.py +204 -0
  114. synth_ai/lm/provider_support/anthropic.py +39 -12
  115. synth_ai/lm/provider_support/openai.py +31 -4
  116. synth_ai/lm/vendors/core/anthropic_api.py +16 -0
  117. synth_ai/lm/vendors/openai_standard.py +35 -5
  118. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/METADATA +2 -1
  119. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/RECORD +123 -13
  120. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/WHEEL +0 -0
  121. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/entry_points.txt +0 -0
  122. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/licenses/LICENSE +0 -0
  123. {synth_ai-0.2.4.dev4.dist-info → synth_ai-0.2.4.dev6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,74 @@
1
+ import importlib
2
+ import numpy as np
3
+ from typing import Any, Dict
4
+
5
+ # Minimal attributes to serialize per object type
6
+ BASIC_ATTRS: Dict[str, list] = {
7
+ "Player": [
8
+ "pos",
9
+ "facing",
10
+ "health",
11
+ "inventory",
12
+ "achievements",
13
+ "action",
14
+ "sleeping",
15
+ "_last_health",
16
+ "_hunger",
17
+ "_thirst",
18
+ "_fatigue",
19
+ "_recover",
20
+ ],
21
+ "Cow": ["pos", "health"],
22
+ "Zombie": ["pos", "health", "cooldown"],
23
+ "Skeleton": ["pos", "health", "reload"],
24
+ "Arrow": ["pos", "facing"],
25
+ "Plant": ["pos", "health", "grown"],
26
+ "Stone": ["pos"],
27
+ "Table": ["pos"],
28
+ "Furnace": ["pos"],
29
+ # Add other types as needed
30
+ }
31
+
32
+
33
+ def serialize_world_object(obj: Any) -> Dict[str, Any]:
34
+ """Convert a crafter object into a JSON-friendly dict."""
35
+ cls_name = obj.__class__.__name__
36
+ fields = BASIC_ATTRS.get(cls_name, ["pos"])
37
+ payload: Dict[str, Any] = {}
38
+ for field in fields:
39
+ val = getattr(obj, field)
40
+ if isinstance(val, np.ndarray):
41
+ payload[field] = val.tolist()
42
+ else:
43
+ payload[field] = val
44
+ return {
45
+ "type": f"{obj.__class__.__module__}.{cls_name}",
46
+ "state": payload,
47
+ }
48
+
49
+
50
+ def deserialize_world_object(blob: Dict[str, Any], world: Any) -> Any:
51
+ """Reconstruct a crafter object from its serialized dict."""
52
+ type_str = blob.get("type", "")
53
+ module_name, cls_name = type_str.rsplit(".", 1)
54
+ module = importlib.import_module(module_name)
55
+ cls = getattr(module, cls_name)
56
+ # Bypass __init__; create empty instance
57
+ state = blob.get("state", {})
58
+ obj = cls.__new__(cls)
59
+ # Initialize required base attributes
60
+ obj.world = world
61
+ obj.random = world.random
62
+ obj.removed = False
63
+ # Ensure inventory exists for health setter
64
+ obj.inventory = {"health": 0}
65
+ # Set attributes from state
66
+ for field, value in state.items():
67
+ if field == "pos":
68
+ # restore position as numpy array
69
+ obj.pos = np.array(value)
70
+ else:
71
+ # restore other attributes (including property setters)
72
+ # convert lists back to arrays only for known ndarray fields
73
+ setattr(obj, field, value)
74
+ return obj
@@ -0,0 +1,266 @@
1
+ """
2
+ Enhanced monkey patch to add save/load functionality to crafter.Env
3
+ This version handles player references for Zombie and Skeleton objects.
4
+ """
5
+
6
+ import collections
7
+ import pickle
8
+ import numpy as np
9
+ import crafter
10
+ from crafter import objects
11
+ from typing import Dict, Any, Optional, Set
12
+
13
+ print("[PATCH] Attempting to apply Crafter serialization patch v3...")
14
+
15
+ # Check if already patched
16
+ if not hasattr(crafter.Env, "save"):
17
+ print("[PATCH] Adding enhanced save/load methods to crafter.Env...")
18
+
19
+ def _save(self) -> Dict[str, Any]:
20
+ """Save complete environment state including all details."""
21
+ # Save complete world state
22
+ world_state = {
23
+ "area": self._world.area,
24
+ "daylight": self._world.daylight,
25
+ "_mat_map": self._world._mat_map.tolist(),
26
+ "_obj_map": self._world._obj_map.tolist(),
27
+ "_mat_names": dict(self._world._mat_names),
28
+ "_mat_ids": dict(self._world._mat_ids),
29
+ "_chunk_size": self._world._chunk_size,
30
+ "random_state": pickle.dumps(self._world.random.get_state()),
31
+ }
32
+
33
+ # Save all objects with complete state
34
+ objects_data = []
35
+ player_idx = None
36
+
37
+ for i, obj in enumerate(self._world._objects):
38
+ if obj is None:
39
+ objects_data.append(None)
40
+ else:
41
+ # Get all object attributes
42
+ obj_data = {
43
+ "type": f"{obj.__class__.__module__}.{obj.__class__.__name__}",
44
+ "_index": i,
45
+ "pos": obj.pos.tolist() if hasattr(obj, "pos") else None,
46
+ "removed": getattr(obj, "removed", False),
47
+ }
48
+
49
+ # Save ALL attributes based on object type
50
+ if isinstance(obj, objects.Player):
51
+ player_idx = i
52
+ obj_data.update(
53
+ {
54
+ "facing": list(obj.facing) if hasattr(obj, "facing") else None,
55
+ "health": obj.health,
56
+ "inventory": dict(obj.inventory),
57
+ "achievements": dict(obj.achievements),
58
+ "_hunger": obj._hunger,
59
+ "_thirst": obj._thirst,
60
+ "_fatigue": obj._fatigue,
61
+ "_recover": obj._recover,
62
+ "action": obj.action,
63
+ "sleeping": obj.sleeping,
64
+ "_last_health": obj._last_health,
65
+ }
66
+ )
67
+ elif isinstance(obj, objects.Zombie):
68
+ obj_data.update(
69
+ {
70
+ "health": obj.health,
71
+ "cooldown": getattr(obj, "cooldown", 0),
72
+ }
73
+ )
74
+ elif isinstance(obj, objects.Skeleton):
75
+ obj_data.update(
76
+ {
77
+ "health": obj.health,
78
+ "reload": getattr(obj, "reload", 0),
79
+ }
80
+ )
81
+ elif isinstance(obj, objects.Arrow):
82
+ obj_data.update(
83
+ {
84
+ "facing": list(obj.facing) if hasattr(obj, "facing") else None,
85
+ }
86
+ )
87
+ elif isinstance(obj, objects.Plant):
88
+ obj_data.update(
89
+ {
90
+ "health": getattr(obj, "health", 1),
91
+ "grown": getattr(obj, "grown", 0),
92
+ "kind": getattr(obj, "kind", "unknown"),
93
+ }
94
+ )
95
+ elif hasattr(obj, "health"):
96
+ obj_data["health"] = obj.health
97
+
98
+ objects_data.append(obj_data)
99
+
100
+ # Save chunks with proper references
101
+ chunks_data = {}
102
+ for key, chunk_objs in self._world._chunks.items():
103
+ chunk_indices = []
104
+ for obj in chunk_objs:
105
+ if obj is not None:
106
+ try:
107
+ idx = self._world._objects.index(obj)
108
+ chunk_indices.append(idx)
109
+ except ValueError:
110
+ pass
111
+ chunks_data[key] = chunk_indices
112
+
113
+ # Add chunks data to world state
114
+ world_state["chunks"] = chunks_data
115
+ world_state["objects"] = objects_data
116
+
117
+ return {
118
+ "step": self._step,
119
+ "seed": self._seed,
120
+ "length": self._length,
121
+ "episode": self._episode,
122
+ "player_idx": player_idx,
123
+ "world": world_state,
124
+ }
125
+
126
+ def _load(self, state: Dict[str, Any]) -> None:
127
+ """Load environment state from saved data, preserving everything."""
128
+ # Restore basic attributes
129
+ self._step = state["step"]
130
+ self._seed = state["seed"]
131
+ self._length = state["length"]
132
+ self._episode = state["episode"]
133
+
134
+ # Restore world state
135
+ world_data = state["world"]
136
+ self._world.area = world_data["area"]
137
+ self._world.daylight = world_data["daylight"]
138
+ self._world._mat_map = np.array(world_data["_mat_map"])
139
+ self._world._obj_map = np.array(world_data["_obj_map"])
140
+ self._world._mat_names = world_data.get("_mat_names", {})
141
+ self._world._mat_ids = world_data.get("_mat_ids", {})
142
+ self._world._chunk_size = world_data.get("_chunk_size", (16, 16))
143
+
144
+ # Clear existing objects
145
+ self._world._objects = []
146
+ self._world._chunks.clear()
147
+
148
+ # First pass: Create player object first if it exists
149
+ player_obj = None
150
+ player_idx = state.get("player_idx")
151
+
152
+ if player_idx is not None:
153
+ player_data = world_data["objects"][player_idx]
154
+ if player_data and "Player" in player_data["type"]:
155
+ player_obj = objects.Player(self._world, np.array(player_data["pos"]))
156
+ player_obj.facing = (
157
+ tuple(player_data["facing"]) if player_data.get("facing") else (0, 1)
158
+ )
159
+ player_obj.health = player_data["health"]
160
+ player_obj.inventory = collections.Counter(player_data["inventory"])
161
+ player_obj.achievements = dict(player_data["achievements"])
162
+ player_obj._hunger = player_data["_hunger"]
163
+ player_obj._thirst = player_data["_thirst"]
164
+ player_obj._fatigue = player_data["_fatigue"]
165
+ player_obj._recover = player_data["_recover"]
166
+ player_obj.action = player_data["action"]
167
+ player_obj.sleeping = player_data["sleeping"]
168
+ player_obj._last_health = player_data["_last_health"]
169
+ self._player = player_obj
170
+
171
+ # Second pass: Create all objects
172
+ objects_by_idx = {}
173
+
174
+ for obj_data in world_data["objects"]:
175
+ if obj_data is None:
176
+ self._world._objects.append(None)
177
+ else:
178
+ idx = obj_data["_index"]
179
+
180
+ # Skip player as we already created it
181
+ if idx == player_idx and player_obj is not None:
182
+ while len(self._world._objects) <= idx:
183
+ self._world._objects.append(None)
184
+ self._world._objects[idx] = player_obj
185
+ objects_by_idx[idx] = player_obj
186
+ continue
187
+
188
+ # Create object based on type
189
+ type_str = obj_data["type"]
190
+ module_name, cls_name = type_str.rsplit(".", 1)
191
+
192
+ # Special handling for each object type
193
+ if cls_name == "Zombie":
194
+ obj = objects.Zombie(self._world, np.array(obj_data["pos"]), player_obj)
195
+ obj.health = obj_data.get("health", 3)
196
+ obj.cooldown = obj_data.get("cooldown", 0)
197
+ elif cls_name == "Skeleton":
198
+ obj = objects.Skeleton(self._world, np.array(obj_data["pos"]), player_obj)
199
+ obj.health = obj_data.get("health", 2)
200
+ obj.reload = obj_data.get("reload", 0)
201
+ elif cls_name == "Cow":
202
+ obj = objects.Cow(self._world, np.array(obj_data["pos"]))
203
+ obj.health = obj_data.get("health", 3)
204
+ elif cls_name == "Plant":
205
+ obj = objects.Plant(self._world, np.array(obj_data["pos"]))
206
+ obj.health = obj_data.get("health", 1)
207
+ obj.grown = obj_data.get("grown", 0)
208
+ obj.kind = obj_data.get("kind", "tree")
209
+ elif cls_name == "Arrow":
210
+ obj = objects.Arrow(
211
+ self._world,
212
+ np.array(obj_data["pos"]),
213
+ tuple(obj_data.get("facing", [0, 1])),
214
+ )
215
+ elif cls_name in ["Stone", "Coal", "Iron", "Diamond"]:
216
+ # These are material objects
217
+ cls = getattr(objects, cls_name)
218
+ obj = cls(self._world, np.array(obj_data["pos"]))
219
+ elif cls_name in ["Table", "Furnace"]:
220
+ cls = getattr(objects, cls_name)
221
+ obj = cls(self._world, np.array(obj_data["pos"]))
222
+ else:
223
+ # Generic object creation
224
+ import importlib
225
+
226
+ module = importlib.import_module(module_name)
227
+ cls = getattr(module, cls_name)
228
+ obj = cls(self._world, np.array(obj_data["pos"]))
229
+ if hasattr(obj, "health") and "health" in obj_data:
230
+ obj.health = obj_data["health"]
231
+
232
+ obj.removed = obj_data.get("removed", False)
233
+
234
+ # Ensure list is long enough
235
+ while len(self._world._objects) <= idx:
236
+ self._world._objects.append(None)
237
+
238
+ self._world._objects[idx] = obj
239
+ objects_by_idx[idx] = obj
240
+
241
+ # Restore chunks
242
+ for key, obj_indices in world_data["chunks"].items():
243
+ # Convert string key back to tuple if needed
244
+ if isinstance(key, str):
245
+ key = eval(key) # Safe here as we control the format
246
+
247
+ chunk_objects = set()
248
+ for idx in obj_indices:
249
+ if idx in objects_by_idx:
250
+ chunk_objects.add(objects_by_idx[idx])
251
+ if chunk_objects:
252
+ self._world._chunks[key] = chunk_objects
253
+
254
+ # Restore random state
255
+ random_state = pickle.loads(world_data["random_state"])
256
+ self._world.random.set_state(random_state)
257
+
258
+ # Attach methods to Env class
259
+ crafter.Env.save = _save
260
+ crafter.Env.load = _load
261
+
262
+ print("[PATCH] crafter.Env.save() and load() methods added (v3).")
263
+ else:
264
+ print("[PATCH] crafter.Env already has save/load methods.")
265
+
266
+ print("[PATCH] Crafter serialization patch v3 complete.")