synth-ai 0.2.4.dev7__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.
- synth_ai/__init__.py +1 -1
- synth_ai/cli/__init__.py +6 -0
- synth_ai/cli/balance.py +3 -15
- synth_ai/cli/demo.py +68 -9
- synth_ai/cli/rl_demo.py +137 -0
- synth_ai/cli/root.py +65 -0
- synth_ai/config/base_url.py +47 -0
- synth_ai/demos/core/__init__.py +1 -0
- synth_ai/demos/core/cli.py +621 -0
- synth_ai/demos/demo_task_apps/__init__.py +1 -0
- synth_ai/demos/demo_task_apps/core.py +374 -0
- synth_ai/demos/demo_task_apps/math/__init__.py +1 -0
- synth_ai/demos/demo_task_apps/math/app.py +37 -0
- synth_ai/demos/demo_task_apps/math/config.toml +44 -0
- synth_ai/demos/demo_task_apps/math/deploy_modal.py +60 -0
- synth_ai/demos/demo_task_apps/math/deploy_task_app.sh +22 -0
- synth_ai/environments/examples/bandit/__init__.py +33 -0
- synth_ai/environments/examples/bandit/engine.py +294 -0
- synth_ai/environments/examples/bandit/environment.py +194 -0
- synth_ai/environments/examples/bandit/taskset.py +200 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/analyze_semantic_words_markdown.py +250 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +59 -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_config.toml +24 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +1194 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/crafter_synth_config.toml +56 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_config_modal.toml +32 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py +724 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/kick_off_ft_modal.py +384 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_action_results.py +53 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_agent_actions.py +178 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_latest_run.py +222 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_lm_traces.py +183 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_no_rewards.py +210 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_trace_issue.py +206 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_db_schema.py +49 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_latest_results.py +64 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/debug_agent_responses.py +88 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/quick_trace_check.py +77 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/compare_experiments.py +324 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/filter_traces_sft_turso.py +580 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/kick_off_ft_oai.py +362 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/multi_model_config.toml +49 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_enhanced_hooks.py +332 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_events.py +97 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_results.py +217 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_hook_storage.py +87 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_seeds.py +88 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/compare_seed_performance.py +195 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/custom_eval_pipelines.py +400 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/plot_hook_frequency.py +195 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/seed_analysis_summary.py +56 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/run_rollouts_for_models_and_compare_v3.py +858 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +52 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +874 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +1412 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/example_v3_usage.py +216 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/compare_traces.py +296 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_comprehensive_evaluation.py +58 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_env_serialization.py +464 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_evaluation_browser.py +152 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_quick_evaluation.py +51 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_trace_evaluation.py +1412 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/debug_player_loss.py +112 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_service.py +203 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_slowness.py +305 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_by_difficulty.py +126 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_example.py +94 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/explore_saved_states.py +142 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft.py +26 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft_OLD.py +984 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_gemini.py +724 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_modal.py +386 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_metadata.py +205 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_gemini.py +150 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_modal.py +283 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/prepare_vertex_ft.py +280 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/profile_env_slowness.py +456 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/replicate_issue.py +166 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_and_eval.py +102 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_comparison.py +128 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_qwen_rollouts.py +655 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/trace_eval_OLD.py +202 -0
- synth_ai/environments/examples/crafter_classic/agent_demos/old/validate_openai_format.py +166 -0
- synth_ai/environments/examples/crafter_classic/environment.py +41 -2
- synth_ai/environments/examples/crafter_custom/agent_demos/__init__.py +1 -0
- synth_ai/environments/examples/crafter_custom/agent_demos/trace_eval.py +202 -0
- synth_ai/environments/examples/crafter_custom/old/analyze_diamond_issue.py +159 -0
- synth_ai/environments/examples/crafter_custom/old/analyze_diamond_spawning.py +158 -0
- synth_ai/environments/examples/crafter_custom/old/compare_worlds.py +71 -0
- synth_ai/environments/examples/crafter_custom/old/dataset_stats.py +105 -0
- synth_ai/environments/examples/crafter_custom/old/diamond_spawning_summary.py +119 -0
- synth_ai/environments/examples/crafter_custom/old/example_dataset_usage.py +52 -0
- synth_ai/environments/examples/enron/units/keyword_stats.py +112 -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 +48 -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 +221 -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 +831 -0
- synth_ai/environments/examples/red/agent_demos/__init__.py +1 -0
- synth_ai/environments/examples/red/units/__init__.py +1 -0
- synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +899 -0
- synth_ai/environments/examples/sokoban/units/astar_common.py +95 -0
- synth_ai/environments/service/app.py +8 -0
- synth_ai/http.py +102 -0
- synth_ai/inference/__init__.py +7 -0
- synth_ai/inference/client.py +20 -0
- synth_ai/install_sqld.sh +40 -0
- synth_ai/jobs/client.py +246 -0
- synth_ai/learning/__init__.py +24 -0
- synth_ai/learning/client.py +149 -0
- synth_ai/learning/config.py +43 -0
- synth_ai/learning/constants.py +29 -0
- synth_ai/learning/ft_client.py +59 -0
- synth_ai/learning/health.py +43 -0
- synth_ai/learning/jobs.py +205 -0
- synth_ai/learning/rl_client.py +256 -0
- synth_ai/learning/sse.py +58 -0
- synth_ai/learning/validators.py +48 -0
- synth_ai/lm/core/main_v3.py +13 -0
- synth_ai/lm/core/synth_models.py +48 -0
- synth_ai/lm/core/vendor_clients.py +9 -6
- synth_ai/lm/vendors/core/openai_api.py +31 -3
- synth_ai/lm/vendors/openai_standard.py +45 -14
- synth_ai/lm/vendors/supported/custom_endpoint.py +12 -2
- synth_ai/lm/vendors/synth_client.py +372 -28
- synth_ai/rl/__init__.py +30 -0
- synth_ai/rl/contracts.py +32 -0
- synth_ai/rl/env_keys.py +137 -0
- synth_ai/rl/secrets.py +19 -0
- synth_ai/scripts/verify_rewards.py +100 -0
- synth_ai/task/__init__.py +10 -0
- synth_ai/task/contracts.py +120 -0
- synth_ai/task/health.py +28 -0
- synth_ai/task/validators.py +12 -0
- synth_ai/tracing_v3/hooks.py +3 -1
- synth_ai/tracing_v3/session_tracer.py +123 -2
- synth_ai/tracing_v3/turso/manager.py +218 -0
- synth_ai/tracing_v3/turso/models.py +53 -0
- synth_ai-0.2.4.dev9.dist-info/METADATA +91 -0
- {synth_ai-0.2.4.dev7.dist-info → synth_ai-0.2.4.dev9.dist-info}/RECORD +147 -30
- {synth_ai-0.2.4.dev7.dist-info → synth_ai-0.2.4.dev9.dist-info}/entry_points.txt +1 -0
- synth_ai/tui/__init__.py +0 -1
- synth_ai/tui/__main__.py +0 -13
- synth_ai/tui/cli/__init__.py +0 -1
- synth_ai/tui/cli/query_experiments.py +0 -164
- synth_ai/tui/cli/query_experiments_v3.py +0 -164
- synth_ai/tui/dashboard.py +0 -340
- synth_ai-0.2.4.dev7.dist-info/METADATA +0 -193
- {synth_ai-0.2.4.dev7.dist-info → synth_ai-0.2.4.dev9.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.4.dev7.dist-info → synth_ai-0.2.4.dev9.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.4.dev7.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()
|