synth-ai 0.2.9.dev7__py3-none-any.whl → 0.2.9.dev8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of synth-ai might be problematic. Click here for more details.
- examples/__init__.py +16 -0
- examples/crafter_debug_render.py +8 -11
- examples/qwen_coder/README.md +102 -0
- examples/qwen_coder/_shared.py +113 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +61 -0
- examples/qwen_coder/configs/coder_lora_4b.toml +57 -0
- examples/qwen_coder/configs/coder_lora_small.toml +58 -0
- examples/qwen_coder/generate_dataset.py +98 -0
- examples/qwen_coder/infer_ft_smoke.py +64 -0
- examples/qwen_coder/infer_prod_proxy.py +73 -0
- examples/qwen_coder/infer_via_synth.py +87 -0
- examples/qwen_coder/scripts/infer_coder.sh +18 -0
- examples/qwen_coder/scripts/train_coder_30b.sh +21 -0
- examples/qwen_coder/sft_full_17b.py +103 -0
- examples/qwen_coder/sft_lora_30b.py +110 -0
- examples/qwen_coder/subset_jsonl.py +38 -0
- examples/qwen_coder/validate_jsonl.py +59 -0
- examples/rl/run_eval.py +36 -37
- examples/rl/run_rl_and_save.py +5 -5
- examples/rl/task_app/math_single_step.py +65 -43
- examples/rl/task_app/math_task_app.py +3 -3
- examples/sft/README.md +139 -0
- examples/sft/configs/crafter_fft_qwen0p6b.toml +44 -0
- examples/sft/configs/crafter_lora_qwen0p6b.toml +45 -0
- examples/sft/evaluate.py +117 -0
- examples/sft/export_dataset.py +117 -0
- examples/sft/generate_traces.py +162 -0
- examples/swe/__init__.py +12 -0
- examples/swe/task_app/README.md +105 -0
- examples/swe/task_app/__init__.py +2 -0
- examples/swe/task_app/grpo_swe_mini.py +571 -0
- examples/swe/task_app/grpo_swe_mini_task_app.py +136 -0
- examples/swe/task_app/hosted/README.md +173 -0
- examples/swe/task_app/hosted/__init__.py +5 -0
- examples/swe/task_app/hosted/branching.py +143 -0
- examples/swe/task_app/hosted/environment_routes.py +1289 -0
- examples/swe/task_app/hosted/envs/__init__.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/__init__.py +6 -0
- examples/swe/task_app/hosted/envs/crafter/app.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/environment.py +522 -0
- examples/swe/task_app/hosted/envs/crafter/policy.py +478 -0
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +108 -0
- examples/swe/task_app/hosted/envs/crafter/shared.py +305 -0
- examples/swe/task_app/hosted/envs/crafter/tools.py +47 -0
- examples/swe/task_app/hosted/envs/mini_swe/__init__.py +8 -0
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +1164 -0
- examples/swe/task_app/hosted/envs/mini_swe/policy.py +355 -0
- examples/swe/task_app/hosted/envs/mini_swe/shared.py +83 -0
- examples/swe/task_app/hosted/envs/mini_swe/tools.py +96 -0
- examples/swe/task_app/hosted/hosted_app.py +204 -0
- examples/swe/task_app/hosted/inference/__init__.py +5 -0
- examples/swe/task_app/hosted/inference/openai_client.py +618 -0
- examples/swe/task_app/hosted/main.py +100 -0
- examples/swe/task_app/hosted/policy_routes.py +1079 -0
- examples/swe/task_app/hosted/registry.py +195 -0
- examples/swe/task_app/hosted/rollout.py +1869 -0
- examples/swe/task_app/hosted/storage/__init__.py +5 -0
- examples/swe/task_app/hosted/storage/volume.py +211 -0
- examples/swe/task_app/hosted/test_agents.py +161 -0
- examples/swe/task_app/hosted/test_service.py +137 -0
- examples/swe/task_app/hosted/utils.py +62 -0
- examples/vlm/README.md +68 -0
- examples/vlm/configs/crafter_vlm_gpt4o.toml +44 -0
- examples/vlm/crafter_image_only_agent.py +207 -0
- examples/vlm/crafter_openai_vlm_agent.py +277 -0
- examples/vlm/filter_image_rows.py +63 -0
- examples/vlm/run_crafter_vlm_benchmark.py +316 -0
- examples/warming_up_to_rl/analyze_trace_db.py +5 -5
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +11 -1
- examples/warming_up_to_rl/export_trace_sft.py +78 -21
- examples/warming_up_to_rl/groq_test.py +4 -4
- examples/warming_up_to_rl/manage_secrets.py +13 -18
- examples/warming_up_to_rl/run_eval.py +42 -44
- examples/warming_up_to_rl/run_fft_and_save.py +11 -16
- examples/warming_up_to_rl/run_local_rollout.py +1 -3
- examples/warming_up_to_rl/run_local_rollout_modal.py +2 -4
- examples/warming_up_to_rl/run_local_rollout_parallel.py +1 -4
- examples/warming_up_to_rl/run_local_rollout_traced.py +3 -5
- examples/warming_up_to_rl/run_rl_and_save.py +5 -6
- examples/warming_up_to_rl/run_rollout_remote.py +8 -10
- examples/warming_up_to_rl/task_app/README.md +6 -2
- examples/warming_up_to_rl/task_app/grpo_crafter.py +234 -35
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +2 -3
- examples/warming_up_to_rl/task_app/synth_envs_hosted/__init__.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/branching.py +9 -11
- examples/warming_up_to_rl/task_app/synth_envs_hosted/environment_routes.py +131 -114
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +101 -41
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +73 -51
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +14 -6
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +16 -16
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +32 -34
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +94 -31
- examples/warming_up_to_rl/task_app/synth_envs_hosted/main.py +0 -2
- examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +303 -203
- examples/warming_up_to_rl/task_app/synth_envs_hosted/registry.py +21 -23
- examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +328 -225
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +13 -13
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_agents.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_service.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +4 -3
- synth/__init__.py +14 -0
- synth_ai/__init__.py +26 -4
- synth_ai/api/models/supported.py +376 -0
- synth_ai/api/train/builders.py +128 -21
- synth_ai/api/train/cli.py +80 -64
- synth_ai/api/train/config_finder.py +7 -2
- synth_ai/api/train/env_resolver.py +1 -1
- synth_ai/api/train/pollers.py +2 -1
- synth_ai/api/train/supported_algos.py +139 -0
- synth_ai/api/train/task_app.py +1 -2
- synth_ai/api/train/utils.py +13 -44
- synth_ai/cli/__init__.py +8 -0
- synth_ai/cli/_modal_wrapper.py +28 -0
- synth_ai/cli/_typer_patch.py +49 -0
- synth_ai/cli/balance.py +1 -2
- synth_ai/cli/calc.py +1 -1
- synth_ai/cli/demo.py +2 -1
- synth_ai/cli/recent.py +2 -2
- synth_ai/cli/rl_demo.py +2 -1
- synth_ai/cli/root.py +11 -13
- synth_ai/cli/status.py +2 -2
- synth_ai/cli/task_apps.py +529 -179
- synth_ai/cli/traces.py +6 -4
- synth_ai/cli/watch.py +12 -18
- synth_ai/demo_registry.py +1 -1
- synth_ai/demos/core/cli.py +36 -43
- synth_ai/demos/demo_task_apps/__init__.py +3 -3
- synth_ai/demos/demo_task_apps/core.py +17 -25
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +3 -4
- synth_ai/demos/demo_task_apps/math/app.py +2 -1
- synth_ai/demos/demo_task_apps/math/deploy_modal.py +3 -4
- synth_ai/demos/demo_task_apps/math/modal_task_app.py +16 -18
- synth_ai/demos/demo_task_apps/math/task_app_entry.py +0 -1
- synth_ai/environments/examples/crafter_classic/environment.py +76 -1
- synth_ai/environments/reproducibility/tree.py +2 -5
- synth_ai/environments/service/app.py +11 -12
- synth_ai/environments/service/core_routes.py +4 -7
- synth_ai/environments/stateful/engine.py +1 -1
- synth_ai/environments/tasks/core.py +1 -0
- synth_ai/environments/tasks/filters.py +5 -6
- synth_ai/environments/tasks/utils.py +4 -5
- synth_ai/handshake.py +9 -9
- synth_ai/http.py +1 -1
- synth_ai/http_client.py +18 -10
- synth_ai/inference/client.py +15 -5
- synth_ai/jobs/client.py +78 -83
- synth_ai/learning/__init__.py +41 -6
- synth_ai/learning/algorithms.py +14 -0
- synth_ai/learning/client.py +91 -24
- synth_ai/learning/config.py +2 -38
- synth_ai/learning/ft_client.py +4 -59
- synth_ai/learning/health.py +5 -6
- synth_ai/learning/jobs.py +31 -47
- synth_ai/{rl → learning/rl}/__init__.py +14 -4
- synth_ai/learning/rl/client.py +267 -0
- synth_ai/learning/rl/config.py +31 -0
- synth_ai/{rl → learning/rl}/contracts.py +5 -8
- synth_ai/{rl → learning/rl}/env_keys.py +39 -15
- synth_ai/learning/rl/secrets.py +13 -0
- synth_ai/learning/rl_client.py +2 -281
- synth_ai/learning/sft/__init__.py +29 -0
- synth_ai/learning/sft/client.py +68 -0
- synth_ai/learning/sft/config.py +270 -0
- synth_ai/learning/sft/data.py +295 -0
- synth_ai/learning/sse.py +25 -24
- synth_ai/learning/validators.py +25 -28
- synth_ai/lm/__init__.py +21 -47
- synth_ai/main.py +4 -0
- synth_ai/task/__init__.py +25 -27
- synth_ai/task/apps/__init__.py +7 -8
- synth_ai/task/auth.py +8 -8
- synth_ai/task/client.py +14 -14
- synth_ai/task/contracts.py +36 -35
- synth_ai/task/datasets.py +6 -5
- synth_ai/task/errors.py +10 -10
- synth_ai/task/health.py +17 -9
- synth_ai/task/json.py +58 -23
- synth_ai/task/proxy.py +13 -9
- synth_ai/task/rubrics.py +16 -15
- synth_ai/task/server.py +12 -12
- synth_ai/task/tracing_utils.py +4 -4
- synth_ai/task/vendors.py +5 -6
- synth_ai/tracing_v3/__init__.py +2 -0
- synth_ai/tracing_v3/abstractions.py +21 -4
- synth_ai/tracing_v3/decorators.py +18 -16
- synth_ai/tracing_v3/hooks.py +5 -5
- synth_ai/tracing_v3/llm_call_record_helpers.py +6 -6
- synth_ai/tracing_v3/session_tracer.py +40 -14
- synth_ai/tracing_v3/storage/base.py +85 -0
- synth_ai/tracing_v3/storage/config.py +21 -8
- synth_ai/tracing_v3/storage/factory.py +10 -7
- synth_ai/tracing_v3/storage/utils.py +4 -2
- synth_ai/tracing_v3/turso/daemon.py +7 -2
- synth_ai/tracing_v3/turso/models.py +2 -2
- synth_ai/tracing_v3/turso/native_manager.py +1173 -0
- synth_ai/tracing_v3/utils.py +4 -4
- synth_ai/v0/api/__init__.py +8 -0
- synth_ai/v0/api/models/__init__.py +8 -0
- synth_ai/v0/api/models/supported.py +8 -0
- synth_ai/v0/config/__init__.py +15 -0
- synth_ai/v0/config/base_url.py +12 -0
- synth_ai/v0/lm/__init__.py +51 -0
- synth_ai/{lm → v0/lm}/caching/ephemeral.py +2 -2
- synth_ai/{lm → v0/lm}/caching/handler.py +4 -4
- synth_ai/{lm → v0/lm}/caching/initialize.py +1 -1
- synth_ai/{lm → v0/lm}/caching/persistent.py +1 -1
- synth_ai/{lm → v0/lm}/config.py +6 -1
- synth_ai/{lm → v0/lm}/core/all.py +9 -9
- synth_ai/{lm → v0/lm}/core/main.py +6 -6
- synth_ai/{lm → v0/lm}/core/main_v3.py +10 -10
- synth_ai/{lm → v0/lm}/core/synth_models.py +2 -14
- synth_ai/{lm → v0/lm}/core/vendor_clients.py +2 -2
- synth_ai/{lm → v0/lm}/overrides.py +2 -2
- synth_ai/{lm → v0/lm}/provider_support/anthropic.py +4 -4
- synth_ai/{lm → v0/lm}/provider_support/openai.py +5 -5
- synth_ai/{lm → v0/lm}/structured_outputs/handler.py +5 -5
- synth_ai/{lm → v0/lm}/structured_outputs/rehabilitate.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/core/anthropic_api.py +9 -9
- synth_ai/{lm → v0/lm}/vendors/core/gemini_api.py +5 -5
- synth_ai/{lm → v0/lm}/vendors/core/mistral_api.py +5 -5
- synth_ai/{lm → v0/lm}/vendors/core/openai_api.py +10 -10
- synth_ai/{lm → v0/lm}/vendors/openai_standard.py +8 -8
- synth_ai/{lm → v0/lm}/vendors/openai_standard_responses.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/custom_endpoint.py +3 -3
- synth_ai/{lm → v0/lm}/vendors/supported/deepseek.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/grok.py +2 -2
- synth_ai/{lm → v0/lm}/vendors/supported/groq.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/supported/ollama.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/supported/openrouter.py +3 -3
- synth_ai/{lm → v0/lm}/vendors/supported/together.py +1 -1
- synth_ai/{lm → v0/lm}/vendors/synth_client.py +1 -1
- synth_ai/v0/tracing_v3/__init__.py +10 -0
- synth_ai/v0/tracing_v3/abstractions.py +3 -0
- synth_ai/v0/tracing_v3/decorators.py +3 -0
- synth_ai/v0/tracing_v3/llm_call_record_helpers.py +3 -0
- synth_ai/v0/tracing_v3/session_tracer.py +3 -0
- synth_ai-0.2.9.dev8.dist-info/METADATA +191 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev8.dist-info}/RECORD +268 -238
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev8.dist-info}/top_level.txt +1 -0
- examples/common_old/backend.py +0 -20
- examples/evals_old/README.md +0 -98
- examples/evals_old/__init__.py +0 -6
- examples/evals_old/compare_models.py +0 -1038
- examples/evals_old/example_log.md +0 -145
- examples/evals_old/run_demo.sh +0 -126
- examples/evals_old/trace_analysis.py +0 -270
- examples/finetuning_old/_backup_synth_qwen/config.toml +0 -29
- examples/finetuning_old/_backup_synth_qwen/example_log.md +0 -324
- examples/finetuning_old/_backup_synth_qwen/filter_traces.py +0 -60
- examples/finetuning_old/_backup_synth_qwen/filter_traces_achievements.py +0 -243
- examples/finetuning_old/_backup_synth_qwen/purge_v3_traces.py +0 -109
- examples/finetuning_old/_backup_synth_qwen/react_agent_lm.py +0 -1924
- examples/finetuning_old/_backup_synth_qwen/readme.md +0 -49
- examples/finetuning_old/_backup_synth_qwen/run_crafter_qwen4b.py +0 -114
- examples/finetuning_old/_backup_synth_qwen/run_demo.sh +0 -195
- examples/finetuning_old/_backup_synth_qwen/sft_kickoff.py +0 -119
- examples/finetuning_old/synth_qwen_v1/README.md +0 -68
- examples/finetuning_old/synth_qwen_v1/filter_traces.py +0 -60
- examples/finetuning_old/synth_qwen_v1/filter_traces_achievements.py +0 -243
- examples/finetuning_old/synth_qwen_v1/finetune.py +0 -46
- examples/finetuning_old/synth_qwen_v1/hello_ft_model.py +0 -71
- examples/finetuning_old/synth_qwen_v1/infer.py +0 -36
- examples/finetuning_old/synth_qwen_v1/poll.py +0 -46
- examples/finetuning_old/synth_qwen_v1/prepare_data.py +0 -35
- examples/finetuning_old/synth_qwen_v1/purge_v3_traces.py +0 -109
- examples/finetuning_old/synth_qwen_v1/react_agent_lm.py +0 -1933
- examples/finetuning_old/synth_qwen_v1/run_crafter_sft_job.py +0 -210
- examples/finetuning_old/synth_qwen_v1/run_ft_job.py +0 -237
- examples/finetuning_old/synth_qwen_v1/upload_data.py +0 -34
- examples/finetuning_old/synth_qwen_v1/util.py +0 -152
- examples/rl_old/task_app.py +0 -1131
- examples/warming_up_to_rl/old/event_rewards.md +0 -234
- examples/warming_up_to_rl/old/notes.md +0 -73
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py +0 -738
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/filter_traces_sft_turso.py +0 -580
- synth_ai/experimental/synth_oss.py +0 -445
- synth_ai/learning/filtering.py +0 -0
- synth_ai/learning/offline/dpo.py +0 -0
- synth_ai/learning/offline/providers.py +0 -7
- synth_ai/learning/offline/sft.py +0 -0
- synth_ai/learning/offline/shared.py +0 -0
- synth_ai/learning/online/grpo.py +0 -0
- synth_ai/learning/online/irft.py +0 -0
- synth_ai/learning/prompts/banking77_injection_eval.py +0 -168
- synth_ai/learning/prompts/gepa.py +0 -0
- synth_ai/learning/prompts/hello_world_in_context_injection_ex.py +0 -211
- synth_ai/learning/prompts/mipro.py +0 -289
- synth_ai/learning/prompts/random_search.py +0 -249
- synth_ai/learning/prompts/run_mipro_banking77.py +0 -172
- synth_ai/learning/prompts/run_random_search_banking77.py +0 -329
- synth_ai/rl/secrets.py +0 -19
- synth_ai/scripts/verify_rewards.py +0 -100
- synth_ai/tracing/__init__.py +0 -30
- synth_ai/tracing_v1/__init__.py +0 -33
- synth_ai/tracing_v3/turso/__init__.py +0 -25
- synth_ai/tracing_v3/turso/manager.py +0 -838
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.9.dev7.dist-info/METADATA +0 -131
- /synth_ai/{lm → v0/lm}/caching/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/caching/constants.py +0 -0
- /synth_ai/{lm → v0/lm}/caching/dbs.py +0 -0
- /synth_ai/{lm → v0/lm}/constants.py +0 -0
- /synth_ai/{lm → v0/lm}/core/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/core/exceptions.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/monitor.py +0 -0
- /synth_ai/{lm → v0/lm}/cost/statefulness.py +0 -0
- /synth_ai/{lm → v0/lm}/injection.py +0 -0
- /synth_ai/{lm → v0/lm}/provider_support/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/provider_support/suppress_logging.py +0 -0
- /synth_ai/{lm → v0/lm}/structured_outputs/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/structured_outputs/inject.py +0 -0
- /synth_ai/{lm → v0/lm}/tools/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/tools/base.py +0 -0
- /synth_ai/{lm → v0/lm}/unified_interface.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/base.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/core/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/core/synth_dev_api.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/local/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/local/ollama.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/retries.py +0 -0
- /synth_ai/{lm → v0/lm}/vendors/supported/__init__.py +0 -0
- /synth_ai/{lm → v0/lm}/warmup.py +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev8.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev8.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.9.dev7.dist-info → synth_ai-0.2.9.dev8.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,7 +8,7 @@ import tarfile
|
|
|
8
8
|
import tempfile
|
|
9
9
|
from datetime import datetime
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
11
|
+
from typing import Any
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class VolumeStorage:
|
|
@@ -57,8 +57,8 @@ class VolumeStorage:
|
|
|
57
57
|
|
|
58
58
|
def create_archive(
|
|
59
59
|
self,
|
|
60
|
-
state_dict:
|
|
61
|
-
meta:
|
|
60
|
+
state_dict: dict[str, Any],
|
|
61
|
+
meta: dict[str, Any],
|
|
62
62
|
) -> bytes:
|
|
63
63
|
"""Create a tar.gz archive with state and metadata."""
|
|
64
64
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
@@ -88,7 +88,7 @@ class VolumeStorage:
|
|
|
88
88
|
|
|
89
89
|
return compressed
|
|
90
90
|
|
|
91
|
-
def extract_archive(self, archive_bytes: bytes) -> tuple[
|
|
91
|
+
def extract_archive(self, archive_bytes: bytes) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
92
92
|
"""Extract state and metadata from a tar.gz archive."""
|
|
93
93
|
# Decompress
|
|
94
94
|
tar_bytes = gzip.decompress(archive_bytes)
|
|
@@ -106,10 +106,10 @@ class VolumeStorage:
|
|
|
106
106
|
tar.extractall(tmppath)
|
|
107
107
|
|
|
108
108
|
# Read state and meta
|
|
109
|
-
with open(tmppath / "state.json"
|
|
109
|
+
with open(tmppath / "state.json") as f:
|
|
110
110
|
state = json.load(f)
|
|
111
111
|
|
|
112
|
-
with open(tmppath / "meta.json"
|
|
112
|
+
with open(tmppath / "meta.json") as f:
|
|
113
113
|
meta = json.load(f)
|
|
114
114
|
|
|
115
115
|
return state, meta
|
|
@@ -122,9 +122,9 @@ class VolumeStorage:
|
|
|
122
122
|
self,
|
|
123
123
|
rl_run_id: str,
|
|
124
124
|
kind: str,
|
|
125
|
-
state_dict:
|
|
126
|
-
config:
|
|
127
|
-
parent_snapshot_id:
|
|
125
|
+
state_dict: dict[str, Any],
|
|
126
|
+
config: dict[str, Any] | None = None,
|
|
127
|
+
parent_snapshot_id: str | None = None,
|
|
128
128
|
) -> tuple[str, str, int]:
|
|
129
129
|
"""Save a snapshot and return (snapshot_id, path, size)."""
|
|
130
130
|
# Build metadata
|
|
@@ -166,7 +166,7 @@ class VolumeStorage:
|
|
|
166
166
|
rl_run_id: str,
|
|
167
167
|
kind: str,
|
|
168
168
|
snapshot_id: str,
|
|
169
|
-
) -> tuple[
|
|
169
|
+
) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
170
170
|
"""Load a snapshot and return (state_dict, meta)."""
|
|
171
171
|
path = self.get_snapshot_path(rl_run_id, kind, snapshot_id)
|
|
172
172
|
|
|
@@ -182,7 +182,7 @@ class VolumeStorage:
|
|
|
182
182
|
def append_to_index(
|
|
183
183
|
self,
|
|
184
184
|
rl_run_id: str,
|
|
185
|
-
meta:
|
|
185
|
+
meta: dict[str, Any],
|
|
186
186
|
) -> None:
|
|
187
187
|
"""Append metadata to the run's index file."""
|
|
188
188
|
index_path = self.get_index_path(rl_run_id)
|
|
@@ -191,7 +191,7 @@ class VolumeStorage:
|
|
|
191
191
|
with open(index_path, "a") as f:
|
|
192
192
|
f.write(json.dumps(meta) + "\n")
|
|
193
193
|
|
|
194
|
-
def read_index(self, rl_run_id: str) -> list[
|
|
194
|
+
def read_index(self, rl_run_id: str) -> list[dict[str, Any]]:
|
|
195
195
|
"""Read all entries from a run's index file."""
|
|
196
196
|
index_path = self.get_index_path(rl_run_id)
|
|
197
197
|
|
|
@@ -199,7 +199,7 @@ class VolumeStorage:
|
|
|
199
199
|
return []
|
|
200
200
|
|
|
201
201
|
entries = []
|
|
202
|
-
with open(index_path
|
|
202
|
+
with open(index_path) as f:
|
|
203
203
|
for line in f:
|
|
204
204
|
if line.strip():
|
|
205
205
|
entries.append(json.loads(line))
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Utility functions for the task service."""
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
3
5
|
import numpy as np
|
|
4
|
-
from typing import Any, Dict, List, Union
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def convert_numpy_to_python(obj: Any) -> Any:
|
|
@@ -22,13 +23,13 @@ def convert_numpy_to_python(obj: Any) -> Any:
|
|
|
22
23
|
return obj.tolist()
|
|
23
24
|
elif isinstance(obj, dict):
|
|
24
25
|
return {key: convert_numpy_to_python(value) for key, value in obj.items()}
|
|
25
|
-
elif isinstance(obj,
|
|
26
|
+
elif isinstance(obj, list | tuple):
|
|
26
27
|
return [convert_numpy_to_python(item) for item in obj]
|
|
27
28
|
else:
|
|
28
29
|
return obj
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
def sanitize_observation(observation:
|
|
32
|
+
def sanitize_observation(observation: dict[str, Any]) -> dict[str, Any]:
|
|
32
33
|
"""
|
|
33
34
|
Sanitize observation data for JSON serialization.
|
|
34
35
|
|
synth/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
_HELP_TEXT = """Synth-AI SDK
|
|
2
|
+
|
|
3
|
+
Quickstart:
|
|
4
|
+
pip install synth-ai
|
|
5
|
+
import synth_ai
|
|
6
|
+
uvx synth-ai setup
|
|
7
|
+
|
|
8
|
+
Docs → https://docs.usesynth.ai/sdk/get-started
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
raise ImportError(
|
|
12
|
+
"No module named 'synth'. Did you mean 'synth_ai'?\n\n"
|
|
13
|
+
f"{_HELP_TEXT}"
|
|
14
|
+
)
|
synth_ai/__init__.py
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Synth AI - Software for aiding the best and multiplying the will.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
1
|
# Environment exports - moved from synth-env
|
|
6
2
|
from synth_ai.environments import * # noqa
|
|
7
3
|
import synth_ai.environments as environments # expose module name for __all__
|
|
@@ -21,11 +17,35 @@ try:
|
|
|
21
17
|
except Exception:
|
|
22
18
|
AsyncOpenAI = OpenAI = None # type: ignore
|
|
23
19
|
|
|
20
|
+
# For LLMs
|
|
21
|
+
try:
|
|
22
|
+
from .main import SynthAI
|
|
23
|
+
except Exception:
|
|
24
|
+
SynthAI = None
|
|
25
|
+
|
|
24
26
|
# Legacy tracing v1 is not required for v3 usage and can be unavailable in minimal envs.
|
|
25
27
|
tracing = None # type: ignore
|
|
26
28
|
EventPartitionElement = RewardSignal = SystemTrace = TrainingQuestion = None # type: ignore
|
|
27
29
|
trace_event_async = trace_event_sync = upload = None # type: ignore
|
|
28
30
|
|
|
31
|
+
SDK_HELP = """
|
|
32
|
+
Synth-AI SDK
|
|
33
|
+
|
|
34
|
+
Quickstart:
|
|
35
|
+
pip install synth-ai
|
|
36
|
+
import synth_ai
|
|
37
|
+
uvx synth-ai setup
|
|
38
|
+
|
|
39
|
+
Docs → https://docs.usesynth.ai/sdk/get-started
|
|
40
|
+
""".strip()
|
|
41
|
+
|
|
42
|
+
__doc__ = SDK_HELP
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def help() -> str:
|
|
46
|
+
"""Return a concise quickstart for the Synth-AI SDK."""
|
|
47
|
+
return SDK_HELP
|
|
48
|
+
|
|
29
49
|
__version__ = "0.2.6.dev4"
|
|
30
50
|
__all__ = [
|
|
31
51
|
"LM",
|
|
@@ -34,4 +54,6 @@ __all__ = [
|
|
|
34
54
|
"Anthropic",
|
|
35
55
|
"AsyncAnthropic",
|
|
36
56
|
"environments",
|
|
57
|
+
"help",
|
|
58
|
+
"SynthAI"
|
|
37
59
|
] # Explicitly define public API (v1 tracing omitted in minimal env)
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"""Catalog of Synth-hosted base models and helpers (core vs experimental)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import warnings
|
|
7
|
+
from collections.abc import Iterable, Iterator, Sequence
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
# ------------------------------------------------------------------------------
|
|
11
|
+
# Model families
|
|
12
|
+
# ------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
QWEN3_MODELS: list[str] = [
|
|
15
|
+
# Core Qwen3 base models
|
|
16
|
+
"Qwen/Qwen3-0.6B",
|
|
17
|
+
"Qwen/Qwen3-1.7B",
|
|
18
|
+
"Qwen/Qwen3-4B",
|
|
19
|
+
"Qwen/Qwen3-8B",
|
|
20
|
+
"Qwen/Qwen3-14B",
|
|
21
|
+
"Qwen/Qwen3-30B-A3B",
|
|
22
|
+
"Qwen/Qwen3-32B",
|
|
23
|
+
# Include 4B-2507 and Thinking variants used in RL
|
|
24
|
+
"Qwen/Qwen3-4B-Thinking-2507",
|
|
25
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
26
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# Qwen3 Coder family (backend-supported); text-only, SFT/inference
|
|
30
|
+
QWEN3_CODER_MODELS: list[str] = [
|
|
31
|
+
# Instruct variants used for coding tasks
|
|
32
|
+
"Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
|
33
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
# Training support sets
|
|
37
|
+
RL_SUPPORTED_MODELS: frozenset[str] = frozenset(
|
|
38
|
+
{
|
|
39
|
+
"Qwen/Qwen3-1.7B",
|
|
40
|
+
"Qwen/Qwen3-4B",
|
|
41
|
+
"Qwen/Qwen3-4B-Thinking-2507",
|
|
42
|
+
"Qwen/Qwen3-8B",
|
|
43
|
+
"Qwen/Qwen3-14B",
|
|
44
|
+
"Qwen/Qwen3-30B-A3B",
|
|
45
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# SFT allowlist includes core Qwen3 plus Coder family
|
|
50
|
+
SFT_SUPPORTED_MODELS: frozenset[str] = frozenset([*QWEN3_MODELS, *QWEN3_CODER_MODELS])
|
|
51
|
+
|
|
52
|
+
# ------------------------------------------------------------------------------
|
|
53
|
+
# Lifecycle classification (core vs experimental)
|
|
54
|
+
# ------------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
# Which base models are considered "experimental" by default.
|
|
57
|
+
_EXPERIMENTAL_DEFAULTS: frozenset[str] = frozenset(
|
|
58
|
+
{
|
|
59
|
+
# Larger (>= 64B) or bleeding-edge variants are experimental by default.
|
|
60
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
61
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
62
|
+
# Thinking variants can fluctuate more rapidly.
|
|
63
|
+
"Qwen/Qwen3-30B-A3B-Thinking-2507",
|
|
64
|
+
"Qwen/Qwen3-4B-Thinking-2507",
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _parse_experimental_env() -> frozenset[str]:
|
|
70
|
+
raw = os.getenv("SDK_EXPERIMENTAL_MODELS", "").strip()
|
|
71
|
+
if not raw:
|
|
72
|
+
return frozenset()
|
|
73
|
+
return frozenset(s.strip() for s in raw.split(",") if s.strip())
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Final experimental set (defaults ∪ optional env override)
|
|
77
|
+
EXPERIMENTAL_MODELS: frozenset[str] = frozenset(_EXPERIMENTAL_DEFAULTS | _parse_experimental_env())
|
|
78
|
+
|
|
79
|
+
# Build catalog entries for both core and coder families under unified "Qwen3"
|
|
80
|
+
_ALL_QWEN3_IDS: list[str] = [*QWEN3_MODELS, *QWEN3_CODER_MODELS]
|
|
81
|
+
|
|
82
|
+
CORE_MODELS: frozenset[str] = frozenset(m for m in _ALL_QWEN3_IDS if m not in EXPERIMENTAL_MODELS)
|
|
83
|
+
|
|
84
|
+
# ------------------------------------------------------------------------------
|
|
85
|
+
# Experimental gating / warnings
|
|
86
|
+
# ------------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ExperimentalWarning(UserWarning):
|
|
90
|
+
"""Warning for usage of experimental SDK models/APIs."""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _experimental_enabled() -> bool:
|
|
94
|
+
# Global toggle to permit experimental usage
|
|
95
|
+
return os.getenv("SDK_EXPERIMENTAL", "0") == "1"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _warn_if_experimental(model_id: str) -> None:
|
|
99
|
+
if model_id in EXPERIMENTAL_MODELS:
|
|
100
|
+
warnings.warn(
|
|
101
|
+
f"Model '{model_id}' is experimental and may change or be removed.",
|
|
102
|
+
category=ExperimentalWarning,
|
|
103
|
+
stacklevel=2,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# ------------------------------------------------------------------------------
|
|
108
|
+
# Model metadata + catalog
|
|
109
|
+
# ------------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass(frozen=True, slots=True)
|
|
113
|
+
class SupportedModel:
|
|
114
|
+
"""Metadata describing a supported base model."""
|
|
115
|
+
|
|
116
|
+
model_id: str
|
|
117
|
+
family: str
|
|
118
|
+
provider: str
|
|
119
|
+
modalities: tuple[str, ...] = ()
|
|
120
|
+
training_modes: tuple[str, ...] = ()
|
|
121
|
+
lifecycle: str = "core" # "core" | "experimental"
|
|
122
|
+
|
|
123
|
+
def as_dict(self) -> dict[str, object]:
|
|
124
|
+
data: dict[str, object] = {
|
|
125
|
+
"model_id": self.model_id,
|
|
126
|
+
"family": self.family,
|
|
127
|
+
"provider": self.provider,
|
|
128
|
+
"lifecycle": self.lifecycle,
|
|
129
|
+
}
|
|
130
|
+
if self.modalities:
|
|
131
|
+
data["modalities"] = list(self.modalities)
|
|
132
|
+
if self.training_modes:
|
|
133
|
+
data["training_modes"] = list(self.training_modes)
|
|
134
|
+
return data
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
SUPPORTED_MODELS: tuple[SupportedModel, ...] = tuple(
|
|
138
|
+
SupportedModel(
|
|
139
|
+
model_id=model,
|
|
140
|
+
family="Qwen3",
|
|
141
|
+
provider="Qwen",
|
|
142
|
+
modalities=("text",),
|
|
143
|
+
training_modes=tuple(
|
|
144
|
+
sorted(
|
|
145
|
+
{
|
|
146
|
+
*(("sft",) if model in SFT_SUPPORTED_MODELS else ()),
|
|
147
|
+
*(("rl",) if model in RL_SUPPORTED_MODELS else ()),
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
),
|
|
151
|
+
lifecycle=("experimental" if model in EXPERIMENTAL_MODELS else "core"),
|
|
152
|
+
)
|
|
153
|
+
for model in _ALL_QWEN3_IDS
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
_BASE_LOOKUP = {model.model_id.lower(): model.model_id for model in SUPPORTED_MODELS}
|
|
157
|
+
SUPPORTED_BASE_MODEL_IDS: frozenset[str] = frozenset(_BASE_LOOKUP.values())
|
|
158
|
+
FINE_TUNED_PREFIXES: tuple[str, ...] = ("ft:", "fft:", "qft:", "rl:")
|
|
159
|
+
_MODEL_BY_ID = {model.model_id: model for model in SUPPORTED_MODELS}
|
|
160
|
+
|
|
161
|
+
# ------------------------------------------------------------------------------
|
|
162
|
+
# Public API
|
|
163
|
+
# ------------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class UnsupportedModelError(ValueError):
|
|
167
|
+
"""Raised when a model identifier is not supported by Synth."""
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _extract_base_model(candidate: str, *, allow_finetuned_prefixes: bool) -> str | None:
|
|
171
|
+
cleaned = candidate.strip()
|
|
172
|
+
lowered = cleaned.lower()
|
|
173
|
+
base = _BASE_LOOKUP.get(lowered)
|
|
174
|
+
if base:
|
|
175
|
+
return base
|
|
176
|
+
if not allow_finetuned_prefixes or ":" not in cleaned:
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
segments = cleaned.split(":")
|
|
180
|
+
for segment in segments[1:]:
|
|
181
|
+
candidate_base = segment.strip()
|
|
182
|
+
if not candidate_base:
|
|
183
|
+
continue
|
|
184
|
+
base = _BASE_LOOKUP.get(candidate_base.lower())
|
|
185
|
+
if base:
|
|
186
|
+
return base
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def ensure_supported_model(
|
|
191
|
+
model_id: str,
|
|
192
|
+
*,
|
|
193
|
+
allow_finetuned_prefixes: bool = True,
|
|
194
|
+
) -> str:
|
|
195
|
+
"""Validate that *model_id* resolves to a supported base model (no lifecycle gate)."""
|
|
196
|
+
candidate = (model_id or "").strip()
|
|
197
|
+
if not candidate:
|
|
198
|
+
raise UnsupportedModelError("Model identifier is empty")
|
|
199
|
+
|
|
200
|
+
base = _extract_base_model(candidate, allow_finetuned_prefixes=allow_finetuned_prefixes)
|
|
201
|
+
if base:
|
|
202
|
+
return base
|
|
203
|
+
|
|
204
|
+
raise UnsupportedModelError(
|
|
205
|
+
f"Model '{candidate}' is not supported. Call supported_model_ids() for available base models."
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def ensure_allowed_model(
|
|
210
|
+
model_id: str,
|
|
211
|
+
*,
|
|
212
|
+
allow_finetuned_prefixes: bool = True,
|
|
213
|
+
allow_experimental: bool | None = None,
|
|
214
|
+
) -> str:
|
|
215
|
+
"""Validate support + lifecycle; gate experimental unless enabled."""
|
|
216
|
+
base = ensure_supported_model(model_id, allow_finetuned_prefixes=allow_finetuned_prefixes)
|
|
217
|
+
is_exp = base in EXPERIMENTAL_MODELS
|
|
218
|
+
allow_exp = allow_experimental if allow_experimental is not None else _experimental_enabled()
|
|
219
|
+
if is_exp and not allow_exp:
|
|
220
|
+
raise UnsupportedModelError(
|
|
221
|
+
f"Model '{base}' is experimental and disabled. "
|
|
222
|
+
"Set SDK_EXPERIMENTAL=1 or pass allow_experimental=True."
|
|
223
|
+
)
|
|
224
|
+
if is_exp:
|
|
225
|
+
_warn_if_experimental(base)
|
|
226
|
+
return base
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def normalize_model_identifier(
|
|
230
|
+
model_id: str,
|
|
231
|
+
*,
|
|
232
|
+
allow_finetuned_prefixes: bool = True,
|
|
233
|
+
) -> str:
|
|
234
|
+
"""Return a cleaned model identifier suitable for job payloads (no lifecycle gate)."""
|
|
235
|
+
canonical = ensure_supported_model(model_id, allow_finetuned_prefixes=allow_finetuned_prefixes)
|
|
236
|
+
cleaned = (model_id or "").strip()
|
|
237
|
+
if not cleaned:
|
|
238
|
+
return canonical
|
|
239
|
+
if cleaned.lower() in _BASE_LOOKUP:
|
|
240
|
+
return canonical
|
|
241
|
+
return cleaned
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def is_supported_model(model_id: str, *, allow_finetuned_prefixes: bool = True) -> bool:
|
|
245
|
+
"""Return True if *model_id* resolves to a supported base model (ignores lifecycle)."""
|
|
246
|
+
try:
|
|
247
|
+
ensure_supported_model(model_id, allow_finetuned_prefixes=allow_finetuned_prefixes)
|
|
248
|
+
except UnsupportedModelError:
|
|
249
|
+
return False
|
|
250
|
+
return True
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def is_experimental_model(model_id: str) -> bool:
|
|
254
|
+
"""Return True if *model_id* is marked experimental."""
|
|
255
|
+
try:
|
|
256
|
+
base = ensure_supported_model(model_id, allow_finetuned_prefixes=True)
|
|
257
|
+
except UnsupportedModelError:
|
|
258
|
+
return False
|
|
259
|
+
return base in EXPERIMENTAL_MODELS
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def is_core_model(model_id: str) -> bool:
|
|
263
|
+
"""Return True if *model_id* is marked core."""
|
|
264
|
+
try:
|
|
265
|
+
base = ensure_supported_model(model_id, allow_finetuned_prefixes=True)
|
|
266
|
+
except UnsupportedModelError:
|
|
267
|
+
return False
|
|
268
|
+
return base in CORE_MODELS
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def iter_supported_models(
|
|
272
|
+
*,
|
|
273
|
+
families: Sequence[str] | None = None,
|
|
274
|
+
include: Sequence[str] | None = None,
|
|
275
|
+
exclude: Sequence[str] | None = None,
|
|
276
|
+
) -> Iterator[SupportedModel]:
|
|
277
|
+
"""Yield supported models, optionally filtered by family and lifecycle."""
|
|
278
|
+
include_set = {s.lower() for s in include} if include else None
|
|
279
|
+
exclude_set = {s.lower() for s in exclude} if exclude else None
|
|
280
|
+
fam_set = {f.lower() for f in families} if families else None
|
|
281
|
+
|
|
282
|
+
for m in SUPPORTED_MODELS:
|
|
283
|
+
if fam_set is not None and m.family.lower() not in fam_set:
|
|
284
|
+
continue
|
|
285
|
+
if include_set is not None and m.lifecycle.lower() not in include_set:
|
|
286
|
+
continue
|
|
287
|
+
if exclude_set is not None and m.lifecycle.lower() in exclude_set:
|
|
288
|
+
continue
|
|
289
|
+
yield m
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def list_supported_models(
|
|
293
|
+
*,
|
|
294
|
+
families: Sequence[str] | None = None,
|
|
295
|
+
include: Sequence[str] | None = None,
|
|
296
|
+
exclude: Sequence[str] | None = None,
|
|
297
|
+
) -> list[SupportedModel]:
|
|
298
|
+
"""Return supported models as a list for easier consumption."""
|
|
299
|
+
return list(iter_supported_models(families=families, include=include, exclude=exclude))
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def supported_model_ids(
|
|
303
|
+
*,
|
|
304
|
+
families: Sequence[str] | None = None,
|
|
305
|
+
include: Sequence[str] | None = None,
|
|
306
|
+
exclude: Sequence[str] | None = None,
|
|
307
|
+
) -> list[str]:
|
|
308
|
+
"""Return just the model identifiers for supported models."""
|
|
309
|
+
return [m.model_id for m in iter_supported_models(families=families, include=include, exclude=exclude)]
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def experimental_model_ids(*, families: Sequence[str] | None = None) -> list[str]:
|
|
313
|
+
"""Return identifiers for experimental supported models."""
|
|
314
|
+
return supported_model_ids(families=families, include=("experimental",))
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def core_model_ids(*, families: Sequence[str] | None = None) -> list[str]:
|
|
318
|
+
"""Return identifiers for core supported models."""
|
|
319
|
+
return supported_model_ids(families=families, include=("core",))
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def format_supported_models(
|
|
323
|
+
*,
|
|
324
|
+
families: Sequence[str] | None = None,
|
|
325
|
+
include: Sequence[str] | None = None,
|
|
326
|
+
exclude: Sequence[str] | None = None,
|
|
327
|
+
) -> str:
|
|
328
|
+
"""Produce a human readable table of supported models."""
|
|
329
|
+
rows: Iterable[SupportedModel] = iter_supported_models(families=families, include=include, exclude=exclude)
|
|
330
|
+
lines = ["model_id | family | provider | lifecycle | modalities | training_modes", "-" * 96]
|
|
331
|
+
for model in rows:
|
|
332
|
+
modalities = ",".join(model.modalities) or "-"
|
|
333
|
+
training = ",".join(model.training_modes) or "-"
|
|
334
|
+
lines.append(
|
|
335
|
+
f"{model.model_id} | {model.family} | {model.provider} | {model.lifecycle} | {modalities} | {training}"
|
|
336
|
+
)
|
|
337
|
+
return "\n".join(lines)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def training_modes_for_model(model_id: str) -> tuple[str, ...]:
|
|
341
|
+
"""Return the supported training modes (e.g., ('sft','rl')) for the given base model."""
|
|
342
|
+
canonical = ensure_supported_model(model_id, allow_finetuned_prefixes=True)
|
|
343
|
+
model = _MODEL_BY_ID.get(canonical)
|
|
344
|
+
if not model:
|
|
345
|
+
raise UnsupportedModelError(f"Model '{model_id}' is not registered as supported.")
|
|
346
|
+
return model.training_modes
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
__all__ = [
|
|
350
|
+
"QWEN3_MODELS",
|
|
351
|
+
"QWEN3_CODER_MODELS",
|
|
352
|
+
"RL_SUPPORTED_MODELS",
|
|
353
|
+
"SFT_SUPPORTED_MODELS",
|
|
354
|
+
"EXPERIMENTAL_MODELS",
|
|
355
|
+
"CORE_MODELS",
|
|
356
|
+
"ExperimentalWarning",
|
|
357
|
+
"SupportedModel",
|
|
358
|
+
"SUPPORTED_MODELS",
|
|
359
|
+
"SUPPORTED_BASE_MODEL_IDS",
|
|
360
|
+
"FINE_TUNED_PREFIXES",
|
|
361
|
+
"UnsupportedModelError",
|
|
362
|
+
"ensure_supported_model",
|
|
363
|
+
"ensure_allowed_model",
|
|
364
|
+
"normalize_model_identifier",
|
|
365
|
+
"is_supported_model",
|
|
366
|
+
"is_experimental_model",
|
|
367
|
+
"is_core_model",
|
|
368
|
+
"iter_supported_models",
|
|
369
|
+
"list_supported_models",
|
|
370
|
+
"supported_model_ids",
|
|
371
|
+
"experimental_model_ids",
|
|
372
|
+
"core_model_ids",
|
|
373
|
+
"format_supported_models",
|
|
374
|
+
"training_modes_for_model",
|
|
375
|
+
]
|
|
376
|
+
|