freesolo-flash-dev 1.2.36__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.36 → freesolo_flash_dev-1.2.39}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/__init__.py +13 -5
- freesolo_flash_dev-1.2.39/flash/cli/commands/prompt_budget.py +146 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/train_cost.py +3 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/core/catalog.py +7 -3
- freesolo_flash_dev-1.2.39/flash/engine/plan/prompt_budget.py +63 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/backend_common.py +51 -65
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/opd_train_runner.py +6 -2
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/failures.py +4 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/checkpoints.py +7 -1
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/inputs.py +5 -5
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/checkpoints.py +18 -1
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/checkpoints.py +137 -57
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/__init__.py +7 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/preparation.py +6 -5
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/submit.py +17 -5
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_backend_common.py +2 -2
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_client_server_integration.py +5 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_disk_gb.py +90 -16
- freesolo_flash_dev-1.2.39/tests/test_prompt_budget.py +392 -0
- {freesolo_flash_dev-1.2.36 → 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.36 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_cross_repo.py +14 -4
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.env.example +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/README.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/shims.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.36 → freesolo_flash_dev-1.2.39}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.36 → 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
|
|
@@ -399,6 +399,7 @@ def cmd_train(args) -> int:
|
|
|
399
399
|
# equally not a verification -- so treat anything but an explicit True as unverified.
|
|
400
400
|
affordability_verified = status.pop("affordability_verified", None) is True
|
|
401
401
|
cost = "and cost" if affordability_verified else "but NOT cost"
|
|
402
|
+
budget_validated = prompt_budget_validation_suffix(status)
|
|
402
403
|
environment = (
|
|
403
404
|
"it did NOT import or run your environment.py. packaged input/output fields and the "
|
|
404
405
|
"statically readable training contract were tokenized together; tokens, retention, "
|
|
@@ -411,8 +412,8 @@ def cmd_train(args) -> int:
|
|
|
411
412
|
)
|
|
412
413
|
print(
|
|
413
414
|
"dry-run validated: config/schema, model+algorithm compatibility, lora rank, "
|
|
414
|
-
f"runtime-secret presence, warm-start source, serving context cap
|
|
415
|
-
f"{environment}",
|
|
415
|
+
f"runtime-secret presence, warm-start source, serving context cap{budget_validated}, "
|
|
416
|
+
f"{cost}. {environment}",
|
|
416
417
|
file=sys.stderr,
|
|
417
418
|
)
|
|
418
419
|
if not affordability_verified:
|
|
@@ -430,8 +431,10 @@ def cmd_train(args) -> int:
|
|
|
430
431
|
else:
|
|
431
432
|
print(json.dumps(status, indent=2))
|
|
432
433
|
_print_unpacked_batch_warning(status, spec) # after the payload, so stdout stays parseable
|
|
434
|
+
print_status_prompt_budget_warning(status)
|
|
433
435
|
_print_reasoning_loss_warning(status)
|
|
434
436
|
return 0
|
|
437
|
+
local_budget = warn_before_paid_submit(client, spec)
|
|
435
438
|
status = client.create_run(
|
|
436
439
|
payload,
|
|
437
440
|
runtime_secrets=runtime_secrets,
|
|
@@ -440,6 +443,7 @@ def cmd_train(args) -> int:
|
|
|
440
443
|
run_id = status["run_id"]
|
|
441
444
|
_print_unpacked_batch_warning(status, spec) # a real submit overrides batch_size the same way
|
|
442
445
|
_print_reasoning_loss_warning(status) # and trains on whatever reasoning the template kept
|
|
446
|
+
print_warmstart_context_supplement(local_budget, status)
|
|
443
447
|
logger.info(
|
|
444
448
|
"submitted run %s: model=%s algorithm=%s gpu=%s",
|
|
445
449
|
run_id,
|
|
@@ -963,9 +967,13 @@ from flash.cli.commands.deploy import ( # noqa: E402,F401
|
|
|
963
967
|
cmd_undeploy,
|
|
964
968
|
)
|
|
965
969
|
|
|
966
|
-
#
|
|
967
|
-
|
|
968
|
-
|
|
970
|
+
# imported at the bottom because the train helpers resolve patched command-package names lazily.
|
|
971
|
+
from flash.cli.commands.prompt_budget import ( # noqa: E402
|
|
972
|
+
print_status_prompt_budget_warning,
|
|
973
|
+
print_warmstart_context_supplement,
|
|
974
|
+
prompt_budget_validation_suffix,
|
|
975
|
+
warn_before_paid_submit,
|
|
976
|
+
)
|
|
969
977
|
from flash.cli.commands.train_cost import ( # noqa: E402,F401
|
|
970
978
|
_client_train_schema,
|
|
971
979
|
_cmd_train_cost,
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""prompt-budget warnings and warm-start context lookup for training commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from typing import TypeGuard, cast
|
|
7
|
+
|
|
8
|
+
from flash import __version__
|
|
9
|
+
from flash.cli.ui import render
|
|
10
|
+
from flash.engine.plan.prompt_budget import PromptBudget, rl_prompt_budget
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _positive_int(value: object) -> TypeGuard[int]:
|
|
14
|
+
return isinstance(value, int) and not isinstance(value, bool) and value > 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _budget_from_status(status: object) -> PromptBudget | None:
|
|
18
|
+
budget = status.get("prompt_budget") if isinstance(status, dict) else None
|
|
19
|
+
if not isinstance(budget, dict):
|
|
20
|
+
return None
|
|
21
|
+
if budget.get("algorithm") not in {"grpo", "opd", "rl"}:
|
|
22
|
+
return None
|
|
23
|
+
if budget.get("context_source") not in {"authored", "recipe_default"}:
|
|
24
|
+
return None
|
|
25
|
+
if budget.get("prompt_budget_is_upper_bound") is not True:
|
|
26
|
+
return None
|
|
27
|
+
engine_len = budget.get("engine_len")
|
|
28
|
+
max_completion = budget.get("max_completion")
|
|
29
|
+
prompt_budget = budget.get("prompt_budget")
|
|
30
|
+
if not _positive_int(engine_len):
|
|
31
|
+
return None
|
|
32
|
+
if not _positive_int(max_completion):
|
|
33
|
+
return None
|
|
34
|
+
if not _positive_int(prompt_budget):
|
|
35
|
+
return None
|
|
36
|
+
if prompt_budget != engine_len - max_completion:
|
|
37
|
+
return None
|
|
38
|
+
source_context = budget.get("warm_start_context")
|
|
39
|
+
if source_context is not None and not _positive_int(source_context):
|
|
40
|
+
return None
|
|
41
|
+
return cast("PromptBudget", budget)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def prompt_budget_validation_suffix(status: object) -> str:
|
|
45
|
+
"""qualify a dry-run summary only when the server returned a budget."""
|
|
46
|
+
return ", prompt budget (upper bound)" if _budget_from_status(status) is not None else ""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def warmstart_source_context(client, spec) -> int | None:
|
|
50
|
+
"""read a warm-start source's authored context through the cli's authenticated client."""
|
|
51
|
+
from flash.core.catalog import samples_on_policy
|
|
52
|
+
from flash.schema import parse_checkpoint_ref
|
|
53
|
+
|
|
54
|
+
ref = getattr(spec.train, "init_from_adapter", "")
|
|
55
|
+
if not ref or not samples_on_policy(spec.algorithm):
|
|
56
|
+
return None
|
|
57
|
+
parsed = parse_checkpoint_ref(ref)
|
|
58
|
+
if parsed is None:
|
|
59
|
+
return None
|
|
60
|
+
try:
|
|
61
|
+
source = client.get_run(parsed[0])
|
|
62
|
+
# reporting is best-effort and must never block a valid submission
|
|
63
|
+
except Exception:
|
|
64
|
+
return None
|
|
65
|
+
train = (source or {}).get("spec", {}).get("train", {}) if isinstance(source, dict) else {}
|
|
66
|
+
context = train.get("max_context_tokens") if isinstance(train, dict) else None
|
|
67
|
+
if isinstance(context, bool) or not isinstance(context, int) or context <= 0:
|
|
68
|
+
return None
|
|
69
|
+
return context
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _warmstart_context_sentence(context: object) -> str | None:
|
|
73
|
+
if isinstance(context, bool) or not isinstance(context, int) or context <= 0:
|
|
74
|
+
return None
|
|
75
|
+
return (
|
|
76
|
+
f"The warm-start source was configured with max_context_tokens={context}; "
|
|
77
|
+
"it is NOT inherited."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def prompt_budget_warning(
|
|
82
|
+
budget: object,
|
|
83
|
+
*,
|
|
84
|
+
derived_locally: bool = False,
|
|
85
|
+
include_warm_start_context: bool = True,
|
|
86
|
+
) -> str | None:
|
|
87
|
+
"""render the defaulted-budget warning for one prompt-budget descriptor."""
|
|
88
|
+
if not isinstance(budget, dict) or budget.get("context_source") != "recipe_default":
|
|
89
|
+
return None
|
|
90
|
+
try:
|
|
91
|
+
prompt_budget = int(budget["prompt_budget"])
|
|
92
|
+
max_completion = int(budget["max_completion"])
|
|
93
|
+
except (KeyError, TypeError, ValueError):
|
|
94
|
+
return None
|
|
95
|
+
algorithm = str(budget.get("algorithm") or "").upper() or "RL"
|
|
96
|
+
message = (
|
|
97
|
+
f"train.max_context_tokens is unset, so {algorithm} derives a prompt budget of at most "
|
|
98
|
+
f"{prompt_budget} tokens from the recipe default (engine {budget.get('engine_len')} minus "
|
|
99
|
+
f"max_completion_tokens {max_completion}), not from the model's context. The worker clamps "
|
|
100
|
+
"the engine length to the model architecture first, so its budget can be smaller than "
|
|
101
|
+
"this. Prompts over the budget are DROPPED, not truncated, so the run trains on a "
|
|
102
|
+
"shorter, biased subset."
|
|
103
|
+
)
|
|
104
|
+
if derived_locally:
|
|
105
|
+
message += (
|
|
106
|
+
f" (Derived locally by this CLI {__version__}; if the control plane is on a "
|
|
107
|
+
"different release its recipe default may differ.)"
|
|
108
|
+
)
|
|
109
|
+
if include_warm_start_context:
|
|
110
|
+
source = _warmstart_context_sentence(budget.get("warm_start_context"))
|
|
111
|
+
if source:
|
|
112
|
+
message += f" {source}"
|
|
113
|
+
return message + " Set train.max_context_tokens explicitly to choose the budget."
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _print_warning(message: str | None) -> None:
|
|
117
|
+
if message:
|
|
118
|
+
print(render.warn(message) if render.styled() else f"warning: {message}", file=sys.stderr)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def print_status_prompt_budget_warning(status: object) -> None:
|
|
122
|
+
"""print the server-derived warning carried by a submit or dry-run response."""
|
|
123
|
+
_print_warning(prompt_budget_warning(_budget_from_status(status)))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def warn_before_paid_submit(client, spec) -> PromptBudget | None:
|
|
127
|
+
"""print the locally derived warning before create_run can start provisioning."""
|
|
128
|
+
budget = rl_prompt_budget(spec, warm_start_context=warmstart_source_context(client, spec))
|
|
129
|
+
_print_warning(prompt_budget_warning(budget, derived_locally=True))
|
|
130
|
+
return budget
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def print_warmstart_context_supplement(local_budget: PromptBudget | None, status: object) -> None:
|
|
134
|
+
"""print only context the server resolved after the generic pre-submit warning."""
|
|
135
|
+
served_budget = _budget_from_status(status)
|
|
136
|
+
if served_budget is None or (
|
|
137
|
+
local_budget is not None and local_budget.get("warm_start_context")
|
|
138
|
+
):
|
|
139
|
+
return
|
|
140
|
+
_print_warning(_warmstart_context_sentence(served_budget.get("warm_start_context")))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def warn_cost_prompt_budget(spec) -> None:
|
|
144
|
+
"""print the local prompt-budget warning for the offline ``--cost`` path."""
|
|
145
|
+
budget = rl_prompt_budget(spec)
|
|
146
|
+
_print_warning(prompt_budget_warning(budget, derived_locally=True))
|
|
@@ -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()]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""derived grpo/opd prompt-budget data reported before paid training."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Literal, NotRequired, TypedDict
|
|
6
|
+
|
|
7
|
+
from flash.engine.plan.vram import (
|
|
8
|
+
grpo_completion_len,
|
|
9
|
+
grpo_rollout_seq_len,
|
|
10
|
+
opd_completion_len,
|
|
11
|
+
opd_rollout_seq_len,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PromptBudget(TypedDict):
|
|
16
|
+
"""serialized prompt-budget descriptor carried by prepared and persisted runs."""
|
|
17
|
+
|
|
18
|
+
algorithm: Literal["grpo", "opd", "rl"]
|
|
19
|
+
engine_len: int
|
|
20
|
+
max_completion: int
|
|
21
|
+
prompt_budget: int
|
|
22
|
+
context_source: Literal["authored", "recipe_default"]
|
|
23
|
+
prompt_budget_is_upper_bound: Literal[True]
|
|
24
|
+
warm_start_context: NotRequired[int]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def rl_prompt_budget(spec, *, warm_start_context: int | None = None) -> PromptBudget | None:
|
|
28
|
+
"""derive the pre-clamp prompt budget used by a grpo/opd worker.
|
|
29
|
+
|
|
30
|
+
the worker clamps ``engine_len`` to the model architecture before subtracting the completion
|
|
31
|
+
allowance, so this control-plane value is an upper bound. sft returns ``None`` because it
|
|
32
|
+
truncates over-long rows and reports that behavior through its workload profile instead.
|
|
33
|
+
"""
|
|
34
|
+
from typing import cast
|
|
35
|
+
|
|
36
|
+
from flash.core.catalog import samples_on_policy
|
|
37
|
+
|
|
38
|
+
raw_algorithm = getattr(spec, "algorithm", "")
|
|
39
|
+
if not samples_on_policy(raw_algorithm):
|
|
40
|
+
return None
|
|
41
|
+
algorithm = cast("Literal['grpo', 'opd', 'rl']", raw_algorithm)
|
|
42
|
+
train = spec.train
|
|
43
|
+
authored = int(getattr(train, "max_context_tokens", 0) or 0)
|
|
44
|
+
max_tokens = getattr(train, "max_completion_tokens", None)
|
|
45
|
+
thinking = bool(getattr(spec, "thinking", False))
|
|
46
|
+
if algorithm == "opd":
|
|
47
|
+
max_completion = opd_completion_len(max_tokens, thinking)
|
|
48
|
+
engine_len = opd_rollout_seq_len(authored, max_tokens, thinking)
|
|
49
|
+
else:
|
|
50
|
+
max_completion = grpo_completion_len(max_tokens, thinking)
|
|
51
|
+
engine_len = grpo_rollout_seq_len(authored, max_tokens, thinking)
|
|
52
|
+
budget: PromptBudget = {
|
|
53
|
+
"algorithm": algorithm,
|
|
54
|
+
"engine_len": int(engine_len),
|
|
55
|
+
"max_completion": int(max_completion),
|
|
56
|
+
"prompt_budget": int(engine_len) - int(max_completion),
|
|
57
|
+
"context_source": "authored" if authored else "recipe_default",
|
|
58
|
+
"prompt_budget_is_upper_bound": True,
|
|
59
|
+
}
|
|
60
|
+
source_context = int(warm_start_context or 0)
|
|
61
|
+
if source_context > 0:
|
|
62
|
+
budget["warm_start_context"] = source_context
|
|
63
|
+
return budget
|
{freesolo_flash_dev-1.2.36 → 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.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/opd_train_runner.py
RENAMED
|
@@ -157,8 +157,12 @@ def _prepare_prompts(
|
|
|
157
157
|
if tokenizer.pad_token is None:
|
|
158
158
|
tokenizer.pad_token = tokenizer.eos_token
|
|
159
159
|
thinking_prefill = _opd_train._thinking_prefill_text(tokenizer)
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
from flash.engine.plan.vram import opd_rollout_seq_len
|
|
161
|
+
|
|
162
|
+
requested_len = opd_rollout_seq_len(
|
|
163
|
+
request.knobs.max_length,
|
|
164
|
+
request.knobs.max_completion,
|
|
165
|
+
bool(_opd_train._w.THINKING),
|
|
162
166
|
)
|
|
163
167
|
# clamp to the architecture BEFORE deriving the prompt budget, so every downstream length agrees.
|
|
164
168
|
# clamping only the engine would admit prompts sized against the unclamped budget and then fail
|
{freesolo_flash_dev-1.2.36 → 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.36 → 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.36 → freesolo_flash_dev-1.2.39}/flash/engine/worker/train/rl/inputs.py
RENAMED
|
@@ -208,15 +208,15 @@ def _grpo_is_multimodal(train, message_prompts):
|
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
def _resolve_sequence_lengths(model_id, model_revision, train_spec, rl, gcfg, tok, multi_turn):
|
|
211
|
-
|
|
212
|
-
# the run this would have failed here after the gpu was already paid for.
|
|
213
|
-
from flash.engine.plan.vram import grpo_completion_len
|
|
211
|
+
from flash.engine.plan.vram import grpo_completion_len, grpo_rollout_seq_len
|
|
214
212
|
|
|
215
|
-
|
|
213
|
+
thinking = bool(_w.THINKING)
|
|
214
|
+
max_tokens = gcfg.get("max_tokens")
|
|
215
|
+
max_completion = grpo_completion_len(max_tokens, thinking)
|
|
216
216
|
train_ctx = (
|
|
217
217
|
train_spec.max_context_tokens if (train_spec and train_spec.max_context_tokens) else 0
|
|
218
218
|
)
|
|
219
|
-
requested_len =
|
|
219
|
+
requested_len = grpo_rollout_seq_len(train_ctx, max_tokens, thinking)
|
|
220
220
|
# clamp to the architecture BEFORE deriving the prompt budget, so every downstream length agrees.
|
|
221
221
|
# clamping only the engine would admit prompts up to the unclamped budget and then fail them at
|
|
222
222
|
# rollout, and would let the token budget pack more than the one-sequence memory floor intends.
|
{freesolo_flash_dev-1.2.36 → 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.
|