synth-ai 0.2.4.dev8__py3-none-any.whl → 0.2.4.dev9__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.

Potentially problematic release.


This version of synth-ai might be problematic. Click here for more details.

Files changed (111) hide show
  1. synth_ai/cli/__init__.py +6 -0
  2. synth_ai/cli/demo.py +68 -9
  3. synth_ai/cli/rl_demo.py +137 -0
  4. synth_ai/cli/root.py +65 -0
  5. synth_ai/demos/core/__init__.py +1 -0
  6. synth_ai/demos/core/cli.py +621 -0
  7. synth_ai/demos/demo_task_apps/__init__.py +1 -0
  8. synth_ai/demos/demo_task_apps/core.py +374 -0
  9. synth_ai/demos/demo_task_apps/math/__init__.py +1 -0
  10. synth_ai/demos/demo_task_apps/math/app.py +37 -0
  11. synth_ai/demos/demo_task_apps/math/config.toml +44 -0
  12. synth_ai/demos/demo_task_apps/math/deploy_modal.py +60 -0
  13. synth_ai/demos/demo_task_apps/math/deploy_task_app.sh +22 -0
  14. synth_ai/environments/examples/bandit/__init__.py +33 -0
  15. synth_ai/environments/examples/bandit/engine.py +294 -0
  16. synth_ai/environments/examples/bandit/environment.py +194 -0
  17. synth_ai/environments/examples/bandit/taskset.py +200 -0
  18. synth_ai/environments/examples/crafter_classic/agent_demos/analyze_semantic_words_markdown.py +250 -0
  19. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +59 -0
  20. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_browser.py +152 -0
  21. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_config.toml +24 -0
  22. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +1194 -0
  23. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/crafter_synth_config.toml +56 -0
  24. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_config_modal.toml +32 -0
  25. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py +724 -0
  26. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/kick_off_ft_modal.py +384 -0
  27. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_action_results.py +53 -0
  28. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_agent_actions.py +178 -0
  29. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_latest_run.py +222 -0
  30. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_lm_traces.py +183 -0
  31. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_no_rewards.py +210 -0
  32. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_trace_issue.py +206 -0
  33. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_db_schema.py +49 -0
  34. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_latest_results.py +64 -0
  35. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/debug_agent_responses.py +88 -0
  36. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/quick_trace_check.py +77 -0
  37. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/compare_experiments.py +324 -0
  38. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/filter_traces_sft_turso.py +580 -0
  39. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/kick_off_ft_oai.py +362 -0
  40. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/multi_model_config.toml +49 -0
  41. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_enhanced_hooks.py +332 -0
  42. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_events.py +97 -0
  43. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_results.py +217 -0
  44. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_hook_storage.py +87 -0
  45. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_seeds.py +88 -0
  46. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/compare_seed_performance.py +195 -0
  47. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/custom_eval_pipelines.py +400 -0
  48. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/plot_hook_frequency.py +195 -0
  49. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/seed_analysis_summary.py +56 -0
  50. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/run_rollouts_for_models_and_compare_v3.py +858 -0
  51. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +52 -0
  52. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +874 -0
  53. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +1412 -0
  54. synth_ai/environments/examples/crafter_classic/agent_demos/example_v3_usage.py +216 -0
  55. synth_ai/environments/examples/crafter_classic/agent_demos/old/compare_traces.py +296 -0
  56. synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_comprehensive_evaluation.py +58 -0
  57. synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_env_serialization.py +464 -0
  58. synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_evaluation_browser.py +152 -0
  59. synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_quick_evaluation.py +51 -0
  60. synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_trace_evaluation.py +1412 -0
  61. synth_ai/environments/examples/crafter_classic/agent_demos/old/debug_player_loss.py +112 -0
  62. synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_service.py +203 -0
  63. synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_slowness.py +305 -0
  64. synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_by_difficulty.py +126 -0
  65. synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_example.py +94 -0
  66. synth_ai/environments/examples/crafter_classic/agent_demos/old/explore_saved_states.py +142 -0
  67. synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft.py +26 -0
  68. synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft_OLD.py +984 -0
  69. synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_gemini.py +724 -0
  70. synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_modal.py +386 -0
  71. synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_metadata.py +205 -0
  72. synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_gemini.py +150 -0
  73. synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_modal.py +283 -0
  74. synth_ai/environments/examples/crafter_classic/agent_demos/old/prepare_vertex_ft.py +280 -0
  75. synth_ai/environments/examples/crafter_classic/agent_demos/old/profile_env_slowness.py +456 -0
  76. synth_ai/environments/examples/crafter_classic/agent_demos/old/replicate_issue.py +166 -0
  77. synth_ai/environments/examples/crafter_classic/agent_demos/old/run_and_eval.py +102 -0
  78. synth_ai/environments/examples/crafter_classic/agent_demos/old/run_comparison.py +128 -0
  79. synth_ai/environments/examples/crafter_classic/agent_demos/old/run_qwen_rollouts.py +655 -0
  80. synth_ai/environments/examples/crafter_classic/agent_demos/old/trace_eval_OLD.py +202 -0
  81. synth_ai/environments/examples/crafter_classic/agent_demos/old/validate_openai_format.py +166 -0
  82. synth_ai/environments/examples/crafter_classic/environment.py +41 -2
  83. synth_ai/environments/examples/crafter_custom/agent_demos/__init__.py +1 -0
  84. synth_ai/environments/examples/crafter_custom/agent_demos/trace_eval.py +202 -0
  85. synth_ai/environments/examples/crafter_custom/old/analyze_diamond_issue.py +159 -0
  86. synth_ai/environments/examples/crafter_custom/old/analyze_diamond_spawning.py +158 -0
  87. synth_ai/environments/examples/crafter_custom/old/compare_worlds.py +71 -0
  88. synth_ai/environments/examples/crafter_custom/old/dataset_stats.py +105 -0
  89. synth_ai/environments/examples/crafter_custom/old/diamond_spawning_summary.py +119 -0
  90. synth_ai/environments/examples/crafter_custom/old/example_dataset_usage.py +52 -0
  91. synth_ai/environments/examples/enron/units/keyword_stats.py +112 -0
  92. synth_ai/environments/examples/minigrid/agent_demos/minigrid_evaluation_framework.py +1188 -0
  93. synth_ai/environments/examples/minigrid/agent_demos/minigrid_quick_evaluation.py +48 -0
  94. synth_ai/environments/examples/minigrid/agent_demos/minigrid_react_agent.py +562 -0
  95. synth_ai/environments/examples/minigrid/agent_demos/minigrid_trace_evaluation.py +221 -0
  96. synth_ai/environments/examples/nethack/agent_demos/nethack_evaluation_framework.py +981 -0
  97. synth_ai/environments/examples/nethack/agent_demos/nethack_quick_evaluation.py +74 -0
  98. synth_ai/environments/examples/nethack/agent_demos/nethack_react_agent.py +831 -0
  99. synth_ai/environments/examples/red/agent_demos/__init__.py +1 -0
  100. synth_ai/environments/examples/red/units/__init__.py +1 -0
  101. synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +899 -0
  102. synth_ai/environments/examples/sokoban/units/astar_common.py +95 -0
  103. synth_ai/environments/service/app.py +8 -0
  104. synth_ai/install_sqld.sh +40 -0
  105. synth_ai-0.2.4.dev9.dist-info/METADATA +91 -0
  106. {synth_ai-0.2.4.dev8.dist-info → synth_ai-0.2.4.dev9.dist-info}/RECORD +110 -11
  107. {synth_ai-0.2.4.dev8.dist-info → synth_ai-0.2.4.dev9.dist-info}/entry_points.txt +1 -0
  108. synth_ai-0.2.4.dev8.dist-info/METADATA +0 -635
  109. {synth_ai-0.2.4.dev8.dist-info → synth_ai-0.2.4.dev9.dist-info}/WHEEL +0 -0
  110. {synth_ai-0.2.4.dev8.dist-info → synth_ai-0.2.4.dev9.dist-info}/licenses/LICENSE +0 -0
  111. {synth_ai-0.2.4.dev8.dist-info → synth_ai-0.2.4.dev9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug exactly where player reference is lost
4
+ ============================================
5
+ """
6
+
7
+ import asyncio
8
+ from uuid import uuid4
9
+ import gc
10
+
11
+ from synth_ai.environments.examples.crafter_classic.environment import CrafterClassicEnvironment
12
+ from synth_ai.environments.examples.crafter_classic.taskset import CrafterTaskInstance, CrafterTaskInstanceMetadata
13
+ from synth_ai.environments.environment.tools import EnvToolCall
14
+ from synth_ai.environments.tasks.core import Impetus, Intent
15
+
16
+
17
+ async def debug_player_loss():
18
+ """Find exactly where player reference is lost."""
19
+ task = CrafterTaskInstance(
20
+ id=uuid4(),
21
+ impetus=Impetus(instructions="Test"),
22
+ intent=Intent(rubric={"goal": "Test"}, gold_trajectories=None, gold_state_diff={}),
23
+ metadata=CrafterTaskInstanceMetadata(
24
+ difficulty="easy",
25
+ seed=600,
26
+ num_trees_radius=5,
27
+ num_cows_radius=2,
28
+ num_hostiles_radius=0
29
+ ),
30
+ is_reproducible=True,
31
+ initial_engine_snapshot=None
32
+ )
33
+
34
+ # Create and initialize environment
35
+ env = CrafterClassicEnvironment(task)
36
+ await env.initialize()
37
+
38
+ # Take some actions
39
+ for action in [1, 2, 5, 3]:
40
+ await env.step(EnvToolCall(tool="interact", args={"action": action}))
41
+
42
+ print("BEFORE SERIALIZATION:")
43
+ print(f" Player id: {id(env.engine.env._player)}")
44
+ print(f" Player: {env.engine.env._player}")
45
+ print(f" Player pos: {env.engine.env._player.pos}")
46
+
47
+ # Serialize
48
+ snapshot = await env._serialize_engine()
49
+
50
+ # Check snapshot contents
51
+ print("\nSNAPSHOT CONTENTS:")
52
+ print(f" env_raw_state keys: {list(snapshot.env_raw_state.keys())}")
53
+ print(f" player_idx in snapshot: {snapshot.env_raw_state.get('player_idx')}")
54
+
55
+ # Deserialize
56
+ restored_env = await CrafterClassicEnvironment._deserialize_engine(snapshot, task)
57
+
58
+ print("\nAFTER DESERIALIZATION:")
59
+ print(f" Player id: {id(restored_env.engine.env._player)}")
60
+ print(f" Player: {restored_env.engine.env._player}")
61
+ print(f" Player pos: {restored_env.engine.env._player.pos if restored_env.engine.env._player else 'None'}")
62
+
63
+ # Check if player is in objects list
64
+ player_in_objects = False
65
+ for i, obj in enumerate(restored_env.engine.env._world._objects):
66
+ if obj is restored_env.engine.env._player:
67
+ player_in_objects = True
68
+ print(f" Player found in objects at index {i}")
69
+ break
70
+ if not player_in_objects:
71
+ print(" Player NOT in objects list!")
72
+
73
+ # Now let's trace through a step
74
+ print("\nTRACING THROUGH STEP:")
75
+
76
+ # Check before _step_engine
77
+ print("1. Before _step_engine:")
78
+ print(f" Player: {restored_env.engine.env._player}")
79
+
80
+ # Check at start of _step_engine (manually)
81
+ print("\n2. Inside _step_engine (manual check):")
82
+ print(f" self.env._player: {restored_env.engine.env._player}")
83
+
84
+ # Try render directly
85
+ print("\n3. Testing render directly:")
86
+ try:
87
+ img = restored_env.engine.env.render()
88
+ print(f" Render succeeded")
89
+ print(f" Player after render: {restored_env.engine.env._player}")
90
+ except Exception as e:
91
+ print(f" Render failed: {e}")
92
+ print(f" Player after failed render: {restored_env.engine.env._player}")
93
+
94
+ # Now try actual step
95
+ print("\n4. Trying actual step:")
96
+ try:
97
+ result = await restored_env.step(EnvToolCall(tool="interact", args={"action": 5}))
98
+ print(f" Step succeeded, reward: {result.get('reward_last_step')}")
99
+ except Exception as e:
100
+ print(f" Step failed: {e}")
101
+
102
+ # Check player again
103
+ print(f"\n5. Player after step attempt: {restored_env.engine.env._player}")
104
+
105
+ # Check if garbage collection is involved
106
+ print("\n6. Checking garbage collection:")
107
+ gc.collect()
108
+ print(f" Player after gc: {restored_env.engine.env._player}")
109
+
110
+
111
+ if __name__ == "__main__":
112
+ asyncio.run(debug_player_loss())
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Diagnostic script to test Crafter service performance directly.
4
+ This will help identify if the slowdown is in the service or the client.
5
+ """
6
+
7
+ import asyncio
8
+ import time
9
+ import httpx
10
+ import uuid
11
+ from typing import List, Dict, Any
12
+
13
+ async def test_service_performance():
14
+ """Test the Crafter service performance directly."""
15
+
16
+ service_url = "http://localhost:8901"
17
+
18
+ print("🔍 Crafter Service Performance Diagnostic")
19
+ print("=" * 60)
20
+
21
+ # Test 1: Health check
22
+ print("\n1️⃣ Testing health check...")
23
+ async with httpx.AsyncClient(timeout=5.0) as client:
24
+ start_time = time.time()
25
+ try:
26
+ response = await client.get(f"{service_url}/health")
27
+ end_time = time.time()
28
+ print(f" ✅ Health check: {response.status_code} in {(end_time - start_time)*1000:.1f}ms")
29
+ print(f" 📄 Response size: {len(response.content)} bytes")
30
+ except Exception as e:
31
+ print(f" ❌ Health check failed: {e}")
32
+ return
33
+
34
+ # Test 2: Environment creation
35
+ print("\n2️⃣ Testing environment creation...")
36
+ async with httpx.AsyncClient(timeout=10.0) as client:
37
+ start_time = time.time()
38
+ try:
39
+ # Create proper task instance format
40
+ task_instance = {
41
+ "id": str(uuid.uuid4()),
42
+ "metadata": {
43
+ "difficulty": "easy",
44
+ "seed": 42,
45
+ "num_trees_radius": 5,
46
+ "num_cows_radius": 2,
47
+ "num_hostiles_radius": 0
48
+ },
49
+ "impetus": {
50
+ "instructions": "Survive and unlock achievements in easy environment."
51
+ },
52
+ "intent": {
53
+ "rubric": {},
54
+ "gold_trajectories": None,
55
+ "gold_state_diff": {}
56
+ },
57
+ "is_reproducible": True,
58
+ "initial_engine_snapshot": None,
59
+ "config": {"world_config": "easy"}
60
+ }
61
+
62
+ response = await client.post(
63
+ f"{service_url}/env/CrafterClassic/initialize",
64
+ json={"task_instance": task_instance}
65
+ )
66
+ end_time = time.time()
67
+ print(f" ✅ Environment creation: {response.status_code} in {(end_time - start_time)*1000:.1f}ms")
68
+
69
+ if response.status_code != 200:
70
+ print(f" ❌ Error response: {response.text[:200]}")
71
+
72
+ if response.status_code == 200:
73
+ data = response.json()
74
+ obs_size = len(str(data.get("observation", {})))
75
+ print(f" 📄 Observation size: {obs_size} characters")
76
+ print(f" 🆔 Environment ID: {data.get('env_id', 'N/A')}")
77
+
78
+ env_id = data.get("env_id")
79
+
80
+ # Test 3: Step execution
81
+ if env_id:
82
+ print(f"\n3️⃣ Testing step execution (env_id: {env_id})...")
83
+ step_start = time.time()
84
+ step_response = await client.post(
85
+ f"{service_url}/env/CrafterClassic/step",
86
+ json={
87
+ "env_id": env_id,
88
+ "request_id": str(uuid.uuid4()),
89
+ "action": {
90
+ "tool_calls": [{"tool": "interact", "args": {"action": 5}}]
91
+ }
92
+ }
93
+ )
94
+
95
+ if step_response.status_code != 200:
96
+ print(f" ❌ Step error: {step_response.text[:200]}")
97
+ step_end = time.time()
98
+ print(f" ✅ Step execution: {step_response.status_code} in {(step_end - step_start)*1000:.1f}ms")
99
+
100
+ if step_response.status_code == 200:
101
+ step_data = step_response.json()
102
+ step_obs_size = len(str(step_data.get("observation", {})))
103
+ print(f" 📄 Step observation size: {step_obs_size} characters")
104
+
105
+ # Test 4: Multiple rapid steps
106
+ print(f"\n4️⃣ Testing multiple rapid steps...")
107
+ step_times = []
108
+ for i in range(5):
109
+ step_start = time.time()
110
+ rapid_response = await client.post(
111
+ f"{service_url}/env/CrafterClassic/step",
112
+ json={
113
+ "env_id": env_id,
114
+ "request_id": str(uuid.uuid4()),
115
+ "action": {
116
+ "tool_calls": [{"tool": "interact", "args": {"action": 5}}]
117
+ }
118
+ }
119
+ )
120
+ step_end = time.time()
121
+ step_time = (step_end - step_start) * 1000
122
+ step_times.append(step_time)
123
+ print(f" Step {i+1}: {rapid_response.status_code} in {step_time:.1f}ms")
124
+
125
+ avg_step_time = sum(step_times) / len(step_times)
126
+ print(f" 📊 Average step time: {avg_step_time:.1f}ms")
127
+ print(f" 📊 Min step time: {min(step_times):.1f}ms")
128
+ print(f" 📊 Max step time: {max(step_times):.1f}ms")
129
+
130
+ # Test 5: Close environment
131
+ print(f"\n5️⃣ Testing environment cleanup...")
132
+ cleanup_start = time.time()
133
+ cleanup_response = await client.post(f"{service_url}/env/{env_id}/close")
134
+ cleanup_end = time.time()
135
+ print(f" ✅ Cleanup: {cleanup_response.status_code} in {(cleanup_end - cleanup_start)*1000:.1f}ms")
136
+
137
+ except Exception as e:
138
+ print(f" ❌ Environment test failed: {e}")
139
+
140
+ # Test 6: Concurrent requests
141
+ print(f"\n6️⃣ Testing concurrent requests...")
142
+ async with httpx.AsyncClient(timeout=10.0) as client:
143
+ async def create_and_step():
144
+ try:
145
+ # Create proper task instance format
146
+ task_instance = {
147
+ "id": str(uuid.uuid4()),
148
+ "metadata": {
149
+ "difficulty": "easy",
150
+ "seed": 42,
151
+ "num_trees_radius": 5,
152
+ "num_cows_radius": 2,
153
+ "num_hostiles_radius": 0
154
+ },
155
+ "impetus": {
156
+ "instructions": "Survive and unlock achievements in easy environment."
157
+ },
158
+ "intent": {
159
+ "rubric": {},
160
+ "gold_trajectories": None,
161
+ "gold_state_diff": {}
162
+ },
163
+ "is_reproducible": True,
164
+ "initial_engine_snapshot": None,
165
+ "config": {"world_config": "easy"}
166
+ }
167
+
168
+ # Create environment
169
+ create_response = await client.post(
170
+ f"{service_url}/env/CrafterClassic/initialize",
171
+ json={"task_instance": task_instance}
172
+ )
173
+ if create_response.status_code == 200:
174
+ env_id = create_response.json()["env_id"]
175
+ # Take one step
176
+ step_response = await client.post(
177
+ f"{service_url}/env/CrafterClassic/step",
178
+ json={
179
+ "env_id": env_id,
180
+ "request_id": str(uuid.uuid4()),
181
+ "action": {
182
+ "tool_calls": [{"tool": "interact", "args": {"action": 5}}]
183
+ }
184
+ }
185
+ )
186
+ # Cleanup
187
+ await client.post(f"{service_url}/env/{env_id}/close")
188
+ return step_response.status_code == 200
189
+ return False
190
+ except:
191
+ return False
192
+
193
+ # Run 3 concurrent requests
194
+ start_time = time.time()
195
+ results = await asyncio.gather(*[create_and_step() for _ in range(3)])
196
+ end_time = time.time()
197
+
198
+ success_count = sum(results)
199
+ print(f" ✅ Concurrent test: {success_count}/3 successful in {(end_time - start_time)*1000:.1f}ms")
200
+ print(f" 📊 Average per request: {(end_time - start_time)*1000/3:.1f}ms")
201
+
202
+ if __name__ == "__main__":
203
+ asyncio.run(test_service_performance())
@@ -0,0 +1,305 @@
1
+ #!/usr/bin/env python3
2
+ """Diagnose Crafter environment slowness by profiling different components."""
3
+
4
+ import time
5
+ import logging
6
+ import crafter
7
+ import numpy as np
8
+ import asyncio
9
+ from typing import Dict, List, Any
10
+ import statistics
11
+ import cProfile
12
+ import pstats
13
+ import io
14
+
15
+ # Configure logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Import patches
23
+ import synth_ai.environments.examples.crafter_classic.engine_deterministic_patch
24
+ import synth_ai.environments.examples.crafter_classic.engine_serialization_patch_v3
25
+ import synth_ai.environments.examples.crafter_classic.world_config_patch_simple
26
+
27
+
28
+ class CrafterProfiler:
29
+ """Profile different aspects of Crafter environment."""
30
+
31
+ def __init__(self):
32
+ self.timings: Dict[str, List[float]] = {
33
+ "env_creation": [],
34
+ "env_reset": [],
35
+ "env_step": [],
36
+ "env_render": [],
37
+ "state_extraction": [],
38
+ "serialization": [],
39
+ }
40
+
41
+ def profile_raw_crafter(self, num_episodes: int = 5, steps_per_episode: int = 50):
42
+ """Profile the raw Crafter environment without any wrappers."""
43
+ logger.info("=" * 60)
44
+ logger.info("PROFILING RAW CRAFTER ENVIRONMENT")
45
+ logger.info("=" * 60)
46
+
47
+ for episode in range(num_episodes):
48
+ logger.info(f"\nEpisode {episode + 1}/{num_episodes}")
49
+
50
+ # Time environment creation
51
+ start = time.time()
52
+ env = crafter.Env(area=(64, 64), length=1000)
53
+ self.timings["env_creation"].append(time.time() - start)
54
+ logger.info(f" Environment created in {self.timings['env_creation'][-1]:.3f}s")
55
+
56
+ # Time reset
57
+ start = time.time()
58
+ obs = env.reset()
59
+ self.timings["env_reset"].append(time.time() - start)
60
+ logger.info(f" Environment reset in {self.timings['env_reset'][-1]:.3f}s")
61
+
62
+ # Time steps
63
+ step_times = []
64
+ render_times = []
65
+
66
+ for step in range(steps_per_episode):
67
+ # Time step
68
+ action = np.random.randint(0, env.action_space.n)
69
+ start = time.time()
70
+ obs, reward, done, info = env.step(action)
71
+ step_time = time.time() - start
72
+ step_times.append(step_time)
73
+
74
+ # Time render
75
+ start = time.time()
76
+ rendered = env.render()
77
+ render_time = time.time() - start
78
+ render_times.append(render_time)
79
+
80
+ if done:
81
+ logger.info(f" Episode ended at step {step + 1}")
82
+ break
83
+
84
+ self.timings["env_step"].extend(step_times)
85
+ self.timings["env_render"].extend(render_times)
86
+
87
+ mean_step = statistics.mean(step_times) if step_times else 0
88
+ mean_render = statistics.mean(render_times) if render_times else 0
89
+ logger.info(f" Mean step time: {mean_step:.3f}s")
90
+ logger.info(f" Mean render time: {mean_render:.3f}s")
91
+
92
+ def profile_with_patches(self, num_episodes: int = 3, steps_per_episode: int = 20):
93
+ """Profile Crafter with all patches applied."""
94
+ logger.info("\n" + "=" * 60)
95
+ logger.info("PROFILING CRAFTER WITH PATCHES")
96
+ logger.info("=" * 60)
97
+
98
+ for episode in range(num_episodes):
99
+ logger.info(f"\nEpisode {episode + 1}/{num_episodes}")
100
+
101
+ # Create environment
102
+ start = time.time()
103
+ env = crafter.Env(area=(64, 64), length=1000)
104
+ self.timings["env_creation"].append(time.time() - start)
105
+ logger.info(f" Environment created in {self.timings['env_creation'][-1]:.3f}s")
106
+
107
+ # Reset
108
+ start = time.time()
109
+ obs = env.reset()
110
+ self.timings["env_reset"].append(time.time() - start)
111
+ logger.info(f" Environment reset in {self.timings['env_reset'][-1]:.3f}s")
112
+
113
+ # Test serialization
114
+ if hasattr(env, 'save'):
115
+ start = time.time()
116
+ state = env.save()
117
+ save_time = time.time() - start
118
+ self.timings["serialization"].append(save_time)
119
+ logger.info(f" State saved in {save_time:.3f}s")
120
+
121
+ # Test loading
122
+ start = time.time()
123
+ env.load(state)
124
+ load_time = time.time() - start
125
+ logger.info(f" State loaded in {load_time:.3f}s")
126
+
127
+ # Run steps
128
+ for step in range(steps_per_episode):
129
+ action = np.random.randint(0, env.action_space.n)
130
+ start = time.time()
131
+ obs, reward, done, info = env.step(action)
132
+ self.timings["env_step"].append(time.time() - start)
133
+
134
+ if done:
135
+ break
136
+
137
+ def profile_specific_operations(self):
138
+ """Profile specific operations that might be slow."""
139
+ logger.info("\n" + "=" * 60)
140
+ logger.info("PROFILING SPECIFIC OPERATIONS")
141
+ logger.info("=" * 60)
142
+
143
+ env = crafter.Env(area=(64, 64), length=1000)
144
+ env.reset()
145
+
146
+ # Profile world generation
147
+ logger.info("\n1. World Generation:")
148
+ start = time.time()
149
+ # Access internal world generation if available
150
+ if hasattr(env, '_world'):
151
+ logger.info(f" World object exists: {env._world is not None}")
152
+ logger.info(f" World size: {env._area}")
153
+ elapsed = time.time() - start
154
+ logger.info(f" Time to access world: {elapsed:.3f}s")
155
+
156
+ # Profile rendering operations
157
+ logger.info("\n2. Rendering Operations:")
158
+ render_times = []
159
+ for i in range(10):
160
+ start = time.time()
161
+ obs = env.render()
162
+ render_times.append(time.time() - start)
163
+ logger.info(f" Mean render time: {statistics.mean(render_times):.3f}s")
164
+ logger.info(f" Render output shape: {obs.shape if hasattr(obs, 'shape') else 'N/A'}")
165
+
166
+ # Profile achievement checking
167
+ logger.info("\n3. Achievement System:")
168
+ if hasattr(env, '_achievements'):
169
+ start = time.time()
170
+ # Simulate achievement checking
171
+ for _ in range(10):
172
+ env.step(0) # No-op action
173
+ elapsed = time.time() - start
174
+ logger.info(f" 10 steps with achievement checking: {elapsed:.3f}s")
175
+
176
+ def run_cprofile_analysis(self):
177
+ """Run cProfile analysis on a typical episode."""
178
+ logger.info("\n" + "=" * 60)
179
+ logger.info("RUNNING CPROFILE ANALYSIS")
180
+ logger.info("=" * 60)
181
+
182
+ def run_episode():
183
+ env = crafter.Env(area=(64, 64), length=1000)
184
+ env.reset()
185
+ for _ in range(50):
186
+ action = np.random.randint(0, env.action_space.n)
187
+ obs, reward, done, info = env.step(action)
188
+ if done:
189
+ break
190
+
191
+ # Profile the episode
192
+ profiler = cProfile.Profile()
193
+ profiler.enable()
194
+ run_episode()
195
+ profiler.disable()
196
+
197
+ # Print stats
198
+ s = io.StringIO()
199
+ ps = pstats.Stats(profiler, stream=s).sort_stats('cumulative')
200
+ ps.print_stats(20) # Top 20 functions
201
+ logger.info("\nTop 20 time-consuming functions:")
202
+ logger.info(s.getvalue())
203
+
204
+ def print_summary(self):
205
+ """Print timing summary."""
206
+ logger.info("\n" + "=" * 60)
207
+ logger.info("TIMING SUMMARY")
208
+ logger.info("=" * 60)
209
+
210
+ for operation, times in self.timings.items():
211
+ if times:
212
+ logger.info(f"\n{operation.upper()}:")
213
+ logger.info(f" Count: {len(times)}")
214
+ logger.info(f" Mean: {statistics.mean(times):.3f}s")
215
+ logger.info(f" Median: {statistics.median(times):.3f}s")
216
+ logger.info(f" Min: {min(times):.3f}s")
217
+ logger.info(f" Max: {max(times):.3f}s")
218
+ if len(times) > 1:
219
+ logger.info(f" Std Dev: {statistics.stdev(times):.3f}s")
220
+
221
+
222
+ async def check_import_time():
223
+ """Check how long it takes to import Crafter environment."""
224
+ logger.info("\n" + "=" * 60)
225
+ logger.info("CHECKING IMPORT TIMES")
226
+ logger.info("=" * 60)
227
+
228
+ # Time importing the environment module
229
+ start = time.time()
230
+ import synth_ai.environments.examples.crafter_classic.environment
231
+ env_import_time = time.time() - start
232
+ logger.info(f"Importing crafter_classic.environment: {env_import_time:.3f}s")
233
+
234
+ # Time importing the engine
235
+ start = time.time()
236
+ import synth_ai.environments.examples.crafter_classic.engine
237
+ engine_import_time = time.time() - start
238
+ logger.info(f"Importing crafter_classic.engine: {engine_import_time:.3f}s")
239
+
240
+ # Time creating environment wrapper
241
+ from synth_ai.environments.examples.crafter_classic.environment import CrafterClassicEnvironment
242
+ from types import SimpleNamespace
243
+
244
+ start = time.time()
245
+ task = SimpleNamespace(initial_engine_snapshot={})
246
+ env_wrapper = CrafterClassicEnvironment(task)
247
+ wrapper_creation_time = time.time() - start
248
+ logger.info(f"Creating CrafterClassicEnvironment wrapper: {wrapper_creation_time:.3f}s")
249
+
250
+ # Time initialization
251
+ start = time.time()
252
+ await env_wrapper.initialize()
253
+ init_time = time.time() - start
254
+ logger.info(f"Initializing environment: {init_time:.3f}s")
255
+
256
+
257
+ def main():
258
+ """Run all profiling tests."""
259
+ profiler = CrafterProfiler()
260
+
261
+ # Test 1: Profile raw Crafter
262
+ profiler.profile_raw_crafter(num_episodes=2, steps_per_episode=20)
263
+
264
+ # Test 2: Profile with patches
265
+ profiler.profile_with_patches(num_episodes=2, steps_per_episode=20)
266
+
267
+ # Test 3: Profile specific operations
268
+ profiler.profile_specific_operations()
269
+
270
+ # Test 4: Run cProfile analysis
271
+ profiler.run_cprofile_analysis()
272
+
273
+ # Test 5: Check import times
274
+ asyncio.run(check_import_time())
275
+
276
+ # Print summary
277
+ profiler.print_summary()
278
+
279
+ # Recommendations
280
+ logger.info("\n" + "=" * 60)
281
+ logger.info("RECOMMENDATIONS")
282
+ logger.info("=" * 60)
283
+
284
+ mean_step = statistics.mean(profiler.timings["env_step"]) if profiler.timings["env_step"] else 0
285
+ mean_render = statistics.mean(profiler.timings["env_render"]) if profiler.timings["env_render"] else 0
286
+
287
+ if mean_step > 0.1:
288
+ logger.info("⚠️ Step operations are slow (>100ms). Consider:")
289
+ logger.info(" - Check if debug mode is enabled")
290
+ logger.info(" - Profile the step() method specifically")
291
+ logger.info(" - Check for unnecessary computations")
292
+
293
+ if mean_render > 0.05:
294
+ logger.info("⚠️ Render operations are slow (>50ms). Consider:")
295
+ logger.info(" - Caching rendered observations")
296
+ logger.info(" - Optimizing image generation")
297
+
298
+ if profiler.timings["serialization"] and statistics.mean(profiler.timings["serialization"]) > 0.5:
299
+ logger.info("⚠️ Serialization is slow (>500ms). Consider:")
300
+ logger.info(" - Using more efficient serialization format")
301
+ logger.info(" - Reducing state size")
302
+
303
+
304
+ if __name__ == "__main__":
305
+ main()