freesolo-flash-dev 0.2.57__tar.gz → 1.0.0__tar.gz
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.
- freesolo_flash_dev-1.0.0/.claude/skills/verify/SKILL.md +11 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/auto-rebake.yml +3 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/bake-kernel-cache.yml +1 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/worker-image.yml +8 -9
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/Dockerfile.worker +10 -10
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/PKG-INFO +7 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/bake_kernel_cache.py +1 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/kernel_fingerprint.py +76 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/_channel.py +0 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/_fileio.py +1 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/_update_check.py +5 -15
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/adapter_artifacts.py +0 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/catalog.py +71 -34
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/__init__.py +8 -17
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/commands.py +140 -59
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/envpush.py +2 -4
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/render.py +27 -22
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/training_doc.py +100 -33
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/client/config.py +6 -4
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/client/http.py +104 -64
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/client/runtime_secrets.py +2 -7
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/client/specs.py +7 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cost/analytical.py +133 -28
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cost/facts.py +36 -19
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cost/spec.py +31 -23
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cost/types.py +31 -7
- freesolo_flash_dev-1.0.0/flash/diagnostics.py +41 -0
- freesolo_flash_dev-1.0.0/flash/engine/accounting.py +79 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/multiturn_rollout.py +165 -39
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/recipe.py +0 -20
- freesolo_flash_dev-1.0.0/flash/engine/steps.py +79 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/vram.py +116 -10
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/__init__.py +100 -18
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/adapter.py +57 -15
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/finalize.py +13 -11
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/gpu_setup.py +5 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/grpo.py +1 -0
- freesolo_flash_dev-1.0.0/flash/engine/worker/hf.py +846 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/lora.py +11 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/opd.py +711 -529
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/opd_gkd.py +1 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/opd_vllm.py +45 -11
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/packing.py +30 -8
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/lifecycle.py +28 -5
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/liger.py +8 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/memory.py +6 -4
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/rl.py +78 -29
- freesolo_flash_dev-1.0.0/flash/engine/worker/rng.py +83 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/sft.py +131 -32
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/teacher.py +36 -13
- freesolo_flash_dev-1.0.0/flash/engine/worker_entrypoint.py +22 -0
- freesolo_flash_dev-1.0.0/flash/envs/archive.py +71 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/loader.py +26 -112
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/pull.py +8 -1
- freesolo_flash_dev-1.0.0/flash/lora_rank.py +357 -0
- freesolo_flash_dev-1.0.0/flash/opd_retry_contract.py +266 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/__init__.py +9 -8
- freesolo_flash_dev-1.0.0/flash/providers/_deadline.py +51 -0
- freesolo_flash_dev-1.0.0/flash/providers/_hf_artifacts.py +350 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_hf_retry.py +19 -4
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_http.py +64 -26
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_instance.py +181 -102
- freesolo_flash_dev-1.0.0/flash/providers/_instance_bootstrap.py +944 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_instance_poll.py +267 -117
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_instance_provider.py +25 -15
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_poll.py +33 -27
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_worker.py +64 -60
- freesolo_flash_dev-1.0.0/flash/providers/allocator.py +164 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/base.py +33 -8
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/__init__.py +12 -10
- freesolo_flash_dev-1.0.0/flash/providers/lambdalabs/api.py +322 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/jobs/__init__.py +231 -74
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/jobs/builders.py +25 -12
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/pricing.py +2 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/__init__.py +59 -13
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/api.py +81 -42
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/jobs.py +245 -81
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/preload.py +76 -59
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/train/endpoints.py +376 -260
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/__init__.py +13 -12
- freesolo_flash_dev-1.0.0/flash/providers/vast/api.py +479 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/jobs/__init__.py +322 -135
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/jobs/builders.py +20 -8
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/pricing.py +39 -7
- freesolo_flash_dev-1.0.0/flash/runner/__init__.py +1667 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/runner/checkpoints.py +19 -35
- freesolo_flash_dev-1.0.0/flash/runner/deploy.py +1036 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/runner/lifecycle.py +306 -133
- freesolo_flash_dev-1.0.0/flash/runner/verified_revisions.py +168 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/schema/__init__.py +218 -90
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/schema/fields.py +23 -12
- freesolo_flash_dev-1.0.0/flash/serve/deploy.py +905 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/serve/export.py +26 -12
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/serve/pricing.py +0 -20
- freesolo_flash_dev-1.0.0/flash/serve/urls.py +26 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/_internal_client.py +2 -8
- freesolo_flash_dev-1.0.0/flash/server/_locks.py +76 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/_runtime.py +56 -22
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/app.py +12 -11
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/auth.py +4 -9
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/billing.py +1 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/checkpoints.py +2 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/reconcile.py +3 -4
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/repo_cleanup.py +1 -1
- freesolo_flash_dev-1.0.0/flash/server/routes/runs.py +311 -0
- freesolo_flash_dev-1.0.0/flash/server/routes/serving.py +1183 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/run_registry.py +37 -0
- freesolo_flash_dev-1.0.0/flash/spec.py +436 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/pyproject.toml +16 -9
- freesolo_flash_dev-1.0.0/tests/test_accounting_coverage.py +76 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_agent_flash_cli_contract.py +2 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_allocator.py +166 -10
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_backend_jobspec_contract.py +5 -4
- freesolo_flash_dev-1.0.0/tests/test_base_model_provenance.py +94 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_billing_retry.py +5 -2
- freesolo_flash_dev-1.0.0/tests/test_cancel_remote.py +2182 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_checkpoints.py +107 -16
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_commands.py +237 -17
- freesolo_flash_dev-1.0.0/tests/test_cli_commands_coverage.py +213 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_estimate.py +118 -5
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_help.py +6 -0
- freesolo_flash_dev-1.0.0/tests/test_cli_main_coverage.py +19 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_render_coverage.py +3 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_render_theme.py +22 -15
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_client.py +199 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_config_overrides.py +42 -3
- freesolo_flash_dev-1.0.0/tests/test_controlled_experiment_repairs.py +395 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_analytical.py +39 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_estimate.py +251 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_cache_evict.py +28 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_pull.py +1 -1
- freesolo_flash_dev-1.0.0/tests/test_env_pull_coverage.py +175 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_pull_loader_coverage.py +36 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_export.py +30 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_flash_mvp.py +10 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_flash_worker.py +42 -5
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_gpus.py +15 -0
- freesolo_flash_dev-1.0.0/tests/test_hf_retry.py +69 -0
- freesolo_flash_dev-1.0.0/tests/test_instance_bootstrap_coverage.py +1846 -0
- freesolo_flash_dev-1.0.0/tests/test_internal_client.py +22 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_jobs.py +1704 -360
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_kernel_fingerprint.py +120 -13
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_lambda_api_coverage.py +73 -19
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_lambda_runner.py +955 -199
- freesolo_flash_dev-1.0.0/tests/test_lora_rank_coverage.py +163 -0
- freesolo_flash_dev-1.0.0/tests/test_lora_rank_preflight.py +298 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_managed_hf_repo.py +2 -2
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_multiturn_rollout.py +135 -130
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_multiturn_rollout_coverage.py +125 -163
- freesolo_flash_dev-1.0.0/tests/test_multiturn_rollout_records.py +218 -0
- freesolo_flash_dev-1.0.0/tests/test_multiturn_rollout_request_policy.py +353 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_oom_escalate_gpu.py +102 -26
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_opd.py +935 -531
- freesolo_flash_dev-1.0.0/tests/test_opd_full_state_resume.py +1161 -0
- freesolo_flash_dev-1.0.0/tests/test_opd_resume_safety.py +1224 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_opd_vllm.py +65 -9
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_orchestrator_flash.py +15 -7
- freesolo_flash_dev-1.0.0/tests/test_packing_coverage.py +149 -0
- freesolo_flash_dev-1.0.0/tests/test_poll_helpers.py +138 -0
- freesolo_flash_dev-1.0.0/tests/test_provider_preflight_coverage.py +61 -0
- freesolo_flash_dev-1.0.0/tests/test_provider_routing.py +1114 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_provider_teardown_robustness.py +0 -13
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_providers_symmetry.py +59 -30
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_realized_cost.py +40 -12
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_repo_cleanup.py +41 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_resume_on_retry.py +377 -28
- freesolo_flash_dev-1.0.0/tests/test_runmgmt.py +1836 -0
- freesolo_flash_dev-1.0.0/tests/test_runpod_api_delete.py +67 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_runpod_key_fingerprint.py +44 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_serve.py +593 -44
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_server_api.py +2390 -143
- freesolo_flash_dev-1.0.0/tests/test_server_app_coverage.py +192 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_server_billing.py +76 -6
- freesolo_flash_dev-1.0.0/tests/test_server_checkpoints_coverage.py +77 -0
- freesolo_flash_dev-1.0.0/tests/test_server_envs_coverage.py +863 -0
- freesolo_flash_dev-1.0.0/tests/test_server_locks_coverage.py +55 -0
- freesolo_flash_dev-1.0.0/tests/test_serving_contract.py +907 -0
- freesolo_flash_dev-1.0.0/tests/test_serving_pricing_coverage.py +21 -0
- freesolo_flash_dev-1.0.0/tests/test_serving_schema_coverage.py +203 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_spec_and_validation.py +383 -18
- freesolo_flash_dev-1.0.0/tests/test_training_controls.py +676 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_vast_api.py +358 -57
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_vast_api_coverage.py +56 -7
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_vast_offers.py +68 -11
- freesolo_flash_dev-1.0.0/tests/test_vast_provider_coverage.py +131 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_vast_runner.py +1145 -132
- freesolo_flash_dev-1.0.0/tests/test_verified_revisions.py +201 -0
- freesolo_flash_dev-1.0.0/tests/test_wandb_log_coverage.py +109 -0
- freesolo_flash_dev-1.0.0/tests/test_warmstart_cross_repo.py +745 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_weight_cache.py +614 -281
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_hardexit.py +150 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_image.py +12 -13
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_init_heartbeat.py +1 -1
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_stack.py +438 -3
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/uv.lock +13 -1
- freesolo_flash_dev-0.2.57/flash/engine/accounting.py +0 -38
- freesolo_flash_dev-0.2.57/flash/engine/steps.py +0 -18
- freesolo_flash_dev-0.2.57/flash/engine/worker/hf.py +0 -489
- freesolo_flash_dev-0.2.57/flash/lora_rank.py +0 -203
- freesolo_flash_dev-0.2.57/flash/providers/_hf_artifacts.py +0 -177
- freesolo_flash_dev-0.2.57/flash/providers/_instance_bootstrap.py +0 -525
- freesolo_flash_dev-0.2.57/flash/providers/allocator.py +0 -100
- freesolo_flash_dev-0.2.57/flash/providers/lambdalabs/api.py +0 -200
- freesolo_flash_dev-0.2.57/flash/providers/runpod/train/deps.py +0 -19
- freesolo_flash_dev-0.2.57/flash/providers/vast/api.py +0 -314
- freesolo_flash_dev-0.2.57/flash/runner/__init__.py +0 -835
- freesolo_flash_dev-0.2.57/flash/runner/deploy.py +0 -364
- freesolo_flash_dev-0.2.57/flash/serve/deploy.py +0 -542
- freesolo_flash_dev-0.2.57/flash/server/_locks.py +0 -43
- freesolo_flash_dev-0.2.57/flash/server/routes/runs.py +0 -180
- freesolo_flash_dev-0.2.57/flash/server/routes/serving.py +0 -645
- freesolo_flash_dev-0.2.57/flash/spec.py +0 -264
- freesolo_flash_dev-0.2.57/tests/test_cancel_remote.py +0 -835
- freesolo_flash_dev-0.2.57/tests/test_instance_bootstrap_coverage.py +0 -453
- freesolo_flash_dev-0.2.57/tests/test_internal_client.py +0 -30
- freesolo_flash_dev-0.2.57/tests/test_lora_rank_preflight.py +0 -142
- freesolo_flash_dev-0.2.57/tests/test_poll_helpers.py +0 -91
- freesolo_flash_dev-0.2.57/tests/test_provider_routing.py +0 -573
- freesolo_flash_dev-0.2.57/tests/test_runmgmt.py +0 -420
- freesolo_flash_dev-0.2.57/tests/test_runpod_api_delete.py +0 -90
- freesolo_flash_dev-0.2.57/tests/test_server_envs_coverage.py +0 -436
- freesolo_flash_dev-0.2.57/tests/test_serving_contract.py +0 -395
- freesolo_flash_dev-0.2.57/tests/test_warmstart_cross_repo.py +0 -104
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.dockerignore +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.env.example +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.gitignore +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/Dockerfile +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/LICENSE +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/README.md +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/_logging.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/_tty.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cli/env_setup.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/structured_outputs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/kernel_warmup.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/tokenizer_align.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/archive_policy.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/envs/registry.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/py.typed +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/db.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/conftest.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_b200_rollout_opt.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_grpo_sleep_gate.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_version.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/tests/test_worker_thinking.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# flash verification
|
|
2
|
+
|
|
3
|
+
Use isolated loopback services to exercise the public FastAPI and CLI surfaces.
|
|
4
|
+
|
|
5
|
+
1. set `HOME` to a temporary directory so run JSON and `server.db` stay isolated.
|
|
6
|
+
2. launch a synthetic serving backend on an unused localhost port that implements `/adapters` and `/v1/chat/completions` and records request paths.
|
|
7
|
+
3. launch `flash.server.app.create_app()` with uvicorn through a temporary launcher. patch startup credential and external-provider preflights only, and set `FREESOLO_INTERNAL_KEY`, `FLASH_DEPLOY_SYNC=1`, and `FREESOLO_SERVING_URL` to the synthetic backend.
|
|
8
|
+
4. drive the real HTTP routes with curl using the internal bearer key. create dry-run records through `POST /v1/runs`; when a completed artifact is needed, edit only the isolated temporary run JSON before driving deploy, chat, list, cancel, and undeploy routes.
|
|
9
|
+
5. capture API response bodies and the synthetic backend request log. stop both loopback processes after verification.
|
|
10
|
+
|
|
11
|
+
Use `uv run --project <repo> python ...` for all Python launchers. Never use production credentials or network services.
|
|
@@ -105,9 +105,9 @@ jobs:
|
|
|
105
105
|
FP_BASE: ${{ steps.base.outputs.fp_base }}
|
|
106
106
|
REV: ${{ steps.base.outputs.revision }}
|
|
107
107
|
run: |
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
arches=$(python3
|
|
108
|
+
# flash/providers/_worker.py is the single source of truth for the arch list; the bake
|
|
109
|
+
# matrix mirrors it. read the canonical assignment statically without importing flash.
|
|
110
|
+
arches=$(python3 docker/kernel_fingerprint.py --print-baked-arches)
|
|
111
111
|
relayer=(); gpu=()
|
|
112
112
|
summary="| arch | published fp_cache | published fp_base | action |\n|---|---|---|---|\n"
|
|
113
113
|
for sm in $arches; do
|
{freesolo_flash_dev-0.2.57 → freesolo_flash_dev-1.0.0}/.github/workflows/bake-kernel-cache.yml
RENAMED
|
@@ -5,7 +5,7 @@ name: flash worker kernel-cache (per-arch)
|
|
|
5
5
|
# 1. offloads the warmup to a RunPod GPU of that arch (GH runners have none) -> build/kernel_cache,
|
|
6
6
|
# 2. docker build --build-arg BUILD_KERNEL_CACHE=true -> ghcr.io/freesolo-co/flash-worker:cu128-<sm>,
|
|
7
7
|
# 3. pushes it. The allocator then selects the cu128-<sm> tag per GPU class for baked arches
|
|
8
|
-
# (see flash/providers/
|
|
8
|
+
# (see flash/providers/_worker.py).
|
|
9
9
|
#
|
|
10
10
|
# Depends on the base ghcr.io/freesolo-co/flash-worker:cu128 image existing (worker-image.yml) — the
|
|
11
11
|
# warmup runs INSIDE it so the cache matches the image's pinned torch/triton/fla/liger toolchain.
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
name: flash worker image
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
# pushes it to
|
|
5
|
-
# cold-start cost).
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# (flash/serve/deploy.py).
|
|
3
|
+
# builds the prebuilt flash worker image (full training stack + flash-attn baked in) and
|
|
4
|
+
# pushes it to ghcr, so runpod/vast/lambda training cold-start skips the per-host dependency
|
|
5
|
+
# install (the dominant cold-start cost). training providers select the pinned image and operator
|
|
6
|
+
# override through flash/providers/_worker.py. serving has no consumer for this training-worker
|
|
7
|
+
# image or override.
|
|
9
8
|
#
|
|
10
9
|
# Triggered automatically on flash/** changes (worker training code is baked in; skipping a
|
|
11
10
|
# rebuild leaves GPU workers running stale code) and manually for Dockerfile/dep changes.
|
|
@@ -95,9 +94,9 @@ jobs:
|
|
|
95
94
|
context: .
|
|
96
95
|
file: Dockerfile.worker
|
|
97
96
|
push: true
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
97
|
+
# pin the freesolo-co namespace: runpod, vast, and lambda training paths pull the image
|
|
98
|
+
# declared in flash/providers/_worker.py, so a fork run must not push to its own owner
|
|
99
|
+
# namespace and leave the real image stale.
|
|
101
100
|
tags: ghcr.io/freesolo-co/flash-worker:${{ github.event.inputs.tag || 'cu128' }}
|
|
102
101
|
provenance: false
|
|
103
102
|
# Stamp the kernel-cache fingerprints + the source commit so auto-rebake.yml can read what
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Flash prebuilt WORKER image — the full training stack baked in for RunPod workers.
|
|
2
2
|
# The worker still fetches the flash `code/**` from HF at runtime, so only DEPS live here.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
4
|
+
# this image name is defined in flash/providers/_worker.py. it must be
|
|
5
5
|
# published to GHCR and the package set PUBLIC (no registry login is configured) so RunPod can
|
|
6
6
|
# pull it. Normally built by
|
|
7
7
|
# .github/workflows/worker-image.yml (manual dispatch); to build/push by hand:
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
#
|
|
13
13
|
# Base is torch 2.10 / cu12.8 / cudnn9 (-devel = has nvcc for any source builds); it ships the
|
|
14
14
|
# CUDA 12.8 runtime libs the PyPI wheels link against. The pinned stack mirrors
|
|
15
|
-
# flash/providers/
|
|
15
|
+
# flash/providers/_worker.py:WORKER_DEPS.
|
|
16
16
|
FROM pytorch/pytorch:2.10.0-cuda12.8-cudnn9-devel
|
|
17
17
|
|
|
18
18
|
ENV DEBIAN_FRONTEND=noninteractive \
|
|
@@ -78,7 +78,7 @@ RUN pip install --no-cache-dir \
|
|
|
78
78
|
# pure-PyTorch fallback (H100 SXM, Qwen3.5 hidden-2560 LoRA): seq4096 4.2x faster / 1.6x less mem,
|
|
79
79
|
# seq16384 12.6x / 1.9x, loss matches to 1.8e-4. fla is from git: the PyPI wheel is a broken stub
|
|
80
80
|
# (no fla.modules). The git URL is PINNED to a commit (not the moving default branch) for
|
|
81
|
-
# reproducible image builds
|
|
81
|
+
# reproducible image builds; keep this sha in lockstep with the worker dependencies in flash/providers/_worker.py.
|
|
82
82
|
|
|
83
83
|
# FlashAttention: PREFER a prebuilt wheel. There is no OFFICIAL Dao-AILab wheel for torch 2.10 yet,
|
|
84
84
|
# but community CI publishes matching wheels (cu128/torch2.10/cp312); CI passes one as FLASH_ATTN_SPEC
|
|
@@ -144,13 +144,13 @@ RUN TORCH_CUDA_ARCH_LIST="8.0 8.6 8.9 9.0 10.0 12.0" CAUSAL_CONV1D_FORCE_BUILD=T
|
|
|
144
144
|
|| { echo "causal_conv1d: build/import failed -> removing + GDN packing stays off (Qwen3.5/3.6 train unpacked)"; \
|
|
145
145
|
pip uninstall -y causal-conv1d 2>/dev/null || true; }
|
|
146
146
|
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
# only at runtime and only when attached, so a baked
|
|
147
|
+
# weight cache (runtime, not baked): when the shared weight-cache network volume is attached,
|
|
148
|
+
# flash/providers/_worker.py:weight_cache_env redirects only base-model prefetching through
|
|
149
|
+
# FLASH_WEIGHT_CACHE_DIR to the persistent volume for reuse across runs. HF_HOME remains ephemeral,
|
|
150
|
+
# so environment and reward downloads are not shared. executable kernel-jit caches are deliberately
|
|
151
|
+
# not shared because the volume is multi-tenant; a poisoned compiled artifact could affect another
|
|
152
|
+
# tenant. the redirect cannot be a static image environment variable: the volume mounts at a fixed
|
|
153
|
+
# path only at runtime and only when attached, so a baked redirect would break cache-less cold runs.
|
|
154
154
|
#
|
|
155
155
|
# Compiled-kernel cache: OPT-IN bake, JIT fallback. The fused Triton (fla/chalk),
|
|
156
156
|
# TorchInductor, and Hopper tilelang kernels the trainer builds on first use are content-addressed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI
|
|
5
5
|
Project-URL: Homepage, https://github.com/freesolo-co/flash
|
|
6
6
|
Project-URL: Repository, https://github.com/freesolo-co/flash
|
|
@@ -21,8 +21,11 @@ Requires-Dist: fastapi; extra == 'dev'
|
|
|
21
21
|
Requires-Dist: freesolo>=0.2.54; extra == 'dev'
|
|
22
22
|
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
23
23
|
Requires-Dist: huggingface-hub>=0.34; extra == 'dev'
|
|
24
|
+
Requires-Dist: jsonschema>=4.23; extra == 'dev'
|
|
24
25
|
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
25
26
|
Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
27
|
+
Requires-Dist: referencing>=0.28.4; extra == 'dev'
|
|
28
|
+
Requires-Dist: regex>=2024.11.6; extra == 'dev'
|
|
26
29
|
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
27
30
|
Requires-Dist: runpod-flash; extra == 'dev'
|
|
28
31
|
Requires-Dist: transformers<5.11,>=5.6; extra == 'dev'
|
|
@@ -44,6 +47,9 @@ Requires-Dist: fastapi; extra == 'server'
|
|
|
44
47
|
Requires-Dist: freesolo>=0.2.54; extra == 'server'
|
|
45
48
|
Requires-Dist: httpx>=0.27; extra == 'server'
|
|
46
49
|
Requires-Dist: huggingface-hub>=0.34; extra == 'server'
|
|
50
|
+
Requires-Dist: jsonschema>=4.23; extra == 'server'
|
|
51
|
+
Requires-Dist: referencing>=0.28.4; extra == 'server'
|
|
52
|
+
Requires-Dist: regex>=2024.11.6; extra == 'server'
|
|
47
53
|
Requires-Dist: runpod-flash; extra == 'server'
|
|
48
54
|
Requires-Dist: transformers<5.11,>=5.6; extra == 'server'
|
|
49
55
|
Requires-Dist: uvicorn; extra == 'server'
|
|
@@ -105,7 +105,7 @@ def main() -> int:
|
|
|
105
105
|
chalk_spec = os.environ.get("FLASH_CHALK_SPEC", "").strip()
|
|
106
106
|
if not chalk_spec:
|
|
107
107
|
try:
|
|
108
|
-
from flash.providers.
|
|
108
|
+
from flash.providers._worker import DEFAULT_CHALK_SPEC
|
|
109
109
|
|
|
110
110
|
chalk_spec = DEFAULT_CHALK_SPEC
|
|
111
111
|
except Exception as exc:
|
|
@@ -58,6 +58,8 @@ LABEL_REVISION = "org.opencontainers.image.revision"
|
|
|
58
58
|
# pip specs in Dockerfile.worker's main stack whose kernels land in the mega-cache. everything else
|
|
59
59
|
# in that block is a base-layer dep (fp_base). fla is matched separately (it carries the git sha).
|
|
60
60
|
_CACHE_PKGS = {"tilelang", "apache-tvm-ffi"}
|
|
61
|
+
_BAKED_ARCHES_NAME = "BAKED_PER_SM_ARCHES"
|
|
62
|
+
_BAKED_ARCH_PATTERN = re.compile(r"sm[0-9]+")
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
def _search(pattern: str, text: str, what: str, *, flags: int = 0) -> str:
|
|
@@ -110,6 +112,62 @@ def _python_string_constant(text: str, name: str, what: str) -> str:
|
|
|
110
112
|
return values[name]
|
|
111
113
|
|
|
112
114
|
|
|
115
|
+
def parse_baked_per_sm_arches(text: str, *, source: str = "_worker.py") -> list[str]:
|
|
116
|
+
"""Parse the canonical baked-architecture frozenset without importing flash."""
|
|
117
|
+
tree = ast.parse(text, filename=source)
|
|
118
|
+
assignments = [
|
|
119
|
+
node
|
|
120
|
+
for node in tree.body
|
|
121
|
+
if (
|
|
122
|
+
isinstance(node, ast.Assign)
|
|
123
|
+
and any(isinstance(t, ast.Name) and t.id == _BAKED_ARCHES_NAME for t in node.targets)
|
|
124
|
+
)
|
|
125
|
+
or (
|
|
126
|
+
isinstance(node, ast.AnnAssign)
|
|
127
|
+
and isinstance(node.target, ast.Name)
|
|
128
|
+
and node.target.id == _BAKED_ARCHES_NAME
|
|
129
|
+
)
|
|
130
|
+
]
|
|
131
|
+
context = f"kernel_fingerprint: {_BAKED_ARCHES_NAME} in {source}"
|
|
132
|
+
if len(assignments) != 1:
|
|
133
|
+
raise ValueError(
|
|
134
|
+
f"{context}: expected exactly one top-level assignment, found {len(assignments)}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
assignment = assignments[0]
|
|
138
|
+
if isinstance(assignment, ast.Assign) and (
|
|
139
|
+
len(assignment.targets) != 1 or not isinstance(assignment.targets[0], ast.Name)
|
|
140
|
+
):
|
|
141
|
+
raise ValueError(f"{context} must use one named target")
|
|
142
|
+
value = assignment.value
|
|
143
|
+
if value is None:
|
|
144
|
+
raise ValueError(f"{context} must have a value")
|
|
145
|
+
if not (
|
|
146
|
+
isinstance(value, ast.Call)
|
|
147
|
+
and isinstance(value.func, ast.Name)
|
|
148
|
+
and value.func.id == "frozenset"
|
|
149
|
+
and len(value.args) == 1
|
|
150
|
+
and not value.keywords
|
|
151
|
+
and isinstance(value.args[0], ast.Set)
|
|
152
|
+
):
|
|
153
|
+
raise ValueError(f"{context} must be frozenset({{...}}) of string literals")
|
|
154
|
+
|
|
155
|
+
arches: list[str] = []
|
|
156
|
+
for element in value.args[0].elts:
|
|
157
|
+
if not isinstance(element, ast.Constant) or not isinstance(element.value, str):
|
|
158
|
+
raise ValueError(f"{context} must contain strings")
|
|
159
|
+
if _BAKED_ARCH_PATTERN.fullmatch(element.value) is None:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"{context} has invalid architecture {element.value!r}; expected sm followed by digits"
|
|
162
|
+
)
|
|
163
|
+
arches.append(element.value)
|
|
164
|
+
if not arches:
|
|
165
|
+
raise ValueError(f"{context} must not be empty")
|
|
166
|
+
if len(arches) != len(set(arches)):
|
|
167
|
+
raise ValueError(f"{context} must not contain duplicates")
|
|
168
|
+
return arches
|
|
169
|
+
|
|
170
|
+
|
|
113
171
|
def _pip_stack_specs(dockerfile: str) -> list[str]:
|
|
114
172
|
"""The quoted specs from Dockerfile.worker's first `pip install` block (the pinned worker stack)."""
|
|
115
173
|
specs: list[str] = []
|
|
@@ -257,6 +315,11 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
257
315
|
ap.add_argument(
|
|
258
316
|
"--print-label-keys", action="store_true", help="print the OCI label keys + exit"
|
|
259
317
|
)
|
|
318
|
+
ap.add_argument(
|
|
319
|
+
"--print-baked-arches",
|
|
320
|
+
action="store_true",
|
|
321
|
+
help="print BAKED_PER_SM_ARCHES from _worker.py + exit",
|
|
322
|
+
)
|
|
260
323
|
args = ap.parse_args(argv)
|
|
261
324
|
|
|
262
325
|
if args.print_label_keys:
|
|
@@ -265,8 +328,20 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
265
328
|
print(f"revision={LABEL_REVISION}")
|
|
266
329
|
return 0
|
|
267
330
|
|
|
331
|
+
root = Path(args.root)
|
|
332
|
+
if args.print_baked_arches:
|
|
333
|
+
worker_source = root / "flash" / "providers" / "_worker.py"
|
|
334
|
+
try:
|
|
335
|
+
arches = parse_baked_per_sm_arches(
|
|
336
|
+
worker_source.read_text(encoding="utf-8"), source=str(worker_source)
|
|
337
|
+
)
|
|
338
|
+
except (OSError, SyntaxError, ValueError) as exc:
|
|
339
|
+
ap.error(str(exc))
|
|
340
|
+
print(" ".join(arches))
|
|
341
|
+
return 0
|
|
342
|
+
|
|
268
343
|
fp_cache, fp_base, cache_inputs, base_inputs = fingerprints(
|
|
269
|
-
|
|
344
|
+
root, fa2_spec=args.fa2_spec, fa3_spec=args.fa3_spec
|
|
270
345
|
)
|
|
271
346
|
if args.explain:
|
|
272
347
|
print(
|
|
@@ -9,7 +9,6 @@ import re
|
|
|
9
9
|
import sys
|
|
10
10
|
import threading
|
|
11
11
|
import time
|
|
12
|
-
import urllib.error
|
|
13
12
|
import urllib.request
|
|
14
13
|
|
|
15
14
|
from flash import __version__
|
|
@@ -27,7 +26,7 @@ _PYPI_JSON_URL = f"https://pypi.org/pypi/{PACKAGE_NAME}/json"
|
|
|
27
26
|
CACHE_PATH = CONFIG_DIR / "update_check.json"
|
|
28
27
|
|
|
29
28
|
_CHECK_INTERVAL_S = 24 * 60 * 60
|
|
30
|
-
# join
|
|
29
|
+
# keep the join budget above the fetch timeout to allow parsing and persistence before exit.
|
|
31
30
|
_FETCH_TIMEOUT_S = 1.5
|
|
32
31
|
_JOIN_TIMEOUT_S = 2.0
|
|
33
32
|
|
|
@@ -96,9 +95,7 @@ def _clean_version(value: object) -> str | None:
|
|
|
96
95
|
|
|
97
96
|
|
|
98
97
|
def _read_cache() -> dict:
|
|
99
|
-
|
|
100
|
-
cache = read_json_or_empty(CACHE_PATH)
|
|
101
|
-
return cache if isinstance(cache, dict) else {}
|
|
98
|
+
return read_json_or_empty(CACHE_PATH)
|
|
102
99
|
|
|
103
100
|
|
|
104
101
|
def _check_due(now: float) -> bool:
|
|
@@ -122,7 +119,7 @@ def _fetch_latest_version(timeout: float = _FETCH_TIMEOUT_S) -> str | None:
|
|
|
122
119
|
try:
|
|
123
120
|
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
124
121
|
payload = json.loads(resp.read())
|
|
125
|
-
except (
|
|
122
|
+
except (OSError, ValueError) as exc:
|
|
126
123
|
logger.debug("update check: PyPI lookup failed: %s", exc)
|
|
127
124
|
return None
|
|
128
125
|
info = payload.get("info") if isinstance(payload, dict) else None
|
|
@@ -152,23 +149,16 @@ def _refresh_cache() -> None:
|
|
|
152
149
|
logger.debug("update check: refresh failed: %s", exc)
|
|
153
150
|
|
|
154
151
|
|
|
155
|
-
def _supports_color() -> bool:
|
|
156
|
-
return not os.environ.get("NO_COLOR")
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def _red(text: str) -> str:
|
|
160
|
-
return f"\033[31m{text}\033[0m" if _supports_color() else text
|
|
161
|
-
|
|
162
|
-
|
|
163
152
|
def _build_notice() -> str | None:
|
|
164
153
|
"""Build the upgrade notice from the cached PyPI version, or ``None`` if up to date."""
|
|
165
154
|
latest = _clean_version(_read_cache().get("pypi_version"))
|
|
166
155
|
if not latest or _is_prerelease(latest) or not _is_newer(latest, __version__):
|
|
167
156
|
return None
|
|
168
|
-
|
|
157
|
+
notice = (
|
|
169
158
|
f"A new release of {PACKAGE_NAME} is available: {__version__} -> {latest}\n"
|
|
170
159
|
f"Update with `{UPGRADE_COMMAND}`."
|
|
171
160
|
)
|
|
161
|
+
return f"\033[31m{notice}\033[0m" if not os.environ.get("NO_COLOR") else notice
|
|
172
162
|
|
|
173
163
|
|
|
174
164
|
def maybe_start_update_check() -> threading.Thread | None:
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""Shared adapter artifact filenames used by training and control-plane code."""
|
|
2
2
|
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
3
|
# The PEFT adapter weights file a deployable adapter must carry. Modern saves use safetensors,
|
|
6
4
|
# but older PEFT/default settings may emit adapter_model.bin.
|
|
7
5
|
ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors", "adapter_model.bin")
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import math
|
|
6
|
-
from dataclasses import asdict, dataclass
|
|
6
|
+
from dataclasses import asdict, dataclass, replace
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
ALGORITHMS = ("sft", "grpo", "opd")
|
|
@@ -78,7 +78,7 @@ class ModelInfo:
|
|
|
78
78
|
recommended_gpu: str = DEFAULT_GPU
|
|
79
79
|
# 0 => GRPO uses min_vram_gb like SFT; set when colocated vLLM rollout needs a bigger card.
|
|
80
80
|
grpo_min_vram_gb: int = 0
|
|
81
|
-
# 0 =>
|
|
81
|
+
# 0 => non-grpo sizing uses the param-based estimate; set when a model must not down-route to the cheapest card.
|
|
82
82
|
sft_min_vram_gb: int = 0
|
|
83
83
|
# vLLM sleep mode (offload the colocate rollout engine between GRPO steps) is NON-FUNCTIONAL for
|
|
84
84
|
# this model: the wake/reload HANGS the rollout (a ~70 GB weight reallocation can't be placed in
|
|
@@ -124,9 +124,9 @@ class ModelInfo:
|
|
|
124
124
|
|
|
125
125
|
def to_dict(self) -> dict[str, Any]:
|
|
126
126
|
data = asdict(self)
|
|
127
|
-
serving = data
|
|
127
|
+
serving = data["serving"]
|
|
128
128
|
if serving is None:
|
|
129
|
-
data
|
|
129
|
+
del data["serving"]
|
|
130
130
|
else:
|
|
131
131
|
for key in (
|
|
132
132
|
"serve_model_id",
|
|
@@ -162,7 +162,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
162
162
|
params="1.2B dense (Llama arch)",
|
|
163
163
|
params_b=1.2,
|
|
164
164
|
vocab_size=130_560,
|
|
165
|
-
algos=
|
|
165
|
+
algos=ALGORITHMS,
|
|
166
166
|
min_vram_gb=12,
|
|
167
167
|
recommended_gpu="RTX 4090",
|
|
168
168
|
serving=ServingCapacity(
|
|
@@ -181,7 +181,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
181
181
|
params="0.9B (text-only fine-tune)",
|
|
182
182
|
params_b=0.9,
|
|
183
183
|
vocab_size=248_320,
|
|
184
|
-
algos=
|
|
184
|
+
algos=ALGORITHMS,
|
|
185
185
|
min_vram_gb=12,
|
|
186
186
|
recommended_gpu="RTX 4090",
|
|
187
187
|
serving=ServingCapacity(
|
|
@@ -200,7 +200,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
200
200
|
params="2.3B (text-only fine-tune)",
|
|
201
201
|
params_b=2.3,
|
|
202
202
|
vocab_size=248_320,
|
|
203
|
-
algos=
|
|
203
|
+
algos=ALGORITHMS,
|
|
204
204
|
min_vram_gb=16,
|
|
205
205
|
recommended_gpu="RTX 4090",
|
|
206
206
|
serving=ServingCapacity(
|
|
@@ -218,7 +218,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
218
218
|
params="4.7B (text-only fine-tune)",
|
|
219
219
|
params_b=4.7,
|
|
220
220
|
vocab_size=248_320,
|
|
221
|
-
algos=
|
|
221
|
+
algos=ALGORITHMS,
|
|
222
222
|
min_vram_gb=32,
|
|
223
223
|
recommended_gpu="RTX 5090",
|
|
224
224
|
serving=ServingCapacity(
|
|
@@ -240,7 +240,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
240
240
|
params="9.7B (text-only fine-tune)",
|
|
241
241
|
params_b=9.7,
|
|
242
242
|
vocab_size=248_320,
|
|
243
|
-
algos=
|
|
243
|
+
algos=ALGORITHMS,
|
|
244
244
|
min_vram_gb=48,
|
|
245
245
|
# NOT QLoRA: peft bnb merge during GRPO rollout diverges trainer precision -> TRL ratio collapses to 0.
|
|
246
246
|
grpo_min_vram_gb=80,
|
|
@@ -272,7 +272,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
272
272
|
num_layers=40,
|
|
273
273
|
hidden_size=2048,
|
|
274
274
|
vocab_size=248_320,
|
|
275
|
-
algos=
|
|
275
|
+
algos=ALGORITHMS,
|
|
276
276
|
min_vram_gb=141,
|
|
277
277
|
# Floor to 100 GB so SFT lands on H200, not the thin-margin consumer Blackwell or 80 GB H100.
|
|
278
278
|
sft_min_vram_gb=100,
|
|
@@ -328,19 +328,20 @@ def get_model(model_id: str) -> ModelInfo:
|
|
|
328
328
|
) from exc
|
|
329
329
|
|
|
330
330
|
|
|
331
|
+
def _model_info_for_serving(model: str | ModelInfo | None) -> ModelInfo | None:
|
|
332
|
+
if isinstance(model, ModelInfo):
|
|
333
|
+
return model
|
|
334
|
+
if isinstance(model, str) and model.strip():
|
|
335
|
+
return MODELS.get(model.strip())
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
|
|
331
339
|
def serving_lora_rank_cap(model: str | ModelInfo | None) -> int | None:
|
|
332
|
-
"""Return the model
|
|
340
|
+
"""Return the model-specific serving LoRA rank cap.
|
|
333
341
|
|
|
334
|
-
|
|
335
|
-
serving paths currently allow rank 32. Unknown/open-policy models intentionally return None instead
|
|
336
|
-
of inheriting a global fallback.
|
|
342
|
+
Unknown and open-policy models return None.
|
|
337
343
|
"""
|
|
338
|
-
|
|
339
|
-
info = model
|
|
340
|
-
elif isinstance(model, str) and model.strip():
|
|
341
|
-
info = MODELS.get(model.strip())
|
|
342
|
-
else:
|
|
343
|
-
info = None
|
|
344
|
+
info = _model_info_for_serving(model)
|
|
344
345
|
if info is None or info.serving is None:
|
|
345
346
|
return None
|
|
346
347
|
return int(info.serving.max_lora_rank)
|
|
@@ -355,12 +356,7 @@ def serving_context_cap(model: str | ModelInfo | None) -> int | None:
|
|
|
355
356
|
``flash.lora_rank.preflight_train_context_within_serving``). Resolution mirrors
|
|
356
357
|
``serving_lora_rank_cap``: unknown/open-policy models return None rather than a global fallback.
|
|
357
358
|
"""
|
|
358
|
-
|
|
359
|
-
info = model
|
|
360
|
-
elif isinstance(model, str) and model.strip():
|
|
361
|
-
info = MODELS.get(model.strip())
|
|
362
|
-
else:
|
|
363
|
-
info = None
|
|
359
|
+
info = _model_info_for_serving(model)
|
|
364
360
|
if info is None or info.serving is None:
|
|
365
361
|
return None
|
|
366
362
|
return int(info.serving.max_model_len)
|
|
@@ -372,26 +368,66 @@ def vocab_size_for(model_id: str) -> int:
|
|
|
372
368
|
return info.vocab_size if info is not None else _DEFAULT_VOCAB_SIZE
|
|
373
369
|
|
|
374
370
|
|
|
371
|
+
def resolve_vocab_size(model_id: str, revision: str = "") -> int:
|
|
372
|
+
"""vocab_size for a model, revision-aware when a commit is pinned (mirrors resolve_params_b).
|
|
373
|
+
|
|
374
|
+
catalog vocab by default; for a pinned revision, the hf config vocab validated against the
|
|
375
|
+
catalog (fail-closed, same as the vram path).
|
|
376
|
+
"""
|
|
377
|
+
info = MODELS.get(model_id)
|
|
378
|
+
if revision:
|
|
379
|
+
from flash.engine.vram import _validated_revision_geometry, fetch_hf_model_geometry
|
|
380
|
+
|
|
381
|
+
if info is not None:
|
|
382
|
+
_params_b, vocab = _validated_revision_geometry(model_id, revision, info)
|
|
383
|
+
return int(vocab or info.vocab_size)
|
|
384
|
+
_p, vocab, _h, _l = fetch_hf_model_geometry(model_id, revision, strict=True)
|
|
385
|
+
if vocab:
|
|
386
|
+
return int(vocab)
|
|
387
|
+
return vocab_size_for(model_id)
|
|
388
|
+
|
|
389
|
+
|
|
375
390
|
def resolve_model(
|
|
376
391
|
model_id: str,
|
|
377
392
|
algorithm: str,
|
|
378
393
|
policy: str = "catalog",
|
|
379
394
|
gpu: str | None = None,
|
|
395
|
+
model_revision: str = "",
|
|
380
396
|
) -> ModelInfo:
|
|
381
397
|
"""Resolve a model under the configured policy; "allow" accepts any HF model."""
|
|
382
398
|
algo = normalize_algorithm(algorithm)
|
|
383
399
|
if model_id in MODELS:
|
|
384
|
-
|
|
400
|
+
info = validate_model_for_algorithm(model_id, algo)
|
|
401
|
+
if model_revision:
|
|
402
|
+
from flash.engine.vram import _validated_revision_geometry
|
|
403
|
+
|
|
404
|
+
params_b, vocab_size = _validated_revision_geometry(model_id, model_revision, info)
|
|
405
|
+
info = replace(
|
|
406
|
+
info,
|
|
407
|
+
params_b=params_b,
|
|
408
|
+
params=f"{params_b:.1f}B",
|
|
409
|
+
vocab_size=vocab_size,
|
|
410
|
+
min_disk_gb=max(info.min_disk_gb, int(params_b * 2) + 64),
|
|
411
|
+
)
|
|
412
|
+
return info
|
|
385
413
|
if policy != "allow":
|
|
386
414
|
return get_model(model_id)
|
|
387
|
-
return _resolve_open_model(model_id, algo, gpu)
|
|
415
|
+
return _resolve_open_model(model_id, algo, gpu, model_revision=model_revision)
|
|
388
416
|
|
|
389
417
|
|
|
390
|
-
def _resolve_open_model(
|
|
418
|
+
def _resolve_open_model(
|
|
419
|
+
model_id: str, algo: str, gpu: str | None, *, model_revision: str = ""
|
|
420
|
+
) -> ModelInfo:
|
|
391
421
|
"""Synthesize a ModelInfo for the open-model "allow" policy via a coarse HF VRAM-fit estimate."""
|
|
392
422
|
from flash.engine.vram import check_fit
|
|
393
423
|
|
|
394
|
-
|
|
424
|
+
resolved_gpu = gpu or DEFAULT_GPU
|
|
425
|
+
est = check_fit(
|
|
426
|
+
model_id,
|
|
427
|
+
algo,
|
|
428
|
+
resolved_gpu,
|
|
429
|
+
model_revision=model_revision,
|
|
430
|
+
)
|
|
395
431
|
if est.verdict == "too_big":
|
|
396
432
|
raise ValueError(
|
|
397
433
|
f"{model_id} does not fit the requested GPU: {est.describe()}. "
|
|
@@ -399,19 +435,20 @@ def _resolve_open_model(model_id: str, algo: str, gpu: str | None) -> ModelInfo:
|
|
|
399
435
|
)
|
|
400
436
|
if est.verdict in ("tight", "unknown"):
|
|
401
437
|
print(f"warning: open-model policy: {est.describe()}")
|
|
402
|
-
|
|
403
|
-
|
|
438
|
+
params_b = est.params_b or 0.0
|
|
439
|
+
params = f"{params_b:.1f}B" if params_b else "unknown size"
|
|
440
|
+
min_disk = int(params_b * 2) + 64 if params_b else 0
|
|
404
441
|
return ModelInfo(
|
|
405
442
|
id=model_id,
|
|
406
443
|
display_name=model_id,
|
|
407
444
|
params=params,
|
|
408
445
|
# Carry the estimated/HF param count straight through (0.0 when size is unknown) so downstream
|
|
409
446
|
# sizing reads ``params_b`` directly — no re-parsing the display string.
|
|
410
|
-
params_b=
|
|
447
|
+
params_b=params_b,
|
|
411
448
|
algos=ALGORITHMS,
|
|
412
449
|
min_vram_gb=math.ceil(est.est_gb) if est.est_gb else 24,
|
|
413
450
|
min_disk_gb=min_disk,
|
|
414
|
-
recommended_gpu=
|
|
451
|
+
recommended_gpu=resolved_gpu,
|
|
415
452
|
thinking="unknown",
|
|
416
453
|
notes="unlisted model accepted via the open-model policy (not curated/validated)",
|
|
417
454
|
)
|
|
@@ -11,20 +11,14 @@ from typing import NoReturn
|
|
|
11
11
|
|
|
12
12
|
from flash import __version__
|
|
13
13
|
from flash._channel import CLI_NAME
|
|
14
|
-
from flash._logging import configure_logging
|
|
14
|
+
from flash._logging import configure_logging
|
|
15
15
|
from flash._update_check import emit_update_notice, maybe_start_update_check
|
|
16
16
|
from flash.cli import render
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
# `flash.cli` stays the single public import surface (and so monkeypatching
|
|
20
|
-
# `flash.cli.commands` reaches the bare globals the handlers read).
|
|
18
|
+
# package-level command imports remain available through flash.cli.
|
|
21
19
|
from flash.cli.commands import ( # noqa: F401
|
|
22
20
|
_CLI_DONE_STATES,
|
|
23
|
-
_OK_STATES,
|
|
24
|
-
_STARTER_ENV_PY,
|
|
25
21
|
_USER_ERRORS,
|
|
26
|
-
_follow_run,
|
|
27
|
-
_poll_logs,
|
|
28
22
|
client_from_config,
|
|
29
23
|
cmd_cancel,
|
|
30
24
|
cmd_chat,
|
|
@@ -32,7 +26,6 @@ from flash.cli.commands import ( # noqa: F401
|
|
|
32
26
|
cmd_deploy,
|
|
33
27
|
cmd_deployments,
|
|
34
28
|
cmd_env_list,
|
|
35
|
-
cmd_env_setup,
|
|
36
29
|
cmd_export,
|
|
37
30
|
cmd_gpus,
|
|
38
31
|
cmd_log,
|
|
@@ -46,10 +39,9 @@ from flash.cli.commands import ( # noqa: F401
|
|
|
46
39
|
cmd_whoami,
|
|
47
40
|
verify_freesolo_key,
|
|
48
41
|
)
|
|
42
|
+
from flash.cli.env_setup import cmd_env_setup
|
|
49
43
|
from flash.cli.envpush import cmd_env_delete, cmd_env_pull, cmd_env_push
|
|
50
44
|
|
|
51
|
-
logger = get_logger("flash.cli")
|
|
52
|
-
|
|
53
45
|
# Themed `flash --help` catalog. Groups are ordered along the training workflow; each row's
|
|
54
46
|
# summary is the short one-liner the themed grid shows (the verbose per-command text stays on
|
|
55
47
|
# every subparser's own `help=` / `<cmd> --help`). test_cli_help.py asserts these rows stay in
|
|
@@ -392,12 +384,6 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
392
384
|
help="run id for the final adapter, or RUN_ID/step-N for a saved checkpoint",
|
|
393
385
|
)
|
|
394
386
|
deploy.add_argument("--dry-run", action="store_true")
|
|
395
|
-
deploy.add_argument(
|
|
396
|
-
"--no-verify",
|
|
397
|
-
action="store_true",
|
|
398
|
-
help="skip the server-side post-deploy smoke generation (registration alone does NOT "
|
|
399
|
-
"guarantee the adapter serves; only ready deployments should be scored by evals)",
|
|
400
|
-
)
|
|
401
387
|
deploy.set_defaults(func=cmd_deploy)
|
|
402
388
|
|
|
403
389
|
undeploy = sub.add_parser("undeploy", help="tear down a run's serving endpoint")
|
|
@@ -430,6 +416,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
430
416
|
export.set_defaults(func=cmd_export)
|
|
431
417
|
|
|
432
418
|
deployments = sub.add_parser("deployments", help="list active serving deployments")
|
|
419
|
+
deployments.add_argument(
|
|
420
|
+
"--json",
|
|
421
|
+
action="store_true",
|
|
422
|
+
help="print machine-readable deployment records",
|
|
423
|
+
)
|
|
433
424
|
deployments.set_defaults(func=cmd_deployments)
|
|
434
425
|
|
|
435
426
|
chat = sub.add_parser("chat", help="chat with a deployed adapter")
|