freesolo-flash-dev 1.2.97__tar.gz → 1.2.98__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.97 → freesolo_flash_dev-1.2.98}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/train_cost.py +18 -9
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/kv_sizing.py +31 -5
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/vram.py +41 -14
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/opd_train_runner.py +1 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/verl_config.py +9 -5
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/schema/__init__.py +38 -7
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_estimate.py +119 -3
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_kv_util.py +108 -4
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lora_rank_preflight.py +28 -3
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_train.py +2 -1
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_rl_train.py +89 -1
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_spec_and_validation.py +96 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vram_architecture.py +39 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.env.example +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/dev-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/production-kernel-cache-ready.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/README.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/adapters/fused_experts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/adapters/targets.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/setup_wandb.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/commands/worker_output.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/errors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/content/image_descriptors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/core/grpo.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/core/spec_persistence.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/huggingface.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/image_tokens.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/sft_image_rows.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/chatml_mask.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/multiturn_media.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/child/patches.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/identity.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/reward_module.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/sft/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/verl/process_census.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/package/direct_tokens.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/envs/staged.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/preparation.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/teacher/provider_status.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/check_rollout_identity_actor.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/capture_image_sft_processor_oracle.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/fixtures/image_sft_processor_oracle.json +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/fixtures/qwen35_08b_target_metadata.json +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_fused_expert_warmstart.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_process_census.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_rollout_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_grpo_rollout_identity.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_image_environment_capability.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_image_incremental_processor.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_image_sft_markers.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_image_sft_processor_parity.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_image_tokens.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lora_rank_nested_rung.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lora_targeting.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_lora_targeting_pinned_verl.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_multiturn_failure_exit.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_persisted_spec_envelope.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_source_attestation_flow.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_spec_contract_bytes.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_staged_environment.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_verl_child_plugins.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_warmstart_image_adapters.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/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.98
|
|
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
|
|
@@ -61,21 +61,30 @@ def _cmd_train_cost(args) -> int:
|
|
|
61
61
|
|
|
62
62
|
def _cmd_train_cost_offline(spec) -> int:
|
|
63
63
|
"""Catalog-only quote for the algorithms that do not need workload evidence yet (grpo, opd)."""
|
|
64
|
+
from dataclasses import replace
|
|
65
|
+
|
|
64
66
|
from flash.cost import estimate_cost
|
|
67
|
+
from flash.schema import MIN_LORA_RANK
|
|
65
68
|
|
|
69
|
+
config = runconfig_from_spec(spec)
|
|
66
70
|
if spec.train.init_from_adapter:
|
|
67
|
-
# --cost is offline/catalog-only and cannot read the source adapter,
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
+
# --cost is offline/catalog-only and cannot read the source adapter's rank, and the parser
|
|
72
|
+
# rejects an authored `lora_rank` alongside `init_from_adapter`, so there is never an
|
|
73
|
+
# authored rank to quote at. stderr keeps stdout clean for machine-readable callers.
|
|
74
|
+
#
|
|
75
|
+
# quote at rank 1 rather than at the serialization placeholder. the placeholder is not a
|
|
76
|
+
# measurement of anything, and `estimate_cost` reads the rank for both the exact-card fit and
|
|
77
|
+
# cost-ranked hardware selection. rank 1 is a vram lower bound, but not a dollar lower bound:
|
|
78
|
+
# a higher source rank can move the run onto a cheaper multi-card shape.
|
|
79
|
+
config = replace(config, lora_rank=MIN_LORA_RANK)
|
|
71
80
|
print(
|
|
72
|
-
"warning: warm-start (train.init_from_adapter) cost
|
|
73
|
-
"source adapter
|
|
74
|
-
|
|
75
|
-
"for a source
|
|
81
|
+
"warning: warm-start (train.init_from_adapter) cost is a provisional rank-1 estimate. "
|
|
82
|
+
"The authoritative source adapter rank is resolved server-side and can change the "
|
|
83
|
+
"selected hardware and cost in either direction. Run "
|
|
84
|
+
f"`{_commands().CLI_NAME} train --dry-run` for a quote using the resolved source rank.",
|
|
76
85
|
file=sys.stderr,
|
|
77
86
|
)
|
|
78
|
-
estimate = estimate_cost(
|
|
87
|
+
estimate = estimate_cost(config)
|
|
79
88
|
if render.styled():
|
|
80
89
|
print(render.cost_panel(estimate))
|
|
81
90
|
else:
|
|
@@ -132,6 +132,26 @@ def _colocate_util_cap(weights_gb: float, total_vram_gb: float) -> float:
|
|
|
132
132
|
return 0.55 if (big_weight_copy and leaves_room_for_trainer_copy) else 0.45
|
|
133
133
|
|
|
134
134
|
|
|
135
|
+
def _capped_engine_util(
|
|
136
|
+
weights_gb: float,
|
|
137
|
+
adapter_gb: float,
|
|
138
|
+
requested_kv_gb: float,
|
|
139
|
+
total_vram_gb: float,
|
|
140
|
+
util_cap: float,
|
|
141
|
+
) -> float:
|
|
142
|
+
"""Fit weights, adapter, then KV into vllm's capped share of one card."""
|
|
143
|
+
card_gb = max(1.0, total_vram_gb)
|
|
144
|
+
max_engine_gb = util_cap * card_gb
|
|
145
|
+
# gpu_memory_utilization is vllm's whole allocation, and its lora weights live inside it. reserve
|
|
146
|
+
# weights plus adapter first; only a cap collision may reduce the requested kv pool. spelling out
|
|
147
|
+
# fitted_kv_gb makes that loss visible instead of incidentally subtracting adapter bytes from a
|
|
148
|
+
# weights-plus-kv fraction. if weights plus adapter alone exceed the cap, kv reaches zero and the
|
|
149
|
+
# returned cap truthfully exposes that this engine shape has no viable cache budget.
|
|
150
|
+
fitted_kv_gb = max(0.0, min(requested_kv_gb, max_engine_gb - weights_gb - adapter_gb))
|
|
151
|
+
fitted_engine_gb = weights_gb + adapter_gb + fitted_kv_gb
|
|
152
|
+
return min(util_cap, fitted_engine_gb / card_gb)
|
|
153
|
+
|
|
154
|
+
|
|
135
155
|
def colocate_kv_util(
|
|
136
156
|
params_b: float | None,
|
|
137
157
|
vllm_max_len: int,
|
|
@@ -143,14 +163,19 @@ def colocate_kv_util(
|
|
|
143
163
|
model_info=None,
|
|
144
164
|
preserve_legacy_floor: bool = False,
|
|
145
165
|
tensor_parallel: int = 1,
|
|
166
|
+
lora_rank: int = 0,
|
|
146
167
|
) -> float:
|
|
147
168
|
"""vllm_gpu_memory_utilization for one colocated rollout tensor-parallel rank.
|
|
148
169
|
|
|
149
|
-
|
|
150
|
-
with measured overhead and an 8
|
|
170
|
+
budget the rank's weight shard, rank-local bf16 lora footprint, and conservative full kv cache.
|
|
171
|
+
catalog models use geometry with measured overhead and an 8 gb floor; uncataloged models retain
|
|
172
|
+
the legacy kv equation and no unverified adapter margin.
|
|
151
173
|
"""
|
|
174
|
+
from flash.engine.plan.vram import _lora_weight_memory_gb
|
|
175
|
+
|
|
152
176
|
total_weights_gb = max(0.5, float(params_b or 1.0)) * 2.0
|
|
153
177
|
tp_size = max(1, int(tensor_parallel))
|
|
178
|
+
adapter_gb = _lora_weight_memory_gb(lora_rank, model_info, tensor_parallel=tp_size) or 0.0
|
|
154
179
|
# tensor parallelism shards vllm's bf16 weights, but kv heads can replicate when tp is wider than
|
|
155
180
|
# the model's kv-head count. shard only the weight term and keep the full kv budget on every rank.
|
|
156
181
|
weights_gb = total_weights_gb if tp_size == 1 else total_weights_gb / tp_size
|
|
@@ -162,7 +187,7 @@ def colocate_kv_util(
|
|
|
162
187
|
# but not H200. `_NvidiaSmiPeakSampler` verifies runtime headroom.
|
|
163
188
|
_util_cap = _colocate_util_cap(weights_gb, total_vram_gb)
|
|
164
189
|
if not sleep_mode:
|
|
165
|
-
# `gpu_memory_utilization` covers weights
|
|
190
|
+
# `gpu_memory_utilization` covers weights, adapter, and kv, so budget all three. scale kv with
|
|
166
191
|
# context and group, floor at `_KV_CAP`, and keep the 0.45 cap aligned with
|
|
167
192
|
# `estimate_vram_gb(..., sleep_offload=False)`.
|
|
168
193
|
kv_gb = max(
|
|
@@ -176,7 +201,8 @@ def colocate_kv_util(
|
|
|
176
201
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
177
202
|
),
|
|
178
203
|
)
|
|
179
|
-
|
|
204
|
+
sized = _capped_engine_util(weights_gb, adapter_gb, kv_gb, total_vram_gb, _util_cap)
|
|
205
|
+
return max(_MIN_ENGINE_UTIL, sized)
|
|
180
206
|
# Sleep mode keeps a larger pool (1.5x margin): the engine is offloaded during the backward, so a
|
|
181
207
|
# bigger rollout-phase KV does not compete with the training peak.
|
|
182
208
|
kv_pool_gb = max(
|
|
@@ -191,7 +217,7 @@ def colocate_kv_util(
|
|
|
191
217
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
192
218
|
),
|
|
193
219
|
)
|
|
194
|
-
sized =
|
|
220
|
+
sized = _capped_engine_util(weights_gb, adapter_gb, kv_pool_gb, total_vram_gb, _util_cap)
|
|
195
221
|
# sharding the weight term can drive a small model's rank budget low enough that vllm has no
|
|
196
222
|
# room left for its own runtime once the kv pool is carved out -- a 4B model on 2 cards prices
|
|
197
223
|
# under this floor. single-rank sizing carries the whole weight copy and never gets that small,
|
|
@@ -129,6 +129,33 @@ def _legacy_lora_floor_gb(lora_rank: int, effective_params_b: float) -> float:
|
|
|
129
129
|
return (lora_rank / 16.0) * (0.3 + 0.04 * effective_params_b)
|
|
130
130
|
|
|
131
131
|
|
|
132
|
+
def _lora_parameter_count(
|
|
133
|
+
lora_rank: int, model_info=None, *, tensor_parallel: int = 1
|
|
134
|
+
) -> int | None:
|
|
135
|
+
"""lora parameters resident on one tensor-parallel rank from concrete target geometry."""
|
|
136
|
+
shapes = tuple(getattr(model_info, "lora_target_shapes", ()) or ())
|
|
137
|
+
rank = int(lora_rank)
|
|
138
|
+
if not shapes or rank <= 0:
|
|
139
|
+
return None
|
|
140
|
+
tp_size = max(1, int(tensor_parallel))
|
|
141
|
+
if tp_size == 1:
|
|
142
|
+
return rank * sum((int(i) + int(o)) * int(count) for i, o, count in shapes)
|
|
143
|
+
# vllm shards one factor, except the current min-dim-1 gate keeps that factor whole. integer shard
|
|
144
|
+
# sizing covers that catalog shape exactly; this is not a general replicated-layer classifier.
|
|
145
|
+
return sum(
|
|
146
|
+
rank * int(count) * (max(int(i), int(o)) + math.ceil(min(int(i), int(o)) / tp_size))
|
|
147
|
+
for i, o, count in shapes
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _lora_weight_memory_gb(
|
|
152
|
+
lora_rank: int, model_info=None, *, tensor_parallel: int = 1
|
|
153
|
+
) -> float | None:
|
|
154
|
+
"""rank-local resident bf16 lora weights, or none without catalog target geometry."""
|
|
155
|
+
params = _lora_parameter_count(lora_rank, model_info, tensor_parallel=tensor_parallel)
|
|
156
|
+
return None if params is None else params * _BYTES_PER_PARAM["bf16"] / 1e9
|
|
157
|
+
|
|
158
|
+
|
|
132
159
|
def _lora_memory_gb(
|
|
133
160
|
lora_rank: int,
|
|
134
161
|
effective_params_b: float,
|
|
@@ -137,14 +164,9 @@ def _lora_memory_gb(
|
|
|
137
164
|
) -> float:
|
|
138
165
|
"""Adapter, gradient, and optimizer memory for the actual PEFT all-linear targets."""
|
|
139
166
|
floor = _legacy_lora_floor_gb(lora_rank, effective_params_b)
|
|
140
|
-
|
|
141
|
-
if
|
|
167
|
+
trainable_params = _lora_parameter_count(lora_rank, model_info)
|
|
168
|
+
if trainable_params is None:
|
|
142
169
|
return floor
|
|
143
|
-
target_dims = sum(
|
|
144
|
-
(int(in_features) + int(out_features)) * int(count)
|
|
145
|
-
for in_features, out_features, count in shapes
|
|
146
|
-
)
|
|
147
|
-
trainable_params = max(1, int(lora_rank)) * target_dims
|
|
148
170
|
bytes_per_param = (
|
|
149
171
|
_LORA_PAGED_BYTES_PER_PARAM
|
|
150
172
|
if (algorithm or "").lower() in ("grpo", "rl")
|
|
@@ -225,15 +247,15 @@ def grpo_kv_floor_gb(
|
|
|
225
247
|
fp8_kv: bool = False,
|
|
226
248
|
model_info=None,
|
|
227
249
|
preserve_legacy_floor: bool = False,
|
|
250
|
+
lora_rank: int = 0,
|
|
251
|
+
tensor_parallel: int = 1,
|
|
228
252
|
) -> int:
|
|
229
|
-
"""Smallest card
|
|
230
|
-
|
|
231
|
-
The 0.45/0.55 cap must hold the weight copy plus half the concurrent group's KV; otherwise
|
|
232
|
-
vLLM can fail with "No available memory for the cache blocks".
|
|
233
|
-
"""
|
|
253
|
+
"""Smallest card whose cap holds rank-local weights, adapter, and half the KV pool."""
|
|
234
254
|
kv_params_b = float(active_params_b) if active_params_b else float(params_b)
|
|
235
|
-
|
|
236
|
-
|
|
255
|
+
tp_size = max(1, int(tensor_parallel))
|
|
256
|
+
weights_gb = max(0.5, float(params_b)) * 2.0 / tp_size
|
|
257
|
+
adapter_gb = _lora_weight_memory_gb(lora_rank, model_info, tensor_parallel=tp_size) or 0.0
|
|
258
|
+
kv_gb = _resident_kv_gb(
|
|
237
259
|
kv_params_b,
|
|
238
260
|
vllm_max_len,
|
|
239
261
|
group_size,
|
|
@@ -241,6 +263,7 @@ def grpo_kv_floor_gb(
|
|
|
241
263
|
model_info=model_info,
|
|
242
264
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
243
265
|
)
|
|
266
|
+
need = weights_gb + adapter_gb + 0.5 * kv_gb
|
|
244
267
|
lower = math.ceil(need / 0.55)
|
|
245
268
|
upper = math.ceil(need / 0.45)
|
|
246
269
|
for total_vram_gb in range(lower, upper + 1):
|
|
@@ -295,6 +318,7 @@ def _rollout_kv_floor_gb(
|
|
|
295
318
|
model_info=None,
|
|
296
319
|
model_id: str = "",
|
|
297
320
|
preserve_legacy_floor: bool = False,
|
|
321
|
+
lora_rank: int = 0,
|
|
298
322
|
) -> int:
|
|
299
323
|
floor = grpo_kv_floor_gb(
|
|
300
324
|
params_b,
|
|
@@ -303,6 +327,7 @@ def _rollout_kv_floor_gb(
|
|
|
303
327
|
active_params_b=active_params_b,
|
|
304
328
|
model_info=model_info,
|
|
305
329
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
330
|
+
lora_rank=lora_rank,
|
|
306
331
|
)
|
|
307
332
|
from flash.providers.base import max_non_fp8_kv_vram_gb
|
|
308
333
|
|
|
@@ -323,6 +348,7 @@ def _rollout_kv_floor_gb(
|
|
|
323
348
|
fp8_kv=True,
|
|
324
349
|
model_info=model_info,
|
|
325
350
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
351
|
+
lora_rank=lora_rank,
|
|
326
352
|
)
|
|
327
353
|
return max(fp8_floor, ceiling + 1)
|
|
328
354
|
|
|
@@ -838,6 +864,7 @@ def _catalog_model_required_vram_gb(
|
|
|
838
864
|
model_info=sizing_info,
|
|
839
865
|
model_id=model_id,
|
|
840
866
|
preserve_legacy_floor=is_opd,
|
|
867
|
+
lora_rank=lora_rank,
|
|
841
868
|
),
|
|
842
869
|
)
|
|
843
870
|
return need
|
{freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/opd_train_runner.py
RENAMED
|
@@ -560,6 +560,7 @@ def _resolve_opd_gpu_mem_util(
|
|
|
560
560
|
"model_id": model_id,
|
|
561
561
|
"model_revision": str(getattr(request, "model_revision", "") or ""),
|
|
562
562
|
"engine_len": int(prompt_state.max_model_len),
|
|
563
|
+
"lora_rank": int(workload.lora_rank),
|
|
563
564
|
# opd submits prompts_per_step * group_size generations to the rollout engine together.
|
|
564
565
|
# grpo's concurrency is group_size because its resolver receives one prompt group here.
|
|
565
566
|
"group_size": int(workload.prompts_per_step) * int(request.knobs.group_size),
|
{freesolo_flash_dev-1.2.97 → freesolo_flash_dev-1.2.98}/flash/engine/worker/train/rl/verl_config.py
RENAMED
|
@@ -503,13 +503,16 @@ def resolve_gpu_mem_util(
|
|
|
503
503
|
) -> float:
|
|
504
504
|
"""size vllm's colocated executor budget from this run's geometry.
|
|
505
505
|
|
|
506
|
-
``gpu_memory_utilization`` covers the second bf16 weight copy
|
|
506
|
+
``gpu_memory_utilization`` covers the second bf16 weight copy, lora adapter, and kv pool. using
|
|
507
507
|
``colocate_kv_util`` keeps worker allocation aligned with preflight admission.
|
|
508
508
|
|
|
509
|
-
for multi-gpu runs, vllm shards its bf16 weight copy across tensor-parallel ranks.
|
|
510
|
-
|
|
511
|
-
the
|
|
512
|
-
|
|
509
|
+
for multi-gpu runs, vllm shards its bf16 weight copy across tensor-parallel ranks. its default
|
|
510
|
+
lora layout shards only one factor of each projection's a/b pair, so the rank-local adapter uses
|
|
511
|
+
the larger safe orientation from catalog geometry rather than dividing the full adapter evenly.
|
|
512
|
+
the kv term remains unsharded here because vllm can replicate kv heads when tensor parallelism is
|
|
513
|
+
wider than the model's kv-head count. the adapter lives inside vllm's reservation, and the result
|
|
514
|
+
is explicitly capped at the old 0.5 constant, so this path can only lower a rank's reservation
|
|
515
|
+
and cannot create a new over-reservation.
|
|
513
516
|
|
|
514
517
|
the flat constant is kept where the model does not apply, because a wrong number is worse than
|
|
515
518
|
a conservative one:
|
|
@@ -564,6 +567,7 @@ def resolve_gpu_mem_util(
|
|
|
564
567
|
model_info=info,
|
|
565
568
|
preserve_legacy_floor=preserve_legacy_floor,
|
|
566
569
|
tensor_parallel=n_gpus,
|
|
570
|
+
lora_rank=int(inp["lora_rank"]),
|
|
567
571
|
)
|
|
568
572
|
# multi-rank sizing is strictly one-directional against the previous worker contract: it may
|
|
569
573
|
# free memory but can never claim more than the flat reservation a working run already used.
|
|
@@ -50,6 +50,12 @@ from flash.schema.fields import (
|
|
|
50
50
|
_wandb_spec,
|
|
51
51
|
)
|
|
52
52
|
|
|
53
|
+
# the smallest rank the parser accepts, and so the smallest a source adapter can turn out to have.
|
|
54
|
+
# unresolved warm starts use it instead of the serialization default for permissive client-side
|
|
55
|
+
# sizing. it is a vram lower bound, not a dollar lower bound because cost-ranked hardware selection
|
|
56
|
+
# is non-monotonic across shapes. keep it aligned with the `lora_rank` parser floor.
|
|
57
|
+
MIN_LORA_RANK = 1
|
|
58
|
+
|
|
53
59
|
_OWNER_REPO_RE = r"[A-Za-z0-9][A-Za-z0-9._-]*"
|
|
54
60
|
_RUN_ID_RE = r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}"
|
|
55
61
|
# canonical short checkpoint references name a run alias or a saved checkpoint. immutable adapter
|
|
@@ -437,6 +443,7 @@ def _validate_gpu_section(
|
|
|
437
443
|
model_revision: str,
|
|
438
444
|
algorithm: str,
|
|
439
445
|
train_raw: dict[str, Any],
|
|
446
|
+
init_from_adapter: str,
|
|
440
447
|
thinking: bool,
|
|
441
448
|
) -> tuple[GpuSpec, bool]:
|
|
442
449
|
"""Validate the GPU section and return its canonical spec plus auto-sizing provenance."""
|
|
@@ -483,10 +490,18 @@ def _validate_gpu_section(
|
|
|
483
490
|
# provider preferences are soft; configured unnamed providers remain eligible.
|
|
484
491
|
|
|
485
492
|
requested_gpu_count = authored_gpu_ceiling(gpu_spec.type, gpu_count)
|
|
493
|
+
unresolved_warmstart_rank = bool(init_from_adapter) and "lora_rank" not in train_raw
|
|
494
|
+
# the client cannot resolve a run id to the source adapter metadata, so rank 32 is only a
|
|
495
|
+
# serialization placeholder here. keep geometry checks and reject shapes that cannot fit even at
|
|
496
|
+
# the minimum valid rank; the server replaces this value from adapter_config.json before its
|
|
497
|
+
# authoritative allocation-time vram check.
|
|
498
|
+
preflight_train = (
|
|
499
|
+
{**train_raw, "lora_rank": MIN_LORA_RANK} if unresolved_warmstart_rank else train_raw
|
|
500
|
+
)
|
|
486
501
|
preflight_gpu_count = provisional_gpu_count(
|
|
487
502
|
model,
|
|
488
503
|
algorithm,
|
|
489
|
-
train=
|
|
504
|
+
train=preflight_train,
|
|
490
505
|
thinking=thinking,
|
|
491
506
|
geometry_model_revision=model_revision,
|
|
492
507
|
gpu_count=requested_gpu_count,
|
|
@@ -495,10 +510,16 @@ def _validate_gpu_section(
|
|
|
495
510
|
if gpu_types and preflight_gpu_count <= 1 and not model_revision:
|
|
496
511
|
from flash.providers.allocator import required_vram_gb
|
|
497
512
|
|
|
513
|
+
# sized from `preflight_train`, so an unresolved warm start is measured at rank 1 rather
|
|
514
|
+
# than at the placeholder. that is a true vram lower bound: no source adapter can need
|
|
515
|
+
# less. a card rejected here therefore cannot fit at any rank the source could turn out to
|
|
516
|
+
# have, which keeps an impossible pin (an 80 GB A100 for a run needing 180 GB at rank 1)
|
|
517
|
+
# rejected at parse time. relaxing the rank is not the same as dropping the check --
|
|
518
|
+
# dropping it would let the authored `gpu.type` go unvalidated entirely.
|
|
498
519
|
required_vram = required_vram_gb(
|
|
499
520
|
model,
|
|
500
521
|
algorithm,
|
|
501
|
-
train=
|
|
522
|
+
train=preflight_train,
|
|
502
523
|
thinking=thinking,
|
|
503
524
|
)
|
|
504
525
|
# every authored class is checked, not just the head: a fallback too small to hold the
|
|
@@ -517,7 +538,7 @@ def _validate_gpu_section(
|
|
|
517
538
|
provisional_gpu(
|
|
518
539
|
model,
|
|
519
540
|
algorithm=algorithm,
|
|
520
|
-
train=
|
|
541
|
+
train=preflight_train,
|
|
521
542
|
thinking=thinking,
|
|
522
543
|
geometry_model_revision=model_revision,
|
|
523
544
|
gpu_count=preflight_gpu_count,
|
|
@@ -529,7 +550,12 @@ def _validate_gpu_section(
|
|
|
529
550
|
|
|
530
551
|
|
|
531
552
|
def _validate_algorithm_model_consistency(
|
|
532
|
-
model: str,
|
|
553
|
+
model: str,
|
|
554
|
+
algorithm: str,
|
|
555
|
+
thinking: bool,
|
|
556
|
+
train_raw: dict[str, Any],
|
|
557
|
+
*,
|
|
558
|
+
init_from_adapter: str,
|
|
533
559
|
) -> tuple[str, int, int]:
|
|
534
560
|
"""Validate algorithm and model-info consistency."""
|
|
535
561
|
try:
|
|
@@ -547,7 +573,6 @@ def _validate_algorithm_model_consistency(
|
|
|
547
573
|
f"{model} always emits <think> reasoning and cannot run with thinking "
|
|
548
574
|
f"disabled; set thinking = true"
|
|
549
575
|
)
|
|
550
|
-
init_from_adapter = _init_from_adapter_ref(train_raw)
|
|
551
576
|
if init_from_adapter and "lora_rank" in train_raw:
|
|
552
577
|
raise ConfigError(
|
|
553
578
|
"train.lora_rank cannot be set with train.init_from_adapter because source adapter "
|
|
@@ -558,7 +583,7 @@ def _validate_algorithm_model_consistency(
|
|
|
558
583
|
"train.lora_alpha cannot be set with train.init_from_adapter because source adapter "
|
|
559
584
|
"alpha metadata is authoritative"
|
|
560
585
|
)
|
|
561
|
-
lora_rank = _train_int(train_raw, "lora_rank", minimum=
|
|
586
|
+
lora_rank = _train_int(train_raw, "lora_rank", minimum=MIN_LORA_RANK) or 32
|
|
562
587
|
# unset -> the tuned 2 x rank default. authored -> the user's value, which need not be 2 x rank.
|
|
563
588
|
lora_alpha = _train_int(train_raw, "lora_alpha", minimum=1) or 2 * lora_rank
|
|
564
589
|
max_lora_rank = serving_lora_rank_cap(info)
|
|
@@ -590,16 +615,22 @@ def spec_from_dict(
|
|
|
590
615
|
)
|
|
591
616
|
except (TypeError, ValueError) as exc:
|
|
592
617
|
raise ConfigError(str(exc)) from exc
|
|
618
|
+
init_from_adapter = _init_from_adapter_ref(train_raw)
|
|
593
619
|
gpu_spec, gpu_count_auto = _validate_gpu_section(
|
|
594
620
|
raw,
|
|
595
621
|
model=model,
|
|
596
622
|
model_revision=model_revision,
|
|
597
623
|
algorithm=algorithm,
|
|
598
624
|
train_raw=train_raw,
|
|
625
|
+
init_from_adapter=init_from_adapter,
|
|
599
626
|
thinking=thinking,
|
|
600
627
|
)
|
|
601
628
|
init_from_adapter, lora_rank, lora_alpha = _validate_algorithm_model_consistency(
|
|
602
|
-
model,
|
|
629
|
+
model,
|
|
630
|
+
algorithm,
|
|
631
|
+
thinking,
|
|
632
|
+
train_raw,
|
|
633
|
+
init_from_adapter=init_from_adapter,
|
|
603
634
|
)
|
|
604
635
|
wandb_spec = _validate_wandb_section(raw)
|
|
605
636
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.98"
|
|
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.98"
|
|
141
141
|
|
|
142
142
|
[tool.pytest.ini_options]
|
|
143
143
|
pythonpath = ["."]
|
|
@@ -1021,8 +1021,8 @@ def test_sft_cost_warns_when_an_env_key_shadows_the_saved_login(tmp_path, monkey
|
|
|
1021
1021
|
|
|
1022
1022
|
|
|
1023
1023
|
@pytest.mark.parametrize("algorithm", ["grpo", "opd"])
|
|
1024
|
-
def
|
|
1025
|
-
"""grpo/opd keep the local analytical quote until PR2 profiles their rollouts.
|
|
1024
|
+
def test_warm_start_non_sft_cost_stays_offline(tmp_path, monkeypatch, capsys, algorithm):
|
|
1025
|
+
"""warm-start grpo/opd keep the local analytical quote until PR2 profiles their rollouts.
|
|
1026
1026
|
|
|
1027
1027
|
Asserted by making the client constructor itself fatal: a passing quote then proves no
|
|
1028
1028
|
authenticated request was possible, not merely that none was observed.
|
|
@@ -1037,7 +1037,8 @@ def test_non_sft_cost_stays_offline(tmp_path, monkeypatch, capsys, algorithm):
|
|
|
1037
1037
|
monkeypatch.setenv("FLASH_STYLE", "0")
|
|
1038
1038
|
# group_size 2 is grpo's floor (advantages are group-relative) and is valid for opd too.
|
|
1039
1039
|
body = SFT_TOML.replace('algorithm = "sft"', f'algorithm = "{algorithm}"').replace(
|
|
1040
|
-
"batch_size = 8\n",
|
|
1040
|
+
"batch_size = 8\n",
|
|
1041
|
+
'prompts_per_step = 8\nmax_examples = 40\ngroup_size = 2\ninit_from_adapter = "source-run"\n',
|
|
1041
1042
|
)
|
|
1042
1043
|
|
|
1043
1044
|
assert cmd_train(_sft_args(tmp_path, body)) == 0
|
|
@@ -1047,6 +1048,121 @@ def test_non_sft_cost_stays_offline(tmp_path, monkeypatch, capsys, algorithm):
|
|
|
1047
1048
|
assert "source rows in published copy" not in captured.out
|
|
1048
1049
|
assert "selected from" not in captured.out
|
|
1049
1050
|
assert "shadowed!" not in captured.err
|
|
1051
|
+
assert (
|
|
1052
|
+
"warning: warm-start (train.init_from_adapter) cost is a provisional rank-1 estimate. "
|
|
1053
|
+
"The authoritative source adapter rank is resolved server-side and can change the selected "
|
|
1054
|
+
"hardware and cost in either direction. Run `flash train --dry-run` for a quote using the "
|
|
1055
|
+
"resolved source rank.\n" in captured.err
|
|
1056
|
+
)
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
@pytest.mark.parametrize("algorithm", ["grpo", "opd"])
|
|
1060
|
+
def test_plain_non_sft_cost_stays_offline(tmp_path, monkeypatch, capsys, algorithm):
|
|
1061
|
+
"""Ordinary grpo/opd quotes stay local independently of the warm-start branch."""
|
|
1062
|
+
from flash.cli import commands
|
|
1063
|
+
|
|
1064
|
+
monkeypatch.setattr(
|
|
1065
|
+
commands,
|
|
1066
|
+
"client_from_config",
|
|
1067
|
+
lambda *_a, **_kw: pytest.fail(f"{algorithm} --cost must not contact the control plane"),
|
|
1068
|
+
)
|
|
1069
|
+
monkeypatch.setenv("FLASH_STYLE", "0")
|
|
1070
|
+
body = SFT_TOML.replace('algorithm = "sft"', f'algorithm = "{algorithm}"').replace(
|
|
1071
|
+
"batch_size = 8\n", "prompts_per_step = 8\nmax_examples = 40\ngroup_size = 2\n"
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
assert cmd_train(_sft_args(tmp_path, body)) == 0
|
|
1075
|
+
captured = capsys.readouterr()
|
|
1076
|
+
assert "TOTAL" in captured.out
|
|
1077
|
+
assert "warm-start" not in captured.err
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
def test_warm_start_cost_quotes_the_card_the_parser_accepts(tmp_path, capsys, monkeypatch):
|
|
1081
|
+
"""The quote must not refuse the exact configuration the parser now admits.
|
|
1082
|
+
|
|
1083
|
+
`estimate_cost` reads the rank for both the price and the exact-card fit, so quoting at the
|
|
1084
|
+
serialization placeholder rejected a single B200 as needing 199 GB and advised `--gpus 2`, a
|
|
1085
|
+
shortfall the real source rank may not have. Sized at the rank-1 vram lower bound it fits in 180
|
|
1086
|
+
GB, while the warning accurately labels the dollars as provisional.
|
|
1087
|
+
"""
|
|
1088
|
+
from flash.cli import commands
|
|
1089
|
+
|
|
1090
|
+
monkeypatch.setattr(
|
|
1091
|
+
commands,
|
|
1092
|
+
"client_from_config",
|
|
1093
|
+
lambda *_a, **_kw: pytest.fail("offline quote must not contact the plane"),
|
|
1094
|
+
)
|
|
1095
|
+
monkeypatch.setenv("FLASH_STYLE", "0")
|
|
1096
|
+
body = SFT_TOML.replace('algorithm = "sft"', 'algorithm = "grpo"').replace(
|
|
1097
|
+
"batch_size = 8\n",
|
|
1098
|
+
'prompts_per_step = 8\nmax_examples = 40\ngroup_size = 2\ninit_from_adapter = "source-run"\n',
|
|
1099
|
+
)
|
|
1100
|
+
# SFT_TOML ends with an empty `[gpu]`, so the pin is appended into that section.
|
|
1101
|
+
body = body.replace('model = "Qwen/Qwen3.5-4B"', 'model = "Qwen/Qwen3.6-35B-A3B"')
|
|
1102
|
+
body += 'type = "B200"\ncount = 1\n'
|
|
1103
|
+
|
|
1104
|
+
assert cmd_train(_sft_args(tmp_path, body)) == 0
|
|
1105
|
+
captured = capsys.readouterr()
|
|
1106
|
+
assert "TOTAL" in captured.out
|
|
1107
|
+
assert "--gpus 2" not in captured.err
|
|
1108
|
+
assert (
|
|
1109
|
+
"warning: warm-start (train.init_from_adapter) cost is a provisional rank-1 estimate. "
|
|
1110
|
+
"The authoritative source adapter rank is resolved server-side and can change the selected "
|
|
1111
|
+
"hardware and cost in either direction. Run `flash train --dry-run` for a quote using the "
|
|
1112
|
+
"resolved source rank.\n" in captured.err
|
|
1113
|
+
)
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
def _warm_start_rank_boundary_config():
|
|
1117
|
+
from flash.cost.spec import runconfig_from_spec
|
|
1118
|
+
|
|
1119
|
+
spec = spec_from_dict(
|
|
1120
|
+
{
|
|
1121
|
+
"project": "00000000-0000-0000-0000-000000000001",
|
|
1122
|
+
"model": "Qwen/Qwen3.6-35B-A3B",
|
|
1123
|
+
"algorithm": "grpo",
|
|
1124
|
+
"environment": {"id": "my-org/my-proj/my-env"},
|
|
1125
|
+
"train": {"prompts_per_step": 8, "max_examples": 40, "group_size": 2},
|
|
1126
|
+
}
|
|
1127
|
+
)
|
|
1128
|
+
return runconfig_from_spec(spec)
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
def test_higher_warm_start_rank_crosses_hardware_shape_boundary():
|
|
1132
|
+
"""Catalog geometry, not mutable prices, owns the rank-dependent hardware boundary."""
|
|
1133
|
+
from dataclasses import replace
|
|
1134
|
+
|
|
1135
|
+
from flash.cost import estimate_cost
|
|
1136
|
+
from flash.providers.base import GPU_INFO
|
|
1137
|
+
|
|
1138
|
+
config = _warm_start_rank_boundary_config()
|
|
1139
|
+
rank_1 = estimate_cost(replace(config, lora_rank=1))
|
|
1140
|
+
rank_8 = estimate_cost(replace(config, lora_rank=8))
|
|
1141
|
+
|
|
1142
|
+
assert GPU_INFO["B200"].vram_gb == 180
|
|
1143
|
+
assert GPU_INFO["H200"].vram_gb == 141
|
|
1144
|
+
assert (rank_1.required_vram_gb, rank_1.gpu_count, rank_1.gpu) == (180, 1, "B200")
|
|
1145
|
+
assert (rank_8.required_vram_gb, rank_8.gpu_count, rank_8.gpu) == (182, 2, "H200")
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
def test_higher_warm_start_rank_can_select_cheaper_hardware(monkeypatch):
|
|
1149
|
+
"""Controlled prices prove that crossing the shape boundary can lower total cost."""
|
|
1150
|
+
from dataclasses import replace
|
|
1151
|
+
|
|
1152
|
+
from flash.cost import estimate_cost
|
|
1153
|
+
from flash.providers import base
|
|
1154
|
+
|
|
1155
|
+
b200 = replace(base.GPU_INFO["B200"], hourly_usd=5.50)
|
|
1156
|
+
h200 = replace(base.GPU_INFO["H200"], hourly_usd=4.00)
|
|
1157
|
+
monkeypatch.setattr(base, "GPU_INFO", {"B200": b200, "H200": h200})
|
|
1158
|
+
|
|
1159
|
+
config = _warm_start_rank_boundary_config()
|
|
1160
|
+
rank_1 = estimate_cost(replace(config, lora_rank=1))
|
|
1161
|
+
rank_8 = estimate_cost(replace(config, lora_rank=8))
|
|
1162
|
+
|
|
1163
|
+
assert (rank_1.gpu, rank_1.gpu_count, rank_1.gpu_hourly_usd) == ("B200", 1, 5.50)
|
|
1164
|
+
assert (rank_8.gpu, rank_8.gpu_count, rank_8.gpu_hourly_usd) == ("H200", 2, 4.00)
|
|
1165
|
+
assert rank_8.total_usd < rank_1.total_usd
|
|
1050
1166
|
|
|
1051
1167
|
|
|
1052
1168
|
def test_cmd_train_cost_rejects_context_above_serving_cap(tmp_path):
|