synth-ai 0.2.14__py3-none-any.whl → 0.2.17__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/README.md +1 -0
- examples/analyze_semantic_words.sh +2 -2
- examples/blog_posts/pokemon_vl/README.md +98 -0
- examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +25 -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 +42 -0
- examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
- examples/blog_posts/warming_up_to_rl/README.md +158 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -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/train_rl_from_sft.toml +41 -0
- examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
- examples/dev/qwen3_32b_qlora_4xh100.toml +5 -0
- examples/multi_step/SFT_README.md +147 -0
- examples/multi_step/configs/crafter_rl_outcome.toml +1 -1
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +73 -115
- examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +1 -1
- examples/multi_step/configs/crafter_rl_stepwise_simple.toml +1 -1
- 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/verilog_rl_lora.toml +80 -123
- examples/multi_step/convert_traces_to_sft.py +84 -0
- examples/multi_step/run_sft_qwen30b.sh +45 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +1 -2
- examples/qwen_coder/configs/coder_lora_4b.toml +5 -1
- examples/qwen_coder/configs/coder_lora_small.toml +1 -2
- 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 +6 -6
- 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 +79 -0
- examples/rl/configs/rl_from_ft_qwen.toml +37 -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
- examples/rl/task_app/math_single_step.py +990 -0
- examples/rl/task_app/math_task_app.py +111 -0
- examples/run_crafter_demo.sh +2 -2
- examples/sft/README.md +6 -6
- examples/sft/configs/crafter_fft_qwen0p6b.toml +7 -2
- examples/sft/configs/crafter_lora_qwen0p6b.toml +7 -3
- examples/sft/evaluate.py +2 -4
- examples/sft/export_dataset.py +7 -4
- examples/swe/task_app/README.md +33 -3
- examples/swe/task_app/grpo_swe_mini.py +4 -1
- examples/swe/task_app/grpo_swe_mini_task_app.py +0 -12
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +1 -1
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +50 -23
- examples/swe/task_app/hosted/inference/openai_client.py +4 -4
- examples/swe/task_app/hosted/policy_routes.py +0 -2
- examples/swe/task_app/hosted/rollout.py +0 -8
- examples/swe/task_app/morph_backend.py +178 -0
- examples/task_apps/crafter/task_app/README.md +1 -1
- examples/task_apps/crafter/task_app/grpo_crafter.py +70 -10
- examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +1 -1
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +63 -27
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -2
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +48 -50
- examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +75 -36
- examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +31 -15
- examples/task_apps/enron/__init__.py +1 -0
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +1 -1
- examples/task_apps/math/README.md +1 -2
- examples/task_apps/pokemon_red/README.md +3 -4
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +6 -5
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +1 -2
- examples/task_apps/pokemon_red/task_app.py +36 -5
- examples/task_apps/sokoban/README.md +2 -3
- examples/task_apps/verilog/eval_groq_qwen32b.toml +12 -14
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +1 -1
- examples/vlm/README.md +3 -3
- examples/vlm/configs/crafter_vlm_gpt4o.toml +5 -0
- examples/vlm/crafter_openai_vlm_agent.py +3 -5
- examples/vlm/filter_image_rows.py +1 -1
- examples/vlm/run_crafter_vlm_benchmark.py +2 -2
- examples/warming_up_to_rl/_utils.py +92 -0
- examples/warming_up_to_rl/analyze_trace_db.py +1 -1
- examples/warming_up_to_rl/configs/crafter_fft.toml +5 -0
- examples/warming_up_to_rl/configs/eval_fft_qwen4b.toml +2 -0
- examples/warming_up_to_rl/configs/eval_groq_qwen32b.toml +2 -0
- examples/warming_up_to_rl/configs/eval_modal_qwen4b.toml +2 -1
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +2 -1
- examples/warming_up_to_rl/configs/rl_from_ft.toml +2 -0
- examples/warming_up_to_rl/export_trace_sft.py +174 -60
- examples/warming_up_to_rl/readme.md +63 -132
- examples/warming_up_to_rl/run_fft_and_save.py +1 -1
- examples/warming_up_to_rl/run_local_rollout_traced.py +1 -1
- examples/warming_up_to_rl/run_rl_and_save.py +1 -1
- examples/warming_up_to_rl/task_app/README.md +42 -0
- examples/warming_up_to_rl/task_app/grpo_crafter.py +827 -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 +204 -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 +618 -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 +1084 -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 +1861 -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 +62 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen.toml +27 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +5 -0
- synth_ai/__init__.py +44 -30
- 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 +144 -7
- synth_ai/api/train/__init__.py +13 -1
- synth_ai/api/train/builders.py +9 -3
- synth_ai/api/train/cli.py +155 -17
- synth_ai/api/train/config_finder.py +18 -11
- synth_ai/api/train/configs/__init__.py +8 -1
- synth_ai/api/train/configs/rl.py +32 -7
- synth_ai/api/train/configs/sft.py +6 -2
- synth_ai/api/train/configs/shared.py +59 -2
- synth_ai/api/train/env_resolver.py +13 -10
- synth_ai/auth/credentials.py +119 -0
- synth_ai/cli/__init__.py +61 -69
- synth_ai/cli/_modal_wrapper.py +7 -5
- synth_ai/cli/_typer_patch.py +0 -2
- synth_ai/cli/_validate_task_app.py +22 -4
- synth_ai/cli/commands/__init__.py +17 -0
- synth_ai/cli/commands/demo/__init__.py +6 -0
- synth_ai/cli/commands/demo/core.py +163 -0
- synth_ai/cli/commands/deploy/__init__.py +23 -0
- synth_ai/cli/commands/deploy/core.py +614 -0
- synth_ai/cli/commands/deploy/errors.py +72 -0
- synth_ai/cli/commands/deploy/validation.py +11 -0
- synth_ai/cli/commands/eval/__init__.py +19 -0
- synth_ai/cli/commands/eval/core.py +1109 -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 +388 -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 +177 -0
- synth_ai/cli/commands/help/core.py +73 -0
- synth_ai/cli/commands/status/__init__.py +64 -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/runs.py +81 -0
- synth_ai/cli/commands/status/subcommands/summary.py +47 -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 +199 -0
- synth_ai/cli/commands/train/judge_validation.py +304 -0
- synth_ai/cli/commands/train/validation.py +443 -0
- synth_ai/cli/demo.py +2 -162
- synth_ai/cli/deploy/__init__.py +28 -0
- synth_ai/cli/deploy/core.py +5 -0
- synth_ai/cli/deploy/errors.py +23 -0
- synth_ai/cli/deploy/validation.py +5 -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 +3 -1
- 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/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/recent.py +2 -1
- 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 +21 -0
- synth_ai/cli/status.py +7 -126
- 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 +110 -1499
- synth_ai/cli/traces.py +1 -1
- 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 +1 -1
- synth_ai/cli/watch.py +1 -1
- synth_ai/demos/__init__.py +10 -0
- synth_ai/demos/core/__init__.py +28 -1
- 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/crafter/grpo_crafter_task_app.py +1 -1
- 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 +702 -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 +0 -1
- synth_ai/environments/examples/bandit/environment.py +0 -1
- synth_ai/environments/examples/red/engine.py +33 -12
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
- synth_ai/environments/examples/red/environment.py +26 -0
- synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
- synth_ai/environments/examples/wordle/environment.py +0 -1
- synth_ai/evals/base.py +16 -5
- synth_ai/evals/client.py +1 -1
- synth_ai/http.py +8 -22
- synth_ai/inference/client.py +1 -1
- synth_ai/judge_schemas.py +4 -5
- synth_ai/learning/client.py +1 -1
- synth_ai/learning/health.py +1 -1
- synth_ai/learning/jobs.py +1 -1
- synth_ai/learning/rl/client.py +4 -2
- synth_ai/learning/rl/env_keys.py +1 -1
- synth_ai/learning/rl/secrets.py +1 -1
- synth_ai/learning/sft/client.py +1 -1
- synth_ai/learning/sft/data.py +407 -4
- synth_ai/learning/validators.py +4 -1
- synth_ai/streaming/__init__.py +29 -0
- synth_ai/streaming/config.py +94 -0
- synth_ai/streaming/handlers.py +469 -0
- synth_ai/streaming/streamer.py +301 -0
- synth_ai/streaming/types.py +95 -0
- synth_ai/task/apps/__init__.py +4 -2
- synth_ai/task/config.py +6 -4
- synth_ai/task/rubrics/__init__.py +1 -2
- synth_ai/task/rubrics/loaders.py +14 -10
- synth_ai/task/rubrics.py +219 -0
- synth_ai/task/trace_correlation_helpers.py +24 -11
- synth_ai/task/tracing_utils.py +14 -3
- synth_ai/task/validators.py +0 -1
- synth_ai/tracing_v3/abstractions.py +3 -3
- synth_ai/tracing_v3/config.py +15 -13
- synth_ai/tracing_v3/constants.py +21 -0
- synth_ai/tracing_v3/db_config.py +3 -1
- synth_ai/tracing_v3/decorators.py +10 -7
- synth_ai/tracing_v3/llm_call_record_helpers.py +5 -5
- synth_ai/tracing_v3/migration_helper.py +1 -2
- synth_ai/tracing_v3/session_tracer.py +7 -7
- synth_ai/tracing_v3/storage/base.py +29 -29
- synth_ai/tracing_v3/storage/config.py +3 -3
- synth_ai/tracing_v3/turso/daemon.py +8 -9
- synth_ai/tracing_v3/turso/native_manager.py +80 -72
- synth_ai/tracing_v3/utils.py +2 -2
- synth_ai/utils/__init__.py +101 -0
- synth_ai/utils/base_url.py +94 -0
- synth_ai/utils/cli.py +131 -0
- synth_ai/utils/env.py +294 -0
- synth_ai/utils/http.py +172 -0
- synth_ai/utils/modal.py +308 -0
- synth_ai/utils/process.py +212 -0
- synth_ai/utils/prompts.py +39 -0
- synth_ai/utils/sqld.py +122 -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/user_config.py +137 -0
- synth_ai/v0/config/__init__.py +1 -5
- synth_ai/v0/config/base_url.py +1 -7
- synth_ai/v0/tracing/config.py +1 -1
- synth_ai/v0/tracing/decorators.py +1 -1
- synth_ai/v0/tracing/upload.py +1 -1
- synth_ai/v0/tracing_v1/config.py +1 -1
- synth_ai/v0/tracing_v1/decorators.py +1 -1
- synth_ai/v0/tracing_v1/upload.py +1 -1
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/METADATA +91 -32
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/RECORD +341 -154
- synth_ai/cli/man.py +0 -106
- synth_ai/cli/tui.py +0 -57
- synth_ai/compound/cais.py +0 -0
- synth_ai/core/experiment.py +0 -13
- synth_ai/core/system.py +0 -15
- synth_ai/demo_registry.py +0 -295
- synth_ai/handshake.py +0 -109
- synth_ai/tui/__init__.py +0 -5
- synth_ai/tui/__main__.py +0 -13
- synth_ai/tui/cli/__init__.py +0 -1
- synth_ai/tui/cli/query_experiments.py +0 -164
- synth_ai/tui/cli/query_experiments_v3.py +0 -164
- synth_ai/tui/dashboard.py +0 -906
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/top_level.txt +0 -0
synth_ai/__init__.py
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Synth AI - Software for aiding the best and multiplying the will.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
1
|
from __future__ import annotations
|
|
6
2
|
|
|
3
|
+
import importlib
|
|
7
4
|
from importlib import metadata as _metadata
|
|
8
5
|
from importlib.metadata import PackageNotFoundError
|
|
9
6
|
from pathlib import Path
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
import synth_ai.environments as environments # expose module name for __all__
|
|
10
|
+
from synth_ai.environments import * # noqa
|
|
11
|
+
from synth_ai.judge_schemas import (
|
|
12
|
+
CriterionScorePayload,
|
|
13
|
+
JudgeOptions,
|
|
14
|
+
JudgeScoreRequest,
|
|
15
|
+
JudgeScoreResponse,
|
|
16
|
+
JudgeTaskApp,
|
|
17
|
+
JudgeTracePayload,
|
|
18
|
+
ReviewPayload,
|
|
19
|
+
)
|
|
10
20
|
|
|
11
21
|
try: # Prefer the installed package metadata when available
|
|
12
22
|
__version__ = _metadata.version("synth-ai")
|
|
@@ -24,35 +34,39 @@ except PackageNotFoundError: # Fallback to pyproject version for editable insta
|
|
|
24
34
|
except Exception:
|
|
25
35
|
__version__ = "0.0.0.dev0"
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
def _optional_import(module_path: str) -> Any | None:
|
|
38
|
+
try:
|
|
39
|
+
return importlib.import_module(module_path)
|
|
40
|
+
except Exception:
|
|
41
|
+
return None
|
|
30
42
|
|
|
31
|
-
try:
|
|
32
|
-
from synth_ai.lm.core.main import LM # Moved from zyk to lm for better organization
|
|
33
|
-
except Exception: # allow minimal imports (e.g., tracing) without LM stack
|
|
34
|
-
LM = None # type: ignore
|
|
35
|
-
try:
|
|
36
|
-
from synth_ai.lm.provider_support.anthropic import Anthropic, AsyncAnthropic
|
|
37
|
-
except Exception: # optional in minimal environments
|
|
38
|
-
Anthropic = AsyncAnthropic = None # type: ignore
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
from synth_ai.lm.provider_support.openai import AsyncOpenAI, OpenAI
|
|
43
|
-
except Exception:
|
|
44
|
-
AsyncOpenAI = OpenAI = None # type: ignore
|
|
44
|
+
_lm_module = _optional_import("synth_ai.lm.core.main")
|
|
45
|
+
LM = cast(Any, _lm_module).LM if _lm_module and hasattr(_lm_module, "LM") else None # type: ignore[attr-defined]
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
_anthropic_module = _optional_import("synth_ai.lm.provider_support.anthropic")
|
|
48
|
+
Anthropic = (
|
|
49
|
+
cast(Any, _anthropic_module).Anthropic
|
|
50
|
+
if _anthropic_module and hasattr(_anthropic_module, "Anthropic")
|
|
51
|
+
else None
|
|
52
|
+
) # type: ignore[attr-defined]
|
|
53
|
+
AsyncAnthropic = (
|
|
54
|
+
cast(Any, _anthropic_module).AsyncAnthropic
|
|
55
|
+
if _anthropic_module and hasattr(_anthropic_module, "AsyncAnthropic")
|
|
56
|
+
else None
|
|
57
|
+
) # type: ignore[attr-defined]
|
|
58
|
+
|
|
59
|
+
_openai_module = _optional_import("synth_ai.lm.provider_support.openai")
|
|
60
|
+
AsyncOpenAI = (
|
|
61
|
+
cast(Any, _openai_module).AsyncOpenAI
|
|
62
|
+
if _openai_module and hasattr(_openai_module, "AsyncOpenAI")
|
|
63
|
+
else None
|
|
64
|
+
) # type: ignore[attr-defined]
|
|
65
|
+
OpenAI = (
|
|
66
|
+
cast(Any, _openai_module).OpenAI
|
|
67
|
+
if _openai_module and hasattr(_openai_module, "OpenAI")
|
|
68
|
+
else None
|
|
69
|
+
) # type: ignore[attr-defined]
|
|
56
70
|
|
|
57
71
|
# Legacy tracing v1 is not required for v3 usage and can be unavailable in minimal envs.
|
|
58
72
|
tracing = None # type: ignore
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Compatibility shims for legacy `synth_ai._utils.*` imports.
|
|
3
|
+
|
|
4
|
+
The modern codebase exposes these helpers under ``synth_ai.utils``. These
|
|
5
|
+
modules re-export the public symbols so existing downstream code (and our own
|
|
6
|
+
older examples/tests) continue to work without modification.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from importlib import import_module
|
|
12
|
+
from types import ModuleType
|
|
13
|
+
|
|
14
|
+
_MAPPING = {
|
|
15
|
+
"base_url": "synth_ai.utils.base_url",
|
|
16
|
+
"http": "synth_ai.utils.http",
|
|
17
|
+
"prompts": "synth_ai.utils.prompts",
|
|
18
|
+
"task_app_state": "synth_ai.utils.task_app_state",
|
|
19
|
+
"user_config": "synth_ai.utils.user_config",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
__all__ = sorted(_MAPPING.keys())
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def __getattr__(name: str) -> ModuleType:
|
|
26
|
+
target = _MAPPING.get(name)
|
|
27
|
+
if not target:
|
|
28
|
+
raise AttributeError(f"module 'synth_ai._utils' has no attribute '{name}'")
|
|
29
|
+
module = import_module(target)
|
|
30
|
+
globals()[name] = module
|
|
31
|
+
return module
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __dir__() -> list[str]:
|
|
35
|
+
return sorted(set(globals()) | set(__all__))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _export(module_name: str) -> None:
|
|
39
|
+
module = import_module(_MAPPING[module_name])
|
|
40
|
+
globals().setdefault(module_name, module)
|
|
41
|
+
if hasattr(module, "__all__"):
|
|
42
|
+
for attr in module.__all__: # type: ignore[attr-defined]
|
|
43
|
+
globals().setdefault(attr, getattr(module, attr))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
for _name in __all__:
|
|
47
|
+
_export(_name)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synth_ai.utils.base_url import * # noqa: F401,F403
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from synth_ai.utils.base_url import __all__ as __wrapped_all__ # type: ignore[attr-defined]
|
|
7
|
+
except ImportError: # pragma: no cover - defensive
|
|
8
|
+
__wrapped_all__ = []
|
|
9
|
+
|
|
10
|
+
__all__ = list(__wrapped_all__)
|
synth_ai/_utils/http.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synth_ai.utils.http import * # noqa: F401,F403
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from synth_ai.utils.http import __all__ as __wrapped_all__ # type: ignore[attr-defined]
|
|
7
|
+
except ImportError: # pragma: no cover - defensive
|
|
8
|
+
__wrapped_all__ = []
|
|
9
|
+
|
|
10
|
+
__all__ = list(__wrapped_all__)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synth_ai.utils.prompts import * # noqa: F401,F403
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from synth_ai.utils.prompts import __all__ as __wrapped_all__ # type: ignore[attr-defined]
|
|
7
|
+
except ImportError: # pragma: no cover - defensive
|
|
8
|
+
__wrapped_all__ = []
|
|
9
|
+
|
|
10
|
+
__all__ = list(__wrapped_all__)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synth_ai.utils.task_app_state import * # noqa: F401,F403
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from synth_ai.utils.task_app_state import (
|
|
7
|
+
__all__ as __wrapped_all__, # type: ignore[attr-defined]
|
|
8
|
+
)
|
|
9
|
+
except ImportError: # pragma: no cover - defensive
|
|
10
|
+
__wrapped_all__ = []
|
|
11
|
+
|
|
12
|
+
__all__ = list(__wrapped_all__)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synth_ai.utils.user_config import * # noqa: F401,F403
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from synth_ai.utils.user_config import __all__ as __wrapped_all__ # type: ignore[attr-defined]
|
|
7
|
+
except ImportError: # pragma: no cover - defensive
|
|
8
|
+
__wrapped_all__ = []
|
|
9
|
+
|
|
10
|
+
__all__ = list(__wrapped_all__)
|
synth_ai/api/models/supported.py
CHANGED
|
@@ -20,35 +20,106 @@ QWEN3_MODELS: list[str] = [
|
|
|
20
20
|
"Qwen/Qwen3-14B",
|
|
21
21
|
"Qwen/Qwen3-30B-A3B",
|
|
22
22
|
"Qwen/Qwen3-32B",
|
|
23
|
-
#
|
|
23
|
+
# 2507 baseline models
|
|
24
|
+
"Qwen/Qwen3-4B-2507",
|
|
25
|
+
# Instruct variants (no <think> tags)
|
|
26
|
+
"Qwen/Qwen3-4B-Instruct-2507",
|
|
27
|
+
"Qwen/Qwen3-4B-Instruct-2507-FP8",
|
|
28
|
+
"Qwen/Qwen3-30B-A3B-Instruct-2507",
|
|
29
|
+
"Qwen/Qwen3-30B-A3B-Instruct-2507-FP8",
|
|
30
|
+
"Qwen/Qwen3-235B-A22B-Instruct-2507",
|
|
31
|
+
"Qwen/Qwen3-235B-A22B-Instruct-2507-FP8",
|
|
32
|
+
# Thinking variants (with <think> tags)
|
|
24
33
|
"Qwen/Qwen3-4B-Thinking-2507",
|
|
34
|
+
"Qwen/Qwen3-4B-Thinking-2507-FP8",
|
|
25
35
|
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
36
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507-FP8",
|
|
26
37
|
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
38
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507-FP8",
|
|
27
39
|
]
|
|
28
40
|
|
|
29
41
|
# Qwen3 Coder family (backend-supported); text-only, SFT/inference
|
|
30
42
|
QWEN3_CODER_MODELS: list[str] = [
|
|
31
|
-
# Instruct variants used for coding tasks
|
|
43
|
+
# Instruct variants used for coding tasks (no <think> tags)
|
|
32
44
|
"Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
|
45
|
+
"Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8",
|
|
33
46
|
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
47
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
# Qwen3-VL family (vision-language models); multimodal, SFT/inference
|
|
51
|
+
QWEN3_VL_MODELS: list[str] = [
|
|
52
|
+
# Vision-Language Models (Qwen3-VL)
|
|
53
|
+
"Qwen/Qwen3-VL-2B-Instruct",
|
|
54
|
+
"Qwen/Qwen3-VL-2B-Thinking",
|
|
55
|
+
"Qwen/Qwen3-VL-4B-Instruct",
|
|
56
|
+
"Qwen/Qwen3-VL-4B-Thinking",
|
|
57
|
+
"Qwen/Qwen3-VL-8B-Instruct",
|
|
58
|
+
"Qwen/Qwen3-VL-8B-Thinking",
|
|
59
|
+
"Qwen/Qwen3-VL-30B-A3B-Instruct",
|
|
60
|
+
"Qwen/Qwen3-VL-30B-A3B-Thinking",
|
|
61
|
+
"Qwen/Qwen3-VL-32B-Instruct",
|
|
62
|
+
"Qwen/Qwen3-VL-32B-Thinking",
|
|
63
|
+
"Qwen/Qwen3-VL-235B-A22B-Instruct",
|
|
64
|
+
"Qwen/Qwen3-VL-235B-A22B-Thinking",
|
|
34
65
|
]
|
|
35
66
|
|
|
36
67
|
# Training support sets
|
|
37
68
|
RL_SUPPORTED_MODELS: frozenset[str] = frozenset(
|
|
38
69
|
{
|
|
70
|
+
# Legacy base models
|
|
39
71
|
"Qwen/Qwen3-0.6B",
|
|
40
72
|
"Qwen/Qwen3-1.7B",
|
|
41
73
|
"Qwen/Qwen3-4B",
|
|
42
|
-
"Qwen/Qwen3-4B-Thinking-2507",
|
|
43
74
|
"Qwen/Qwen3-8B",
|
|
44
75
|
"Qwen/Qwen3-14B",
|
|
45
76
|
"Qwen/Qwen3-30B-A3B",
|
|
77
|
+
# 2507 models - base
|
|
78
|
+
"Qwen/Qwen3-4B-2507",
|
|
79
|
+
# 2507 models - instruct (no <think> tags)
|
|
80
|
+
"Qwen/Qwen3-4B-Instruct-2507",
|
|
81
|
+
"Qwen/Qwen3-4B-Instruct-2507-FP8",
|
|
82
|
+
"Qwen/Qwen3-30B-A3B-Instruct-2507",
|
|
83
|
+
"Qwen/Qwen3-30B-A3B-Instruct-2507-FP8",
|
|
84
|
+
# 2507 models - thinking (with <think> tags)
|
|
85
|
+
"Qwen/Qwen3-4B-Thinking-2507",
|
|
86
|
+
"Qwen/Qwen3-4B-Thinking-2507-FP8",
|
|
46
87
|
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
88
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507-FP8",
|
|
89
|
+
# Coder instruct models
|
|
90
|
+
"Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
|
91
|
+
"Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8",
|
|
92
|
+
# Vision-Language models (Qwen3-VL)
|
|
93
|
+
"Qwen/Qwen3-VL-2B-Instruct",
|
|
94
|
+
"Qwen/Qwen3-VL-2B-Thinking",
|
|
95
|
+
"Qwen/Qwen3-VL-4B-Instruct",
|
|
96
|
+
"Qwen/Qwen3-VL-4B-Thinking",
|
|
97
|
+
"Qwen/Qwen3-VL-8B-Instruct",
|
|
98
|
+
"Qwen/Qwen3-VL-8B-Thinking",
|
|
47
99
|
}
|
|
48
100
|
)
|
|
49
101
|
|
|
50
|
-
# SFT allowlist includes core Qwen3 plus Coder
|
|
51
|
-
SFT_SUPPORTED_MODELS: frozenset[str] = frozenset([*QWEN3_MODELS, *QWEN3_CODER_MODELS])
|
|
102
|
+
# SFT allowlist includes core Qwen3 plus Coder and VL families
|
|
103
|
+
SFT_SUPPORTED_MODELS: frozenset[str] = frozenset([*QWEN3_MODELS, *QWEN3_CODER_MODELS, *QWEN3_VL_MODELS])
|
|
104
|
+
|
|
105
|
+
# Models that support <think> reasoning tags
|
|
106
|
+
THINKING_MODELS: frozenset[str] = frozenset(
|
|
107
|
+
{
|
|
108
|
+
"Qwen/Qwen3-4B-Thinking-2507",
|
|
109
|
+
"Qwen/Qwen3-4B-Thinking-2507-FP8",
|
|
110
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
111
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507-FP8",
|
|
112
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
113
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507-FP8",
|
|
114
|
+
# Vision-Language Thinking models
|
|
115
|
+
"Qwen/Qwen3-VL-2B-Thinking",
|
|
116
|
+
"Qwen/Qwen3-VL-4B-Thinking",
|
|
117
|
+
"Qwen/Qwen3-VL-8B-Thinking",
|
|
118
|
+
"Qwen/Qwen3-VL-30B-A3B-Thinking",
|
|
119
|
+
"Qwen/Qwen3-VL-32B-Thinking",
|
|
120
|
+
"Qwen/Qwen3-VL-235B-A22B-Thinking",
|
|
121
|
+
}
|
|
122
|
+
)
|
|
52
123
|
|
|
53
124
|
# ------------------------------------------------------------------------------
|
|
54
125
|
# Lifecycle classification (core vs experimental)
|
|
@@ -58,11 +129,17 @@ SFT_SUPPORTED_MODELS: frozenset[str] = frozenset([*QWEN3_MODELS, *QWEN3_CODER_MO
|
|
|
58
129
|
_EXPERIMENTAL_DEFAULTS: frozenset[str] = frozenset(
|
|
59
130
|
{
|
|
60
131
|
# Larger (>= 64B) or bleeding-edge variants are experimental by default.
|
|
132
|
+
"Qwen/Qwen3-235B-A22B-Instruct-2507",
|
|
133
|
+
"Qwen/Qwen3-235B-A22B-Instruct-2507-FP8",
|
|
61
134
|
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
135
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507-FP8",
|
|
62
136
|
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
137
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8",
|
|
63
138
|
# Thinking variants can fluctuate more rapidly.
|
|
64
139
|
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
140
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507-FP8",
|
|
65
141
|
"Qwen/Qwen3-4B-Thinking-2507",
|
|
142
|
+
"Qwen/Qwen3-4B-Thinking-2507-FP8",
|
|
66
143
|
}
|
|
67
144
|
)
|
|
68
145
|
|
|
@@ -77,8 +154,8 @@ def _parse_experimental_env() -> frozenset[str]:
|
|
|
77
154
|
# Final experimental set (defaults ∪ optional env override)
|
|
78
155
|
EXPERIMENTAL_MODELS: frozenset[str] = frozenset(_EXPERIMENTAL_DEFAULTS | _parse_experimental_env())
|
|
79
156
|
|
|
80
|
-
# Build catalog entries for
|
|
81
|
-
_ALL_QWEN3_IDS: list[str] = [*QWEN3_MODELS, *QWEN3_CODER_MODELS]
|
|
157
|
+
# Build catalog entries for core, coder, and VL families under unified "Qwen3"
|
|
158
|
+
_ALL_QWEN3_IDS: list[str] = [*QWEN3_MODELS, *QWEN3_CODER_MODELS, *QWEN3_VL_MODELS]
|
|
82
159
|
|
|
83
160
|
CORE_MODELS: frozenset[str] = frozenset(m for m in _ALL_QWEN3_IDS if m not in EXPERIMENTAL_MODELS)
|
|
84
161
|
|
|
@@ -120,6 +197,7 @@ class SupportedModel:
|
|
|
120
197
|
modalities: tuple[str, ...] = ()
|
|
121
198
|
training_modes: tuple[str, ...] = ()
|
|
122
199
|
lifecycle: str = "core" # "core" | "experimental"
|
|
200
|
+
supports_thinking: bool = False # Whether model supports <think> reasoning tags
|
|
123
201
|
|
|
124
202
|
def as_dict(self) -> dict[str, object]:
|
|
125
203
|
data: dict[str, object] = {
|
|
@@ -127,6 +205,7 @@ class SupportedModel:
|
|
|
127
205
|
"family": self.family,
|
|
128
206
|
"provider": self.provider,
|
|
129
207
|
"lifecycle": self.lifecycle,
|
|
208
|
+
"supports_thinking": self.supports_thinking,
|
|
130
209
|
}
|
|
131
210
|
if self.modalities:
|
|
132
211
|
data["modalities"] = list(self.modalities)
|
|
@@ -150,6 +229,7 @@ SUPPORTED_MODELS: tuple[SupportedModel, ...] = tuple(
|
|
|
150
229
|
)
|
|
151
230
|
),
|
|
152
231
|
lifecycle=("experimental" if model in EXPERIMENTAL_MODELS else "core"),
|
|
232
|
+
supports_thinking=(model in THINKING_MODELS),
|
|
153
233
|
)
|
|
154
234
|
for model in _ALL_QWEN3_IDS
|
|
155
235
|
)
|
|
@@ -347,11 +427,66 @@ def training_modes_for_model(model_id: str) -> tuple[str, ...]:
|
|
|
347
427
|
return model.training_modes
|
|
348
428
|
|
|
349
429
|
|
|
430
|
+
def supports_thinking(model_id: str) -> bool:
|
|
431
|
+
"""Return True if the model supports <think> reasoning tags.
|
|
432
|
+
|
|
433
|
+
Thinking models use structured <think>...</think> tags for reasoning.
|
|
434
|
+
Instruct models do not have these tags and should not use thinking-specific logic.
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
model_id: Model identifier (can include prefixes like 'rl:', 'fft:', etc.)
|
|
438
|
+
|
|
439
|
+
Returns:
|
|
440
|
+
True if the model supports thinking tags, False otherwise.
|
|
441
|
+
Returns False for unsupported models.
|
|
442
|
+
|
|
443
|
+
Example:
|
|
444
|
+
>>> supports_thinking("Qwen/Qwen3-4B-Thinking-2507")
|
|
445
|
+
True
|
|
446
|
+
>>> supports_thinking("Qwen/Qwen3-4B-Instruct-2507")
|
|
447
|
+
False
|
|
448
|
+
>>> supports_thinking("rl:Qwen/Qwen3-4B-Thinking-2507")
|
|
449
|
+
True
|
|
450
|
+
"""
|
|
451
|
+
try:
|
|
452
|
+
canonical = ensure_supported_model(model_id, allow_finetuned_prefixes=True)
|
|
453
|
+
except UnsupportedModelError:
|
|
454
|
+
return False
|
|
455
|
+
model = _MODEL_BY_ID.get(canonical)
|
|
456
|
+
if not model:
|
|
457
|
+
return False
|
|
458
|
+
return model.supports_thinking
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def get_model_metadata(model_id: str) -> SupportedModel | None:
|
|
462
|
+
"""Return the full metadata for a supported model, or None if not supported.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
model_id: Model identifier (can include prefixes like 'rl:', 'fft:', etc.)
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
SupportedModel instance with full metadata, or None if model is not supported.
|
|
469
|
+
|
|
470
|
+
Example:
|
|
471
|
+
>>> meta = get_model_metadata("Qwen/Qwen3-4B-Instruct-2507")
|
|
472
|
+
>>> meta.supports_thinking
|
|
473
|
+
False
|
|
474
|
+
>>> meta.training_modes
|
|
475
|
+
('rl', 'sft')
|
|
476
|
+
"""
|
|
477
|
+
try:
|
|
478
|
+
canonical = ensure_supported_model(model_id, allow_finetuned_prefixes=True)
|
|
479
|
+
except UnsupportedModelError:
|
|
480
|
+
return None
|
|
481
|
+
return _MODEL_BY_ID.get(canonical)
|
|
482
|
+
|
|
483
|
+
|
|
350
484
|
__all__ = [
|
|
351
485
|
"QWEN3_MODELS",
|
|
352
486
|
"QWEN3_CODER_MODELS",
|
|
353
487
|
"RL_SUPPORTED_MODELS",
|
|
354
488
|
"SFT_SUPPORTED_MODELS",
|
|
489
|
+
"THINKING_MODELS",
|
|
355
490
|
"EXPERIMENTAL_MODELS",
|
|
356
491
|
"CORE_MODELS",
|
|
357
492
|
"ExperimentalWarning",
|
|
@@ -373,5 +508,7 @@ __all__ = [
|
|
|
373
508
|
"core_model_ids",
|
|
374
509
|
"format_supported_models",
|
|
375
510
|
"training_modes_for_model",
|
|
511
|
+
"supports_thinking",
|
|
512
|
+
"get_model_metadata",
|
|
376
513
|
]
|
|
377
514
|
|
synth_ai/api/train/__init__.py
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from typing import Any
|
|
4
4
|
|
|
5
5
|
__all__ = ["register", "train_command"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def register(cli: Any) -> None:
|
|
9
|
+
from synth_ai.cli.train import register as _register # local import avoids circular dependency
|
|
10
|
+
|
|
11
|
+
_register(cli)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def train_command(*args: Any, **kwargs: Any) -> Any:
|
|
15
|
+
from synth_ai.cli.train import train_command as _train_command # local import avoids cycle
|
|
16
|
+
|
|
17
|
+
return _train_command(*args, **kwargs)
|
synth_ai/api/train/builders.py
CHANGED
|
@@ -74,8 +74,14 @@ def build_rl_payload(
|
|
|
74
74
|
idempotency: str | None,
|
|
75
75
|
allow_experimental: bool | None = None,
|
|
76
76
|
) -> RLBuildResult:
|
|
77
|
+
# Load and validate config with SDK-level checks
|
|
78
|
+
from synth_ai.api.train.utils import load_toml
|
|
79
|
+
from synth_ai.cli.commands.train.validation import validate_rl_config
|
|
80
|
+
|
|
77
81
|
try:
|
|
78
|
-
|
|
82
|
+
raw_config = load_toml(config_path)
|
|
83
|
+
validated_config = validate_rl_config(raw_config) # Adds defaults & validates
|
|
84
|
+
rl_cfg = RLConfig.from_mapping(validated_config)
|
|
79
85
|
except ValidationError as exc:
|
|
80
86
|
raise click.ClickException(_format_validation_error(config_path, exc)) from exc
|
|
81
87
|
|
|
@@ -110,8 +116,8 @@ def build_rl_payload(
|
|
|
110
116
|
"Task app URL required (provide --task-url or set services.task_url in TOML)"
|
|
111
117
|
)
|
|
112
118
|
|
|
113
|
-
model_source = (model_cfg.source or "").strip()
|
|
114
|
-
model_base = (model_cfg.base or "").strip()
|
|
119
|
+
model_source = (model_cfg.source or "").strip() if model_cfg else ""
|
|
120
|
+
model_base = (model_cfg.base or "").strip() if model_cfg else ""
|
|
115
121
|
override_model = (overrides.get("model") or "").strip()
|
|
116
122
|
if override_model:
|
|
117
123
|
model_source = override_model
|