freesolo-flash-dev 0.2.37__tar.gz → 0.2.38__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 (279) hide show
  1. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/Dockerfile.worker +5 -6
  2. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/PKG-INFO +1 -1
  3. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/Dockerfile.kernelcache +1 -1
  4. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/bake_kernel_cache.py +4 -4
  5. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/kernel_fingerprint.py +43 -5
  6. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/catalog.py +27 -14
  7. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/__init__.py +1 -2
  8. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/envpush.py +16 -34
  9. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/chalk_kernels.py +30 -7
  10. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/vram.py +13 -3
  11. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/kernel_warmup.py +18 -98
  12. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/rl.py +15 -85
  13. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/sft.py +93 -26
  14. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/pull.py +3 -87
  15. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_instance_bootstrap.py +35 -3
  16. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/train/__init__.py +1 -0
  17. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/train/deps.py +10 -3
  18. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/train/endpoints.py +33 -3
  19. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/pyproject.toml +7 -10
  20. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_allocator.py +35 -0
  21. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_catalog_consistency.py +32 -21
  22. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_chalk_kernels.py +34 -13
  23. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_pull.py +99 -411
  24. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_flash_worker.py +104 -11
  25. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_grpo_params.py +16 -40
  26. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_kernel_cache.py +38 -0
  27. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_kernel_fingerprint.py +9 -2
  28. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_lambda_runner.py +68 -0
  29. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_lora_rank_preflight.py +11 -6
  30. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_serve.py +9 -6
  31. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_spec_and_validation.py +9 -6
  32. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_vl_warmstart_recombine.py +20 -14
  33. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/uv.lock +1 -1
  34. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.dockerignore +0 -0
  35. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.env.example +0 -0
  36. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/auto-rebake.yml +0 -0
  37. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/bake-kernel-cache.yml +0 -0
  38. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/ci.yml +0 -0
  39. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/main-source-guard.yml +0 -0
  40. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/notify-tests-repo.yml +0 -0
  41. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/publish-dev.yml +0 -0
  42. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/publish-image.yml +0 -0
  43. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/publish.yml +0 -0
  44. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/version-parity.yml +0 -0
  45. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.github/workflows/worker-image.yml +0 -0
  46. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/.gitignore +0 -0
  47. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/Dockerfile +0 -0
  48. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/LICENSE +0 -0
  49. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/README.md +0 -0
  50. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/build/kernel_cache/.gitignore +0 -0
  51. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/build/kernel_cache/.keep +0 -0
  52. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/Dockerfile.kernelcache.relayer +0 -0
  53. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/bake_pod_entry.py +0 -0
  54. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docker/make_rp_handler.py +0 -0
  55. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/cli-style/README.md +0 -0
  56. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/cli-style/generate.py +0 -0
  57. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/cli-style/index.html +0 -0
  58. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/cli-style/preview.png +0 -0
  59. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/cli-style/themed-errors.png +0 -0
  60. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/docs/kernel-cache.md +0 -0
  61. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/__init__.py +0 -0
  62. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/_channel.py +0 -0
  63. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/_fileio.py +0 -0
  64. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/_logging.py +0 -0
  65. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/_update_check.py +0 -0
  66. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/adapter_artifacts.py +0 -0
  67. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/__main__.py +0 -0
  68. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/_tty.py +0 -0
  69. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/commands.py +0 -0
  70. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/render.py +0 -0
  71. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cli/training_doc.py +0 -0
  72. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/client/__init__.py +0 -0
  73. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/client/config.py +0 -0
  74. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/client/http.py +0 -0
  75. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/client/runtime_secrets.py +0 -0
  76. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/client/specs.py +0 -0
  77. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cost/__init__.py +0 -0
  78. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cost/analytical.py +0 -0
  79. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cost/facts.py +0 -0
  80. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cost/spec.py +0 -0
  81. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/cost/types.py +0 -0
  82. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/__init__.py +0 -0
  83. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/accounting.py +0 -0
  84. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/multiturn_rollout.py +0 -0
  85. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/recipe.py +0 -0
  86. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/__init__.py +0 -0
  87. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/__main__.py +0 -0
  88. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/_pkg.py +0 -0
  89. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/adapter.py +0 -0
  90. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/decoding.py +0 -0
  91. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/finalize.py +0 -0
  92. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/gpu_setup.py +0 -0
  93. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/grpo.py +0 -0
  94. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/heartbeat.py +0 -0
  95. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/hf.py +0 -0
  96. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/lora.py +0 -0
  97. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/packing.py +0 -0
  98. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/__init__.py +0 -0
  99. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/attn.py +0 -0
  100. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/diagnostics.py +0 -0
  101. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/lifecycle.py +0 -0
  102. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/liger.py +0 -0
  103. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/loraplus.py +0 -0
  104. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/perf/memory.py +0 -0
  105. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/engine/worker/wandb_log.py +0 -0
  106. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/__init__.py +0 -0
  107. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/adapter.py +0 -0
  108. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/archive_policy.py +0 -0
  109. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/base.py +0 -0
  110. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/loader.py +0 -0
  111. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/envs/registry.py +0 -0
  112. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/lora_rank.py +0 -0
  113. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/__init__.py +0 -0
  114. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_auth.py +0 -0
  115. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_hf_retry.py +0 -0
  116. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_http.py +0 -0
  117. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_instance.py +0 -0
  118. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/_poll.py +0 -0
  119. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/allocator.py +0 -0
  120. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/base.py +0 -0
  121. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/__init__.py +0 -0
  122. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/api.py +0 -0
  123. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/auth.py +0 -0
  124. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/gpus.py +0 -0
  125. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
  126. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  127. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/preflight.py +0 -0
  128. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/pricing.py +0 -0
  129. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/lambdalabs/train.py +0 -0
  130. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/preflight.py +0 -0
  131. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/realized.py +0 -0
  132. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/__init__.py +0 -0
  133. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/api.py +0 -0
  134. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/auth.py +0 -0
  135. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/cost.py +0 -0
  136. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/gpus.py +0 -0
  137. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/jobs.py +0 -0
  138. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/keys.py +0 -0
  139. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/preflight.py +0 -0
  140. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/preload.py +0 -0
  141. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/pricing.py +0 -0
  142. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/providers/runpod/slots.py +0 -0
  143. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/py.typed +0 -0
  144. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/runner/__init__.py +0 -0
  145. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/runner/checkpoints.py +0 -0
  146. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/runner/deploy.py +0 -0
  147. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/runner/lifecycle.py +0 -0
  148. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/schema/__init__.py +0 -0
  149. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/schema/fields.py +0 -0
  150. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/serve/__init__.py +0 -0
  151. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/serve/deploy.py +0 -0
  152. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/serve/export.py +0 -0
  153. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/serve/pricing.py +0 -0
  154. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/__init__.py +0 -0
  155. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/__main__.py +0 -0
  156. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/_deps.py +0 -0
  157. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/_internal_client.py +0 -0
  158. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/_locks.py +0 -0
  159. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/_runtime.py +0 -0
  160. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/app.py +0 -0
  161. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/auth.py +0 -0
  162. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/billing.py +0 -0
  163. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/billing_retry.py +0 -0
  164. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/checkpoints.py +0 -0
  165. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/db.py +0 -0
  166. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/environment_registry.py +0 -0
  167. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/envs.py +0 -0
  168. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/reconcile.py +0 -0
  169. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/routes/__init__.py +0 -0
  170. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/routes/envs.py +0 -0
  171. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/routes/meta.py +0 -0
  172. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/routes/runs.py +0 -0
  173. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/routes/serving.py +0 -0
  174. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/server/run_registry.py +0 -0
  175. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/flash/spec.py +0 -0
  176. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/infisical-entrypoint.sh +0 -0
  177. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/scripts/build_dev_dist.py +0 -0
  178. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/__init__.py +0 -0
  179. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/_helpers/__init__.py +0 -0
  180. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/_helpers/runner.py +0 -0
  181. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/_helpers/specs.py +0 -0
  182. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/conftest.py +0 -0
  183. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/fixtures/math_eval.jsonl +0 -0
  184. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/fixtures/math_train.jsonl +0 -0
  185. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/live/__init__.py +0 -0
  186. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/live/conftest.py +0 -0
  187. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/live/test_lambda_live.py +0 -0
  188. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/live/test_runpod_live.py +0 -0
  189. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_agent_flash_cli_contract.py +0 -0
  190. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_algorithms.py +0 -0
  191. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_b200_rollout_opt.py +0 -0
  192. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_backend_jobspec_contract.py +0 -0
  193. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_billing_retry.py +0 -0
  194. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cancel_remote.py +0 -0
  195. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_charge_pricing.py +0 -0
  196. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_checkpoints.py +0 -0
  197. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_commands.py +0 -0
  198. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_errors.py +0 -0
  199. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_estimate.py +0 -0
  200. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_help.py +0 -0
  201. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_managed.py +0 -0
  202. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cli_render_theme.py +0 -0
  203. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_client.py +0 -0
  204. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_client_server_integration.py +0 -0
  205. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_config_overrides.py +0 -0
  206. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_analytical.py +0 -0
  207. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_equation.py +0 -0
  208. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_estimate.py +0 -0
  209. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_hardware.py +0 -0
  210. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_models.py +0 -0
  211. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_cost_rewards.py +0 -0
  212. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_dev_channel.py +0 -0
  213. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_disk_gb.py +0 -0
  214. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_endpoint_name.py +0 -0
  215. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_cache_evict.py +0 -0
  216. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_delete.py +0 -0
  217. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_download.py +0 -0
  218. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_download_api.py +0 -0
  219. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_no_install.py +0 -0
  220. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_publish.py +0 -0
  221. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_pull_managed_control_plane.py +0 -0
  222. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_push.py +0 -0
  223. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_env_rate_limit_resolve.py +0 -0
  224. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_envs_coverage.py +0 -0
  225. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_export.py +0 -0
  226. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_flash_mvp.py +0 -0
  227. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_flashinfer_cache_dirs.py +0 -0
  228. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_github_urlopen_retry.py +0 -0
  229. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_gpus.py +0 -0
  230. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_grpo_mask_aware.py +0 -0
  231. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_grpo_sleep_gate.py +0 -0
  232. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_health_liveness.py +0 -0
  233. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_idle_endpoint_reaper.py +0 -0
  234. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_internal_client.py +0 -0
  235. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_jobs.py +0 -0
  236. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_kv_util.py +0 -0
  237. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_logging.py +0 -0
  238. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_login_perms.py +0 -0
  239. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_managed_hf_repo.py +0 -0
  240. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_metrics_schema_agent_contract.py +0 -0
  241. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_mig_guard.py +0 -0
  242. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_multiturn_rollout.py +0 -0
  243. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_oom_escalate_gpu.py +0 -0
  244. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_open_model_policy.py +0 -0
  245. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_orchestrator_flash.py +0 -0
  246. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_packing.py +0 -0
  247. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_poll_helpers.py +0 -0
  248. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_preflight.py +0 -0
  249. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_provider_routing.py +0 -0
  250. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_provider_teardown_robustness.py +0 -0
  251. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_providers_symmetry.py +0 -0
  252. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_realized_cost.py +0 -0
  253. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_resolve_params_b.py +0 -0
  254. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_resume_on_retry.py +0 -0
  255. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_runmgmt.py +0 -0
  256. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_runpod_api_delete.py +0 -0
  257. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_runpod_key_fingerprint.py +0 -0
  258. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_runpod_key_waterfall.py +0 -0
  259. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_runpod_slots.py +0 -0
  260. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_server_api.py +0 -0
  261. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_server_billing.py +0 -0
  262. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_server_db.py +0 -0
  263. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_serving_contract.py +0 -0
  264. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_sft_gc_off.py +0 -0
  265. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_thinking_config.py +0 -0
  266. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_update_check.py +0 -0
  267. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_verifiers.py +0 -0
  268. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_version.py +0 -0
  269. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  270. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_vl_weight_sync.py +0 -0
  271. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_wandb_naming.py +0 -0
  272. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_warmstart_cross_repo.py +0 -0
  273. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_weight_cache.py +0 -0
  274. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_dryrun.py +0 -0
  275. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_hardexit.py +0 -0
  276. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_image.py +0 -0
  277. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_init_heartbeat.py +0 -0
  278. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_stack.py +0 -0
  279. {freesolo_flash_dev-0.2.37 → freesolo_flash_dev-0.2.38}/tests/test_worker_thinking.py +0 -0
