freesolo-flash-dev 1.0.0__tar.gz → 1.0.2__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 (342) hide show
  1. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/catalog.py +25 -6
  3. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/commands.py +17 -13
  4. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/training_doc.py +42 -0
  5. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/client/http.py +2 -2
  6. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/opd_vllm.py +8 -1
  7. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/runner/__init__.py +2 -2
  8. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/runner/verified_revisions.py +7 -1
  9. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/schema/__init__.py +9 -1
  10. freesolo_flash_dev-1.0.2/flash/serve/export.py +357 -0
  11. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/_deps.py +44 -17
  12. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/repo_cleanup.py +23 -0
  13. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/routes/runs.py +40 -9
  14. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/pyproject.toml +2 -2
  15. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_catalog_consistency.py +30 -8
  16. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_commands.py +21 -1
  17. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_estimate.py +24 -0
  18. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_client.py +2 -2
  19. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_export.py +435 -0
  20. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_jobs.py +7 -3
  21. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_opd.py +45 -0
  22. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_opd_vllm.py +67 -0
  23. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_api.py +229 -7
  24. freesolo_flash_dev-1.0.2/tests/test_serving_context_preflight.py +39 -0
  25. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_train_context_preflight.py +6 -6
  26. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_verified_revisions.py +29 -0
  27. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_warmstart_cross_repo.py +2 -2
  28. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/uv.lock +1 -1
  29. freesolo_flash_dev-1.0.0/flash/serve/export.py +0 -171
  30. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.claude/skills/verify/SKILL.md +0 -0
  31. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.dockerignore +0 -0
  32. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.env.example +0 -0
  33. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/auto-rebake.yml +0 -0
  34. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/bake-kernel-cache.yml +0 -0
  35. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/ci.yml +0 -0
  36. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/main-source-guard.yml +0 -0
  37. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/notify-tests-repo.yml +0 -0
  38. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/publish-dev.yml +0 -0
  39. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/publish-image.yml +0 -0
  40. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/publish.yml +0 -0
  41. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/version-parity.yml +0 -0
  42. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.github/workflows/worker-image.yml +0 -0
  43. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/.gitignore +0 -0
  44. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/Dockerfile +0 -0
  45. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/Dockerfile.worker +0 -0
  46. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/LICENSE +0 -0
  47. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/README.md +0 -0
  48. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/build/kernel_cache/.gitignore +0 -0
  49. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/build/kernel_cache/.keep +0 -0
  50. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/Dockerfile.kernelcache +0 -0
  51. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/Dockerfile.kernelcache.relayer +0 -0
  52. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/bake_kernel_cache.py +0 -0
  53. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/bake_pod_entry.py +0 -0
  54. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/kernel_fingerprint.py +0 -0
  55. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/docker/make_rp_handler.py +0 -0
  56. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/__init__.py +0 -0
  57. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/_channel.py +0 -0
  58. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/_fileio.py +0 -0
  59. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/_logging.py +0 -0
  60. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/_update_check.py +0 -0
  61. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/adapter_artifacts.py +0 -0
  62. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/__init__.py +0 -0
  63. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/__main__.py +0 -0
  64. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/_tty.py +0 -0
  65. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/env_setup.py +0 -0
  66. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/envpush.py +0 -0
  67. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cli/render.py +0 -0
  68. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/client/__init__.py +0 -0
  69. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/client/config.py +0 -0
  70. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/client/runtime_secrets.py +0 -0
  71. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/client/specs.py +0 -0
  72. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cost/__init__.py +0 -0
  73. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cost/analytical.py +0 -0
  74. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cost/facts.py +0 -0
  75. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cost/spec.py +0 -0
  76. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/cost/types.py +0 -0
  77. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/diagnostics.py +0 -0
  78. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/__init__.py +0 -0
  79. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/accounting.py +0 -0
  80. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/chalk_kernels.py +0 -0
  81. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/multiturn_rollout.py +0 -0
  82. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/recipe.py +0 -0
  83. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/steps.py +0 -0
  84. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/structured_outputs.py +0 -0
  85. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/vram.py +0 -0
  86. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/__init__.py +0 -0
  87. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/__main__.py +0 -0
  88. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/_pkg.py +0 -0
  89. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/adapter.py +0 -0
  90. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/decoding.py +0 -0
  91. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/finalize.py +0 -0
  92. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/gpu_setup.py +0 -0
  93. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/grpo.py +0 -0
  94. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/heartbeat.py +0 -0
  95. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/hf.py +0 -0
  96. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/kernel_warmup.py +0 -0
  97. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/lora.py +0 -0
  98. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/opd.py +0 -0
  99. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/opd_gkd.py +0 -0
  100. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/packing.py +0 -0
  101. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/__init__.py +0 -0
  102. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/attn.py +0 -0
  103. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/diagnostics.py +0 -0
  104. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/lifecycle.py +0 -0
  105. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/liger.py +0 -0
  106. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/loraplus.py +0 -0
  107. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/perf/memory.py +0 -0
  108. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/rl.py +0 -0
  109. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/rng.py +0 -0
  110. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/sft.py +0 -0
  111. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/teacher.py +0 -0
  112. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/tokenizer_align.py +0 -0
  113. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker/wandb_log.py +0 -0
  114. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/engine/worker_entrypoint.py +0 -0
  115. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/__init__.py +0 -0
  116. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/adapter.py +0 -0
  117. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/archive.py +0 -0
  118. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/archive_policy.py +0 -0
  119. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/base.py +0 -0
  120. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/loader.py +0 -0
  121. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/pull.py +0 -0
  122. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/envs/registry.py +0 -0
  123. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/lora_rank.py +0 -0
  124. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/opd_retry_contract.py +0 -0
  125. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/__init__.py +0 -0
  126. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_auth.py +0 -0
  127. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_deadline.py +0 -0
  128. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_hf_artifacts.py +0 -0
  129. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_hf_retry.py +0 -0
  130. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_http.py +0 -0
  131. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_instance.py +0 -0
  132. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_instance_bootstrap.py +0 -0
  133. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_instance_poll.py +0 -0
  134. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_instance_provider.py +0 -0
  135. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_poll.py +0 -0
  136. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/_worker.py +0 -0
  137. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/allocator.py +0 -0
  138. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/base.py +0 -0
  139. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/__init__.py +0 -0
  140. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/api.py +0 -0
  141. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/auth.py +0 -0
  142. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/gpus.py +0 -0
  143. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
  144. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  145. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/preflight.py +0 -0
  146. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/lambdalabs/pricing.py +0 -0
  147. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/preflight.py +0 -0
  148. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/realized.py +0 -0
  149. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/__init__.py +0 -0
  150. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/api.py +0 -0
  151. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/auth.py +0 -0
  152. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/cost.py +0 -0
  153. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/gpus.py +0 -0
  154. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/jobs.py +0 -0
  155. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/keys.py +0 -0
  156. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/preflight.py +0 -0
  157. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/preload.py +0 -0
  158. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/pricing.py +0 -0
  159. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/slots.py +0 -0
  160. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/train/__init__.py +0 -0
  161. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/runpod/train/endpoints.py +0 -0
  162. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/__init__.py +0 -0
  163. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/api.py +0 -0
  164. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/auth.py +0 -0
  165. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/jobs/__init__.py +0 -0
  166. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/jobs/builders.py +0 -0
  167. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/preflight.py +0 -0
  168. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/providers/vast/pricing.py +0 -0
  169. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/py.typed +0 -0
  170. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/runner/checkpoints.py +0 -0
  171. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/runner/deploy.py +0 -0
  172. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/runner/lifecycle.py +0 -0
  173. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/schema/fields.py +0 -0
  174. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/serve/__init__.py +0 -0
  175. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/serve/deploy.py +0 -0
  176. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/serve/pricing.py +0 -0
  177. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/serve/urls.py +0 -0
  178. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/__init__.py +0 -0
  179. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/__main__.py +0 -0
  180. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/_internal_client.py +0 -0
  181. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/_locks.py +0 -0
  182. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/_runtime.py +0 -0
  183. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/app.py +0 -0
  184. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/auth.py +0 -0
  185. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/billing.py +0 -0
  186. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/billing_retry.py +0 -0
  187. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/checkpoints.py +0 -0
  188. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/db.py +0 -0
  189. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/environment_registry.py +0 -0
  190. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/envs.py +0 -0
  191. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/reconcile.py +0 -0
  192. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/routes/__init__.py +0 -0
  193. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/routes/envs.py +0 -0
  194. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/routes/meta.py +0 -0
  195. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/routes/serving.py +0 -0
  196. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/server/run_registry.py +0 -0
  197. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/flash/spec.py +0 -0
  198. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/infisical-entrypoint.sh +0 -0
  199. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/scripts/build_dev_dist.py +0 -0
  200. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/__init__.py +0 -0
  201. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/_helpers/__init__.py +0 -0
  202. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/_helpers/runner.py +0 -0
  203. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/_helpers/specs.py +0 -0
  204. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/_helpers/vast.py +0 -0
  205. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/conftest.py +0 -0
  206. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/fixtures/math_eval.jsonl +0 -0
  207. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/fixtures/math_train.jsonl +0 -0
  208. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/live/__init__.py +0 -0
  209. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/live/conftest.py +0 -0
  210. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/live/test_lambda_live.py +0 -0
  211. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/live/test_runpod_live.py +0 -0
  212. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/live/test_vast_live.py +0 -0
  213. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_accounting_coverage.py +0 -0
  214. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_agent_flash_cli_contract.py +0 -0
  215. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_algorithms.py +0 -0
  216. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_allocator.py +0 -0
  217. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_b200_rollout_opt.py +0 -0
  218. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_backend_jobspec_contract.py +0 -0
  219. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_base_model_provenance.py +0 -0
  220. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_billing_retry.py +0 -0
  221. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cancel_remote.py +0 -0
  222. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_chalk_kernels.py +0 -0
  223. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_charge_pricing.py +0 -0
  224. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_checkpoints.py +0 -0
  225. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_commands_coverage.py +0 -0
  226. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_errors.py +0 -0
  227. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_help.py +0 -0
  228. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_main_coverage.py +0 -0
  229. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_managed.py +0 -0
  230. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_render_coverage.py +0 -0
  231. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cli_render_theme.py +0 -0
  232. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_client_server_integration.py +0 -0
  233. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_config_overrides.py +0 -0
  234. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_controlled_experiment_repairs.py +0 -0
  235. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_analytical.py +0 -0
  236. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_equation.py +0 -0
  237. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_estimate.py +0 -0
  238. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_hardware.py +0 -0
  239. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_models.py +0 -0
  240. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_cost_rewards.py +0 -0
  241. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_dev_channel.py +0 -0
  242. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_disk_gb.py +0 -0
  243. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_endpoint_name.py +0 -0
  244. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_cache_evict.py +0 -0
  245. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_delete.py +0 -0
  246. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_download.py +0 -0
  247. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_download_api.py +0 -0
  248. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_no_install.py +0 -0
  249. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_publish.py +0 -0
  250. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_pull.py +0 -0
  251. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_pull_coverage.py +0 -0
  252. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_pull_loader_coverage.py +0 -0
  253. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_pull_managed_control_plane.py +0 -0
  254. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_push.py +0 -0
  255. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_env_rate_limit_resolve.py +0 -0
  256. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_envs_coverage.py +0 -0
  257. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_flash_mvp.py +0 -0
  258. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_flash_worker.py +0 -0
  259. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_flashinfer_cache_dirs.py +0 -0
  260. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_github_urlopen_retry.py +0 -0
  261. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_gpus.py +0 -0
  262. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_grpo_mask_aware.py +0 -0
  263. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_grpo_params.py +0 -0
  264. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_grpo_sleep_gate.py +0 -0
  265. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_health_liveness.py +0 -0
  266. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_hf_retry.py +0 -0
  267. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_idle_endpoint_reaper.py +0 -0
  268. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_instance_bootstrap_coverage.py +0 -0
  269. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_internal_client.py +0 -0
  270. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_kernel_cache.py +0 -0
  271. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_kernel_fingerprint.py +0 -0
  272. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_kv_util.py +0 -0
  273. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_lambda_api_coverage.py +0 -0
  274. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_lambda_runner.py +0 -0
  275. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_logging.py +0 -0
  276. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_login_perms.py +0 -0
  277. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_lora_rank_coverage.py +0 -0
  278. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_lora_rank_preflight.py +0 -0
  279. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_managed_hf_repo.py +0 -0
  280. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_metrics_schema_agent_contract.py +0 -0
  281. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_mig_guard.py +0 -0
  282. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_multiturn_rollout.py +0 -0
  283. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_multiturn_rollout_coverage.py +0 -0
  284. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_multiturn_rollout_records.py +0 -0
  285. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_multiturn_rollout_request_policy.py +0 -0
  286. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_oom_escalate_gpu.py +0 -0
  287. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_opd_full_state_resume.py +0 -0
  288. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_opd_resume_safety.py +0 -0
  289. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_open_model_policy.py +0 -0
  290. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_orchestrator_flash.py +0 -0
  291. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_packing.py +0 -0
  292. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_packing_coverage.py +0 -0
  293. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_poll_helpers.py +0 -0
  294. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_preflight.py +0 -0
  295. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_provider_preflight_coverage.py +0 -0
  296. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_provider_routing.py +0 -0
  297. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_provider_teardown_robustness.py +0 -0
  298. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_providers_symmetry.py +0 -0
  299. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_realized_cost.py +0 -0
  300. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_repo_cleanup.py +0 -0
  301. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_resolve_params_b.py +0 -0
  302. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_resume_on_retry.py +0 -0
  303. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_runmgmt.py +0 -0
  304. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_runpod_api_delete.py +0 -0
  305. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_runpod_key_fingerprint.py +0 -0
  306. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_runpod_key_waterfall.py +0 -0
  307. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_runpod_slots.py +0 -0
  308. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_serve.py +0 -0
  309. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_app_coverage.py +0 -0
  310. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_billing.py +0 -0
  311. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_checkpoints_coverage.py +0 -0
  312. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_db.py +0 -0
  313. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_envs_coverage.py +0 -0
  314. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_server_locks_coverage.py +0 -0
  315. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_serving_contract.py +0 -0
  316. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_serving_pricing_coverage.py +0 -0
  317. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_serving_schema_coverage.py +0 -0
  318. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_sft_example_selection.py +0 -0
  319. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_sft_gc_off.py +0 -0
  320. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_sft_max_context.py +0 -0
  321. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_spec_and_validation.py +0 -0
  322. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_structured_outputs.py +0 -0
  323. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_thinking_config.py +0 -0
  324. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_training_controls.py +0 -0
  325. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_update_check.py +0 -0
  326. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vast_api.py +0 -0
  327. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vast_api_coverage.py +0 -0
  328. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vast_offers.py +0 -0
  329. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vast_provider_coverage.py +0 -0
  330. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vast_runner.py +0 -0
  331. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_verifiers.py +0 -0
  332. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_version.py +0 -0
  333. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  334. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_wandb_log_coverage.py +0 -0
  335. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_wandb_naming.py +0 -0
  336. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_weight_cache.py +0 -0
  337. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_worker_dryrun.py +0 -0
  338. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_worker_hardexit.py +0 -0
  339. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_worker_image.py +0 -0
  340. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_worker_init_heartbeat.py +0 -0
  341. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/tests/test_worker_stack.py +0 -0
  342. {freesolo_flash_dev-1.0.0 → freesolo_flash_dev-1.0.2}/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.0
