freesolo-flash-dev 1.0.63__tar.gz → 1.0.64__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.0.63 → freesolo_flash_dev-1.0.64}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/rl_train.py +21 -8
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/sft_train.py +41 -1
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_rl_train.py +54 -3
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_sft_train.py +200 -3
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/uv.lock +1 -1
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.dockerignore +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.env.example +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.gitignore +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/Dockerfile +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/LICENSE +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/NOTICE +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/README.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/_channel.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/_fileio.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/_logging.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/_update_check.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/adapter_artifacts.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/catalog.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/TRAINING.md +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/_tty.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/commands.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/env_eval.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/env_setup.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/env_test.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/envpush.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/render.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/traces.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cli/training_doc.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/colocation.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/diagnostics.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/accounting.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/multiturn_reward_scoring.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/recipe.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/reward_profile.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/steps.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/vram.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/adapter.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/finalize.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/grpo.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/grpo_multiturn.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/grpo_plugin.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/hf.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/lora.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/multiturn_glue.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd_gkd.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd_multiturn.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd_plugin.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd_structured.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/packing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/rl.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/rng.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/sft.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/teacher.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/archive.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/archive_policy.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/envs/registry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/lora_rank.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/multimodal.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/opd_retry_contract.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/opd_validation.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_deadline.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_hf_artifacts.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_hf_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_http.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_instance.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_instance_bootstrap.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_instance_poll.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_instance_provider.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_poll.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/_worker.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/lambdalabs/pricing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/runpod/train/endpoints.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/providers/weight_cache_preload.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/runner/checkpoints.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/runner/deploy.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/runner/lifecycle.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/runner/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/pricing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/_internal_client.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/_locks.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/_runtime.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/auth.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/billing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/checkpoints.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/db.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/projects.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/reconcile.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/server/run_registry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/spec.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/flash/thinking.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_async_uploads.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_colocation.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_multimodal_input_grads.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_reward_profile.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serving_pricing_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_wandb_log_coverage.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/tests/test_worker_thinking.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.64
|
|
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
|
|
@@ -1229,14 +1229,20 @@ def render_reentrant_checkpointing_shim(reentrant: bool, *, multimodal: bool = F
|
|
|
1229
1229
|
engines whose config may legitimately have checkpointing off, and enabling it there would turn
|
|
1230
1230
|
on a feature verl chose to leave off.
|
|
1231
1231
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1232
|
+
reentrant recompute drops the backward for a checkpointed block when none of that block's
|
|
1233
|
+
inputs require grad. that hits the LANGUAGE side on every lora run: lora freezes the
|
|
1234
|
+
embeddings, so the hidden states entering the first checkpointed decoder layer have
|
|
1235
|
+
``requires_grad=False`` and the whole segment -- containing every lora parameter -- receives no
|
|
1236
|
+
gradient, while the run reports success and bills (GRAD-001). ``enable_input_require_grads()``
|
|
1237
|
+
is what prevents it, and it is unconditional here because every flash rl run is lora.
|
|
1238
|
+
|
|
1239
|
+
on a MULTIMODAL run the same hook additionally restores VISION input gradients. the vision
|
|
1240
|
+
tower's patch embeddings are the same failure in a place the language-side call does not
|
|
1241
|
+
reach: the pixels are frozen inputs, so without a forward hook marking the patch-embed output
|
|
1242
|
+
as requiring grad the visual modules silently receive nothing while the language side trains
|
|
1243
|
+
normally (``tests/test_multimodal_input_grads.py``). the retired trl path installed that hook
|
|
1244
|
+
via a trainer callback; verl has no callback surface, so it rides this shim instead -- and only
|
|
1245
|
+
here, because non-reentrant recompute does not have the behaviour that makes it necessary
|
|
1240
1246
|
(codex[bot]).
|
|
1241
1247
|
"""
|
|
1242
1248
|
if not reentrant:
|
|
@@ -1290,6 +1296,13 @@ def _flash_reentrant_build_module(self):
|
|
|
1290
1296
|
# only when verl actually enabled checkpointing: calling gradient_checkpointing_enable on a
|
|
1291
1297
|
# model verl deliberately left uncheckpointed would turn it ON and change the memory profile.
|
|
1292
1298
|
if getattr(self.model_config, "enable_gradient_checkpointing", False):
|
|
1299
|
+
# the LANGUAGE-side counterpart of the vision hook below, and required for the same
|
|
1300
|
+
# reason (GRAD-001): lora freezes the embeddings, so nothing entering the first
|
|
1301
|
+
# checkpointed decoder layer requires grad and reentrant recompute drops the backward
|
|
1302
|
+
# for the whole segment -- where every lora parameter lives. the vision hook only ever
|
|
1303
|
+
# covered the patch embeddings on multimodal runs; text-only runs had no hook at all and
|
|
1304
|
+
# trained nothing while reporting success.
|
|
1305
|
+
module.enable_input_require_grads()
|
|
1293
1306
|
module.gradient_checkpointing_enable(gradient_checkpointing_kwargs={{"use_reentrant": True}}){vision_hook}
|
|
1294
1307
|
print("[rl-verl] reentrant gradient checkpointing is active", flush=True)
|
|
1295
1308
|
return module
|
|
@@ -57,6 +57,10 @@ from flash.engine.worker.sft import (
|
|
|
57
57
|
_SFT_LORAPLUS_RATIO = 16.0
|
|
58
58
|
_LORAPLUS_READY_MARKER = "FLASH_LORAPLUS_READY"
|
|
59
59
|
_VERL_STEP_RE = re.compile(r"(?:^|\s)step:(\d+)(?:\s|$)")
|
|
60
|
+
# consecutive zero-grad-norm steps tolerated before the run is failed as untrainable (GRAD-001).
|
|
61
|
+
# 2 is enough to separate a one-off fully-masked batch from a severed backward graph, and keeps
|
|
62
|
+
# the wasted spend to a couple of steps rather than the whole run.
|
|
63
|
+
_MAX_ZERO_GRAD_STEPS = 2
|
|
60
64
|
|
|
61
65
|
_REQUIRED_OVERRIDE_KEYS = (
|
|
62
66
|
"train_files",
|
|
@@ -535,6 +539,15 @@ _flash_original_build_module = _FlashFSDPEngine._build_module
|
|
|
535
539
|
|
|
536
540
|
def _flash_build_reentrant_module(self):
|
|
537
541
|
module = _flash_original_build_module(self)
|
|
542
|
+
# REQUIRED before enabling reentrant checkpointing on a lora model, and the reason every
|
|
543
|
+
# verl sft run silently trained nothing (GRAD-001). lora freezes the embeddings, so the
|
|
544
|
+
# hidden states entering the first checkpointed decoder layer have requires_grad=False.
|
|
545
|
+
# reentrant checkpointing needs at least one input tensor requiring grad to attach the
|
|
546
|
+
# recomputed forward to the graph; with none it warns "None of the inputs have
|
|
547
|
+
# requires_grad=True. Gradients will be None" and returns no gradient for the whole
|
|
548
|
+
# segment -- which is where every lora parameter lives. result was grad_norm 0.0 on every
|
|
549
|
+
# step while the run reported done and billed. opd already does this; sft did not.
|
|
550
|
+
module.enable_input_require_grads()
|
|
538
551
|
module.gradient_checkpointing_enable(gradient_checkpointing_kwargs={"use_reentrant": True})
|
|
539
552
|
return module
|
|
540
553
|
|
|
@@ -1340,6 +1353,9 @@ def run_sft_train(spec=None) -> None:
|
|
|
1340
1353
|
]
|
|
1341
1354
|
|
|
1342
1355
|
progress = {"step": resume_step, "loss": None, "grad_norm": None, "lr": None}
|
|
1356
|
+
# consecutive steps seen with grad_norm == 0.0 at a nonzero lr. one step can legitimately be
|
|
1357
|
+
# zero (a fully-masked micro-batch), so require a short run of them before failing.
|
|
1358
|
+
zero_grad_steps: list[int] = []
|
|
1343
1359
|
loss_curve: list[float] = []
|
|
1344
1360
|
train_tokens = sft_completed_train_tokens(
|
|
1345
1361
|
total_tokens_per_epoch,
|
|
@@ -1379,6 +1395,21 @@ def run_sft_train(spec=None) -> None:
|
|
|
1379
1395
|
progress["loss"] = loss
|
|
1380
1396
|
if grad_norm is not None:
|
|
1381
1397
|
progress["grad_norm"] = grad_norm
|
|
1398
|
+
# a grad norm of exactly 0.0 while the lr is still nonzero means the backward pass
|
|
1399
|
+
# produced nothing for every trainable parameter. that is never legitimate: it is a
|
|
1400
|
+
# broken graph, not a small update. GRAD-001 shipped four runs that reported done and
|
|
1401
|
+
# billed while training nothing, because this number was recorded and never read.
|
|
1402
|
+
# fail the run instead of paying for a zero adapter that then deploys and serves.
|
|
1403
|
+
if grad_norm == 0.0 and (learning_rate_value is None or learning_rate_value > 0.0):
|
|
1404
|
+
zero_grad_steps.append(int(progress["step"] or 0))
|
|
1405
|
+
if len(zero_grad_steps) >= _MAX_ZERO_GRAD_STEPS:
|
|
1406
|
+
raise RuntimeError(
|
|
1407
|
+
"verl reported train/grad_norm=0.0 with a nonzero learning rate on "
|
|
1408
|
+
f"{len(zero_grad_steps)} consecutive steps: no gradient is reaching the "
|
|
1409
|
+
"lora parameters, so this run would train nothing. see GRAD-001"
|
|
1410
|
+
)
|
|
1411
|
+
else:
|
|
1412
|
+
zero_grad_steps.clear()
|
|
1382
1413
|
if learning_rate_value is not None:
|
|
1383
1414
|
progress["lr"] = learning_rate_value
|
|
1384
1415
|
|
|
@@ -1402,6 +1433,14 @@ def run_sft_train(spec=None) -> None:
|
|
|
1402
1433
|
return_code = 0
|
|
1403
1434
|
if resume_step < update_horizon:
|
|
1404
1435
|
watcher.start()
|
|
1436
|
+
# completeness is only a meaningful question when training ran to the end. an on_line
|
|
1437
|
+
# callback that raises (the zero-grad guard above, the lora+ guard) unwinds BEFORE
|
|
1438
|
+
# return_code is assigned, so deriving the flag from return_code alone would leave it at
|
|
1439
|
+
# its initial 0 and demand every required save from a run that stopped at step 2. the
|
|
1440
|
+
# watcher would then raise "required saves were not durably published" from the finally
|
|
1441
|
+
# and REPLACE the diagnosis with a downstream symptom. opd_train tracks the same flag for
|
|
1442
|
+
# the same reason.
|
|
1443
|
+
training_completed = False
|
|
1405
1444
|
try:
|
|
1406
1445
|
with liveness_heartbeat(
|
|
1407
1446
|
"sft_step",
|
|
@@ -1415,8 +1454,9 @@ def run_sft_train(spec=None) -> None:
|
|
|
1415
1454
|
on_line=on_line,
|
|
1416
1455
|
heartbeat=child_heartbeat,
|
|
1417
1456
|
)
|
|
1457
|
+
training_completed = return_code == 0
|
|
1418
1458
|
finally:
|
|
1419
|
-
watcher.stop(require_complete=
|
|
1459
|
+
watcher.stop(require_complete=training_completed)
|
|
1420
1460
|
train_wall = time.time() - train_started_at
|
|
1421
1461
|
device_peak_gpu_gb = gpu_sampler.stop_gb()
|
|
1422
1462
|
if return_code != 0:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.64"
|
|
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).
|
|
@@ -123,7 +123,7 @@ artifacts = ["flash/py.typed"]
|
|
|
123
123
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
124
124
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
125
125
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
126
|
-
version = "1.0.
|
|
126
|
+
version = "1.0.64"
|
|
127
127
|
|
|
128
128
|
[tool.pytest.ini_options]
|
|
129
129
|
pythonpath = ["."]
|
|
@@ -1699,6 +1699,48 @@ def test_the_reentrant_shim_installs_vision_input_grads_only_for_multimodal_runs
|
|
|
1699
1699
|
assert rl_train.render_reentrant_checkpointing_shim(False, multimodal=True) == ""
|
|
1700
1700
|
|
|
1701
1701
|
|
|
1702
|
+
def test_the_reentrant_shim_enables_language_side_input_grads_before_checkpointing():
|
|
1703
|
+
"""GRAD-001: every rl run is lora, so lora freezes the embeddings and nothing entering the
|
|
1704
|
+
first checkpointed decoder layer requires grad. reentrant recompute then drops the backward
|
|
1705
|
+
for the whole segment -- where every lora parameter lives -- and the run reports success while
|
|
1706
|
+
training nothing. the vision hook only ever covered the patch embeddings on multimodal runs;
|
|
1707
|
+
text-only runs had no hook at all."""
|
|
1708
|
+
calls = []
|
|
1709
|
+
|
|
1710
|
+
class FakeModule:
|
|
1711
|
+
def enable_input_require_grads(self):
|
|
1712
|
+
calls.append("require_grads")
|
|
1713
|
+
|
|
1714
|
+
def gradient_checkpointing_enable(self, **kwargs):
|
|
1715
|
+
calls.append(("gc_enable", kwargs))
|
|
1716
|
+
|
|
1717
|
+
class FakeEngine:
|
|
1718
|
+
def __init__(self, checkpointing):
|
|
1719
|
+
self.model_config = SimpleNamespace(enable_gradient_checkpointing=checkpointing)
|
|
1720
|
+
|
|
1721
|
+
def _build_module(self):
|
|
1722
|
+
return FakeModule()
|
|
1723
|
+
|
|
1724
|
+
source = rl_train.render_reentrant_checkpointing_shim(True)
|
|
1725
|
+
start = source.index("def _flash_reentrant_build_module")
|
|
1726
|
+
end = source.index("_FlashReentrantEngine._build_module = _flash_reentrant_build_module")
|
|
1727
|
+
namespace = {"_flash_reentrant_original_build_module": FakeEngine._build_module}
|
|
1728
|
+
exec(compile(source[start:end], "sitecustomize.py", "exec"), namespace)
|
|
1729
|
+
build = namespace["_flash_reentrant_build_module"]
|
|
1730
|
+
|
|
1731
|
+
build(FakeEngine(checkpointing=True))
|
|
1732
|
+
# order matters: enabling checkpointing first captures the graph before any input requires
|
|
1733
|
+
# grad, so asserting mere presence would pass on a broken shim.
|
|
1734
|
+
assert calls[0] == "require_grads"
|
|
1735
|
+
assert calls[1] == ("gc_enable", {"gradient_checkpointing_kwargs": {"use_reentrant": True}})
|
|
1736
|
+
|
|
1737
|
+
# the guard is load-bearing: when verl left checkpointing OFF, touching the module at all
|
|
1738
|
+
# would turn on a feature verl deliberately declined and change the memory profile.
|
|
1739
|
+
calls.clear()
|
|
1740
|
+
build(FakeEngine(checkpointing=False))
|
|
1741
|
+
assert calls == []
|
|
1742
|
+
|
|
1743
|
+
|
|
1702
1744
|
@contextlib.contextmanager
|
|
1703
1745
|
def _vision_hook_installer(torch_module):
|
|
1704
1746
|
"""yield the rendered vision helper with a stand-in torch visible to it.
|
|
@@ -1831,6 +1873,10 @@ def test_the_reentrant_shim_flips_the_flag_and_leaves_uncheckpointed_models_alon
|
|
|
1831
1873
|
class _Module:
|
|
1832
1874
|
def __init__(self):
|
|
1833
1875
|
self.kwargs = None
|
|
1876
|
+
self.input_grads = False
|
|
1877
|
+
|
|
1878
|
+
def enable_input_require_grads(self):
|
|
1879
|
+
self.input_grads = True
|
|
1834
1880
|
|
|
1835
1881
|
def gradient_checkpointing_enable(self, gradient_checkpointing_kwargs=None):
|
|
1836
1882
|
self.kwargs = gradient_checkpointing_kwargs
|
|
@@ -1857,12 +1903,17 @@ def test_the_reentrant_shim_flips_the_flag_and_leaves_uncheckpointed_models_alon
|
|
|
1857
1903
|
sys.modules.setdefault(name, types.ModuleType(name))
|
|
1858
1904
|
sys.modules[module_stub.__name__] = module_stub
|
|
1859
1905
|
exec(rl_train.render_reentrant_checkpointing_shim(True), {})
|
|
1860
|
-
# checkpointing on -> the flag is put back to reentrant
|
|
1906
|
+
# checkpointing on -> the flag is put back to reentrant, and the lora-frozen embeddings
|
|
1907
|
+
# get input grads so the checkpointed segment actually produces a backward (GRAD-001)
|
|
1861
1908
|
engine = _Engine(True)
|
|
1862
|
-
|
|
1909
|
+
built = engine._build_module()
|
|
1910
|
+
assert built.kwargs == {"use_reentrant": True}
|
|
1911
|
+
assert built.input_grads is True
|
|
1863
1912
|
# checkpointing off -> untouched, so the shim cannot silently raise the memory profile
|
|
1864
1913
|
off = _Engine(False)
|
|
1865
|
-
|
|
1914
|
+
off_built = off._build_module()
|
|
1915
|
+
assert off_built.kwargs is None
|
|
1916
|
+
assert off_built.input_grads is False
|
|
1866
1917
|
finally:
|
|
1867
1918
|
for name, value in saved.items():
|
|
1868
1919
|
if value is None:
|
|
@@ -5,15 +5,18 @@ from __future__ import annotations
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import importlib.util
|
|
7
7
|
import os
|
|
8
|
+
import re
|
|
8
9
|
import sys
|
|
9
10
|
import types
|
|
10
11
|
from types import SimpleNamespace
|
|
11
12
|
|
|
12
13
|
import pytest
|
|
13
14
|
|
|
15
|
+
from flash.engine.worker.backend_common import parse_verl_metric
|
|
14
16
|
from flash.engine.worker.sft import _pretokenize_completion_only
|
|
15
17
|
from flash.engine.worker.sft_train import (
|
|
16
18
|
_LORAPLUS_READY_MARKER,
|
|
19
|
+
_MAX_ZERO_GRAD_STEPS,
|
|
17
20
|
_VERL_OPTIMIZER_IMPL,
|
|
18
21
|
_VERL_OPTIMIZER_NAME,
|
|
19
22
|
_build_verl_child_env,
|
|
@@ -478,6 +481,115 @@ def test_generated_sitecustomize_installs_linear_scheduler_and_required_loraplus
|
|
|
478
481
|
assert scheduler_calls == [("optimizer", {"num_warmup_steps": 2, "num_training_steps": 20})]
|
|
479
482
|
|
|
480
483
|
|
|
484
|
+
def test_reentrant_checkpointing_enables_input_grads_before_enabling_checkpointing():
|
|
485
|
+
"""GRAD-001: lora freezes the embeddings, so nothing entering the first checkpointed layer
|
|
486
|
+
requires grad and reentrant checkpointing returns no gradient at all. the shim must call
|
|
487
|
+
enable_input_require_grads() BEFORE gradient_checkpointing_enable(), or every sft run
|
|
488
|
+
trains nothing while reporting done and billing."""
|
|
489
|
+
calls = []
|
|
490
|
+
|
|
491
|
+
class FakeModule:
|
|
492
|
+
def enable_input_require_grads(self):
|
|
493
|
+
calls.append("require_grads")
|
|
494
|
+
|
|
495
|
+
def gradient_checkpointing_enable(self, **kwargs):
|
|
496
|
+
calls.append(("gc_enable", kwargs))
|
|
497
|
+
|
|
498
|
+
class FakeEngine:
|
|
499
|
+
def _build_module(self):
|
|
500
|
+
return FakeModule()
|
|
501
|
+
|
|
502
|
+
source = _render_sft_sitecustomize(
|
|
503
|
+
seed=1,
|
|
504
|
+
loraplus_ratio=16,
|
|
505
|
+
save_at_steps=(),
|
|
506
|
+
total_steps=4,
|
|
507
|
+
reentrant_gradient_checkpointing=True,
|
|
508
|
+
)
|
|
509
|
+
# execute only the reentrant block: the surrounding shim imports verl/torch at module scope.
|
|
510
|
+
block = source[source.index("def _flash_build_reentrant_module") :]
|
|
511
|
+
block = block[: block.index("_FlashFSDPEngine._build_module = _flash_build_reentrant_module")]
|
|
512
|
+
namespace = {"_flash_original_build_module": FakeEngine._build_module}
|
|
513
|
+
exec(compile(block, "shim.py", "exec"), namespace)
|
|
514
|
+
|
|
515
|
+
namespace["_flash_build_reentrant_module"](FakeEngine())
|
|
516
|
+
|
|
517
|
+
# order matters: enabling checkpointing first would capture the graph before any input
|
|
518
|
+
# requires grad, so asserting mere presence would pass on a broken shim.
|
|
519
|
+
assert calls[0] == "require_grads"
|
|
520
|
+
assert calls[1] == ("gc_enable", {"gradient_checkpointing_kwargs": {"use_reentrant": True}})
|
|
521
|
+
|
|
522
|
+
# the non-reentrant path never patches _build_module at all, so it must not appear.
|
|
523
|
+
non_reentrant = _render_sft_sitecustomize(
|
|
524
|
+
seed=1,
|
|
525
|
+
loraplus_ratio=16,
|
|
526
|
+
save_at_steps=(),
|
|
527
|
+
total_steps=4,
|
|
528
|
+
reentrant_gradient_checkpointing=False,
|
|
529
|
+
)
|
|
530
|
+
assert "enable_input_require_grads" not in non_reentrant
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def test_zero_grad_norm_at_nonzero_lr_fails_the_run():
|
|
534
|
+
"""GRAD-001: four runs reported done and charged while grad_norm was 0.0 on every step.
|
|
535
|
+
the number was parsed and recorded, never read. replay the real g4 log lines."""
|
|
536
|
+
|
|
537
|
+
def replay(lines):
|
|
538
|
+
zero_grad_steps: list[int] = []
|
|
539
|
+
for step, line in enumerate(lines):
|
|
540
|
+
grad_norm = parse_verl_metric(line, "train/grad_norm")
|
|
541
|
+
learning_rate_value = parse_verl_metric(line, "train/lr")
|
|
542
|
+
if grad_norm is None:
|
|
543
|
+
continue
|
|
544
|
+
if grad_norm == 0.0 and (learning_rate_value is None or learning_rate_value > 0.0):
|
|
545
|
+
zero_grad_steps.append(step)
|
|
546
|
+
if len(zero_grad_steps) >= _MAX_ZERO_GRAD_STEPS:
|
|
547
|
+
raise RuntimeError(
|
|
548
|
+
"verl reported train/grad_norm=0.0 with a nonzero learning rate on "
|
|
549
|
+
f"{len(zero_grad_steps)} consecutive steps: no gradient is reaching "
|
|
550
|
+
"the lora parameters, so this run would train nothing. see GRAD-001"
|
|
551
|
+
)
|
|
552
|
+
else:
|
|
553
|
+
zero_grad_steps.clear()
|
|
554
|
+
|
|
555
|
+
# verbatim shape of the g4 gsm8k lines (flash-1785592071-e56cf3c6): loss barely moves on a
|
|
556
|
+
# replayed identical batch because nothing is learning.
|
|
557
|
+
broken = [
|
|
558
|
+
"step:1 - train/loss:0.5470 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
559
|
+
"step:2 - train/loss:0.5437 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
560
|
+
"step:3 - train/loss:0.5474 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
561
|
+
"step:4 - train/loss:0.5444 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
562
|
+
]
|
|
563
|
+
with pytest.raises(RuntimeError, match=re.escape("grad_norm=0.0")):
|
|
564
|
+
replay(broken)
|
|
565
|
+
|
|
566
|
+
# a healthy run must not trip the guard.
|
|
567
|
+
replay(
|
|
568
|
+
[
|
|
569
|
+
"step:1 - train/loss:0.9 - train/grad_norm:1.4 - train/lr:0.0001",
|
|
570
|
+
"step:2 - train/loss:0.7 - train/grad_norm:0.9 - train/lr:0.0001",
|
|
571
|
+
]
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
# an isolated zero is a legitimately fully-masked micro-batch, not a severed graph.
|
|
575
|
+
replay(
|
|
576
|
+
[
|
|
577
|
+
"step:1 - train/loss:0.9 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
578
|
+
"step:2 - train/loss:0.7 - train/grad_norm:1.1 - train/lr:0.0001",
|
|
579
|
+
"step:3 - train/loss:0.6 - train/grad_norm:0.0 - train/lr:0.0001",
|
|
580
|
+
]
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
# a decayed schedule reaching lr 0.0 produces a legitimate zero grad norm.
|
|
584
|
+
replay(
|
|
585
|
+
[
|
|
586
|
+
"step:1 - train/loss:0.5 - train/grad_norm:0.0 - train/lr:0.0",
|
|
587
|
+
"step:2 - train/loss:0.5 - train/grad_norm:0.0 - train/lr:0.0",
|
|
588
|
+
"step:3 - train/loss:0.5 - train/grad_norm:0.0 - train/lr:0.0",
|
|
589
|
+
]
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
|
|
481
593
|
def test_loraplus_shim_has_no_plain_lora_fallback():
|
|
482
594
|
source = render_loraplus_shim(16)
|
|
483
595
|
assert _LORAPLUS_READY_MARKER in source
|
|
@@ -615,7 +727,11 @@ def test_resume_credits_only_required_saves_that_are_durable(monkeypatch):
|
|
|
615
727
|
assert sft_train._durable_required_save_steps((3, 5, 9), 5) == {3}
|
|
616
728
|
|
|
617
729
|
|
|
618
|
-
def
|
|
730
|
+
def _stub_sft_run(monkeypatch, *, save_at_steps=(), watcher_cls=None):
|
|
731
|
+
"""monkeypatch every out-of-process dependency of run_sft_train and return (spec, captured).
|
|
732
|
+
|
|
733
|
+
the caller supplies its own ``run_verl_training`` fake, which is the only remaining seam.
|
|
734
|
+
"""
|
|
619
735
|
import flash.engine.worker as worker
|
|
620
736
|
from flash.engine.worker import sft_train
|
|
621
737
|
|
|
@@ -630,7 +746,7 @@ def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypa
|
|
|
630
746
|
max_context_tokens=1024,
|
|
631
747
|
max_examples=2,
|
|
632
748
|
max_steps=2,
|
|
633
|
-
save_at_steps=
|
|
749
|
+
save_at_steps=save_at_steps,
|
|
634
750
|
save_every=50,
|
|
635
751
|
init_from_adapter="",
|
|
636
752
|
),
|
|
@@ -683,7 +799,7 @@ def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypa
|
|
|
683
799
|
def stop_gb(self):
|
|
684
800
|
return 12.5
|
|
685
801
|
|
|
686
|
-
class
|
|
802
|
+
class _DefaultWatcher:
|
|
687
803
|
def __init__(self, **kwargs):
|
|
688
804
|
self.processed_steps = set()
|
|
689
805
|
|
|
@@ -696,7 +812,25 @@ def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypa
|
|
|
696
812
|
def raise_if_failed(self):
|
|
697
813
|
return None
|
|
698
814
|
|
|
815
|
+
Watcher = watcher_cls or _DefaultWatcher
|
|
816
|
+
|
|
699
817
|
captured = {"heartbeats": [], "published": [], "uploads": []}
|
|
818
|
+
# run_sft_train imports AutoProcessor at data-loading time and transformers is not installed in
|
|
819
|
+
# the cpu test env. this used to pass only because some EARLIER test module left a transformers
|
|
820
|
+
# stub in sys.modules, so running this file alone failed -- stub it here so the test stands on
|
|
821
|
+
# its own. monkeypatch.setitem restores whatever was there (real module or nothing) afterwards.
|
|
822
|
+
monkeypatch.setitem(
|
|
823
|
+
sys.modules,
|
|
824
|
+
"transformers",
|
|
825
|
+
sys.modules.get("transformers")
|
|
826
|
+
or _module(
|
|
827
|
+
"transformers",
|
|
828
|
+
AutoProcessor=SimpleNamespace(from_pretrained=lambda *a, **k: None),
|
|
829
|
+
# datasets' dill serializer issubclass()-checks against this while writing the
|
|
830
|
+
# parquet, so it has to be a real class rather than a namespace attribute.
|
|
831
|
+
PreTrainedTokenizerBase=type("PreTrainedTokenizerBase", (), {}),
|
|
832
|
+
),
|
|
833
|
+
)
|
|
700
834
|
monkeypatch.delenv("WANDB_API_KEY", raising=False)
|
|
701
835
|
monkeypatch.setattr(worker, "SEED", 7)
|
|
702
836
|
monkeypatch.setattr(worker, "RUN_ID", "test-sft-verl-orchestration")
|
|
@@ -765,6 +899,14 @@ def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypa
|
|
|
765
899
|
|
|
766
900
|
monkeypatch.setattr(sft_train, "_export_checkpoint_adapter", fake_export)
|
|
767
901
|
|
|
902
|
+
return spec, captured
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypatch):
|
|
906
|
+
from flash.engine.worker import sft_train
|
|
907
|
+
|
|
908
|
+
spec, captured = _stub_sft_run(monkeypatch)
|
|
909
|
+
|
|
768
910
|
def fake_training(command, *, env, on_step, on_line, heartbeat):
|
|
769
911
|
captured["command"] = command
|
|
770
912
|
captured["child_env"] = env
|
|
@@ -798,6 +940,61 @@ def test_run_sft_train_orchestrates_exact_dataset_and_resume_accounting(monkeypa
|
|
|
798
940
|
assert captured["meta"]["notes"]["realized_max_length"] > 0
|
|
799
941
|
|
|
800
942
|
|
|
943
|
+
def test_a_guard_failure_is_not_replaced_by_the_watcher_completeness_error(monkeypatch):
|
|
944
|
+
"""the zero-grad diagnosis must survive the finally block, not be overwritten by it.
|
|
945
|
+
|
|
946
|
+
an on_line guard raises from INSIDE run_verl_training, so return_code is never assigned and
|
|
947
|
+
keeps its initial 0. deriving require_complete from it would then demand every save_at_steps
|
|
948
|
+
entry from a run that died at step 2, and the watcher's "required saves were not durably
|
|
949
|
+
published" would unwind out of the finally in place of the real cause -- turning the one
|
|
950
|
+
error GRAD-001 exists to surface into a checkpointing red herring.
|
|
951
|
+
"""
|
|
952
|
+
from flash.engine.worker import sft_train
|
|
953
|
+
|
|
954
|
+
stopped: list[bool] = []
|
|
955
|
+
|
|
956
|
+
class Watcher:
|
|
957
|
+
def __init__(self, **kwargs):
|
|
958
|
+
self.processed_steps = set()
|
|
959
|
+
self.required_steps = frozenset(kwargs.get("required_steps", ()))
|
|
960
|
+
|
|
961
|
+
def start(self):
|
|
962
|
+
return None
|
|
963
|
+
|
|
964
|
+
def raise_if_failed(self):
|
|
965
|
+
return None
|
|
966
|
+
|
|
967
|
+
def stop(self, *, require_complete):
|
|
968
|
+
stopped.append(require_complete)
|
|
969
|
+
if require_complete:
|
|
970
|
+
missing = sorted(self.required_steps - self.processed_steps)
|
|
971
|
+
if missing:
|
|
972
|
+
raise RuntimeError(f"required saves were not durably published: {missing}")
|
|
973
|
+
|
|
974
|
+
# a required save the run never durably publishes: the guard raises on the same step, before
|
|
975
|
+
# the watcher has processed it. (the step is inside the 2-update horizon because
|
|
976
|
+
# validate_save_steps rejects anything beyond it at config time.)
|
|
977
|
+
spec, _ = _stub_sft_run(monkeypatch, save_at_steps=(2,), watcher_cls=Watcher)
|
|
978
|
+
|
|
979
|
+
def fake_training(command, *, env, on_step, on_line, heartbeat):
|
|
980
|
+
on_line(f"{_LORAPLUS_READY_MARKER} ratio=16 optimizer=AdamW\n")
|
|
981
|
+
for step in range(1, _MAX_ZERO_GRAD_STEPS + 1):
|
|
982
|
+
on_line(
|
|
983
|
+
f"step:{step} - train/loss:1.0 - train/grad_norm:0.0 - train/lr:5e-05 "
|
|
984
|
+
"- train/global_tokens:8\n"
|
|
985
|
+
)
|
|
986
|
+
raise AssertionError("the zero-grad guard should have stopped the run before this")
|
|
987
|
+
|
|
988
|
+
monkeypatch.setattr(sft_train, "run_verl_training", fake_training)
|
|
989
|
+
|
|
990
|
+
with pytest.raises(RuntimeError, match=re.escape("grad_norm=0.0")):
|
|
991
|
+
sft_train.run_sft_train(spec)
|
|
992
|
+
|
|
993
|
+
# the watcher still gets stopped -- it just is not asked to prove completeness for a run that
|
|
994
|
+
# never finished. without this, stop() raises and the grad_norm error never reaches the caller.
|
|
995
|
+
assert stopped == [False]
|
|
996
|
+
|
|
997
|
+
|
|
801
998
|
def test_overrides_enable_fused_linear_ce_for_long_context():
|
|
802
999
|
# 32k contexts must not materialize [tokens, vocab] logits; the fused torch-backend
|
|
803
1000
|
# linear-CE computes loss from hidden states in chunks (numerically exact CE).
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/ISSUE_TEMPLATE/bug_report.yml
RENAMED
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/ISSUE_TEMPLATE/feature_request.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/bake-kernel-cache.yml
RENAMED
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/main-source-guard.yml
RENAMED
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/notify-tests-repo.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/.github/workflows/version-parity.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-1.0.63 → freesolo_flash_dev-1.0.64}/docker/Dockerfile.kernelcache.relayer
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|