@@ -42,7 +42,7 @@ ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
42
42
  RUN mkdir -p /opt/flash/kernelcache/triton /opt/flash/kernelcache/inductor \
43
43
  /opt/flash/kernelcache/flashinfer_cubin /opt/flash/kernelcache/flashinfer
44
44
 
45
- # build-essential for Triton/Inductor (Liger) + any source builds; git for pip VCS installs.
45
+ # build-essential for Triton/Inductor/chalk + any source builds; git for pip VCS installs.
46
46
  RUN apt-get update && apt-get install -y --no-install-recommends build-essential git curl \
47
47
  && rm -rf /var/lib/apt/lists/*
48
48
 
@@ -58,7 +58,6 @@ RUN pip install --no-cache-dir \
58
58
  "huggingface_hub>=0.25" \
59
59
  "accelerate>=1.4" \
60
60
  "wandb>=0.17" \
61
- "liger-kernel>=0.5" \
62
61
  "flash-linear-attention @ git+https://github.com/fla-org/flash-linear-attention.git@f0e213dbd8b5fb90c3c7eca869ac1706d5377139" \
63
62
  "tilelang==0.1.11" \
64
63
  "apache-tvm-ffi==0.1.11" \
@@ -148,7 +147,7 @@ RUN TORCH_CUDA_ARCH_LIST="8.0 8.6 8.9 9.0 10.0 12.0" CAUSAL_CONV1D_FORCE_BUILD=T
148
147
  # affect another tenant). The redirect can't be a static image ENV: the volume mounts at a fixed path
149
148
  # only at runtime and only when attached, so a baked ENV would break cache-less (no-volume) cold runs.
150
149
  #
151
- # Compiled-kernel cache: OPT-IN bake, JIT fallback. The fused Triton (Liger/fla/chalk),
150
+ # Compiled-kernel cache: OPT-IN bake, JIT fallback. The fused Triton (fla/chalk),
152
151
  # TorchInductor, and Hopper tilelang kernels the trainer builds on first use are content-addressed
153
152
  # by GPU ARCH + toolchain version, so they can only be compiled on a real GPU of each catalog arch
154
153
  # (8.0/8.6/8.9/9.0/12.0) — which the CI image builder normally lacks (the FA2 *source* path above
@@ -187,7 +186,7 @@ RUN if [ "${BUILD_KERNEL_CACHE}" = "true" ] && [ -f /opt/flash/kernelcache/mega_
187
186
  # Sanity: the worker imports must succeed (catches a broken stack at build time, not run time).
188
187
  # Import EVERY package the worker runtime uses (derived from a full AST scan of the engine/envs/
189
188
  # bootstrap code + the WORKER_DEPS list above): the core stack, the optimizer/accelerator libs
190
- # (liger, flash-linear-attention=fla, flash_attn, bitsandbytes, triton), and the HF/env libs. A
189
+ # (flash-linear-attention=fla, flash_attn, bitsandbytes, triton), and the HF/env libs. A
191
190
  # missing or ABI-broken package fails the build HERE instead of silently shipping (the FA wheel in
192
191
  # particular can install yet fail to import against this torch). cuDNN comes from the base image.
193
192
  # flash_attn is BEST-EFFORT (the install above tolerates a build failure -> SDPA fallback), so it
@@ -195,7 +194,7 @@ RUN if [ "${BUILD_KERNEL_CACHE}" = "true" ] && [ -f /opt/flash/kernelcache/mega_
195
194
  # could never be produced. The rest of the stack is mandatory.
196
195
  RUN python -c "import importlib.metadata as M; \
197
196
  import torch, transformers, trl, peft, vllm, datasets, huggingface_hub, accelerate, wandb, \
198
- liger_kernel, fla, bitsandbytes, hf_transfer, triton, freesolo, runpod; \
197
+ fla, bitsandbytes, hf_transfer, triton, freesolo, runpod; \
199
198
  import importlib; \
200
199
  fa_ok = False; \
201
200
  exec('try:\n import flash_attn\n fa_ok = True\nexcept Exception:\n fa_ok = False'); \
@@ -207,7 +206,7 @@ cudnn = torch.backends.cudnn.version(); assert cudnn, 'cuDNN not compiled into t
207
206
  ver = lambda n: M.version(n); \
208
207
  print('worker stack OK | torch', torch.__version__, '| cudnn', cudnn, '| triton', triton.__version__, '| flash_attn', 'present' if fa_ok else 'ABSENT (SDPA fallback)', '| flash_attn_3', 'present (Hopper FA3)' if fa3_ok else 'ABSENT (SDPA on Hopper)', '| flashinfer', 'present (B200 MoE/attn)' if fi_ok else 'ABSENT (Triton fused-MoE fallback)'); \
209
208
  [print(' ', d, ver(d)) for d in ['transformers','trl','peft','vllm','flashinfer-python','datasets','huggingface-hub', \
210
- 'accelerate','wandb','liger-kernel','flash-linear-attention','bitsandbytes', \
209
+ 'accelerate','wandb','flash-linear-attention','bitsandbytes', \
211
210
  'hf-transfer','freesolo','runpod']]"
212
211
 
213
212
  # RunPod Serverless worker entrypoint (Pattern D — Flash custom image). Generate /rp_handler.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 0.2.37
3
+ Version: 0.2.38
4
4
  Summary: Flash — managed LoRA post-training (SFT/GRPO) for Freesolo environments, driven by the `flash` CLI
5
5
  Project-URL: Homepage, https://github.com/freesolo-co/flash
6
6
  Project-URL: Repository, https://github.com/freesolo-co/flash
@@ -1,7 +1,7 @@
1
1
  # Thin per-arch kernel-cache layer.
2
2
  #
3
3
  # Bakes a warmup-produced mega-cache ON TOP of the EXACT base image the warmup ran inside, so the
4
- # cache's toolchain (torch/triton/fla/liger) is guaranteed to match the image it ships in. Rebuilding
4
+ # cache's toolchain (torch/triton/fla/chalk) is guaranteed to match the image it ships in. Rebuilding
5
5
  # the full Dockerfile.worker from the checkout instead could drift from the published base and bake a
6
6
  # cache that silently won't load (cold-JIT fallback) -- this avoids that by construction.
7
7
  #
@@ -100,16 +100,16 @@ def main() -> int:
100
100
  entry_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bake_pod_entry.py")
101
101
  allowed_cuda = [v.strip() for v in args.allowed_cuda.split(",") if v.strip()] or None
102
102
 
103
- # the chalk install spec the production worker uses (so the bake warms chalk's kernels too);
104
- # FLASH_CHALK_SPEC overrides, else the source-of-truth DEFAULT_CHALK_SPEC, else a safe literal.
103
+ # The chalk install spec the production worker uses, so the bake warms the same kernels. Keep the
104
+ # default import fail-loud: a stale hidden fallback would silently bake against the wrong chalk SHA.
105
105
  chalk_spec = os.environ.get("FLASH_CHALK_SPEC", "").strip()
106
106
  if not chalk_spec:
107
107
  try:
108
108
  from flash.providers.runpod.train.deps import DEFAULT_CHALK_SPEC
109
109
 
110
110
  chalk_spec = DEFAULT_CHALK_SPEC
111
- except Exception:
112
- chalk_spec = "freesolo-chalk>=0.1.0,<0.2.0"
111
+ except Exception as exc:
112
+ raise RuntimeError("could not import DEFAULT_CHALK_SPEC for kernel-cache bake") from exc
113
113
 
114
114
  _upload_flash_code(api, repo, token)
115
115
 
@@ -11,7 +11,7 @@ Two fingerprints, because "out of date" has two flavors with very different cost
11
11
  * fp_cache = hash of the inputs whose kernels live in the baked mega-cache
12
12
  (torch.compiler.save_cache_artifacts: Triton/Inductor/torch.compile). Changing one of these
13
13
  INVALIDATES the cache, so the per-arch image needs a real GPU re-warm. These are: the base
14
- FROM image (torch+triton), the fla git pin, liger, tilelang, apache-tvm-ffi, the default chalk
14
+ FROM image (torch+triton), the fla git pin, tilelang, apache-tvm-ffi, the default chalk
15
15
  spec, and the warmup script itself (it decides which kernels get compiled).
16
16
 
17
17
  * fp_base = hash of everything else baked into :cu128 that is NOT in the cache (FA2/FA3 wheels,
@@ -27,7 +27,7 @@ time, which is why every parse below FAILS LOUD rather than hashing a None.
27
27
  Known limitations (deliberately scoped -- each only ever costs a recoverable cold-JIT, never
28
28
  correctness, and the alternatives over-fire the paid GPU bake):
29
29
  * fp_cache hashes the Dockerfile dep PINS, not pip-resolved versions. A cache-affecting range
30
- (liger-kernel>=, the chalk spec) could resolve a newer build on a later worker-image rebuild with
30
+ (the chalk spec) could resolve a newer build on a later worker-image rebuild with
31
31
  no text change, leaving fp_cache unmoved. Pin those exactly for airtight coverage. (fp_base DOES
32
32
  hash the whole Dockerfile.worker, so arbitrary base edits -- apt/ENV/CMD/cache-dir -- still
33
33
  trigger a free re-layer; only a cache-affecting change that isn't a parsed pin slips through.)
@@ -43,6 +43,7 @@ stdlib only, no flash/torch import, so it runs under a bare python3 in CI (no uv
43
43
  from __future__ import annotations
44
44
 
45
45
  import argparse
46
+ import ast
46
47
  import hashlib
47
48
  import json
48
49
  import re
@@ -56,7 +57,7 @@ LABEL_REVISION = "org.opencontainers.image.revision"
56
57
 
57
58
  # pip specs in Dockerfile.worker's main stack whose kernels land in the mega-cache. everything else
58
59
  # in that block is a base-layer dep (fp_base). fla is matched separately (it carries the git sha).
59
- _CACHE_PKGS = {"liger-kernel", "tilelang", "apache-tvm-ffi"}
60
+ _CACHE_PKGS = {"tilelang", "apache-tvm-ffi"}
60
61
 
61
62
 
62
63
  def _search(pattern: str, text: str, what: str, *, flags: int = 0) -> str:
@@ -71,6 +72,44 @@ def _sha256_file(path: Path) -> str:
71
72
  return hashlib.sha256(path.read_bytes()).hexdigest()
72
73
 
73
74
 
75
+ def _python_string_constant(text: str, name: str, what: str) -> str:
76
+ """Resolve a simple module-level string constant, including f-strings using prior constants."""
77
+ values: dict[str, str] = {}
78
+
79
+ def _eval(node: ast.AST) -> str | None:
80
+ if isinstance(node, ast.Constant) and isinstance(node.value, str):
81
+ return node.value
82
+ if isinstance(node, ast.JoinedStr):
83
+ parts: list[str] = []
84
+ for value in node.values:
85
+ if isinstance(value, ast.Constant) and isinstance(value.value, str):
86
+ parts.append(value.value)
87
+ elif (
88
+ isinstance(value, ast.FormattedValue)
89
+ and isinstance(value.value, ast.Name)
90
+ and value.value.id in values
91
+ ):
92
+ parts.append(values[value.value.id])
93
+ else:
94
+ return None
95
+ return "".join(parts)
96
+ return None
97
+
98
+ tree = ast.parse(text)
99
+ for node in tree.body:
100
+ if not isinstance(node, ast.Assign):
101
+ continue
102
+ value = _eval(node.value)
103
+ if value is None:
104
+ continue
105
+ for target in node.targets:
106
+ if isinstance(target, ast.Name):
107
+ values[target.id] = value
108
+ if name not in values:
109
+ raise ValueError(f"kernel_fingerprint: could not parse {what}")
110
+ return values[name]
111
+
112
+
74
113
  def _pip_stack_specs(dockerfile: str) -> list[str]:
75
114
  """The quoted specs from Dockerfile.worker's first `pip install` block (the pinned worker stack)."""
76
115
  specs: list[str] = []
@@ -129,12 +168,11 @@ def collect_inputs(
129
168
  raise ValueError(
130
169
  "kernel_fingerprint: fla spec missing or not pinned to a 40-char commit sha"
131
170
  )
132
- chalk = _search(r'DEFAULT_CHALK_SPEC\s*=\s*"([^"]+)"', deps, "deps.py DEFAULT_CHALK_SPEC")
171
+ chalk = _python_string_constant(deps, "DEFAULT_CHALK_SPEC", "deps.py DEFAULT_CHALK_SPEC")
133
172
 
134
173
  cache_inputs = {
135
174
  "from_image": from_image,
136
175
  "fla": fla,
137
- "liger": _need("liger-kernel"),
138
176
  "tilelang": _need("tilelang"),
139
177
  "tvm_ffi": _need("apache-tvm-ffi"),
140
178
  "chalk": chalk,
@@ -115,9 +115,16 @@ class ModelInfo:
115
115
 
116
116
  DEFAULT_MODEL = "Qwen/Qwen3.5-4B"
117
117
 
118
+ # The pre-quantized FP8 checkpoint each base model's serving engine LOADS (mirrors serving's
119
+ # ``src.prequant_config``). Every dense model now serves a Freesolo-OWNED FP8_DYNAMIC checkpoint (no
120
+ # community-repo dependence); the 35B VL MoE serves the OFFICIAL Qwen FP8 (it preserves the full
121
+ # vision-language model). Informational for the catalog mirror — deploy gating reads only max_lora_rank.
118
122
  SERVING_FP8_MODEL_REPOS: dict[str, str] = {
119
- "Qwen/Qwen3.5-4B": "lovedheart/Qwen3.5-4B-FP8",
120
- "Qwen/Qwen3.5-9B": "lovedheart/Qwen3.5-9B-FP8",
123
+ "openbmb/MiniCPM5-1B": "Freesolo-Co/MiniCPM5-1B-FP8",
124
+ "Qwen/Qwen3.5-0.8B": "Freesolo-Co/Qwen3.5-0.8B-FP8",
125
+ "Qwen/Qwen3.5-2B": "Freesolo-Co/Qwen3.5-2B-FP8",
126
+ "Qwen/Qwen3.5-4B": "Freesolo-Co/Qwen3.5-4B-FP8",
127
+ "Qwen/Qwen3.5-9B": "Freesolo-Co/Qwen3.5-9B-FP8",
121
128
  "Qwen/Qwen3.6-35B-A3B": "Qwen/Qwen3.6-35B-A3B-FP8",
122
129
  }
123
130
 
@@ -133,9 +140,10 @@ MODELS: dict[str, ModelInfo] = {
133
140
  recommended_gpu="RTX 4090",
134
141
  serving=ServingCapacity(
135
142
  gpu="L4",
143
+ serve_model_id=SERVING_FP8_MODEL_REPOS["openbmb/MiniCPM5-1B"],
136
144
  max_loras=16,
137
- max_lora_rank=64,
138
- max_model_len=32768,
145
+ max_lora_rank=128,
146
+ max_model_len=8192,
139
147
  ),
140
148
  thinking="hybrid",
141
149
  notes="On-device class SLM (131k ctx); standard Llama architecture.",
@@ -151,9 +159,10 @@ MODELS: dict[str, ModelInfo] = {
151
159
  recommended_gpu="RTX 4090",
152
160
  serving=ServingCapacity(
153
161
  gpu="L4",
162
+ serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-0.8B"],
154
163
  max_loras=16,
155
- max_lora_rank=64,
156
- max_model_len=32768,
164
+ max_lora_rank=128,
165
+ max_model_len=8192,
157
166
  ),
158
167
  thinking="hybrid",
159
168
  notes="Smallest Qwen3.5; cheap smoke/dev runs with the modern arch.",
@@ -169,9 +178,10 @@ MODELS: dict[str, ModelInfo] = {
169
178
  recommended_gpu="RTX 4090",
170
179
  serving=ServingCapacity(
171
180
  gpu="L4",
181
+ serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-2B"],
172
182
  max_loras=16,
173
- max_lora_rank=64,
174
- max_model_len=32768,
183
+ max_lora_rank=128,
184
+ max_model_len=8192,
175
185
  ),
176
186
  thinking="hybrid",
177
187
  ),
@@ -187,8 +197,8 @@ MODELS: dict[str, ModelInfo] = {
187
197
  serving=ServingCapacity(
188
198
  gpu="L4",
189
199
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-4B"],
190
- max_loras=64,
191
- max_lora_rank=32,
200
+ max_loras=16,
201
+ max_lora_rank=64,
192
202
  max_model_len=8192,
193
203
  max_num_seqs=8,
194
204
  gpu_memory_utilization=0.98,
@@ -212,8 +222,8 @@ MODELS: dict[str, ModelInfo] = {
212
222
  serving=ServingCapacity(
213
223
  gpu="L4",
214
224
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-9B"],
215
- max_loras=44,
216
- max_lora_rank=32,
225
+ max_loras=16,
226
+ max_lora_rank=64,
217
227
  max_model_len=8192,
218
228
  max_num_seqs=8,
219
229
  gpu_memory_utilization=0.98,
@@ -250,8 +260,11 @@ MODELS: dict[str, ModelInfo] = {
250
260
  serving=ServingCapacity(
251
261
  gpu="A100-80GB",
252
262
  serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.6-35B-A3B"],
253
- max_loras=12,
254
- max_lora_rank=32,
263
+ # rank-64 at only 6 hot slots: the fused-MoE LoRA buffer scales with
264
+ # max_loras x rank x num_experts, so the A100-80GB ceiling is ~max_loras x rank = 384
265
+ # (6 x 64 fits at 99.3% util; 16 x 64 OOMs on every single/multi GPU). Serving-validated.
266
+ max_loras=6,
267
+ max_lora_rank=64,
255
268
  max_model_len=8192,
256
269
  max_num_seqs=8,
257
270
  max_num_batched_tokens=4096,
@@ -253,8 +253,7 @@ def _build_parser() -> argparse.ArgumentParser:
253
253
  )
254
254
  env_pull.add_argument(
255
255
  "env_id",
256
- help='the Freesolo environment id: a managed slug "your-name/your-env", a '
257
- '"github:owner/repo@ref:path" ref, or a github.com URL',
256
+ help='the managed Freesolo environment slug "your-name/your-env"',
258
257
  )
259
258
  env_pull.add_argument(
260
259
  "path",
@@ -65,38 +65,32 @@ def _normalize_managed_hub_id(raw: object) -> tuple[str | None, _ManagedHubIdErr
65
65
  def cmd_env_pull(args) -> int:
66
66
  """Download a published Freesolo environment (or a single file from it) to local disk.
67
67
 
68
- Managed hub slugs pull package tarballs through the authenticated Flash control plane. Explicit
69
- GitHub refs still pull via GitHub's tarball / raw media type, so files larger than 1 MB
70
- (e.g. ``datasets/train.jsonl``) come back intact instead of empty.
68
+ Environments are addressed by their managed hub slug ``namespace/name`` and pulled as package
69
+ tarballs through the authenticated Flash control plane.
71
70
  """
72
71
  from flash.client import ClientError, client_from_config
73
- from flash.envs.adapter import is_freesolo_environment_id
74
72
  from flash.envs.pull import (
75
- download_environment_file,
76
73
  download_environment_file_from_archive,
77
74
  ensure_environment_pull_destination_available,
78
75
  environment_local_dirname,
79
- pull_environment_package,
80
76
  pull_environment_package_from_archive,
81
77
  )
82
78
 
83
79
  env_id = str(args.env_id or "").strip()
84
- if not is_freesolo_environment_id(env_id):
80
+ managed_env_id, managed_error = _normalize_managed_hub_id(env_id)
81
+ if managed_error == "not-canonical":
82
+ return _err(
83
+ f'env id must be lowercase "namespace/name" with no spaces (got {args.env_id!r})'
84
+ )
85
+ if managed_env_id is None:
85
86
  print(
86
- 'env id must be a Freesolo environment id — a managed slug "your-name/your-env", '
87
- f'a "github:owner/repo@ref:path" ref, or a github.com URL (got {args.env_id!r})',
87
+ 'env id must be a managed Freesolo hub slug "your-name/your-env" '
88
+ f"(got {args.env_id!r})",
88
89
  file=sys.stderr,
89
90
  )
90
91
  return 1
92
+ env_id = managed_env_id
91
93
  try:
92
- managed_env_id, managed_error = _normalize_managed_hub_id(env_id)
93
- if managed_error == "not-canonical":
94
- return _err(
95
- f'env id must be lowercase "namespace/name" with no spaces (got {args.env_id!r})'
96
- )
97
- managed = managed_env_id is not None
98
- if managed:
99
- env_id = managed_env_id
100
94
  if args.path:
101
95
  default_name = Path(args.path.replace("\\", "/")).name
102
96
  out = Path(args.output) if args.output else Path(default_name)
@@ -110,11 +104,8 @@ def cmd_env_pull(args) -> int:
110
104
  if (out.exists() or out.is_symlink()) and not args.force:
111
105
  print(f"refusing to overwrite {out} (pass --force)", file=sys.stderr)
112
106
  return 1
113
- if managed:
114
- package = client_from_config().download_env_package(env_id)
115
- data = download_environment_file_from_archive(package, args.path)
116
- else:
117
- data = download_environment_file(env_id, args.path)
107
+ package = client_from_config().download_env_package(env_id)
108
+ data = download_environment_file_from_archive(package, args.path)
118
109
  out.parent.mkdir(parents=True, exist_ok=True)
119
110
  _atomic_write_bytes(out, data)
120
111
  if render.styled():
@@ -123,12 +114,9 @@ def cmd_env_pull(args) -> int:
123
114
  print(f"pulled {args.path} from {env_id} -> {out} ({len(data):,} bytes)")
124
115
  else:
125
116
  out = Path(args.output) if args.output else Path(environment_local_dirname(env_id))
126
- if managed:
127
- ensure_environment_pull_destination_available(out, overwrite=args.force)
128
- package = client_from_config().download_env_package(env_id)
129
- pull_environment_package_from_archive(package, out, overwrite=args.force)
130
- else:
131
- pull_environment_package(env_id, out, overwrite=args.force)
117
+ ensure_environment_pull_destination_available(out, overwrite=args.force)
118
+ package = client_from_config().download_env_package(env_id)
119
+ pull_environment_package_from_archive(package, out, overwrite=args.force)
132
120
  if render.styled():
133
121
  print(render.env_pulled(f"{out}/", env_id))
134
122
  else:
@@ -146,12 +134,6 @@ def cmd_env_pull(args) -> int:
146
134
  return 1
147
135
  except (ValueError, FileNotFoundError, RuntimeError, OSError) as exc:
148
136
  print(f"env pull failed: {exc}", file=sys.stderr)
149
- if "GitHub environment request failed" in str(exc) and not os.environ.get("GITHUB_TOKEN"):
150
- print(
151
- "hint: private/internal environments need a GitHub token; set GITHUB_TOKEN "
152
- "(e.g. `export GITHUB_TOKEN=$(gh auth token)`).",
153
- file=sys.stderr,
154
- )
155
137
  return 1
156
138
 
157
139
 
@@ -1,7 +1,8 @@
1
1
  """Optional chalk GPU kernels (the ``freesolo-chalk`` package).
2
2
 
3
- Gap-filling Triton kernels for qwen3.5 applied on top of Liger (liger=False; TRL owns Liger).
4
- Degrades to a no-op if freesolo-chalk is not installed.
3
+ Standalone Triton kernels for qwen3.5/3.6. Flash does not ask TRL to apply Liger; chalk owns the
4
+ RMSNorm, SwiGLU, fused-linear-CE, RoPE, LoRA-delta, trainable attention epilogue, embedding, and GDN
5
+ patches. Degrades to a no-op if freesolo-chalk is not installed.
5
6
  """
6
7
 
7
8
  from __future__ import annotations
@@ -14,11 +15,16 @@ log = get_logger(__name__)
14
15
 
15
16
  _KERNELS: list[tuple[str, bool]] = [
16
17
  ("rope", True),
18
+ ("rmsnorm", True),
19
+ ("swiglu", True),
20
+ ("fused_linear_cross_entropy", True),
17
21
  ("fused_lora_delta", True),
22
+ ("trainable_attn_epilogue", True),
18
23
  ("fused_embedding", True),
19
- ("fused_mlp", False), # off (Liger owns MLP/SwiGLU)
24
+ ("gdn", True),
25
+ ("fused_mlp", False), # off: eval-only bf16 MLP forward, not the training activation path
20
26
  ("attn_epilogue", False), # off (eval-only; needs q/k/v out of LoRA)
21
- ("fp8_frozen_base", False), # off (Hopper sm_90+ only)
27
+ ("fp8_frozen_base", False), # off by default: speed/memory tradeoff, enable only after run A/B
22
28
  ]
23
29
 
24
30
 
@@ -31,8 +37,25 @@ def active_kernels(report: Mapping[str, object] | None) -> list[str]:
31
37
  )
32
38
 
33
39
 
40
+ def chalk_supports_fused_ce_model(model_id: str | None) -> bool:
41
+ """True when chalk's standalone fused-CE patch supports this model family."""
42
+ mid = (model_id or "").lower()
43
+ return any(token in mid for token in ("qwen3.5", "qwen3_5", "qwen3.6", "qwen3_6"))
44
+
45
+
46
+ def chalk_fused_ce_available(model_id: str | None = None) -> bool:
47
+ """Best-effort preflight for SFT fused-CE sizing before the trainer exists."""
48
+ if model_id is not None and not chalk_supports_fused_ce_model(model_id):
49
+ return False
50
+ try:
51
+ from chalk.transformers import apply_chalk_kernel_to_qwen35 as _apply
52
+ except Exception:
53
+ return False
54
+ return callable(_apply)
55
+
56
+
34
57
  def install_chalk_kernels(model=None) -> dict:
35
- """Apply chalk's gap-filling kernels to ``model``; call AFTER TRL builds the trainer.
58
+ """Apply chalk standalone kernels to ``model``; call AFTER TRL builds the trainer.
36
59
 
37
60
  Returns chalk's per-kernel report, or ``{}`` when freesolo-chalk isn't installed.
38
61
  """
@@ -45,7 +68,7 @@ def install_chalk_kernels(model=None) -> dict:
45
68
  except ImportError:
46
69
  log.info(
47
70
  "freesolo-chalk is not installed on this worker (set FLASH_CHALK_SPEC to an installable "
48
- "spec, or check the default PyPI install); chalk kernels off, using eager/Liger."
71
+ "spec, or check the default install); chalk kernels off, using eager kernels."
49
72
  )
50
73
  return {}
51
74
  except Exception as e:
@@ -53,7 +76,7 @@ def install_chalk_kernels(model=None) -> dict:
53
76
  return {}
54
77
 
55
78
  try:
56
- # liger=False: TRL already applied Liger; chalk composes on top of the live Liger modules.
79
+ # liger=False: flash uses chalk standalone. TRL must not have applied Liger first.
57
80
  report = apply_chalk_kernel_to_qwen35(model, liger=False, **kwargs)
58
81
  except Exception as e: # never block training on the optional kernel stack
59
82
  log.warning("chalk apply failed (ignored, kernels disabled): %s", e)
@@ -162,7 +162,8 @@ _VOCAB_DEFAULT = 248_320
162
162
  _LOGITS_BUDGET_GB = 6.0
163
163
  # 16 B/elem: fp32 logits+grad + bf16 logits+grad + CE temp. 8 B/elem under-counts (live OOM confirmed).
164
164
  _SFT_LOGITS_BYTES_PER_ELEM = 16.0
165
- # Single source of truth for Liger gate engine.worker.perf imports these.
165
+ # Single source of truth for the SFT fused-CE gate. Keep the historical constant names because
166
+ # engine.worker.perf and tests import them.
166
167
  _LIGER_MIN_PARAMS_B = 3.0
167
168
  _LIGER_LONG_CTX_TOKENS = 2048
168
169
 
@@ -264,6 +265,7 @@ def estimate_vram_gb(
264
265
  sleep_offload: bool = True,
265
266
  active_params_b: float | None = None,
266
267
  fp8_kv: bool = False,
268
+ sft_fused_ce: bool | None = None,
267
269
  ) -> float:
268
270
  """Estimated peak VRAM (GB) for a LoRA job on one GPU.
269
271
 
@@ -292,7 +294,7 @@ def estimate_vram_gb(
292
294
  logits = min(completion * vocab * 4 / 1e9, _LOGITS_BUDGET_GB)
293
295
  train = activations + logits
294
296
  return base + (max(rollout, train) if sleep_offload else rollout + train)
295
- fused = sft_logits_fused(params_b, seq_len)
297
+ fused = sft_logits_fused(params_b, seq_len) if sft_fused_ce is None else bool(sft_fused_ce)
296
298
  pd = sft_per_device(batch_size, seq_len=seq_len, vocab=vocab, fused=fused)
297
299
  activations = _ACT_COEF * pd * (seq_len / 1024.0) * width
298
300
  # Don't clamp to budget: pd=1 is irreducible and the logits can exceed the budget at near-2048 ctx.
@@ -372,7 +374,7 @@ def sft_gc_off_peak_gb(
372
374
  ) -> float:
373
375
  """Estimated peak VRAM (GB) for a FUSED-CE LoRA SFT step with gradient checkpointing OFF: the
374
376
  resident weights + optimizer/base + the no-recompute activations held across ALL ``num_layers``.
375
- Fused CE (Liger FLCE) is assumed, so there is no ``[B, T, vocab]`` logits term (the thing that
377
+ Fused CE (chalk FLCE) is assumed, so there is no ``[B, T, vocab]`` logits term (the thing that
376
378
  made GC-off impossible at a 248k vocab). Unknown architecture dims -> ``inf`` (caller keeps GC on).
377
379
 
378
380
  MoE: the activation backbone scales with the model's real ``hidden`` x ``num_layers`` (geometry),
@@ -482,14 +484,22 @@ def model_required_vram_gb(
482
484
  use_vllm=use_vllm,
483
485
  vocab=vocab,
484
486
  active_params_b=active_params_b,
487
+ sft_fused_ce=sft_fused_ce,
485
488
  )
486
489
  return math.ceil(est * headroom)
487
490
 
488
491
  from flash.catalog import MODELS, vocab_size_for
492
+ from flash.engine.chalk_kernels import chalk_supports_fused_ce_model
489
493
 
490
494
  info = MODELS.get(model_id)
491
495
  model_vocab = vocab_size_for(model_id)
492
496
  is_grpo = (algorithm or "").lower() in ("grpo", "rl")
497
+ sft_fused_ce = (
498
+ None
499
+ if is_grpo
500
+ else sft_logits_fused(resolve_params_b(model_id), seq_len)
501
+ and chalk_supports_fused_ce_model(model_id)
502
+ )
493
503
  if info is not None:
494
504
  params_b = info.params_b # curated, authoritative (required field) — no string parsing
495
505
  quant = getattr(info, "quant", "bf16") or "bf16"