3
+ Version: 1.0.2
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
@@ -111,6 +111,8 @@ class ModelInfo:
111
111
  # multimodal-nested config, so the curated values are what actually engage the gate.
112
112
  num_layers: int = 0
113
113
  hidden_size: int = 0
114
+ # vllm hybrid-mamba cache block size in tokens. 0 means the model has no catalogued mamba floor.
115
+ mamba_block_size: int = 0
114
116
 
115
117
  @property
116
118
  def is_moe(self) -> bool:
@@ -124,6 +126,8 @@ class ModelInfo:
124
126
 
125
127
  def to_dict(self) -> dict[str, Any]:
126
128
  data = asdict(self)
129
+ if not data["mamba_block_size"]:
130
+ del data["mamba_block_size"]
127
131
  serving = data["serving"]
128
132
  if serving is None:
129
133
  del data["serving"]
@@ -170,7 +174,7 @@ MODELS: dict[str, ModelInfo] = {
170
174
  serve_model_id=SERVING_FP8_MODEL_REPOS["openbmb/MiniCPM5-1B"],
171
175
  max_loras=16,
172
176
  max_lora_rank=128,
173
- max_model_len=8192,
177
+ max_model_len=32768,
174
178
  ),
175
179
  thinking="hybrid",
176
180
  notes="On-device class SLM (131k ctx); standard Llama architecture.",
