synth-ai 0.2.9.dev5__py3-none-any.whl → 0.2.9.dev6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +23 -17
- 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/configs/eval_base_qwen.toml +1 -1
- examples/rl/configs/rl_from_base_qwen17.toml +1 -1
- examples/rl/download_dataset.py +26 -10
- examples/rl/run_eval.py +53 -52
- examples/rl/run_rl_and_save.py +29 -12
- examples/rl/task_app/math_single_step.py +180 -41
- examples/rl/task_app/math_task_app.py +14 -6
- 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 +12 -10
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +11 -1
- examples/warming_up_to_rl/export_trace_sft.py +218 -36
- examples/warming_up_to_rl/groq_test.py +15 -8
- examples/warming_up_to_rl/manage_secrets.py +29 -25
- examples/warming_up_to_rl/readme.md +9 -2
- examples/warming_up_to_rl/run_eval.py +137 -61
- examples/warming_up_to_rl/run_fft_and_save.py +131 -60
- examples/warming_up_to_rl/run_local_rollout.py +88 -39
- examples/warming_up_to_rl/run_local_rollout_modal.py +114 -28
- examples/warming_up_to_rl/run_local_rollout_parallel.py +81 -20
- examples/warming_up_to_rl/run_local_rollout_traced.py +126 -23
- examples/warming_up_to_rl/run_rl_and_save.py +35 -12
- examples/warming_up_to_rl/run_rollout_remote.py +44 -19
- examples/warming_up_to_rl/task_app/README.md +6 -2
- examples/warming_up_to_rl/task_app/grpo_crafter.py +319 -57
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +11 -30
- 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 +137 -182
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/app.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +150 -57
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +105 -69
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +19 -7
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +45 -42
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/tools.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +47 -45
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +198 -92
- 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 +361 -263
- 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 +394 -274
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +56 -62
- 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 +6 -15
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +4 -3
- synth/__init__.py +14 -0
- synth_ai/__init__.py +20 -4
- synth_ai/api/models/supported.py +376 -0
- synth_ai/api/train/builders.py +157 -26
- synth_ai/api/train/cli.py +213 -57
- synth_ai/api/train/config_finder.py +65 -5
- synth_ai/api/train/env_resolver.py +33 -15
- synth_ai/api/train/pollers.py +13 -4
- synth_ai/api/train/supported_algos.py +139 -0
- synth_ai/api/train/task_app.py +5 -3
- synth_ai/api/train/utils.py +33 -48
- synth_ai/cli/__init__.py +19 -4
- synth_ai/cli/_modal_wrapper.py +28 -0
- synth_ai/cli/_typer_patch.py +49 -0
- synth_ai/cli/balance.py +2 -3
- synth_ai/cli/calc.py +1 -1
- synth_ai/cli/demo.py +21 -6
- synth_ai/cli/recent.py +2 -2
- synth_ai/cli/rl_demo.py +77 -17
- synth_ai/cli/root.py +116 -39
- synth_ai/cli/status.py +2 -2
- synth_ai/cli/task_apps.py +1699 -259
- synth_ai/cli/traces.py +7 -4
- synth_ai/cli/turso.py +73 -0
- synth_ai/cli/watch.py +12 -18
- synth_ai/core/experiment.py +0 -2
- synth_ai/demo_registry.py +68 -31
- synth_ai/demos/core/cli.py +516 -194
- 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/configs/crafter_fft_4b.toml +2 -3
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +37 -30
- 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 +183 -82
- synth_ai/demos/demo_task_apps/math/task_app_entry.py +0 -2
- synth_ai/environments/examples/bandit/engine.py +12 -4
- synth_ai/environments/examples/bandit/taskset.py +4 -4
- synth_ai/environments/examples/crafter_classic/environment.py +76 -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/base.py +0 -2
- synth_ai/handshake.py +11 -9
- synth_ai/http.py +1 -1
- synth_ai/http_client.py +43 -11
- synth_ai/inference/__init__.py +0 -2
- synth_ai/inference/client.py +20 -6
- synth_ai/jobs/client.py +103 -78
- synth_ai/learning/__init__.py +41 -6
- synth_ai/learning/algorithms.py +14 -0
- synth_ai/learning/client.py +121 -29
- 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 +13 -7
- synth_ai/learning/jobs.py +43 -47
- synth_ai/{rl → learning/rl}/__init__.py +14 -5
- synth_ai/learning/rl/client.py +267 -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 +295 -0
- synth_ai/learning/sse.py +25 -26
- synth_ai/learning/validators.py +25 -24
- synth_ai/lm/__init__.py +21 -47
- synth_ai/task/__init__.py +26 -27
- synth_ai/task/apps/__init__.py +18 -19
- synth_ai/task/auth.py +35 -23
- synth_ai/task/client.py +15 -13
- synth_ai/task/contracts.py +37 -35
- synth_ai/task/datasets.py +9 -6
- synth_ai/task/errors.py +11 -10
- synth_ai/task/health.py +17 -11
- synth_ai/task/json.py +58 -24
- synth_ai/task/proxy.py +15 -14
- synth_ai/task/rubrics.py +22 -15
- synth_ai/task/server.py +43 -17
- synth_ai/task/tracing_utils.py +12 -7
- synth_ai/task/validators.py +0 -1
- synth_ai/task/vendors.py +5 -7
- synth_ai/tracing_v3/__init__.py +2 -0
- synth_ai/tracing_v3/abstractions.py +21 -4
- synth_ai/tracing_v3/db_config.py +26 -1
- synth_ai/tracing_v3/decorators.py +18 -15
- synth_ai/tracing_v3/examples/basic_usage.py +3 -2
- synth_ai/tracing_v3/hooks.py +6 -4
- synth_ai/tracing_v3/llm_call_record_helpers.py +6 -6
- synth_ai/tracing_v3/replica_sync.py +1 -0
- synth_ai/tracing_v3/session_tracer.py +63 -16
- synth_ai/tracing_v3/storage/base.py +89 -1
- synth_ai/tracing_v3/storage/config.py +21 -8
- synth_ai/tracing_v3/storage/factory.py +10 -8
- 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 +5 -2
- synth_ai/tracing_v3/turso/native_manager.py +1173 -0
- synth_ai/tracing_v3/utils.py +4 -3
- 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 +3 -5
- 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/exceptions.py +0 -2
- synth_ai/{lm → v0/lm}/core/main.py +19 -7
- synth_ai/{lm → v0/lm}/core/main_v3.py +10 -10
- synth_ai/{lm → v0/lm}/core/synth_models.py +2 -15
- synth_ai/{lm → v0/lm}/core/vendor_clients.py +6 -4
- synth_ai/{lm → v0/lm}/overrides.py +4 -4
- 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 +16 -16
- 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 +12 -10
- synth_ai/{lm → v0/lm}/vendors/openai_standard.py +11 -9
- synth_ai/{lm → v0/lm}/vendors/openai_standard_responses.py +8 -5
- synth_ai/{lm → v0/lm}/vendors/supported/custom_endpoint.py +4 -6
- 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 +38 -11
- synth_ai/v0/tracing/upload.py +32 -135
- 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.dev6.dist-info/METADATA +191 -0
- {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.9.dev6.dist-info}/RECORD +291 -262
- {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.9.dev6.dist-info}/top_level.txt +1 -0
- examples/common_old/backend.py +0 -21
- examples/evals_old/README.md +0 -98
- examples/evals_old/__init__.py +0 -6
- examples/evals_old/compare_models.py +0 -1037
- 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 -239
- 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 -118
- 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 -239
- 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 -37
- examples/finetuning_old/synth_qwen_v1/poll.py +0 -44
- 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 -1932
- examples/finetuning_old/synth_qwen_v1/run_crafter_sft_job.py +0 -207
- examples/finetuning_old/synth_qwen_v1/run_ft_job.py +0 -232
- examples/finetuning_old/synth_qwen_v1/upload_data.py +0 -34
- examples/finetuning_old/synth_qwen_v1/util.py +0 -147
- examples/rl_old/task_app.py +0 -962
- 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 -446
- synth_ai/install_sqld.sh +0 -40
- 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 -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/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 -774
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.9.dev5.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}/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.dev5.dist-info → synth_ai-0.2.9.dev6.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.9.dev6.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.9.dev6.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,12 +6,13 @@ import json
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
import time
|
|
9
|
+
import tomllib
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import Any
|
|
11
|
+
from typing import Any
|
|
11
12
|
|
|
12
|
-
import tomllib
|
|
13
|
-
import re
|
|
14
13
|
import requests
|
|
14
|
+
from dotenv import load_dotenv
|
|
15
|
+
from synth_ai.config.base_url import PROD_BASE_URL_DEFAULT
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def mask(val: str) -> str:
|
|
@@ -20,7 +21,9 @@ def mask(val: str) -> str:
|
|
|
20
21
|
return f"{val[:6]}…{val[-4:]}" if len(val) >= 10 else "****"
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def post_multipart(
|
|
24
|
+
def post_multipart(
|
|
25
|
+
base: str, api_key: str, path: str, file_field: str, filepath: Path
|
|
26
|
+
) -> dict[str, Any]:
|
|
24
27
|
"""Upload a file, trying backend-specific endpoints with fallbacks.
|
|
25
28
|
|
|
26
29
|
Priority:
|
|
@@ -33,9 +36,9 @@ def post_multipart(base: str, api_key: str, path: str, file_field: str, filepath
|
|
|
33
36
|
|
|
34
37
|
endpoints = [
|
|
35
38
|
f"{base.rstrip('/')}/{path.lstrip('/')}", # e.g., /learning/files
|
|
36
|
-
f"{base.rstrip('/')}/files",
|
|
39
|
+
f"{base.rstrip('/')}/files", # OpenAI-style
|
|
37
40
|
]
|
|
38
|
-
last_err:
|
|
41
|
+
last_err: dict[str, Any] | None = None
|
|
39
42
|
for ep in endpoints:
|
|
40
43
|
try:
|
|
41
44
|
r = requests.post(ep, headers=headers, files=files, data=data, timeout=300)
|
|
@@ -67,7 +70,7 @@ def post_multipart(base: str, api_key: str, path: str, file_field: str, filepath
|
|
|
67
70
|
return last_err or {"error": True, "detail": "upload_failed_all_endpoints"}
|
|
68
71
|
|
|
69
72
|
|
|
70
|
-
def post_json(base: str, api_key: str, path: str, body:
|
|
73
|
+
def post_json(base: str, api_key: str, path: str, body: dict[str, Any]) -> dict[str, Any]:
|
|
71
74
|
url = f"{base.rstrip('/')}/{path.lstrip('/')}"
|
|
72
75
|
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
|
|
73
76
|
r = requests.post(url, headers=headers, data=json.dumps(body), timeout=120)
|
|
@@ -77,7 +80,7 @@ def post_json(base: str, api_key: str, path: str, body: Dict[str, Any]) -> Dict[
|
|
|
77
80
|
return {"status": r.status_code, "text": r.text[:400]}
|
|
78
81
|
|
|
79
82
|
|
|
80
|
-
def get_json(base: str, api_key: str, path: str) ->
|
|
83
|
+
def get_json(base: str, api_key: str, path: str) -> dict[str, Any]:
|
|
81
84
|
url = f"{base.rstrip('/')}/{path.lstrip('/')}"
|
|
82
85
|
headers = {"Authorization": f"Bearer {api_key}"}
|
|
83
86
|
r = requests.get(url, headers=headers, timeout=30)
|
|
@@ -87,17 +90,94 @@ def get_json(base: str, api_key: str, path: str) -> Dict[str, Any]:
|
|
|
87
90
|
return {"status": r.status_code, "text": r.text[:400]}
|
|
88
91
|
|
|
89
92
|
|
|
93
|
+
def _find_fft_configs() -> list[Path]:
|
|
94
|
+
"""Find FFT TOML configs in standard locations."""
|
|
95
|
+
candidates: list[Path] = []
|
|
96
|
+
|
|
97
|
+
# Check current directory configs/
|
|
98
|
+
cwd = Path.cwd()
|
|
99
|
+
configs_dir = cwd / "configs"
|
|
100
|
+
if configs_dir.is_dir():
|
|
101
|
+
for f in configs_dir.glob("*.toml"):
|
|
102
|
+
# Look for FFT configs (check if they have [algorithm] method = "supervised_finetune")
|
|
103
|
+
try:
|
|
104
|
+
content = f.read_text()
|
|
105
|
+
if "supervised_finetune" in content or "fft" in content.lower():
|
|
106
|
+
candidates.append(f)
|
|
107
|
+
except Exception:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
# Also check for any .toml files in current directory
|
|
111
|
+
for f in cwd.glob("*.toml"):
|
|
112
|
+
if f not in candidates:
|
|
113
|
+
try:
|
|
114
|
+
content = f.read_text()
|
|
115
|
+
if "supervised_finetune" in content or "fft" in content.lower():
|
|
116
|
+
candidates.append(f)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
return sorted(candidates)
|
|
121
|
+
|
|
122
|
+
|
|
90
123
|
def main() -> None:
|
|
124
|
+
# Load .env file from current directory first if it exists
|
|
125
|
+
default_env = Path.cwd() / ".env"
|
|
126
|
+
if default_env.exists():
|
|
127
|
+
load_dotenv(default_env, override=False)
|
|
128
|
+
|
|
91
129
|
parser = argparse.ArgumentParser(description="Submit FFT job and save resulting model id")
|
|
92
|
-
parser.add_argument(
|
|
93
|
-
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--backend", default=os.getenv("BACKEND_BASE_URL", f"{PROD_BASE_URL_DEFAULT}/api")
|
|
132
|
+
)
|
|
133
|
+
parser.add_argument("--toml", required=False, help="Path to FFT TOML config")
|
|
94
134
|
parser.add_argument("--data", default="", help="Override dataset JSONL path")
|
|
95
135
|
parser.add_argument("--poll-seconds", type=int, default=1800)
|
|
96
|
-
parser.add_argument(
|
|
136
|
+
parser.add_argument(
|
|
137
|
+
"--env-file", default="", help="Optional path to .env file with SYNTH_API_KEY"
|
|
138
|
+
)
|
|
97
139
|
args = parser.parse_args()
|
|
98
140
|
|
|
99
|
-
|
|
100
|
-
if
|
|
141
|
+
# Also load from explicit --env-file if provided
|
|
142
|
+
if args.env_file:
|
|
143
|
+
env_path = Path(args.env_file).expanduser()
|
|
144
|
+
if not env_path.exists():
|
|
145
|
+
print(f"[WARN] Env file not found: {env_path}")
|
|
146
|
+
else:
|
|
147
|
+
load_dotenv(env_path, override=False)
|
|
148
|
+
|
|
149
|
+
# Auto-discover TOML config if not specified
|
|
150
|
+
config_path: Path | None = None
|
|
151
|
+
if args.toml:
|
|
152
|
+
config_path = Path(args.toml).expanduser().resolve()
|
|
153
|
+
else:
|
|
154
|
+
configs = _find_fft_configs()
|
|
155
|
+
if not configs:
|
|
156
|
+
print(
|
|
157
|
+
"No FFT config files found. Please specify --toml or create a config in configs/",
|
|
158
|
+
file=sys.stderr,
|
|
159
|
+
)
|
|
160
|
+
sys.exit(2)
|
|
161
|
+
elif len(configs) == 1:
|
|
162
|
+
config_path = configs[0]
|
|
163
|
+
print(f"Using FFT config: {config_path}")
|
|
164
|
+
else:
|
|
165
|
+
print("\nFound multiple FFT configs:")
|
|
166
|
+
for idx, cfg in enumerate(configs, 1):
|
|
167
|
+
print(f" [{idx}] {cfg}")
|
|
168
|
+
choice = input(f"Select config [1-{len(configs)}]: ").strip()
|
|
169
|
+
try:
|
|
170
|
+
selected_idx = int(choice) - 1
|
|
171
|
+
if 0 <= selected_idx < len(configs):
|
|
172
|
+
config_path = configs[selected_idx]
|
|
173
|
+
else:
|
|
174
|
+
print("Invalid selection", file=sys.stderr)
|
|
175
|
+
sys.exit(2)
|
|
176
|
+
except ValueError:
|
|
177
|
+
print("Invalid input", file=sys.stderr)
|
|
178
|
+
sys.exit(2)
|
|
179
|
+
|
|
180
|
+
if not config_path or not config_path.exists():
|
|
101
181
|
print(f"Config not found: {config_path}", file=sys.stderr)
|
|
102
182
|
sys.exit(2)
|
|
103
183
|
with config_path.open("rb") as fh:
|
|
@@ -107,7 +187,9 @@ def main() -> None:
|
|
|
107
187
|
compute_cfg = cfg.get("compute", {}) if isinstance(cfg.get("compute"), dict) else {}
|
|
108
188
|
data_cfg_full = cfg.get("data", {}) if isinstance(cfg.get("data"), dict) else {}
|
|
109
189
|
topo_cfg = (data_cfg_full or {}).get("topology", {}) if isinstance(data_cfg_full, dict) else {}
|
|
110
|
-
validation_local_path = (
|
|
190
|
+
validation_local_path = (
|
|
191
|
+
(data_cfg_full or {}).get("validation_path") if isinstance(data_cfg_full, dict) else None
|
|
192
|
+
)
|
|
111
193
|
train_cfg = cfg.get("training", {}) if isinstance(cfg.get("training"), dict) else {}
|
|
112
194
|
hp_cfg = cfg.get("hyperparameters", {}) if isinstance(cfg.get("hyperparameters"), dict) else {}
|
|
113
195
|
|
|
@@ -119,7 +201,10 @@ def main() -> None:
|
|
|
119
201
|
if isinstance(data_path, str) and data_path.strip():
|
|
120
202
|
p = Path(data_path).expanduser()
|
|
121
203
|
if not p.is_absolute():
|
|
122
|
-
|
|
204
|
+
# Try relative to cwd first, then relative to config directory
|
|
205
|
+
cwd_relative = Path.cwd() / p
|
|
206
|
+
config_relative = config_path.parent / p
|
|
207
|
+
p = cwd_relative.resolve() if cwd_relative.exists() else config_relative.resolve()
|
|
123
208
|
data_file = p
|
|
124
209
|
if data_file is None:
|
|
125
210
|
print("Missing dataset path in --data or [job].data", file=sys.stderr)
|
|
@@ -129,38 +214,11 @@ def main() -> None:
|
|
|
129
214
|
sys.exit(2)
|
|
130
215
|
|
|
131
216
|
synth_key = (os.getenv("SYNTH_API_KEY") or "").strip()
|
|
132
|
-
# Fallback: try to load from .env if not present in environment
|
|
133
217
|
if not synth_key:
|
|
134
|
-
|
|
135
|
-
if
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# Prefer .env next to the TOML config
|
|
139
|
-
candidate_env = (config_path.parent / ".env").resolve()
|
|
140
|
-
if candidate_env and candidate_env.exists():
|
|
141
|
-
try:
|
|
142
|
-
env_text = candidate_env.read_text(encoding="utf-8", errors="ignore")
|
|
143
|
-
# Match lines like: SYNTH_API_KEY=..., or export SYNTH_API_KEY=...
|
|
144
|
-
key_val: str | None = None
|
|
145
|
-
for line in env_text.splitlines():
|
|
146
|
-
m = re.match(r"^\s*(?:export\s+)?SYNTH_API_KEY\s*=\s*(.*)$", line)
|
|
147
|
-
if m:
|
|
148
|
-
raw = m.group(1).strip()
|
|
149
|
-
# Trim surrounding quotes if present
|
|
150
|
-
if (raw.startswith('"') and raw.endswith('"')) or (raw.startswith("'") and raw.endswith("'")):
|
|
151
|
-
raw = raw[1:-1]
|
|
152
|
-
key_val = raw.strip()
|
|
153
|
-
break
|
|
154
|
-
if key_val:
|
|
155
|
-
synth_key = key_val
|
|
156
|
-
os.environ["SYNTH_API_KEY"] = synth_key
|
|
157
|
-
print(f"[INFO] Loaded SYNTH_API_KEY from {candidate_env}")
|
|
158
|
-
except Exception as _e:
|
|
159
|
-
# Ignore and fall through to error below
|
|
160
|
-
pass
|
|
161
|
-
if not synth_key:
|
|
162
|
-
print("Missing SYNTH_API_KEY (set in env or provide --env-file pointing to .env)", file=sys.stderr)
|
|
163
|
-
sys.exit(2)
|
|
218
|
+
synth_key = input("Please enter your Synth API key:\n> ").strip()
|
|
219
|
+
if not synth_key:
|
|
220
|
+
print("Synth API key is required", file=sys.stderr)
|
|
221
|
+
sys.exit(2)
|
|
164
222
|
|
|
165
223
|
backend = args.backend.rstrip("/")
|
|
166
224
|
print(f"[INFO] Using backend={backend} key_fp={mask(synth_key)} data={data_file}")
|
|
@@ -180,7 +238,10 @@ def main() -> None:
|
|
|
180
238
|
err_status = (upf or {}).get("status")
|
|
181
239
|
err_body = (upf or {}).get("body") or (upf or {}).get("text")
|
|
182
240
|
err_ep = (upf or {}).get("endpoint")
|
|
183
|
-
print(
|
|
241
|
+
print(
|
|
242
|
+
f"Upload failed (status={err_status} endpoint={err_ep}) body={str(err_body)[:200]}",
|
|
243
|
+
file=sys.stderr,
|
|
244
|
+
)
|
|
184
245
|
sys.exit(4)
|
|
185
246
|
|
|
186
247
|
# Optionally upload validation file
|
|
@@ -203,10 +264,12 @@ def main() -> None:
|
|
|
203
264
|
err_status = (upv or {}).get("status")
|
|
204
265
|
err_body = (upv or {}).get("body") or (upv or {}).get("text")
|
|
205
266
|
err_ep = (upv or {}).get("endpoint")
|
|
206
|
-
print(
|
|
267
|
+
print(
|
|
268
|
+
f"[WARN] Validation upload failed (status={err_status} endpoint={err_ep}) body={str(err_body)[:180]} — continuing without validation"
|
|
269
|
+
)
|
|
207
270
|
|
|
208
271
|
# 2) Build job payload
|
|
209
|
-
hp_block:
|
|
272
|
+
hp_block: dict[str, Any] = {
|
|
210
273
|
"n_epochs": int(hp_cfg.get("n_epochs") or 1),
|
|
211
274
|
}
|
|
212
275
|
# Optional extras if present
|
|
@@ -227,7 +290,7 @@ def main() -> None:
|
|
|
227
290
|
if parallel:
|
|
228
291
|
hp_block["parallelism"] = parallel
|
|
229
292
|
|
|
230
|
-
compute_block:
|
|
293
|
+
compute_block: dict[str, Any] = {}
|
|
231
294
|
for k in ("gpu_type", "gpu_count", "nodes"):
|
|
232
295
|
if k in compute_cfg:
|
|
233
296
|
compute_block[k] = compute_cfg[k]
|
|
@@ -238,18 +301,24 @@ def main() -> None:
|
|
|
238
301
|
"training": {k: v for k, v in train_cfg.items() if k in ("mode", "use_qlora")},
|
|
239
302
|
}
|
|
240
303
|
# If TOML includes a [training.validation] block, forward relevant knobs into hyperparameters
|
|
241
|
-
validation_cfg =
|
|
304
|
+
validation_cfg = (
|
|
305
|
+
train_cfg.get("validation") if isinstance(train_cfg.get("validation"), dict) else None
|
|
306
|
+
)
|
|
242
307
|
if isinstance(validation_cfg, dict):
|
|
243
308
|
# Enable evaluation and map keys as-is; backend trainer maps metric_for_best_model 'val.loss'→'eval_loss'
|
|
244
|
-
hp_block.update(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
309
|
+
hp_block.update(
|
|
310
|
+
{
|
|
311
|
+
"evaluation_strategy": validation_cfg.get("evaluation_strategy", "steps"),
|
|
312
|
+
"eval_steps": int(validation_cfg.get("eval_steps", 0) or 0),
|
|
313
|
+
"save_best_model_at_end": bool(validation_cfg.get("save_best_model_at_end", True)),
|
|
314
|
+
"metric_for_best_model": validation_cfg.get("metric_for_best_model", "val.loss"),
|
|
315
|
+
"greater_is_better": bool(validation_cfg.get("greater_is_better", False)),
|
|
316
|
+
}
|
|
317
|
+
)
|
|
251
318
|
# Also surface validation enable flag into effective_config for visibility (optional)
|
|
252
|
-
effective.setdefault("training", {})["validation"] = {
|
|
319
|
+
effective.setdefault("training", {})["validation"] = {
|
|
320
|
+
"enabled": bool(validation_cfg.get("enabled", True))
|
|
321
|
+
}
|
|
253
322
|
|
|
254
323
|
body = {
|
|
255
324
|
"model": model,
|
|
@@ -289,7 +358,9 @@ def main() -> None:
|
|
|
289
358
|
break
|
|
290
359
|
# Warn if stuck queued for >10 minutes
|
|
291
360
|
if status == "queued" and (time.time() - queued_since) > 600:
|
|
292
|
-
print(
|
|
361
|
+
print(
|
|
362
|
+
"[WARN] Job has remained queued for >10 minutes. Backend may be capacity constrained."
|
|
363
|
+
)
|
|
293
364
|
queued_since = time.time()
|
|
294
365
|
time.sleep(5)
|
|
295
366
|
|
|
@@ -7,14 +7,12 @@ import argparse
|
|
|
7
7
|
import asyncio
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
|
+
import sys
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
|
-
import sys
|
|
14
|
-
|
|
15
14
|
import httpx
|
|
16
15
|
from dotenv import load_dotenv
|
|
17
|
-
|
|
18
16
|
from synth_ai.task import (
|
|
19
17
|
RolloutEnvSpec,
|
|
20
18
|
RolloutPolicySpec,
|
|
@@ -46,17 +44,21 @@ def build_rollout_request(
|
|
|
46
44
|
)
|
|
47
45
|
return RolloutRequest(
|
|
48
46
|
run_id=run_id,
|
|
49
|
-
env=RolloutEnvSpec(env_name=
|
|
50
|
-
policy=RolloutPolicySpec(policy_name=
|
|
47
|
+
env=RolloutEnvSpec(env_name="crafter", seed=seed, config={}),
|
|
48
|
+
policy=RolloutPolicySpec(policy_name="crafter-react", config=policy_config),
|
|
51
49
|
ops=ops,
|
|
52
50
|
record=record_cfg,
|
|
53
|
-
on_done=
|
|
51
|
+
on_done="reset",
|
|
54
52
|
safety=RolloutSafetyConfig(),
|
|
55
53
|
)
|
|
56
54
|
|
|
57
55
|
|
|
58
56
|
def summarise_response(data: Any) -> dict[str, Any]:
|
|
59
|
-
metrics =
|
|
57
|
+
metrics = (
|
|
58
|
+
data.metrics.model_dump()
|
|
59
|
+
if hasattr(data.metrics, "model_dump")
|
|
60
|
+
else data.get("metrics", {})
|
|
61
|
+
)
|
|
60
62
|
error = None
|
|
61
63
|
rollout_status = None
|
|
62
64
|
try:
|
|
@@ -86,16 +88,42 @@ async def main() -> None:
|
|
|
86
88
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
87
89
|
parser.add_argument("--base-url", default="http://localhost:8001", help="Task app base URL")
|
|
88
90
|
parser.add_argument("--api-key", help="Environment API key (or set via --env-file)")
|
|
89
|
-
parser.add_argument(
|
|
90
|
-
parser.add_argument(
|
|
91
|
-
parser.add_argument(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
parser.add_argument(
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
parser.add_argument("--seed", type=int, default=42, help="Env seed to rollout")
|
|
92
|
+
parser.add_argument("--run-id", default="local-demo", help="Run identifier")
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"--model",
|
|
95
|
+
default="gpt-4o-mini",
|
|
96
|
+
help="Model identifier for the Crafter policy (OpenAI-compatible)",
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
"--inference-url",
|
|
100
|
+
default="https://api.openai.com",
|
|
101
|
+
help="Inference base URL used by the policy (e.g., https://api.openai.com)",
|
|
102
|
+
)
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--env-file", type=str, default=None, help="Path to .env file with API keys"
|
|
105
|
+
)
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
"--ops", default=None, help="Comma-separated rollout ops (advanced override)"
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--max-llm-calls",
|
|
111
|
+
type=int,
|
|
112
|
+
default=1,
|
|
113
|
+
help="Number of policy inference calls when --ops not provided",
|
|
114
|
+
)
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
"--max-policy-tokens",
|
|
117
|
+
type=int,
|
|
118
|
+
default=None,
|
|
119
|
+
help="Optional per-call token limit forwarded to the policy config",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"--timeout", type=float, default=600.0, help="HTTP timeout (seconds) for task app requests"
|
|
123
|
+
)
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--verbose", action="store_true", help="Print resolved configuration and headers"
|
|
126
|
+
)
|
|
99
127
|
args = parser.parse_args()
|
|
100
128
|
|
|
101
129
|
if args.env_file:
|
|
@@ -117,12 +145,13 @@ async def main() -> None:
|
|
|
117
145
|
os.environ["OPENAI_API_KEY"] = synth_key
|
|
118
146
|
|
|
119
147
|
if args.verbose:
|
|
148
|
+
|
|
120
149
|
def _mask(val: str | None) -> str:
|
|
121
150
|
if not val:
|
|
122
|
-
return
|
|
151
|
+
return "<unset>"
|
|
123
152
|
return f"{val[:6]}…{val[-4:]} (len={len(val)})"
|
|
124
153
|
|
|
125
|
-
print(
|
|
154
|
+
print("Resolved configuration:")
|
|
126
155
|
print(f" Task app base URL : {args.base_url}")
|
|
127
156
|
print(f" Inference base URL : {args.inference_url}")
|
|
128
157
|
print(f" Task app API key : {_mask(api_key)}")
|
|
@@ -130,21 +159,23 @@ async def main() -> None:
|
|
|
130
159
|
print(f" HTTP timeout : {args.timeout:.1f}s")
|
|
131
160
|
|
|
132
161
|
if args.ops:
|
|
133
|
-
ops = [op.strip() for op in args.ops.split(
|
|
162
|
+
ops = [op.strip() for op in args.ops.split(",") if op.strip()]
|
|
134
163
|
if not ops:
|
|
135
|
-
raise ValueError(
|
|
164
|
+
raise ValueError("Ops must contain at least one entry")
|
|
136
165
|
else:
|
|
137
166
|
llm_calls = max(args.max_llm_calls, 1)
|
|
138
167
|
if llm_calls > 20:
|
|
139
|
-
print(
|
|
168
|
+
print(
|
|
169
|
+
"[WARN] --max-llm-calls capped at 20 to avoid excessive episodes; use --ops for manual control."
|
|
170
|
+
)
|
|
140
171
|
llm_calls = 20
|
|
141
172
|
ops = []
|
|
142
173
|
for _ in range(llm_calls):
|
|
143
|
-
ops.extend([
|
|
174
|
+
ops.extend(["agent", "env"])
|
|
144
175
|
|
|
145
176
|
async with TaskAppClient(args.base_url, api_key=api_key, timeout=args.timeout) as client:
|
|
146
177
|
try:
|
|
147
|
-
print(f
|
|
178
|
+
print(f"Fetching task_info for seed {args.seed}…")
|
|
148
179
|
task_info = await client.task_info(seeds=[args.seed])
|
|
149
180
|
info_payload = task_info[0] if isinstance(task_info, list) else task_info
|
|
150
181
|
print(json.dumps(info_payload.model_dump(), indent=2)[:600])
|
|
@@ -158,29 +189,47 @@ async def main() -> None:
|
|
|
158
189
|
extra_headers=extra_headers,
|
|
159
190
|
)
|
|
160
191
|
if args.max_policy_tokens is not None:
|
|
161
|
-
request.policy.config.update(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
192
|
+
request.policy.config.update(
|
|
193
|
+
{
|
|
194
|
+
"max_completion_tokens": args.max_policy_tokens,
|
|
195
|
+
"max_tokens": args.max_policy_tokens,
|
|
196
|
+
}
|
|
197
|
+
)
|
|
165
198
|
if args.verbose:
|
|
166
|
-
print(f
|
|
167
|
-
print(f
|
|
168
|
-
print(
|
|
199
|
+
print(f"Ops: {ops}")
|
|
200
|
+
print(f"Request headers: {request.policy.config.get('extra_headers', {})}")
|
|
201
|
+
print("Requesting rollout…")
|
|
169
202
|
response = await client.rollout(request)
|
|
170
203
|
summary = summarise_response(response)
|
|
171
204
|
print(json.dumps(summary, indent=2))
|
|
172
|
-
print(f
|
|
173
|
-
print(
|
|
205
|
+
print(f"Ops executed: {ops}")
|
|
206
|
+
print("Tip: use --max-llm-calls N for agent/env pairs or --ops for manual control.")
|
|
174
207
|
except httpx.HTTPStatusError as exc:
|
|
175
|
-
detail =
|
|
176
|
-
|
|
208
|
+
detail = (
|
|
209
|
+
exc.response.json()
|
|
210
|
+
if exc.response.headers.get("content-type", "").startswith("application/json")
|
|
211
|
+
else exc.response.text
|
|
212
|
+
)
|
|
213
|
+
print(f"HTTP error {exc.response.status_code}: {detail}", file=sys.stderr)
|
|
177
214
|
if exc.response.status_code in (401, 503):
|
|
178
|
-
print(
|
|
215
|
+
print(
|
|
216
|
+
"Hint: ensure the task app was started with ENVIRONMENT_API_KEY set and pass the same key via --api-key.",
|
|
217
|
+
file=sys.stderr,
|
|
218
|
+
)
|
|
179
219
|
if exc.response.status_code == 500 and args.model in str(detail):
|
|
180
|
-
print(
|
|
181
|
-
|
|
220
|
+
print(
|
|
221
|
+
"Hint: supply --model/--inference-url (and set OPENAI_API_KEY or GROQ_API_KEY) so the policy can route inference.",
|
|
222
|
+
file=sys.stderr,
|
|
223
|
+
)
|
|
224
|
+
print(
|
|
225
|
+
"Hint: the inference URL should be the base (e.g., https://api.openai.com); the task app appends /v1/chat/completions.",
|
|
226
|
+
file=sys.stderr,
|
|
227
|
+
)
|
|
182
228
|
if args.max_policy_tokens is not None:
|
|
183
|
-
print(
|
|
229
|
+
print(
|
|
230
|
+
f"Hint: --max-policy-tokens={args.max_policy_tokens} is forwarded to the policy config as max_completion_tokens.",
|
|
231
|
+
file=sys.stderr,
|
|
232
|
+
)
|
|
184
233
|
raise
|
|
185
234
|
|
|
186
235
|
|