freesolo-flash-dev 1.2.37__tar.gz → 1.2.39__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/core/catalog.py +7 -3
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/backend_common.py +51 -65
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/failures.py +4 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/checkpoints.py +7 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/checkpoints.py +18 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/checkpoints.py +137 -57
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/preparation.py +1 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_backend_common.py +2 -2
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_disk_gb.py +90 -16
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_train.py +100 -226
- freesolo_flash_dev-1.2.39/tests/test_verl_checkpoint_export.py +495 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_cross_repo.py +1 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.env.example +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/README.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/shims.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/tests/test_zero2_sharding_gate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.39
|
|
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
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from dataclasses import asdict, dataclass, replace
|
|
6
|
+
from math import ceil
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
8
9
|
ALGORITHMS = ("sft", "grpo", "opd")
|
|
@@ -622,6 +623,10 @@ def resolve_vocab_size(model_id: str, revision: str = "") -> int:
|
|
|
622
623
|
return vocab_size_for(model_id)
|
|
623
624
|
|
|
624
625
|
|
|
626
|
+
def _with_merge_disk_floor(info: ModelInfo) -> ModelInfo:
|
|
627
|
+
return replace(info, min_disk_gb=max(info.min_disk_gb, ceil(info.params_b * 2) + 64))
|
|
628
|
+
|
|
629
|
+
|
|
625
630
|
def resolve_model(model_id: str, algorithm: str, model_revision: str = "") -> ModelInfo:
|
|
626
631
|
"""Resolve a curated model, validated for ``algorithm``; anything uncataloged is rejected.
|
|
627
632
|
|
|
@@ -643,9 +648,8 @@ def resolve_model(model_id: str, algorithm: str, model_revision: str = "") -> Mo
|
|
|
643
648
|
params_b=params_b,
|
|
644
649
|
params=f"{params_b:.1f}B",
|
|
645
650
|
vocab_size=vocab_size,
|
|
646
|
-
min_disk_gb=max(info.min_disk_gb, int(params_b * 2) + 64),
|
|
647
651
|
)
|
|
648
|
-
return info
|
|
652
|
+
return _with_merge_disk_floor(info)
|
|
649
653
|
|
|
650
654
|
|
|
651
655
|
def validate_model_for_algorithm(model_id: str, algorithm: str) -> ModelInfo:
|
|
@@ -660,4 +664,4 @@ def validate_model_for_algorithm(model_id: str, algorithm: str) -> ModelInfo:
|
|
|
660
664
|
|
|
661
665
|
|
|
662
666
|
def public_model_rows() -> list[dict[str, Any]]:
|
|
663
|
-
return [
|
|
667
|
+
return [_with_merge_disk_floor(model).to_dict() for model in list_models()]
|
{freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/backend_common.py
RENAMED
|
@@ -471,29 +471,14 @@ def ray_num_cpus(gpu_count: int = 1, *, cap: int = 16) -> int:
|
|
|
471
471
|
return max(floor, min(affinity, cap))
|
|
472
472
|
|
|
473
473
|
|
|
474
|
-
def
|
|
474
|
+
def _run_streaming_verl_subprocess(
|
|
475
475
|
cmd: list[str],
|
|
476
476
|
*,
|
|
477
477
|
env: dict[str, str],
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
heartbeat: Callable[[], None] | None = None,
|
|
481
|
-
step_pattern: str = r"step:\s*(\d+)",
|
|
482
|
-
heartbeat_interval_s: float = 20.0,
|
|
483
|
-
tail: ChildOutputTail | None = None,
|
|
478
|
+
on_line: Callable[[str], None],
|
|
479
|
+
errors: str | None = None,
|
|
484
480
|
) -> int:
|
|
485
|
-
"""
|
|
486
|
-
|
|
487
|
-
returns the process exit code. stdout+stderr are merged and scanned line by line: ``on_line``
|
|
488
|
-
receives every line, ``on_step`` receives each parsed training step, and ``heartbeat`` is called
|
|
489
|
-
at most once per ``heartbeat_interval_s``. callback failures terminate the child before they are
|
|
490
|
-
re-raised so a failed required checkpoint upload cannot leave paid training running unattended.
|
|
491
|
-
"""
|
|
492
|
-
step_re = re.compile(step_pattern)
|
|
493
|
-
child_tail = tail if tail is not None else ChildOutputTail()
|
|
494
|
-
# before the child exists, so any grandchild it orphans reparents here and can actually be
|
|
495
|
-
# reaped. this process is not pid 1 -- the runpod handler is -- so without it every wait below
|
|
496
|
-
# answers ChildProcessError for a zombie nobody will collect.
|
|
481
|
+
"""stream a verl subprocess under the shared process-group lifecycle supervisor."""
|
|
497
482
|
adopt_orphaned_descendants()
|
|
498
483
|
proc = subprocess.Popen(
|
|
499
484
|
cmd,
|
|
@@ -501,87 +486,88 @@ def run_verl_training(
|
|
|
501
486
|
stdout=subprocess.PIPE,
|
|
502
487
|
stderr=subprocess.STDOUT,
|
|
503
488
|
text=True,
|
|
489
|
+
errors=errors,
|
|
504
490
|
bufsize=1,
|
|
505
491
|
start_new_session=True,
|
|
506
492
|
)
|
|
507
|
-
# start_new_session
|
|
493
|
+
# start_new_session keeps the group addressable after the leader is reaped.
|
|
508
494
|
process_group_id = proc.pid
|
|
509
|
-
last_hb = 0.0
|
|
510
495
|
try:
|
|
511
|
-
# the child's exit is watched independently of pipe EOF. a grandchild holding the inherited
|
|
512
|
-
# pipe open after the trainer dies would otherwise keep the loop below running forever, on a
|
|
513
|
-
# paid gpu, having already lost the process whose output it is waiting for.
|
|
514
496
|
with _ChildExitWatchdog(
|
|
515
497
|
proc, process_group_id=process_group_id, grace_s=_ORPHANED_PIPE_GRACE_S
|
|
516
498
|
) as watchdog:
|
|
517
499
|
assert proc.stdout is not None
|
|
518
500
|
for line in proc.stdout:
|
|
519
|
-
# held across the callbacks, not just the arrival: on_step uploads a checkpoint, and
|
|
520
|
-
# a reader inside one is working, not stuck.
|
|
521
501
|
with watchdog.handling_line():
|
|
522
|
-
|
|
523
|
-
child_tail.record(line)
|
|
524
|
-
if on_line is not None:
|
|
525
|
-
on_line(line)
|
|
526
|
-
m = step_re.search(line)
|
|
527
|
-
if m and on_step is not None:
|
|
528
|
-
on_step(int(m.group(1)))
|
|
529
|
-
if heartbeat is not None:
|
|
530
|
-
now = time.monotonic()
|
|
531
|
-
if now - last_hb >= heartbeat_interval_s:
|
|
532
|
-
heartbeat()
|
|
533
|
-
last_hb = now
|
|
502
|
+
on_line(line)
|
|
534
503
|
except BaseException:
|
|
535
504
|
kill_process_group(proc, process_group_id=process_group_id)
|
|
536
505
|
raise
|
|
537
506
|
finally:
|
|
538
507
|
if proc.poll() is None:
|
|
539
|
-
# BOUNDED. EOF is not the child's exit, so a child that outlives its own stdout would
|
|
540
|
-
# park the attempt here. one that has not exited within the grace after its stdout closed
|
|
541
|
-
# is not going to, so tear the group down and let the wait inside that call collect it.
|
|
542
508
|
try:
|
|
543
509
|
proc.wait(timeout=_TEARDOWN_GRACE_S)
|
|
544
510
|
except subprocess.TimeoutExpired:
|
|
545
511
|
kill_process_group(proc, process_group_id=process_group_id)
|
|
546
|
-
# every job boundary, not just the failing ones. a straggler an earlier teardown SIGKILLed
|
|
547
|
-
# but could not drain in time exits shortly after, and `kill_process_group` -- the only
|
|
548
|
-
# other caller of this -- runs on exceptions alone: a worker whose later jobs all succeed
|
|
549
|
-
# would hold that zombie for its whole life, as pid 1 with nothing else to reap it.
|
|
550
512
|
reap_stragglers()
|
|
551
|
-
|
|
552
|
-
if collected is None:
|
|
553
|
-
# the bounded wait above can end with nothing collected, which the unbounded one it replaced
|
|
554
|
-
# could not: a group member wedged in uninterruptible io outlives even the SIGKILL inside
|
|
555
|
-
# teardown. `int(None)` would replace that diagnosis with a TypeError, so name the survivor
|
|
556
|
-
# instead -- callers already handle a RuntimeError from here.
|
|
513
|
+
if proc.returncode is None:
|
|
557
514
|
raise RuntimeError(
|
|
558
515
|
f"verl subprocess {proc.pid} did not exit after teardown; its process group is still "
|
|
559
516
|
"holding the gpu"
|
|
560
517
|
)
|
|
561
|
-
return_code = int(
|
|
518
|
+
return_code = int(proc.returncode)
|
|
562
519
|
if watchdog.tore_down and return_code == 0:
|
|
563
|
-
# the child exited 0 but a descendant held the pipe open past the grace, so the group was
|
|
564
|
-
# killed to release it. reporting success here would upload whatever partial artifacts exist
|
|
565
|
-
# as a completed run: the trainer's own exit status says nothing about the descendant that
|
|
566
|
-
# was still running, and that descendant is why the pipe never closed.
|
|
567
520
|
raise RuntimeError(
|
|
568
521
|
f"verl subprocess {proc.pid} exited 0 but a descendant held its output pipe open for "
|
|
569
522
|
f"{_ORPHANED_PIPE_GRACE_S:.0f}s; the process group was torn down to release the gpu"
|
|
570
523
|
)
|
|
571
|
-
try:
|
|
572
|
-
raise_for_classified_verl_exit(return_code, child_tail)
|
|
573
|
-
except BaseException:
|
|
574
|
-
kill_process_group(proc, process_group_id=process_group_id)
|
|
575
|
-
raise
|
|
576
524
|
if return_code != 0:
|
|
577
|
-
# a nonzero exit that carried no recognized signature RETURNS from the classifier rather
|
|
578
|
-
# than raising, so this is the one failing path that reached neither teardown above. the
|
|
579
|
-
# direct child is gone but its group need not be: a surviving EngineCore keeps its cuda
|
|
580
|
-
# context, and a reusable worker then hands the next attempt an occupied gpu.
|
|
581
525
|
kill_process_group(proc, process_group_id=process_group_id)
|
|
582
526
|
return return_code
|
|
583
527
|
|
|
584
528
|
|
|
529
|
+
def run_verl_training(
|
|
530
|
+
cmd: list[str],
|
|
531
|
+
*,
|
|
532
|
+
env: dict[str, str],
|
|
533
|
+
on_step: Callable[[int], None] | None = None,
|
|
534
|
+
on_line: Callable[[str], None] | None = None,
|
|
535
|
+
heartbeat: Callable[[], None] | None = None,
|
|
536
|
+
step_pattern: str = r"step:\s*(\d+)",
|
|
537
|
+
heartbeat_interval_s: float = 20.0,
|
|
538
|
+
tail: ChildOutputTail | None = None,
|
|
539
|
+
) -> int:
|
|
540
|
+
"""run a verl trainer subprocess, streaming stdout and surfacing step progress.
|
|
541
|
+
|
|
542
|
+
returns the process exit code. stdout+stderr are merged and scanned line by line: ``on_line``
|
|
543
|
+
receives every line, ``on_step`` receives each parsed training step, and ``heartbeat`` is called
|
|
544
|
+
at most once per ``heartbeat_interval_s``. callback failures terminate the process group before
|
|
545
|
+
they are re-raised.
|
|
546
|
+
"""
|
|
547
|
+
step_re = re.compile(step_pattern)
|
|
548
|
+
child_tail = tail if tail is not None else ChildOutputTail()
|
|
549
|
+
last_hb = 0.0
|
|
550
|
+
|
|
551
|
+
def handle_line(line: str) -> None:
|
|
552
|
+
nonlocal last_hb
|
|
553
|
+
print(line, end="", flush=True)
|
|
554
|
+
child_tail.record(line)
|
|
555
|
+
if on_line is not None:
|
|
556
|
+
on_line(line)
|
|
557
|
+
match = step_re.search(line)
|
|
558
|
+
if match and on_step is not None:
|
|
559
|
+
on_step(int(match.group(1)))
|
|
560
|
+
if heartbeat is not None:
|
|
561
|
+
now = time.monotonic()
|
|
562
|
+
if now - last_hb >= heartbeat_interval_s:
|
|
563
|
+
heartbeat()
|
|
564
|
+
last_hb = now
|
|
565
|
+
|
|
566
|
+
return_code = _run_streaming_verl_subprocess(cmd, env=env, on_line=handle_line)
|
|
567
|
+
raise_for_classified_verl_exit(return_code, child_tail)
|
|
568
|
+
return return_code
|
|
569
|
+
|
|
570
|
+
|
|
585
571
|
_TEARDOWN_GRACE_S = 10.0
|
|
586
572
|
|
|
587
573
|
# grace for a descendant holding stdout open after the trainer exits. observe child exit separately
|
{freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/failures.py
RENAMED
|
@@ -291,6 +291,10 @@ class _OpdVerlCheckpointWatcher(_VerlCheckpointWatcher):
|
|
|
291
291
|
def _should_publish(self, step: int) -> bool:
|
|
292
292
|
return True
|
|
293
293
|
|
|
294
|
+
def _publishable(self, pending: list[tuple[int, str]]) -> list[tuple[int, str]]:
|
|
295
|
+
"""keep every pending retry state because each checkpoint carries distinct accounting."""
|
|
296
|
+
return pending
|
|
297
|
+
|
|
294
298
|
def _publish(self, step: int, checkpoint_dir: str) -> None:
|
|
295
299
|
actor_dir = os.path.join(checkpoint_dir, "actor")
|
|
296
300
|
adapter_dir = os.path.join(self.export_root, f"step-{step}")
|
{freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/checkpoints.py
RENAMED
|
@@ -23,7 +23,11 @@ from flash.engine.worker.backend_common import (
|
|
|
23
23
|
)
|
|
24
24
|
from flash.engine.worker.io.heartbeat import join_while_draining
|
|
25
25
|
from flash.engine.worker.runtime.pkg_proxy import W as _w
|
|
26
|
-
from flash.engine.worker.verl.checkpoints import
|
|
26
|
+
from flash.engine.worker.verl.checkpoints import (
|
|
27
|
+
MergeDiskExhaustedError,
|
|
28
|
+
MergeDiskHeadroomError,
|
|
29
|
+
resume_checkpoint_is_loadable,
|
|
30
|
+
)
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
def _rl_train():
|
|
@@ -121,6 +125,8 @@ class _VerlResumeUploader:
|
|
|
121
125
|
called only after training finished cleanly: on a crash or cancel the missing steps are a
|
|
122
126
|
symptom of the real failure, and raising here would mask it.
|
|
123
127
|
"""
|
|
128
|
+
if isinstance(self._error, (MergeDiskHeadroomError, MergeDiskExhaustedError)):
|
|
129
|
+
raise self._error
|
|
124
130
|
if self._error is not None:
|
|
125
131
|
raise RuntimeError("verl resume uploader failed") from self._error
|
|
126
132
|
missing = sorted(self.required_steps - self.published_steps)
|
{freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/checkpoints.py
RENAMED
|
@@ -23,6 +23,7 @@ from flash.engine.worker.backend_common import (
|
|
|
23
23
|
)
|
|
24
24
|
from flash.engine.worker.io.heartbeat import join_while_draining
|
|
25
25
|
from flash.engine.worker.runtime.pkg_proxy import W as _w
|
|
26
|
+
from flash.engine.worker.verl.checkpoints import MergeDiskExhaustedError, MergeDiskHeadroomError
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def _sft_train():
|
|
@@ -113,6 +114,8 @@ class _VerlCheckpointWatcher:
|
|
|
113
114
|
self._thread.start()
|
|
114
115
|
|
|
115
116
|
def raise_if_failed(self) -> None:
|
|
117
|
+
if isinstance(self._error, (MergeDiskHeadroomError, MergeDiskExhaustedError)):
|
|
118
|
+
raise self._error
|
|
116
119
|
if self._error is not None:
|
|
117
120
|
raise RuntimeError("verl checkpoint watcher failed") from self._error
|
|
118
121
|
|
|
@@ -141,6 +144,20 @@ class _VerlCheckpointWatcher:
|
|
|
141
144
|
def _should_publish(self, step: int) -> bool:
|
|
142
145
|
return not self.required_steps or step in self.required_steps
|
|
143
146
|
|
|
147
|
+
def _publishable(self, pending: list[tuple[int, str]]) -> list[tuple[int, str]]:
|
|
148
|
+
"""coalesce only an optional multi-checkpoint backlog to its newest save."""
|
|
149
|
+
if self.required_steps or len(pending) <= 1:
|
|
150
|
+
return pending
|
|
151
|
+
superseded = pending[:-1]
|
|
152
|
+
self.processed_steps.update(step for step, _ in superseded)
|
|
153
|
+
print(
|
|
154
|
+
f"[ckpt] publishing step {pending[-1][0]} and skipping superseded periodic "
|
|
155
|
+
f"checkpoint(s) {', '.join(str(step) for step, _ in superseded)}: the publisher is "
|
|
156
|
+
"behind training, and each export writes a full model copy to the same disk",
|
|
157
|
+
flush=True,
|
|
158
|
+
)
|
|
159
|
+
return pending[-1:]
|
|
160
|
+
|
|
144
161
|
def _staged_source(self, step: int, checkpoint_dir: str) -> str:
|
|
145
162
|
"""hardlink a completed checkpoint before verl retention can prune it.
|
|
146
163
|
|
|
@@ -220,7 +237,7 @@ class _VerlCheckpointWatcher:
|
|
|
220
237
|
def _run(self) -> None:
|
|
221
238
|
try:
|
|
222
239
|
while True:
|
|
223
|
-
for step, checkpoint_dir in self._pending():
|
|
240
|
+
for step, checkpoint_dir in self._publishable(self._pending()):
|
|
224
241
|
self._publish(step, checkpoint_dir)
|
|
225
242
|
# re-read rather than reusing the sweep above: verl advances the tracker right up to
|
|
226
243
|
# the moment the child exits, so a step can become visible during that sweep.
|
{freesolo_flash_dev-1.2.37 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/checkpoints.py
RENAMED
|
@@ -9,6 +9,7 @@ Split out of `flash.engine.worker.backend_common` to keep that module under the
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import errno
|
|
12
13
|
import json
|
|
13
14
|
import os
|
|
14
15
|
import re
|
|
@@ -20,24 +21,37 @@ class MergeDiskHeadroomError(RuntimeError):
|
|
|
20
21
|
"""the merged model this export must write does not fit beside the checkpoint it reads."""
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
class MergeDiskExhaustedError(RuntimeError):
|
|
25
|
+
"""the merge started with room and then ran the disk out partway through writing its output."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# a genuine short write leaves almost no free space; keep the fallback absolute so a normal partial
|
|
29
|
+
# merge is not misclassified merely because its output is large.
|
|
30
|
+
_MERGE_DISK_EXHAUSTED_FREE_BYTES = 64 * 1024 * 1024
|
|
31
|
+
|
|
32
|
+
# quota exhaustion can leave the underlying filesystem reporting free space, so preserve both errno
|
|
33
|
+
# and text forms emitted by torch and safetensors.
|
|
34
|
+
_DISK_EXHAUSTED_ERRNOS = (errno.ENOSPC, errno.EDQUOT)
|
|
35
|
+
_DISK_EXHAUSTED_MARKERS = (
|
|
36
|
+
"no space left on device",
|
|
37
|
+
"errno 28",
|
|
38
|
+
"os error 28",
|
|
39
|
+
"disk quota exceeded",
|
|
40
|
+
"errno 122",
|
|
41
|
+
"os error 122",
|
|
42
|
+
)
|
|
43
|
+
_SHORT_WRITE_MARKERS = ("unexpected pos",)
|
|
44
|
+
|
|
45
|
+
# disk size is platform-managed, so checkpoint frequency is the reachable remedy.
|
|
46
|
+
_FEWER_CHECKPOINTS_ADVICE = (
|
|
47
|
+
"publish fewer checkpoints: raise train.save_every (save_every == the run's total steps "
|
|
48
|
+
"publishes only the final adapter), or drop entries from train.save_at_steps if the run sets "
|
|
49
|
+
"them -- exact steps override save_every and are always published."
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
23
53
|
def _model_shard_bytes(path: str) -> int:
|
|
24
|
-
"""total size of the fsdp model shards
|
|
25
|
-
|
|
26
|
-
only `model_world_size_*_rank_*.pt` is measured, because only those files become merge output:
|
|
27
|
-
`_load_and_merge_state_dicts` loads exactly those names, and the merged dict is what
|
|
28
|
-
`save_pretrained` writes back out. the `optim_*` and `extra_state_*` files sitting beside them
|
|
29
|
-
are read by resume, never by the merger, so including them would inflate the requirement by the
|
|
30
|
-
whole optimizer state -- ~7.6 GB of adam moments on a 35b rank-32 run -- and refuse merges that
|
|
31
|
-
would have fit.
|
|
32
|
-
|
|
33
|
-
a flat scan, not a walk, because the merger's read is flat: it opens
|
|
34
|
-
`Path(local_dir) / f"model_world_size_{W}_rank_{r}.pt"` per rank and never recurses. walking
|
|
35
|
-
would add up nested files it will never read, which is the same over-estimate in a new form.
|
|
36
|
-
|
|
37
|
-
shares `_FSDP_SHARD_RE` with `checkpoint_world_size` rather than matching the name a second way:
|
|
38
|
-
one definition of what a shard filename is, so a future change to verl's layout cannot leave the
|
|
39
|
-
two disagreeing about which files a merge reads.
|
|
40
|
-
"""
|
|
54
|
+
"""total size of the top-level fsdp model shards the merger reads."""
|
|
41
55
|
try:
|
|
42
56
|
names = os.listdir(path)
|
|
43
57
|
except OSError:
|
|
@@ -54,37 +68,12 @@ def _model_shard_bytes(path: str) -> int:
|
|
|
54
68
|
|
|
55
69
|
|
|
56
70
|
def require_merge_headroom(ckpt_actor_dir: str, merge_out: str) -> None:
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
`model_merger merge` does NOT write only the small lora adapter. `save_hf_model_and_tokenizer`
|
|
60
|
-
materializes the full base model and calls `model.save_pretrained(target_dir, state_dict=...)`
|
|
61
|
-
(verl `model_merger/base_model_merger.py`), so exporting one 35b checkpoint writes ~70 GB into
|
|
62
|
-
`<adapter>_merge` beside the ~60 GB checkpoint it is reading. That is the single largest
|
|
63
|
-
transient on the disk, and it recurs on EVERY publish, not just at finalization.
|
|
64
|
-
|
|
65
|
-
Without this guard the merger dies partway through `save_pretrained` with ENOSPC, and the run
|
|
66
|
-
fails after training has already succeeded. Checking first turns a silent late disk death into
|
|
67
|
-
an actionable error naming the shortfall, while the checkpoint is still intact and resumable.
|
|
68
|
-
|
|
69
|
-
The requirement is derived from what the merger actually moves rather than from the checkpoint's
|
|
70
|
-
total size: it loads the `model_world_size_*_rank_*.pt` shards, casts every tensor to bf16, and
|
|
71
|
-
writes that same state back out as base model plus adapter (`fsdp_model_merger.py`,
|
|
72
|
-
`base_model_merger.py`). Shard bytes in, shard bytes out. Sizing the whole directory instead
|
|
73
|
-
would add the `optim_*` and `extra_state_*` files, which resume reads and the merger never
|
|
74
|
-
materializes -- on a 35b rank-32 run that is ~7.6 GB of adam moments, enough to refuse a merge
|
|
75
|
-
that had room.
|
|
76
|
-
|
|
77
|
-
The two error directions are not symmetric, which is why no safety margin is added on top.
|
|
78
|
-
Underestimating leaves the merger to hit ENOSPC exactly as it does today, so the guard is merely
|
|
79
|
-
absent. Overestimating fails a run that would have completed, which is a regression this guard
|
|
80
|
-
would have introduced. When in doubt, let the merge proceed.
|
|
81
|
-
"""
|
|
71
|
+
"""fail before the merger when its full-bf16 output cannot fit beside its input shards."""
|
|
82
72
|
need = _model_shard_bytes(ckpt_actor_dir)
|
|
83
73
|
if need <= 0:
|
|
84
74
|
return
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
except OSError:
|
|
75
|
+
free = _free_bytes(merge_out)
|
|
76
|
+
if free is None:
|
|
88
77
|
# an unreadable mount is not evidence of exhaustion; let the merger run and report for real.
|
|
89
78
|
return
|
|
90
79
|
if free >= need:
|
|
@@ -92,10 +81,99 @@ def require_merge_headroom(ckpt_actor_dir: str, merge_out: str) -> None:
|
|
|
92
81
|
raise MergeDiskHeadroomError(
|
|
93
82
|
f"cannot export the adapter: merging {ckpt_actor_dir} needs about "
|
|
94
83
|
f"{need / 1e9:.1f} GB beside it but only {free / 1e9:.1f} GB is free. "
|
|
95
|
-
|
|
84
|
+
+ _FEWER_CHECKPOINTS_ADVICE
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _run_merger(cmd: list[str], env: dict[str, str]) -> None:
|
|
89
|
+
"""stream merger output and prefer direct disk evidence over a short-write marker."""
|
|
90
|
+
from flash.engine.worker import backend_common
|
|
91
|
+
|
|
92
|
+
disk_line = ""
|
|
93
|
+
short_write_line = ""
|
|
94
|
+
|
|
95
|
+
def handle_line(line: str) -> None:
|
|
96
|
+
nonlocal disk_line, short_write_line
|
|
97
|
+
print(line, end="", flush=True)
|
|
98
|
+
lowered = line.lower()
|
|
99
|
+
if not disk_line and any(marker in lowered for marker in _DISK_EXHAUSTED_MARKERS):
|
|
100
|
+
disk_line = line.strip()
|
|
101
|
+
elif not short_write_line and any(marker in lowered for marker in _SHORT_WRITE_MARKERS):
|
|
102
|
+
short_write_line = line.strip()
|
|
103
|
+
|
|
104
|
+
merger_env = {**env, "PYTHONUNBUFFERED": "1"}
|
|
105
|
+
return_code = backend_common._run_streaming_verl_subprocess(
|
|
106
|
+
cmd, env=merger_env, on_line=handle_line, errors="replace"
|
|
107
|
+
)
|
|
108
|
+
if return_code != 0:
|
|
109
|
+
raise subprocess.CalledProcessError(
|
|
110
|
+
return_code, cmd, output=disk_line or short_write_line or None
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _free_bytes(path: str) -> int | None:
|
|
115
|
+
"""free bytes on the filesystem holding ``path``, or none when it cannot be read."""
|
|
116
|
+
try:
|
|
117
|
+
return shutil.disk_usage(os.path.dirname(path.rstrip("/")) or ".").free
|
|
118
|
+
except OSError:
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _error_chain_matches(
|
|
123
|
+
error: BaseException, *, errnos: tuple[int, ...] = (), markers: tuple[str, ...] = ()
|
|
124
|
+
) -> bool:
|
|
125
|
+
"""whether an error chain contains any requested errno or text marker."""
|
|
126
|
+
seen: set[int] = set()
|
|
127
|
+
current: BaseException | None = error
|
|
128
|
+
while current is not None and id(current) not in seen:
|
|
129
|
+
seen.add(id(current))
|
|
130
|
+
if isinstance(current, OSError) and current.errno in errnos:
|
|
131
|
+
return True
|
|
132
|
+
for evidence in (
|
|
133
|
+
current,
|
|
134
|
+
getattr(current, "output", None),
|
|
135
|
+
getattr(current, "stderr", None),
|
|
136
|
+
):
|
|
137
|
+
if isinstance(evidence, bytes):
|
|
138
|
+
evidence = evidence.decode("utf-8", "replace")
|
|
139
|
+
if evidence is not None and any(marker in str(evidence).lower() for marker in markers):
|
|
140
|
+
return True
|
|
141
|
+
current = current.__cause__ or current.__context__
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _disk_exhausted_error(error: BaseException) -> bool:
|
|
146
|
+
"""whether an error chain contains direct volume or quota exhaustion evidence."""
|
|
147
|
+
return _error_chain_matches(
|
|
148
|
+
error, errnos=_DISK_EXHAUSTED_ERRNOS, markers=_DISK_EXHAUSTED_MARKERS
|
|
96
149
|
)
|
|
97
150
|
|
|
98
151
|
|
|
152
|
+
def raise_for_merge_disk_exhaustion(
|
|
153
|
+
error: BaseException, ckpt_actor_dir: str, merge_out: str, *, merger_succeeded: bool = False
|
|
154
|
+
) -> None:
|
|
155
|
+
"""classify direct disk evidence or a low-space short write before cleanup."""
|
|
156
|
+
direct_evidence = _disk_exhausted_error(error)
|
|
157
|
+
if not direct_evidence and isinstance(error, OSError):
|
|
158
|
+
return
|
|
159
|
+
if merger_succeeded and not direct_evidence:
|
|
160
|
+
return
|
|
161
|
+
short_write_evidence = _error_chain_matches(error, markers=_SHORT_WRITE_MARKERS)
|
|
162
|
+
if not direct_evidence and not short_write_evidence:
|
|
163
|
+
return
|
|
164
|
+
free = _free_bytes(merge_out)
|
|
165
|
+
if not direct_evidence and (free is None or free > _MERGE_DISK_EXHAUSTED_FREE_BYTES):
|
|
166
|
+
return
|
|
167
|
+
free_text = "unknown" if free is None else f"{free / 1e9:.2f} GB"
|
|
168
|
+
raise MergeDiskExhaustedError(
|
|
169
|
+
f"ran out of disk while merging {ckpt_actor_dir} into {merge_out}: "
|
|
170
|
+
f"{free_text} free on that filesystem. publishing a checkpoint materializes the FULL base "
|
|
171
|
+
"model beside the checkpoint it reads, so a small lora adapter still needs room for a whole "
|
|
172
|
+
"model copy. the underlying error is a short write, not a corrupt checkpoint. "
|
|
173
|
+
+ _FEWER_CHECKPOINTS_ADVICE
|
|
174
|
+
) from error
|
|
175
|
+
|
|
176
|
+
|
|
99
177
|
def resolve_checkpoint_actor_dir(step_dir: str) -> str:
|
|
100
178
|
"""return the directory inside ``global_step_N`` that holds the saved model + ``huggingface/``.
|
|
101
179
|
|
|
@@ -302,12 +380,10 @@ def export_peft_adapter(
|
|
|
302
380
|
merge_env["HF_HUB_OFFLINE"] = "1"
|
|
303
381
|
merge_env["TRANSFORMERS_OFFLINE"] = "1"
|
|
304
382
|
merge_env["HF_HUB_DISABLE_XET"] = "1"
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
# when the merger dies or writes an unexpected layout would strand tens of gb on the exact
|
|
308
|
-
# disk this guard exists to protect, and the next save would inherit less room than this one.
|
|
383
|
+
# after a successful merge, low free space is expected and cannot classify placement failures.
|
|
384
|
+
merger_succeeded = False
|
|
309
385
|
try:
|
|
310
|
-
|
|
386
|
+
_run_merger(
|
|
311
387
|
[
|
|
312
388
|
python_bin,
|
|
313
389
|
"-m",
|
|
@@ -320,21 +396,25 @@ def export_peft_adapter(
|
|
|
320
396
|
"--target_dir",
|
|
321
397
|
merge_out,
|
|
322
398
|
],
|
|
323
|
-
|
|
324
|
-
env=merge_env,
|
|
399
|
+
merge_env,
|
|
325
400
|
)
|
|
401
|
+
merger_succeeded = True
|
|
326
402
|
lora_dir = os.path.join(merge_out, "lora_adapter")
|
|
327
403
|
if not os.path.exists(os.path.join(lora_dir, "adapter_config.json")):
|
|
328
404
|
raise RuntimeError(
|
|
329
405
|
f"verl model_merger did not produce a peft adapter at {lora_dir} (no adapter_config.json); "
|
|
330
406
|
"the merger output layout must be adjusted for this verl version."
|
|
331
407
|
)
|
|
332
|
-
#
|
|
333
|
-
# in one run workdir, so the two are on one filesystem and `os.replace` is a metadata
|
|
334
|
-
# operation that moves no bytes. copying would hold a second copy of the adapter beside the
|
|
335
|
-
# still-undeleted merge tree, a peak this function's own headroom check does not budget for.
|
|
408
|
+
# move within the shared filesystem so placement does not create another adapter copy.
|
|
336
409
|
for name in os.listdir(lora_dir):
|
|
337
410
|
os.replace(os.path.join(lora_dir, name), os.path.join(out_adapter_dir, name))
|
|
411
|
+
except Exception as error:
|
|
412
|
+
# classify before cleanup frees the merge tree and its low-space evidence.
|
|
413
|
+
# cancellation remains a base exception and is never relabelled as disk exhaustion.
|
|
414
|
+
raise_for_merge_disk_exhaustion(
|
|
415
|
+
error, ckpt_actor_dir, merge_out, merger_succeeded=merger_succeeded
|
|
416
|
+
)
|
|
417
|
+
raise
|
|
338
418
|
finally:
|
|
339
419
|
shutil.rmtree(merge_out, ignore_errors=True)
|
|
340
420
|
|
|
@@ -92,7 +92,7 @@ def _inherit_warmstart_revision(
|
|
|
92
92
|
"""Adopt a warm-start source's pin BEFORE the spec is sized against it.
|
|
93
93
|
|
|
94
94
|
Sizing reads the revision: ``resolve_model`` re-derives params/vocab/disk from the pinned
|
|
95
|
-
commit's geometry, and ``min_disk_gb`` becomes ``
|
|
95
|
+
commit's geometry, and ``min_disk_gb`` becomes ``ceil(2 * params_b) + 64``, which for half of today's
|
|
96
96
|
catalog is strictly larger than the catalog default. Adopting the pin only inside
|
|
97
97
|
``_prepare_init_from_adapter`` -- which runs after ``resolve_model``, ``_with_model_disk``, and
|
|
98
98
|
``_assign_weight_cache_volume`` -- would provision the child as if unpinned while training it
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.39"
|
|
4
4
|
description ="Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -137,7 +137,7 @@ artifacts = ["flash/py.typed"]
|
|
|
137
137
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
138
138
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
139
139
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
140
|
-
version = "1.2.
|
|
140
|
+
version = "1.2.39"
|
|
141
141
|
|
|
142
142
|
[tool.pytest.ini_options]
|
|
143
143
|
pythonpath = ["."]
|
|
@@ -3711,13 +3711,13 @@ def test_without_the_claim_the_orphan_reparents_past_this_process():
|
|
|
3711
3711
|
|
|
3712
3712
|
|
|
3713
3713
|
@_needs_process_teardown
|
|
3714
|
-
def
|
|
3714
|
+
def test_the_claim_is_made_before_each_verl_process_is_spawned():
|
|
3715
3715
|
"""Order matters: the kernel only reparents to a process that was ALREADY a subreaper.
|
|
3716
3716
|
|
|
3717
3717
|
Claiming after the child exists leaves any grandchild it has already orphaned parented
|
|
3718
3718
|
elsewhere, so the fix would work only for the second job onward on a reused worker.
|
|
3719
3719
|
"""
|
|
3720
|
-
for fn in (vc.
|
|
3720
|
+
for fn in (vc._run_streaming_verl_subprocess, rl_train._execute_rl_child):
|
|
3721
3721
|
src = " ".join(inspect.getsource(fn).split())
|
|
3722
3722
|
assert "adopt_orphaned_descendants()" in src, f"{fn.__name__} never claims its orphans"
|
|
3723
3723
|
assert src.index("adopt_orphaned_descendants()") < src.index("subprocess.Popen("), (
|