@@ -189,7 +193,7 @@ MODELS: dict[str, ModelInfo] = {
189
193
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-0.8B"],
190
194
  max_loras=16,
191
195
  max_lora_rank=128,
192
- max_model_len=8192,
196
+ max_model_len=32768,
193
197
  ),
194
198
  thinking="hybrid",
195
199
  notes="Smallest Qwen3.5; cheap smoke/dev runs with the modern arch.",
@@ -208,7 +212,7 @@ MODELS: dict[str, ModelInfo] = {
208
212
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-2B"],
209
213
  max_loras=16,
210
214
  max_lora_rank=128,
211
- max_model_len=8192,
215
+ max_model_len=32768,
212
216
  ),
213
217
  thinking="hybrid",
214
218
  ),
@@ -226,7 +230,7 @@ MODELS: dict[str, ModelInfo] = {
226
230
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-4B"],
227
231
  max_loras=16,
228
232
  max_lora_rank=64,
229
- max_model_len=8192,
233
+ max_model_len=32768,
230
234
  max_num_seqs=8,
231
235
  gpu_memory_utilization=0.98,
232
236
  ),
@@ -247,11 +251,11 @@ MODELS: dict[str, ModelInfo] = {
247
251
  quant="bf16",
248
252
  recommended_gpu="A100 PCIe",
249
253
  serving=ServingCapacity(
250
- gpu="L4",
254
+ gpu="H100",
251
255
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-9B"],
252
256
  max_loras=16,
253
257
  max_lora_rank=64,
254
- max_model_len=8192,
258
+ max_model_len=32768,
255
259
  max_num_seqs=8,
256
260
  gpu_memory_utilization=0.98,
257
261
  ),
@@ -271,6 +275,10 @@ MODELS: dict[str, ModelInfo] = {
271
275
  # layers x 2048 hidden (hybrid GatedDeltaNet + full-attention, 256 experts / 8 active).
272
276
  num_layers=40,
273
277
  hidden_size=2048,
278
+ # vllm 0.19.1 model_executor/models/config.py derives this from the qwen config via
279
+ # mamba_utils.py: the 1,097,728-byte gdn state page needs 1072 fp8 attention tokens
280
+ # after the 16-token backend alignment applied by hybridattentionmambamodelconfig.
281
+ mamba_block_size=1072,
274
282
  vocab_size=248_320,
275
283
  algos=ALGORITHMS,
276
284
  min_vram_gb=141,
@@ -312,6 +320,17 @@ MODELS: dict[str, ModelInfo] = {
312
320
  }
313
321
 
314
322
 
323
+ def opd_mamba_batched_token_floor(
324
+ model_id: str, seq_cap: int, max_num_seqs: int | None
325
+ ) -> int | None:
326
+ """return a mamba floor only when vllm's derived opd scheduler budget is too small."""
327
+ info = MODELS.get(model_id)
328
+ if info is None or info.mamba_block_size <= 0 or max_num_seqs is None:
329
+ return None
330
+ derived_budget = int(max_num_seqs) * int(seq_cap)
331
+ return info.mamba_block_size if derived_budget < info.mamba_block_size else None
332
+
333
+
315
334
  def list_models() -> list[ModelInfo]:
316
335
  return sorted(MODELS.values(), key=lambda m: (m.min_vram_gb, m.id))
317
336
 
@@ -214,6 +214,7 @@ def _cmd_train_cost(args) -> int:
214
214
  Catalog-only and deterministic. SFT cost never imports the environment; it requires a positive
215
215
  [train].max_examples row count instead of guessing or locally counting a dataset."""
216
216
  from flash.cost import estimate_cost
217
+ from flash.lora_rank import preflight_train_context_within_serving
217
218
 
218
219
  spec = spec_from_file(
219
220
  args.config,
@@ -221,6 +222,7 @@ def _cmd_train_cost(args) -> int:
221
222
  overrides=args.overrides,
222
223
  extra_configs=args.extra_configs,
223
224
  )
225
+ preflight_train_context_within_serving(spec)
224
226
  if spec.train.init_from_adapter:
225
227
  # --cost is offline/catalog-only and cannot read the source adapter, so the rank stays at the
226
228
  # local default. Warm starts train and are priced at the SOURCE adapter's authoritative rank
@@ -302,23 +304,24 @@ def cmd_train(args) -> int:
302
304
  )
303
305
  payload = spec_payload(spec, authored_train_keys=authored_train_keys)
304
306
  client = client_from_config()
307
+ client_train_schema = {
308
+ "version": __version__,
309
+ "fields": train_schema_metadata(),
310
+ "authored_keys": sorted(authored_train_keys),
311
+ }
312
+ runtime_secrets = (
313
+ runtime_secrets_from_local_env(args.config, keys=spec.environment.secrets) or None
314
+ )
305
315
  if args.dry_run:
306
- # Dry-run is a faithful server-side preview: the control plane runs the SAME config
307
- # validation and warm-start/serving preflights it would at real submit (serving rank/context
308
- # caps, the continued warm-start rank match, cost quote) and records a state=dry_run run, but
309
- # allocates no GPU and charges nothing. Local runtime secrets aren't sent — the server
310
- # relaxes the required-[environment].secrets check for a preview, so `--dry-run` works before
311
- # prod secrets are wired up. A rejection surfaces as the server's `error: ...` (exit 1),
312
- # exactly as a real submit would.
316
+ # dry-run is a faithful server-side preview: it sends the same declared secrets and runs the
317
+ # same config, warm-start, serving, and cost preflights as a real submit, but allocates no gpu
318
+ # and charges nothing. a rejection surfaces as the server's error with exit status 1.
313
319
  try:
314
320
  status = client.create_run(
315
321
  payload,
322
+ runtime_secrets=runtime_secrets,
316
323
  dry_run=True,
317
- client_train_schema={
318
- "version": __version__,
319
- "fields": train_schema_metadata(),
320
- "authored_keys": sorted(authored_train_keys),
321
- },
324
+ client_train_schema=client_train_schema,
322
325
  )
323
326
  except ApiError as exc:
324
327
  detail = _legacy_train_key_rejection_detail(exc, authored_train_keys)
@@ -338,7 +341,8 @@ def cmd_train(args) -> int:
338
341
  return 0
339
342
  status = client.create_run(
340
343
  payload,
341
- runtime_secrets=runtime_secrets_from_local_env(args.config, keys=spec.environment.secrets),
344
+ runtime_secrets=runtime_secrets,
345
+ client_train_schema=client_train_schema,
342
346
  )
343
347
  run_id = status["run_id"]
344
348
  logger.info(
@@ -154,6 +154,47 @@ flash undeploy <run-id> # tear the endpoint down
154
154
  flash export --adapter-id <run-id> --repository <you>/<repo> # copy adapter weights to your HF repo
155
155
  ```
156
156
 
157
+ ### Loading an exported adapter locally (transformers + peft)
158
+
159
+ Flash trains the Qwen3.5/3.6 family against the full multimodal module tree, so adapter
160
+ weights saved by the worker carry a `language_model.` infix in their tensor keys
161
+ (`base_model.model.model.language_model.layers.*`). During `flash export`, adapters that
162
+ can be represented in the text-only namespace are normalized to
163
+ `base_model.model.model.layers.*`. When an export retains non-LM tensors, it keeps the
164
+ multimodal namespace instead. Do not infer the namespace solely from whether `flash export`
165
+ was used: inspect the keys. For normalized keys, load with vanilla peft and
166
+ `AutoModelForCausalLM`:
167
+
168
+ ```python
169
+ from peft import PeftModel
170
+ from transformers import AutoModelForCausalLM
171
+
172
+ base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-0.8B") # qwen3.5 causal-lm class
173
+ model = PeftModel.from_pretrained(base, "<you>/<repo>")
174
+ ```
175
+
176
+ **Before you trust any local eval, check the key namespace matches the model class you
177
+ loaded.** peft does NOT error on mismatched keys — it emits a `UserWarning` about missing
178
+ adapter keys and silently applies *nothing*, so you would benchmark the bare base model
179
+ believing it is your adapter. If the inspected keys carry the `language_model.` infix,
180
+ load the base with the multimodal class whose parameters live under that namespace instead:
181
+
182
+ ```python
183
+ # infixed keys (base_model.model.model.language_model.layers.*) need the multimodal class:
184
+ from transformers import AutoModelForImageTextToText
185
+
186
+ base = AutoModelForImageTextToText.from_pretrained("Qwen/Qwen3.5-0.8B")
187
+ # qwen3.5/3.6 dense models resolve to Qwen3_5ForConditionalGeneration
188
+ # qwen3.6-35b-a3b (moe) resolves to Qwen3_5MoeForConditionalGeneration
189
+ model = PeftModel.from_pretrained(base, "<you>/<repo>")
190
+ ```
191
+
192
+ To check which form you have, read the safetensors key names (stdlib, no torch needed):
193
+ the JSON header of `adapter_model.safetensors` lists every tensor key. Rule of thumb:
194
+ `model.layers.*` keys pair with `AutoModelForCausalLM`; `model.language_model.layers.*`
195
+ keys pair with the `*ForConditionalGeneration` class. After loading, confirm the adapter
196
+ actually applied: outputs (or a probe metric) must differ from the bare base model.
197
+
157
198
  The rest of this file is about doing the above *well* — designing a reward that teaches,
158
199
  and deciding honestly whether a run improved.
159
200
 
@@ -221,6 +262,7 @@ spending another GPU run:
221
262
  | Run looks stuck after disconnecting | Terminal stopped streaming but the job may still be alive | Ctrl-C detaches. Use `flash log <run-id> --follow` to reattach, `flash log <run-id>` for the console/error output, or `flash cancel <run-id>` if you intentionally want to stop it. |
222
263
  | Final checkpoint regresses | Last step is worse than an earlier checkpoint | Run `flash checkpoints <run-id>`, deploy a specific step with `flash deploy <run-id>/step-N`, and compare with held-out probes before exporting or relying on the final adapter. |
223
264
  | Export fails before upload | CLI says no HuggingFace token | Pass `flash export --api-key hf_...`, or set `HF_TOKEN` in your shell, `.env`, or `.env.local`. Exports are private unless you pass `--public`. |
265
+ | Exported adapter is a silent no-op locally | peft warns about missing adapter keys and local eval matches the bare base model | The adapter's key namespace does not match the loaded model class. `model.layers.*` keys pair with `AutoModelForCausalLM`; `model.language_model.layers.*` keys pair with `Qwen3_5ForConditionalGeneration` / `Qwen3_5MoeForConditionalGeneration` (via `AutoModelForImageTextToText`). See "Loading an exported adapter locally". |
224
266
  | SFT loss improves but quality does not | Train loss falls while held-out behavior stalls or degrades | Keep a held-out split outside training. Deploy and score that split; if quality drops, reduce epochs or improve data instead of adding more passes. |
225
267
  | Cost surprises | A quick experiment uses more GPU time than intended | Start with `--dry-run` and `--cost`, keep `epochs` and `max_examples` small for smoke tests, and scale only after reward/data wiring is proven. Setup time is reported for observability; customer cost is based on training-loop GPU time. |
226
268
 
@@ -343,8 +343,8 @@ class ApiClient:
343
343
  # Server-side preview: runs the same validation/preflights as a real submit and records a
344
344
  # state=dry_run run, but allocates no GPU and charges nothing. Returns that status.
345
345
  body["dry_run"] = True
346
- if client_train_schema is not None:
347
- body["client_train_schema"] = client_train_schema
346
+ if client_train_schema is not None:
347
+ body["client_train_schema"] = client_train_schema
348
348
  return self._request("POST", "/v1/runs", body=body)
349
349
 
350
350
  def list_runs(self) -> list[dict]:
@@ -127,7 +127,8 @@ def opd_vllm_kwargs(model_id: str, knobs: Any, seq_cap: int) -> dict[str, Any]:
127
127
 
128
128
  fp8_kv = bool(cc >= (8, 9))
129
129
  kwargs["kv_cache_dtype"] = "fp8" if fp8_kv else None
130
- kwargs["max_num_batched_tokens"] = max(8192, int(seq_cap)) if card_gb >= 140 else None
130
+ if card_gb >= 140:
131
+ kwargs["max_num_batched_tokens"] = max(8192, int(seq_cap))
131
132
 
132
133
  if card_gb > 0:
133
134
  try:
@@ -189,6 +190,12 @@ def opd_vllm_kwargs(model_id: str, knobs: Any, seq_cap: int) -> dict[str, Any]:
189
190
  kwargs["rollout_batch_size"] = rollout_concurrency
190
191
  except Exception as exc:
191
192
  print(f"[opd] vLLM memory-util sizing failed; using 0.10: {exc}")
193
+ if card_gb < 140:
194
+ from flash.catalog import opd_mamba_batched_token_floor
195
+
196
+ kwargs["max_num_batched_tokens"] = opd_mamba_batched_token_floor(
197
+ model_id, seq_cap, kwargs["max_num_seqs"]
198
+ )
192
199
  if startup_oom is not None:
193
200
  raise startup_oom
194
201
 
@@ -691,7 +691,7 @@ def _prepare_init_from_adapter(
691
691
  owner_key_id: int | None = None,
692
692
  token: str | None = None,
693
693
  ) -> tuple[JobSpec, JobSpec, dict | None]:
694
- """Preserve the public request while applying source metadata only to the worker spec."""
694
+ """prepare public and worker specs with source-authoritative adapter metadata."""
695
695
  _require_supported_adapter_continuation(spec)
696
696
  ref = spec.train.init_from_adapter
697
697
  if not ref:
@@ -776,7 +776,7 @@ def _prepare_init_from_adapter(
776
776
  )
777
777
  assert metadata is not None
778
778
  identity = adapter_artifact_identity(storage, config, token, revision).to_dict()
779
- public_spec = spec
779
+ public_spec = replace(spec, train=replace(spec.train, lora_alpha=metadata.alpha))
780
780
  worker_spec = replace(
781
781
  worker_spec,
782
782
  train=replace(worker_spec.train, lora_rank=metadata.rank, lora_alpha=metadata.alpha),
@@ -3,13 +3,17 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import contextlib
6
- import fcntl
7
6
  import json
8
7
  import os
9
8
  import tempfile
10
9
  from collections.abc import Callable, Iterator
11
10
  from contextlib import contextmanager
12
11
 
12
+ try:
13
+ import fcntl
14
+ except ImportError: # pragma: no cover - linux production fails closed below
15
+ fcntl = None
16
+
13
17
  from flash.schema import parse_adapter_revision
14
18
 
15
19
  _LEDGER_SUFFIX = ".verified-revisions"
@@ -29,6 +33,8 @@ def _paths(run_id: str) -> tuple[str, str, str]:
29
33
 
30
34
  @contextmanager
31
35
  def _locked_ledger(run_id: str, *, exclusive: bool) -> Iterator[tuple[str, str]]:
36
+ if fcntl is None:
37
+ raise RuntimeError("interprocess verified-revision locking is unavailable")
32
38
  runs_dir, ledger_path, lock_path = _paths(run_id)
33
39
  fd = os.open(lock_path, os.O_CREAT | os.O_RDWR, 0o600)
34
40
  with os.fdopen(fd, "a+") as lock_file:
@@ -546,7 +546,12 @@ def _validate_grpo(spec: JobSpec) -> None:
546
546
 
547
547
 
548
548
  def _validate_opd(spec: JobSpec) -> None:
549
- """validate that the opd context budget leaves room for a prompt."""
549
+ """validate opd-specific training constraints."""
550
+ if spec.train.kl_penalty_coef == 0.0:
551
+ raise ConfigError(
552
+ "[train] kl_penalty_coef must be > 0 for opd because it scales the gkd "
553
+ "distillation objective; omit it to use the default 1.0 or set a positive value"
554
+ )
550
555
  if spec.train.max_context_tokens:
551
556
  # Mirror run_opd's prompt-budget guard at PARSE time: a context budget that leaves no room
552
557
  # for any prompt after the completion budget is rejected here, BEFORE a paid worker is
@@ -564,6 +569,9 @@ def _validate_opd(spec: JobSpec) -> None:
564
569
  f"invalid budget fails before a GPU worker is provisioned."
565
570
  )
566
571
 
572
+ # short hybrid-mamba contexts are safe because the worker compares vllm's derived scheduler
573
+ # budget with the catalogued block size and supplies an explicit floor only when required.
574
+
567
575
 
568
576
  # Each algorithm's spec-level contract lives in ONE validator, dispatched by name so a new algorithm
569
577
  # adds a function + a map entry rather than another scattered ``if spec.algorithm == ...`` block.