freesolo-flash 0.2.26__tar.gz → 0.2.30__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-0.2.30/.github/workflows/auto-rebake.yml +245 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/bake-kernel-cache.yml +95 -17
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/worker-image.yml +36 -14
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/Dockerfile.worker +20 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/PKG-INFO +1 -1
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/Dockerfile.kernelcache +10 -0
- freesolo_flash-0.2.30/docker/Dockerfile.kernelcache.relayer +27 -0
- freesolo_flash-0.2.30/docker/kernel_fingerprint.py +245 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/generate.py +3 -16
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/index.html +79 -131
- freesolo_flash-0.2.30/docs/cli-style/themed-errors.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/README.md +32 -0
- freesolo_flash-0.2.30/docs/cli-theme/before-after-dark.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/before-after-light.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/gallery-dark.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/gallery-light.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/help-dark.png +0 -0
- freesolo_flash-0.2.30/docs/cli-theme/help-light.png +0 -0
- freesolo_flash-0.2.30/flash/__init__.py +13 -0
- freesolo_flash-0.2.30/flash/_channel.py +11 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_fileio.py +4 -9
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_logging.py +4 -16
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_update_check.py +14 -82
- freesolo_flash-0.2.30/flash/catalog.py +264 -0
- freesolo_flash-0.2.30/flash/cli/__init__.py +440 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/commands.py +47 -79
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/envpush.py +151 -42
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/render.py +193 -77
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/training_doc.py +7 -17
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/config.py +3 -11
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/http.py +82 -133
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/runtime_secrets.py +3 -19
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/specs.py +1 -5
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/__init__.py +1 -2
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/analytical.py +8 -13
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/facts.py +9 -32
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/spec.py +5 -7
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/types.py +1 -13
- freesolo_flash-0.2.30/flash/engine/__init__.py +1 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/accounting.py +4 -8
- freesolo_flash-0.2.30/flash/engine/chalk_kernels.py +65 -0
- freesolo_flash-0.2.30/flash/engine/multiturn_rollout.py +598 -0
- freesolo_flash-0.2.30/flash/engine/recipe.py +53 -0
- freesolo_flash-0.2.30/flash/engine/vram.py +571 -0
- freesolo_flash-0.2.30/flash/engine/worker/__init__.py +417 -0
- freesolo_flash-0.2.30/flash/engine/worker/_pkg.py +24 -0
- freesolo_flash-0.2.30/flash/engine/worker/adapter.py +255 -0
- freesolo_flash-0.2.30/flash/engine/worker/decoding.py +69 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/finalize.py +1 -12
- freesolo_flash-0.2.30/flash/engine/worker/gpu_setup.py +158 -0
- freesolo_flash-0.2.30/flash/engine/worker/grpo.py +225 -0
- freesolo_flash-0.2.30/flash/engine/worker/heartbeat.py +240 -0
- freesolo_flash-0.2.30/flash/engine/worker/hf.py +477 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/kernel_warmup.py +104 -66
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/lora.py +208 -236
- freesolo_flash-0.2.30/flash/engine/worker/packing.py +313 -0
- freesolo_flash-0.2.30/flash/engine/worker/perf/__init__.py +363 -0
- freesolo_flash-0.2.30/flash/engine/worker/perf/attn.py +107 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/perf/diagnostics.py +6 -20
- freesolo_flash-0.2.30/flash/engine/worker/perf/lifecycle.py +240 -0
- freesolo_flash-0.2.30/flash/engine/worker/perf/liger.py +49 -0
- freesolo_flash-0.2.30/flash/engine/worker/perf/loraplus.py +18 -0
- freesolo_flash-0.2.30/flash/engine/worker/perf/memory.py +128 -0
- freesolo_flash-0.2.30/flash/engine/worker/rl.py +767 -0
- freesolo_flash-0.2.30/flash/engine/worker/sft.py +532 -0
- freesolo_flash-0.2.30/flash/engine/worker/wandb_log.py +110 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/adapter.py +257 -212
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/base.py +2 -7
- freesolo_flash-0.2.30/flash/envs/pull.py +215 -0
- freesolo_flash-0.2.30/flash/envs/registry.py +26 -0
- freesolo_flash-0.2.30/flash/providers/__init__.py +37 -0
- freesolo_flash-0.2.30/flash/providers/_auth.py +10 -0
- freesolo_flash-0.2.30/flash/providers/_http.py +166 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/_instance.py +24 -162
- freesolo_flash-0.2.30/flash/providers/_instance_bootstrap.py +384 -0
- freesolo_flash-0.2.30/flash/providers/_poll.py +309 -0
- freesolo_flash-0.2.30/flash/providers/allocator.py +112 -0
- freesolo_flash-0.2.30/flash/providers/base.py +341 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/__init__.py +5 -36
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/api.py +12 -73
- freesolo_flash-0.2.30/flash/providers/lambdalabs/auth.py +15 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/gpus.py +1 -6
- freesolo_flash-0.2.30/flash/providers/lambdalabs/jobs/__init__.py +617 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/jobs/builders.py +7 -25
- freesolo_flash-0.2.30/flash/providers/lambdalabs/preflight.py +15 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/pricing.py +2 -9
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/train.py +1 -8
- freesolo_flash-0.2.30/flash/providers/preflight.py +65 -0
- freesolo_flash-0.2.30/flash/providers/realized.py +56 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/__init__.py +12 -32
- freesolo_flash-0.2.30/flash/providers/runpod/api.py +212 -0
- freesolo_flash-0.2.30/flash/providers/runpod/auth.py +23 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/cost.py +1 -6
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/gpus.py +1 -9
- freesolo_flash-0.2.30/flash/providers/runpod/jobs.py +801 -0
- freesolo_flash-0.2.30/flash/providers/runpod/keys.py +97 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/preflight.py +1 -7
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/preload.py +38 -266
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/slots.py +2 -11
- freesolo_flash-0.2.30/flash/providers/runpod/train/__init__.py +62 -0
- freesolo_flash-0.2.30/flash/providers/runpod/train/deps.py +239 -0
- freesolo_flash-0.2.30/flash/providers/runpod/train/endpoints.py +616 -0
- freesolo_flash-0.2.30/flash/runner/__init__.py +525 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/runner/checkpoints.py +6 -6
- freesolo_flash-0.2.30/flash/runner/deploy.py +220 -0
- freesolo_flash-0.2.30/flash/runner/lifecycle.py +591 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/schema/__init__.py +21 -81
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/schema/fields.py +11 -126
- freesolo_flash-0.2.30/flash/serve/deploy.py +309 -0
- freesolo_flash-0.2.30/flash/serve/export.py +107 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/serve/pricing.py +2 -7
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/_deps.py +12 -12
- freesolo_flash-0.2.30/flash/server/_internal_client.py +58 -0
- freesolo_flash-0.2.30/flash/server/_locks.py +55 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/_runtime.py +75 -9
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/app.py +15 -5
- freesolo_flash-0.2.30/flash/server/auth.py +206 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/billing.py +11 -39
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/billing_retry.py +10 -9
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/checkpoints.py +26 -36
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/db.py +5 -31
- freesolo_flash-0.2.30/flash/server/environment_registry.py +104 -0
- freesolo_flash-0.2.30/flash/server/envs.py +603 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/reconcile.py +3 -4
- freesolo_flash-0.2.30/flash/server/repo_cleanup.py +296 -0
- freesolo_flash-0.2.30/flash/server/routes/__init__.py +1 -0
- freesolo_flash-0.2.30/flash/server/routes/envs.py +67 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/routes/meta.py +2 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/routes/runs.py +6 -38
- freesolo_flash-0.2.30/flash/server/routes/serving.py +332 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/run_registry.py +9 -22
- freesolo_flash-0.2.30/flash/spec.py +246 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/pyproject.toml +2 -2
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/conftest.py +11 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_agent_flash_cli_contract.py +2 -10
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_algorithms.py +1 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_allocator.py +34 -2
- freesolo_flash-0.2.30/tests/test_b200_rollout_opt.py +144 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_backend_jobspec_contract.py +0 -2
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_billing_retry.py +13 -59
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cancel_remote.py +102 -25
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_catalog_consistency.py +9 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_checkpoints.py +159 -18
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_errors.py +4 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_estimate.py +2 -10
- freesolo_flash-0.2.30/tests/test_cli_help.py +125 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_managed.py +1 -1
- freesolo_flash-0.2.30/tests/test_cli_render_theme.py +412 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_client.py +52 -2
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_client_server_integration.py +3 -1
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_config_overrides.py +5 -3
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_analytical.py +10 -16
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_disk_gb.py +1 -0
- freesolo_flash-0.2.30/tests/test_env_delete.py +116 -0
- freesolo_flash-0.2.30/tests/test_env_no_install.py +59 -0
- freesolo_flash-0.2.30/tests/test_env_publish.py +926 -0
- freesolo_flash-0.2.30/tests/test_env_pull.py +625 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_env_push.py +29 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_env_rate_limit_resolve.py +1 -1
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_flash_mvp.py +1 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_flash_worker.py +55 -11
- freesolo_flash-0.2.30/tests/test_flashinfer_cache_dirs.py +54 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_github_urlopen_retry.py +75 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_gpus.py +3 -3
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_grpo_params.py +122 -23
- freesolo_flash-0.2.30/tests/test_grpo_sleep_gate.py +223 -0
- freesolo_flash-0.2.30/tests/test_internal_client.py +30 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_jobs.py +276 -87
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_kernel_cache.py +8 -14
- freesolo_flash-0.2.30/tests/test_kernel_fingerprint.py +132 -0
- freesolo_flash-0.2.30/tests/test_kv_util.py +153 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_lambda_runner.py +93 -13
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_login_perms.py +15 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_mig_guard.py +9 -68
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_multiturn_rollout.py +50 -0
- freesolo_flash-0.2.30/tests/test_oom_escalate_gpu.py +121 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_orchestrator_flash.py +5 -5
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_poll_helpers.py +4 -8
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_provider_routing.py +83 -3
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_provider_teardown_robustness.py +0 -18
- freesolo_flash-0.2.30/tests/test_repo_cleanup.py +513 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_resolve_params_b.py +8 -6
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_resume_on_retry.py +24 -8
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runmgmt.py +69 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_key_waterfall.py +32 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_serve.py +87 -25
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_api.py +357 -33
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_billing.py +14 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_db.py +3 -1
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_serving_contract.py +14 -6
- freesolo_flash-0.2.30/tests/test_sft_gc_off.py +158 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_spec_and_validation.py +57 -19
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_thinking_config.py +3 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_verifiers.py +158 -31
- freesolo_flash-0.2.30/tests/test_vl_warmstart_adapter_keys.py +296 -0
- freesolo_flash-0.2.30/tests/test_vl_warmstart_recombine.py +393 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_wandb_naming.py +2 -3
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_warmstart_cross_repo.py +4 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_weight_cache.py +4 -4
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_hardexit.py +42 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_stack.py +51 -16
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/uv.lock +1 -1
- freesolo_flash-0.2.26/flash/__init__.py +0 -29
- freesolo_flash-0.2.26/flash/_channel.py +0 -28
- freesolo_flash-0.2.26/flash/catalog.py +0 -324
- freesolo_flash-0.2.26/flash/cli/__init__.py +0 -261
- freesolo_flash-0.2.26/flash/engine/__init__.py +0 -6
- freesolo_flash-0.2.26/flash/engine/chalk_kernels.py +0 -111
- freesolo_flash-0.2.26/flash/engine/multiturn_rollout.py +0 -780
- freesolo_flash-0.2.26/flash/engine/recipe.py +0 -74
- freesolo_flash-0.2.26/flash/engine/vram.py +0 -636
- freesolo_flash-0.2.26/flash/engine/worker/__init__.py +0 -589
- freesolo_flash-0.2.26/flash/engine/worker/_pkg.py +0 -30
- freesolo_flash-0.2.26/flash/engine/worker/adapter.py +0 -222
- freesolo_flash-0.2.26/flash/engine/worker/decoding.py +0 -144
- freesolo_flash-0.2.26/flash/engine/worker/gpu_setup.py +0 -101
- freesolo_flash-0.2.26/flash/engine/worker/grpo.py +0 -297
- freesolo_flash-0.2.26/flash/engine/worker/heartbeat.py +0 -322
- freesolo_flash-0.2.26/flash/engine/worker/hf.py +0 -526
- freesolo_flash-0.2.26/flash/engine/worker/packing.py +0 -486
- freesolo_flash-0.2.26/flash/engine/worker/perf/__init__.py +0 -495
- freesolo_flash-0.2.26/flash/engine/worker/perf/attn.py +0 -176
- freesolo_flash-0.2.26/flash/engine/worker/perf/lifecycle.py +0 -274
- freesolo_flash-0.2.26/flash/engine/worker/perf/liger.py +0 -73
- freesolo_flash-0.2.26/flash/engine/worker/perf/loraplus.py +0 -40
- freesolo_flash-0.2.26/flash/engine/worker/perf/memory.py +0 -84
- freesolo_flash-0.2.26/flash/engine/worker/rl.py +0 -912
- freesolo_flash-0.2.26/flash/engine/worker/sft.py +0 -683
- freesolo_flash-0.2.26/flash/engine/worker/wandb_log.py +0 -145
- freesolo_flash-0.2.26/flash/envs/registry.py +0 -62
- freesolo_flash-0.2.26/flash/providers/__init__.py +0 -54
- freesolo_flash-0.2.26/flash/providers/_auth.py +0 -16
- freesolo_flash-0.2.26/flash/providers/_http.py +0 -230
- freesolo_flash-0.2.26/flash/providers/_instance_bootstrap.py +0 -515
- freesolo_flash-0.2.26/flash/providers/_poll.py +0 -444
- freesolo_flash-0.2.26/flash/providers/allocator.py +0 -165
- freesolo_flash-0.2.26/flash/providers/base.py +0 -442
- freesolo_flash-0.2.26/flash/providers/lambdalabs/auth.py +0 -18
- freesolo_flash-0.2.26/flash/providers/lambdalabs/jobs/__init__.py +0 -831
- freesolo_flash-0.2.26/flash/providers/lambdalabs/preflight.py +0 -27
- freesolo_flash-0.2.26/flash/providers/preflight.py +0 -92
- freesolo_flash-0.2.26/flash/providers/realized.py +0 -80
- freesolo_flash-0.2.26/flash/providers/runpod/api.py +0 -278
- freesolo_flash-0.2.26/flash/providers/runpod/auth.py +0 -37
- freesolo_flash-0.2.26/flash/providers/runpod/jobs.py +0 -1064
- freesolo_flash-0.2.26/flash/providers/runpod/keys.py +0 -145
- freesolo_flash-0.2.26/flash/providers/runpod/train/__init__.py +0 -101
- freesolo_flash-0.2.26/flash/providers/runpod/train/deps.py +0 -461
- freesolo_flash-0.2.26/flash/providers/runpod/train/endpoints.py +0 -830
- freesolo_flash-0.2.26/flash/runner/__init__.py +0 -811
- freesolo_flash-0.2.26/flash/runner/deploy.py +0 -422
- freesolo_flash-0.2.26/flash/runner/lifecycle.py +0 -682
- freesolo_flash-0.2.26/flash/serve/deploy.py +0 -332
- freesolo_flash-0.2.26/flash/serve/export.py +0 -176
- freesolo_flash-0.2.26/flash/server/_locks.py +0 -54
- freesolo_flash-0.2.26/flash/server/auth.py +0 -263
- freesolo_flash-0.2.26/flash/server/environment_registry.py +0 -102
- freesolo_flash-0.2.26/flash/server/envs.py +0 -350
- freesolo_flash-0.2.26/flash/server/routes/__init__.py +0 -6
- freesolo_flash-0.2.26/flash/server/routes/envs.py +0 -48
- freesolo_flash-0.2.26/flash/server/routes/serving.py +0 -427
- freesolo_flash-0.2.26/flash/spec.py +0 -334
- freesolo_flash-0.2.26/tests/test_cli_render_theme.py +0 -159
- freesolo_flash-0.2.26/tests/test_env_install.py +0 -43
- freesolo_flash-0.2.26/tests/test_env_publish.py +0 -522
- freesolo_flash-0.2.26/tests/test_grpo_sleep_gate.py +0 -97
- freesolo_flash-0.2.26/tests/test_kv_util.py +0 -75
- freesolo_flash-0.2.26/tests/test_vl_warmstart_adapter_keys.py +0 -581
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.dockerignore +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.env.example +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/ci.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.gitignore +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/Dockerfile +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/LICENSE +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/README.md +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/build/kernel_cache/.keep +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/make_rp_handler.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/README.md +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/preview.png +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/kernel-cache.md +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/__main__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/py.typed +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/serve/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/__main__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/infisical-entrypoint.sh +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/runner.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/specs.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/__init__.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/conftest.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_commands.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_equation.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_models.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_dev_channel.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_export.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_logging.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_packing.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_preflight.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_realized_cost.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_update_check.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_version.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_vl_weight_sync.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_image.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_thinking.py +0 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
name: auto-rebake per-arch kernel cache
|
|
2
|
+
|
|
3
|
+
# Keeps the per-arch ghcr.io/freesolo-co/flash-worker:cu128-sm* images fresh whenever the :cu128 base
|
|
4
|
+
# is rebuilt. Each cu128-smXX is physically `FROM :cu128` + a baked mega-cache, so a new base leaves
|
|
5
|
+
# the per-arch tags pointing at the OLD base until rebaked. "Out of date" has two flavors, keyed off
|
|
6
|
+
# the fp_cache / fp_base labels worker-image.yml stamps on :cu128 (docker/kernel_fingerprint.py):
|
|
7
|
+
#
|
|
8
|
+
# * fp_cache changed -> the baked Triton/Inductor mega-cache is INVALID -> a real GPU re-warm is
|
|
9
|
+
# required (bake-kernel-cache.yml). PAID, and AUTO-fired by this detection (no manual approval) --
|
|
10
|
+
# fp_cache only moves on a deliberate toolchain bump, so spend stays tied to real need.
|
|
11
|
+
# * fp_cache same but fp_base changed -> the cache is still valid, the base just moved (FA wheel /
|
|
12
|
+
# causal-conv1d / rp_handler / a non-kernel dep) -> a FREE re-layer grafts the existing cache onto
|
|
13
|
+
# the fresh base (docker/Dockerfile.kernelcache.relayer), no GPU.
|
|
14
|
+
# * both same -> skip (this is the pure-flash-code case the old reminder over-fired on).
|
|
15
|
+
#
|
|
16
|
+
# The gate READS the published labels (authoritative for what was actually built, incl. a manual FA3
|
|
17
|
+
# override) rather than recomputing from the checkout, and aborts unless the base's revision label ==
|
|
18
|
+
# the build's head_sha (so a superseded base build or a `tag=...` dispatch that never touched :cu128
|
|
19
|
+
# can't trigger a stale rebake).
|
|
20
|
+
|
|
21
|
+
on:
|
|
22
|
+
workflow_run:
|
|
23
|
+
workflows: ["flash worker image"]
|
|
24
|
+
types: [completed]
|
|
25
|
+
|
|
26
|
+
permissions:
|
|
27
|
+
contents: read
|
|
28
|
+
packages: write
|
|
29
|
+
actions: read
|
|
30
|
+
issues: write
|
|
31
|
+
|
|
32
|
+
# Scope the group to the triggering base build's commit so a no-op completion (e.g. a tag=cu128-test
|
|
33
|
+
# worker-image run, whose head_sha differs) can't cancel an in-flight real bake. The revision guard
|
|
34
|
+
# already neutralizes superseded runs, so a global cancel-in-progress isn't needed.
|
|
35
|
+
concurrency:
|
|
36
|
+
group: auto-rebake-${{ github.event.workflow_run.head_sha }}
|
|
37
|
+
cancel-in-progress: true
|
|
38
|
+
|
|
39
|
+
env:
|
|
40
|
+
BASE: ghcr.io/freesolo-co/flash-worker:cu128
|
|
41
|
+
|
|
42
|
+
jobs:
|
|
43
|
+
gate:
|
|
44
|
+
if: github.event.workflow_run.conclusion == 'success'
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
outputs:
|
|
47
|
+
proceed: ${{ steps.base.outputs.proceed }}
|
|
48
|
+
relayer_sms: ${{ steps.classify.outputs.relayer_sms }}
|
|
49
|
+
gpu_sms: ${{ steps.classify.outputs.gpu_sms }}
|
|
50
|
+
fp_cache: ${{ steps.base.outputs.fp_cache }}
|
|
51
|
+
fp_base: ${{ steps.base.outputs.fp_base }}
|
|
52
|
+
base_ref: ${{ steps.base.outputs.base_ref }}
|
|
53
|
+
base_revision: ${{ steps.base.outputs.revision }}
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v6
|
|
56
|
+
with:
|
|
57
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
58
|
+
|
|
59
|
+
- name: Install crane
|
|
60
|
+
run: |
|
|
61
|
+
curl -sSL https://github.com/google/go-containerregistry/releases/download/v0.20.2/go-containerregistry_Linux_x86_64.tar.gz \
|
|
62
|
+
| sudo tar -xz -C /usr/local/bin crane
|
|
63
|
+
crane version
|
|
64
|
+
|
|
65
|
+
- name: Log in to GHCR
|
|
66
|
+
uses: docker/login-action@v3
|
|
67
|
+
with:
|
|
68
|
+
registry: ghcr.io
|
|
69
|
+
username: ${{ github.actor }}
|
|
70
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
71
|
+
|
|
72
|
+
- name: Read base labels
|
|
73
|
+
id: base
|
|
74
|
+
env:
|
|
75
|
+
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
|
76
|
+
run: |
|
|
77
|
+
# canonical digest ref (repo@sha256, no tag) so every tool (crane/docker/runpod) accepts it.
|
|
78
|
+
digest=$(crane digest "$BASE")
|
|
79
|
+
repo=${BASE%:*}
|
|
80
|
+
cfg=$(crane config "$repo@$digest")
|
|
81
|
+
fpc=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')
|
|
82
|
+
fpb=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')
|
|
83
|
+
rev=$(echo "$cfg" | jq -r '.config.Labels["org.opencontainers.image.revision"] // ""')
|
|
84
|
+
echo "base_ref=$repo@$digest" >> "$GITHUB_OUTPUT"
|
|
85
|
+
echo "fp_cache=$fpc" >> "$GITHUB_OUTPUT"
|
|
86
|
+
echo "fp_base=$fpb" >> "$GITHUB_OUTPUT"
|
|
87
|
+
echo "revision=$rev" >> "$GITHUB_OUTPUT"
|
|
88
|
+
# Only proceed if this base IS the build that triggered us: its revision label must match the
|
|
89
|
+
# build's head_sha. Guards (a) a newer base that already superseded this run, and (b) a
|
|
90
|
+
# `tag=cu128-test` dispatch that never updated :cu128 (the workflow_run payload can't reveal
|
|
91
|
+
# the dispatch tag). An unlabeled base (pre-rollout) also no-ops here.
|
|
92
|
+
if [ -n "$fpc" ] && [ "$rev" = "$HEAD_SHA" ]; then
|
|
93
|
+
echo "proceed=true" >> "$GITHUB_OUTPUT"
|
|
94
|
+
echo "base $BASE@$digest is rev $rev (== head_sha) fp_cache=$fpc fp_base=$fpb"
|
|
95
|
+
else
|
|
96
|
+
echo "proceed=false" >> "$GITHUB_OUTPUT"
|
|
97
|
+
echo "::notice::auto-rebake no-op: base rev '$rev' != head_sha '$HEAD_SHA' (or base unlabeled)"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
- name: Classify arches
|
|
101
|
+
id: classify
|
|
102
|
+
if: steps.base.outputs.proceed == 'true'
|
|
103
|
+
env:
|
|
104
|
+
FP_CACHE: ${{ steps.base.outputs.fp_cache }}
|
|
105
|
+
FP_BASE: ${{ steps.base.outputs.fp_base }}
|
|
106
|
+
REV: ${{ steps.base.outputs.revision }}
|
|
107
|
+
run: |
|
|
108
|
+
# arch list is the single source of truth in deps.py (mirrored by the bake matrix; a test
|
|
109
|
+
# pins that mirror). textual parse -> no flash import / uv sync needed.
|
|
110
|
+
arches=$(python3 -c "import re,pathlib; t=pathlib.Path('flash/providers/runpod/train/deps.py').read_text(); m=re.search(r'BAKED_PER_SM_ARCHES\s*=\s*frozenset\(\{([^}]+)\}\)', t); print(' '.join(re.findall(r'sm\d+', m.group(1))))")
|
|
111
|
+
relayer=(); gpu=()
|
|
112
|
+
summary="| arch | published fp_cache | published fp_base | action |\n|---|---|---|---|\n"
|
|
113
|
+
for sm in $arches; do
|
|
114
|
+
img="ghcr.io/freesolo-co/flash-worker:cu128-$sm"
|
|
115
|
+
if cfg=$(crane config "$img" 2>/dev/null); then
|
|
116
|
+
pc=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')
|
|
117
|
+
pb=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')
|
|
118
|
+
else
|
|
119
|
+
pc="(missing)"; pb="(missing)"
|
|
120
|
+
fi
|
|
121
|
+
if [ "$pc" != "$FP_CACHE" ]; then
|
|
122
|
+
gpu+=("$sm"); action="GPU re-warm (cache invalid)"
|
|
123
|
+
elif [ "$pb" != "$FP_BASE" ]; then
|
|
124
|
+
relayer+=("$sm"); action="re-layer (free)"
|
|
125
|
+
else
|
|
126
|
+
action="up to date"
|
|
127
|
+
fi
|
|
128
|
+
echo "$sm: pc=$pc pb=$pb -> $action"
|
|
129
|
+
summary="$summary| $sm | \`$pc\` | \`$pb\` | $action |\n"
|
|
130
|
+
done
|
|
131
|
+
if [ ${#relayer[@]} -gt 0 ]; then
|
|
132
|
+
relayer_json=$(printf '%s\n' "${relayer[@]}" | jq -R . | jq -cs .)
|
|
133
|
+
else
|
|
134
|
+
relayer_json='[]'
|
|
135
|
+
fi
|
|
136
|
+
gpu_csv=$(IFS=,; echo "${gpu[*]}")
|
|
137
|
+
echo "relayer_sms=$relayer_json" >> "$GITHUB_OUTPUT"
|
|
138
|
+
echo "gpu_sms=$gpu_csv" >> "$GITHUB_OUTPUT"
|
|
139
|
+
{
|
|
140
|
+
echo "### auto-rebake plan (base rev \`$REV\`, fp_cache \`$FP_CACHE\` fp_base \`$FP_BASE\`)"
|
|
141
|
+
echo ""
|
|
142
|
+
echo -e "$summary"
|
|
143
|
+
echo ""
|
|
144
|
+
echo "re-layer (free): \`$relayer_json\` | GPU re-warm (paid, auto-started): \`${gpu_csv:-none}\`"
|
|
145
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
146
|
+
|
|
147
|
+
# FYI notification (not an action item -- the bake auto-runs). Keeps a heads-up + cost trail of
|
|
148
|
+
# which arches a paid GPU re-warm fired for.
|
|
149
|
+
- name: Notify GPU re-bake auto-started
|
|
150
|
+
if: steps.base.outputs.proceed == 'true' && steps.classify.outputs.gpu_sms != ''
|
|
151
|
+
env:
|
|
152
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
153
|
+
GPU_SMS: ${{ steps.classify.outputs.gpu_sms }}
|
|
154
|
+
REV: ${{ steps.base.outputs.revision }}
|
|
155
|
+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
156
|
+
run: |
|
|
157
|
+
title="kernel-cache: per-arch GPU re-bake auto-started"
|
|
158
|
+
body=$(printf 'The kernel toolchain changed (fp_cache), so a PAID GPU re-warm auto-started for these per-arch images (no approval needed):\n\n- arches: `%s`\n- base rev: `%s`\n\nTrack it in the run: %s' "$GPU_SMS" "$REV" "$RUN_URL")
|
|
159
|
+
# best-effort: a labeling/permission hiccup must never fail the gate. self-heal the label so
|
|
160
|
+
# no manual setup is needed, then reuse one open issue (comment) instead of spamming new ones.
|
|
161
|
+
gh label create kernel-rebake-pending --color B60205 --description "per-arch kernel cache GPU re-bake auto-started" 2>/dev/null || true
|
|
162
|
+
existing=$(gh issue list --label kernel-rebake-pending --state open --json number -q '.[0].number' 2>/dev/null || true)
|
|
163
|
+
if [ -n "${existing:-}" ]; then
|
|
164
|
+
gh issue comment "$existing" --body "$body" || true
|
|
165
|
+
else
|
|
166
|
+
gh issue create --title "$title" --body "$body" --label kernel-rebake-pending \
|
|
167
|
+
|| gh issue create --title "$title" --body "$body" || true
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# FREE path: graft the existing valid cache onto the fresh base, no GPU. Runs automatically.
|
|
171
|
+
relayer:
|
|
172
|
+
needs: gate
|
|
173
|
+
if: needs.gate.outputs.proceed == 'true' && needs.gate.outputs.relayer_sms != '[]' && needs.gate.outputs.relayer_sms != ''
|
|
174
|
+
runs-on: ubuntu-24.04-8core
|
|
175
|
+
strategy:
|
|
176
|
+
fail-fast: false
|
|
177
|
+
matrix:
|
|
178
|
+
sm: ${{ fromJson(needs.gate.outputs.relayer_sms || '[]') }}
|
|
179
|
+
env:
|
|
180
|
+
BASE_REF: ${{ needs.gate.outputs.base_ref }}
|
|
181
|
+
FP_CACHE: ${{ needs.gate.outputs.fp_cache }}
|
|
182
|
+
FP_BASE: ${{ needs.gate.outputs.fp_base }}
|
|
183
|
+
BASE_REVISION: ${{ needs.gate.outputs.base_revision }}
|
|
184
|
+
steps:
|
|
185
|
+
- uses: actions/checkout@v6
|
|
186
|
+
with:
|
|
187
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
188
|
+
|
|
189
|
+
# The graft pulls two ~20GB images (old per-arch tag + fresh base); reclaim runner disk first.
|
|
190
|
+
- name: Free disk space
|
|
191
|
+
run: |
|
|
192
|
+
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup \
|
|
193
|
+
/usr/local/lib/android /opt/hostedtoolcache /usr/share/swift \
|
|
194
|
+
/usr/local/share/boost /usr/local/lib/node_modules \
|
|
195
|
+
/usr/local/share/powershell /usr/share/miniconda || true
|
|
196
|
+
sudo apt-get clean || true
|
|
197
|
+
sudo docker image prune -af || true
|
|
198
|
+
df -h /
|
|
199
|
+
|
|
200
|
+
- uses: docker/setup-buildx-action@v3
|
|
201
|
+
|
|
202
|
+
- name: Log in to GHCR
|
|
203
|
+
uses: docker/login-action@v3
|
|
204
|
+
with:
|
|
205
|
+
registry: ghcr.io
|
|
206
|
+
username: ${{ github.actor }}
|
|
207
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
208
|
+
|
|
209
|
+
# Pin OLDCACHE by digest so a concurrent overwrite of the source tag can't graft a wrong cache.
|
|
210
|
+
- name: Resolve old per-arch cache digest
|
|
211
|
+
id: old
|
|
212
|
+
run: |
|
|
213
|
+
img="ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}"
|
|
214
|
+
digest=$(docker buildx imagetools inspect "$img" --format '{{.Manifest.Digest}}')
|
|
215
|
+
# canonical digest ref (repo@sha256, no tag) for the FROM in the relayer build.
|
|
216
|
+
echo "ref=${img%:*}@$digest" >> "$GITHUB_OUTPUT"
|
|
217
|
+
|
|
218
|
+
- name: Re-layer cache onto the fresh base (no GPU)
|
|
219
|
+
uses: docker/build-push-action@v6
|
|
220
|
+
with:
|
|
221
|
+
context: .
|
|
222
|
+
file: docker/Dockerfile.kernelcache.relayer
|
|
223
|
+
push: true
|
|
224
|
+
tags: ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}
|
|
225
|
+
provenance: false
|
|
226
|
+
build-args: |
|
|
227
|
+
BASE=${{ env.BASE_REF }}
|
|
228
|
+
OLDCACHE=${{ steps.old.outputs.ref }}
|
|
229
|
+
FP_CACHE=${{ env.FP_CACHE }}
|
|
230
|
+
FP_BASE=${{ env.FP_BASE }}
|
|
231
|
+
BASE_REVISION=${{ env.BASE_REVISION }}
|
|
232
|
+
|
|
233
|
+
# PAID path: re-warm the cache on a real GPU per arch. Runs automatically -- the fingerprint gate
|
|
234
|
+
# above is the only thing that decides it fires (only when fp_cache changed), so no manual approval.
|
|
235
|
+
gpu-warm:
|
|
236
|
+
needs: gate
|
|
237
|
+
if: needs.gate.outputs.proceed == 'true' && needs.gate.outputs.gpu_sms != ''
|
|
238
|
+
uses: ./.github/workflows/bake-kernel-cache.yml
|
|
239
|
+
with:
|
|
240
|
+
sms: ${{ needs.gate.outputs.gpu_sms }}
|
|
241
|
+
fp_cache: ${{ needs.gate.outputs.fp_cache }}
|
|
242
|
+
fp_base: ${{ needs.gate.outputs.fp_base }}
|
|
243
|
+
base_ref: ${{ needs.gate.outputs.base_ref }}
|
|
244
|
+
base_revision: ${{ needs.gate.outputs.base_revision }}
|
|
245
|
+
secrets: inherit
|
|
@@ -10,8 +10,12 @@ name: flash worker kernel-cache (per-arch)
|
|
|
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.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Secrets: RUNPOD_API_KEY (the warmup GPU pod) + HF_TOKEN (the temp dataset that ferries code + the
|
|
14
|
+
# cache artifact) are native repo Actions secrets, synced from Infisical (prod:/flash-ci) by the
|
|
15
|
+
# github-ci-flash Secret Sync; the GHCR push uses the default GITHUB_TOKEN. Heavy + paid,
|
|
16
|
+
# but UNGATED: the fingerprint detection in auto-rebake.yml decides WHEN this runs (only on a real
|
|
17
|
+
# kernel-toolchain change), so there is no manual approval step. Invoked by hand (workflow_dispatch)
|
|
18
|
+
# OR automatically by auto-rebake.yml (workflow_call) when the kernel toolchain changed.
|
|
15
19
|
|
|
16
20
|
on:
|
|
17
21
|
workflow_dispatch:
|
|
@@ -20,12 +24,40 @@ on:
|
|
|
20
24
|
description: "comma-separated sm list to bake; default is all validated arches"
|
|
21
25
|
default: "sm80,sm86,sm89,sm90,sm120"
|
|
22
26
|
required: false
|
|
27
|
+
# auto-rebake.yml calls this for the EXPENSIVE path (the cache is invalid and must be re-warmed on a
|
|
28
|
+
# real GPU). It passes the arch subset, the fingerprints to stamp, and a digest-pinned base so the
|
|
29
|
+
# warm runs inside the exact :cu128 the per-arch tag will sit on.
|
|
30
|
+
workflow_call:
|
|
31
|
+
inputs:
|
|
32
|
+
sms:
|
|
33
|
+
type: string
|
|
34
|
+
required: true
|
|
35
|
+
fp_cache:
|
|
36
|
+
type: string
|
|
37
|
+
required: false
|
|
38
|
+
default: ""
|
|
39
|
+
fp_base:
|
|
40
|
+
type: string
|
|
41
|
+
required: false
|
|
42
|
+
default: ""
|
|
43
|
+
base_ref:
|
|
44
|
+
type: string
|
|
45
|
+
required: false
|
|
46
|
+
default: "ghcr.io/freesolo-co/flash-worker:cu128"
|
|
47
|
+
base_revision:
|
|
48
|
+
type: string
|
|
49
|
+
required: false
|
|
50
|
+
default: ""
|
|
23
51
|
|
|
24
52
|
permissions:
|
|
25
53
|
contents: read
|
|
26
54
|
packages: write
|
|
27
55
|
|
|
28
56
|
jobs:
|
|
57
|
+
# Ungated: the PAID RunPod bake runs as soon as it's called/dispatched. The decision of WHEN to run
|
|
58
|
+
# lives in auto-rebake.yml's fingerprint gate (it only invokes this when fp_cache changed), so a
|
|
59
|
+
# second manual approval here would be redundant. Re-add an `approve` job with `environment: gpu-bake`
|
|
60
|
+
# (and `needs: approve`) if you ever want a human checkpoint back.
|
|
29
61
|
bake:
|
|
30
62
|
runs-on: ubuntu-24.04-8core
|
|
31
63
|
strategy:
|
|
@@ -77,19 +109,63 @@ jobs:
|
|
|
77
109
|
allowed_cuda: "13.0",
|
|
78
110
|
}
|
|
79
111
|
steps:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# skip arches not requested in the dispatch input
|
|
112
|
+
# Gate FIRST (no checkout needed) so skipped arches do no crane / checkout / build work.
|
|
83
113
|
- name: Should bake ${{ matrix.sm }}?
|
|
84
114
|
id: gate
|
|
85
115
|
run: |
|
|
86
|
-
req="${{
|
|
116
|
+
req="${{ inputs.sms || 'sm80,sm86,sm89,sm90,sm120' }}"
|
|
87
117
|
req="${req// /}" # tolerate spaces, e.g. "sm80, sm86"
|
|
88
118
|
case ",$req," in
|
|
89
119
|
*,${{ matrix.sm }},*) echo "run=true" >> "$GITHUB_OUTPUT" ;;
|
|
90
120
|
*) echo "run=false" >> "$GITHUB_OUTPUT"; echo "skipping ${{ matrix.sm }}" ;;
|
|
91
121
|
esac
|
|
92
122
|
|
|
123
|
+
- name: Install crane
|
|
124
|
+
if: steps.gate.outputs.run == 'true'
|
|
125
|
+
run: |
|
|
126
|
+
curl -sSL https://github.com/google/go-containerregistry/releases/download/v0.20.2/go-containerregistry_Linux_x86_64.tar.gz \
|
|
127
|
+
| sudo tar -xz -C /usr/local/bin crane
|
|
128
|
+
crane version
|
|
129
|
+
|
|
130
|
+
- name: Log in to GHCR
|
|
131
|
+
if: steps.gate.outputs.run == 'true'
|
|
132
|
+
uses: docker/login-action@v3
|
|
133
|
+
with:
|
|
134
|
+
registry: ghcr.io
|
|
135
|
+
username: ${{ github.actor }}
|
|
136
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
137
|
+
|
|
138
|
+
# Resolve the base + fingerprints BEFORE checkout, so the checkout (hence the warmed flash code)
|
|
139
|
+
# is pinned to the EXACT commit the base was built from. auto-rebake passes everything (fast path);
|
|
140
|
+
# a manual dispatch READS the labels off the published base, so the per-arch image always matches
|
|
141
|
+
# the base it extends (same source of truth as the gate) instead of recomputing from the checkout.
|
|
142
|
+
- name: Resolve base + fingerprints
|
|
143
|
+
id: base
|
|
144
|
+
if: steps.gate.outputs.run == 'true'
|
|
145
|
+
run: |
|
|
146
|
+
if [ -n "${{ inputs.fp_cache }}" ]; then
|
|
147
|
+
echo "ref=${{ inputs.base_ref }}" >> "$GITHUB_OUTPUT"
|
|
148
|
+
echo "fp_cache=${{ inputs.fp_cache }}" >> "$GITHUB_OUTPUT"
|
|
149
|
+
echo "fp_base=${{ inputs.fp_base }}" >> "$GITHUB_OUTPUT"
|
|
150
|
+
echo "revision=${{ inputs.base_revision }}" >> "$GITHUB_OUTPUT"
|
|
151
|
+
else
|
|
152
|
+
base="${{ inputs.base_ref || 'ghcr.io/freesolo-co/flash-worker:cu128' }}"
|
|
153
|
+
digest=$(crane digest "$base"); repo=${base%:*}
|
|
154
|
+
cfg=$(crane config "$repo@$digest")
|
|
155
|
+
echo "ref=$repo@$digest" >> "$GITHUB_OUTPUT"
|
|
156
|
+
echo "fp_cache=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')" >> "$GITHUB_OUTPUT"
|
|
157
|
+
echo "fp_base=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')" >> "$GITHUB_OUTPUT"
|
|
158
|
+
echo "revision=$(echo "$cfg" | jq -r '.config.Labels["org.opencontainers.image.revision"] // ""')" >> "$GITHUB_OUTPUT"
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Pin the checkout to the base's source commit so the warmed flash code matches the base exactly
|
|
162
|
+
# (the cache is content-keyed by the code that compiled it). Falls back to the event sha if the
|
|
163
|
+
# base predates the revision label.
|
|
164
|
+
- uses: actions/checkout@v6
|
|
165
|
+
if: steps.gate.outputs.run == 'true'
|
|
166
|
+
with:
|
|
167
|
+
ref: ${{ steps.base.outputs.revision || github.sha }}
|
|
168
|
+
|
|
93
169
|
- name: Install uv
|
|
94
170
|
if: steps.gate.outputs.run == 'true'
|
|
95
171
|
uses: astral-sh/setup-uv@v5
|
|
@@ -103,17 +179,24 @@ jobs:
|
|
|
103
179
|
if: steps.gate.outputs.run == 'true'
|
|
104
180
|
run: uv sync --extra server
|
|
105
181
|
|
|
182
|
+
# RUNPOD_API_KEY (the warmup GPU pod) + HF_TOKEN (the temp dataset that ferries code/cache) are
|
|
183
|
+
# native repo Actions secrets, synced from Infisical (prod:/flash-ci) by the github-ci-flash
|
|
184
|
+
# Secret Sync. No Infisical CLI/login at job time -- Infisical stays the source of truth and
|
|
185
|
+
# rotations propagate via the sync. FLASH_CHALK_SPEC isn't synced, so bake_kernel_cache.py uses
|
|
186
|
+
# the repo-default DEFAULT_CHALK_SPEC (the value the fingerprint hashed) automatically. BASE_IMAGE
|
|
187
|
+
# is digest-pinned so the warm runs inside the EXACT base the per-arch tag will sit on.
|
|
106
188
|
- name: Warm kernels on a RunPod ${{ matrix.sm }} GPU -> build/kernel_cache
|
|
107
189
|
if: steps.gate.outputs.run == 'true'
|
|
108
190
|
env:
|
|
109
191
|
RUNPOD_API_KEY: ${{ secrets.RUNPOD_API_KEY }}
|
|
110
192
|
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
|
193
|
+
BASE_IMAGE: ${{ steps.base.outputs.ref }}
|
|
111
194
|
run: |
|
|
112
195
|
uv run python docker/bake_kernel_cache.py \
|
|
113
196
|
--arch "${{ matrix.arch }}" --sm "${{ matrix.sm }}" \
|
|
114
197
|
--gpu-type-id "${{ matrix.gpu_type_id }}" \
|
|
115
198
|
--allowed-cuda "${{ matrix.allowed_cuda }}" \
|
|
116
|
-
--image
|
|
199
|
+
--image "$BASE_IMAGE" \
|
|
117
200
|
--out build/kernel_cache
|
|
118
201
|
|
|
119
202
|
- name: Free disk space
|
|
@@ -130,17 +213,9 @@ jobs:
|
|
|
130
213
|
- uses: docker/setup-buildx-action@v3
|
|
131
214
|
if: steps.gate.outputs.run == 'true'
|
|
132
215
|
|
|
133
|
-
- name: Log in to GHCR
|
|
134
|
-
if: steps.gate.outputs.run == 'true'
|
|
135
|
-
uses: docker/login-action@v3
|
|
136
|
-
with:
|
|
137
|
-
registry: ghcr.io
|
|
138
|
-
username: ${{ github.actor }}
|
|
139
|
-
password: ${{ secrets.GITHUB_TOKEN }}
|
|
140
|
-
|
|
141
216
|
# thin layer FROM the SAME base the warmup ran inside -> the cache toolchain always matches the
|
|
142
217
|
# shipped image (rebuilding the full Dockerfile.worker from the checkout could drift from the
|
|
143
|
-
# published base and bake a cache that silently won't load).
|
|
218
|
+
# published base and bake a cache that silently won't load). GHCR auth from the login step above.
|
|
144
219
|
- name: Build + push baked per-sm image (thin layer on the warmed base)
|
|
145
220
|
if: steps.gate.outputs.run == 'true'
|
|
146
221
|
uses: docker/build-push-action@v6
|
|
@@ -151,4 +226,7 @@ jobs:
|
|
|
151
226
|
tags: ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}
|
|
152
227
|
provenance: false
|
|
153
228
|
build-args: |
|
|
154
|
-
BASE
|
|
229
|
+
BASE=${{ steps.base.outputs.ref }}
|
|
230
|
+
FP_CACHE=${{ steps.base.outputs.fp_cache }}
|
|
231
|
+
FP_BASE=${{ steps.base.outputs.fp_base }}
|
|
232
|
+
BASE_REVISION=${{ steps.base.outputs.revision }}
|
|
@@ -36,17 +36,40 @@ on:
|
|
|
36
36
|
# so handler changes (e.g. the weight-cache preload branch) MUST rebuild the image. flash/**
|
|
37
37
|
# covers the handler source (endpoints.py); the generator lives outside flash/, so watch it too.
|
|
38
38
|
- docker/make_rp_handler.py
|
|
39
|
+
# The fp_cache/fp_base labels are computed by this script at build time, so a change to the
|
|
40
|
+
# fingerprint logic must rebuild :cu128 to re-stamp them (else auto-rebake never reclassifies).
|
|
41
|
+
- docker/kernel_fingerprint.py
|
|
39
42
|
|
|
40
43
|
permissions:
|
|
41
44
|
contents: read
|
|
42
45
|
packages: write
|
|
43
46
|
|
|
47
|
+
# A newer base build supersedes an older one: cancel the in-flight run so auto-rebake (which triggers
|
|
48
|
+
# on this workflow's completion) only ever reasons about the latest :cu128. The tag is in the group so
|
|
49
|
+
# a non-prod `tag=cu128-test` dispatch can't cancel an in-flight prod `cu128` push on the same ref
|
|
50
|
+
# (which would leave :cu128 unpublished for that commit and auto-rebake blind to it).
|
|
51
|
+
concurrency:
|
|
52
|
+
group: worker-image-${{ github.ref }}-${{ github.event.inputs.tag || 'cu128' }}
|
|
53
|
+
cancel-in-progress: true
|
|
54
|
+
|
|
44
55
|
jobs:
|
|
45
56
|
build:
|
|
46
57
|
runs-on: ubuntu-24.04-8core
|
|
58
|
+
# Single source for the FlashAttention wheels: used BOTH as build-args and as fingerprint inputs
|
|
59
|
+
# (so a wheel bump moves fp_base). Keep FA3_SPEC in sync with Dockerfile.worker's ARG default.
|
|
60
|
+
env:
|
|
61
|
+
FA2_SPEC: https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.0/flash_attn-2.8.3%2Bcu128torch2.10-cp312-cp312-linux_x86_64.whl
|
|
62
|
+
FA3_SPEC: ${{ github.event.inputs.flash_attn_3_spec || 'https://github.com/windreamer/flash-attention3-wheels/releases/download/2026.03.19-850211f/flash_attn_3-3.0.0%2B20260318.cu128torch2100cxx11abitrue.8afc61-cp39-abi3-linux_x86_64.whl' }}
|
|
47
63
|
steps:
|
|
48
64
|
- uses: actions/checkout@v6
|
|
49
65
|
|
|
66
|
+
# Compute the kernel-cache fingerprints (stdlib-only, no uv sync) and stamp them as labels on
|
|
67
|
+
# :cu128 below, so auto-rebake.yml can read what this base was built from. Fails the build if a
|
|
68
|
+
# pin can't be parsed -- a silent miss would let a stale per-arch cache ship as a cold-JIT.
|
|
69
|
+
- name: Compute kernel fingerprints
|
|
70
|
+
id: fp
|
|
71
|
+
run: python3 docker/kernel_fingerprint.py --format github --fa2-spec "$FA2_SPEC" --fa3-spec "$FA3_SPEC" >> "$GITHUB_OUTPUT"
|
|
72
|
+
|
|
50
73
|
- name: Free disk space
|
|
51
74
|
run: |
|
|
52
75
|
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup \
|
|
@@ -77,21 +100,20 @@ jobs:
|
|
|
77
100
|
# so a fork run must not push to its own owner namespace and leave the real image stale.
|
|
78
101
|
tags: ghcr.io/freesolo-co/flash-worker:${{ github.event.inputs.tag || 'cu128' }}
|
|
79
102
|
provenance: false
|
|
103
|
+
# Stamp the kernel-cache fingerprints + the source commit so auto-rebake.yml can read what
|
|
104
|
+
# this base was built from (docker/kernel_fingerprint.py is the source of truth).
|
|
105
|
+
labels: |
|
|
106
|
+
co.freesolo.flash.kernelcache.fp_cache=${{ steps.fp.outputs.fp_cache }}
|
|
107
|
+
co.freesolo.flash.kernelcache.fp_base=${{ steps.fp.outputs.fp_base }}
|
|
108
|
+
org.opencontainers.image.revision=${{ github.sha }}
|
|
80
109
|
# Install a PREBUILT flash-attn wheel instead of compiling from source (a multi-arch
|
|
81
110
|
# source compile is huge and OOM-kills the runner). The wheel matches the base exactly
|
|
82
|
-
# (cu128 / torch2.10 / cp312).
|
|
111
|
+
# (cu128 / torch2.10 / cp312). FA specs come from the job-level env (single source).
|
|
83
112
|
build-args: |
|
|
84
|
-
FLASH_ATTN_SPEC
|
|
85
|
-
FLASH_ATTN_3_SPEC=${{
|
|
113
|
+
FLASH_ATTN_SPEC=${{ env.FA2_SPEC }}
|
|
114
|
+
FLASH_ATTN_3_SPEC=${{ env.FA3_SPEC }}
|
|
86
115
|
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
run: |
|
|
92
|
-
echo "::warning title=Rebake per-SM images::A new :cu128 base was published. If FLASH_WORKER_IMAGE_PER_SM=1 is enabled, run bake-kernel-cache.yml to refresh cu128-sm{80,86,89,90,120}, else workers run stale baked deps."
|
|
93
|
-
{
|
|
94
|
-
echo "### ⚠️ Per-SM kernel-cache images may now be stale"
|
|
95
|
-
echo ""
|
|
96
|
-
echo "A fresh \`:cu128\` base was just published. If \`FLASH_WORKER_IMAGE_PER_SM=1\` is enabled, re-run **bake-kernel-cache.yml** to refresh the per-arch \`cu128-sm*\` tags, or workers will run the previous baked deps."
|
|
97
|
-
} >> "$GITHUB_STEP_SUMMARY"
|
|
116
|
+
# When :cu128 is republished the per-arch cu128-sm* tags go stale. auto-rebake.yml now handles
|
|
117
|
+
# that automatically on this workflow's completion: a free re-layer when only the base moved, or
|
|
118
|
+
# a one-click GPU re-warm when the kernel toolchain changed (it reads the fp_cache/fp_base labels
|
|
119
|
+
# stamped above vs each published per-arch tag). The old manual reminder is gone.
|
|
@@ -25,9 +25,22 @@ ENV DEBIAN_FRONTEND=noninteractive \
|
|
|
25
25
|
# JIT on a cold worker writes here too. These ENVs are always set (cheap); whether the dir is
|
|
26
26
|
# pre-populated is what the opt-in bake controls. engine.worker._load_kernel_cache_if_present reads
|
|
27
27
|
# /opt/flash/kernelcache at boot.
|
|
28
|
+
# FLASHINFER_CUBIN_DIR / FLASHINFER_CACHE_DIR / FLASHINFER_WORKSPACE_BASE: FlashInfer's attention-backend
|
|
29
|
+
# cubins (the Blackwell sm120 / B200 rollout attention backend) are NOT bundled in the wheel — flashinfer
|
|
30
|
+
# downloads them from NVIDIA Artifactory on first use. Bake the cubin store + JIT cache into the same
|
|
31
|
+
# persistent kernelcache tree so
|
|
32
|
+
# a baked/volume cache serves them and a cold worker never re-fetches from Artifactory (kernel_warmup
|
|
33
|
+
# also sets these). FLASHINFER_WORKSPACE_BASE is the var flashinfer 0.6.x actually reads to relocate the
|
|
34
|
+
# JIT host-wrapper cache (FLASHINFER_CACHE_DIR is a DERIVED constant there, not an env knob), so set it
|
|
35
|
+
# too — otherwise a B200 path that touches flashinfer before kernel_warmup runs lands the wrapper under
|
|
36
|
+
# the default home workspace and re-JITs instead of using the baked cache.
|
|
28
37
|
ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
|
|
29
|
-
TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
|
|
30
|
-
|
|
38
|
+
TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor \
|
|
39
|
+
FLASHINFER_CUBIN_DIR=/opt/flash/kernelcache/flashinfer_cubin \
|
|
40
|
+
FLASHINFER_CACHE_DIR=/opt/flash/kernelcache/flashinfer \
|
|
41
|
+
FLASHINFER_WORKSPACE_BASE=/opt/flash/kernelcache/flashinfer
|
|
42
|
+
RUN mkdir -p /opt/flash/kernelcache/triton /opt/flash/kernelcache/inductor \
|
|
43
|
+
/opt/flash/kernelcache/flashinfer_cubin /opt/flash/kernelcache/flashinfer
|
|
31
44
|
|
|
32
45
|
# build-essential for Triton/Inductor (Liger) + any source builds; git for pip VCS installs.
|
|
33
46
|
RUN apt-get update && apt-get install -y --no-install-recommends build-essential git curl \
|
|
@@ -39,6 +52,7 @@ RUN pip install --no-cache-dir \
|
|
|
39
52
|
"trl>=1.6,<1.7" \
|
|
40
53
|
"peft>=0.19" \
|
|
41
54
|
"vllm==0.19.1" \
|
|
55
|
+
"flashinfer-python==0.6.6" \
|
|
42
56
|
"bitsandbytes>=0.49" \
|
|
43
57
|
"datasets>=4.7,<6" \
|
|
44
58
|
"huggingface_hub>=0.25" \
|
|
@@ -187,10 +201,12 @@ fa_ok = False; \
|
|
|
187
201
|
exec('try:\n import flash_attn\n fa_ok = True\nexcept Exception:\n fa_ok = False'); \
|
|
188
202
|
fa3_ok = False; \
|
|
189
203
|
exec('try:\n import flash_attn_interface\n fa3_ok = True\nexcept Exception:\n fa3_ok = False'); \
|
|
204
|
+
fi_ok = False; \
|
|
205
|
+
exec('try:\n import flashinfer\n fi_ok = True\nexcept Exception:\n fi_ok = False'); \
|
|
190
206
|
cudnn = torch.backends.cudnn.version(); assert cudnn, 'cuDNN not compiled into torch'; \
|
|
191
207
|
ver = lambda n: M.version(n); \
|
|
192
|
-
print('worker stack OK | torch', torch.__version__, '| cudnn', cudnn, '| triton', triton.__version__, '| flash_attn', 'present' if fa_ok else 'ABSENT (SDPA fallback)', '| flash_attn_3', 'present (Hopper FA3)' if fa3_ok else 'ABSENT (SDPA on Hopper)'); \
|
|
193
|
-
[print(' ', d, ver(d)) for d in ['transformers','trl','peft','vllm','datasets','huggingface-hub', \
|
|
208
|
+
print('worker stack OK | torch', torch.__version__, '| cudnn', cudnn, '| triton', triton.__version__, '| flash_attn', 'present' if fa_ok else 'ABSENT (SDPA fallback)', '| flash_attn_3', 'present (Hopper FA3)' if fa3_ok else 'ABSENT (SDPA on Hopper)', '| flashinfer', 'present (B200 MoE/attn)' if fi_ok else 'ABSENT (Triton fused-MoE fallback)'); \
|
|
209
|
+
[print(' ', d, ver(d)) for d in ['transformers','trl','peft','vllm','flashinfer-python','datasets','huggingface-hub', \
|
|
194
210
|
'accelerate','wandb','liger-kernel','flash-linear-attention','bitsandbytes', \
|
|
195
211
|
'hf-transfer','freesolo','runpod']]"
|
|
196
212
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.30
|
|
4
4
|
Summary: Flash — managed LoRA post-training (SFT/GRPO) 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
|
|
@@ -16,3 +16,13 @@ ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
|
|
|
16
16
|
TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
|
|
17
17
|
|
|
18
18
|
COPY build/kernel_cache/ /opt/flash/kernelcache/
|
|
19
|
+
|
|
20
|
+
# Fingerprint + base-revision stamps so auto-rebake.yml can read what this image was baked from and
|
|
21
|
+
# decide skip / re-layer / re-warm (docker/kernel_fingerprint.py is the source of truth for the
|
|
22
|
+
# values). Default to "unknown" so a hand build still works; CI always passes the real ones.
|
|
23
|
+
ARG FP_CACHE=unknown
|
|
24
|
+
ARG FP_BASE=unknown
|
|
25
|
+
ARG BASE_REVISION=unknown
|
|
26
|
+
LABEL co.freesolo.flash.kernelcache.fp_cache=$FP_CACHE \
|
|
27
|
+
co.freesolo.flash.kernelcache.fp_base=$FP_BASE \
|
|
28
|
+
org.opencontainers.image.revision=$BASE_REVISION
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Cheap per-arch RE-LAYER: graft the EXISTING baked mega-cache onto a freshly rebuilt :cu128 base,
|
|
2
|
+
# with NO GPU. Used by auto-rebake.yml when fp_cache is unchanged (the cache is still valid) but the
|
|
3
|
+
# base moved (fp_base changed) -- e.g. an FA2/FA3/causal-conv1d/rp_handler bump. The valid cache
|
|
4
|
+
# already lives inside the currently-published per-arch tag, so OLDCACHE IS the cache store; we just
|
|
5
|
+
# re-stack it on the new base. This is what makes a base-only change free (vs a paid GPU re-warm).
|
|
6
|
+
#
|
|
7
|
+
# BASE and OLDCACHE are passed DIGEST-PINNED by the gate so a concurrent base/tag overwrite can't
|
|
8
|
+
# graft the cache onto the wrong base.
|
|
9
|
+
ARG BASE=ghcr.io/freesolo-co/flash-worker:cu128
|
|
10
|
+
ARG OLDCACHE=ghcr.io/freesolo-co/flash-worker:cu128-sm89
|
|
11
|
+
FROM ${OLDCACHE} AS oldcache
|
|
12
|
+
FROM ${BASE}
|
|
13
|
+
|
|
14
|
+
# Match Dockerfile.worker / Dockerfile.kernelcache so the layer is self-contained even on an older base.
|
|
15
|
+
ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
|
|
16
|
+
TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
|
|
17
|
+
|
|
18
|
+
# Pull the warmed cache straight out of the old per-arch image -- no GPU, no external cache store.
|
|
19
|
+
COPY --from=oldcache /opt/flash/kernelcache /opt/flash/kernelcache
|
|
20
|
+
|
|
21
|
+
# Re-stamp with the CURRENT fingerprints (fp_cache unchanged, fp_base + revision are the new base's).
|
|
22
|
+
ARG FP_CACHE=unknown
|
|
23
|
+
ARG FP_BASE=unknown
|
|
24
|
+
ARG BASE_REVISION=unknown
|
|
25
|
+
LABEL co.freesolo.flash.kernelcache.fp_cache=$FP_CACHE \
|
|
26
|
+
co.freesolo.flash.kernelcache.fp_base=$FP_BASE \
|
|
27
|
+
org.opencontainers.image.revision=$BASE_REVISION
|