freesolo-flash-dev 0.2.35__tar.gz → 0.2.36__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-0.2.35 → freesolo_flash_dev-0.2.36}/Dockerfile.worker +1 -1
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/PKG-INFO +4 -4
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/catalog.py +13 -20
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/commands.py +25 -7
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/client/http.py +18 -2
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/__init__.py +0 -4
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/registry.py +1 -1
- freesolo_flash_dev-0.2.36/flash/lora_rank.py +193 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/train/deps.py +1 -1
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/runner/__init__.py +24 -4
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/runner/checkpoints.py +21 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/runner/deploy.py +37 -20
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/schema/__init__.py +7 -2
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/serve/deploy.py +2 -19
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/_runtime.py +23 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/app.py +1 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/routes/serving.py +117 -4
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/pyproject.toml +6 -6
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_catalog_consistency.py +18 -24
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_checkpoints.py +52 -1
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_commands.py +25 -1
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_grpo_params.py +1 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_jobs.py +104 -0
- freesolo_flash_dev-0.2.36/tests/test_lora_rank_preflight.py +97 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_serve.py +7 -7
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_server_api.py +193 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_spec_and_validation.py +6 -6
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_verifiers.py +1 -1
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_vl_warmstart_recombine.py +11 -10
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/uv.lock +8 -8
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.dockerignore +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.env.example +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/.gitignore +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/Dockerfile +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/LICENSE +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/README.md +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/cli-style/README.md +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/cli-style/generate.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/cli-style/index.html +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/cli-style/preview.png +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/cli-style/themed-errors.png +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/docs/kernel-cache.md +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/_channel.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/_fileio.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/_logging.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/_update_check.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/envpush.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/render.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cli/training_doc.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/client/config.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/accounting.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/recipe.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/vram.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/adapter.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/finalize.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/gpu_setup.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/grpo.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/hf.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/kernel_warmup.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/lora.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/packing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/rl.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/sft.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/_http.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/_instance.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/_instance_bootstrap.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/_poll.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/api.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/pricing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/lambdalabs/train.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/preload.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/train/endpoints.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/py.typed +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/runner/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/serve/pricing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/_locks.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/auth.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/billing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/db.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/reconcile.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/server/run_registry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/spec.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/conftest.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_b200_rollout_opt.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_client.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_export.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_grpo_sleep_gate.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_version.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_vl_weight_sync.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/tests/test_worker_thinking.py +0 -0
|
@@ -63,7 +63,7 @@ RUN pip install --no-cache-dir \
|
|
|
63
63
|
"tilelang==0.1.11" \
|
|
64
64
|
"apache-tvm-ffi==0.1.11" \
|
|
65
65
|
"hf_transfer" \
|
|
66
|
-
"freesolo>=0.2.
|
|
66
|
+
"freesolo>=0.2.54" \
|
|
67
67
|
"runpod"
|
|
68
68
|
# Gated-DeltaNet (Qwen3.5/3.6) runs on flash-linear-attention's Triton kernels. On consumer cards
|
|
69
69
|
# (Ampere/Ada/Blackwell) the Triton path is correct. On Hopper (sm90) fla's GDN chunk_bwd is
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.36
|
|
4
4
|
Summary: Flash — managed LoRA post-training (SFT/GRPO) 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
|
|
@@ -18,7 +18,7 @@ Requires-Python: <3.13,>=3.11
|
|
|
18
18
|
Provides-Extra: dev
|
|
19
19
|
Requires-Dist: datasets>=2.19; extra == 'dev'
|
|
20
20
|
Requires-Dist: fastapi; extra == 'dev'
|
|
21
|
-
Requires-Dist: freesolo>=0.2.
|
|
21
|
+
Requires-Dist: freesolo>=0.2.54; extra == 'dev'
|
|
22
22
|
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
23
23
|
Requires-Dist: huggingface-hub>=0.34; extra == 'dev'
|
|
24
24
|
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
@@ -31,7 +31,7 @@ Provides-Extra: gpu
|
|
|
31
31
|
Requires-Dist: accelerate>=1.4; extra == 'gpu'
|
|
32
32
|
Requires-Dist: bitsandbytes>=0.49; extra == 'gpu'
|
|
33
33
|
Requires-Dist: datasets>=2.19; extra == 'gpu'
|
|
34
|
-
Requires-Dist: freesolo>=0.2.
|
|
34
|
+
Requires-Dist: freesolo>=0.2.54; extra == 'gpu'
|
|
35
35
|
Requires-Dist: huggingface-hub>=0.34; extra == 'gpu'
|
|
36
36
|
Requires-Dist: peft>=0.19; extra == 'gpu'
|
|
37
37
|
Requires-Dist: torch==2.10.0; extra == 'gpu'
|
|
@@ -41,7 +41,7 @@ Requires-Dist: vllm==0.19.1; extra == 'gpu'
|
|
|
41
41
|
Provides-Extra: server
|
|
42
42
|
Requires-Dist: datasets>=2.19; extra == 'server'
|
|
43
43
|
Requires-Dist: fastapi; extra == 'server'
|
|
44
|
-
Requires-Dist: freesolo>=0.2.
|
|
44
|
+
Requires-Dist: freesolo>=0.2.54; extra == 'server'
|
|
45
45
|
Requires-Dist: httpx>=0.27; extra == 'server'
|
|
46
46
|
Requires-Dist: huggingface-hub>=0.34; extra == 'server'
|
|
47
47
|
Requires-Dist: runpod-flash; extra == 'server'
|
|
@@ -116,11 +116,8 @@ class ModelInfo:
|
|
|
116
116
|
DEFAULT_MODEL = "Qwen/Qwen3.5-4B"
|
|
117
117
|
|
|
118
118
|
SERVING_FP8_MODEL_REPOS: dict[str, str] = {
|
|
119
|
-
"
|
|
120
|
-
"Qwen/Qwen3.5-
|
|
121
|
-
"Qwen/Qwen3.5-2B": "Freesolo-Co/Qwen3.5-2B-FP8",
|
|
122
|
-
"Qwen/Qwen3.5-4B": "Freesolo-Co/Qwen3.5-4B-FP8",
|
|
123
|
-
"Qwen/Qwen3.5-9B": "Freesolo-Co/Qwen3.5-9B-FP8",
|
|
119
|
+
"Qwen/Qwen3.5-4B": "lovedheart/Qwen3.5-4B-FP8",
|
|
120
|
+
"Qwen/Qwen3.5-9B": "lovedheart/Qwen3.5-9B-FP8",
|
|
124
121
|
"Qwen/Qwen3.6-35B-A3B": "Qwen/Qwen3.6-35B-A3B-FP8",
|
|
125
122
|
}
|
|
126
123
|
|
|
@@ -136,9 +133,8 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
136
133
|
recommended_gpu="RTX 4090",
|
|
137
134
|
serving=ServingCapacity(
|
|
138
135
|
gpu="L4",
|
|
139
|
-
serve_model_id=SERVING_FP8_MODEL_REPOS["openbmb/MiniCPM5-1B"],
|
|
140
136
|
max_loras=16,
|
|
141
|
-
max_lora_rank=
|
|
137
|
+
max_lora_rank=64,
|
|
142
138
|
max_model_len=32768,
|
|
143
139
|
),
|
|
144
140
|
thinking="hybrid",
|
|
@@ -155,9 +151,8 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
155
151
|
recommended_gpu="RTX 4090",
|
|
156
152
|
serving=ServingCapacity(
|
|
157
153
|
gpu="L4",
|
|
158
|
-
serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-0.8B"],
|
|
159
154
|
max_loras=16,
|
|
160
|
-
max_lora_rank=
|
|
155
|
+
max_lora_rank=64,
|
|
161
156
|
max_model_len=32768,
|
|
162
157
|
),
|
|
163
158
|
thinking="hybrid",
|
|
@@ -174,9 +169,8 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
174
169
|
recommended_gpu="RTX 4090",
|
|
175
170
|
serving=ServingCapacity(
|
|
176
171
|
gpu="L4",
|
|
177
|
-
serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-2B"],
|
|
178
172
|
max_loras=16,
|
|
179
|
-
max_lora_rank=
|
|
173
|
+
max_lora_rank=64,
|
|
180
174
|
max_model_len=32768,
|
|
181
175
|
),
|
|
182
176
|
thinking="hybrid",
|
|
@@ -191,10 +185,10 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
191
185
|
min_vram_gb=32,
|
|
192
186
|
recommended_gpu="RTX 5090",
|
|
193
187
|
serving=ServingCapacity(
|
|
194
|
-
gpu="
|
|
188
|
+
gpu="L4",
|
|
195
189
|
serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-4B"],
|
|
196
190
|
max_loras=64,
|
|
197
|
-
max_lora_rank=
|
|
191
|
+
max_lora_rank=32,
|
|
198
192
|
max_model_len=8192,
|
|
199
193
|
max_num_seqs=8,
|
|
200
194
|
gpu_memory_utilization=0.98,
|
|
@@ -216,10 +210,10 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
216
210
|
quant="bf16",
|
|
217
211
|
recommended_gpu="A100 PCIe",
|
|
218
212
|
serving=ServingCapacity(
|
|
219
|
-
gpu="
|
|
213
|
+
gpu="L4",
|
|
220
214
|
serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.5-9B"],
|
|
221
215
|
max_loras=44,
|
|
222
|
-
max_lora_rank=
|
|
216
|
+
max_lora_rank=32,
|
|
223
217
|
max_model_len=8192,
|
|
224
218
|
max_num_seqs=8,
|
|
225
219
|
gpu_memory_utilization=0.98,
|
|
@@ -254,14 +248,13 @@ MODELS: dict[str, ModelInfo] = {
|
|
|
254
248
|
quant="bf16",
|
|
255
249
|
recommended_gpu="H200",
|
|
256
250
|
serving=ServingCapacity(
|
|
257
|
-
gpu="A100-80GB
|
|
251
|
+
gpu="A100-80GB",
|
|
258
252
|
serve_model_id=SERVING_FP8_MODEL_REPOS["Qwen/Qwen3.6-35B-A3B"],
|
|
259
253
|
max_loras=12,
|
|
260
|
-
max_lora_rank=
|
|
254
|
+
max_lora_rank=32,
|
|
261
255
|
max_model_len=8192,
|
|
262
256
|
max_num_seqs=8,
|
|
263
257
|
max_num_batched_tokens=4096,
|
|
264
|
-
tensor_parallel_size=2,
|
|
265
258
|
gpu_memory_utilization=0.98,
|
|
266
259
|
),
|
|
267
260
|
thinking="hybrid",
|
|
@@ -292,8 +285,8 @@ def get_model(model_id: str) -> ModelInfo:
|
|
|
292
285
|
def serving_lora_rank_cap(model: str | ModelInfo | None) -> int | None:
|
|
293
286
|
"""Return the model's serving LoRA rank cap, or None when Flash has no local cap.
|
|
294
287
|
|
|
295
|
-
Serving capacity is model-specific: small serving models currently allow rank
|
|
296
|
-
serving paths currently allow rank
|
|
288
|
+
Serving capacity is model-specific: small serving models currently allow rank 64, while larger
|
|
289
|
+
serving paths currently allow rank 32. Unknown/open-policy models intentionally return None instead
|
|
297
290
|
of inheriting a global fallback.
|
|
298
291
|
"""
|
|
299
292
|
if isinstance(model, ModelInfo):
|
|
@@ -594,10 +594,17 @@ def cmd_deploy(args) -> int:
|
|
|
594
594
|
print(render.arrow(url_note) if render.styled() else f"note: {url_note}", file=sys.stderr)
|
|
595
595
|
if dep.get("state") != "dry_run":
|
|
596
596
|
state = dep.get("state", "deploying")
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
597
|
+
if state == "failed":
|
|
598
|
+
detail = str(dep.get("error") or dep.get("detail") or "unknown error")
|
|
599
|
+
status_note = (
|
|
600
|
+
f"deployment failed: {detail}; run `flash deployments` for details and "
|
|
601
|
+
f"retry `flash deploy {args.run_id}` after fixing the error."
|
|
602
|
+
)
|
|
603
|
+
else:
|
|
604
|
+
status_note = (
|
|
605
|
+
f"deployment state is {state!r}; run `flash deployments` to check progress "
|
|
606
|
+
"and use `flash chat` once it is ready."
|
|
607
|
+
)
|
|
601
608
|
print(
|
|
602
609
|
render.arrow(status_note) if render.styled() else f"note: {status_note}",
|
|
603
610
|
file=sys.stderr,
|
|
@@ -608,7 +615,7 @@ def cmd_deploy(args) -> int:
|
|
|
608
615
|
render.arrow(skip_note) if render.styled() else f"note: {skip_note}",
|
|
609
616
|
file=sys.stderr,
|
|
610
617
|
)
|
|
611
|
-
return 0
|
|
618
|
+
return 1 if dep.get("state") == "failed" else 0
|
|
612
619
|
|
|
613
620
|
|
|
614
621
|
def cmd_export(args) -> int:
|
|
@@ -678,6 +685,17 @@ def cmd_deployments(args) -> int:
|
|
|
678
685
|
|
|
679
686
|
|
|
680
687
|
def cmd_chat(args) -> int:
|
|
688
|
+
from flash.schema import parse_checkpoint_ref
|
|
689
|
+
|
|
690
|
+
parsed = parse_checkpoint_ref(args.run_id)
|
|
691
|
+
if parsed is None:
|
|
692
|
+
print(
|
|
693
|
+
f"invalid run/checkpoint reference {args.run_id!r} "
|
|
694
|
+
"(expected <run_id> or <run_id>/step-N)",
|
|
695
|
+
file=sys.stderr,
|
|
696
|
+
)
|
|
697
|
+
return 1
|
|
698
|
+
base_run_id, _step = parsed
|
|
681
699
|
client = client_from_config()
|
|
682
700
|
messages = [{"role": "user", "content": args.message}]
|
|
683
701
|
system = getattr(args, "system", None)
|
|
@@ -689,7 +707,7 @@ def cmd_chat(args) -> int:
|
|
|
689
707
|
if stream is not None:
|
|
690
708
|
wrote = False
|
|
691
709
|
for chunk in stream(
|
|
692
|
-
|
|
710
|
+
base_run_id,
|
|
693
711
|
messages=messages,
|
|
694
712
|
temperature=args.temperature,
|
|
695
713
|
max_tokens=args.max_tokens,
|
|
@@ -701,7 +719,7 @@ def cmd_chat(args) -> int:
|
|
|
701
719
|
return 0
|
|
702
720
|
|
|
703
721
|
resp = client.chat(
|
|
704
|
-
|
|
722
|
+
base_run_id,
|
|
705
723
|
messages=messages,
|
|
706
724
|
temperature=args.temperature,
|
|
707
725
|
max_tokens=args.max_tokens,
|
|
@@ -301,10 +301,18 @@ class ApiClient:
|
|
|
301
301
|
max_tokens: int = 512,
|
|
302
302
|
timeout: float | None = None,
|
|
303
303
|
) -> dict:
|
|
304
|
+
from flash.schema import parse_checkpoint_ref
|
|
305
|
+
|
|
306
|
+
parsed = parse_checkpoint_ref(run_id)
|
|
307
|
+
if parsed is None:
|
|
308
|
+
raise ClientError(
|
|
309
|
+
"invalid run id: expected RUN_ID or RUN_ID/step-N for a deployed checkpoint"
|
|
310
|
+
)
|
|
311
|
+
base_run_id, _step = parsed
|
|
304
312
|
_validate_chat_messages(messages)
|
|
305
313
|
return self._request(
|
|
306
314
|
"POST",
|
|
307
|
-
f"/v1/runs/{
|
|
315
|
+
f"/v1/runs/{base_run_id}/chat",
|
|
308
316
|
body={"messages": messages, "temperature": temperature, "max_tokens": max_tokens},
|
|
309
317
|
timeout=timeout if timeout is not None else 30 * 60,
|
|
310
318
|
)
|
|
@@ -316,12 +324,20 @@ class ApiClient:
|
|
|
316
324
|
temperature: float = 0.0,
|
|
317
325
|
max_tokens: int = 512,
|
|
318
326
|
) -> Iterator[str]:
|
|
327
|
+
from flash.schema import parse_checkpoint_ref
|
|
328
|
+
|
|
329
|
+
parsed = parse_checkpoint_ref(run_id)
|
|
330
|
+
if parsed is None:
|
|
331
|
+
raise ClientError(
|
|
332
|
+
"invalid run id: expected RUN_ID or RUN_ID/step-N for a deployed checkpoint"
|
|
333
|
+
)
|
|
334
|
+
base_run_id, _step = parsed
|
|
319
335
|
_validate_chat_messages(messages)
|
|
320
336
|
headers = {"Content-Type": "application/json"}
|
|
321
337
|
if self.api_key:
|
|
322
338
|
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
323
339
|
req = urllib.request.Request(
|
|
324
|
-
f"{self.api_url}/v1/runs/{
|
|
340
|
+
f"{self.api_url}/v1/runs/{base_run_id}/chat",
|
|
325
341
|
method="POST",
|
|
326
342
|
data=json.dumps(
|
|
327
343
|
{
|
{freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/engine/worker/perf/__init__.py
RENAMED
|
@@ -14,8 +14,6 @@ import contextlib
|
|
|
14
14
|
import os
|
|
15
15
|
import sys
|
|
16
16
|
|
|
17
|
-
# back-compat re-export from flash.engine.vram
|
|
18
|
-
from flash.engine.vram import _LIGER_LONG_CTX_TOKENS, _LIGER_MIN_PARAMS_B
|
|
19
17
|
from flash.engine.worker.perf.attn import (
|
|
20
18
|
_attn_impl_for_capability,
|
|
21
19
|
_flash_attn_3_available,
|
|
@@ -323,9 +321,7 @@ def _ensure_fla_fastpath_on_hopper() -> None:
|
|
|
323
321
|
|
|
324
322
|
__all__ = [
|
|
325
323
|
"RETRIABLE_INFRA_MARKER",
|
|
326
|
-
"_LIGER_LONG_CTX_TOKENS",
|
|
327
324
|
"_LIGER_MIN_PARAMS",
|
|
328
|
-
"_LIGER_MIN_PARAMS_B",
|
|
329
325
|
"_LONG_CONTEXT_TOKENS",
|
|
330
326
|
"RetriableInfraError",
|
|
331
327
|
"_GpuPeakSampler",
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""LoRA adapter rank parsing and control-plane preflight helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections.abc import Callable, Mapping
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from flash.catalog import serving_lora_rank_cap
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from flash.spec import JobSpec
|
|
13
|
+
|
|
14
|
+
_VL_WARMSTART_RECOMBINE_PREFIXES = ("Qwen/Qwen3.5-", "Qwen/Qwen3.6-")
|
|
15
|
+
|
|
16
|
+
AdapterConfigLoader = Callable[[str, str | None], Mapping[str, Any]]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def resolve_adapter_ref(adapter_ref: str) -> tuple[str, str] | None:
|
|
20
|
+
"""Resolve an internal storage ref into ``(repo, artifact_prefix)``."""
|
|
21
|
+
from flash.schema import parse_adapter_storage_ref
|
|
22
|
+
|
|
23
|
+
return parse_adapter_storage_ref(adapter_ref)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def adapter_config_path_from_ref(adapter_ref: str) -> tuple[str, str]:
|
|
27
|
+
resolved = resolve_adapter_ref(adapter_ref)
|
|
28
|
+
if resolved is None:
|
|
29
|
+
raise ValueError(
|
|
30
|
+
"train.init_from_adapter could not be resolved to an internal adapter storage ref"
|
|
31
|
+
)
|
|
32
|
+
repo, prefix = resolved
|
|
33
|
+
return repo, f"{prefix}/adapter/adapter_config.json"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _positive_int(value: Any, *, source: str, field: str) -> int:
|
|
37
|
+
if isinstance(value, bool):
|
|
38
|
+
raise ValueError(
|
|
39
|
+
f"could not verify adapter rank: {source} has invalid rank metadata ({field})"
|
|
40
|
+
)
|
|
41
|
+
try:
|
|
42
|
+
rank = int(value)
|
|
43
|
+
except (TypeError, ValueError) as exc:
|
|
44
|
+
raise ValueError(
|
|
45
|
+
f"could not verify adapter rank: {source} has invalid rank metadata ({field})"
|
|
46
|
+
) from exc
|
|
47
|
+
if rank <= 0:
|
|
48
|
+
raise ValueError(f"could not verify adapter rank: {source} has non-positive rank {rank}")
|
|
49
|
+
return rank
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
|
|
53
|
+
"""Return the max LoRA rank advertised by PEFT adapter metadata."""
|
|
54
|
+
if not isinstance(config, Mapping):
|
|
55
|
+
raise ValueError(f"could not verify adapter rank: {source} is not a JSON object")
|
|
56
|
+
ranks: list[int] = []
|
|
57
|
+
if config.get("r") is not None:
|
|
58
|
+
ranks.append(_positive_int(config["r"], source=source, field="r"))
|
|
59
|
+
if "rank_pattern" in config and config["rank_pattern"] is not None:
|
|
60
|
+
rank_pattern = config["rank_pattern"]
|
|
61
|
+
if not isinstance(rank_pattern, Mapping):
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"could not verify adapter rank: {source} has invalid rank metadata "
|
|
64
|
+
"(rank_pattern)"
|
|
65
|
+
)
|
|
66
|
+
ranks.extend(
|
|
67
|
+
_positive_int(v, source=source, field="rank_pattern") for v in rank_pattern.values()
|
|
68
|
+
)
|
|
69
|
+
if not ranks:
|
|
70
|
+
raise ValueError(f"could not verify adapter rank: {source} has no LoRA rank metadata")
|
|
71
|
+
return max(ranks)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def uniform_rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
|
|
75
|
+
"""Return a uniform adapter rank for the VL SFT+GRPO recombine path."""
|
|
76
|
+
if not isinstance(config, Mapping):
|
|
77
|
+
raise ValueError(f"adapter rank preflight: {source} is not a JSON object")
|
|
78
|
+
if config.get("r") is None:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
f"adapter rank preflight: {source} must contain a positive integer `r`"
|
|
81
|
+
)
|
|
82
|
+
rank = _positive_int(config["r"], source=source, field="r")
|
|
83
|
+
for key in ("rank_pattern", "alpha_pattern"):
|
|
84
|
+
pattern = config.get(key)
|
|
85
|
+
if pattern is None:
|
|
86
|
+
continue
|
|
87
|
+
if not isinstance(pattern, Mapping):
|
|
88
|
+
raise ValueError(
|
|
89
|
+
f"adapter rank preflight: {source} has invalid {key}={pattern!r}; "
|
|
90
|
+
"VL warm-start recombine requires a uniform LoRA rank/alpha"
|
|
91
|
+
)
|
|
92
|
+
if pattern:
|
|
93
|
+
raise ValueError(
|
|
94
|
+
f"adapter rank preflight: {source} has non-empty {key}={pattern!r}; "
|
|
95
|
+
"VL warm-start recombine requires a uniform LoRA rank/alpha"
|
|
96
|
+
)
|
|
97
|
+
return rank
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def load_hf_adapter_config(adapter_ref: str, token: str | None = None) -> Mapping[str, Any]:
|
|
101
|
+
"""Read ``adapter_config.json`` for a Flash adapter ref from Hugging Face datasets."""
|
|
102
|
+
repo, filename = adapter_config_path_from_ref(adapter_ref)
|
|
103
|
+
try:
|
|
104
|
+
from huggingface_hub import hf_hub_download
|
|
105
|
+
except ImportError as exc: # pragma: no cover - package extra is present in supported installs
|
|
106
|
+
raise ValueError(
|
|
107
|
+
"could not verify train.init_from_adapter rank: huggingface_hub is not installed"
|
|
108
|
+
) from exc
|
|
109
|
+
try:
|
|
110
|
+
local = hf_hub_download(
|
|
111
|
+
repo_id=repo,
|
|
112
|
+
filename=filename,
|
|
113
|
+
repo_type="dataset",
|
|
114
|
+
token=token,
|
|
115
|
+
)
|
|
116
|
+
except Exception as exc:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f"could not verify train.init_from_adapter rank: failed to read {repo}:{filename}"
|
|
119
|
+
) from exc
|
|
120
|
+
try:
|
|
121
|
+
with open(local, encoding="utf-8") as f:
|
|
122
|
+
config = json.load(f)
|
|
123
|
+
except Exception as exc:
|
|
124
|
+
raise ValueError(
|
|
125
|
+
f"could not verify train.init_from_adapter rank: invalid JSON in {repo}:{filename}"
|
|
126
|
+
) from exc
|
|
127
|
+
if not isinstance(config, Mapping):
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"could not verify train.init_from_adapter rank: {repo}:{filename} "
|
|
130
|
+
"is not a JSON object"
|
|
131
|
+
)
|
|
132
|
+
return config
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _uses_vl_warmstart_recombine(model: str) -> bool:
|
|
136
|
+
return model.startswith(_VL_WARMSTART_RECOMBINE_PREFIXES)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def preflight_init_adapter_lora_rank(
|
|
140
|
+
spec: JobSpec,
|
|
141
|
+
*,
|
|
142
|
+
token: str | None = None,
|
|
143
|
+
config_loader: AdapterConfigLoader | None = None,
|
|
144
|
+
) -> None:
|
|
145
|
+
"""Reject warm-start adapters that cannot fit the model's serving LoRA rank cap.
|
|
146
|
+
|
|
147
|
+
The control plane calls this before creating/submitting a run. It intentionally uses only
|
|
148
|
+
``adapter_config.json`` so the preflight stays CPU-only and catches undeployable adapters before
|
|
149
|
+
any training GPU is allocated.
|
|
150
|
+
"""
|
|
151
|
+
adapter_storage_ref = (spec.train.init_from_adapter or "").strip()
|
|
152
|
+
if not adapter_storage_ref:
|
|
153
|
+
return
|
|
154
|
+
max_lora_rank = serving_lora_rank_cap(spec.model)
|
|
155
|
+
if max_lora_rank is None:
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
repo, filename = adapter_config_path_from_ref(adapter_storage_ref)
|
|
159
|
+
source = f"{repo}:{filename}"
|
|
160
|
+
loader = config_loader or load_hf_adapter_config
|
|
161
|
+
config = loader(adapter_storage_ref, token)
|
|
162
|
+
|
|
163
|
+
adapter_rank = rank_from_adapter_config(config, source=source)
|
|
164
|
+
if adapter_rank > max_lora_rank:
|
|
165
|
+
raise ValueError(
|
|
166
|
+
f"train.init_from_adapter={adapter_storage_ref!r} has rank {adapter_rank}, exceeding "
|
|
167
|
+
f"{spec.model}'s serving max_lora_rank={max_lora_rank}; use a lower-rank adapter "
|
|
168
|
+
"or raise the serving cap after real-GPU validation"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if spec.algorithm != "grpo" or not _uses_vl_warmstart_recombine(spec.model):
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
sft_rank = uniform_rank_from_adapter_config(config, source=source)
|
|
175
|
+
grpo_rank = int(spec.train.lora_rank)
|
|
176
|
+
recombined_rank = sft_rank + grpo_rank
|
|
177
|
+
if recombined_rank <= max_lora_rank:
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
allowed_grpo_rank = max_lora_rank - sft_rank
|
|
181
|
+
if allowed_grpo_rank >= 1:
|
|
182
|
+
guidance = f"set GRPO train.lora_rank <= {allowed_grpo_rank}"
|
|
183
|
+
else:
|
|
184
|
+
allowed_sft_rank = max_lora_rank - grpo_rank
|
|
185
|
+
if allowed_sft_rank >= 1:
|
|
186
|
+
guidance = f"retrain the SFT adapter at rank <= {allowed_sft_rank}"
|
|
187
|
+
else:
|
|
188
|
+
guidance = f"lower both SFT and GRPO ranks so their sum is <= {max_lora_rank}"
|
|
189
|
+
raise ValueError(
|
|
190
|
+
"train.init_from_adapter rank preflight failed: recombined SFT+GRPO adapter would be "
|
|
191
|
+
f"rank {recombined_rank} (SFT rank {sft_rank} + GRPO rank {grpo_rank}), exceeding "
|
|
192
|
+
f"{spec.model}'s serving max_lora_rank={max_lora_rank}; {guidance}"
|
|
193
|
+
)
|
{freesolo_flash_dev-0.2.35 → freesolo_flash_dev-0.2.36}/flash/providers/runpod/train/deps.py
RENAMED
|
@@ -30,7 +30,7 @@ WORKER_DEPS = [
|
|
|
30
30
|
"flashinfer-python==0.6.6",
|
|
31
31
|
"bitsandbytes>=0.49",
|
|
32
32
|
"datasets>=4.7,<6",
|
|
33
|
-
# >=0.2.
|
|
33
|
+
# >=0.2.54: includes robust JSONL loading and corrected package metadata.
|
|
34
34
|
FREESOLO_WORKER_SPEC,
|
|
35
35
|
"huggingface_hub>=0.25",
|
|
36
36
|
"accelerate>=1.4",
|
|
@@ -387,10 +387,7 @@ def _resolve_init_from_adapter(
|
|
|
387
387
|
ref = spec.train.init_from_adapter
|
|
388
388
|
if not ref:
|
|
389
389
|
return spec
|
|
390
|
-
from flash.schema import checkpoint_storage_ref,
|
|
391
|
-
|
|
392
|
-
if parse_adapter_storage_ref(ref) is not None:
|
|
393
|
-
return spec
|
|
390
|
+
from flash.schema import checkpoint_storage_ref, parse_checkpoint_ref
|
|
394
391
|
|
|
395
392
|
parsed = parse_checkpoint_ref(ref)
|
|
396
393
|
if parsed is None:
|
|
@@ -431,6 +428,25 @@ def _resolve_init_from_adapter(
|
|
|
431
428
|
f"train.init_from_adapter references {src_run_id}/step-{step}, but that "
|
|
432
429
|
"deployable checkpoint was not found"
|
|
433
430
|
)
|
|
431
|
+
else:
|
|
432
|
+
if src_status.state not in {"done", "deployed"}:
|
|
433
|
+
raise ValueError(
|
|
434
|
+
f"train.init_from_adapter references run {src_run_id!r}, but that run is "
|
|
435
|
+
f"{src_status.state!r}; use a completed source run or a concrete "
|
|
436
|
+
f"{src_run_id}/step-N checkpoint"
|
|
437
|
+
)
|
|
438
|
+
from flash.runner.checkpoints import CheckpointListingError, final_adapter_exists
|
|
439
|
+
|
|
440
|
+
try:
|
|
441
|
+
exists = final_adapter_exists(src_spec)
|
|
442
|
+
except CheckpointListingError as exc:
|
|
443
|
+
raise ValueError(str(exc)) from exc
|
|
444
|
+
if not exists:
|
|
445
|
+
raise ValueError(
|
|
446
|
+
f"train.init_from_adapter references run {src_run_id!r}, but its final "
|
|
447
|
+
"adapter was not found; use a concrete checkpoint ref like "
|
|
448
|
+
f"{src_run_id}/step-N if one exists"
|
|
449
|
+
)
|
|
434
450
|
storage = checkpoint_storage_ref(src_spec.train.hf_repo, src_spec.phase, src_run_id, step)
|
|
435
451
|
return replace(spec, train=replace(spec.train, init_from_adapter=storage))
|
|
436
452
|
|
|
@@ -459,6 +475,10 @@ def submit_job(
|
|
|
459
475
|
owner_org_id=owner_org_id,
|
|
460
476
|
owner_key_id=owner_key_id,
|
|
461
477
|
)
|
|
478
|
+
if not dry_run:
|
|
479
|
+
from flash.lora_rank import preflight_init_adapter_lora_rank
|
|
480
|
+
|
|
481
|
+
preflight_init_adapter_lora_rank(worker_spec, token=os.environ.get("HF_TOKEN"))
|
|
462
482
|
# env ref->sha pin is deferred (background) or after status save (sync) — never on creation path.
|
|
463
483
|
status = RunStatus(
|
|
464
484
|
run_id=public_spec.run_id,
|
|
@@ -39,6 +39,15 @@ def _adapter_file_re(base: str) -> re.Pattern[str]:
|
|
|
39
39
|
return re.compile(re.escape(base) + r"/checkpoints/step-(\d+)/adapter/([^/]+)$")
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
def _adapter_folder_has_required_files(files: list[str], prefix: str) -> bool:
|
|
43
|
+
names = {
|
|
44
|
+
path.removeprefix(f"{prefix}/adapter/")
|
|
45
|
+
for path in files
|
|
46
|
+
if path.startswith(f"{prefix}/adapter/") and "/" not in path.removeprefix(f"{prefix}/adapter/")
|
|
47
|
+
}
|
|
48
|
+
return "adapter_config.json" in names and not names.isdisjoint(_ADAPTER_WEIGHT_FILES)
|
|
49
|
+
|
|
50
|
+
|
|
42
51
|
def _repo_files(spec: JobSpec, *, strict: bool) -> list[str]:
|
|
43
52
|
repo = spec.train.hf_repo
|
|
44
53
|
if not repo:
|
|
@@ -110,3 +119,15 @@ def checkpoint_step_exists(spec: JobSpec, step: int) -> bool:
|
|
|
110
119
|
int(item.get("step", -1)) == int(step)
|
|
111
120
|
for item in _checkpoints_from_files(spec, _repo_files(spec, strict=True))
|
|
112
121
|
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def final_adapter_exists(spec: JobSpec) -> bool:
|
|
125
|
+
"""Authoritatively verify that the run-level final adapter exists in the artifact repo."""
|
|
126
|
+
try:
|
|
127
|
+
files = _repo_files(spec, strict=True)
|
|
128
|
+
except CheckpointListingError as exc:
|
|
129
|
+
cause = exc.__cause__ or exc
|
|
130
|
+
raise CheckpointListingError(
|
|
131
|
+
f"could not verify final adapter for {spec.run_id}: {cause}"
|
|
132
|
+
) from cause
|
|
133
|
+
return _adapter_folder_has_required_files(files, adapter_prefix(spec))
|