freesolo-flash-dev 1.2.39__tar.gz → 1.2.43__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.39 → freesolo_flash_dev-1.2.43}/PKG-INFO +1 -1
- freesolo_flash_dev-1.2.43/flash/adapters/fused_experts.py +375 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/__init__.py +3 -3
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/model/adapter.py +15 -20
- freesolo_flash_dev-1.2.43/flash/engine/worker/model/lora.py +157 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/sft_train.py +3 -2
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/inputs.py +1 -1
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/checkpoints.py +21 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/preparation.py +2 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_adapter_shard_completeness.py +95 -4
- freesolo_flash_dev-1.2.43/tests/test_fused_expert_warmstart.py +651 -0
- freesolo_flash_dev-1.2.43/tests/test_lora_rank_preflight.py +623 -0
- freesolo_flash_dev-1.2.43/tests/test_vl_warmstart_adapter_keys.py +161 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_warmstart_adapter_download.py +10 -12
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_stack.py +11 -15
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/uv.lock +1 -1
- freesolo_flash_dev-1.2.39/flash/engine/worker/model/lora.py +0 -118
- freesolo_flash_dev-1.2.39/tests/test_lora_rank_preflight.py +0 -311
- freesolo_flash_dev-1.2.39/tests/test_vl_warmstart_adapter_keys.py +0 -83
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.env.example +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/README.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/shims.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/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.43
|
|
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
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"""Fused-expert LoRA targeting, validation, and export normalization."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from collections import Counter
|
|
7
|
+
from collections.abc import Mapping
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from flash.adapters.lora_rank import (
|
|
11
|
+
_rank_for_module,
|
|
12
|
+
declared_lora_ranks,
|
|
13
|
+
lora_tensor_rank_disagrees,
|
|
14
|
+
)
|
|
15
|
+
from flash.core.catalog import get_model
|
|
16
|
+
|
|
17
|
+
_QWEN36_MODEL_ID = "Qwen/Qwen3.6-35B-A3B"
|
|
18
|
+
_QWEN36_EXPERT_TARGET_PARAMETERS = (
|
|
19
|
+
"mlp.experts.gate_up_proj",
|
|
20
|
+
"mlp.experts.down_proj",
|
|
21
|
+
)
|
|
22
|
+
_QWEN36_FUSED_TARGET_DIMENSIONS = {
|
|
23
|
+
"mlp.experts.gate_up_proj": (2048, 1024),
|
|
24
|
+
"mlp.experts.down_proj": (512, 2048),
|
|
25
|
+
}
|
|
26
|
+
_QWEN36_FUSED_TARGET_RUNGS = {
|
|
27
|
+
"mlp.experts.down_proj": "",
|
|
28
|
+
"mlp.experts.gate_up_proj": "base_layer",
|
|
29
|
+
}
|
|
30
|
+
_FUSED_EXPERT_SYNTHETIC_MODULES = frozenset({"experts", "base_layer"})
|
|
31
|
+
_FUSED_EXPERT_WRAPPER_MODULES = ("mlp.experts", "mlp.experts.base_layer")
|
|
32
|
+
_INVALID_FUSED_LOCATION = object()
|
|
33
|
+
|
|
34
|
+
_LoraTensor = tuple[str, str, str, str, tuple[int, ...]]
|
|
35
|
+
_LoraPair = tuple[tuple[int, ...], tuple[int, ...]]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def lora_target_parameters(model_id: str | None) -> list[str] | None:
|
|
39
|
+
"""Return direct parameter targets required by the model's fused expert layout."""
|
|
40
|
+
if model_id == _QWEN36_MODEL_ID:
|
|
41
|
+
return list(_QWEN36_EXPERT_TARGET_PARAMETERS)
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def validate_fused_expert_adapter_config(config: Mapping[str, Any], model_id: str) -> None:
|
|
46
|
+
"""Validate the exact current adapter config required by a fused-expert model."""
|
|
47
|
+
required = lora_target_parameters(model_id)
|
|
48
|
+
if not required:
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
targets = config.get("target_parameters")
|
|
52
|
+
if not isinstance(targets, list):
|
|
53
|
+
raise ValueError(
|
|
54
|
+
f"adapter for {model_id} omits required expert targets; "
|
|
55
|
+
"target_parameters must be a list of strings"
|
|
56
|
+
)
|
|
57
|
+
if any(not isinstance(target, str) for target in targets):
|
|
58
|
+
raise ValueError(
|
|
59
|
+
f"adapter for {model_id} must declare target_parameters as a list of strings"
|
|
60
|
+
)
|
|
61
|
+
if len(targets) != len(set(targets)):
|
|
62
|
+
raise ValueError(f"adapter for {model_id} must declare unique target_parameters")
|
|
63
|
+
if set(targets) != set(required):
|
|
64
|
+
raise ValueError(
|
|
65
|
+
f"adapter for {model_id} must declare exactly the fused expert targets {required}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
rank_pattern = config.get("rank_pattern")
|
|
69
|
+
_validate_rank_pattern(rank_pattern, model_id)
|
|
70
|
+
declared = declared_lora_ranks(config)
|
|
71
|
+
unresolved = [target for target in required if _rank_for_module(target, declared) is None]
|
|
72
|
+
if unresolved:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"adapter for {model_id} has no resolved LoRA rank for fused targets {unresolved}"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
modules = config.get("target_modules")
|
|
78
|
+
if isinstance(modules, str):
|
|
79
|
+
if modules != "all-linear":
|
|
80
|
+
raise ValueError(f"adapter for {model_id} string target_modules must be 'all-linear'")
|
|
81
|
+
# all-linear names no modules, so only a default rank can resolve every ordinary target.
|
|
82
|
+
if declared.default is None:
|
|
83
|
+
raise ValueError(
|
|
84
|
+
f"adapter for {model_id} has no resolved default LoRA rank for 'all-linear' "
|
|
85
|
+
"target_modules"
|
|
86
|
+
)
|
|
87
|
+
return
|
|
88
|
+
if (
|
|
89
|
+
not isinstance(modules, list)
|
|
90
|
+
or not modules
|
|
91
|
+
or any(not isinstance(module, str) or not module for module in modules)
|
|
92
|
+
):
|
|
93
|
+
raise ValueError(
|
|
94
|
+
f"adapter for {model_id} target_modules must be 'all-linear' or a non-empty "
|
|
95
|
+
"list of non-empty strings"
|
|
96
|
+
)
|
|
97
|
+
synthetic = [module for module in modules if _targets_fused_expert_wrapper(module)]
|
|
98
|
+
if synthetic:
|
|
99
|
+
raise ValueError(
|
|
100
|
+
f"adapter for {model_id} contains invalid synthetic target_modules {sorted(synthetic)}"
|
|
101
|
+
)
|
|
102
|
+
unresolved = [module for module in modules if _rank_for_module(module, declared) is None]
|
|
103
|
+
if unresolved:
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"adapter for {model_id} has no resolved LoRA rank for ordinary target_modules "
|
|
106
|
+
f"{unresolved}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _validate_rank_pattern(rank_pattern: Any, model_id: str) -> None:
|
|
111
|
+
"""Validate positive ranks and PEFT's anchored regex pattern syntax."""
|
|
112
|
+
message = (
|
|
113
|
+
f"adapter for {model_id} rank_pattern must map valid non-empty string patterns "
|
|
114
|
+
"to positive integer ranks"
|
|
115
|
+
)
|
|
116
|
+
if rank_pattern is None:
|
|
117
|
+
return
|
|
118
|
+
if not isinstance(rank_pattern, Mapping):
|
|
119
|
+
raise ValueError(message)
|
|
120
|
+
for pattern, rank in rank_pattern.items():
|
|
121
|
+
if (
|
|
122
|
+
not isinstance(pattern, str)
|
|
123
|
+
or not pattern.strip()
|
|
124
|
+
or not isinstance(rank, int)
|
|
125
|
+
or isinstance(rank, bool)
|
|
126
|
+
or rank <= 0
|
|
127
|
+
):
|
|
128
|
+
raise ValueError(message)
|
|
129
|
+
try:
|
|
130
|
+
re.compile(rf"(.*\.)?({pattern})$")
|
|
131
|
+
except re.error as exc:
|
|
132
|
+
raise ValueError(message) from exc
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _targets_fused_expert_wrapper(module: str) -> bool:
|
|
136
|
+
"""Return whether PEFT suffix matching binds this target to an expert wrapper."""
|
|
137
|
+
return any(
|
|
138
|
+
module == wrapper or module.endswith(f".{wrapper}") or wrapper.endswith(f".{module}")
|
|
139
|
+
for wrapper in _FUSED_EXPERT_WRAPPER_MODULES
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def normalize_verl_fused_expert_export(config: dict[str, Any], model_id: str) -> None:
|
|
144
|
+
"""Write the canonical fused targets into a verl-exported adapter config."""
|
|
145
|
+
targets = lora_target_parameters(model_id)
|
|
146
|
+
if not targets:
|
|
147
|
+
return
|
|
148
|
+
config["target_parameters"] = targets
|
|
149
|
+
modules = config.get("target_modules")
|
|
150
|
+
if modules is None:
|
|
151
|
+
raise ValueError(
|
|
152
|
+
f"exported adapter for {model_id} must retain ordinary LoRA target_modules"
|
|
153
|
+
)
|
|
154
|
+
if isinstance(modules, list):
|
|
155
|
+
config["target_modules"] = [
|
|
156
|
+
module
|
|
157
|
+
for module in modules
|
|
158
|
+
if not isinstance(module, str) or module not in _FUSED_EXPERT_SYNTHETIC_MODULES
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def has_complete_fused_expert_tensors(
|
|
163
|
+
tensors: Mapping[str, tuple[int, ...]], config: Mapping[str, Any], model_id: str
|
|
164
|
+
) -> bool:
|
|
165
|
+
"""Return whether fused and ordinary LoRA tensors match the declared PEFT topology."""
|
|
166
|
+
expected = _expected_fused_expert_rungs(config, model_id)
|
|
167
|
+
if expected is None:
|
|
168
|
+
return False
|
|
169
|
+
parsed = [
|
|
170
|
+
tensor
|
|
171
|
+
for key, shape in tensors.items()
|
|
172
|
+
if (tensor := _parse_lora_tensor(key, shape)) is not None
|
|
173
|
+
]
|
|
174
|
+
if len({adapter_name for _, _, adapter_name, _, _ in parsed}) != 1:
|
|
175
|
+
return False
|
|
176
|
+
return _has_complete_fused_rungs(parsed, expected, model_id) and _has_ordinary_evidence(
|
|
177
|
+
parsed, config, expected
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _parse_lora_tensor(key: str, shape: tuple[int, ...]) -> _LoraTensor | None:
|
|
182
|
+
"""Parse one canonical PEFT LoRA tensor key."""
|
|
183
|
+
matches = [
|
|
184
|
+
(factor, infix) for factor, infix in (("A", ".lora_A."), ("B", ".lora_B.")) if infix in key
|
|
185
|
+
]
|
|
186
|
+
if len(matches) != 1:
|
|
187
|
+
return None
|
|
188
|
+
factor, infix = matches[0]
|
|
189
|
+
module_path, _, leaf = key.partition(infix)
|
|
190
|
+
leaf_parts = leaf.split(".")
|
|
191
|
+
if not module_path or len(leaf_parts) != 2:
|
|
192
|
+
return None
|
|
193
|
+
adapter_name, parameter = leaf_parts
|
|
194
|
+
if not adapter_name or parameter != "weight":
|
|
195
|
+
return None
|
|
196
|
+
return module_path, factor, adapter_name, key, shape
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _expected_fused_expert_rungs(
|
|
200
|
+
config: Mapping[str, Any], model_id: str
|
|
201
|
+
) -> dict[str, dict[str, _LoraPair]] | None:
|
|
202
|
+
"""Return the exact target-specific PEFT rung geometry for each fused owner."""
|
|
203
|
+
targets = lora_target_parameters(model_id)
|
|
204
|
+
if model_id != _QWEN36_MODEL_ID or not targets:
|
|
205
|
+
return None
|
|
206
|
+
model = get_model(model_id)
|
|
207
|
+
experts = model.lora_expert_count
|
|
208
|
+
if experts <= 0 or model.num_layers <= 0:
|
|
209
|
+
return None
|
|
210
|
+
fused_count = model.num_layers * experts
|
|
211
|
+
catalog_dimensions = Counter(
|
|
212
|
+
(input_dim, output_dim)
|
|
213
|
+
for input_dim, output_dim, count in model.lora_target_shapes
|
|
214
|
+
if count == fused_count
|
|
215
|
+
)
|
|
216
|
+
if catalog_dimensions != Counter(_QWEN36_FUSED_TARGET_DIMENSIONS.values()):
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
declared = declared_lora_ranks(config)
|
|
220
|
+
expected: dict[str, dict[str, _LoraPair]] = {}
|
|
221
|
+
for target in targets:
|
|
222
|
+
rank = _rank_for_module(target, declared)
|
|
223
|
+
dimensions = _QWEN36_FUSED_TARGET_DIMENSIONS.get(target)
|
|
224
|
+
rung = _QWEN36_FUSED_TARGET_RUNGS.get(target)
|
|
225
|
+
owner, separator, _ = target.rpartition(".")
|
|
226
|
+
if rank is None or dimensions is None or rung is None or not separator or not owner:
|
|
227
|
+
return None
|
|
228
|
+
input_dim, output_dim = dimensions
|
|
229
|
+
stacked_rank = rank * experts
|
|
230
|
+
expected.setdefault(owner, {})[rung] = (
|
|
231
|
+
(stacked_rank, input_dim),
|
|
232
|
+
(output_dim, stacked_rank),
|
|
233
|
+
)
|
|
234
|
+
return expected
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _has_complete_fused_rungs(
|
|
238
|
+
tensors: list[_LoraTensor], expected: Mapping[str, Mapping[str, _LoraPair]], model_id: str
|
|
239
|
+
) -> bool:
|
|
240
|
+
"""Validate every concrete fused owner, rung, namespace, and factor shape."""
|
|
241
|
+
model = get_model(model_id)
|
|
242
|
+
for owner, expected_rungs in expected.items():
|
|
243
|
+
factors: dict[str, dict[str, dict[str, dict[str, tuple[int, ...]]]]] = {}
|
|
244
|
+
for module_path, factor, adapter_name, _key, shape in tensors:
|
|
245
|
+
location = _fused_tensor_location(module_path, owner, frozenset(expected_rungs))
|
|
246
|
+
if location is _INVALID_FUSED_LOCATION:
|
|
247
|
+
return False
|
|
248
|
+
if location is None:
|
|
249
|
+
continue
|
|
250
|
+
instance, rung = location
|
|
251
|
+
factors.setdefault(instance, {}).setdefault(rung, {}).setdefault(adapter_name, {})[
|
|
252
|
+
factor
|
|
253
|
+
] = shape
|
|
254
|
+
if not factors:
|
|
255
|
+
return False
|
|
256
|
+
for seen_rungs in factors.values():
|
|
257
|
+
if set(seen_rungs) != set(expected_rungs):
|
|
258
|
+
return False
|
|
259
|
+
for rung, expected_pair in expected_rungs.items():
|
|
260
|
+
namespaces = seen_rungs[rung]
|
|
261
|
+
if len(namespaces) != 1:
|
|
262
|
+
return False
|
|
263
|
+
seen_factors = next(iter(namespaces.values()))
|
|
264
|
+
if _lora_pair_shapes(seen_factors) != expected_pair:
|
|
265
|
+
return False
|
|
266
|
+
expert_layers = {
|
|
267
|
+
prefix
|
|
268
|
+
for instance in factors
|
|
269
|
+
for prefix in [_layer_prefix(instance)]
|
|
270
|
+
if prefix is not None
|
|
271
|
+
}
|
|
272
|
+
layer_roots = {prefix.rsplit(".", 1)[0] for prefix in expert_layers}
|
|
273
|
+
if len(layer_roots) != 1:
|
|
274
|
+
return False
|
|
275
|
+
layer_root = next(iter(layer_roots))
|
|
276
|
+
expected_layers = {f"{layer_root}.{index}" for index in range(model.num_layers)}
|
|
277
|
+
if expert_layers != expected_layers:
|
|
278
|
+
return False
|
|
279
|
+
return True
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _fused_tensor_location(
|
|
283
|
+
module_path: str, owner: str, rungs: frozenset[str]
|
|
284
|
+
) -> tuple[str, str] | object | None:
|
|
285
|
+
"""Locate one tensor on an exact concrete fused owner rung."""
|
|
286
|
+
if module_path.endswith(f".{owner}"):
|
|
287
|
+
instance, rung = module_path[: -len(owner) - 1], ""
|
|
288
|
+
else:
|
|
289
|
+
marker = f".{owner}."
|
|
290
|
+
if marker not in module_path:
|
|
291
|
+
return None
|
|
292
|
+
instance, rung = module_path.rsplit(marker, 1)
|
|
293
|
+
if rung not in rungs:
|
|
294
|
+
return _INVALID_FUSED_LOCATION
|
|
295
|
+
layer_prefix = _layer_prefix(instance)
|
|
296
|
+
if layer_prefix is None or instance != layer_prefix:
|
|
297
|
+
return _INVALID_FUSED_LOCATION
|
|
298
|
+
return f"{instance}.{owner}", rung
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _has_ordinary_evidence(
|
|
302
|
+
tensors: list[_LoraTensor],
|
|
303
|
+
config: Mapping[str, Any],
|
|
304
|
+
fused_rungs: Mapping[str, Mapping[str, _LoraPair]],
|
|
305
|
+
) -> bool:
|
|
306
|
+
"""Validate concrete ordinary target evidence with per-module ranks and namespaces."""
|
|
307
|
+
modules = config.get("target_modules")
|
|
308
|
+
all_linear = modules == "all-linear"
|
|
309
|
+
targets = () if all_linear else tuple(modules) if isinstance(modules, list) else ()
|
|
310
|
+
groups: dict[str, dict[str, dict[str, tuple[str, tuple[int, ...]]]]] = {}
|
|
311
|
+
evidence: set[str] = set()
|
|
312
|
+
for module_path, factor, adapter_name, key, shape in tensors:
|
|
313
|
+
if _is_fused_rung(module_path, fused_rungs):
|
|
314
|
+
continue
|
|
315
|
+
matched = tuple(target for target in targets if _anchored_suffix_match(module_path, target))
|
|
316
|
+
if not all_linear and not matched:
|
|
317
|
+
continue
|
|
318
|
+
evidence.update(matched)
|
|
319
|
+
groups.setdefault(module_path, {}).setdefault(adapter_name, {})[factor] = (key, shape)
|
|
320
|
+
if not groups or (not all_linear and evidence != set(targets)):
|
|
321
|
+
return False
|
|
322
|
+
|
|
323
|
+
declared = declared_lora_ranks(config)
|
|
324
|
+
for module_path, namespaces in groups.items():
|
|
325
|
+
if len(namespaces) != 1 or _rank_for_module(module_path, declared) is None:
|
|
326
|
+
return False
|
|
327
|
+
factors = next(iter(namespaces.values()))
|
|
328
|
+
if set(factors) != {"A", "B"}:
|
|
329
|
+
return False
|
|
330
|
+
for key, shape in factors.values():
|
|
331
|
+
if not _is_positive_2d(shape) or lora_tensor_rank_disagrees(key, shape, declared):
|
|
332
|
+
return False
|
|
333
|
+
return True
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _is_fused_rung(module_path: str, fused_rungs: Mapping[str, Mapping[str, _LoraPair]]) -> bool:
|
|
337
|
+
"""Return whether a module path is one of the exact fused wrapper rungs."""
|
|
338
|
+
return any(
|
|
339
|
+
_fused_tensor_location(module_path, owner, frozenset(rungs))
|
|
340
|
+
not in (None, _INVALID_FUSED_LOCATION)
|
|
341
|
+
for owner, rungs in fused_rungs.items()
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _anchored_suffix_match(module_path: str, target: str) -> bool:
|
|
346
|
+
"""Mirror PEFT list-target matching without accepting partial segment suffixes."""
|
|
347
|
+
return module_path == target or module_path.endswith(f".{target}")
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _is_positive_2d(shape: tuple[int, ...]) -> bool:
|
|
351
|
+
"""Return whether a tensor shape is positive, integral, and two-dimensional."""
|
|
352
|
+
return len(shape) == 2 and all(
|
|
353
|
+
isinstance(dimension, int) and not isinstance(dimension, bool) and dimension > 0
|
|
354
|
+
for dimension in shape
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _lora_pair_shapes(factors: Mapping[str, tuple[int, ...]]) -> _LoraPair | None:
|
|
359
|
+
"""Return one complete positive 2-D A/B shape pair."""
|
|
360
|
+
if set(factors) != {"A", "B"}:
|
|
361
|
+
return None
|
|
362
|
+
shape_a = factors["A"]
|
|
363
|
+
shape_b = factors["B"]
|
|
364
|
+
if not _is_positive_2d(shape_a) or not _is_positive_2d(shape_b):
|
|
365
|
+
return None
|
|
366
|
+
return shape_a, shape_b
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _layer_prefix(path: str) -> str | None:
|
|
370
|
+
"""Return the concrete ``...layers.N`` prefix in a tensor path, if present."""
|
|
371
|
+
segments = path.split(".")
|
|
372
|
+
for index in range(len(segments) - 2, -1, -1):
|
|
373
|
+
if segments[index] == "layers" and segments[index + 1].isdigit():
|
|
374
|
+
return ".".join(segments[: index + 2])
|
|
375
|
+
return None
|
|
@@ -17,6 +17,7 @@ import time
|
|
|
17
17
|
import traceback
|
|
18
18
|
|
|
19
19
|
from flash._internal.diagnostics import sanitize_diagnostic
|
|
20
|
+
from flash.adapters.fused_experts import lora_target_parameters
|
|
20
21
|
from flash.core.spec import FIXED_SEED, load_job_spec_from_env
|
|
21
22
|
from flash.engine.result.accounting import RunMetrics
|
|
22
23
|
from flash.engine.worker.backend_common import collect_ray_failure_logs
|
|
@@ -56,9 +57,8 @@ from flash.engine.worker.io.wandb_log import (
|
|
|
56
57
|
)
|
|
57
58
|
from flash.engine.worker.model.adapter import (
|
|
58
59
|
_download_adapter,
|
|
59
|
-
lora_target_parameters,
|
|
60
60
|
make_lora,
|
|
61
|
-
|
|
61
|
+
validate_warmstart_adapter,
|
|
62
62
|
)
|
|
63
63
|
from flash.engine.worker.model.decoding import (
|
|
64
64
|
graded_text,
|
|
@@ -503,7 +503,7 @@ __all__ = [
|
|
|
503
503
|
"think_token_count",
|
|
504
504
|
"thinking_text",
|
|
505
505
|
"upload_resume_checkpoint",
|
|
506
|
-
"
|
|
506
|
+
"validate_warmstart_adapter",
|
|
507
507
|
"wait_for_gpu",
|
|
508
508
|
"wandb_run_name",
|
|
509
509
|
"write_base_model_provenance",
|
{freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/model/adapter.py
RENAMED
|
@@ -5,7 +5,14 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
7
|
import shutil
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
from typing import Any
|
|
8
10
|
|
|
11
|
+
from flash.adapters.fused_experts import (
|
|
12
|
+
has_complete_fused_expert_tensors,
|
|
13
|
+
lora_target_parameters,
|
|
14
|
+
validate_fused_expert_adapter_config,
|
|
15
|
+
)
|
|
9
16
|
from flash.adapters.lora_rank import resolve_adapter_ref
|
|
10
17
|
from flash.engine.plan.recipe import RECIPE
|
|
11
18
|
from flash.engine.worker.io.hf import (
|
|
@@ -17,35 +24,23 @@ from flash.engine.worker.io.hf import (
|
|
|
17
24
|
)
|
|
18
25
|
from flash.engine.worker.model.lora import (
|
|
19
26
|
_read_adapter_tensor_keys,
|
|
27
|
+
_read_adapter_tensor_metadata,
|
|
20
28
|
)
|
|
21
29
|
from flash.engine.worker.runtime.pkg_proxy import W as _w
|
|
22
30
|
|
|
23
31
|
_ADAPTER_DOWNLOAD_RETRIES = 4
|
|
24
32
|
_ADAPTER_DOWNLOAD_BACKOFF_S = 5.0
|
|
25
|
-
_QWEN35_EXPERT_TARGET_PARAMETERS = (
|
|
26
|
-
"mlp.experts.gate_up_proj",
|
|
27
|
-
"mlp.experts.down_proj",
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def lora_target_parameters(model_id: str | None) -> list[str] | None:
|
|
32
|
-
"""return direct parameter targets required by the model's fused expert layout."""
|
|
33
|
-
if model_id == "Qwen/Qwen3.6-35B-A3B":
|
|
34
|
-
return list(_QWEN35_EXPERT_TARGET_PARAMETERS)
|
|
35
|
-
return None
|
|
36
33
|
|
|
37
34
|
|
|
38
|
-
def
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
if not
|
|
35
|
+
def validate_warmstart_adapter(config: Mapping[str, Any], model_id: str, adapter_dir: str) -> None:
|
|
36
|
+
"""Validate a downloaded warm-start adapter without changing its config or files."""
|
|
37
|
+
validate_fused_expert_adapter_config(config, model_id)
|
|
38
|
+
if not lora_target_parameters(model_id):
|
|
42
39
|
return
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if missing:
|
|
40
|
+
tensors = _read_adapter_tensor_metadata(adapter_dir) or {}
|
|
41
|
+
if not has_complete_fused_expert_tensors(tensors, config, model_id):
|
|
46
42
|
raise ValueError(
|
|
47
|
-
f"warm-start adapter for {model_id}
|
|
48
|
-
"retrain the source adapter with the current Flash version"
|
|
43
|
+
f"warm-start adapter for {model_id} does not contain complete fused expert LoRA weights"
|
|
49
44
|
)
|
|
50
45
|
|
|
51
46
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""read adapter tensor metadata from a downloaded adapter directory.
|
|
2
|
+
|
|
3
|
+
helpers must not import ``flash.engine.worker``. heavy dependencies remain lazy so this leaf
|
|
4
|
+
module has no package cycle or eager gpu stack import.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
# a safetensors header is small even for huge models (a few hundred kb at most); 100 mb is a wildly
|
|
10
|
+
# generous ceiling that still refuses a corrupt or hostile file declaring a multi-gb header length
|
|
11
|
+
# before safetensors parses it.
|
|
12
|
+
_MAX_SAFETENSORS_HEADER_BYTES = 100 * 1024 * 1024
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _read_adapter_tensor_metadata(adir: str) -> dict[str, tuple[int, ...]] | None:
|
|
16
|
+
"""return the authoritative tensor name and shape map for the representation peft loads.
|
|
17
|
+
|
|
18
|
+
safetensors is validated through ``safe_open`` and ``get_slice`` without materializing tensor
|
|
19
|
+
payloads. torch ``.bin`` files use weights-only cpu loading because their format has no separate
|
|
20
|
+
metadata header. for sharded adapters, the index ``weight_map`` must agree exactly with every
|
|
21
|
+
selected shard header; no duplicate, missing, extra, or misrouted key is accepted.
|
|
22
|
+
"""
|
|
23
|
+
import os
|
|
24
|
+
|
|
25
|
+
from flash.adapters.artifacts import loadable_adapter_weight_files
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
selected = loadable_adapter_weight_files(os.listdir(adir))
|
|
29
|
+
except OSError:
|
|
30
|
+
return None
|
|
31
|
+
if not selected:
|
|
32
|
+
return None
|
|
33
|
+
weight_map = _read_sharded_weight_map(adir, selected)
|
|
34
|
+
tensors: dict[str, tuple[int, ...]] = {}
|
|
35
|
+
for name in selected:
|
|
36
|
+
path = os.path.join(adir, name)
|
|
37
|
+
shard_tensors = (
|
|
38
|
+
_read_safetensors_tensor_metadata(path)
|
|
39
|
+
if name.endswith(".safetensors")
|
|
40
|
+
else _read_bin_tensor_metadata(path)
|
|
41
|
+
)
|
|
42
|
+
duplicates = tensors.keys() & shard_tensors.keys()
|
|
43
|
+
if duplicates:
|
|
44
|
+
raise ValueError(
|
|
45
|
+
f"adapter shards contain duplicate tensor keys {sorted(duplicates)[:4]}"
|
|
46
|
+
)
|
|
47
|
+
if weight_map is not None:
|
|
48
|
+
misrouted = [key for key in shard_tensors if weight_map.get(key) != name]
|
|
49
|
+
if misrouted:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
f"adapter shard {name} disagrees with weight_map for keys {misrouted[:4]}"
|
|
52
|
+
)
|
|
53
|
+
tensors.update(shard_tensors)
|
|
54
|
+
if weight_map is not None and tensors.keys() != weight_map.keys():
|
|
55
|
+
missing = sorted(weight_map.keys() - tensors.keys())[:4]
|
|
56
|
+
extra = sorted(tensors.keys() - weight_map.keys())[:4]
|
|
57
|
+
raise ValueError(
|
|
58
|
+
f"adapter shard headers disagree with weight_map; missing={missing}, extra={extra}"
|
|
59
|
+
)
|
|
60
|
+
return tensors
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _read_adapter_tensor_keys(adir: str) -> list[str] | None:
|
|
64
|
+
"""return tensor key names from adapter weights without loading safetensors payloads."""
|
|
65
|
+
tensors = _read_adapter_tensor_metadata(adir)
|
|
66
|
+
return list(tensors) if tensors is not None else None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _read_sharded_weight_map(adir: str, selected: list[str]) -> dict[str, str] | None:
|
|
70
|
+
"""return an authoritative sharded index map, or none for a selected single-file adapter."""
|
|
71
|
+
import json
|
|
72
|
+
import os
|
|
73
|
+
|
|
74
|
+
from flash._internal.fileio import reject_duplicate_keys
|
|
75
|
+
from flash.adapters.artifacts import ADAPTER_SHARD_PREFIX
|
|
76
|
+
|
|
77
|
+
if not selected[0].startswith(ADAPTER_SHARD_PREFIX):
|
|
78
|
+
return None
|
|
79
|
+
suffix = ".safetensors" if selected[0].endswith(".safetensors") else ".bin"
|
|
80
|
+
index_path = os.path.join(adir, f"adapter_model{suffix}.index.json")
|
|
81
|
+
duplicate_guard = reject_duplicate_keys(
|
|
82
|
+
lambda key: ValueError(f"{index_path}: duplicate JSON key {key!r}")
|
|
83
|
+
)
|
|
84
|
+
try:
|
|
85
|
+
with open(index_path, encoding="utf-8") as index_file:
|
|
86
|
+
index = json.load(index_file, object_pairs_hook=duplicate_guard)
|
|
87
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
88
|
+
raise ValueError(f"{index_path}: unreadable adapter weight index") from exc
|
|
89
|
+
weight_map = index.get("weight_map") if isinstance(index, dict) else None
|
|
90
|
+
if not isinstance(weight_map, dict) or any(
|
|
91
|
+
not isinstance(key, str) or not key or not isinstance(shard, str) or not shard
|
|
92
|
+
for key, shard in weight_map.items()
|
|
93
|
+
):
|
|
94
|
+
raise ValueError(f"{index_path}: weight_map must map non-empty tensor names to shard names")
|
|
95
|
+
selected_set = set(selected)
|
|
96
|
+
referenced = set(weight_map.values())
|
|
97
|
+
if referenced != selected_set:
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"{index_path}: weight_map shards {sorted(referenced)} do not match selected shards "
|
|
100
|
+
f"{sorted(selected_set)}"
|
|
101
|
+
)
|
|
102
|
+
return weight_map
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _read_safetensors_tensor_metadata(st_path: str) -> dict[str, tuple[int, ...]]:
|
|
106
|
+
"""return names and shapes after safetensors validates the complete file structure."""
|
|
107
|
+
import os
|
|
108
|
+
import struct
|
|
109
|
+
|
|
110
|
+
file_size = os.path.getsize(st_path)
|
|
111
|
+
with open(st_path, "rb") as tensor_file:
|
|
112
|
+
length_bytes = tensor_file.read(8)
|
|
113
|
+
if len(length_bytes) < 8:
|
|
114
|
+
raise ValueError(f"{st_path}: too small to be a safetensors file")
|
|
115
|
+
(header_length,) = struct.unpack("<Q", length_bytes)
|
|
116
|
+
if header_length > file_size - 8 or header_length > _MAX_SAFETENSORS_HEADER_BYTES:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f"{st_path}: declared safetensors header length {header_length} is implausible "
|
|
119
|
+
f"(file is {file_size} bytes)"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
from safetensors import safe_open
|
|
124
|
+
|
|
125
|
+
with safe_open(st_path, framework="numpy") as tensors:
|
|
126
|
+
metadata: dict[str, tuple[int, ...]] = {}
|
|
127
|
+
tensor_keys = tensors.keys()
|
|
128
|
+
for key in tensor_keys:
|
|
129
|
+
shape = tensors.get_slice(key).get_shape()
|
|
130
|
+
if not isinstance(shape, list) or any(
|
|
131
|
+
not isinstance(dim, int) or isinstance(dim, bool) or dim < 0 for dim in shape
|
|
132
|
+
):
|
|
133
|
+
raise ValueError(f"invalid tensor shape for {key!r}")
|
|
134
|
+
metadata[key] = tuple(shape)
|
|
135
|
+
return metadata
|
|
136
|
+
except Exception as exc:
|
|
137
|
+
raise ValueError(f"{st_path}: invalid safetensors structure ({exc})") from exc
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _read_bin_tensor_metadata(bin_path: str) -> dict[str, tuple[int, ...]]:
|
|
141
|
+
"""return the tensor names and shapes in one torch ``.bin`` adapter state dict."""
|
|
142
|
+
import torch
|
|
143
|
+
|
|
144
|
+
state = torch.load(bin_path, map_location="cpu", weights_only=True)
|
|
145
|
+
if not isinstance(state, dict):
|
|
146
|
+
raise ValueError(f"{bin_path}: expected a tensor state dict, got {type(state).__name__}")
|
|
147
|
+
bad = [
|
|
148
|
+
key
|
|
149
|
+
for key, value in state.items()
|
|
150
|
+
if not isinstance(key, str) or not isinstance(value, torch.Tensor)
|
|
151
|
+
]
|
|
152
|
+
if bad:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"{bin_path}: contains non-tensor entries (e.g. {bad[:4]}); "
|
|
155
|
+
"expected a plain PEFT adapter state dict"
|
|
156
|
+
)
|
|
157
|
+
return {key: tuple(tensor.shape) for key, tensor in state.items()}
|
|
@@ -14,6 +14,7 @@ import sys
|
|
|
14
14
|
import threading
|
|
15
15
|
import time
|
|
16
16
|
|
|
17
|
+
from flash.adapters.lora_rank import rank_from_adapter_config
|
|
17
18
|
from flash.engine.worker.runtime.pkg_proxy import W as _w
|
|
18
19
|
from flash.engine.worker.verl.checkpoints import resume_checkpoint_is_loadable
|
|
19
20
|
from flash.engine.worker.verl.parallelism import ULYSSES_SEQUENCE_PARALLEL_SIZE
|
|
@@ -61,13 +62,13 @@ def _warmstart_adapter_path(model_id: str, model_revision: str, expected_rank: i
|
|
|
61
62
|
raise RuntimeError("the prepared SFT warm-start adapter could not be downloaded")
|
|
62
63
|
with open(os.path.join(adapter_dir, "adapter_config.json"), encoding="utf-8") as file:
|
|
63
64
|
config = json.load(file)
|
|
64
|
-
rank =
|
|
65
|
+
rank = rank_from_adapter_config(config, source=os.path.join(adapter_dir, "adapter_config.json"))
|
|
65
66
|
if rank != expected_rank:
|
|
66
67
|
raise ValueError(
|
|
67
68
|
f"SFT warm-start adapter rank {rank} does not match the prepared train.lora_rank "
|
|
68
69
|
f"{expected_rank}; rank changes are not supported"
|
|
69
70
|
)
|
|
70
|
-
_w.
|
|
71
|
+
_w.validate_warmstart_adapter(config, model_id, adapter_dir)
|
|
71
72
|
base = str(config.get("base_model_name_or_path") or "").strip()
|
|
72
73
|
if base and base != model_id:
|
|
73
74
|
raise ValueError("SFT warm-start adapter base model does not match the target model")
|
{freesolo_flash_dev-1.2.39 → freesolo_flash_dev-1.2.43}/flash/engine/worker/train/rl/inputs.py
RENAMED
|
@@ -172,7 +172,7 @@ def _resolve_grpo_options(train_spec, rl, multi_turn):
|
|
|
172
172
|
def _resolve_warmstart_config(train_spec, model_id, adapter_path, lora_rank, lora_alpha):
|
|
173
173
|
with open(os.path.join(adapter_path, "adapter_config.json")) as f:
|
|
174
174
|
source_config = json.load(f)
|
|
175
|
-
_w.
|
|
175
|
+
_w.validate_warmstart_adapter(source_config, model_id, adapter_path)
|
|
176
176
|
# a patterned adapter trains some modules at higher rank than the base `r`; verl allocates
|
|
177
177
|
# one uniform rank, so it must cover the MAXIMUM prepared rank or the load truncates.
|
|
178
178
|
ranks = [int(source_config.get("r", lora_rank))]
|