synth-ai 0.2.9.dev7__py3-none-any.whl → 0.2.9.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.
- examples/__init__.py +16 -0
- examples/crafter_debug_render.py +8 -11
- examples/qwen_coder/README.md +102 -0
- examples/qwen_coder/_shared.py +113 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +61 -0
- examples/qwen_coder/configs/coder_lora_4b.toml +57 -0
- examples/qwen_coder/configs/coder_lora_small.toml +58 -0
- examples/qwen_coder/generate_dataset.py +98 -0
- examples/qwen_coder/infer_ft_smoke.py +64 -0
- examples/qwen_coder/infer_prod_proxy.py +73 -0
- examples/qwen_coder/infer_via_synth.py +87 -0
- examples/qwen_coder/scripts/infer_coder.sh +18 -0
- examples/qwen_coder/scripts/train_coder_30b.sh +21 -0
- examples/qwen_coder/sft_full_17b.py +103 -0
- examples/qwen_coder/sft_lora_30b.py +110 -0
- examples/qwen_coder/subset_jsonl.py +38 -0
- examples/qwen_coder/validate_jsonl.py +59 -0
- examples/rl/run_eval.py +36 -37
- examples/rl/run_rl_and_save.py +5 -5
- examples/rl/task_app/math_single_step.py +65 -43
- examples/rl/task_app/math_task_app.py +3 -3
- examples/sft/README.md +139 -0
- examples/sft/configs/crafter_fft_qwen0p6b.toml +44 -0
- examples/sft/configs/crafter_lora_qwen0p6b.toml +45 -0
- examples/sft/evaluate.py +117 -0
- examples/sft/export_dataset.py +117 -0
- examples/sft/generate_traces.py +162 -0
- examples/swe/__init__.py +12 -0
- examples/swe/task_app/README.md +105 -0
- examples/swe/task_app/__init__.py +2 -0
- examples/swe/task_app/grpo_swe_mini.py +571 -0
- examples/swe/task_app/grpo_swe_mini_task_app.py +136 -0
- examples/swe/task_app/hosted/README.md +173 -0
- examples/swe/task_app/hosted/__init__.py +5 -0
- examples/swe/task_app/hosted/branching.py +143 -0
- examples/swe/task_app/hosted/environment_routes.py +1289 -0
- examples/swe/task_app/hosted/envs/__init__.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/__init__.py +6 -0
- examples/swe/task_app/hosted/envs/crafter/app.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/environment.py +522 -0
- examples/swe/task_app/hosted/envs/crafter/policy.py +478 -0
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +108 -0
- examples/swe/task_app/hosted/envs/crafter/shared.py +305 -0
- examples/swe/task_app/hosted/envs/crafter/tools.py +47 -0
- examples/swe/task_app/hosted/envs/mini_swe/__init__.py +8 -0
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +1164 -0
- examples/swe/task_app/hosted/envs/mini_swe/policy.py +355 -0
- examples/swe/task_app/hosted/envs/mini_swe/shared.py +83 -0
- examples/swe/task_app/hosted/envs/mini_swe/tools.py +96 -0
- examples/swe/task_app/hosted/hosted_app.py +204 -0
- examples/swe/task_app/hosted/inference/__init__.py +5 -0
- examples/swe/task_app/hosted/inference/openai_client.py +618 -0
- examples/swe/task_app/hosted/main.py +100 -0
- examples/swe/task_app/hosted/policy_routes.py +1079 -0
- examples/swe/task_app/hosted/registry.py +195 -0
- examples/swe/task_app/hosted/rollout.py +1869 -0
- examples/swe/task_app/hosted/storage/__init__.py +5 -0
- examples/swe/task_app/hosted/storage/volume.py +211 -0
- examples/swe/task_app/hosted/test_agents.py +161 -0
- examples/swe/task_app/hosted/test_service.py +137 -0
- examples/swe/task_app/hosted/utils.py +62 -0
- examples/vlm/README.md +68 -0
- examples/vlm/configs/crafter_vlm_gpt4o.toml +44 -0
- examples/vlm/crafter_image_only_agent.py +207 -0
- examples/vlm/crafter_openai_vlm_agent.py +277 -0
- examples/vlm/filter_image_rows.py +63 -0
- examples/vlm/run_crafter_vlm_benchmark.py +316 -0
- examples/warming_up_to_rl/analyze_trace_db.py +5 -5
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +11 -1
- examples/warming_up_to_rl/export_trace_sft.py +78 -21
- examples/warming_up_to_rl/groq_test.py +4 -4
- examples/warming_up_to_rl/manage_secrets.py +13 -18
- examples/warming_up_to_rl/run_eval.py +42 -44
- examples/warming_up_to_rl/run_fft_and_save.py +11 -16
- examples/warming_up_to_rl/run_local_rollout.py +1 -3
- examples/warming_up_to_rl/run_local_rollout_modal.py +2 -4
- examples/warming_up_to_rl/run_local_rollout_parallel.py +1 -4
- examples/warming_up_to_rl/run_local_rollout_traced.py +3 -5
- examples/warming_up_to_rl/run_rl_and_save.py +5 -6
- examples/warming_up_to_rl/run_rollout_remote.py +8 -10
- examples/warming_up_to_rl/task_app/README.md +6 -2
- examples/warming_up_to_rl/task_app/grpo_crafter.py +234 -35
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +2 -3
- examples/warming_up_to_rl/task_app/synth_envs_hosted/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/branching.py +9 -11
- examples/warming_up_to_rl/task_app/synth_envs_hosted/environment_routes.py +131 -114
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +101 -41
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +73 -51
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +14 -6
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +16 -16
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +32 -34
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +94 -31
- examples/warming_up_to_rl/task_app/synth_envs_hosted/main.py +0 -2
- examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +303 -203
- examples/warming_up_to_rl/task_app/synth_envs_hosted/registry.py +21 -23
- examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +328 -225
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +13 -13
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_agents.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_service.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +4 -3
- synth/__init__.py +14 -0
- synth_ai/__init__.py +26 -4
- synth_ai/api/models/supported.py +376 -0
- synth_ai/api/train/builders.py +128 -21
- synth_ai/api/train/cli.py +80 -64
- synth_ai/api/train/config_finder.py +7 -2
- synth_ai/api/train/env_resolver.py +1 -1
- synth_ai/api/train/pollers.py +2 -1
- synth_ai/api/train/supported_algos.py +139 -0
- synth_ai/api/train/task_app.py +1 -2
- synth_ai/api/train/utils.py +13 -44
- synth_ai/cli/__init__.py +8 -0
- synth_ai/cli/_modal_wrapper.py +28 -0
- synth_ai/cli/_typer_patch.py +49 -0
- synth_ai/cli/balance.py +1 -2
- synth_ai/cli/calc.py +1 -1
- synth_ai/cli/demo.py +2 -1
- synth_ai/cli/recent.py +2 -2
- synth_ai/cli/rl_demo.py +2 -1
- synth_ai/cli/root.py +11 -13
- synth_ai/cli/status.py +2 -2
- synth_ai/cli/task_apps.py +529 -179
- synth_ai/cli/traces.py +6 -4
- synth_ai/cli/watch.py +12 -18
- synth_ai/demo_registry.py +1 -1
- synth_ai/demos/core/cli.py +36 -43
- synth_ai/demos/demo_task_apps/__init__.py +3 -3
- synth_ai/demos/demo_task_apps/core.py +17 -25
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +3 -4
- synth_ai/demos/demo_task_apps/math/app.py +2 -1
- synth_ai/demos/demo_task_apps/math/deploy_modal.py +3 -4
- synth_ai/demos/demo_task_apps/math/modal_task_app.py +16 -18
- synth_ai/demos/demo_task_apps/math/task_app_entry.py +0 -1
- synth_ai/environments/examples/crafter_classic/environment.py +76 -1
- synth_ai/environments/reproducibility/tree.py +2 -5
- synth_ai/environments/service/app.py +11 -12
- synth_ai/environments/service/core_routes.py +4 -7
- synth_ai/environments/stateful/engine.py +1 -1
- synth_ai/environments/tasks/core.py +1 -0
- synth_ai/environments/tasks/filters.py +5 -6
- synth_ai/environments/tasks/utils.py +4 -5
- synth_ai/handshake.py +9 -9
- synth_ai/http.py +1 -1
- synth_ai/http_client.py +18 -10
- synth_ai/inference/client.py +15 -5
- synth_ai/jobs/client.py +78 -83
- synth_ai/learning/__init__.py +41 -6
- synth_ai/learning/algorithms.py +14 -0
- synth_ai/learning/client.py +91 -24
- synth_ai/learning/config.py +2 -38
- synth_ai/learning/ft_client.py +4 -59
- synth_ai/learning/health.py +5 -6
- synth_ai/learning/jobs.py +31 -47
- synth_ai/{rl → learning/rl}/__init__.py +14 -4
- synth_ai/learning/rl/client.py +267 -0
- synth_ai/learning/rl/config.py +31 -0
- synth_ai/{rl → learning/rl}/contracts.py +5 -8
- synth_ai/{rl → learning/rl}/env_keys.py +39 -15
- synth_ai/learning/rl/secrets.py +13 -0
- synth_ai/learning/rl_client.py +2 -281
- synth_ai/learning/sft/__init__.py +29 -0
- synth_ai/learning/sft/client.py +68 -0
- synth_ai/learning/sft/config.py +270 -0
- synth_ai/learning/sft/data.py +295 -0
- synth_ai/learning/sse.py +25 -24
- synth_ai/learning/validators.py +25 -28
- synth_ai/lm/__init__.py +21 -47
- synth_ai/main.py +6 -0
- synth_ai/task/__init__.py +25 -27
- synth_ai/task/apps/__init__.py +7 -8
- synth_ai/task/auth.py +8 -8
- synth_ai/task/client.py +14 -14
- synth_ai/task/contracts.py +36 -35
- synth_ai/task/datasets.py +6 -5
- synth_ai/task/errors.py +10 -10
- synth_ai/task/health.py +17 -9
- synth_ai/task/json.py +58 -23
- synth_ai/task/proxy.py +13 -9
- synth_ai/task/rubrics.py +16 -15
- synth_ai/task/server.py +12 -12
- synth_ai/task/tracing_utils.py +4 -4
- synth_ai/task/vendors.py +5 -6
- synth_ai/tracing_v3/__init__.py +2 -0
- synth_ai/tracing_v3/abstractions.py +21 -4
- synth_ai/tracing_v3/decorators.py +18 -16
- synth_ai/tracing_v3/hooks.py +5 -5
- synth_ai/tracing_v3/llm_call_record_helpers.py +6 -6
- synth_ai/tracing_v3/session_tracer.py +40 -14
- synth_ai/tracing_v3/storage/base.py +85 -0
- synth_ai/tracing_v3/storage/config.py +21 -8
- synth_ai/tracing_v3/storage/factory.py +10 -7
- synth_ai/tracing_v3/storage/utils.py +4 -2
- synth_ai/tracing_v3/turso/daemon.py +7 -2
- synth_ai/tracing_v3/turso/models.py +2 -2
- synth_ai/tracing_v3/turso/native_manager.py +1173 -0
- synth_ai/tracing_v3/utils.py +4 -4
- synth_ai/v0/api/__init__.py +8 -0
- synth_ai/v0/api/models/__init__.py +8 -0
- synth_ai/v0/api/models/supported.py +8 -0
- synth_ai/v0/config/__init__.py +15 -0
- synth_ai/v0/config/base_url.py +12 -0
- synth_ai/v0/lm/__init__.py +51 -0
- synth_ai/{lm → v0/lm}/caching/ephemeral.py +2 -2
- synth_ai/{lm → v0/lm}/caching/handler.py +4 -4
- synth_ai/{lm → v0/lm}/caching/initialize.py +1 -1
- synth_ai/{lm → v0/lm}/caching/persistent.py +1 -1
- synth_ai/{lm → v0/lm}/config.py +6 -1
- synth_ai/{lm → v0/lm}/core/all.py +9 -9
- synth_ai/{lm → v0/lm}/core/main.py +6 -6
- synth_ai/{lm → v0/lm}/core/main_v3.py +10 -10
- synth_ai/{lm → v0/lm}/core/synth_models.py +2 -14
- synth_ai/{lm → v0/lm}/core/vendor_clients.py +2 -2
- synth_ai/{lm → v0/lm}/overrides.py +2 -2
- synth_ai/{lm → v0/lm}/provider_support/anthropic.py +4 -4
- synth_ai/{lm → v0/lm}/provider_support/openai.py +5 -5
- synth_ai/{lm → v0/lm}/structured_outputs/handler.py +5 -5
- synth_ai/{lm → v0/lm}/structured_outputs/rehabilitate.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/core/anthropic_api.py +9 -9
- synth_ai/{lm → v0/lm}/vendors/core/gemini_api.py +5 -5
- synth_ai/{lm → v0/lm}/vendors/core/mistral_api.py +5 -5
- synth_ai/{lm → v0/lm}/vendors/core/openai_api.py +10 -10
- synth_ai/{lm → v0/lm}/vendors/openai_standard.py +8 -8
- synth_ai/{lm → v0/lm}/vendors/openai_standard_responses.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/custom_endpoint.py +3 -3
- synth_ai/{lm → v0/lm}/vendors/supported/deepseek.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/grok.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/groq.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/supported/ollama.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/supported/openrouter.py +3 -3
- synth_ai/{lm → v0/lm}/vendors/supported/together.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/synth_client.py +1 -1
- synth_ai/v0/tracing_v3/__init__.py +10 -0
- synth_ai/v0/tracing_v3/abstractions.py +3 -0
- synth_ai/v0/tracing_v3/decorators.py +3 -0
- synth_ai/v0/tracing_v3/llm_call_record_helpers.py +3 -0
- synth_ai/v0/tracing_v3/session_tracer.py +3 -0
- synth_ai-0.2.9.dev9.dist-info/METADATA +191 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev9.dist-info}/RECORD +268 -238
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev9.dist-info}/top_level.txt +1 -0
- examples/common_old/backend.py +0 -20
- examples/evals_old/README.md +0 -98
- examples/evals_old/__init__.py +0 -6
- examples/evals_old/compare_models.py +0 -1038
- examples/evals_old/example_log.md +0 -145
- examples/evals_old/run_demo.sh +0 -126
- examples/evals_old/trace_analysis.py +0 -270
- examples/finetuning_old/_backup_synth_qwen/config.toml +0 -29
- examples/finetuning_old/_backup_synth_qwen/example_log.md +0 -324
- examples/finetuning_old/_backup_synth_qwen/filter_traces.py +0 -60
- examples/finetuning_old/_backup_synth_qwen/filter_traces_achievements.py +0 -243
- examples/finetuning_old/_backup_synth_qwen/purge_v3_traces.py +0 -109
- examples/finetuning_old/_backup_synth_qwen/react_agent_lm.py +0 -1924
- examples/finetuning_old/_backup_synth_qwen/readme.md +0 -49
- examples/finetuning_old/_backup_synth_qwen/run_crafter_qwen4b.py +0 -114
- examples/finetuning_old/_backup_synth_qwen/run_demo.sh +0 -195
- examples/finetuning_old/_backup_synth_qwen/sft_kickoff.py +0 -119
- examples/finetuning_old/synth_qwen_v1/README.md +0 -68
- examples/finetuning_old/synth_qwen_v1/filter_traces.py +0 -60
- examples/finetuning_old/synth_qwen_v1/filter_traces_achievements.py +0 -243
- examples/finetuning_old/synth_qwen_v1/finetune.py +0 -46
- examples/finetuning_old/synth_qwen_v1/hello_ft_model.py +0 -71
- examples/finetuning_old/synth_qwen_v1/infer.py +0 -36
- examples/finetuning_old/synth_qwen_v1/poll.py +0 -46
- examples/finetuning_old/synth_qwen_v1/prepare_data.py +0 -35
- examples/finetuning_old/synth_qwen_v1/purge_v3_traces.py +0 -109
- examples/finetuning_old/synth_qwen_v1/react_agent_lm.py +0 -1933
- examples/finetuning_old/synth_qwen_v1/run_crafter_sft_job.py +0 -210
- examples/finetuning_old/synth_qwen_v1/run_ft_job.py +0 -237
- examples/finetuning_old/synth_qwen_v1/upload_data.py +0 -34
- examples/finetuning_old/synth_qwen_v1/util.py +0 -152
- examples/rl_old/task_app.py +0 -1131
- examples/warming_up_to_rl/old/event_rewards.md +0 -234
- examples/warming_up_to_rl/old/notes.md +0 -73
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py +0 -738
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/filter_traces_sft_turso.py +0 -580
- synth_ai/experimental/synth_oss.py +0 -445
- synth_ai/learning/filtering.py +0 -0
- synth_ai/learning/offline/dpo.py +0 -0
- synth_ai/learning/offline/providers.py +0 -7
- synth_ai/learning/offline/sft.py +0 -0
- synth_ai/learning/offline/shared.py +0 -0
- synth_ai/learning/online/grpo.py +0 -0
- synth_ai/learning/online/irft.py +0 -0
- synth_ai/learning/prompts/banking77_injection_eval.py +0 -168
- synth_ai/learning/prompts/gepa.py +0 -0
- synth_ai/learning/prompts/hello_world_in_context_injection_ex.py +0 -211
- synth_ai/learning/prompts/mipro.py +0 -289
- synth_ai/learning/prompts/random_search.py +0 -249
- synth_ai/learning/prompts/run_mipro_banking77.py +0 -172
- synth_ai/learning/prompts/run_random_search_banking77.py +0 -329
- synth_ai/rl/secrets.py +0 -19
- synth_ai/scripts/verify_rewards.py +0 -100
- synth_ai/tracing/__init__.py +0 -30
- synth_ai/tracing_v1/__init__.py +0 -33
- synth_ai/tracing_v3/turso/__init__.py +0 -25
- synth_ai/tracing_v3/turso/manager.py +0 -838
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.9.dev7.dist-info/METADATA +0 -131
- /synth_ai/{lm → v0/lm}/caching/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/caching/constants.py +0 -0
- /synth_ai/{lm → v0/lm}/caching/dbs.py +0 -0
- /synth_ai/{lm → v0/lm}/constants.py +0 -0
- /synth_ai/{lm → v0/lm}/core/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/core/exceptions.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/monitor.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/statefulness.py +0 -0
- /synth_ai/{lm → v0/lm}/injection.py +0 -0
- /synth_ai/{lm → v0/lm}/provider_support/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/provider_support/suppress_logging.py +0 -0
- /synth_ai/{lm → v0/lm}/structured_outputs/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/structured_outputs/inject.py +0 -0
- /synth_ai/{lm → v0/lm}/tools/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/tools/base.py +0 -0
- /synth_ai/{lm → v0/lm}/unified_interface.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/base.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/core/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/core/synth_dev_api.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/local/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/local/ollama.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/retries.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/supported/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/warmup.py +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev9.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev9.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
3
|
+
import contextlib
|
|
5
4
|
import json
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any
|
|
7
|
+
from uuid import uuid4
|
|
6
8
|
|
|
7
9
|
from fastapi import APIRouter, HTTPException
|
|
8
10
|
from pydantic import BaseModel
|
|
9
11
|
|
|
10
|
-
from uuid import uuid4
|
|
11
|
-
|
|
12
12
|
# Import the actual classes from synth-ai
|
|
13
13
|
from synth_ai.environments.examples.crafter_classic.environment import (
|
|
14
14
|
CrafterClassicEnvironment,
|
|
@@ -98,41 +98,41 @@ async def validate_environment_observation(observation: Any, context: str) -> No
|
|
|
98
98
|
|
|
99
99
|
class EnvCreateRequest(BaseModel):
|
|
100
100
|
env_name: str
|
|
101
|
-
config:
|
|
102
|
-
seed:
|
|
103
|
-
parent_env_id:
|
|
101
|
+
config: dict[str, Any] = {}
|
|
102
|
+
seed: int | None = None
|
|
103
|
+
parent_env_id: str | None = None
|
|
104
104
|
rl_run_id: str
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
class EnvCreateResponse(BaseModel):
|
|
108
108
|
env_id: str
|
|
109
|
-
observation:
|
|
110
|
-
info:
|
|
109
|
+
observation: dict[str, Any]
|
|
110
|
+
info: dict[str, Any] | None = None
|
|
111
111
|
step_idx: int
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
class EnvResetRequest(BaseModel):
|
|
115
115
|
env_id: str
|
|
116
|
-
seed:
|
|
116
|
+
seed: int | None = None
|
|
117
117
|
|
|
118
118
|
|
|
119
119
|
class EnvResetResponse(BaseModel):
|
|
120
|
-
observation:
|
|
121
|
-
info:
|
|
120
|
+
observation: dict[str, Any]
|
|
121
|
+
info: dict[str, Any] | None = None
|
|
122
122
|
step_idx: int
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
class EnvStepRequest(BaseModel):
|
|
126
126
|
env_id: str
|
|
127
|
-
tool_calls:
|
|
127
|
+
tool_calls: list[dict[str, Any]]
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
class EnvStepResponse(BaseModel):
|
|
131
|
-
observation:
|
|
131
|
+
observation: dict[str, Any]
|
|
132
132
|
done: bool
|
|
133
|
-
info:
|
|
134
|
-
reward:
|
|
135
|
-
truncated:
|
|
133
|
+
info: dict[str, Any] | None = None
|
|
134
|
+
reward: float | None = None
|
|
135
|
+
truncated: bool | None = None
|
|
136
136
|
step_idx: int
|
|
137
137
|
|
|
138
138
|
|
|
@@ -153,8 +153,8 @@ class EnvRestoreRequest(BaseModel):
|
|
|
153
153
|
|
|
154
154
|
class EnvRestoreResponse(BaseModel):
|
|
155
155
|
env_id: str
|
|
156
|
-
observation:
|
|
157
|
-
info:
|
|
156
|
+
observation: dict[str, Any]
|
|
157
|
+
info: dict[str, Any] | None = None
|
|
158
158
|
step_idx: int
|
|
159
159
|
|
|
160
160
|
|
|
@@ -213,7 +213,8 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
213
213
|
# Log a world signature for sanity: seed + starting public state hash
|
|
214
214
|
try:
|
|
215
215
|
pub_state = base_env.engine._get_public_state_from_env() # type: ignore[attr-defined]
|
|
216
|
-
import hashlib
|
|
216
|
+
import hashlib
|
|
217
|
+
import json as _json
|
|
217
218
|
|
|
218
219
|
sig_src = {
|
|
219
220
|
"player_position": list(pub_state.player_position),
|
|
@@ -268,23 +269,27 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
268
269
|
elif env_name_lower == "wordle":
|
|
269
270
|
# Defer imports to avoid hard dependency when not used
|
|
270
271
|
try:
|
|
272
|
+
from synth_ai.environments.examples.wordle.environment import (
|
|
273
|
+
WordleEnvironment,
|
|
274
|
+
)
|
|
271
275
|
from synth_ai.environments.examples.wordle.taskset import (
|
|
272
276
|
WordleTaskInstance,
|
|
273
277
|
WordleTaskInstanceMetadata,
|
|
274
278
|
)
|
|
275
|
-
from synth_ai.environments.examples.wordle.environment import (
|
|
276
|
-
WordleEnvironment,
|
|
277
|
-
)
|
|
278
279
|
except Exception as e:
|
|
279
|
-
raise HTTPException(
|
|
280
|
+
raise HTTPException(
|
|
281
|
+
status_code=500, detail=f"Wordle modules unavailable: {e}"
|
|
282
|
+
) from e
|
|
280
283
|
|
|
281
284
|
# Lazy import of wrapper within branch
|
|
282
285
|
try:
|
|
283
|
-
from .envs.wordle.environment import
|
|
284
|
-
WordleEnvironmentWrapper as _WordleWrapper,
|
|
285
|
-
)
|
|
286
|
+
from .envs.wordle.environment import WordleEnvironmentWrapper
|
|
286
287
|
except Exception as e:
|
|
287
|
-
raise HTTPException(
|
|
288
|
+
raise HTTPException(
|
|
289
|
+
status_code=500, detail=f"Wordle wrapper unavailable: {e}"
|
|
290
|
+
) from e
|
|
291
|
+
else:
|
|
292
|
+
wordle_wrapper_cls = WordleEnvironmentWrapper
|
|
288
293
|
|
|
289
294
|
cfg = request.config or {}
|
|
290
295
|
word_length = int(cfg.get("word_length", 5))
|
|
@@ -312,7 +317,7 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
312
317
|
# Try to preserve the exact puzzle snapshot for reproducibility
|
|
313
318
|
init_snap = getattr(instance, "initial_engine_snapshot", None)
|
|
314
319
|
|
|
315
|
-
wrapper =
|
|
320
|
+
wrapper = wordle_wrapper_cls(
|
|
316
321
|
env=base_env,
|
|
317
322
|
seed=request.seed,
|
|
318
323
|
word_length=word_length,
|
|
@@ -356,23 +361,25 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
356
361
|
|
|
357
362
|
elif env_name_lower == "sokoban":
|
|
358
363
|
try:
|
|
364
|
+
from synth_ai.environments.examples.sokoban.environment import (
|
|
365
|
+
SokobanEnvironment,
|
|
366
|
+
)
|
|
359
367
|
from synth_ai.environments.examples.sokoban.taskset import (
|
|
360
368
|
SokobanTaskInstance,
|
|
361
369
|
SokobanTaskInstanceMetadata,
|
|
362
370
|
)
|
|
363
|
-
from synth_ai.environments.examples.sokoban.environment import (
|
|
364
|
-
SokobanEnvironment,
|
|
365
|
-
)
|
|
366
371
|
except Exception as e:
|
|
367
|
-
raise HTTPException(
|
|
372
|
+
raise HTTPException(
|
|
373
|
+
status_code=500, detail=f"Sokoban modules unavailable: {e}"
|
|
374
|
+
) from e
|
|
368
375
|
|
|
369
376
|
# Lazy import of wrapper within branch
|
|
370
377
|
try:
|
|
371
|
-
from .envs.sokoban.environment import
|
|
372
|
-
SokobanEnvironmentWrapper as _SokobanWrapper,
|
|
373
|
-
)
|
|
378
|
+
from .envs.sokoban.environment import SokobanEnvironmentWrapper
|
|
374
379
|
except Exception as e:
|
|
375
|
-
raise HTTPException(
|
|
380
|
+
raise HTTPException(
|
|
381
|
+
status_code=500, detail=f"Sokoban wrapper unavailable: {e}"
|
|
382
|
+
) from e
|
|
376
383
|
|
|
377
384
|
cfg = request.config or {}
|
|
378
385
|
difficulty = cfg.get("difficulty", "easy")
|
|
@@ -395,7 +402,7 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
395
402
|
)
|
|
396
403
|
base_env = SokobanEnvironment(task_instance=instance)
|
|
397
404
|
|
|
398
|
-
wrapper =
|
|
405
|
+
wrapper = SokobanEnvironmentWrapper(env=base_env, seed=request.seed, config=cfg)
|
|
399
406
|
result = await wrapper.initialize()
|
|
400
407
|
|
|
401
408
|
# Handle the observation structure consistently for Sokoban
|
|
@@ -431,13 +438,11 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
431
438
|
cfg = request.config or {}
|
|
432
439
|
# Lazy import of wrapper within branch
|
|
433
440
|
try:
|
|
434
|
-
from .envs.math.environment import
|
|
435
|
-
MathEnvironmentWrapper as _MathWrapper,
|
|
436
|
-
)
|
|
441
|
+
from .envs.math.environment import MathEnvironmentWrapper
|
|
437
442
|
except Exception as e:
|
|
438
|
-
raise HTTPException(status_code=500, detail=f"Math wrapper unavailable: {e}")
|
|
443
|
+
raise HTTPException(status_code=500, detail=f"Math wrapper unavailable: {e}") from e
|
|
439
444
|
|
|
440
|
-
wrapper =
|
|
445
|
+
wrapper = MathEnvironmentWrapper(
|
|
441
446
|
seed=request.seed,
|
|
442
447
|
problem_id=cfg.get("problem_id"),
|
|
443
448
|
problem_text=cfg.get("problem_text"),
|
|
@@ -477,7 +482,7 @@ async def create_environment(request: EnvCreateRequest) -> EnvCreateResponse:
|
|
|
477
482
|
|
|
478
483
|
except Exception as e:
|
|
479
484
|
logger.error(f"Failed to create environment: {e}")
|
|
480
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
485
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
481
486
|
|
|
482
487
|
|
|
483
488
|
# --- Compatibility routes for existing eval scripts that expect CrafterClassic paths ---
|
|
@@ -572,27 +577,28 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
572
577
|
|
|
573
578
|
elif True:
|
|
574
579
|
# Try to dynamically import Wordle wrapper and check instance safely
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
)
|
|
579
|
-
except Exception:
|
|
580
|
-
_WordleWrapper = None # type: ignore
|
|
580
|
+
wordle_wrapper_cls = None
|
|
581
|
+
with contextlib.suppress(Exception):
|
|
582
|
+
from .envs.wordle.environment import WordleEnvironmentWrapper
|
|
581
583
|
|
|
582
|
-
|
|
584
|
+
wordle_wrapper_cls = WordleEnvironmentWrapper # type: ignore[assignment]
|
|
585
|
+
|
|
586
|
+
if wordle_wrapper_cls is not None and isinstance(wrapper, wordle_wrapper_cls):
|
|
583
587
|
# Rebuild Wordle env with the same configuration; if we have a preserved
|
|
584
588
|
# initial_engine_snapshot, prefer constructing the instance directly.
|
|
585
589
|
try:
|
|
590
|
+
from synth_ai.environments.examples.wordle.environment import (
|
|
591
|
+
WordleEnvironment,
|
|
592
|
+
)
|
|
586
593
|
from synth_ai.environments.examples.wordle.taskset import (
|
|
587
|
-
create_wordle_taskset,
|
|
588
594
|
WordleTaskInstance,
|
|
589
595
|
WordleTaskInstanceMetadata,
|
|
590
|
-
|
|
591
|
-
from synth_ai.environments.examples.wordle.environment import (
|
|
592
|
-
WordleEnvironment,
|
|
596
|
+
create_wordle_taskset,
|
|
593
597
|
)
|
|
594
598
|
except Exception as e:
|
|
595
|
-
raise HTTPException(
|
|
599
|
+
raise HTTPException(
|
|
600
|
+
status_code=500, detail=f"Wordle modules unavailable: {e}"
|
|
601
|
+
) from e
|
|
596
602
|
|
|
597
603
|
init_snap = getattr(wrapper, "initial_engine_snapshot", None)
|
|
598
604
|
if init_snap is not None:
|
|
@@ -630,16 +636,18 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
630
636
|
# Rebuild Wordle env with the same configuration; if we have a preserved
|
|
631
637
|
# initial_engine_snapshot, prefer constructing the instance directly.
|
|
632
638
|
try:
|
|
639
|
+
from synth_ai.environments.examples.wordle.environment import (
|
|
640
|
+
WordleEnvironment,
|
|
641
|
+
)
|
|
633
642
|
from synth_ai.environments.examples.wordle.taskset import (
|
|
634
|
-
create_wordle_taskset,
|
|
635
643
|
WordleTaskInstance,
|
|
636
644
|
WordleTaskInstanceMetadata,
|
|
637
|
-
|
|
638
|
-
from synth_ai.environments.examples.wordle.environment import (
|
|
639
|
-
WordleEnvironment,
|
|
645
|
+
create_wordle_taskset,
|
|
640
646
|
)
|
|
641
647
|
except Exception as e:
|
|
642
|
-
raise HTTPException(
|
|
648
|
+
raise HTTPException(
|
|
649
|
+
status_code=500, detail=f"Wordle modules unavailable: {e}"
|
|
650
|
+
) from e
|
|
643
651
|
|
|
644
652
|
init_snap = getattr(wrapper, "initial_engine_snapshot", None)
|
|
645
653
|
if init_snap is not None:
|
|
@@ -675,25 +683,26 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
675
683
|
|
|
676
684
|
elif True:
|
|
677
685
|
# Try to dynamically import Sokoban wrapper and check instance safely
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
)
|
|
682
|
-
except Exception:
|
|
683
|
-
_SokobanWrapper = None # type: ignore
|
|
686
|
+
sokoban_wrapper_cls = None
|
|
687
|
+
with contextlib.suppress(Exception):
|
|
688
|
+
from .envs.sokoban.environment import SokobanEnvironmentWrapper
|
|
684
689
|
|
|
685
|
-
|
|
690
|
+
sokoban_wrapper_cls = SokobanEnvironmentWrapper # type: ignore[assignment]
|
|
691
|
+
|
|
692
|
+
if sokoban_wrapper_cls is not None and isinstance(wrapper, sokoban_wrapper_cls):
|
|
686
693
|
# Rebuild Sokoban env using stored config snapshot
|
|
687
694
|
try:
|
|
695
|
+
from synth_ai.environments.examples.sokoban.environment import (
|
|
696
|
+
SokobanEnvironment,
|
|
697
|
+
)
|
|
688
698
|
from synth_ai.environments.examples.sokoban.taskset import (
|
|
689
699
|
SokobanTaskInstance,
|
|
690
700
|
SokobanTaskInstanceMetadata,
|
|
691
701
|
)
|
|
692
|
-
from synth_ai.environments.examples.sokoban.environment import (
|
|
693
|
-
SokobanEnvironment,
|
|
694
|
-
)
|
|
695
702
|
except Exception as e:
|
|
696
|
-
raise HTTPException(
|
|
703
|
+
raise HTTPException(
|
|
704
|
+
status_code=500, detail=f"Sokoban modules unavailable: {e}"
|
|
705
|
+
) from e
|
|
697
706
|
|
|
698
707
|
cfg = dict(wrapper.config or {})
|
|
699
708
|
metadata = SokobanTaskInstanceMetadata(
|
|
@@ -718,15 +727,17 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
718
727
|
pass
|
|
719
728
|
# Rebuild Sokoban env using stored config snapshot
|
|
720
729
|
try:
|
|
730
|
+
from synth_ai.environments.examples.sokoban.environment import (
|
|
731
|
+
SokobanEnvironment,
|
|
732
|
+
)
|
|
721
733
|
from synth_ai.environments.examples.sokoban.taskset import (
|
|
722
734
|
SokobanTaskInstance,
|
|
723
735
|
SokobanTaskInstanceMetadata,
|
|
724
736
|
)
|
|
725
|
-
from synth_ai.environments.examples.sokoban.environment import (
|
|
726
|
-
SokobanEnvironment,
|
|
727
|
-
)
|
|
728
737
|
except Exception as e:
|
|
729
|
-
raise HTTPException(
|
|
738
|
+
raise HTTPException(
|
|
739
|
+
status_code=500, detail=f"Sokoban modules unavailable: {e}"
|
|
740
|
+
) from e
|
|
730
741
|
|
|
731
742
|
cfg = dict(wrapper.config or {})
|
|
732
743
|
metadata = SokobanTaskInstanceMetadata(
|
|
@@ -753,7 +764,8 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
753
764
|
try:
|
|
754
765
|
base_env = handle.env.env # type: ignore[attr-defined]
|
|
755
766
|
pub_state = base_env.engine._get_public_state_from_env() # type: ignore[attr-defined]
|
|
756
|
-
import hashlib
|
|
767
|
+
import hashlib
|
|
768
|
+
import json as _json
|
|
757
769
|
|
|
758
770
|
sig_src = {
|
|
759
771
|
"player_position": list(pub_state.player_position),
|
|
@@ -786,7 +798,7 @@ async def reset_environment(request: EnvResetRequest) -> EnvResetResponse:
|
|
|
786
798
|
|
|
787
799
|
except Exception as e:
|
|
788
800
|
logger.error(f"Failed to reset environment {request.env_id}: {e}")
|
|
789
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
801
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
790
802
|
|
|
791
803
|
|
|
792
804
|
@router.post("/step", response_model=EnvStepResponse)
|
|
@@ -799,16 +811,15 @@ async def step_environment(request: EnvStepRequest) -> EnvStepResponse:
|
|
|
799
811
|
try:
|
|
800
812
|
# Execute the step, pre-normalizing invalid Wordle guesses to avoid hard failures
|
|
801
813
|
wrapper = handle.env
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
)
|
|
806
|
-
except Exception:
|
|
807
|
-
_WordleWrapper = None # type: ignore
|
|
814
|
+
wordle_wrapper_cls = None
|
|
815
|
+
with contextlib.suppress(Exception):
|
|
816
|
+
from .envs.wordle.environment import WordleEnvironmentWrapper
|
|
808
817
|
|
|
809
|
-
|
|
818
|
+
wordle_wrapper_cls = WordleEnvironmentWrapper # type: ignore[assignment]
|
|
819
|
+
|
|
820
|
+
if wordle_wrapper_cls is not None and isinstance(wrapper, wordle_wrapper_cls):
|
|
810
821
|
expected_len = int(getattr(wrapper, "word_length", 5))
|
|
811
|
-
normalized:
|
|
822
|
+
normalized: list[dict[str, Any]] = []
|
|
812
823
|
for tc in request.tool_calls or []:
|
|
813
824
|
tool = tc.get("tool") or tc.get("tool_name") or tc.get("name") or "interact"
|
|
814
825
|
args = tc.get("arguments") or tc.get("args") or {}
|
|
@@ -880,14 +891,16 @@ async def step_environment(request: EnvStepRequest) -> EnvStepResponse:
|
|
|
880
891
|
logger.error(f"Failed to step environment {request.env_id}: {e}")
|
|
881
892
|
# Fallback for Wordle: convert invalid guesses into 'invalid_guess' tool calls and retry once
|
|
882
893
|
try:
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
894
|
+
wordle_wrapper_cls = None
|
|
895
|
+
with contextlib.suppress(Exception):
|
|
896
|
+
from .envs.wordle.environment import WordleEnvironmentWrapper
|
|
897
|
+
|
|
898
|
+
wordle_wrapper_cls = WordleEnvironmentWrapper # type: ignore[assignment]
|
|
886
899
|
|
|
887
900
|
wrapper = handle.env
|
|
888
|
-
if isinstance(wrapper,
|
|
901
|
+
if wordle_wrapper_cls is not None and isinstance(wrapper, wordle_wrapper_cls):
|
|
889
902
|
expected_len = int(getattr(wrapper, "word_length", 5))
|
|
890
|
-
normalized:
|
|
903
|
+
normalized: list[dict[str, Any]] = []
|
|
891
904
|
for tc in request.tool_calls or []:
|
|
892
905
|
tool = tc.get("tool") or tc.get("tool_name") or tc.get("name") or "interact"
|
|
893
906
|
args = tc.get("arguments") or tc.get("args") or {}
|
|
@@ -941,7 +954,7 @@ async def step_environment(request: EnvStepRequest) -> EnvStepResponse:
|
|
|
941
954
|
# Ignore fallback errors; fall through to generic error
|
|
942
955
|
pass
|
|
943
956
|
|
|
944
|
-
raise HTTPException(status_code=500, detail=f"{type(e).__name__}: {e}")
|
|
957
|
+
raise HTTPException(status_code=500, detail=f"{type(e).__name__}: {e}") from e
|
|
945
958
|
|
|
946
959
|
|
|
947
960
|
@router.post("/snapshot", response_model=EnvSnapshotResponse)
|
|
@@ -980,7 +993,7 @@ async def snapshot_environment(request: EnvSnapshotRequest) -> EnvSnapshotRespon
|
|
|
980
993
|
|
|
981
994
|
except Exception as e:
|
|
982
995
|
logger.error(f"Failed to snapshot environment {request.env_id}: {e}")
|
|
983
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
996
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
984
997
|
|
|
985
998
|
|
|
986
999
|
@router.post("/restore", response_model=EnvRestoreResponse)
|
|
@@ -1060,16 +1073,18 @@ async def restore_environment(request: EnvRestoreRequest) -> EnvRestoreResponse:
|
|
|
1060
1073
|
)
|
|
1061
1074
|
elif name_lower == "wordle":
|
|
1062
1075
|
try:
|
|
1076
|
+
from synth_ai.environments.examples.wordle.environment import (
|
|
1077
|
+
WordleEnvironment,
|
|
1078
|
+
)
|
|
1063
1079
|
from synth_ai.environments.examples.wordle.taskset import (
|
|
1064
|
-
create_wordle_taskset,
|
|
1065
1080
|
WordleTaskInstance,
|
|
1066
1081
|
WordleTaskInstanceMetadata,
|
|
1067
|
-
|
|
1068
|
-
from synth_ai.environments.examples.wordle.environment import (
|
|
1069
|
-
WordleEnvironment,
|
|
1082
|
+
create_wordle_taskset,
|
|
1070
1083
|
)
|
|
1071
1084
|
except Exception as e:
|
|
1072
|
-
raise HTTPException(
|
|
1085
|
+
raise HTTPException(
|
|
1086
|
+
status_code=500, detail=f"Wordle modules unavailable: {e}"
|
|
1087
|
+
) from e
|
|
1073
1088
|
|
|
1074
1089
|
cfg = state_dict.get("config", {}) or {}
|
|
1075
1090
|
word_length = int(cfg.get("word_length", 5))
|
|
@@ -1100,12 +1115,12 @@ async def restore_environment(request: EnvRestoreRequest) -> EnvRestoreResponse:
|
|
|
1100
1115
|
base_env = WordleEnvironment(task_instance=instance)
|
|
1101
1116
|
# Lazy import of wrapper only when needed
|
|
1102
1117
|
try:
|
|
1103
|
-
from .envs.wordle.environment import
|
|
1104
|
-
WordleEnvironmentWrapper as _WordleWrapper,
|
|
1105
|
-
)
|
|
1118
|
+
from .envs.wordle.environment import WordleEnvironmentWrapper
|
|
1106
1119
|
except Exception as e:
|
|
1107
|
-
raise HTTPException(
|
|
1108
|
-
|
|
1120
|
+
raise HTTPException(
|
|
1121
|
+
status_code=500, detail=f"Wordle wrapper unavailable: {e}"
|
|
1122
|
+
) from e
|
|
1123
|
+
wrapper = await WordleEnvironmentWrapper.deserialize(payload=state_dict, env=base_env)
|
|
1109
1124
|
|
|
1110
1125
|
env_id = registry.register_env(
|
|
1111
1126
|
env=wrapper,
|
|
@@ -1126,15 +1141,17 @@ async def restore_environment(request: EnvRestoreRequest) -> EnvRestoreResponse:
|
|
|
1126
1141
|
|
|
1127
1142
|
elif name_lower == "sokoban":
|
|
1128
1143
|
try:
|
|
1144
|
+
from synth_ai.environments.examples.sokoban.environment import (
|
|
1145
|
+
SokobanEnvironment,
|
|
1146
|
+
)
|
|
1129
1147
|
from synth_ai.environments.examples.sokoban.taskset import (
|
|
1130
1148
|
SokobanTaskInstance,
|
|
1131
1149
|
SokobanTaskInstanceMetadata,
|
|
1132
1150
|
)
|
|
1133
|
-
from synth_ai.environments.examples.sokoban.environment import (
|
|
1134
|
-
SokobanEnvironment,
|
|
1135
|
-
)
|
|
1136
1151
|
except Exception as e:
|
|
1137
|
-
raise HTTPException(
|
|
1152
|
+
raise HTTPException(
|
|
1153
|
+
status_code=500, detail=f"Sokoban modules unavailable: {e}"
|
|
1154
|
+
) from e
|
|
1138
1155
|
|
|
1139
1156
|
cfg = state_dict.get("config", {}) or {}
|
|
1140
1157
|
metadata = SokobanTaskInstanceMetadata(difficulty=cfg.get("difficulty", "easy"))
|
|
@@ -1153,12 +1170,12 @@ async def restore_environment(request: EnvRestoreRequest) -> EnvRestoreResponse:
|
|
|
1153
1170
|
base_env = SokobanEnvironment(task_instance=instance)
|
|
1154
1171
|
# Lazy import of wrapper only when needed
|
|
1155
1172
|
try:
|
|
1156
|
-
from .envs.sokoban.environment import
|
|
1157
|
-
SokobanEnvironmentWrapper as _SokobanWrapper,
|
|
1158
|
-
)
|
|
1173
|
+
from .envs.sokoban.environment import SokobanEnvironmentWrapper
|
|
1159
1174
|
except Exception as e:
|
|
1160
|
-
raise HTTPException(
|
|
1161
|
-
|
|
1175
|
+
raise HTTPException(
|
|
1176
|
+
status_code=500, detail=f"Sokoban wrapper unavailable: {e}"
|
|
1177
|
+
) from e
|
|
1178
|
+
wrapper = await SokobanEnvironmentWrapper.deserialize(payload=state_dict, env=base_env)
|
|
1162
1179
|
|
|
1163
1180
|
env_id = registry.register_env(
|
|
1164
1181
|
env=wrapper,
|
|
@@ -1185,7 +1202,7 @@ async def restore_environment(request: EnvRestoreRequest) -> EnvRestoreResponse:
|
|
|
1185
1202
|
|
|
1186
1203
|
except Exception as e:
|
|
1187
1204
|
logger.error(f"Failed to restore environment from snapshot {request.snapshot_id}: {e}")
|
|
1188
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
1205
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
1189
1206
|
|
|
1190
1207
|
|
|
1191
1208
|
@router.post("/terminate", response_model=EnvTerminateResponse)
|
|
@@ -1206,4 +1223,4 @@ async def terminate_environment(request: EnvTerminateRequest) -> EnvTerminateRes
|
|
|
1206
1223
|
|
|
1207
1224
|
except Exception as e:
|
|
1208
1225
|
logger.error(f"Failed to terminate environment {request.env_id}: {e}")
|
|
1209
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
1226
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|