freesolo-flash-dev 1.0.74__tar.gz → 1.0.76__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.
Files changed (398) hide show
  1. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/catalog.py +19 -3
  3. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/TRAINING.md +5 -6
  4. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/__init__.py +2 -2
  5. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/env_setup.py +1 -1
  6. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/traces.py +1 -16
  7. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cost/analytical.py +6 -2
  8. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/recipe.py +2 -8
  9. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/vram.py +33 -76
  10. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/backend_common.py +20 -0
  11. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/heartbeat.py +8 -5
  12. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd_train.py +7 -27
  13. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/rl_train.py +15 -119
  14. freesolo_flash_dev-1.0.76/flash/engine/worker/rng.py +29 -0
  15. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/sft_train.py +2 -21
  16. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/multimodal.py +0 -21
  17. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/opd_validation.py +10 -1
  18. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_instance_provider.py +9 -3
  19. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/allocator.py +64 -61
  20. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/base.py +103 -11
  21. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/__init__.py +14 -4
  22. freesolo_flash_dev-1.0.76/flash/providers/lambdalabs/gpus.py +55 -0
  23. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/jobs/__init__.py +52 -8
  24. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/jobs/builders.py +6 -1
  25. freesolo_flash_dev-1.0.76/flash/providers/lambdalabs/pricing.py +64 -0
  26. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/__init__.py +8 -2
  27. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/__init__.py +38 -23
  28. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/api.py +3 -3
  29. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/jobs/__init__.py +33 -3
  30. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/jobs/builders.py +7 -1
  31. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/pricing.py +9 -3
  32. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/runner/__init__.py +17 -36
  33. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/runner/lifecycle.py +22 -25
  34. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/schema/__init__.py +12 -1
  35. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/deploy.py +1 -5
  36. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/billing_retry.py +1 -1
  37. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/routes/runs.py +0 -2
  38. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/pyproject.toml +2 -2
  39. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_allocator.py +31 -5
  40. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_backend_common.py +25 -0
  41. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_billing_retry.py +1 -1
  42. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_gpus_flag.py +14 -11
  43. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_gpus.py +9 -3
  44. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_lambda_runner.py +16 -8
  45. freesolo_flash_dev-1.0.76/tests/test_multi_gpu_gate.py +1017 -0
  46. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_multimodal_training.py +1 -1
  47. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_opd.py +32 -28
  48. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_opd_train.py +54 -54
  49. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_provider_routing.py +6 -4
  50. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_rl_train.py +11 -36
  51. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_billing.py +37 -8
  52. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serving_contract.py +3 -3
  53. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vast_offers.py +37 -1
  54. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/uv.lock +1 -1
  55. freesolo_flash_dev-1.0.74/flash/engine/worker/rng.py +0 -83
  56. freesolo_flash_dev-1.0.74/flash/providers/lambdalabs/gpus.py +0 -17
  57. freesolo_flash_dev-1.0.74/flash/providers/lambdalabs/pricing.py +0 -44
  58. freesolo_flash_dev-1.0.74/tests/test_multi_gpu_gate.py +0 -176
  59. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.dockerignore +0 -0
  60. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.env.example +0 -0
  61. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  62. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  63. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  64. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/dependabot.yml +0 -0
  66. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/auto-rebake.yml +0 -0
  67. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/bake-kernel-cache.yml +0 -0
  68. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/ci.yml +0 -0
  69. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/main-source-guard.yml +0 -0
  70. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/notify-tests-repo.yml +0 -0
  71. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/publish-dev.yml +0 -0
  72. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/publish-image.yml +0 -0
  73. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/publish.yml +0 -0
  74. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/version-parity.yml +0 -0
  75. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.github/workflows/worker-image.yml +0 -0
  76. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/.gitignore +0 -0
  77. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/CODE_OF_CONDUCT.md +0 -0
  78. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/CONTRIBUTING.md +0 -0
  79. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/Dockerfile +0 -0
  80. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/Dockerfile.worker +0 -0
  81. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/LICENSE +0 -0
  82. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/NOTICE +0 -0
  83. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/README.md +0 -0
  84. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/SECURITY.md +0 -0
  85. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/SELF_HOSTING.md +0 -0
  86. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/build/kernel_cache/.gitignore +0 -0
  87. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/build/kernel_cache/.keep +0 -0
  88. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/Dockerfile.kernelcache +0 -0
  89. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/Dockerfile.kernelcache.relayer +0 -0
  90. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/bake_kernel_cache.py +0 -0
  91. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/bake_pod_entry.py +0 -0
  92. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/kernel_fingerprint.py +0 -0
  93. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/docker/make_rp_handler.py +0 -0
  94. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/__init__.py +0 -0
  95. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/_channel.py +0 -0
  96. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/_fileio.py +0 -0
  97. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/_logging.py +0 -0
  98. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/_update_check.py +0 -0
  99. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/adapter_artifacts.py +0 -0
  100. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/__main__.py +0 -0
  101. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/_tty.py +0 -0
  102. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/commands.py +0 -0
  103. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/env_eval.py +0 -0
  104. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/env_test.py +0 -0
  105. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/envpush.py +0 -0
  106. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/render.py +0 -0
  107. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cli/training_doc.py +0 -0
  108. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/client/__init__.py +0 -0
  109. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/client/config.py +0 -0
  110. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/client/http.py +0 -0
  111. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/client/runtime_secrets.py +0 -0
  112. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/client/specs.py +0 -0
  113. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cost/__init__.py +0 -0
  114. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cost/facts.py +0 -0
  115. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cost/spec.py +0 -0
  116. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/cost/types.py +0 -0
  117. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/diagnostics.py +0 -0
  118. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/__init__.py +0 -0
  119. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/accounting.py +0 -0
  120. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/multiturn_reward_scoring.py +0 -0
  121. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/reward_profile.py +0 -0
  122. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/steps.py +0 -0
  123. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/structured_outputs.py +0 -0
  124. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/__init__.py +0 -0
  125. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/__main__.py +0 -0
  126. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/_pkg.py +0 -0
  127. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/adapter.py +0 -0
  128. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/decoding.py +0 -0
  129. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/finalize.py +0 -0
  130. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/grpo.py +0 -0
  131. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/grpo_multiturn.py +0 -0
  132. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/grpo_plugin.py +0 -0
  133. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/hf.py +0 -0
  134. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/kernel_warmup.py +0 -0
  135. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/lora.py +0 -0
  136. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/multiturn_glue.py +0 -0
  137. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd.py +0 -0
  138. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd_gkd.py +0 -0
  139. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd_multiturn.py +0 -0
  140. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd_plugin.py +0 -0
  141. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/opd_structured.py +0 -0
  142. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/packing.py +0 -0
  143. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/__init__.py +0 -0
  144. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/attn.py +0 -0
  145. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/diagnostics.py +0 -0
  146. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/lifecycle.py +0 -0
  147. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/liger.py +0 -0
  148. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/loraplus.py +0 -0
  149. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/perf/memory.py +0 -0
  150. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/rl.py +0 -0
  151. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/rollout_samples.py +0 -0
  152. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/sft.py +0 -0
  153. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/teacher.py +0 -0
  154. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/tokenizer_align.py +0 -0
  155. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker/wandb_log.py +0 -0
  156. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/engine/worker_entrypoint.py +0 -0
  157. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/__init__.py +0 -0
  158. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/adapter.py +0 -0
  159. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/archive.py +0 -0
  160. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/archive_policy.py +0 -0
  161. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/base.py +0 -0
  162. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/evaluations.py +0 -0
  163. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/loader.py +0 -0
  164. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/pull.py +0 -0
  165. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/envs/registry.py +0 -0
  166. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/lora_rank.py +0 -0
  167. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/opd_retry_contract.py +0 -0
  168. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/__init__.py +0 -0
  169. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_auth.py +0 -0
  170. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_deadline.py +0 -0
  171. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_hf_artifacts.py +0 -0
  172. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_hf_retry.py +0 -0
  173. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_http.py +0 -0
  174. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_instance.py +0 -0
  175. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_instance_bootstrap.py +0 -0
  176. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_instance_poll.py +0 -0
  177. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_poll.py +0 -0
  178. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/_worker.py +0 -0
  179. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/api.py +0 -0
  180. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/auth.py +0 -0
  181. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/lambdalabs/preflight.py +0 -0
  182. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/preflight.py +0 -0
  183. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/realized.py +0 -0
  184. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/api.py +0 -0
  185. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/auth.py +0 -0
  186. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/cost.py +0 -0
  187. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/gpus.py +0 -0
  188. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/jobs.py +0 -0
  189. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/keys.py +0 -0
  190. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/preflight.py +0 -0
  191. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/pricing.py +0 -0
  192. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/slots.py +0 -0
  193. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/train/__init__.py +0 -0
  194. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/runpod/train/endpoints.py +0 -0
  195. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/auth.py +0 -0
  196. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/vast/preflight.py +0 -0
  197. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/providers/weight_cache_preload.py +0 -0
  198. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/py.typed +0 -0
  199. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/runner/checkpoints.py +0 -0
  200. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/runner/deploy.py +0 -0
  201. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/runner/verified_revisions.py +0 -0
  202. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/schema/fields.py +0 -0
  203. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/__init__.py +0 -0
  204. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/export.py +0 -0
  205. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/preflight.py +0 -0
  206. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/pricing.py +0 -0
  207. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/serve/urls.py +0 -0
  208. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/__init__.py +0 -0
  209. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/__main__.py +0 -0
  210. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/_deps.py +0 -0
  211. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/_internal_client.py +0 -0
  212. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/_locks.py +0 -0
  213. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/_runtime.py +0 -0
  214. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/app.py +0 -0
  215. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/auth.py +0 -0
  216. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/billing.py +0 -0
  217. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/checkpoints.py +0 -0
  218. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/db.py +0 -0
  219. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/environment_registry.py +0 -0
  220. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/envs.py +0 -0
  221. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/projects.py +0 -0
  222. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/reconcile.py +0 -0
  223. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/repo_cleanup.py +0 -0
  224. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/routes/__init__.py +0 -0
  225. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/routes/envs.py +0 -0
  226. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/routes/meta.py +0 -0
  227. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/routes/serving.py +0 -0
  228. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/server/run_registry.py +0 -0
  229. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/spec.py +0 -0
  230. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/flash/thinking.py +0 -0
  231. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/infisical-entrypoint.sh +0 -0
  232. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/scripts/build_dev_dist.py +0 -0
  233. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/scripts/scrub_history.sh +0 -0
  234. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/__init__.py +0 -0
  235. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/_helpers/__init__.py +0 -0
  236. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/_helpers/runner.py +0 -0
  237. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/_helpers/specs.py +0 -0
  238. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/_helpers/vast.py +0 -0
  239. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/conftest.py +0 -0
  240. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/fixtures/math_eval.jsonl +0 -0
  241. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/fixtures/math_train.jsonl +0 -0
  242. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/live/__init__.py +0 -0
  243. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/live/conftest.py +0 -0
  244. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/live/test_lambda_live.py +0 -0
  245. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/live/test_runpod_live.py +0 -0
  246. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/live/test_vast_live.py +0 -0
  247. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_accounting_coverage.py +0 -0
  248. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_agent_flash_cli_contract.py +0 -0
  249. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_algorithms.py +0 -0
  250. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_async_uploads.py +0 -0
  251. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_backend_jobspec_contract.py +0 -0
  252. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_base_model_provenance.py +0 -0
  253. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cancel_remote.py +0 -0
  254. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_catalog_consistency.py +0 -0
  255. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_charge_pricing.py +0 -0
  256. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_checkpoints.py +0 -0
  257. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_commands.py +0 -0
  258. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_commands_coverage.py +0 -0
  259. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_credential_shadowing.py +0 -0
  260. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_errors.py +0 -0
  261. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_estimate.py +0 -0
  262. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_help.py +0 -0
  263. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_main_coverage.py +0 -0
  264. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_managed.py +0 -0
  265. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_render_coverage.py +0 -0
  266. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_render_theme.py +0 -0
  267. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_traces.py +0 -0
  268. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cli_wandb_warning.py +0 -0
  269. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_client.py +0 -0
  270. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_client_server_integration.py +0 -0
  271. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_client_stream_reads.py +0 -0
  272. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_config_overrides.py +0 -0
  273. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_controlled_experiment_repairs.py +0 -0
  274. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_analytical.py +0 -0
  275. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_equation.py +0 -0
  276. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_estimate.py +0 -0
  277. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_hardware.py +0 -0
  278. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_models.py +0 -0
  279. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_cost_rewards.py +0 -0
  280. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_deploy_latency.py +0 -0
  281. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_dev_channel.py +0 -0
  282. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_disk_gb.py +0 -0
  283. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_endpoint_name.py +0 -0
  284. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_cache_evict.py +0 -0
  285. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_delete.py +0 -0
  286. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_download.py +0 -0
  287. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_download_api.py +0 -0
  288. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_evaluations.py +0 -0
  289. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_no_install.py +0 -0
  290. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_publish.py +0 -0
  291. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_pull.py +0 -0
  292. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_pull_coverage.py +0 -0
  293. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_pull_loader_coverage.py +0 -0
  294. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_pull_managed_control_plane.py +0 -0
  295. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_push.py +0 -0
  296. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_rate_limit_resolve.py +0 -0
  297. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_ref_pinning.py +0 -0
  298. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_env_test.py +0 -0
  299. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_envs_coverage.py +0 -0
  300. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_export.py +0 -0
  301. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_flash_mvp.py +0 -0
  302. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_flash_worker.py +0 -0
  303. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_flashinfer_cache_dirs.py +0 -0
  304. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_github_urlopen_retry.py +0 -0
  305. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_gpu_type_single_field.py +0 -0
  306. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_grpo_mask_aware.py +0 -0
  307. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_grpo_params.py +0 -0
  308. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_grpo_resident_sizing.py +0 -0
  309. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_health_liveness.py +0 -0
  310. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_hf_retry.py +0 -0
  311. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_idle_endpoint_reaper.py +0 -0
  312. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_instance_bootstrap_coverage.py +0 -0
  313. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_internal_client.py +0 -0
  314. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_jobs.py +0 -0
  315. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_kernel_cache.py +0 -0
  316. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_kernel_fingerprint.py +0 -0
  317. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_kv_util.py +0 -0
  318. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_lambda_api_coverage.py +0 -0
  319. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_logging.py +0 -0
  320. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_login_perms.py +0 -0
  321. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_lora_rank_coverage.py +0 -0
  322. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_lora_rank_preflight.py +0 -0
  323. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_managed_config_fields.py +0 -0
  324. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_managed_hf_repo.py +0 -0
  325. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_metrics_schema_agent_contract.py +0 -0
  326. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_mig_guard.py +0 -0
  327. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_multimodal_input_grads.py +0 -0
  328. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_named_reward_metrics.py +0 -0
  329. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_oom_escalate_gpu.py +0 -0
  330. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_opd_resume_safety.py +0 -0
  331. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_open_model_policy.py +0 -0
  332. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_orchestrator_flash.py +0 -0
  333. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_packing.py +0 -0
  334. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_packing_coverage.py +0 -0
  335. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_poll_helpers.py +0 -0
  336. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_preflight.py +0 -0
  337. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_projects.py +0 -0
  338. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_provider_preflight_coverage.py +0 -0
  339. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_provider_teardown_robustness.py +0 -0
  340. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_providers_symmetry.py +0 -0
  341. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_realized_cost.py +0 -0
  342. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_repo_cleanup.py +0 -0
  343. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_resolve_params_b.py +0 -0
  344. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_resume_on_retry.py +0 -0
  345. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_reward_profile.py +0 -0
  346. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_rollout_samples.py +0 -0
  347. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_runmgmt.py +0 -0
  348. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_runpod_api_delete.py +0 -0
  349. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_runpod_key_fingerprint.py +0 -0
  350. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_runpod_key_waterfall.py +0 -0
  351. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_runpod_slots.py +0 -0
  352. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serve.py +0 -0
  353. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serve_reasoning_content.py +0 -0
  354. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_api.py +0 -0
  355. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_app_coverage.py +0 -0
  356. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_auth_singleflight.py +0 -0
  357. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_checkpoints_coverage.py +0 -0
  358. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_db.py +0 -0
  359. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_envs_coverage.py +0 -0
  360. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_locks_coverage.py +0 -0
  361. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_server_standalone.py +0 -0
  362. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serving_context_preflight.py +0 -0
  363. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serving_pricing_coverage.py +0 -0
  364. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_serving_schema_coverage.py +0 -0
  365. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_sft_chunked_nll.py +0 -0
  366. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_sft_example_selection.py +0 -0
  367. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_sft_gc_off.py +0 -0
  368. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_sft_max_context.py +0 -0
  369. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_sft_train.py +0 -0
  370. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_spec_and_validation.py +0 -0
  371. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_step_metrics.py +0 -0
  372. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_structured_outputs.py +0 -0
  373. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_thinking_config.py +0 -0
  374. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_train_context_preflight.py +0 -0
  375. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_training_controls.py +0 -0
  376. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_update_check.py +0 -0
  377. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vast_api.py +0 -0
  378. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vast_api_coverage.py +0 -0
  379. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vast_provider_coverage.py +0 -0
  380. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vast_runner.py +0 -0
  381. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_verified_revisions.py +0 -0
  382. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_verifiers.py +0 -0
  383. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_version.py +0 -0
  384. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  385. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_vram_architecture.py +0 -0
  386. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_wandb_link.py +0 -0
  387. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_wandb_log_coverage.py +0 -0
  388. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_wandb_naming.py +0 -0
  389. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_warmstart_adapter_download.py +0 -0
  390. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_warmstart_cross_repo.py +0 -0
  391. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_warmstart_error_attribution.py +0 -0
  392. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_weight_cache.py +0 -0
  393. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_dryrun.py +0 -0
  394. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_hardexit.py +0 -0
  395. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_image.py +0 -0
  396. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_init_heartbeat.py +0 -0
  397. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_stack.py +0 -0
  398. {freesolo_flash_dev-1.0.74 → freesolo_flash_dev-1.0.76}/tests/test_worker_thinking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 1.0.74
