freesolo-flash-dev 1.2.12__tar.gz → 1.2.13__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.12 → freesolo_flash_dev-1.2.13}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/lora_rank.py +113 -2
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/catalog.py +13 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/multiturn.py +15 -3
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/multi_turn.py +103 -16
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/shims.py +15 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/export.py +75 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/preflight.py +37 -10
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_smoke.py +9 -3
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_export.py +358 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_rl_train.py +199 -1
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_envs_coverage.py +84 -13
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.env.example +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/README.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/preparation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/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.13
|
|
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
|
|
@@ -7,11 +7,11 @@ import json
|
|
|
7
7
|
import math
|
|
8
8
|
import re
|
|
9
9
|
from collections.abc import Callable, Mapping
|
|
10
|
-
from dataclasses import dataclass
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
11
|
from decimal import Decimal, InvalidOperation
|
|
12
12
|
from typing import TYPE_CHECKING, Any
|
|
13
13
|
|
|
14
|
-
from flash.core.catalog import serving_context_cap, serving_lora_rank_cap
|
|
14
|
+
from flash.core.catalog import lora_expert_count, serving_context_cap, serving_lora_rank_cap
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ServingPreflightError(ValueError):
|
|
@@ -279,6 +279,117 @@ def rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
|
|
|
279
279
|
)
|
|
280
280
|
|
|
281
281
|
|
|
282
|
+
_LORA_A_INFIX = ".lora_A."
|
|
283
|
+
_LORA_B_INFIX = ".lora_B."
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@dataclass(frozen=True)
|
|
287
|
+
class DeclaredLoraRanks:
|
|
288
|
+
"""The default rank, per-module overrides, and parameter-target module paths in a config."""
|
|
289
|
+
|
|
290
|
+
default: int | None = None
|
|
291
|
+
by_module: Mapping[str, int] = field(default_factory=dict)
|
|
292
|
+
stacked_rank_modules: tuple[str, ...] = ()
|
|
293
|
+
stacked_rank_multiplier: int | None = None
|
|
294
|
+
|
|
295
|
+
def __bool__(self) -> bool:
|
|
296
|
+
return self.default is not None or bool(self.by_module)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def declared_lora_ranks(config: Mapping[str, Any]) -> DeclaredLoraRanks:
|
|
300
|
+
"""Read the per-module LoRA rank structure out of ``adapter_config.json``."""
|
|
301
|
+
if not isinstance(config, Mapping):
|
|
302
|
+
return DeclaredLoraRanks()
|
|
303
|
+
try:
|
|
304
|
+
default = _positive_int(config["r"], source="adapter_config.json", field="r")
|
|
305
|
+
except (KeyError, ValueError):
|
|
306
|
+
default = None
|
|
307
|
+
|
|
308
|
+
by_module: dict[str, int] = {}
|
|
309
|
+
pattern = config.get("rank_pattern")
|
|
310
|
+
if isinstance(pattern, Mapping):
|
|
311
|
+
for module, value in pattern.items():
|
|
312
|
+
try:
|
|
313
|
+
by_module[str(module)] = _positive_int(
|
|
314
|
+
value, source="adapter_config.json", field="rank_pattern"
|
|
315
|
+
)
|
|
316
|
+
except ValueError:
|
|
317
|
+
continue
|
|
318
|
+
|
|
319
|
+
stacked_rank_modules: list[str] = []
|
|
320
|
+
targets = config.get("target_parameters")
|
|
321
|
+
if isinstance(targets, list):
|
|
322
|
+
for target in targets:
|
|
323
|
+
if not isinstance(target, str):
|
|
324
|
+
continue
|
|
325
|
+
module, separator, _ = target.rpartition(".")
|
|
326
|
+
if separator and module:
|
|
327
|
+
stacked_rank_modules.append(module)
|
|
328
|
+
|
|
329
|
+
base_model = str(config.get("base_model_name_or_path") or "").strip()
|
|
330
|
+
return DeclaredLoraRanks(
|
|
331
|
+
default=default,
|
|
332
|
+
by_module=by_module,
|
|
333
|
+
stacked_rank_modules=tuple(stacked_rank_modules),
|
|
334
|
+
stacked_rank_multiplier=lora_expert_count(base_model),
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | None:
|
|
339
|
+
"""Resolve a module's rank with PEFT's ordered, anchored ``rank_pattern`` matching."""
|
|
340
|
+
for module, rank in declared.by_module.items():
|
|
341
|
+
if not module:
|
|
342
|
+
continue
|
|
343
|
+
try:
|
|
344
|
+
# entries are regexes in PEFT, deliberately not escaped here either
|
|
345
|
+
if re.match(rf"(.*\.)?({module})$", module_path):
|
|
346
|
+
return rank
|
|
347
|
+
except re.error:
|
|
348
|
+
continue
|
|
349
|
+
return declared.default
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _module_uses_target_parameters(module_path: str, declared: DeclaredLoraRanks) -> bool:
|
|
353
|
+
"""Whether this serialized module came from one of PEFT's targeted parameters."""
|
|
354
|
+
return any(
|
|
355
|
+
module_path == module or module_path.endswith(f".{module}")
|
|
356
|
+
for module in declared.stacked_rank_modules
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def lora_tensor_rank_disagrees(key: str, shape: Any, declared: DeclaredLoraRanks) -> bool:
|
|
361
|
+
"""Return whether a 2-D LoRA weight provably contradicts its configured rank.
|
|
362
|
+
|
|
363
|
+
Ordinary module weights carry exactly ``r`` on the LoRA axis. A 3-D parameter targeted through
|
|
364
|
+
PEFT's ``target_parameters`` serializes under its parent module and stacks every model expert on
|
|
365
|
+
that axis, so only that module may carry exactly ``r * num_experts``. The distinction must be per
|
|
366
|
+
module because one config may contain ordinary ``target_modules`` and fused parameters together.
|
|
367
|
+
"""
|
|
368
|
+
if not declared:
|
|
369
|
+
return False
|
|
370
|
+
is_a = _LORA_A_INFIX in key
|
|
371
|
+
is_b = _LORA_B_INFIX in key
|
|
372
|
+
if is_a == is_b: # neither, or a key somehow claiming both
|
|
373
|
+
return False
|
|
374
|
+
if not isinstance(shape, (list, tuple)) or len(shape) != 2:
|
|
375
|
+
return False
|
|
376
|
+
dims = [d for d in shape if isinstance(d, int) and not isinstance(d, bool) and d > 0]
|
|
377
|
+
if len(dims) != 2:
|
|
378
|
+
return False
|
|
379
|
+
|
|
380
|
+
infix = _LORA_A_INFIX if is_a else _LORA_B_INFIX
|
|
381
|
+
module_path = key.partition(infix)[0]
|
|
382
|
+
rank = _rank_for_module(module_path, declared)
|
|
383
|
+
if rank is None:
|
|
384
|
+
return False
|
|
385
|
+
axis = dims[0] if is_a else dims[1]
|
|
386
|
+
if _module_uses_target_parameters(module_path, declared):
|
|
387
|
+
multiplier = declared.stacked_rank_multiplier
|
|
388
|
+
expected = rank * multiplier if multiplier is not None else rank
|
|
389
|
+
return axis != expected
|
|
390
|
+
return axis != rank
|
|
391
|
+
|
|
392
|
+
|
|
282
393
|
def alpha_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
|
|
283
394
|
"""Return the maximum LoRA alpha across default and per-module metadata."""
|
|
284
395
|
return _max_adapter_value(
|
|
@@ -148,6 +148,9 @@ class ModelInfo:
|
|
|
148
148
|
mamba_block_size: int = 0
|
|
149
149
|
# grouped (in_features, out_features, count) for peft all-linear on the full loaded model.
|
|
150
150
|
lora_target_shapes: tuple[tuple[int, int, int], ...] = ()
|
|
151
|
+
# fused routed experts stacked on the lora rank axis for target_parameters. zero means no
|
|
152
|
+
# catalog-backed stacked allowance; ordinary and unknown target parameters carry exactly r.
|
|
153
|
+
lora_expert_count: int = 0
|
|
151
154
|
|
|
152
155
|
@property
|
|
153
156
|
def is_moe(self) -> bool:
|
|
@@ -174,6 +177,7 @@ class ModelInfo:
|
|
|
174
177
|
"linear_value_head_dim",
|
|
175
178
|
"linear_conv_kernel_dim",
|
|
176
179
|
"lora_target_shapes",
|
|
180
|
+
"lora_expert_count",
|
|
177
181
|
):
|
|
178
182
|
data.pop(key, None)
|
|
179
183
|
serving = data["serving"]
|
|
@@ -500,6 +504,7 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
500
504
|
(4608, 2048, 1),
|
|
501
505
|
(4608, 4608, 1),
|
|
502
506
|
),
|
|
507
|
+
lora_expert_count=256,
|
|
503
508
|
vocab_size=248_320,
|
|
504
509
|
algos=ALGORITHMS,
|
|
505
510
|
min_vram_gb=141,
|
|
@@ -569,6 +574,14 @@ def serving_lora_rank_cap(model: str | ModelInfo | None) -> int | None:
|
|
|
569
574
|
return int(info.serving.max_lora_rank)
|
|
570
575
|
|
|
571
576
|
|
|
577
|
+
def lora_expert_count(model: str | ModelInfo | None) -> int | None:
|
|
578
|
+
"""Return the exact fused-expert stack size for LoRA target parameters, when cataloged."""
|
|
579
|
+
info = _model_info_for_serving(model)
|
|
580
|
+
if info is None or info.lora_expert_count <= 0:
|
|
581
|
+
return None
|
|
582
|
+
return int(info.lora_expert_count)
|
|
583
|
+
|
|
584
|
+
|
|
572
585
|
def serving_context_cap(model: str | ModelInfo | None) -> int | None:
|
|
573
586
|
"""Return the model's served ``max_model_len``, or None without a local serving entry.
|
|
574
587
|
|
|
@@ -62,11 +62,23 @@ def post_json(url: str, path: str, payload: dict) -> dict:
|
|
|
62
62
|
with urllib.request.urlopen(request) as response:
|
|
63
63
|
body = response.read()
|
|
64
64
|
except urllib.error.HTTPError as error:
|
|
65
|
+
# decode inside the guard, raise outside it: `suppress(Exception)` around the raise as well
|
|
66
|
+
# swallowed the detail-bearing RuntimeError it was meant to let through, so the bridge's own
|
|
67
|
+
# error text ("can't start new thread") could never reach the user and every failure read as
|
|
68
|
+
# a bare "returned HTTP 400".
|
|
69
|
+
detail = None
|
|
65
70
|
with contextlib.suppress(Exception):
|
|
66
|
-
detail = json.loads(error.read().decode("utf-8"))["error"]
|
|
67
|
-
|
|
71
|
+
detail = str(json.loads(error.read().decode("utf-8"))["error"])
|
|
72
|
+
# 5xx is the bridge failing to serve a valid request (resource exhaustion); 4xx is this
|
|
73
|
+
# request being rejected. naming which one it was stops a server fault from being read as a
|
|
74
|
+
# malformed payload.
|
|
75
|
+
fault = "could not serve" if error.code >= 500 else "rejected"
|
|
76
|
+
if detail:
|
|
77
|
+
raise RuntimeError(
|
|
78
|
+
f"flash multi-turn bridge {fault} {path} (HTTP {error.code}): {detail}"
|
|
79
|
+
) from error
|
|
68
80
|
raise RuntimeError(
|
|
69
|
-
f"flash multi-turn bridge
|
|
81
|
+
f"flash multi-turn bridge {fault} {path}: HTTP {error.code} with no error detail"
|
|
70
82
|
) from error
|
|
71
83
|
except (OSError, http.client.HTTPException) as error:
|
|
72
84
|
raise RuntimeError(
|
{freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/multi_turn.py
RENAMED
|
@@ -39,6 +39,70 @@ _SINGLE_TURN_SCORE_BATCH_SIZE = 64
|
|
|
39
39
|
_SINGLE_TURN_SCORE_FLUSH_WAIT_S = 0.1
|
|
40
40
|
_SINGLE_TURN_SCORE_SHUTDOWN_WAIT_S = 5.0
|
|
41
41
|
|
|
42
|
+
# a body that could not be decoded at all: bad Content-Length, bad utf-8, or bad json.
|
|
43
|
+
_UNDECODABLE_BODY_ERRORS = (ValueError, TypeError, UnicodeDecodeError)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class _BadRequest(Exception):
|
|
47
|
+
"""A request THIS BRIDGE is deliberately rejecting because the request itself is wrong.
|
|
48
|
+
|
|
49
|
+
Raised by the validating code rather than inferred from exception type at the handler, which
|
|
50
|
+
cannot distinguish the bridge rejecting a bad index from a user env raising IndexError inside
|
|
51
|
+
its own scoring -- and reporting the latter as a client error is the bug the 503 split fixes.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class _BadIndex(_BadRequest, IndexError):
|
|
56
|
+
"""An index outside the dataset. Also an IndexError: that is what it genuinely is."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class _BadSession(_BadRequest, KeyError):
|
|
60
|
+
"""An unknown or duplicate session id. Also a KeyError, for the same reason.
|
|
61
|
+
|
|
62
|
+
``KeyError.__str__`` reprs its argument, which would double-quote the message; this reports the
|
|
63
|
+
message as written so the client sees the same text every other rejection produces.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __str__(self) -> str:
|
|
67
|
+
return self.args[0] if self.args else ""
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _request_field(payload: dict, key: str):
|
|
71
|
+
"""Read one required payload field, or reject the request.
|
|
72
|
+
|
|
73
|
+
A decoded body that is not an object at all (``[]``, ``"x"``, ``3``) is a malformed request, so
|
|
74
|
+
it is rejected here rather than raising TypeError out of the subscript and reading as a fault.
|
|
75
|
+
"""
|
|
76
|
+
if not isinstance(payload, dict):
|
|
77
|
+
raise _BadRequest(f"request body must be a json object, got {type(payload).__name__}")
|
|
78
|
+
try:
|
|
79
|
+
return payload[key]
|
|
80
|
+
except KeyError as exc:
|
|
81
|
+
raise _BadRequest(f"missing required field {key!r}") from exc
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def request_int(payload: dict, key: str) -> int:
|
|
85
|
+
"""Read one required integer payload field, or reject the request."""
|
|
86
|
+
value = _request_field(payload, key)
|
|
87
|
+
try:
|
|
88
|
+
return int(value)
|
|
89
|
+
# OverflowError: json decodes 1e309 to inf, and int(inf) overflows rather than ValueError-ing.
|
|
90
|
+
except (TypeError, ValueError, OverflowError) as exc:
|
|
91
|
+
raise _BadRequest(f"field {key!r} is not an integer: {value!r}") from exc
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def request_session_id(payload: dict) -> str:
|
|
95
|
+
"""Read the required session id, or reject the request."""
|
|
96
|
+
return str(_request_field(payload, "session_id"))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ONLY the bridge's own deliberate rejections are client errors. classifying by exception TYPE
|
|
100
|
+
# instead cannot work: a user env raising IndexError/KeyError deep inside its own scoring would be
|
|
101
|
+
# reported as a malformed request -- the same "blame the caller for this side's failure" bug this
|
|
102
|
+
# module's 503 split exists to fix, one layer down. so the rejecting code raises _BadRequest itself
|
|
103
|
+
# and anything else reaching the handler is this side failing to serve a well-formed request.
|
|
104
|
+
_BAD_REQUEST_ERRORS = (_BadRequest,)
|
|
105
|
+
|
|
42
106
|
# size the listen backlog for the full prompts_per_step * group_size connection burst.
|
|
43
107
|
# socketserver's default of 5 resets overflowed clients, and bridge_post intentionally does not retry.
|
|
44
108
|
# a fixed backlog only moves the cliff; linux may clamp this value to somaxconn.
|
|
@@ -113,10 +177,10 @@ class MultiTurnBridge:
|
|
|
113
177
|
self._scorer.close(_MULTI_TURN_SCORE_SHUTDOWN_WAIT_S)
|
|
114
178
|
|
|
115
179
|
def _session(self, payload: dict) -> dict:
|
|
116
|
-
session_id =
|
|
180
|
+
session_id = request_session_id(payload)
|
|
117
181
|
session = self._sessions.get(session_id)
|
|
118
182
|
if session is None:
|
|
119
|
-
raise
|
|
183
|
+
raise _BadSession(f"unknown multi-turn session {session_id}")
|
|
120
184
|
# every touch renews the lease, so only a session nobody is driving can ever age out. all
|
|
121
185
|
# callers already hold the lock.
|
|
122
186
|
session["touched_at"] = time.monotonic()
|
|
@@ -137,12 +201,12 @@ class MultiTurnBridge:
|
|
|
137
201
|
return stale
|
|
138
202
|
|
|
139
203
|
def start(self, payload: dict) -> dict:
|
|
140
|
-
index =
|
|
204
|
+
index = request_int(payload, "index")
|
|
141
205
|
if index < 0 or index >= len(self._examples):
|
|
142
|
-
raise
|
|
206
|
+
raise _BadIndex(
|
|
143
207
|
f"multi-turn example index {index} is outside [0, {len(self._examples)})"
|
|
144
208
|
)
|
|
145
|
-
session_id =
|
|
209
|
+
session_id = request_session_id(payload)
|
|
146
210
|
example = self._examples[index]
|
|
147
211
|
with self._lock:
|
|
148
212
|
# swept here rather than on a timer thread: a session is only ever abandoned by an
|
|
@@ -150,7 +214,7 @@ class MultiTurnBridge:
|
|
|
150
214
|
# exactly here. no extra thread, and nothing to shut down.
|
|
151
215
|
reaped = self._reap_abandoned_sessions()
|
|
152
216
|
if session_id in self._sessions:
|
|
153
|
-
raise
|
|
217
|
+
raise _BadSession(f"duplicate multi-turn session {session_id}")
|
|
154
218
|
state = self._env.new_rollout_state(example)
|
|
155
219
|
# new_rollout_state calls start_episode again after dataset preparation. adopt the dataset's
|
|
156
220
|
# prompt so randomized envs do not generate for episode a and score episode b; keep the
|
|
@@ -216,7 +280,7 @@ class MultiTurnBridge:
|
|
|
216
280
|
return score_rollouts(self._env, requests)
|
|
217
281
|
|
|
218
282
|
def score(self, payload: dict) -> dict:
|
|
219
|
-
turn_count =
|
|
283
|
+
turn_count = request_int(payload, "turn_count")
|
|
220
284
|
with self._lock:
|
|
221
285
|
session = self._session(payload)
|
|
222
286
|
state = session["state"]
|
|
@@ -282,7 +346,7 @@ class MultiTurnBridge:
|
|
|
282
346
|
|
|
283
347
|
def close(self, payload: dict) -> dict:
|
|
284
348
|
with self._lock:
|
|
285
|
-
self._sessions.pop(
|
|
349
|
+
self._sessions.pop(request_session_id(payload), None)
|
|
286
350
|
return {"closed": True}
|
|
287
351
|
|
|
288
352
|
def open_sessions(self) -> int:
|
|
@@ -371,9 +435,9 @@ def start_reward_server(
|
|
|
371
435
|
)
|
|
372
436
|
|
|
373
437
|
def _score_route(payload: dict) -> dict:
|
|
374
|
-
index =
|
|
438
|
+
index = request_int(payload, "index")
|
|
375
439
|
if index < 0 or index >= example_count:
|
|
376
|
-
raise
|
|
440
|
+
raise _BadIndex(f"reward example index {index} is outside [0, {example_count})")
|
|
377
441
|
solution_str = payload.get("solution_str", "")
|
|
378
442
|
if score_batcher is not None:
|
|
379
443
|
return {"score": float(score_batcher.submit((index, solution_str)))}
|
|
@@ -397,14 +461,37 @@ def start_reward_server(
|
|
|
397
461
|
try:
|
|
398
462
|
n = int(self.headers.get("Content-Length", "0"))
|
|
399
463
|
payload = json.loads(self.rfile.read(n).decode("utf-8"))
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
body = json.dumps({"error": str(exc)}).encode()
|
|
404
|
-
self.send_response(400)
|
|
464
|
+
except _UNDECODABLE_BODY_ERRORS as exc:
|
|
465
|
+
status = 400
|
|
466
|
+
detail = f"{type(exc).__name__}: {exc}"
|
|
405
467
|
else:
|
|
468
|
+
try:
|
|
469
|
+
result = route(payload)
|
|
470
|
+
except _BAD_REQUEST_ERRORS as exc:
|
|
471
|
+
# the request itself is wrong: a malformed field, an index outside the dataset,
|
|
472
|
+
# or an unknown/duplicate session. no retry or capacity change makes it succeed.
|
|
473
|
+
# reported without the internal class name -- the message already says what is
|
|
474
|
+
# wrong, and "_BadIndex:" only names a private type the caller cannot act on.
|
|
475
|
+
status = 400
|
|
476
|
+
detail = str(exc)
|
|
477
|
+
except Exception as exc:
|
|
478
|
+
# the request was fine and this side could not serve it -- thread exhaustion
|
|
479
|
+
# ("can't start new thread") under rollout concurrency is the case that drove
|
|
480
|
+
# this split. 400 blamed the caller's payload and sent every reader to score
|
|
481
|
+
# code that cannot produce one, so a resource fault reads as a 5xx here.
|
|
482
|
+
status = 503
|
|
483
|
+
detail = f"{type(exc).__name__}: {exc}"
|
|
484
|
+
else:
|
|
485
|
+
status = 200
|
|
486
|
+
if status == 200:
|
|
406
487
|
body = json.dumps(result).encode()
|
|
407
|
-
|
|
488
|
+
else:
|
|
489
|
+
print(
|
|
490
|
+
f"[rl-verl] reward server request failed ({status}) for {self.path}: {detail}",
|
|
491
|
+
flush=True,
|
|
492
|
+
)
|
|
493
|
+
body = json.dumps({"error": detail}).encode()
|
|
494
|
+
self.send_response(status)
|
|
408
495
|
self.send_header("Content-Type", "application/json")
|
|
409
496
|
self.send_header("Content-Length", str(len(body)))
|
|
410
497
|
self.end_headers()
|
{freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/shims.py
RENAMED
|
@@ -618,6 +618,21 @@ def render_reward_module(url_env: str = "FLASH_VERL_REWARD_URL") -> str:
|
|
|
618
618
|
" with urllib.request.urlopen(req) as r:\n"
|
|
619
619
|
" payload = json.loads(r.read().decode())\n"
|
|
620
620
|
" return float(payload['score'])\n"
|
|
621
|
+
# HTTPError is a URLError subclass, so it must be handled FIRST or the bridge's own error
|
|
622
|
+
# text -- the reason the request failed, e.g. "can't start new thread" -- is dropped for a
|
|
623
|
+
# bare "HTTP Error 503: Service Unavailable" that names no cause.
|
|
624
|
+
" except urllib.error.HTTPError as exc:\n"
|
|
625
|
+
" detail = ''\n"
|
|
626
|
+
" try:\n"
|
|
627
|
+
" detail = str(json.loads(exc.read().decode())['error'])\n"
|
|
628
|
+
" except Exception:\n"
|
|
629
|
+
" detail = ''\n"
|
|
630
|
+
" fault = 'could not serve' if exc.code >= 500 else 'rejected'\n"
|
|
631
|
+
" if detail:\n"
|
|
632
|
+
" raise RuntimeError('flash reward bridge %s the request (HTTP %s): %s'\n"
|
|
633
|
+
" % (fault, exc.code, detail)) from exc\n"
|
|
634
|
+
" raise RuntimeError('flash reward bridge %s the request: HTTP %s with no error detail'\n"
|
|
635
|
+
" % (fault, exc.code)) from exc\n"
|
|
621
636
|
" except urllib.error.URLError as exc:\n"
|
|
622
637
|
" raise RuntimeError('flash reward bridge request failed: %s' % exc) from exc\n"
|
|
623
638
|
" except Exception as exc:\n"
|
|
@@ -27,6 +27,11 @@ from flash.adapters.artifacts import (
|
|
|
27
27
|
has_loadable_adapter_weights,
|
|
28
28
|
is_adapter_weight_filename,
|
|
29
29
|
)
|
|
30
|
+
from flash.adapters.lora_rank import (
|
|
31
|
+
DeclaredLoraRanks,
|
|
32
|
+
declared_lora_ranks,
|
|
33
|
+
lora_tensor_rank_disagrees,
|
|
34
|
+
)
|
|
30
35
|
from flash.serve.deploy import ServingError
|
|
31
36
|
|
|
32
37
|
logger = get_logger(__name__)
|
|
@@ -395,6 +400,9 @@ def _normalize_adapter_key_namespace(adapter_dir: Path) -> str:
|
|
|
395
400
|
raise ValueError("no adapter_model weight file to normalize")
|
|
396
401
|
if paths[0].name.endswith(".safetensors"):
|
|
397
402
|
scans = [_scan_safetensors(path) for path in paths]
|
|
403
|
+
# before any rewrite: the shapes are what they are, and an adapter whose tensors contradict
|
|
404
|
+
# its own config is unloadable regardless of which key namespace it ends up in.
|
|
405
|
+
_verify_export_tensor_ranks(adapter_dir, scans)
|
|
398
406
|
elif any(_bin_may_carry_infixed_keys(path) for path in paths):
|
|
399
407
|
# one shard mentioning the infix commits every shard to a full scan. liveness and
|
|
400
408
|
# post-rename collisions are properties of the union of the shards, so a shard that never
|
|
@@ -445,6 +453,9 @@ def _normalize_export_adapter_keys(adapter_dir: Path) -> str:
|
|
|
445
453
|
"""
|
|
446
454
|
try:
|
|
447
455
|
return _normalize_adapter_key_namespace(adapter_dir)
|
|
456
|
+
except _AdapterRankMismatch:
|
|
457
|
+
# a self-contradicting adapter, not an unreadable key namespace. reported as itself.
|
|
458
|
+
raise
|
|
448
459
|
except Exception as exc:
|
|
449
460
|
raise ServingError(
|
|
450
461
|
f"could not normalize exported adapter keys ({exc}); refusing to export weights "
|
|
@@ -452,6 +463,70 @@ def _normalize_export_adapter_keys(adapter_dir: Path) -> str:
|
|
|
452
463
|
) from exc
|
|
453
464
|
|
|
454
465
|
|
|
466
|
+
class _AdapterRankMismatch(ValueError):
|
|
467
|
+
"""The adapter's tensors contradict its own config, so it is unloadable as published.
|
|
468
|
+
|
|
469
|
+
Distinct from the errors `_normalize_export_adapter_keys` wraps: that wrapper reports a key
|
|
470
|
+
namespace it could not normalize, which is a different defect with a different remedy, and
|
|
471
|
+
letting this one be reported as that would send the user looking in the wrong place. A
|
|
472
|
+
ValueError so it reaches the export route as a 404 beside the sibling "no loadable LoRA
|
|
473
|
+
adapter" refusal, rather than as a 502 that blames the Hub for a bad artifact.
|
|
474
|
+
"""
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _declared_export_ranks(adapter_dir: Path) -> DeclaredLoraRanks:
|
|
478
|
+
"""The rank structure ``adapter_config.json`` declares, or an empty one we cannot judge from.
|
|
479
|
+
|
|
480
|
+
Empty rather than an error: a config carrying no readable rank is the pre-existing shape of
|
|
481
|
+
every fixture and of adapters PEFT wrote without one, and export has never required it. The
|
|
482
|
+
check below exists to catch a config and its tensors DISAGREEING, which needs both halves.
|
|
483
|
+
"""
|
|
484
|
+
try:
|
|
485
|
+
config = json.loads((adapter_dir / "adapter_config.json").read_text(encoding="utf-8"))
|
|
486
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError):
|
|
487
|
+
return DeclaredLoraRanks()
|
|
488
|
+
return declared_lora_ranks(config) if isinstance(config, dict) else DeclaredLoraRanks()
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _verify_export_tensor_ranks(adapter_dir: Path, scans: list[_WeightScan]) -> None:
|
|
492
|
+
"""Refuse an export whose LoRA tensors do not carry the rank its config declares.
|
|
493
|
+
|
|
494
|
+
A serving engine sizes its LoRA slots from ``adapter_config.json`` and then binds the tensors,
|
|
495
|
+
so the two disagreeing is not a cosmetic metadata bug: it is an adapter that cannot be loaded.
|
|
496
|
+
That is not hypothetical -- a 35B MoE SFT run published `r: 32` beside expert tensors export
|
|
497
|
+
checked only for presence and key-namespace readability, so it succeeded and printed a Hub URL
|
|
498
|
+
while deploying the identical artifact failed. Export exiting 0 is what made a broken adapter
|
|
499
|
+
look like a finished deliverable.
|
|
500
|
+
|
|
501
|
+
`lora_tensor_rank_disagrees` resolves the rank PER MODULE the way PEFT does, so a
|
|
502
|
+
`rank_pattern` override is judged against its own rank rather than a summary of the config.
|
|
503
|
+
|
|
504
|
+
Only safetensors headers are read, because they carry shapes as metadata and are already parsed
|
|
505
|
+
here. A `.bin` would have to be loaded through torch, which the control plane does not install,
|
|
506
|
+
and paying that cost is not warranted for a representation the trainer no longer writes.
|
|
507
|
+
"""
|
|
508
|
+
declared = _declared_export_ranks(adapter_dir)
|
|
509
|
+
if not declared:
|
|
510
|
+
return
|
|
511
|
+
mismatched = [
|
|
512
|
+
f"{key} has shape {descriptor.get('shape')}"
|
|
513
|
+
for scan in scans
|
|
514
|
+
for key, descriptor in (scan.header or {}).items()
|
|
515
|
+
if key != "__metadata__"
|
|
516
|
+
and isinstance(descriptor, dict)
|
|
517
|
+
and lora_tensor_rank_disagrees(key, descriptor.get("shape"), declared)
|
|
518
|
+
]
|
|
519
|
+
if not mismatched:
|
|
520
|
+
return
|
|
521
|
+
shown = ", ".join(sorted(mismatched)[:3])
|
|
522
|
+
raise _AdapterRankMismatch(
|
|
523
|
+
f"adapter_config.json declares r={declared.default} but {len(mismatched)} LoRA tensor(s) "
|
|
524
|
+
f"do not carry the rank configured for their module (e.g. {shown}); a serving engine sizes "
|
|
525
|
+
"its LoRA slots from the config, so this adapter cannot be loaded and exporting it would "
|
|
526
|
+
"publish a broken artifact"
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
|
|
455
530
|
def _rewrite_adapter_config_base_model(
|
|
456
531
|
adapter_dir: Path, base_model: str, base_model_revision: str = ""
|
|
457
532
|
) -> bool:
|
|
@@ -18,6 +18,17 @@ from flash.engine.plan.vram import opd_completion_len
|
|
|
18
18
|
|
|
19
19
|
SERVING_PROMPT_TOKEN_ALLOWANCE = 256
|
|
20
20
|
|
|
21
|
+
# ceiling on what one deployment smoke may generate, independent of whatever the run trains at.
|
|
22
|
+
# the smoke asks a fixed trivial question under a wall clock that must ALSO cover cold-starting the
|
|
23
|
+
# base model and loading the adapter, so a budget inherited from training spends that deadline on
|
|
24
|
+
# tokens nobody reads: an sft run raised to an 8192 context asked a thinking 27B for 8192 tokens and
|
|
25
|
+
# timed out the deployment. that also coupled the knobs the wrong way, since raising
|
|
26
|
+
# max_context_tokens to avoid training truncation made the run harder to deploy.
|
|
27
|
+
# sized at the largest thinking budget any algorithm resolves to by default, so no
|
|
28
|
+
# default-configured run is smoked at less than it is today, and a generation that still hits this
|
|
29
|
+
# has failed to answer a trivial prompt rather than run out of room.
|
|
30
|
+
SMOKE_COMPLETION_TOKEN_CEILING = 2048
|
|
31
|
+
|
|
21
32
|
|
|
22
33
|
class ExternalSchemaReference(ValueError):
|
|
23
34
|
def __init__(self, ref: str) -> None:
|
|
@@ -68,21 +79,15 @@ def validate_structured_output_patterns(constraint: dict) -> None:
|
|
|
68
79
|
raise ValueError(f"{field} is invalid: {exc}") from exc
|
|
69
80
|
|
|
70
81
|
|
|
71
|
-
def
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
This sizes a single smoke request, not the run's training context. sft is the reason the two
|
|
75
|
-
cannot share a number: an sft run has no completion budget of its own, because the worker trains
|
|
76
|
-
one packed prompt+completion block bounded by ``max_context_tokens``.
|
|
77
|
-
"""
|
|
82
|
+
def _run_completion_budget(spec: JobSpec) -> int:
|
|
83
|
+
"""The completion budget the run itself trains at, before the smoke's own ceiling applies."""
|
|
78
84
|
explicit = spec.train.max_completion_tokens
|
|
79
85
|
positive_explicit = int(explicit) if explicit is not None and int(explicit) > 0 else None
|
|
80
86
|
if spec.algorithm == "opd":
|
|
81
87
|
return opd_completion_len(positive_explicit, spec.thinking)
|
|
82
88
|
if spec.algorithm == "sft":
|
|
83
|
-
# SFT ignores max_completion_tokens, so mirror the worker: use explicit max_context_tokens
|
|
84
|
-
# the recipe fallback.
|
|
85
|
-
# under-allocation can reject a valid checkpoint. serving clamps the final request.
|
|
89
|
+
# SFT ignores max_completion_tokens, so mirror the worker: use explicit max_context_tokens
|
|
90
|
+
# with the recipe fallback.
|
|
86
91
|
context = spec.train.max_context_tokens
|
|
87
92
|
if context is not None and int(context) > 0:
|
|
88
93
|
return int(context)
|
|
@@ -93,6 +98,28 @@ def resolve_smoke_completion_tokens(spec: JobSpec) -> int:
|
|
|
93
98
|
return int(recipe.max_completion_len_thinking if spec.thinking else recipe.max_completion_len)
|
|
94
99
|
|
|
95
100
|
|
|
101
|
+
def resolve_smoke_completion_tokens(spec: JobSpec, *, constrained: bool = False) -> int:
|
|
102
|
+
"""Resolve the deployment smoke's completion budget for one generation.
|
|
103
|
+
|
|
104
|
+
This sizes a single smoke request, not the run's training context, and the two are deliberately
|
|
105
|
+
decoupled: the smoke's question is fixed and trivial, so what a run trains at says nothing about
|
|
106
|
+
how many tokens answering it needs. Taking the run's number verbatim let a long training context
|
|
107
|
+
spend the smoke's whole wall-clock budget generating, which is why the ceiling exists.
|
|
108
|
+
|
|
109
|
+
A configured grammar is exempt. Deployment registers it as the adapter's serving default, so the
|
|
110
|
+
smoke generates under it too, and the shortest string it admits can exceed the ceiling -- a long
|
|
111
|
+
``choice``, a fixed-repetition ``regex``, a schema with a large ``minLength``. Capping there
|
|
112
|
+
would truncate the only legal answer and reject an adapter that serves correctly. Deciding that
|
|
113
|
+
from the constraint needs the tokenizer and a minimum-length analysis of three grammar dialects,
|
|
114
|
+
so the run's own budget stands in for it: the run trains within that number, so it bounds the
|
|
115
|
+
grammar it was trained to satisfy.
|
|
116
|
+
"""
|
|
117
|
+
budget = _run_completion_budget(spec)
|
|
118
|
+
if constrained:
|
|
119
|
+
return budget
|
|
120
|
+
return min(budget, SMOKE_COMPLETION_TOKEN_CEILING)
|
|
121
|
+
|
|
122
|
+
|
|
96
123
|
def resolve_effective_completion_tokens(spec: JobSpec) -> int | None:
|
|
97
124
|
"""Resolve the completion budget the serving context guard must fit, if the run has one.
|
|
98
125
|
|
{freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_smoke.py
RENAMED
|
@@ -332,10 +332,16 @@ def _run_deployment_smoke(
|
|
|
332
332
|
train = getattr(spec, "train", None)
|
|
333
333
|
constraint = parse_structured_outputs(getattr(train, "structured_outputs", ""))
|
|
334
334
|
max_tokens = 256
|
|
335
|
-
# thinking spends tokens before content
|
|
336
|
-
#
|
|
335
|
+
# thinking spends tokens before content regardless of grammar, so 256 can truncate the think
|
|
336
|
+
# block and reject a healthy deployment. the resolver widens it to what the run reasons within,
|
|
337
|
+
# bounded by a smoke-specific ceiling -- this budget is spent from the same wall clock that must
|
|
338
|
+
# also cold-start the base model and load the adapter, so it cannot track the training context.
|
|
339
|
+
# a grammar lifts that ceiling: it is the adapter's serving default, so the smoke generates under
|
|
340
|
+
# it, and the shortest string it admits may be longer than the ceiling allows.
|
|
337
341
|
if spec.thinking:
|
|
338
|
-
max_tokens = max(
|
|
342
|
+
max_tokens = max(
|
|
343
|
+
256, resolve_smoke_completion_tokens(spec, constrained=constraint is not None)
|
|
344
|
+
)
|
|
339
345
|
serving_capacity = serving_completion_token_capacity(
|
|
340
346
|
spec, prompt_allowance=SERVING_PROMPT_TOKEN_ALLOWANCE
|
|
341
347
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.13"
|
|
4
4
|
description ="Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -137,7 +137,7 @@ artifacts = ["flash/py.typed"]
|
|
|
137
137
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
138
138
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
139
139
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
140
|
-
version = "1.2.
|
|
140
|
+
version = "1.2.13"
|
|
141
141
|
|
|
142
142
|
[tool.pytest.ini_options]
|
|
143
143
|
pythonpath = ["."]
|