synth-ai 0.2.9.dev0__py3-none-any.whl → 0.2.23.dev3__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.
- examples/README.md +1 -0
- examples/__init__.py +16 -0
- examples/analyze_semantic_words.sh +17 -0
- examples/baseline/banking77_baseline.py +243 -0
- examples/baseline/banking77_pipeline_baseline.py +294 -0
- examples/baseline/crafter_baseline.py +407 -0
- examples/baseline/pokemon_red_baseline.py +326 -0
- examples/baseline/simple_baseline.py +56 -0
- examples/baseline/warming_up_to_rl_baseline.py +239 -0
- examples/blog_posts/gepa/README.md +355 -0
- examples/blog_posts/gepa/configs/banking77_gepa_local.toml +95 -0
- examples/blog_posts/gepa/configs/banking77_gepa_test.toml +80 -0
- examples/blog_posts/gepa/configs/banking77_mipro_local.toml +50 -0
- examples/blog_posts/gepa/configs/banking77_pipeline_gepa_local.toml +101 -0
- examples/blog_posts/gepa/configs/banking77_pipeline_gepa_test.toml +96 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/hotpotqa_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/hover_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/hover_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/hover_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/ifbench_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/pupa_gepa_local.toml +58 -0
- examples/blog_posts/gepa/configs/pupa_mipro_local.toml +52 -0
- examples/blog_posts/gepa/deploy_banking77_task_app.sh +54 -0
- examples/blog_posts/gepa/gepa_baseline.py +204 -0
- examples/blog_posts/gepa/query_prompts_example.py +97 -0
- examples/blog_posts/gepa/run_gepa_banking77.sh +112 -0
- examples/blog_posts/gepa/run_gepa_banking77_pipeline.sh +163 -0
- examples/blog_posts/gepa/task_apps.py +105 -0
- examples/blog_posts/gepa/test_gepa_local.sh +67 -0
- examples/blog_posts/gepa/verify_banking77_setup.sh +123 -0
- examples/blog_posts/mipro/README.md +415 -0
- examples/blog_posts/mipro/configs/banking77_mipro_local.toml +91 -0
- examples/blog_posts/mipro/configs/banking77_mipro_test.toml +87 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_gemini_flash_lite_local.toml +98 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_gpt41mini_local.toml +96 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_local.toml +94 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_test.toml +170 -0
- examples/blog_posts/mipro/deploy_banking77_pipeline_task_app.sh +59 -0
- examples/blog_posts/mipro/deploy_banking77_task_app.sh +41 -0
- examples/blog_posts/mipro/multi_step.md +79 -0
- examples/blog_posts/mipro/run_mipro_banking77.sh +191 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline.sh +171 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline_gemini_flash_lite.sh +177 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline_gpt41mini.sh +173 -0
- examples/blog_posts/mipro/verify_banking77_setup.sh +117 -0
- examples/blog_posts/pokemon_vl/README.md +98 -0
- examples/blog_posts/pokemon_vl/configs/eval_gpt5nano.toml +26 -0
- examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +27 -0
- examples/blog_posts/pokemon_vl/configs/eval_rl_final.toml +24 -0
- examples/blog_posts/pokemon_vl/configs/filter_high_reward.toml +10 -0
- examples/blog_posts/pokemon_vl/configs/train_rl_from_sft.toml +43 -0
- examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
- examples/blog_posts/pokemon_vl/extract_images.py +239 -0
- examples/blog_posts/pokemon_vl/pokemon_vl_baseline.py +326 -0
- examples/blog_posts/pokemon_vl/run_eval_extract_images.py +209 -0
- examples/blog_posts/pokemon_vl/run_qwen_eval_extract_images.py +212 -0
- examples/blog_posts/pokemon_vl/text_box_analysis.md +106 -0
- examples/blog_posts/warming_up_to_rl/ARCHITECTURE.md +195 -0
- examples/blog_posts/warming_up_to_rl/FINAL_TEST_RESULTS.md +127 -0
- examples/blog_posts/warming_up_to_rl/INFERENCE_SUCCESS.md +132 -0
- examples/blog_posts/warming_up_to_rl/README.md +158 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TESTING.md +164 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TEST_COMPLETE.md +253 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_baseline_qwen32b_10x20.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b_10x20.toml +26 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_groq_qwen32b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_openai_gpt_oss_120b.toml +29 -0
- examples/blog_posts/warming_up_to_rl/configs/filter_high_reward_dataset.toml +10 -0
- examples/blog_posts/warming_up_to_rl/configs/smoke_test.toml +75 -0
- examples/blog_posts/warming_up_to_rl/configs/train_rl_from_sft.toml +91 -0
- examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
- examples/blog_posts/warming_up_to_rl/warming_up_to_rl_baseline.py +187 -0
- examples/crafter_debug_render.py +186 -0
- examples/dev/qwen3_32b_qlora_4xh100.toml +45 -0
- examples/gepa/banking77_pipeline_gepa.toml +96 -0
- examples/gepa/multi_stage_gepa_example.toml +84 -0
- examples/gepa/run_gepa_banking77_pipeline.sh +157 -0
- examples/multi_step/SFT_README.md +147 -0
- examples/multi_step/configs/README_verilog_rl.md +77 -0
- examples/multi_step/configs/VERILOG_REWARDS.md +103 -0
- examples/multi_step/configs/VERILOG_RL_CHECKLIST.md +196 -0
- examples/multi_step/configs/crafter_eval_synth_qwen4b.toml +35 -0
- examples/multi_step/configs/crafter_eval_text_only_groq_qwen32b.toml +36 -0
- examples/multi_step/configs/crafter_rl_outcome.toml +75 -0
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +145 -0
- examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +84 -0
- examples/multi_step/configs/crafter_rl_stepwise_simple.toml +79 -0
- examples/multi_step/configs/crafter_rl_stepwise_simple_NEW_FORMAT.toml +105 -0
- examples/multi_step/configs/crafter_sft_qwen30b_lora.toml +62 -0
- examples/multi_step/configs/crafter_synth_backend.md +40 -0
- examples/multi_step/configs/verilog_eval_groq_qwen32b.toml +31 -0
- examples/multi_step/configs/verilog_eval_synth_qwen8b.toml +33 -0
- examples/multi_step/configs/verilog_rl_lora.toml +147 -0
- examples/multi_step/convert_traces_to_sft.py +84 -0
- examples/multi_step/crafter_rl_lora.md +70 -0
- examples/multi_step/judges/crafter_backend_judge.py +220 -0
- examples/multi_step/judges/verilog_backend_judge.py +234 -0
- examples/multi_step/readme.md +48 -0
- examples/multi_step/run_sft_qwen30b.sh +45 -0
- examples/multi_step/sse_metrics_streaming_notes.md +357 -0
- examples/multi_step/task_app_config_notes.md +494 -0
- examples/multi_step/verilog_rl_lora.md +218 -0
- examples/qwen_coder/README.md +102 -0
- examples/qwen_coder/_shared.py +113 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +60 -0
- examples/qwen_coder/configs/coder_lora_4b.toml +61 -0
- examples/qwen_coder/configs/coder_lora_small.toml +57 -0
- examples/qwen_coder/generate_dataset.py +98 -0
- examples/qwen_coder/infer_ft_smoke.py +65 -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 +19 -0
- examples/qwen_coder/scripts/train_coder_30b.sh +22 -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 +39 -0
- examples/qwen_coder/todos.md +38 -0
- examples/qwen_coder/validate_jsonl.py +60 -0
- examples/qwen_vl/BUGS_AND_FIXES.md +232 -0
- examples/qwen_vl/IMAGE_VALIDATION_COMPLETE.md +271 -0
- examples/qwen_vl/IMAGE_VALIDATION_SUMMARY.md +260 -0
- examples/qwen_vl/INFERENCE_SFT_TESTS.md +412 -0
- examples/qwen_vl/NEXT_STEPS_2B.md +325 -0
- examples/qwen_vl/QUICKSTART.md +327 -0
- examples/qwen_vl/QUICKSTART_RL_VISION.md +110 -0
- examples/qwen_vl/README.md +152 -0
- examples/qwen_vl/RL_VISION_COMPLETE.md +475 -0
- examples/qwen_vl/RL_VISION_TESTING.md +333 -0
- examples/qwen_vl/SDK_VISION_INTEGRATION.md +328 -0
- examples/qwen_vl/SETUP_COMPLETE.md +274 -0
- examples/qwen_vl/VISION_TESTS_COMPLETE.md +489 -0
- examples/qwen_vl/VLM_PIPELINE_COMPLETE.md +242 -0
- examples/qwen_vl/__init__.py +2 -0
- examples/qwen_vl/collect_data_via_cli.md +415 -0
- examples/qwen_vl/collect_vision_traces.py +368 -0
- examples/qwen_vl/configs/crafter_rl_vision_qwen3vl4b.toml +110 -0
- examples/qwen_vl/configs/crafter_vlm_sft_example.toml +59 -0
- examples/qwen_vl/configs/eval_gpt4o_mini_vision.toml +26 -0
- examples/qwen_vl/configs/eval_gpt4o_vision_proper.toml +29 -0
- examples/qwen_vl/configs/eval_gpt5nano_vision.toml +26 -0
- examples/qwen_vl/configs/eval_qwen3vl_vision.toml +26 -0
- examples/qwen_vl/configs/filter_qwen3vl_sft.toml +49 -0
- examples/qwen_vl/configs/filter_vision_sft.toml +52 -0
- examples/qwen_vl/configs/filter_vision_test.toml +8 -0
- examples/qwen_vl/configs/sft_qwen3_vl_2b_test.toml +54 -0
- examples/qwen_vl/crafter_gpt5nano_agent.py +308 -0
- examples/qwen_vl/crafter_qwen_vl_agent.py +300 -0
- examples/qwen_vl/run_vision_comparison.sh +61 -0
- examples/qwen_vl/run_vision_sft_pipeline.sh +175 -0
- examples/qwen_vl/test_image_validation.py +201 -0
- examples/qwen_vl/test_sft_vision_data.py +110 -0
- examples/rl/README.md +169 -0
- examples/rl/configs/eval_base_qwen.toml +17 -0
- examples/rl/configs/eval_rl_qwen.toml +13 -0
- examples/rl/configs/rl_from_base_qwen.toml +62 -0
- examples/rl/configs/rl_from_base_qwen17.toml +80 -0
- examples/rl/configs/rl_from_ft_qwen.toml +37 -0
- examples/rl/download_dataset.py +80 -0
- examples/rl/run_eval.py +436 -0
- examples/rl/run_rl_and_save.py +111 -0
- examples/rl/task_app/README.md +21 -0
- {synth_ai/task/apps → examples/rl/task_app}/math_single_step.py +188 -50
- examples/rl/task_app/math_task_app.py +111 -0
- examples/run_crafter_demo.sh +10 -0
- examples/sdk_prompt_learning_example.py +55 -0
- examples/sft/README.md +139 -0
- examples/sft/configs/crafter_fft_qwen0p6b.toml +49 -0
- examples/sft/configs/crafter_lora_qwen0p6b.toml +49 -0
- examples/sft/evaluate.py +117 -0
- examples/sft/export_dataset.py +120 -0
- examples/sft/generate_traces.py +164 -0
- examples/swe/__init__.py +12 -0
- examples/swe/task_app/README.md +135 -0
- examples/swe/task_app/__init__.py +2 -0
- examples/swe/task_app/grpo_swe_mini.py +604 -0
- examples/swe/task_app/grpo_swe_mini_task_app.py +124 -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 +1191 -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 +584 -0
- examples/swe/task_app/hosted/main.py +100 -0
- examples/swe/task_app/hosted/policy_routes.py +1094 -0
- examples/swe/task_app/hosted/registry.py +195 -0
- examples/swe/task_app/hosted/rollout.py +1905 -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 +136 -0
- examples/swe/task_app/hosted/utils.py +62 -0
- examples/swe/task_app/morph_backend.py +178 -0
- examples/task_apps/IMAGE_ONLY_EVAL_QUICKSTART.md +258 -0
- examples/task_apps/TESTING.md +275 -0
- examples/task_apps/banking77/__init__.py +6 -0
- examples/task_apps/banking77/banking77_task_app.py +912 -0
- examples/task_apps/banking77/deploy_wrapper.py +46 -0
- examples/task_apps/banking77_pipeline/__init__.py +6 -0
- examples/task_apps/banking77_pipeline/banking77_pipeline_task_app.py +489 -0
- examples/task_apps/banking77_pipeline/deploy_wrapper.py +50 -0
- examples/task_apps/crafter/CREATE_SFT_DATASET.md +286 -0
- examples/task_apps/crafter/EVAL_IMAGE_ONLY_RESULTS.md +152 -0
- examples/task_apps/crafter/FILTER_COMMAND_STATUS.md +187 -0
- examples/task_apps/crafter/FILTER_COMMAND_SUCCESS.md +281 -0
- examples/task_apps/crafter/QUERY_EXAMPLES.md +203 -0
- examples/task_apps/crafter/README_IMAGE_ONLY_EVAL.md +316 -0
- examples/task_apps/crafter/eval_image_only_gpt4o.toml +28 -0
- examples/task_apps/crafter/eval_text_only_groq_llama.toml +36 -0
- examples/task_apps/crafter/filter_sft_dataset.toml +16 -0
- examples/task_apps/crafter/task_app/README.md +42 -0
- examples/task_apps/crafter/task_app/__init__.py +5 -0
- examples/task_apps/crafter/task_app/grpo_crafter.py +1055 -0
- examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +146 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/README.md +173 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/branching.py +143 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/environment_routes.py +1226 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/__init__.py +1 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/__init__.py +6 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/app.py +1 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/environment.py +532 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +583 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +122 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/shared.py +305 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/tools.py +47 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/hosted_app.py +253 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +999 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/main.py +100 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +1252 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/registry.py +195 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +2233 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/storage/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/storage/volume.py +211 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/test_agents.py +161 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/test_service.py +136 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/utils.py +411 -0
- examples/task_apps/dev/pokemon_emerald/__init__.py +2 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/README.md +811 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/__init__.py +120 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/action.py +160 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/memory.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/perception.py +69 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/planning.py +96 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/simple.py +1502 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/system_prompt.py +4 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/grab_map.py +68 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/manual.py +216 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/__init__.py +35 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emerald_utils.py +631 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emulator.py +1544 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/enums.py +1428 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/memory_reader.py +4848 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/types.py +41 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/utils.py +298 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pyproject.toml +95 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/run.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/app.py +2152 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/client.py +429 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/frame_server.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/README.md +78 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/run_tests.py +122 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_direct.py +76 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_prompts.py +413 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_battle_state_formatting.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection.py +133 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection_comprehensive.py +229 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_direct_agent_emulator.py +300 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_fps_adjustment_pytest.py +205 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_direct.py +200 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_transition.py +284 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_map_ground_truth_comparison.py +468 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_memory_map.py +575 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_server_map_validation.py +311 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_torchic_state.py +259 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/anticheat.py +372 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/checkpoint.py +296 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/error_handler.py +275 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/get_local_ip.py +22 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/helpers.py +44 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/llm_logger.py +514 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_formatter.py +415 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher.py +1763 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher_singleton.py +33 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_trimmer.py +106 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_visualizer.py +334 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/ocr_dialogue.py +1020 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/recording.py +188 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/state_formatter.py +1481 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/vlm.py +862 -0
- examples/task_apps/dev/pokemon_emerald/modal_app.py +114 -0
- examples/task_apps/dev/pokemon_emerald/task_app/README.md +81 -0
- examples/task_apps/dev/pokemon_emerald/task_app/__init__.py +6 -0
- examples/task_apps/dev/pokemon_emerald/task_app/pokemon_emerald.py +685 -0
- examples/task_apps/enron/__init__.py +2 -0
- examples/task_apps/enron/eval_groq_qwen32.toml +16 -0
- examples/task_apps/enron/filter_sft.toml +5 -0
- examples/task_apps/enron/task_app/README.md +14 -0
- examples/task_apps/enron/task_app/__init__.py +1 -0
- examples/task_apps/enron/task_app/grpo_enron.py +906 -0
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +146 -0
- examples/task_apps/enron/tests/__init__.py +4 -0
- examples/task_apps/enron/tests/conftest.py +115 -0
- examples/task_apps/enron/tests/integration/__init__.py +4 -0
- examples/task_apps/enron/tests/integration/test_enron_eval.py +179 -0
- examples/task_apps/enron/tests/integration/test_enron_rollout.py +135 -0
- examples/task_apps/enron/tests/unit/__init__.py +4 -0
- examples/task_apps/enron/tests/unit/test_enron_environment.py +126 -0
- examples/task_apps/gepa_benchmarks/__init__.py +7 -0
- examples/task_apps/gepa_benchmarks/common.py +260 -0
- examples/task_apps/gepa_benchmarks/hotpotqa_task_app.py +507 -0
- examples/task_apps/gepa_benchmarks/hover_task_app.py +436 -0
- examples/task_apps/gepa_benchmarks/ifbench_task_app.py +563 -0
- examples/task_apps/gepa_benchmarks/pupa_task_app.py +460 -0
- examples/task_apps/math/README.md +21 -0
- examples/task_apps/math/math_single_step.py +1000 -0
- examples/task_apps/math/math_task_app.py +115 -0
- examples/task_apps/pokemon_battle/__init__.py +2 -0
- examples/task_apps/pokemon_battle/modal_app.py +104 -0
- examples/task_apps/pokemon_battle/task_app/README.md +68 -0
- examples/task_apps/pokemon_battle/task_app/__init__.py +6 -0
- examples/task_apps/pokemon_battle/task_app/pokemon_showdown.py +932 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_COMPLETE.md +283 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_STATUS.md +155 -0
- examples/task_apps/pokemon_red/README.md +356 -0
- examples/task_apps/pokemon_red/README_IMAGE_ONLY_EVAL.md +428 -0
- examples/task_apps/pokemon_red/__init__.py +3 -0
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +30 -0
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +224 -0
- examples/task_apps/pokemon_red/pallet_town_rl_config.toml +75 -0
- examples/task_apps/pokemon_red/task_app.py +1048 -0
- examples/task_apps/pokemon_red/test_pallet_town_rewards.py +193 -0
- examples/task_apps/sokoban/README.md +306 -0
- examples/task_apps/sokoban/__init__.py +3 -0
- examples/task_apps/sokoban/eval_groq_qwen32.toml +16 -0
- examples/task_apps/sokoban/eval_openai_gpt5.toml +16 -0
- examples/task_apps/sokoban/filter_sft.toml +5 -0
- examples/task_apps/sokoban/task_app.py +1058 -0
- examples/task_apps/sokoban/tests/__init__.py +4 -0
- examples/task_apps/sokoban/tests/conftest.py +113 -0
- examples/task_apps/sokoban/tests/integration/__init__.py +4 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_eval.py +57 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_rollout.py +198 -0
- examples/task_apps/sokoban/tests/unit/__init__.py +4 -0
- examples/task_apps/sokoban/tests/unit/test_sokoban_environment.py +114 -0
- examples/task_apps/verilog/__init__.py +1 -0
- examples/task_apps/verilog/eval_groq_qwen32b.toml +22 -0
- examples/task_apps/verilog/filter_sft.toml +5 -0
- examples/task_apps/verilog/task_app/README.md +12 -0
- examples/task_apps/verilog/task_app/__init__.py +1 -0
- examples/task_apps/verilog/task_app/grpo_verilog.py +1166 -0
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +145 -0
- examples/task_apps/verilog/tests/__init__.py +4 -0
- examples/task_apps/verilog/tests/conftest.py +115 -0
- examples/task_apps/verilog/tests/integration/__init__.py +4 -0
- examples/task_apps/verilog/tests/integration/test_verilog_eval.py +181 -0
- examples/task_apps/verilog/tests/integration/test_verilog_rollout.py +55 -0
- examples/task_apps/verilog/tests/unit/__init__.py +4 -0
- examples/task_apps/verilog/tests/unit/test_verilog_scoring.py +118 -0
- examples/tunnel_gepa_banking77/README.md +106 -0
- examples/tunnel_gepa_banking77/banking77_gepa_tunnel.toml +95 -0
- examples/tunnel_gepa_banking77/keep_tunnel_running.py +60 -0
- examples/tunnel_gepa_banking77/run_gepa_with_tunnel.sh +226 -0
- examples/vlm/PROPOSAL.md +53 -0
- examples/vlm/README.md +68 -0
- examples/vlm/configs/crafter_vlm_gpt4o.toml +49 -0
- examples/vlm/crafter_image_only_agent.py +207 -0
- examples/vlm/crafter_openai_vlm_agent.py +275 -0
- examples/vlm/filter_image_rows.py +63 -0
- examples/vlm/run_crafter_vlm_benchmark.py +316 -0
- examples/warming_up_to_rl/_utils.py +92 -0
- examples/warming_up_to_rl/analyze_trace_db.py +422 -0
- examples/warming_up_to_rl/configs/crafter_fft.toml +53 -0
- examples/warming_up_to_rl/configs/crafter_fft_4b.toml +54 -0
- examples/warming_up_to_rl/configs/eval_fft_qwen4b.toml +22 -0
- examples/warming_up_to_rl/configs/eval_groq_qwen32b.toml +15 -0
- examples/warming_up_to_rl/configs/eval_modal_qwen4b.toml +24 -0
- examples/warming_up_to_rl/configs/eval_stepwise_complex.toml +35 -0
- examples/warming_up_to_rl/configs/eval_stepwise_consistent.toml +26 -0
- examples/warming_up_to_rl/configs/eval_stepwise_per_achievement.toml +36 -0
- examples/warming_up_to_rl/configs/eval_stepwise_simple.toml +32 -0
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +85 -0
- examples/warming_up_to_rl/configs/rl_from_ft.toml +58 -0
- examples/warming_up_to_rl/export_trace_sft.py +837 -0
- examples/warming_up_to_rl/groq_test.py +97 -0
- examples/warming_up_to_rl/manage_secrets.py +131 -0
- examples/warming_up_to_rl/old/event_rewards.md +234 -0
- examples/warming_up_to_rl/old/notes.md +73 -0
- examples/warming_up_to_rl/readme.md +110 -0
- examples/warming_up_to_rl/run_eval.py +736 -0
- examples/warming_up_to_rl/run_fft_and_save.py +380 -0
- examples/warming_up_to_rl/run_local_rollout.py +239 -0
- examples/warming_up_to_rl/run_local_rollout_modal.py +248 -0
- examples/warming_up_to_rl/run_local_rollout_parallel.py +405 -0
- examples/warming_up_to_rl/run_local_rollout_traced.py +477 -0
- examples/warming_up_to_rl/run_rl_and_save.py +124 -0
- examples/warming_up_to_rl/run_rollout_remote.py +156 -0
- examples/warming_up_to_rl/task_app/README.md +42 -0
- examples/warming_up_to_rl/task_app/grpo_crafter.py +876 -0
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +135 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/README.md +173 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/branching.py +143 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/environment_routes.py +1226 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/__init__.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/__init__.py +6 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/app.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +522 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +454 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +108 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +305 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/tools.py +47 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +253 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +729 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/main.py +100 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +1114 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/registry.py +195 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +1891 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +211 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_agents.py +161 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_service.py +137 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +129 -0
- examples/workflows/math_rl/configs/eval_base_qwen.toml +15 -0
- examples/workflows/math_rl/configs/eval_rl_qwen.toml +11 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen.toml +62 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +80 -0
- examples/workflows/math_rl/configs/rl_from_ft_qwen.toml +35 -0
- examples/workflows/math_rl/download_dataset.py +80 -0
- examples/workflows/math_rl/run_eval.py +436 -0
- examples/workflows/math_rl/run_rl_and_save.py +111 -0
- synth_ai/__init__.py +47 -23
- synth_ai/_utils/__init__.py +47 -0
- synth_ai/_utils/base_url.py +10 -0
- synth_ai/_utils/http.py +10 -0
- synth_ai/_utils/prompts.py +10 -0
- synth_ai/_utils/task_app_state.py +12 -0
- synth_ai/_utils/user_config.py +10 -0
- synth_ai/api/models/supported.py +514 -0
- synth_ai/api/train/__init__.py +60 -2
- synth_ai/api/train/builders.py +347 -39
- synth_ai/api/train/cli.py +895 -160
- synth_ai/api/train/config_finder.py +103 -25
- synth_ai/api/train/configs/__init__.py +65 -0
- synth_ai/api/train/configs/prompt_learning.py +496 -0
- synth_ai/api/train/configs/rl.py +188 -0
- synth_ai/api/train/configs/sft.py +99 -0
- synth_ai/api/train/configs/shared.py +81 -0
- synth_ai/api/train/env_resolver.py +70 -20
- synth_ai/api/train/pollers.py +29 -4
- synth_ai/api/train/prompt_learning.py +425 -0
- synth_ai/api/train/sft.py +390 -0
- synth_ai/api/train/supported_algos.py +147 -0
- synth_ai/api/train/task_app.py +6 -4
- synth_ai/api/train/utils.py +64 -52
- synth_ai/api/train/validators.py +1117 -0
- synth_ai/api/tunnel.py +49 -0
- synth_ai/auth/credentials.py +94 -0
- synth_ai/baseline/__init__.py +25 -0
- synth_ai/baseline/config.py +209 -0
- synth_ai/baseline/discovery.py +214 -0
- synth_ai/baseline/execution.py +146 -0
- synth_ai/cfgs.py +227 -0
- synth_ai/cli/__init__.py +85 -63
- synth_ai/cli/_modal_wrapper.py +31 -0
- synth_ai/cli/_storage.py +20 -0
- synth_ai/cli/_typer_patch.py +47 -0
- synth_ai/cli/_validate_task_app.py +29 -0
- synth_ai/cli/balance.py +16 -4
- synth_ai/cli/calc.py +36 -21
- synth_ai/cli/claude.py +70 -0
- synth_ai/cli/codex.py +267 -0
- synth_ai/cli/commands/__init__.py +18 -0
- synth_ai/cli/commands/baseline/__init__.py +12 -0
- synth_ai/cli/commands/baseline/core.py +637 -0
- synth_ai/cli/commands/baseline/list.py +93 -0
- synth_ai/cli/commands/demo/__init__.py +6 -0
- synth_ai/cli/commands/demo/core.py +163 -0
- synth_ai/cli/commands/eval/__init__.py +19 -0
- synth_ai/cli/commands/eval/core.py +1112 -0
- synth_ai/cli/commands/eval/errors.py +81 -0
- synth_ai/cli/commands/eval/validation.py +133 -0
- synth_ai/cli/commands/filter/__init__.py +12 -0
- synth_ai/cli/commands/filter/core.py +424 -0
- synth_ai/cli/commands/filter/errors.py +55 -0
- synth_ai/cli/commands/filter/validation.py +77 -0
- synth_ai/cli/commands/help/__init__.py +185 -0
- synth_ai/cli/commands/help/core.py +72 -0
- synth_ai/cli/commands/smoke/__init__.py +7 -0
- synth_ai/cli/commands/smoke/core.py +1437 -0
- synth_ai/cli/commands/status/__init__.py +66 -0
- synth_ai/cli/commands/status/client.py +192 -0
- synth_ai/cli/commands/status/config.py +92 -0
- synth_ai/cli/commands/status/errors.py +20 -0
- synth_ai/cli/commands/status/formatters.py +164 -0
- synth_ai/cli/commands/status/subcommands/__init__.py +9 -0
- synth_ai/cli/commands/status/subcommands/files.py +79 -0
- synth_ai/cli/commands/status/subcommands/jobs.py +334 -0
- synth_ai/cli/commands/status/subcommands/models.py +79 -0
- synth_ai/cli/commands/status/subcommands/pricing.py +22 -0
- synth_ai/cli/commands/status/subcommands/runs.py +81 -0
- synth_ai/cli/commands/status/subcommands/session.py +183 -0
- synth_ai/cli/commands/status/subcommands/summary.py +47 -0
- synth_ai/cli/commands/status/subcommands/usage.py +203 -0
- synth_ai/cli/commands/status/utils.py +114 -0
- synth_ai/cli/commands/train/__init__.py +53 -0
- synth_ai/cli/commands/train/core.py +21 -0
- synth_ai/cli/commands/train/errors.py +117 -0
- synth_ai/cli/commands/train/judge_schemas.py +200 -0
- synth_ai/cli/commands/train/judge_validation.py +305 -0
- synth_ai/cli/commands/train/validation.py +386 -0
- synth_ai/cli/demo.py +32 -140
- synth_ai/cli/deploy.py +233 -0
- synth_ai/cli/eval/__init__.py +36 -0
- synth_ai/cli/eval/core.py +5 -0
- synth_ai/cli/eval/errors.py +31 -0
- synth_ai/cli/eval/validation.py +5 -0
- synth_ai/cli/filter/__init__.py +28 -0
- synth_ai/cli/filter/core.py +5 -0
- synth_ai/cli/filter/errors.py +23 -0
- synth_ai/cli/filter/validation.py +5 -0
- synth_ai/cli/legacy_root_backup.py +28 -22
- synth_ai/cli/lib/__init__.py +10 -0
- synth_ai/cli/lib/task_app_discovery.py +7 -0
- synth_ai/cli/lib/task_app_env.py +518 -0
- synth_ai/cli/mcp.py +34 -0
- synth_ai/cli/modal_serve/__init__.py +12 -0
- synth_ai/cli/modal_serve/core.py +14 -0
- synth_ai/cli/modal_serve/errors.py +8 -0
- synth_ai/cli/modal_serve/validation.py +11 -0
- synth_ai/cli/opencode.py +256 -0
- synth_ai/cli/recent.py +13 -7
- synth_ai/cli/rl_demo.py +156 -116
- synth_ai/cli/root.py +131 -132
- synth_ai/cli/serve/__init__.py +12 -0
- synth_ai/cli/serve/core.py +14 -0
- synth_ai/cli/serve/errors.py +8 -0
- synth_ai/cli/serve/validation.py +11 -0
- synth_ai/cli/setup.py +49 -0
- synth_ai/cli/status.py +7 -125
- synth_ai/cli/task_app_deploy.py +7 -0
- synth_ai/cli/task_app_list.py +25 -0
- synth_ai/cli/task_app_modal_serve.py +11 -0
- synth_ai/cli/task_app_serve.py +11 -0
- synth_ai/cli/task_apps.py +2284 -257
- synth_ai/cli/traces.py +9 -5
- synth_ai/cli/train/__init__.py +12 -0
- synth_ai/cli/train/core.py +21 -0
- synth_ai/cli/train/errors.py +8 -0
- synth_ai/cli/train/validation.py +24 -0
- synth_ai/cli/train.py +5 -0
- synth_ai/cli/turso.py +73 -0
- synth_ai/cli/watch.py +13 -18
- synth_ai/demos/__init__.py +10 -0
- synth_ai/demos/core/__init__.py +28 -1
- synth_ai/demos/core/cli.py +579 -291
- synth_ai/demos/crafter/__init__.py +1 -0
- synth_ai/demos/crafter/crafter_fft_4b.toml +55 -0
- synth_ai/demos/crafter/grpo_crafter_task_app.py +185 -0
- synth_ai/demos/crafter/rl_from_base_qwen4b.toml +74 -0
- synth_ai/demos/demo_registry.py +176 -0
- synth_ai/demos/demo_task_apps/__init__.py +3 -3
- synth_ai/demos/demo_task_apps/core.py +64 -28
- synth_ai/demos/demo_task_apps/crafter/__init__.py +1 -0
- synth_ai/demos/demo_task_apps/crafter/configs/crafter_fft_4b.toml +53 -0
- synth_ai/demos/demo_task_apps/crafter/configs/rl_from_base_qwen4b.toml +73 -0
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +184 -0
- synth_ai/demos/demo_task_apps/math/_common.py +1 -2
- synth_ai/demos/demo_task_apps/math/app.py +2 -1
- synth_ai/demos/demo_task_apps/math/deploy_modal.py +3 -6
- synth_ai/demos/demo_task_apps/math/modal_task_app.py +185 -83
- synth_ai/demos/demo_task_apps/math/task_app_entry.py +0 -2
- synth_ai/demos/math/__init__.py +1 -0
- synth_ai/demos/math/_common.py +16 -0
- synth_ai/demos/math/app.py +38 -0
- synth_ai/demos/math/config.toml +76 -0
- synth_ai/demos/math/deploy_modal.py +54 -0
- synth_ai/demos/math/modal_task_app.py +703 -0
- synth_ai/demos/math/task_app_entry.py +51 -0
- synth_ai/environments/environment/core.py +7 -1
- synth_ai/environments/examples/bandit/engine.py +12 -5
- synth_ai/environments/examples/bandit/environment.py +0 -1
- synth_ai/environments/examples/bandit/taskset.py +4 -4
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +7 -4
- synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +9 -5
- synth_ai/environments/examples/crafter_classic/environment.py +93 -2
- synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +4 -3
- synth_ai/environments/examples/enron/engine.py +7 -2
- synth_ai/environments/examples/enron/environment.py +68 -0
- synth_ai/environments/examples/red/engine.py +60 -12
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +7 -0
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_progression.py +477 -0
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +32 -0
- synth_ai/environments/examples/red/environment.py +86 -0
- synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
- synth_ai/environments/examples/sokoban/taskset.py +116 -0
- synth_ai/environments/examples/verilog/engine.py +104 -12
- synth_ai/environments/examples/wordle/environment.py +0 -1
- synth_ai/environments/reproducibility/tree.py +5 -6
- synth_ai/environments/service/app.py +11 -12
- synth_ai/environments/service/core_routes.py +10 -9
- 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/evals/__init__.py +15 -0
- synth_ai/evals/base.py +14 -5
- synth_ai/evals/client.py +82 -0
- synth_ai/evals/types.py +42 -0
- synth_ai/http.py +8 -22
- synth_ai/http_client.py +45 -12
- synth_ai/inference/__init__.py +0 -2
- synth_ai/inference/client.py +21 -7
- synth_ai/jobs/client.py +129 -80
- synth_ai/judge_schemas.py +127 -0
- synth_ai/learning/__init__.py +51 -6
- synth_ai/learning/algorithms.py +14 -0
- synth_ai/learning/client.py +122 -30
- synth_ai/learning/config.py +2 -40
- synth_ai/learning/constants.py +0 -2
- synth_ai/learning/ft_client.py +4 -56
- synth_ai/learning/health.py +14 -8
- synth_ai/learning/jobs.py +43 -47
- synth_ai/learning/prompt_learning_client.py +276 -0
- synth_ai/learning/prompt_learning_types.py +185 -0
- synth_ai/{rl → learning/rl}/__init__.py +14 -5
- synth_ai/learning/rl/client.py +269 -0
- synth_ai/learning/rl/config.py +31 -0
- synth_ai/{rl → learning/rl}/contracts.py +5 -10
- synth_ai/{rl → learning/rl}/env_keys.py +45 -16
- synth_ai/learning/rl/secrets.py +13 -0
- synth_ai/learning/rl_client.py +2 -253
- 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 +698 -0
- synth_ai/learning/sse.py +25 -26
- synth_ai/learning/validators.py +29 -25
- synth_ai/mcp/__init__.py +5 -0
- synth_ai/mcp/__main__.py +8 -0
- synth_ai/mcp/main.py +254 -0
- synth_ai/mcp/setup.py +100 -0
- synth_ai/modal.py +257 -0
- synth_ai/pricing/__init__.py +3 -0
- synth_ai/pricing/model_pricing.py +64 -0
- synth_ai/session/__init__.py +75 -0
- synth_ai/session/client.py +383 -0
- synth_ai/session/constants.py +63 -0
- synth_ai/session/exceptions.py +105 -0
- synth_ai/session/manager.py +139 -0
- synth_ai/session/models.py +89 -0
- synth_ai/session/query.py +110 -0
- synth_ai/spec/__init__.py +46 -0
- synth_ai/spec/dataclasses.py +149 -0
- synth_ai/spec/loader.py +144 -0
- synth_ai/spec/serializer.py +199 -0
- synth_ai/spec/validation.py +250 -0
- synth_ai/streaming/__init__.py +29 -0
- synth_ai/streaming/config.py +94 -0
- synth_ai/streaming/handlers.py +589 -0
- synth_ai/streaming/streamer.py +320 -0
- synth_ai/streaming/types.py +95 -0
- synth_ai/task/__init__.py +50 -30
- synth_ai/task/apps/__init__.py +63 -19
- synth_ai/task/auth.py +35 -23
- synth_ai/task/client.py +15 -13
- synth_ai/task/config.py +261 -0
- synth_ai/task/contracts.py +165 -64
- synth_ai/task/datasets.py +9 -6
- synth_ai/task/errors.py +11 -10
- synth_ai/task/health.py +17 -11
- synth_ai/task/inference_api.py +101 -0
- synth_ai/task/json.py +58 -24
- synth_ai/task/proxy.py +59 -66
- synth_ai/task/rubrics/__init__.py +55 -0
- synth_ai/task/rubrics/loaders.py +156 -0
- synth_ai/task/rubrics/models.py +57 -0
- synth_ai/task/rubrics/scoring.py +116 -0
- synth_ai/task/rubrics/strict.py +149 -0
- synth_ai/task/rubrics.py +22 -15
- synth_ai/task/server.py +65 -31
- synth_ai/task/trace_correlation_helpers.py +328 -0
- synth_ai/task/tracing_utils.py +44 -28
- synth_ai/task/validators.py +449 -6
- synth_ai/task/vendors.py +5 -7
- synth_ai/tracing_v3/__init__.py +4 -0
- synth_ai/tracing_v3/abstractions.py +21 -4
- synth_ai/tracing_v3/config.py +167 -22
- synth_ai/tracing_v3/constants.py +21 -0
- synth_ai/tracing_v3/db_config.py +42 -29
- synth_ai/tracing_v3/decorators.py +80 -45
- synth_ai/tracing_v3/examples/basic_usage.py +15 -9
- synth_ai/tracing_v3/hooks.py +6 -4
- synth_ai/tracing_v3/llm_call_record_helpers.py +161 -61
- synth_ai/tracing_v3/migration_helper.py +1 -2
- synth_ai/tracing_v3/replica_sync.py +12 -7
- synth_ai/tracing_v3/serialization.py +130 -0
- synth_ai/tracing_v3/session_tracer.py +73 -16
- synth_ai/tracing_v3/storage/base.py +89 -1
- synth_ai/tracing_v3/storage/config.py +63 -16
- synth_ai/tracing_v3/storage/factory.py +11 -9
- synth_ai/tracing_v3/storage/utils.py +15 -11
- synth_ai/tracing_v3/trace_utils.py +317 -0
- synth_ai/tracing_v3/turso/__init__.py +8 -21
- synth_ai/tracing_v3/turso/daemon.py +123 -15
- synth_ai/tracing_v3/turso/models.py +5 -2
- synth_ai/tracing_v3/turso/native_manager.py +1293 -0
- synth_ai/tracing_v3/utils.py +5 -4
- synth_ai/tunnel.py +143 -0
- synth_ai/tunnel_deploy.py +278 -0
- synth_ai/types.py +8 -0
- synth_ai/urls.py +11 -0
- synth_ai/utils/__init__.py +166 -0
- synth_ai/utils/agents.py +74 -0
- synth_ai/utils/apps.py +152 -0
- synth_ai/utils/base_url.py +94 -0
- synth_ai/utils/bin.py +39 -0
- synth_ai/utils/claude.py +36 -0
- synth_ai/utils/cli.py +284 -0
- synth_ai/utils/config.py +81 -0
- synth_ai/utils/env.py +346 -0
- synth_ai/utils/errors.py +85 -0
- synth_ai/utils/http.py +172 -0
- synth_ai/utils/json.py +72 -0
- synth_ai/utils/log_filter.py +99 -0
- synth_ai/utils/logging.py +198 -0
- synth_ai/utils/modal.py +299 -0
- synth_ai/utils/paths.py +95 -0
- synth_ai/utils/process.py +233 -0
- synth_ai/utils/prompts.py +39 -0
- synth_ai/utils/sqld.py +122 -0
- synth_ai/utils/ssl.py +25 -0
- synth_ai/utils/task_app_discovery.py +882 -0
- synth_ai/utils/task_app_env.py +186 -0
- synth_ai/utils/task_app_state.py +318 -0
- synth_ai/utils/tunnel/__init__.py +12 -0
- synth_ai/utils/tunnel/config.py +55 -0
- synth_ai/utils/user_config.py +137 -0
- synth_ai/uvicorn.py +77 -0
- synth_ai-0.2.23.dev3.dist-info/METADATA +357 -0
- synth_ai-0.2.23.dev3.dist-info/RECORD +983 -0
- {synth_ai-0.2.9.dev0.dist-info → synth_ai-0.2.23.dev3.dist-info}/entry_points.txt +0 -1
- {synth_ai-0.2.9.dev0.dist-info → synth_ai-0.2.23.dev3.dist-info}/top_level.txt +1 -0
- synth_ai/cli/man.py +0 -106
- synth_ai/core/experiment.py +0 -15
- synth_ai/core/system.py +0 -15
- synth_ai/demo_registry.py +0 -258
- synth_ai/environments/examples/sokoban/units/astar_common.py +0 -95
- synth_ai/experimental/synth_oss.py +0 -446
- synth_ai/handshake.py +0 -107
- synth_ai/install_sqld.sh +0 -40
- 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 -213
- synth_ai/learning/prompts/mipro.py +0 -289
- synth_ai/learning/prompts/random_search.py +0 -246
- synth_ai/learning/prompts/run_mipro_banking77.py +0 -172
- synth_ai/learning/prompts/run_random_search_banking77.py +0 -324
- synth_ai/lm/__init__.py +0 -51
- synth_ai/lm/caching/constants.py +0 -6
- synth_ai/lm/caching/dbs.py +0 -0
- synth_ai/lm/caching/ephemeral.py +0 -102
- synth_ai/lm/caching/handler.py +0 -137
- synth_ai/lm/caching/initialize.py +0 -11
- synth_ai/lm/caching/persistent.py +0 -114
- synth_ai/lm/config.py +0 -110
- synth_ai/lm/constants.py +0 -32
- synth_ai/lm/core/__init__.py +0 -8
- synth_ai/lm/core/all.py +0 -73
- synth_ai/lm/core/exceptions.py +0 -7
- synth_ai/lm/core/main.py +0 -319
- synth_ai/lm/core/main_v3.py +0 -594
- synth_ai/lm/core/synth_models.py +0 -48
- synth_ai/lm/core/vendor_clients.py +0 -188
- synth_ai/lm/cost/monitor.py +0 -1
- synth_ai/lm/cost/statefulness.py +0 -1
- synth_ai/lm/injection.py +0 -80
- synth_ai/lm/overrides.py +0 -206
- synth_ai/lm/provider_support/__init__.py +0 -8
- synth_ai/lm/provider_support/anthropic.py +0 -972
- synth_ai/lm/provider_support/openai.py +0 -1139
- synth_ai/lm/provider_support/suppress_logging.py +0 -31
- synth_ai/lm/structured_outputs/handler.py +0 -440
- synth_ai/lm/structured_outputs/inject.py +0 -297
- synth_ai/lm/structured_outputs/rehabilitate.py +0 -185
- synth_ai/lm/tools/__init__.py +0 -3
- synth_ai/lm/tools/base.py +0 -172
- synth_ai/lm/unified_interface.py +0 -202
- synth_ai/lm/vendors/base.py +0 -81
- synth_ai/lm/vendors/core/anthropic_api.py +0 -387
- synth_ai/lm/vendors/core/gemini_api.py +0 -292
- synth_ai/lm/vendors/core/mistral_api.py +0 -322
- synth_ai/lm/vendors/core/openai_api.py +0 -225
- synth_ai/lm/vendors/core/synth_dev_api.py +0 -0
- synth_ai/lm/vendors/local/ollama.py +0 -0
- synth_ai/lm/vendors/openai_standard.py +0 -780
- synth_ai/lm/vendors/openai_standard_responses.py +0 -256
- synth_ai/lm/vendors/retries.py +0 -22
- synth_ai/lm/vendors/supported/custom_endpoint.py +0 -417
- synth_ai/lm/vendors/supported/deepseek.py +0 -69
- synth_ai/lm/vendors/supported/grok.py +0 -75
- synth_ai/lm/vendors/supported/groq.py +0 -16
- synth_ai/lm/vendors/supported/ollama.py +0 -15
- synth_ai/lm/vendors/supported/openrouter.py +0 -74
- synth_ai/lm/vendors/supported/together.py +0 -11
- synth_ai/lm/vendors/synth_client.py +0 -808
- synth_ai/lm/warmup.py +0 -186
- synth_ai/rl/secrets.py +0 -19
- synth_ai/scripts/verify_rewards.py +0 -100
- synth_ai/task/apps/grpo_crafter.py +0 -438
- synth_ai/tracing/__init__.py +0 -30
- synth_ai/tracing_v1/__init__.py +0 -33
- synth_ai/tracing_v3/turso/manager.py +0 -774
- synth_ai/v0/tracing/abstractions.py +0 -224
- synth_ai/v0/tracing/base_client.py +0 -91
- synth_ai/v0/tracing/client_manager.py +0 -131
- synth_ai/v0/tracing/config.py +0 -142
- synth_ai/v0/tracing/context.py +0 -146
- synth_ai/v0/tracing/decorators.py +0 -682
- synth_ai/v0/tracing/events/__init__.py +0 -0
- synth_ai/v0/tracing/events/manage.py +0 -147
- synth_ai/v0/tracing/events/scope.py +0 -86
- synth_ai/v0/tracing/events/store.py +0 -228
- synth_ai/v0/tracing/immediate_client.py +0 -151
- synth_ai/v0/tracing/local.py +0 -18
- synth_ai/v0/tracing/log_client_base.py +0 -73
- synth_ai/v0/tracing/retry_queue.py +0 -186
- synth_ai/v0/tracing/trackers.py +0 -515
- synth_ai/v0/tracing/upload.py +0 -512
- synth_ai/v0/tracing/utils.py +0 -9
- synth_ai/v0/tracing_v1/__init__.py +0 -16
- synth_ai/v0/tracing_v1/abstractions.py +0 -224
- synth_ai/v0/tracing_v1/base_client.py +0 -91
- synth_ai/v0/tracing_v1/client_manager.py +0 -131
- synth_ai/v0/tracing_v1/config.py +0 -142
- synth_ai/v0/tracing_v1/context.py +0 -146
- synth_ai/v0/tracing_v1/decorators.py +0 -703
- synth_ai/v0/tracing_v1/events/__init__.py +0 -0
- synth_ai/v0/tracing_v1/events/manage.py +0 -147
- synth_ai/v0/tracing_v1/events/scope.py +0 -86
- synth_ai/v0/tracing_v1/events/store.py +0 -228
- synth_ai/v0/tracing_v1/immediate_client.py +0 -151
- synth_ai/v0/tracing_v1/local.py +0 -18
- synth_ai/v0/tracing_v1/log_client_base.py +0 -73
- synth_ai/v0/tracing_v1/retry_queue.py +0 -186
- synth_ai/v0/tracing_v1/trackers.py +0 -515
- synth_ai/v0/tracing_v1/upload.py +0 -527
- synth_ai/v0/tracing_v1/utils.py +0 -9
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.9.dev0.dist-info/METADATA +0 -131
- synth_ai-0.2.9.dev0.dist-info/RECORD +0 -444
- {synth_ai/lm/caching → examples/task_apps}/__init__.py +0 -0
- {synth_ai/lm/cost → examples/task_apps/crafter}/__init__.py +0 -0
- {synth_ai/lm/structured_outputs → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server}/__init__.py +0 -0
- {synth_ai/lm/vendors → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests}/__init__.py +0 -0
- {synth_ai/lm/vendors/core → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils}/__init__.py +0 -0
- {synth_ai/lm/vendors/local → examples/task_apps/math}/__init__.py +0 -0
- {synth_ai/lm/vendors/supported → examples/workflows}/__init__.py +0 -0
- {synth_ai/v0/tracing → examples/workflows/math_rl}/__init__.py +0 -0
- /synth_ai/{compound/cais.py → cli/__main__.py} +0 -0
- /synth_ai/{learning/filtering.py → py.typed} +0 -0
- {synth_ai-0.2.9.dev0.dist-info → synth_ai-0.2.23.dev3.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.9.dev0.dist-info → synth_ai-0.2.23.dev3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Utility classes for running swe-mini environments on Morph Cloud."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import os
|
|
7
|
+
import shlex
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import Any, Dict
|
|
11
|
+
|
|
12
|
+
_IMPORT_ERROR: Exception | None = None
|
|
13
|
+
|
|
14
|
+
try: # pragma: no cover - optional dependency
|
|
15
|
+
from morphcloud.api import MorphCloudClient
|
|
16
|
+
except Exception as exc: # pragma: no cover - optional dependency
|
|
17
|
+
MorphCloudClient = None # type: ignore[assignment]
|
|
18
|
+
_IMPORT_ERROR = exc
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _quote_env_var(key: str, value: str) -> str:
|
|
22
|
+
"""Return a safe shell export statement."""
|
|
23
|
+
return f"export {key}={shlex.quote(value)}"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _now() -> float:
|
|
27
|
+
return time.time()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class MorphSandboxBackend:
|
|
32
|
+
"""Thin wrapper around Morph Cloud instances for command execution.
|
|
33
|
+
|
|
34
|
+
The API mirrors the subset consumed by :class:`MiniSweEnvironmentWrapper`:
|
|
35
|
+
we expose an ``execute`` method that matches the mini-swe environment shape.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
snapshot_id: str | None = None
|
|
39
|
+
image_id: str | None = None
|
|
40
|
+
cwd: str = "/workspace"
|
|
41
|
+
env: Dict[str, str] | None = None
|
|
42
|
+
metadata: Dict[str, str] | None = None
|
|
43
|
+
vcpus: int = 4
|
|
44
|
+
memory_mb: int = 8192
|
|
45
|
+
disk_mb: int = 65536
|
|
46
|
+
startup_timeout: int = 600
|
|
47
|
+
|
|
48
|
+
_client: MorphCloudClient = field(init=False)
|
|
49
|
+
_instance: Any = field(init=False, default=None)
|
|
50
|
+
_last_exec: Dict[str, Any] = field(init=False, default_factory=dict)
|
|
51
|
+
_started_at: float | None = field(init=False, default=None)
|
|
52
|
+
|
|
53
|
+
def __post_init__(self) -> None:
|
|
54
|
+
if MorphCloudClient is None: # pragma: no cover - optional dependency
|
|
55
|
+
raise RuntimeError(
|
|
56
|
+
"morphcloud package is required for Morph environments. "
|
|
57
|
+
"Install with `pip install morphcloud`."
|
|
58
|
+
) from _IMPORT_ERROR
|
|
59
|
+
|
|
60
|
+
api_key = os.getenv("MORPH_API_KEY", "")
|
|
61
|
+
if not api_key:
|
|
62
|
+
raise RuntimeError("Set MORPH_API_KEY before using the Morph backend.")
|
|
63
|
+
|
|
64
|
+
# Normalise metadata/env early to avoid shared references.
|
|
65
|
+
self.metadata = {str(k): str(v) for k, v in (self.metadata or {}).items()}
|
|
66
|
+
self.env = {str(k): str(v) for k, v in (self.env or {}).items()}
|
|
67
|
+
self.cwd = self.cwd or "/workspace"
|
|
68
|
+
|
|
69
|
+
self._client = MorphCloudClient()
|
|
70
|
+
|
|
71
|
+
# Public API -----------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
def execute(self, command: str, timeout: int | None = None) -> Dict[str, Any]:
|
|
74
|
+
"""Execute ``command`` inside the Morph instance."""
|
|
75
|
+
if not command.strip():
|
|
76
|
+
command = "true"
|
|
77
|
+
|
|
78
|
+
instance = self._ensure_instance()
|
|
79
|
+
|
|
80
|
+
script_parts = []
|
|
81
|
+
for key, value in self.env.items():
|
|
82
|
+
script_parts.append(_quote_env_var(key, value))
|
|
83
|
+
if self.cwd:
|
|
84
|
+
script_parts.append(f"cd {shlex.quote(self.cwd)}")
|
|
85
|
+
script_parts.append(command)
|
|
86
|
+
|
|
87
|
+
script = " && ".join(script_parts)
|
|
88
|
+
if timeout:
|
|
89
|
+
wrapped = f"timeout {int(timeout)}s bash -lc {shlex.quote(script)}"
|
|
90
|
+
else:
|
|
91
|
+
wrapped = script
|
|
92
|
+
|
|
93
|
+
shell_cmd = f"bash -lc {shlex.quote(wrapped)}"
|
|
94
|
+
started = _now()
|
|
95
|
+
result = instance.exec(shell_cmd)
|
|
96
|
+
duration = _now() - started
|
|
97
|
+
|
|
98
|
+
payload = {
|
|
99
|
+
"output": (result.stdout or ""),
|
|
100
|
+
"stderr": (result.stderr or ""),
|
|
101
|
+
"returncode": getattr(result, "exit_code", None),
|
|
102
|
+
"duration": duration,
|
|
103
|
+
}
|
|
104
|
+
self._last_exec = payload
|
|
105
|
+
return payload
|
|
106
|
+
|
|
107
|
+
def close(self) -> None:
|
|
108
|
+
"""Stops the Morph instance if one is running."""
|
|
109
|
+
instance = getattr(self, "_instance", None)
|
|
110
|
+
if not instance:
|
|
111
|
+
return
|
|
112
|
+
try:
|
|
113
|
+
instance.stop()
|
|
114
|
+
except Exception: # pragma: no cover - best-effort shutdown
|
|
115
|
+
pass
|
|
116
|
+
finally:
|
|
117
|
+
self._instance = None
|
|
118
|
+
|
|
119
|
+
# Internal helpers -----------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
def _ensure_instance(self):
|
|
122
|
+
instance = getattr(self, "_instance", None)
|
|
123
|
+
if instance is not None:
|
|
124
|
+
return instance
|
|
125
|
+
|
|
126
|
+
snapshot_id = (
|
|
127
|
+
self.snapshot_id
|
|
128
|
+
or os.getenv("SWE_MINI_MORPH_SNAPSHOT_ID")
|
|
129
|
+
or os.getenv("MORPH_SNAPSHOT_ID")
|
|
130
|
+
)
|
|
131
|
+
metadata = dict(self.metadata)
|
|
132
|
+
|
|
133
|
+
if snapshot_id:
|
|
134
|
+
instance = self._client.instances.start(snapshot_id=snapshot_id, metadata=metadata or None)
|
|
135
|
+
else:
|
|
136
|
+
image_id = (
|
|
137
|
+
self.image_id
|
|
138
|
+
or os.getenv("SWE_MINI_MORPH_IMAGE_ID")
|
|
139
|
+
or os.getenv("MORPH_IMAGE_ID")
|
|
140
|
+
or "morphvm-minimal"
|
|
141
|
+
)
|
|
142
|
+
snapshot = self._client.snapshots.create(
|
|
143
|
+
image_id=image_id,
|
|
144
|
+
vcpus=self.vcpus,
|
|
145
|
+
memory=self.memory_mb,
|
|
146
|
+
disk_size=self.disk_mb,
|
|
147
|
+
)
|
|
148
|
+
instance = self._client.instances.start(snapshot_id=snapshot.id, metadata=metadata or None)
|
|
149
|
+
self.snapshot_id = snapshot.id
|
|
150
|
+
|
|
151
|
+
self._instance = instance
|
|
152
|
+
self._started_at = _now()
|
|
153
|
+
self._wait_until_ready(instance)
|
|
154
|
+
self._ensure_cwd(instance)
|
|
155
|
+
return instance
|
|
156
|
+
|
|
157
|
+
def _wait_until_ready(self, instance) -> None:
|
|
158
|
+
deadline = _now() + float(self.startup_timeout)
|
|
159
|
+
while True:
|
|
160
|
+
try:
|
|
161
|
+
instance.wait_until_ready()
|
|
162
|
+
break
|
|
163
|
+
except Exception as exc: # pragma: no cover - SDK may raise while polling
|
|
164
|
+
if _now() > deadline:
|
|
165
|
+
raise TimeoutError(f"Morph instance did not become ready within {self.startup_timeout}s") from exc
|
|
166
|
+
time.sleep(5.0)
|
|
167
|
+
|
|
168
|
+
def _ensure_cwd(self, instance) -> None:
|
|
169
|
+
if not self.cwd:
|
|
170
|
+
return
|
|
171
|
+
try:
|
|
172
|
+
instance.exec(f"bash -lc {shlex.quote(f'mkdir -p {self.cwd}')}")
|
|
173
|
+
except Exception as exc: # pragma: no cover - surface friendly error
|
|
174
|
+
raise RuntimeError(f"Failed to create remote workspace {self.cwd!r}: {exc}") from exc
|
|
175
|
+
|
|
176
|
+
def __del__(self) -> None: # pragma: no cover - defensive cleanup
|
|
177
|
+
with contextlib.suppress(Exception):
|
|
178
|
+
self.close()
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Image-Only Evaluation - Quick Reference
|
|
2
|
+
|
|
3
|
+
This document provides a quick reference for running image-only evaluations on **Crafter** and **Pokemon Red** with Turso tracing.
|
|
4
|
+
|
|
5
|
+
## 📚 Full Documentation
|
|
6
|
+
|
|
7
|
+
- **Crafter**: [`crafter/README_IMAGE_ONLY_EVAL.md`](crafter/README_IMAGE_ONLY_EVAL.md)
|
|
8
|
+
- **Pokemon Red**: [`pokemon_red/README_IMAGE_ONLY_EVAL.md`](pokemon_red/README_IMAGE_ONLY_EVAL.md)
|
|
9
|
+
|
|
10
|
+
## ⚡ Quick Start
|
|
11
|
+
|
|
12
|
+
### Prerequisites
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# 1. Set OpenAI API key in .env
|
|
16
|
+
echo "OPENAI_API_KEY=sk-proj-..." >> .env
|
|
17
|
+
|
|
18
|
+
# 2. Navigate to synth-ai repo
|
|
19
|
+
cd /path/to/synth-ai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Run Crafter (Easier - 70% Success Rate)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Set up tracing
|
|
26
|
+
export TASKAPP_TRACING_ENABLED=1
|
|
27
|
+
export TURSO_NATIVE=1
|
|
28
|
+
export SQLD_DB_PATH="traces/v3/crafter_eval.db"
|
|
29
|
+
|
|
30
|
+
# Run evaluation
|
|
31
|
+
uv run synth-ai eval grpo-crafter \
|
|
32
|
+
--config examples/task_apps/crafter/eval_image_only_gpt4o.toml
|
|
33
|
+
|
|
34
|
+
# Check results
|
|
35
|
+
sqlite3 -header -column traces/v3/crafter_eval.db \
|
|
36
|
+
"SELECT total_reward, achievements_count,
|
|
37
|
+
json_extract(reward_metadata, '$.final_achievements') as achievements
|
|
38
|
+
FROM outcome_rewards WHERE total_reward > 0;"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Run Pokemon Red (Harder - 0% with Default Config)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Set up tracing
|
|
45
|
+
export TASKAPP_TRACING_ENABLED=1
|
|
46
|
+
export TURSO_NATIVE=1
|
|
47
|
+
export SQLD_DB_PATH="traces/v3/pokemon_red_eval.db"
|
|
48
|
+
|
|
49
|
+
# Run evaluation
|
|
50
|
+
uv run synth-ai eval pokemon_red \
|
|
51
|
+
--config examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml
|
|
52
|
+
|
|
53
|
+
# Check results
|
|
54
|
+
sqlite3 -header -column traces/v3/pokemon_red_eval.db \
|
|
55
|
+
"SELECT total_reward, achievements_count,
|
|
56
|
+
json_extract(reward_metadata, '$.final_map') as map,
|
|
57
|
+
json_extract(reward_metadata, '$.party_count') as party
|
|
58
|
+
FROM outcome_rewards;"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 📊 Comparison
|
|
62
|
+
|
|
63
|
+
| Feature | Crafter | Pokemon Red |
|
|
64
|
+
|---------|---------|-------------|
|
|
65
|
+
| **Difficulty** | Easier | Harder |
|
|
66
|
+
| **Default success** | ~70% earn rewards | ~0% (needs tuning) |
|
|
67
|
+
| **Typical reward** | 1-3 achievements | 0 (10 steps too short) |
|
|
68
|
+
| **Best for** | Testing vision models | RL research |
|
|
69
|
+
| **Recommended steps** | 10 (default works) | 100-500 (need more) |
|
|
70
|
+
|
|
71
|
+
## 🔧 Configuration Files
|
|
72
|
+
|
|
73
|
+
### Crafter Config
|
|
74
|
+
**Location**: `examples/task_apps/crafter/eval_image_only_gpt4o.toml`
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[eval]
|
|
78
|
+
app_id = "grpo-crafter"
|
|
79
|
+
model = "gpt-4o-mini-2024-07-18"
|
|
80
|
+
seeds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
81
|
+
max_turns = 10
|
|
82
|
+
env_name = "crafter"
|
|
83
|
+
policy_name = "crafter-react"
|
|
84
|
+
|
|
85
|
+
[eval.policy_config]
|
|
86
|
+
use_vision = true
|
|
87
|
+
image_only_mode = true # Only images, no text
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Pokemon Red Config
|
|
91
|
+
**Location**: `examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml`
|
|
92
|
+
|
|
93
|
+
```toml
|
|
94
|
+
[eval]
|
|
95
|
+
app_id = "pokemon_red"
|
|
96
|
+
model = "gpt-4o-mini-2024-07-18"
|
|
97
|
+
seeds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
98
|
+
max_turns = 10
|
|
99
|
+
env_name = "pokemon_red"
|
|
100
|
+
|
|
101
|
+
[eval.policy_config]
|
|
102
|
+
use_vision = true
|
|
103
|
+
image_only_mode = true # Only images, no text
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 📈 Improving Pokemon Red Results
|
|
107
|
+
|
|
108
|
+
Pokemon Red is harder and needs more steps. To get non-zero rewards:
|
|
109
|
+
|
|
110
|
+
```toml
|
|
111
|
+
[eval]
|
|
112
|
+
model = "gpt-4o-2024-08-06" # Use full GPT-4o
|
|
113
|
+
max_turns = 100
|
|
114
|
+
|
|
115
|
+
[eval.env_config]
|
|
116
|
+
env_params = {max_steps_per_episode = 500}
|
|
117
|
+
|
|
118
|
+
[eval.policy_config]
|
|
119
|
+
model = "gpt-4o-2024-08-06"
|
|
120
|
+
image_only_mode = false # Enable text too (multimodal)
|
|
121
|
+
max_llm_calls = 100
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 🗄️ Database Queries
|
|
125
|
+
|
|
126
|
+
### Get All Rewards
|
|
127
|
+
|
|
128
|
+
```sql
|
|
129
|
+
-- Crafter
|
|
130
|
+
SELECT
|
|
131
|
+
json_extract(reward_metadata, '$.env_seed') as seed,
|
|
132
|
+
total_reward,
|
|
133
|
+
achievements_count,
|
|
134
|
+
json_extract(reward_metadata, '$.final_achievements') as achievements
|
|
135
|
+
FROM outcome_rewards
|
|
136
|
+
ORDER BY total_reward DESC;
|
|
137
|
+
|
|
138
|
+
-- Pokemon Red
|
|
139
|
+
SELECT
|
|
140
|
+
session_id,
|
|
141
|
+
total_reward,
|
|
142
|
+
achievements_count,
|
|
143
|
+
json_extract(reward_metadata, '$.final_map') as map,
|
|
144
|
+
json_extract(reward_metadata, '$.party_count') as party
|
|
145
|
+
FROM outcome_rewards
|
|
146
|
+
ORDER BY total_reward DESC;
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Filter Non-Zero Rewards
|
|
150
|
+
|
|
151
|
+
```sql
|
|
152
|
+
SELECT * FROM outcome_rewards WHERE total_reward > 0;
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Get Statistics
|
|
156
|
+
|
|
157
|
+
```sql
|
|
158
|
+
SELECT
|
|
159
|
+
COUNT(*) as total,
|
|
160
|
+
SUM(CASE WHEN total_reward > 0 THEN 1 ELSE 0 END) as with_rewards,
|
|
161
|
+
AVG(total_reward) as avg_reward,
|
|
162
|
+
MAX(total_reward) as max_reward
|
|
163
|
+
FROM outcome_rewards;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 🎯 What is Image-Only Mode?
|
|
167
|
+
|
|
168
|
+
**Image-Only Mode** means:
|
|
169
|
+
- ✅ Agent receives **only** base64-encoded PNG images
|
|
170
|
+
- ❌ Agent receives **no** text observations (HP, position, inventory, etc.)
|
|
171
|
+
- 🎓 Tests pure vision understanding
|
|
172
|
+
|
|
173
|
+
**Multimodal Mode** (recommended for Pokemon Red):
|
|
174
|
+
- ✅ Agent receives **both** images and text
|
|
175
|
+
- 🏆 Better performance but "easier"
|
|
176
|
+
|
|
177
|
+
Toggle with:
|
|
178
|
+
```toml
|
|
179
|
+
[eval.policy_config]
|
|
180
|
+
use_vision = true # Enable vision
|
|
181
|
+
image_only_mode = false # false = send text too
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 📁 Files Created
|
|
185
|
+
|
|
186
|
+
### Crafter
|
|
187
|
+
- `crafter/eval_image_only_gpt4o.toml` - Config
|
|
188
|
+
- `crafter/README_IMAGE_ONLY_EVAL.md` - Full guide
|
|
189
|
+
- `crafter/EVAL_IMAGE_ONLY_RESULTS.md` - Example results
|
|
190
|
+
- `crafter/QUERY_EXAMPLES.md` - SQL queries
|
|
191
|
+
|
|
192
|
+
### Pokemon Red
|
|
193
|
+
- `pokemon_red/eval_image_only_gpt4o.toml` - Config
|
|
194
|
+
- `pokemon_red/README_IMAGE_ONLY_EVAL.md` - Full guide
|
|
195
|
+
- `pokemon_red/EVAL_IMAGE_ONLY_COMPLETE.md` - Implementation
|
|
196
|
+
- `pokemon_red/EVAL_IMAGE_ONLY_STATUS.md` - Status
|
|
197
|
+
|
|
198
|
+
## 🐛 Common Issues
|
|
199
|
+
|
|
200
|
+
### Database Not Created
|
|
201
|
+
```bash
|
|
202
|
+
# Ensure variables are set
|
|
203
|
+
export TASKAPP_TRACING_ENABLED=1
|
|
204
|
+
export TURSO_NATIVE=1
|
|
205
|
+
export SQLD_DB_PATH="traces/v3/your_eval.db"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 401 Unauthorized
|
|
209
|
+
```bash
|
|
210
|
+
# Check API key in .env
|
|
211
|
+
cat .env | grep OPENAI_API_KEY
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Pokemon Red: ROM Not Found
|
|
215
|
+
```bash
|
|
216
|
+
# Place ROM at expected location
|
|
217
|
+
cp pokemon_red.gb synth_ai/environments/examples/red/roms/
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### All Rewards Zero
|
|
221
|
+
- **Crafter**: Should get ~70% non-zero by default
|
|
222
|
+
- **Pokemon Red**: Expected with 10 steps - increase to 100-500
|
|
223
|
+
|
|
224
|
+
## 🎓 Understanding Results
|
|
225
|
+
|
|
226
|
+
### Crafter Achievements
|
|
227
|
+
- `collect_wood` - Cut down trees
|
|
228
|
+
- `collect_sapling` - Collect tree saplings
|
|
229
|
+
- `collect_drink` - Drink from water
|
|
230
|
+
|
|
231
|
+
### Pokemon Red Milestones
|
|
232
|
+
- Leave bedroom (+20)
|
|
233
|
+
- Exit house (+30)
|
|
234
|
+
- Find Oak's lab (+40)
|
|
235
|
+
- Get starter Pokemon (+100)
|
|
236
|
+
- Win first battle (+150)
|
|
237
|
+
|
|
238
|
+
**Total possible**: ~600 points
|
|
239
|
+
|
|
240
|
+
## 🚀 Next Steps
|
|
241
|
+
|
|
242
|
+
1. **Read full docs**: See task-specific READMEs for details
|
|
243
|
+
2. **Run evaluations**: Start with Crafter (easier)
|
|
244
|
+
3. **Query database**: Use SQL to analyze results
|
|
245
|
+
4. **Tune configs**: Adjust steps/model for better performance
|
|
246
|
+
5. **Compare modes**: Try image-only vs multimodal
|
|
247
|
+
|
|
248
|
+
## 📞 Support
|
|
249
|
+
|
|
250
|
+
For issues or questions:
|
|
251
|
+
1. Check full README for your task app
|
|
252
|
+
2. Review example results files
|
|
253
|
+
3. Query database to verify data
|
|
254
|
+
4. Adjust config parameters
|
|
255
|
+
|
|
256
|
+
Happy evaluating! 🎮
|
|
257
|
+
|
|
258
|
+
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Task App Testing Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to run tests for the task apps in this directory.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Each task app has unit and integration tests following a consistent pattern inspired by the customer environment tests in `customers/`.
|
|
8
|
+
|
|
9
|
+
## Test Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
examples/task_apps/<app_name>/tests/
|
|
13
|
+
├── __init__.py
|
|
14
|
+
├── integration/
|
|
15
|
+
│ ├── __init__.py
|
|
16
|
+
│ └── test_<app>_eval.py # Server startup + eval tests
|
|
17
|
+
└── unit/
|
|
18
|
+
├── __init__.py
|
|
19
|
+
└── test_<app>_*.py # Environment, scoring, dataset tests
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Running Tests
|
|
23
|
+
|
|
24
|
+
### Prerequisites
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install test dependencies
|
|
28
|
+
uv sync --dev
|
|
29
|
+
|
|
30
|
+
# Set required environment variables
|
|
31
|
+
export GROQ_API_KEY="your-groq-key"
|
|
32
|
+
export OPENAI_API_KEY="your-openai-key" # For Sokoban
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Run All Tests for a Task App
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Verilog
|
|
39
|
+
pytest examples/task_apps/verilog/tests/ -v
|
|
40
|
+
|
|
41
|
+
# Enron
|
|
42
|
+
pytest examples/task_apps/enron/tests/ -v
|
|
43
|
+
|
|
44
|
+
# Sokoban
|
|
45
|
+
pytest examples/task_apps/sokoban/tests/ -v
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Run Only Unit Tests (Fast)
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Runs quickly, no server startup required
|
|
52
|
+
pytest examples/task_apps/verilog/tests/unit/ -v
|
|
53
|
+
pytest examples/task_apps/enron/tests/unit/ -v
|
|
54
|
+
pytest examples/task_apps/sokoban/tests/unit/ -v
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Run Only Integration Tests
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Slower, starts servers and runs evals
|
|
61
|
+
pytest examples/task_apps/verilog/tests/integration/ -v
|
|
62
|
+
pytest examples/task_apps/enron/tests/integration/ -v
|
|
63
|
+
pytest examples/task_apps/sokoban/tests/integration/ -v
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Run All Task App Tests
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Run everything
|
|
70
|
+
pytest examples/task_apps/*/tests/ -v
|
|
71
|
+
|
|
72
|
+
# Skip slow tests
|
|
73
|
+
pytest examples/task_apps/*/tests/ -v -m "not slow"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Test Categories
|
|
77
|
+
|
|
78
|
+
### Unit Tests
|
|
79
|
+
|
|
80
|
+
**Purpose**: Test individual components in isolation
|
|
81
|
+
- Environment initialization
|
|
82
|
+
- Reward calculation
|
|
83
|
+
- Tool implementations
|
|
84
|
+
- State management
|
|
85
|
+
|
|
86
|
+
**Characteristics**:
|
|
87
|
+
- Fast (< 1 second each)
|
|
88
|
+
- No external dependencies
|
|
89
|
+
- No server startup
|
|
90
|
+
- No API calls
|
|
91
|
+
|
|
92
|
+
**Examples**:
|
|
93
|
+
- `test_verilog_scoring.py`: Tests reward components (compile, simulate, submit)
|
|
94
|
+
- `test_enron_environment.py`: Tests search, answer, reward calculation
|
|
95
|
+
- `test_sokoban_environment.py`: Tests actions, rewards, truncation
|
|
96
|
+
|
|
97
|
+
### Integration Tests
|
|
98
|
+
|
|
99
|
+
**Purpose**: Test the full system end-to-end
|
|
100
|
+
- Server startup
|
|
101
|
+
- Health/info endpoints
|
|
102
|
+
- Full evaluation runs
|
|
103
|
+
- **Rollout execution** (manual and policy-driven)
|
|
104
|
+
|
|
105
|
+
**Characteristics**:
|
|
106
|
+
- Slower (30-300 seconds)
|
|
107
|
+
- Requires server startup
|
|
108
|
+
- May require API keys
|
|
109
|
+
- Tests real workflows
|
|
110
|
+
|
|
111
|
+
**Examples**:
|
|
112
|
+
- `test_verilog_eval.py`: Starts server, runs Groq eval with Qwen3-32B
|
|
113
|
+
- `test_verilog_rollout.py`: **Manual & policy rollouts via /rollout endpoint**
|
|
114
|
+
- `test_enron_eval.py`: Starts server, runs Groq eval
|
|
115
|
+
- `test_enron_rollout.py`: **Manual & policy rollouts, auth testing**
|
|
116
|
+
- `test_sokoban_eval.py`: Starts server, tests manual rollout
|
|
117
|
+
- `test_sokoban_rollout.py`: **6 rollout tests (manual, policy, difficulties, limits)**
|
|
118
|
+
|
|
119
|
+
## What Each Test Validates
|
|
120
|
+
|
|
121
|
+
### Verilog Tests
|
|
122
|
+
|
|
123
|
+
**Unit Tests** (4 tests):
|
|
124
|
+
- ✅ Compile success gives +0.1 reward
|
|
125
|
+
- ✅ Simulation pass gives +1.0 reward
|
|
126
|
+
- ✅ Submit success gives +10.0 reward
|
|
127
|
+
- ✅ Submit checks last simulation output correctly
|
|
128
|
+
|
|
129
|
+
**Integration Tests** (5 tests):
|
|
130
|
+
- ✅ Server starts and responds to /health
|
|
131
|
+
- ✅ /task_info returns valid Verilog task metadata
|
|
132
|
+
- ✅ Full eval with Qwen3-32B completes successfully
|
|
133
|
+
- ✅ **Manual rollout** with explicit write/compile/simulate/submit
|
|
134
|
+
- ✅ **Policy rollout** using Groq/Qwen3-32B (verifies LLM integration)
|
|
135
|
+
|
|
136
|
+
### Enron Tests
|
|
137
|
+
|
|
138
|
+
**Unit Tests** (3 tests):
|
|
139
|
+
- ✅ search_emails tool works correctly
|
|
140
|
+
- ✅ answer_question tool calculates rewards
|
|
141
|
+
- ✅ Exact answer match gives high reward (>0.9)
|
|
142
|
+
- ✅ Partial answer match gives medium reward (>0.5)
|
|
143
|
+
- ✅ Wrong answer gives low reward (<0.5)
|
|
144
|
+
|
|
145
|
+
**Integration Tests** (6 tests):
|
|
146
|
+
- ✅ Server starts and responds to /health
|
|
147
|
+
- ✅ /task_info returns valid Enron task metadata
|
|
148
|
+
- ✅ Full eval with Qwen3-32B completes successfully
|
|
149
|
+
- ✅ **Manual rollout** with explicit search/read/answer actions
|
|
150
|
+
- ✅ **Policy rollout** using Groq/Qwen3-32B
|
|
151
|
+
- ✅ **Authentication** enforcement (rejects requests without auth header)
|
|
152
|
+
|
|
153
|
+
### Sokoban Tests
|
|
154
|
+
|
|
155
|
+
**Unit Tests** (3 tests):
|
|
156
|
+
- ✅ Module imports work correctly
|
|
157
|
+
- ✅ Reward components exist (goal achieved, step penalty)
|
|
158
|
+
- ✅ Engine creation with different difficulty levels
|
|
159
|
+
|
|
160
|
+
**Integration Tests** (9 tests):
|
|
161
|
+
- ✅ Server starts and responds to /health
|
|
162
|
+
- ✅ /task_info returns valid Sokoban task metadata
|
|
163
|
+
- ✅ **Manual rollout** with movement actions (left/right/up/down)
|
|
164
|
+
- ✅ **Policy rollout** with OpenAI GPT-5-mini (may skip if slow)
|
|
165
|
+
- ✅ **All difficulty levels** (easy/medium/hard) work correctly
|
|
166
|
+
- ✅ **Max steps limit** enforcement (stops at configured limit)
|
|
167
|
+
- ✅ **Puzzle completion detection** (terminated=True when solved)
|
|
168
|
+
- ✅ Truncation on max_steps
|
|
169
|
+
- ✅ Response structure validation
|
|
170
|
+
|
|
171
|
+
## Debugging Test Failures
|
|
172
|
+
|
|
173
|
+
### Server Won't Start
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Check if port is already in use
|
|
177
|
+
lsof -i :<port>
|
|
178
|
+
|
|
179
|
+
# Check logs manually
|
|
180
|
+
uv run -m synth_ai task-app serve <app_name> --port 8999
|
|
181
|
+
|
|
182
|
+
# Check environment variables
|
|
183
|
+
echo $GROQ_API_KEY
|
|
184
|
+
echo $OPENAI_API_KEY
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Tests Timeout
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Run with more verbose output
|
|
191
|
+
pytest <test_file> -v -s
|
|
192
|
+
|
|
193
|
+
# Skip slow tests
|
|
194
|
+
pytest <test_file> -v --timeout=60
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Import Errors
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Ensure you're in the right directory
|
|
201
|
+
cd /path/to/synth-ai
|
|
202
|
+
|
|
203
|
+
# Reinstall dependencies
|
|
204
|
+
uv sync --dev
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## CI/CD Integration
|
|
208
|
+
|
|
209
|
+
These tests can be run in CI with:
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
# .github/workflows/test-task-apps.yml
|
|
213
|
+
- name: Run task app tests
|
|
214
|
+
env:
|
|
215
|
+
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
|
216
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
217
|
+
run: |
|
|
218
|
+
# Unit tests (fast, always run)
|
|
219
|
+
pytest examples/task_apps/*/tests/unit/ -v
|
|
220
|
+
|
|
221
|
+
# Integration tests (slower, only on main)
|
|
222
|
+
if [ "$GITHUB_REF" = "refs/heads/main" ]; then
|
|
223
|
+
pytest examples/task_apps/*/tests/integration/ -v --timeout=300
|
|
224
|
+
fi
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Adding Tests for New Task Apps
|
|
228
|
+
|
|
229
|
+
When creating a new task app, follow this pattern:
|
|
230
|
+
|
|
231
|
+
1. **Create test structure**:
|
|
232
|
+
```bash
|
|
233
|
+
mkdir -p examples/task_apps/<new_app>/tests/{unit,integration}
|
|
234
|
+
touch examples/task_apps/<new_app>/tests/__init__.py
|
|
235
|
+
touch examples/task_apps/<new_app>/tests/unit/__init__.py
|
|
236
|
+
touch examples/task_apps/<new_app>/tests/integration/__init__.py
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
2. **Create unit tests** (`tests/unit/test_<app>_*.py`):
|
|
240
|
+
- Test environment initialization
|
|
241
|
+
- Test reward calculation
|
|
242
|
+
- Test tool implementations
|
|
243
|
+
- Test edge cases
|
|
244
|
+
|
|
245
|
+
3. **Create integration tests** (`tests/integration/test_<app>_eval.py`):
|
|
246
|
+
- Copy from an existing integration test
|
|
247
|
+
- Update app name, port, config path
|
|
248
|
+
- Add app-specific endpoint tests
|
|
249
|
+
|
|
250
|
+
4. **Add to CI**:
|
|
251
|
+
- Update CI config to include new tests
|
|
252
|
+
- Ensure required env vars are set
|
|
253
|
+
|
|
254
|
+
## Test Coverage Goals
|
|
255
|
+
|
|
256
|
+
- Unit test coverage: >80%
|
|
257
|
+
- Integration test coverage: 100% of critical paths
|
|
258
|
+
- All public APIs have at least one integration test
|
|
259
|
+
- All reward components have unit tests
|
|
260
|
+
|
|
261
|
+
## Common Issues
|
|
262
|
+
|
|
263
|
+
### "Task app terminated immediately"
|
|
264
|
+
- Check that the app name is correct
|
|
265
|
+
- Verify the app is registered in `synth_ai/task/apps.py`
|
|
266
|
+
- Check recent changes to the app code
|
|
267
|
+
|
|
268
|
+
### "GROQ_API_KEY must be set"
|
|
269
|
+
- Set the environment variable
|
|
270
|
+
- Or skip the test: `pytest -k "not groq"`
|
|
271
|
+
|
|
272
|
+
### "Config file not found"
|
|
273
|
+
- Ensure eval config exists in task app directory
|
|
274
|
+
- Check the path in the test matches actual location
|
|
275
|
+
|