3
+ Version: 1.0.76
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
@@ -615,8 +615,13 @@ def resolve_model(
615
615
  policy: str = "catalog",
616
616
  gpu: str | None = None,
617
617
  model_revision: str = "",
618
+ gpu_count: int = 1,
618
619
  ) -> ModelInfo:
619
- """Resolve a model under the configured policy; "allow" accepts any HF model."""
620
+ """Resolve a model under the configured policy; "allow" accepts any HF model.
621
+
622
+ ``gpu_count`` is the run's card ceiling, forwarded to the open-model fit check so a shardable
623
+ run is judged on the shape it will be allocated rather than on one card.
624
+ """
620
625
  algo = normalize_algorithm(algorithm)
621
626
  if model_id in MODELS:
622
627
  info = validate_model_for_algorithm(model_id, algo)
@@ -634,11 +639,18 @@ def resolve_model(
634
639
  return info
635
640
  if policy != "allow":
636
641
  return get_model(model_id)
637
- return _resolve_open_model(model_id, algo, gpu, model_revision=model_revision)
642
+ return _resolve_open_model(
643
+ model_id, algo, gpu, model_revision=model_revision, gpu_count=gpu_count
644
+ )
638
645
 
639
646
 
640
647
  def _resolve_open_model(
641
- model_id: str, algo: str, gpu: str | None, *, model_revision: str = ""
648
+ model_id: str,
649
+ algo: str,
650
+ gpu: str | None,
651
+ *,
652
+ model_revision: str = "",
653
+ gpu_count: int = 1,
642
654
  ) -> ModelInfo:
643
655
  """Synthesize a ModelInfo for the open-model "allow" policy via a coarse HF VRAM-fit estimate."""
644
656
  from flash.engine.vram import check_fit
@@ -649,6 +661,10 @@ def _resolve_open_model(
649
661
  algo,
650
662
  resolved_gpu,
651
663
  model_revision=model_revision,
664
+ # judge the run on the shape the allocator may rent. the per-card class chosen for a wide
665
+ # ceiling is deliberately smaller, so evaluating it as one card rejects exactly the large
666
+ # models the multi-card path exists to serve.
667
+ gpu_count=gpu_count,
652
668
  )
653
669
  if est.verdict == "too_big":
654
670
  raise ValueError(
@@ -848,7 +848,7 @@ with no reward to design. It supports `epochs` like SFT/GRPO and produces a LoRA
848
848
 
849
849
  - **Pick the teacher with `[train] teacher_model`; the key stays managed.** The teacher defaults to
850
850
  the managed **GLM 5.2** and is selectable from a fixed, managed allow-list:
851
- `glm-5.2` (default), `deepseek-v4-pro`, `kimi-k2.6`. Every option is
851
+ `glm-5.2` (default) or `kimi-k2.6`. Every option is
852
852
  a Fireworks-hosted model reached with the platform's own key, so there is nothing to export or
853
853
  declare — an opd run submits like any other, and a `FIREWORKS_API_KEY` in your shell is ignored.
854
854
  Arbitrary bring-your-own teacher models or keys are not supported (the allow-list is curated to
@@ -883,7 +883,7 @@ epochs = 1
883
883
  max_examples = 2
884
884
  lora_rank = 32
885
885
  # teacher_model = "glm-5.2" # managed teacher to distil from; one of
886
- # # glm-5.2 (default) | deepseek-v4-pro | kimi-k2.6
886
+ # # glm-5.2 (default) | kimi-k2.6
887
887
  # # (key stays managed)
888
888
  # kl_penalty_coef = 1.0 # reverse-KL scale
889
889
  ```
@@ -1274,14 +1274,13 @@ select:
1274
1274
  [gpu]
1275
1275
  type = "B200"
1276
1276
  count = 4
1277
- # provider must also be pinned: not every provider puts all n cards on ONE machine, and
1278
- # submit names the ones that qualify when it rejects an unpinned multi-gpu spec.
1277
+ # provider is optional: allocation compares multi-card shapes across every configured provider
1278
+ # and picks the cheapest that can rent n cards on one machine. pin one only to force a choice.
1279
1279
  ```
1280
1280
 
1281
1281
  `flash train configs/grpo.toml --gpus 4` sets the same key from the command line, so a config can
1282
1282
  stay at its authored count while one submit asks for more. The flag is exactly `--set
1283
- gpu.count=4`: the same 1..8 bound rejects a bad value, and the same submit gate still demands a
1284
- provider that rents all n cards on one machine.
1283
+ gpu.count=4`, and the same 1..8 bound rejects a bad value.
1285
1284
 
1286
1285
  `gpu.count` is a **ceiling, not an exact count** — by either spelling. Allocation treats it as the
1287
1286
  most cards it may use, and it stops at the first count that fits: a class that fits the run on one
@@ -576,8 +576,8 @@ def _build_parser() -> argparse.ArgumentParser:
576
576
  metavar="N",
577
577
  help=(
578
578
  "most cards to run the job on; sets [gpu] count (1-8). a ceiling, not an exact "
579
- "count: allocation still picks one card when one fits the run alone. more than one "
580
- "also needs an explicit [gpu] provider that rents n cards on one machine"
579
+ "count: allocation still picks one card when one fits the run alone, and only "
580
+ "rentable counts (1, 2, 4) are ever provisioned"
581
581
  ),
582
582
  )
583
583
  train.add_argument("--dry-run", action="store_true")
@@ -667,7 +667,7 @@ def cmd_env_setup(args) -> int:
667
667
  f"{max_examples_line}"
668
668
  "lora_rank = 32\n"
669
669
  '# teacher_model = "glm-5.2" # teacher to distil from: glm-5.2 (default) |\n'
670
- "# # deepseek-v4-pro | kimi-k2.6 (key stays managed)\n"
670
+ "# # kimi-k2.6 (key stays managed)\n"
671
671
  "# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
672
672
  "# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
673
673
  )
@@ -24,7 +24,7 @@ import json
24
24
  import sys
25
25
  from pathlib import Path
26
26
 
27
- from flash.client import ApiError, ClientError, export_trace_records, list_trace_projects
27
+ from flash.client import ClientError, export_trace_records, list_trace_projects
28
28
  from flash.client.config import load_credentials
29
29
 
30
30
  from . import render
@@ -92,21 +92,6 @@ def fetch_projects(api_key: str | None = None) -> list[dict]:
92
92
  return list_trace_projects(api_key or _require_api_key())
93
93
 
94
94
 
95
- def offer_projects() -> list[dict]:
96
- """Projects to offer as a starting dataset, or [] when we can't or shouldn't ask.
97
-
98
- Used by `flash env setup`, where traces are an optional head start rather than the point of
99
- the command: not being logged in, being offline, or having no traces yet all mean "just
100
- scaffold the starter dataset", so every such failure returns [] instead of raising."""
101
- _api_url, api_key = load_credentials()
102
- if not api_key:
103
- return []
104
- try:
105
- return fetch_projects(api_key)
106
- except (ApiError, ClientError, OSError, ValueError):
107
- return []
108
-
109
-
110
95
  def _resolve_project_id(args, api_key: str) -> str:
111
96
  project_id = getattr(args, "project", None)
112
97
  if project_id:
@@ -8,6 +8,7 @@ policy/reference update.
8
8
  from __future__ import annotations
9
9
 
10
10
  from flash.providers.allocator import required_vram_gb, vram_headroom
11
+ from flash.providers.base import largest_rentable_count
11
12
 
12
13
  from .facts import (
13
14
  GPU_COMPUTE_TFLOPS,
@@ -434,8 +435,11 @@ def estimate_cost(config: RunConfig, *, wall_cap_s: float = DEFAULT_WALL_CAP_S)
434
435
  gpu, need = select_gpu(config, max_wall_seconds=market_wall_s)
435
436
  quote_provider = config.provider
436
437
  # no gpu_type pin means no allocate() call and so no combination search; this branch picks a
437
- # single class that fits alone, and the run occupies the requested count of it.
438
- billed_gpu_count = config.gpu_count
438
+ # single class that fits alone, and the run occupies that count of it. gpu.count is a CEILING
439
+ # though, and only rentable powers of two are ever provisioned -- billing the raw ceiling
440
+ # would charge a `--gpus 3` run for 3 cards when submit rents 2. this quote is persisted at
441
+ # submit and charged verbatim by _status_estimated_charge, so an over-count here overbills.
442
+ billed_gpu_count = largest_rentable_count(config.gpu_count)
439
443
  # quote the same vram-floored vast market pick_gpu selected under (min_vram_gb=need): without the
440
444
  # floor the rate lookup searches from the smallest managed class, letting cheap small-card offers
441
445
  # crowd a high-vram selection off the limited page -> it silently falls back to the static rate.
@@ -26,8 +26,8 @@ class TeacherModel:
26
26
  display_name: str
27
27
  # Fireworks serverless list price, $/1M tokens as (input, output). OPD echo-scores completions
28
28
  # (max_tokens=0) so only the INPUT column is billed / feeds the estimate, but both are kept so a
29
- # mispriced row is obvious. NOTE: the non-GLM entries are best-effort estimates for these next-gen
30
- # serverless models — confirm against the live fireworks.ai pricing before relying on the
29
+ # mispriced row is obvious. note: the non-glm entry is a best-effort estimate for this next-gen
30
+ # serverless model — confirm against the live fireworks.ai pricing before relying on the
31
31
  # `flash train` cost quote.
32
32
  usd_per_1m: tuple[float, float]
33
33
  supports_images: bool = False
@@ -49,12 +49,6 @@ TEACHER_MODELS: dict[str, TeacherModel] = {
49
49
  display_name="GLM 5.2",
50
50
  usd_per_1m=(1.40, 4.40),
51
51
  ),
52
- "deepseek-v4-pro": TeacherModel(
53
- alias="deepseek-v4-pro",
54
- model_id="accounts/fireworks/models/deepseek-v4-pro",
55
- display_name="DeepSeek V4 Pro",
56
- usd_per_1m=(1.74, 3.48),
57
- ),
58
52
  "kimi-k2.6": TeacherModel(
59
53
  alias="kimi-k2.6",
60
54
  model_id="accounts/fireworks/models/kimi-k2p6",
@@ -28,8 +28,6 @@ _BASE_OVERHEAD_GB = 4.0
28
28
  _ACT_COEF = 0.12
29
29
  _SFT_PER_DEVICE_BS_DEFAULT = 4
30
30
  _VOCAB_DEFAULT = 248_320
31
- _OPD_TRAINING_RESERVE_MULTIPLIER = 1.15
32
- _OPD_ALLOCATOR_MARGIN_MAX_GB = 6.0
33
31
  OPD_CE_CHUNK_SIZE = 64
34
32
  _OPD_CE_PEAK_BYTES_PER_LOGIT = 16
35
33
 
@@ -154,75 +152,6 @@ def _legacy_lora_floor_gb(lora_rank: int, effective_params_b: float) -> float:
154
152
  return (lora_rank / 16.0) * (0.3 + 0.04 * effective_params_b)
155
153
 
156
154
 
157
- def opd_training_peak_gb(
158
- params_b: float,
159
- seq_len: int,
160
- *,
161
- max_tokens: int | None = None,
162
- prompts_per_step: int = 1,
163
- group_size: int = 1,
164
- thinking: bool = False,
165
- vocab: int = _VOCAB_DEFAULT,
166
- active_params_b: float | None = None,
167
- ) -> float:
168
- """Additional OPD loss-forward/backward memory above the resident student model."""
169
- eff_b = float(active_params_b) if active_params_b else float(params_b)
170
- width = math.sqrt(max(eff_b, 0.1))
171
- loss_mb = opd_loss_microbatch(params_b, prompts_per_step, group_size)
172
- activations = loss_mb * _ACT_COEF * (seq_len / 1024.0) * width
173
- completion = opd_completion_len(max_tokens, thinking)
174
- # the backward peak holds both full-sequence bf16 logits and fp32 completion rows plus gradients.
175
- dense_logits = 2 * loss_mb * (seq_len * 2 + completion * 4) * vocab / 1e9
176
- return activations + dense_logits
177
-
178
-
179
- def opd_training_reserve_gb(
180
- params_b: float,
181
- seq_len: int,
182
- *,
183
- max_tokens: int | None = None,
184
- prompts_per_step: int = 1,
185
- group_size: int = 1,
186
- thinking: bool = False,
187
- vocab: int = _VOCAB_DEFAULT,
188
- active_params_b: float | None = None,
189
- ) -> float:
190
- """OPD loss-forward/backward peak with the runtime safety multiplier."""
191
- return _OPD_TRAINING_RESERVE_MULTIPLIER * opd_training_peak_gb(
192
- params_b,
193
- seq_len,
194
- max_tokens=max_tokens,
195
- prompts_per_step=prompts_per_step,
196
- group_size=group_size,
197
- thinking=thinking,
198
- vocab=vocab,
199
- active_params_b=active_params_b,
200
- )
201
-
202
-
203
- def opd_allocator_margin_gb(total_vram_gb: float) -> float:
204
- """Allocator fragmentation slack protected by the OPD startup budget."""
205
- return max(2.0, min(_OPD_ALLOCATOR_MARGIN_MAX_GB, float(total_vram_gb) * 0.05))
206
-
207
-
208
- def opd_post_init_reserve_gb(params_b: float, lora_rank: int) -> float:
209
- """Pending LoRA gradient, AdamW state, and persistent post-init growth above model residency.
210
-
211
- OPD trains all linear layers with bf16 LoRA parameters. PyTorch AdamW lazily allocates two
212
- parameter-dtype moment tensors on the first step, so each estimated trainable parameter needs
213
- 2 bytes for its pending gradient plus 4 bytes for optimizer state. Use total model parameters for
214
- the rank-linear geometry so MoE experts are not undercounted, then reserve the measured 35B-class
215
- first-generation and post-init growth with a size-scaled 12 GB ceiling.
216
- """
217
- model_params_b = max(0.1, float(params_b))
218
- rank = max(1, int(lora_rank))
219
- trainable_params_b = (rank / 16.0) * (0.05 + model_params_b / 150.0)
220
- gradient_gb = trainable_params_b * 2.0
221
- adamw_state_gb = trainable_params_b * 4.0
222
- persistent_growth_gb = max(1.0, min(12.0, model_params_b * 0.35))
223
- return gradient_gb + adamw_state_gb + persistent_growth_gb
224
-
225
-
226
155
  def _lora_memory_gb(
227
156
  lora_rank: int,
228
157
  effective_params_b: float,
@@ -617,12 +546,25 @@ class VramEstimate:
617
546
  gpu: str
618
547
  gpu_gb: int
619
548
  verdict: str # "fits" | "tight" | "too_big" | "unknown"
549
+ # cards the run was JUDGED on -- already clamped to a rentable power of two by check_fit, so
550
+ # describe() reports the shape the verdict was computed against rather than the raw ceiling.
551
+ gpu_count: int = 1
620
552
 
621
553
  def describe(self) -> str:
622
554
  if self.est_gb is None:
623
555
  return f"{self.gpu}: VRAM need unknown (could not read model size)"
556
+ # name the SHAPE, not just the class: "RTX 5090 (32 GB)" reads as a rejection the user
557
+ # could fix with a bigger card, when the run was actually judged on 4 of them.
558
+ shape = f"{self.gpu} ({self.gpu_gb} GB)"
559
+ if self.gpu_count > 1:
560
+ from flash.providers.base import combined_vram_gb
561
+
562
+ shape = (
563
+ f"{self.gpu_count}x {self.gpu} "
564
+ f"({combined_vram_gb(self.gpu_gb, self.gpu_count):.0f} GB combined)"
565
+ )
624
566
  return (
625
- f"{self.gpu} ({self.gpu_gb} GB): estimated ~{self.est_gb:.0f} GB needed "
567
+ f"{shape}: estimated ~{self.est_gb:.0f} GB needed "
626
568
  f"({self.params_b:.1f}B params, {self.quant}, {self.algorithm}) -> {self.verdict}"
627
569
  )
628
570
 
@@ -1252,9 +1194,24 @@ def check_fit(
1252
1194
  quant: str = "bf16",
1253
1195
  params_b: float | None = None,
1254
1196
  model_revision: str = "",
1197
+ gpu_count: int = 1,
1255
1198
  ) -> VramEstimate:
1256
- """Estimate whether ``model_id`` plausibly trains on ``gpu``; never raises."""
1199
+ """Estimate whether ``model_id`` plausibly trains on ``gpu``; never raises.
1200
+
1201
+ ``gpu_count`` is the run's card ceiling. A run allowed to shard must be judged against the
1202
+ capacity of the shape it will actually be allocated: sizing a multi-card run against one card
1203
+ rejects the large models sharding exists to serve, and the per-card class picked for a wide
1204
+ ceiling is deliberately SMALLER than the single-card one.
1205
+ """
1206
+ from flash.providers.base import combined_vram_gb, largest_rentable_count
1207
+
1257
1208
  gpu_gb = GPU_VRAM_GB.get(gpu, 32)
1209
+ # clamp to what the ceiling actually BUYS before sizing: only powers of two up to the
1210
+ # combination cap are ever rented, so a ceiling of 3 provisions 2 cards and a ceiling of 8
1211
+ # provisions 4. sizing on the raw ceiling would accept a shape submit can never allocate --
1212
+ # the parse/submit divergence this parameter exists to close, inverted.
1213
+ cards = largest_rentable_count(gpu_count)
1214
+ usable_gb = combined_vram_gb(gpu_gb, cards)
1258
1215
  if params_b is None:
1259
1216
  if model_revision:
1260
1217
  try:
@@ -1266,10 +1223,10 @@ def check_fit(
1266
1223
  if params_b is None:
1267
1224
  return VramEstimate(None, algorithm, quant, None, gpu, gpu_gb, "unknown")
1268
1225
  est = estimate_vram_gb(params_b, algorithm, quant)
1269
- if est > gpu_gb * 1.15:
1226
+ if est > usable_gb * 1.15:
1270
1227
  verdict = "too_big"
1271
- elif est > gpu_gb * 0.85:
1228
+ elif est > usable_gb * 0.85:
1272
1229
  verdict = "tight"
1273
1230
  else:
1274
1231
  verdict = "fits"
1275
- return VramEstimate(params_b, algorithm, quant, est, gpu, gpu_gb, verdict)
1232
+ return VramEstimate(params_b, algorithm, quant, est, gpu, gpu_gb, verdict, cards)
@@ -669,6 +669,26 @@ def latest_global_step_dir(local_dir: str) -> tuple[str, int]:
669
669
  return best, best_step
670
670
 
671
671
 
672
+ def stage_verl_resume(resume_dir: str, local_dir: str, *, job_label: str) -> int:
673
+ """stage a downloaded ``checkpoint-N`` into local_dir where verl looks; return its step.
674
+
675
+ the resume artifact is keyed on the run prefix, not the job type, so the control plane hands
676
+ every trainer the same ``checkpoint-N`` layout. verl finds it via
677
+ latest_checkpointed_iteration.txt under trainer.default_local_dir once resume_mode=auto.
678
+
679
+ ``job_label`` only names the job in the error raised for an unparseable path, which is the sole
680
+ thing the trainers ever varied here.
681
+ """
682
+ match = re.fullmatch(r"checkpoint-(\d+)", os.path.basename(resume_dir))
683
+ if match is None:
684
+ raise RuntimeError(f"invalid {job_label} resume checkpoint path {resume_dir!r}")
685
+ step = int(match.group(1))
686
+ shutil.copytree(resume_dir, os.path.join(local_dir, f"global_step_{step}"), dirs_exist_ok=True)
687
+ with open(os.path.join(local_dir, "latest_checkpointed_iteration.txt"), "w") as file:
688
+ file.write(str(step))
689
+ return step
690
+
691
+
672
692
  def export_peft_adapter(
673
693
  ckpt_actor_dir: str,
674
694
  out_adapter_dir: str,
@@ -37,11 +37,14 @@ _HB_SETUP_LIVENESS_STAGES = frozenset(
37
37
  "sft_configuring",
38
38
  "opd_configuring",
39
39
  "opd_filtering_prompts",
40
+ "opd_prompt_scan",
41
+ "opd_image_prep",
40
42
  "sft_initializing",
41
43
  "rl_initializing",
42
44
  "opd_initializing",
43
45
  "sft_finalizing",
44
46
  "rl_finalizing",
47
+ "opd_finalizing",
45
48
  }
46
49
  )
47
50
  # Mid-training the per-step checkpoint upload runs SYNCHRONOUSLY on the trainer thread (dev #445),
@@ -57,11 +60,11 @@ _HB_TIGHT_LIVENESS_STAGES = _HB_SETUP_LIVENESS_STAGES | _HB_UPLOAD_LIVENESS_STAG
57
60
  # latest per-step GRPO backlog, exposed so a top-level error heartbeat can preserve it
58
61
  # for `flash runs log -f` when a short run raises before the throttled rl_step ping committed
59
62
  LATEST_GRPO_METRICS_LAST: list = []
60
- # Throttled to avoid blowing the 128/hr HF commit cap; terminal transitions are never throttled. Every
61
- # tight-liveness stage is throttled (⊂) PLUS the per-step training stages: opd_filtering_prompts alone
62
- # emits a REAL (non-liveness) heartbeat every scan tick — ~120/hr on a large split before model load —
63
- # so unthrottled the setup stages blow the cap; throttle them exactly like their sft_pretokenizing
64
- # analogue (codex[bot]). checkpoint_uploading keepalive re-emits every 30s too, so it MUST be throttled.
63
+ # throttle these stages to protect the hf repository commit budget; terminal transitions are never throttled.
64
+ # opd_filtering_prompts emits a real heartbeat on each scan tick, while opd_prompt_scan and
65
+ # opd_image_prep emit one when progress advances. opd_finalizing emits one on every keepalive tick.
66
+ # without throttling, these opd stages can make roughly 120 commit attempts per hour. tight-liveness,
67
+ # per-step training, and checkpoint_uploading keepalive stages share the same throttle.
65
68
  _HB_THROTTLED_STAGES = _HB_TIGHT_LIVENESS_STAGES | frozenset({"rl_step", "sft_step", "opd_step"})
66
69
  _HB_TERMINAL_STAGES = frozenset({"done", "already_done"})
67
70
  # 600s -> ~6 commits/hr; keeps stall detector alive without hitting the HF commit cap.
@@ -1859,28 +1859,6 @@ def _read_classified_failure_fallback(base_path: str) -> tuple[str, str] | None:
1859
1859
  return None
1860
1860
 
1861
1861
 
1862
- def _read_mutation_failure_fallback(base_path: str) -> tuple[str, str] | None:
1863
- return _read_classified_failure_fallback(base_path)
1864
-
1865
-
1866
- def _read_score_delivery_failure_fallback(base_path: str) -> tuple[str, str] | None:
1867
- return _read_classified_failure_fallback(base_path)
1868
-
1869
-
1870
- def _read_cycle_commit_failure_fallback(base_path: str) -> tuple[str, str] | None:
1871
- return _read_classified_failure_fallback(base_path)
1872
-
1873
-
1874
- def _read_abandonment_failure_fallback(
1875
- base_path: str,
1876
- ) -> tuple[str, str] | None:
1877
- return _read_classified_failure_fallback(base_path)
1878
-
1879
-
1880
- def _read_resample_failure_fallback(base_path: str) -> tuple[str, str] | None:
1881
- return _read_classified_failure_fallback(base_path)
1882
-
1883
-
1884
1862
  def _reconcile_score_delivery_failure(
1885
1863
  bridge: _TeacherAlignmentBridge,
1886
1864
  failure: tuple[str, str] | None,
@@ -2141,6 +2119,7 @@ def run_opd_train(spec=None) -> None:
2141
2119
  model_id = spec.model if spec else RECIPE.hf_model_id
2142
2120
  model_revision = getattr(spec, "model_revision", "") if spec else ""
2143
2121
  from flash.opd_validation import validate_opd_structured_outputs
2122
+ from flash.spec import gpu_count_of
2144
2123
 
2145
2124
  structured_validation = validate_opd_structured_outputs(
2146
2125
  knobs.structured_outputs,
@@ -2148,6 +2127,7 @@ def run_opd_train(spec=None) -> None:
2148
2127
  model_revision=model_revision,
2149
2128
  model_policy=getattr(spec, "model_policy", "catalog") if spec else "catalog",
2150
2129
  gpu=spec.gpu.type if spec else None,
2130
+ gpu_count=gpu_count_of(spec) if spec else 1,
2151
2131
  )
2152
2132
  structured_outputs = structured_validation.constraint
2153
2133
  model_vocab_size = structured_validation.model_vocab_size
@@ -2639,19 +2619,19 @@ def run_opd_train(spec=None) -> None:
2639
2619
  peak_gpu_gb = gpu_sampler.stop_gb()
2640
2620
  score_delivery_failure = _reconcile_score_delivery_failure(
2641
2621
  bridge,
2642
- _read_score_delivery_failure_fallback(score_delivery_failure_path),
2622
+ _read_classified_failure_fallback(score_delivery_failure_path),
2643
2623
  )
2644
2624
  no_signal_failure = _reconcile_no_signal_notification_failure(
2645
2625
  bridge,
2646
2626
  (
2647
- _read_resample_failure_fallback(resample_failure_path),
2648
- _read_abandonment_failure_fallback(abandonment_failure_path),
2627
+ _read_classified_failure_fallback(resample_failure_path),
2628
+ _read_classified_failure_fallback(abandonment_failure_path),
2649
2629
  ),
2650
2630
  )
2651
- fallback_mutation_failure = _read_mutation_failure_fallback(mutation_failure_path)
2631
+ fallback_mutation_failure = _read_classified_failure_fallback(mutation_failure_path)
2652
2632
  if fallback_mutation_failure is not None:
2653
2633
  bridge._record_mutation_failure(*fallback_mutation_failure)
2654
- cycle_commit_failure = _read_cycle_commit_failure_fallback(cycle_commit_failure_path)
2634
+ cycle_commit_failure = _read_classified_failure_fallback(cycle_commit_failure_path)
2655
2635
  _raise_verl_failure(
2656
2636
  return_code,
2657
2637
  bridge.teacher_failure,