freesolo-flash-dev 0.2.47__tar.gz → 0.2.48__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.47 → freesolo_flash_dev-0.2.48}/PKG-INFO +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/commands.py +3 -3
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/training_doc.py +9 -9
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cost/analytical.py +2 -2
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cost/spec.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cost/types.py +5 -5
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/recipe.py +2 -2
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/vram.py +73 -20
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/grpo.py +2 -2
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/opd.py +236 -247
- freesolo_flash_dev-0.2.48/flash/engine/worker/opd_vllm.py +274 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/lifecycle.py +13 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/memory.py +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/rl.py +6 -5
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/lora_rank.py +8 -7
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/schema/__init__.py +20 -14
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/spec.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/pyproject.toml +2 -2
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_allocator.py +456 -61
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_b200_rollout_opt.py +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_backend_jobspec_contract.py +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_commands.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_estimate.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_analytical.py +27 -14
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_gpus.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_grpo_params.py +51 -15
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_grpo_sleep_gate.py +4 -4
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_jobs.py +54 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_oom_escalate_gpu.py +10 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_opd.py +356 -65
- freesolo_flash_dev-0.2.48/tests/test_opd_vllm.py +184 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_open_model_policy.py +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_spec_and_validation.py +9 -5
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_train_context_preflight.py +19 -14
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/uv.lock +1 -1
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.dockerignore +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.env.example +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/.gitignore +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/Dockerfile +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/LICENSE +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/README.md +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/_channel.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/_fileio.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/_logging.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/_update_check.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/adapter_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/catalog.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/_tty.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/envpush.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cli/render.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/client/config.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/client/http.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/accounting.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/adapter.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/finalize.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/gpu_setup.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/hf.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/kernel_warmup.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/lora.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/opd_gkd.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/packing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/sft.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/teacher.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/tokenizer_align.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/archive_policy.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/envs/registry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_hf_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_hf_retry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_http.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_instance.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_instance_bootstrap.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_instance_poll.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_instance_provider.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_poll.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/_worker.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/lambdalabs/pricing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/preload.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/train/deps.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/runpod/train/endpoints.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/py.typed +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/runner/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/runner/deploy.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/runner/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/serve/pricing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/_locks.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/_runtime.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/app.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/auth.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/billing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/db.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/reconcile.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/flash/server/run_registry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/conftest.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_client.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_export.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_version.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_vl_warmstart_recombine.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-0.2.47 → freesolo_flash_dev-0.2.48}/tests/test_worker_thinking.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.48
|
|
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
|
|
@@ -447,11 +447,11 @@ def cmd_env_setup(args) -> int:
|
|
|
447
447
|
'# secrets = ["SERPAPI_API_KEY"]\n\n'
|
|
448
448
|
)
|
|
449
449
|
# `thinking = true` opts the run into reasoning mode. Reasoning shares the generation budget with
|
|
450
|
-
# the answer, so GRPO also gets a raised
|
|
451
|
-
# off, keeping the default scaffold byte-for-byte identical.
|
|
450
|
+
# the answer, so GRPO also gets a raised completion budget. These strings are empty when reasoning
|
|
451
|
+
# is off, keeping the default scaffold byte-for-byte identical.
|
|
452
452
|
thinking_line = "thinking = true\n" if reasoning else ""
|
|
453
453
|
rl_reasoning_train = (
|
|
454
|
-
"
|
|
454
|
+
"max_completion_tokens = 2048 # reasoning shares this budget with the answer; raised so it isn't truncated\n"
|
|
455
455
|
if reasoning
|
|
456
456
|
else ""
|
|
457
457
|
)
|
|
@@ -201,15 +201,15 @@ spending another GPU run:
|
|
|
201
201
|
| --- | --- | --- |
|
|
202
202
|
| Environment id is blank or stale | `flash train --dry-run` fails, or the worker uses old reward/data | Run `flash env push --name my-env .` after every environment/data edit and paste the returned id into every config you submit. |
|
|
203
203
|
| Local-only env path in config | Config validation says there is no local path mode | Publish first, then use the returned slug in `[environment] id`. `flash train` only runs published env ids, not local paths. |
|
|
204
|
-
| Config knobs are in the wrong table | Validation rejects `[grpo]`, `[sft]`, or unknown `[train]` keys | Put `steps`, `epochs`, `group_size`, `
|
|
204
|
+
| Config knobs are in the wrong table | Validation rejects `[grpo]`, `[sft]`, or unknown `[train]` keys | Put `steps`, `epochs`, `group_size`, `max_completion_tokens`, `temperature`, `max_context_tokens`, LoRA, and other training knobs under `[train]`. |
|
|
205
205
|
| Trying to pin managed infrastructure | `gpu.type`, `train.hf_repo`, or `model_policy` changes do not do what you expected | Treat GPU choice, model policy, and the run artifact repo as managed. Tune the model, algorithm, environment, and `[train]` knobs instead. |
|
|
206
206
|
| Secrets are not available on the worker | Reward code works locally but remote logs show missing API keys or auth failures | List secret names under `[environment] secrets = [...]`, export those env vars locally before submit, or put them in local `.env` / `.env.local`. Never put secret values in `[worker_env]` or hard-code them in the config. |
|
|
207
207
|
| Wrong model / thinking setting | Config validation fails, or chat behavior does not match the run | Use `flash models`; set `thinking = true` only for supported models. Thinking is a training-time/run-level choice and serving preserves that parity, so `flash chat` does not expose an override flag. |
|
|
208
208
|
| Thinking reward grades the wrong text | Rewards accidentally score hidden reasoning, or ignore reasoning you meant to inspect | By default, score the answer text. In thinking mode the response object is still string-compatible, but also exposes `.completion`, `.thinking`, and `.raw` when a reward intentionally needs those fields. |
|
|
209
209
|
| All-zero or flat GRPO reward | `reward_mean` stays near 0 and outputs do not improve | Make the reward dense: give partial credit for parse/format/execution/correctness tiers, and log a separate clean `success` metric. Do not keep rerunning an all-zero reward. |
|
|
210
210
|
| Reward rises but behavior is worse | Short, templated, malformed, or reward-hacked outputs score well | Deploy the adapter and probe real examples. Add hard validity gates before judge calls, penalize degenerate shortcuts, and judge the outcome rather than the surface string. |
|
|
211
|
-
| Output is truncated | Correct-looking answers cut off mid-response or JSON is incomplete | Increase `
|
|
212
|
-
| Infrastructure, CUDA, OOM, vLLM, or kernel failure | Run errors before useful metrics, often during setup/model load | Treat this as infrastructure pressure, not proof the model is too large. Read `flash log <run-id>`, reduce footprint (`
|
|
211
|
+
| Output is truncated | Correct-looking answers cut off mid-response or JSON is incomplete | Increase `max_completion_tokens` for GRPO/OPD rollouts or `max_context_tokens` for total prompt+completion context only after seeing truncation. Oversizing them by default just burns memory/cost. |
|
|
212
|
+
| Infrastructure, CUDA, OOM, vLLM, or kernel failure | Run errors before useful metrics, often during setup/model load | Treat this as infrastructure pressure, not proof the model is too large. Read `flash log <run-id>`, reduce footprint (`max_context_tokens`, `max_completion_tokens`, `group_size`) if needed, and let Flash retry/allocate another fitting GPU class. |
|
|
213
213
|
| Run looks stuck after disconnecting | Terminal stopped streaming but the job may still be alive | Ctrl-C detaches. Use `flash log <run-id> --follow` to reattach, `flash log <run-id>` for the console/error output, or `flash cancel <run-id>` if you intentionally want to stop it. |
|
|
214
214
|
| Final checkpoint regresses | Last step is worse than an earlier checkpoint | Run `flash checkpoints <run-id>`, deploy a specific step with `flash deploy <run-id>/step-N`, and compare with held-out probes before exporting or relying on the final adapter. |
|
|
215
215
|
| Export fails before upload | CLI says no HuggingFace token | Pass `flash export --api-key hf_...`, or set `HF_TOKEN` in your shell, `.env`, or `.env.local`. Exports are private unless you pass `--public`. |
|
|
@@ -335,8 +335,8 @@ Pick SFT when you already have good answers and want the model to imitate them.
|
|
|
335
335
|
split the run never trains on, then **deploy the adapter and score it on that split**
|
|
336
336
|
(`flash deploy` + `flash chat`). If held-out quality stalls or drops while train loss
|
|
337
337
|
keeps falling, reduce `epochs` or add more data — not more passes.
|
|
338
|
-
- **Start `
|
|
339
|
-
`
|
|
338
|
+
- **Start `max_context_tokens` small and grow it on evidence.** Begin from the smallest
|
|
339
|
+
`max_context_tokens` that plausibly fits prompt + completion, and only raise it when you see
|
|
340
340
|
truncation (outputs cut off mid-thought, degraded loss). A bigger context just costs
|
|
341
341
|
more.
|
|
342
342
|
- **For Qwen3.5 thinking multi-turn SFT, put reasoning only in the final assistant
|
|
@@ -397,7 +397,7 @@ far more sample-efficient than reward-based RL and with no reward to design. It
|
|
|
397
397
|
(driving `step_episode` / observations just like GRPO) and distils EVERY assistant turn against the
|
|
398
398
|
teacher, each conditioned on the transcript up to that turn — the episode's total reverse-KL over
|
|
399
399
|
the student's generated tokens is the sum of its per-turn reverse-KLs. Env/observation tokens are
|
|
400
|
-
never distilled (they're context, not the student's output). Set `[train]
|
|
400
|
+
never distilled (they're context, not the student's output). Set `[train] max_context_tokens` to bound the
|
|
401
401
|
transcript; the teacher must cover it (GLM-5.2's context far exceeds the default budget).
|
|
402
402
|
- **Judge it like SFT.** Distillation logs a falling per-token loss; a low loss alone is not proof.
|
|
403
403
|
Keep a held-out split, `flash deploy` the adapter, and score it — confirm the student actually
|
|
@@ -427,7 +427,7 @@ in a sensible value, so only override with a reason.
|
|
|
427
427
|
| Knob | Convention |
|
|
428
428
|
| --- | --- |
|
|
429
429
|
| `group_size` | Completions sampled per prompt (default 8). More = more signal and more cost; drop to 4 to trim cost. The group needs *within-group variance* for an advantage to exist. |
|
|
430
|
-
| `
|
|
430
|
+
| `max_completion_tokens` | Completion budget per rollout. Size it to the expected output length — too small silently truncates good answers and poisons the reward; too large just costs more. |
|
|
431
431
|
| `temperature` | Rollout sampling temperature. Keep it near 1.0 for GRPO — too low collapses diversity (and the model can collapse within a few steps); raise it to widen exploration against uniform-reward groups. |
|
|
432
432
|
| `kl_penalty_coef` | Keeps the trained model from drifting too far from the base. Raise it to anchor against entropy collapse; lower it for more freedom to move. |
|
|
433
433
|
| `thinking_length_penalty_coef` | Per-reasoning-token reward deduction — curb overthinking, but watch it doesn't push the model into terse degeneracy. |
|
|
@@ -468,7 +468,7 @@ targeted fix rather than leaning on the reward gate to slowly select against it.
|
|
|
468
468
|
| --- | --- | --- |
|
|
469
469
|
| Repetition / looping collapse | the same phrase repeats until truncation | repetition or length penalty; lower `temperature` |
|
|
470
470
|
| Overthinking / verbose reasoning | reasoning eats the whole token budget | `thinking_length_penalty_coef`; tighten the prompt |
|
|
471
|
-
|
|
|
471
|
+
| Completion truncation | answers cut off mid-thought | raise `max_completion_tokens` / `max_context_tokens` |
|
|
472
472
|
| Unparsed / over-escaped output | reward can't read the answer | robust parser; return `0.0` on parse fail; format gate |
|
|
473
473
|
| Wrapper / markdown around structured output | prose around the JSON/answer | a format gate; `stop_sequences` |
|
|
474
474
|
| Uniform-reward groups | every rollout in a group scores the same → no gradient | shape the reward for partial credit; raise `temperature` |
|
|
@@ -513,7 +513,7 @@ on a beyond-noise improvement.
|
|
|
513
513
|
## Treat crashes as infra, not model size
|
|
514
514
|
|
|
515
515
|
> A CUDA / OOM / vLLM / kernel / infrastructure error is an **infrastructure** problem, not a
|
|
516
|
-
> sign the model is too big. Lower `
|
|
516
|
+
> sign the model is too big. Lower `max_context_tokens`, `max_completion_tokens`, or `group_size` to shrink
|
|
517
517
|
> the run's footprint and let the allocator retry onto the next fitting GPU class — do
|
|
518
518
|
> **not** switch to a smaller model to make a crash disappear. That silently destroys
|
|
519
519
|
> quality.
|
|
@@ -73,11 +73,11 @@ def _fmt_duration(seconds: float) -> str:
|
|
|
73
73
|
|
|
74
74
|
def setup_seconds(config: RunConfig) -> float:
|
|
75
75
|
"""Cold-start wall time before the first optimizer step: container boot + deps + model load
|
|
76
|
-
(a fixed deserialize/placement/init base + a size-scaled download), plus vLLM init for
|
|
76
|
+
(a fixed deserialize/placement/init base + a size-scaled download), plus vLLM init for rollouts.
|
|
77
77
|
This elapsed setup time is reported but not included in customer-facing cost."""
|
|
78
78
|
model_load = MODEL_LOAD_BASE_S + download_weight_gb(config.model_id) / DOWNLOAD_RATE_GBPS
|
|
79
79
|
s = WORKER_BOOT_S + DEPS_INSTALL_S + model_load
|
|
80
|
-
if config.
|
|
80
|
+
if config.has_rollout:
|
|
81
81
|
s += VLLM_INIT_S
|
|
82
82
|
return s
|
|
83
83
|
|
|
@@ -24,8 +24,8 @@ def _sft_seq_len(spec) -> int:
|
|
|
24
24
|
|
|
25
25
|
t = spec.train
|
|
26
26
|
return (
|
|
27
|
-
int(t.
|
|
28
|
-
if t.
|
|
27
|
+
int(t.max_context_tokens)
|
|
28
|
+
if t.max_context_tokens is not None
|
|
29
29
|
else (RECIPE.sft.max_seq_len_thinking if spec.thinking else RECIPE.sft.max_seq_len)
|
|
30
30
|
)
|
|
31
31
|
|
|
@@ -101,8 +101,8 @@ def runconfig_from_spec(spec) -> RunConfig:
|
|
|
101
101
|
model_id=spec.model,
|
|
102
102
|
method=spec.algorithm,
|
|
103
103
|
steps=spec_steps(spec),
|
|
104
|
-
seq_len=t.
|
|
105
|
-
completion_len=t.
|
|
104
|
+
seq_len=t.max_context_tokens,
|
|
105
|
+
completion_len=t.max_completion_tokens if has_rollout else None,
|
|
106
106
|
batch_size=t.batch_size,
|
|
107
107
|
group_size=t.group_size if has_rollout else None,
|
|
108
108
|
lora_rank=t.lora_rank,
|
|
@@ -17,10 +17,10 @@ class RunConfig:
|
|
|
17
17
|
method: str # "sft" | "grpo" | "opd"
|
|
18
18
|
steps: int
|
|
19
19
|
|
|
20
|
-
# Engine context length (forwarded as [train].
|
|
20
|
+
# Engine context length (forwarded as [train].max_context_tokens, NOT prompt length). When unset the
|
|
21
21
|
# GRPO default mirrors the worker's max(1024, max_prompt_len + completion); see normalized().
|
|
22
22
|
seq_len: int | None = None
|
|
23
|
-
completion_len: int | None = None # GRPO only (
|
|
23
|
+
completion_len: int | None = None # GRPO/OPD only (max_completion_tokens)
|
|
24
24
|
batch_size: int | None = None # SFT effective batch / GRPO prompts_per_step
|
|
25
25
|
group_size: int | None = None # GRPO completions per prompt (G)
|
|
26
26
|
lora_rank: int | None = None
|
|
@@ -82,7 +82,7 @@ class RunConfig:
|
|
|
82
82
|
comp = self.completion_len
|
|
83
83
|
if comp is None:
|
|
84
84
|
comp = rc.max_completion_len_thinking if self.thinking else rc.max_completion_len
|
|
85
|
-
# Explicit pin wins; else mirror the allocator's rollout sizing of an unset
|
|
85
|
+
# Explicit pin wins; else mirror the allocator's rollout sizing of an unset context:
|
|
86
86
|
# max(1024, max_prompt_len + completion), not bare max_prompt_len (which under-sizes).
|
|
87
87
|
seq = (
|
|
88
88
|
self.seq_len
|
|
@@ -116,9 +116,9 @@ class RunConfig:
|
|
|
116
116
|
if self.batch_size is not None:
|
|
117
117
|
knobs["batch_size"] = self.batch_size
|
|
118
118
|
if n.seq_len is not None:
|
|
119
|
-
knobs["
|
|
119
|
+
knobs["max_context_tokens"] = n.seq_len
|
|
120
120
|
if n.completion_len is not None:
|
|
121
|
-
knobs["
|
|
121
|
+
knobs["max_completion_tokens"] = n.completion_len
|
|
122
122
|
if n.group_size is not None:
|
|
123
123
|
knobs["group_size"] = n.group_size
|
|
124
124
|
return knobs
|
|
@@ -36,7 +36,7 @@ class RLConfig:
|
|
|
36
36
|
learning_rate: float = 1e-5
|
|
37
37
|
max_prompt_len: int = 2048
|
|
38
38
|
max_completion_len: int = 320
|
|
39
|
-
# 320 is too short for <think> blocks; overridable via [train].
|
|
39
|
+
# 320 is too short for <think> blocks; overridable via [train].max_completion_tokens.
|
|
40
40
|
max_completion_len_thinking: int = 1536
|
|
41
41
|
prompts_per_step: int = 64
|
|
42
42
|
group_size: int = 8
|
|
@@ -59,7 +59,7 @@ class OPDConfig:
|
|
|
59
59
|
learning_rate: float = 1e-5
|
|
60
60
|
max_prompt_len: int = 1024
|
|
61
61
|
max_completion_len: int = 512
|
|
62
|
-
# 512 is short for <think> traces; overridable via [train].
|
|
62
|
+
# 512 is short for <think> traces; overridable via [train].max_completion_tokens.
|
|
63
63
|
max_completion_len_thinking: int = 1536
|
|
64
64
|
prompts_per_step: int = 8
|
|
65
65
|
# Student samples per prompt. 1 is enough for a direct KD loss (no group-relative baseline
|
|
@@ -96,6 +96,20 @@ def opd_rollout_seq_len(
|
|
|
96
96
|
return int(max_length or max(1024, RECIPE.opd.max_prompt_len + completion))
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def opd_rollout_concurrency(prompts_per_step: int = 1, group_size: int = 1) -> int:
|
|
100
|
+
"""Concurrent student generations in one OPD vLLM rollout batch."""
|
|
101
|
+
|
|
102
|
+
def _positive_int(value: object, default: int) -> int:
|
|
103
|
+
try:
|
|
104
|
+
if isinstance(value, bool):
|
|
105
|
+
return default
|
|
106
|
+
return max(1, int(value))
|
|
107
|
+
except (TypeError, ValueError):
|
|
108
|
+
return default
|
|
109
|
+
|
|
110
|
+
return _positive_int(prompts_per_step, 1) * _positive_int(group_size, 1)
|
|
111
|
+
|
|
112
|
+
|
|
99
113
|
def _resident_kv_gb(
|
|
100
114
|
params_b: float | None, vllm_max_len: int, num_generations: int = 8, fp8_kv: bool = False
|
|
101
115
|
) -> float:
|
|
@@ -188,6 +202,12 @@ def colocate_kv_util(
|
|
|
188
202
|
_TRAIN_COEF = 0.27
|
|
189
203
|
# Small-model colocated GRPO floor: 0.8B OOMs 20 GB; 2B OOMs 24 GB -> both need 32 GB tier.
|
|
190
204
|
_VLLM_COLOCATE_FLOOR_GB = 28.0
|
|
205
|
+
# OPD builds its resident vLLM engine after the HF/PEFT student is already loaded. A real
|
|
206
|
+
# Qwen3.5-2B OPD run with vLLM failed vLLM startup on a 32 GB RTX 5090 despite the raw equation
|
|
207
|
+
# estimating ~28 GB with headroom, because vLLM requires the requested executor budget to be free at
|
|
208
|
+
# init time. Keep 2B+ OPD off <=40 GB classes so the allocator picks an 80 GB-class card instead of a
|
|
209
|
+
# consumer GPU that passes the aggregate estimate but fails the vLLM free-memory preflight.
|
|
210
|
+
_OPD_VLLM_COLOCATE_FLOOR_GB = 41.0
|
|
191
211
|
_VOCAB_DEFAULT = 248_320
|
|
192
212
|
_LOGITS_BUDGET_GB = 6.0
|
|
193
213
|
# 16 B/elem: fp32 logits+grad + bf16 logits+grad + CE temp. 8 B/elem under-counts (live OOM confirmed).
|
|
@@ -328,6 +348,14 @@ def estimate_vram_gb(
|
|
|
328
348
|
train = activations + logits
|
|
329
349
|
return base + (max(rollout, train) if sleep_offload else rollout + train)
|
|
330
350
|
if is_opd:
|
|
351
|
+
# OPD always samples the student through a resident colocated vLLM engine, while the HF/PEFT
|
|
352
|
+
# trainer model stays resident for the GKD loss forward/backward. Budget the second bf16
|
|
353
|
+
# weight copy plus a viable KV pool through the training step. ``use_vllm`` is intentionally
|
|
354
|
+
# ignored for OPD; it only exists for legacy GRPO sizing callers.
|
|
355
|
+
rollout_concurrency = opd_rollout_concurrency(batch_size, group_size)
|
|
356
|
+
rollout = weights + max(
|
|
357
|
+
_KV_CAP, _resident_kv_gb(eff_b, seq_len, rollout_concurrency, fp8_kv=fp8_kv)
|
|
358
|
+
)
|
|
331
359
|
# opd's gkd loss forward materializes DENSE logits — there is NO fused cross-entropy: the
|
|
332
360
|
# student forward yields full-sequence bf16 logits [seq, vocab], then the completion rows are
|
|
333
361
|
# gathered in fp32 [completion, vocab] for the logsumexp. The SFT fused path budgets ZERO
|
|
@@ -357,8 +385,11 @@ def estimate_vram_gb(
|
|
|
357
385
|
logits_fwd = (seq_len * 2 + completion * 4) * vocab
|
|
358
386
|
logits_bwd = (seq_len * 2 + completion * 4) * vocab
|
|
359
387
|
logits = (logits_fwd + logits_bwd) / 1e9
|
|
360
|
-
return base + activations + logits
|
|
361
|
-
fused
|
|
388
|
+
return base + rollout + activations + logits
|
|
389
|
+
# Actual TRL SFT keeps fused CE disabled (see worker/sft.py), so dense logits materialize even
|
|
390
|
+
# for long-context / >=3B models. Callers can pass sft_fused_ce=True only for theoretical
|
|
391
|
+
# comparisons; the default must mirror the worker.
|
|
392
|
+
fused = False if sft_fused_ce is None else bool(sft_fused_ce)
|
|
362
393
|
pd = sft_per_device(batch_size, seq_len=seq_len, vocab=vocab, fused=fused)
|
|
363
394
|
activations = _ACT_COEF * pd * (seq_len / 1024.0) * width
|
|
364
395
|
# Don't clamp to budget: pd=1 is irreducible and the logits can exceed the budget at near-2048 ctx.
|
|
@@ -516,7 +547,7 @@ def model_required_vram_gb(
|
|
|
516
547
|
except (TypeError, ValueError):
|
|
517
548
|
return default
|
|
518
549
|
|
|
519
|
-
max_tokens = _pos_int(_g(train, "
|
|
550
|
+
max_tokens = _pos_int(_g(train, "max_completion_tokens"), None)
|
|
520
551
|
_algo = (algorithm or "").lower()
|
|
521
552
|
if _algo in ("grpo", "rl"):
|
|
522
553
|
_default_len = grpo_rollout_seq_len(0, max_tokens, thinking)
|
|
@@ -525,10 +556,18 @@ def model_required_vram_gb(
|
|
|
525
556
|
_default_len = opd_rollout_seq_len(0, max_tokens, thinking)
|
|
526
557
|
else:
|
|
527
558
|
_default_len = 1024
|
|
528
|
-
seq_len = _pos_int(_g(train, "
|
|
559
|
+
seq_len = _pos_int(_g(train, "max_context_tokens"), _default_len)
|
|
529
560
|
lora_rank = _pos_int(_g(train, "lora_rank"), 32)
|
|
530
|
-
|
|
531
|
-
|
|
561
|
+
if _algo == "opd":
|
|
562
|
+
from flash.engine.recipe import RECIPE
|
|
563
|
+
|
|
564
|
+
batch_size_default = int(RECIPE.opd.prompts_per_step)
|
|
565
|
+
group_size_default = int(RECIPE.opd.group_size)
|
|
566
|
+
else:
|
|
567
|
+
batch_size_default = _sft_per_device_bs()
|
|
568
|
+
group_size_default = 8
|
|
569
|
+
group_size = _pos_int(_g(train, "group_size"), group_size_default)
|
|
570
|
+
batch_size = _pos_int(_g(train, "batch_size"), batch_size_default)
|
|
532
571
|
|
|
533
572
|
def _need(
|
|
534
573
|
params_b: float,
|
|
@@ -557,17 +596,21 @@ def model_required_vram_gb(
|
|
|
557
596
|
return math.ceil(est * headroom)
|
|
558
597
|
|
|
559
598
|
from flash.catalog import MODELS, vocab_size_for
|
|
560
|
-
from flash.engine.chalk_kernels import chalk_supports_fused_ce_model
|
|
561
599
|
|
|
562
600
|
info = MODELS.get(model_id)
|
|
563
601
|
model_vocab = vocab_size_for(model_id)
|
|
564
|
-
is_grpo =
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
and chalk_supports_fused_ce_model(model_id)
|
|
602
|
+
is_grpo = _algo in ("grpo", "rl")
|
|
603
|
+
is_opd = _algo == "opd"
|
|
604
|
+
is_vllm_rollout = is_grpo or is_opd
|
|
605
|
+
vllm_concurrency = (
|
|
606
|
+
opd_rollout_concurrency(batch_size, group_size) if is_opd else group_size
|
|
570
607
|
)
|
|
608
|
+
# Worker parity: TRL SFT deliberately calls install_chalk_kernels(..., fused_ce=False), because
|
|
609
|
+
# SFTTrainer.compute_loss reads outputs.logits and crashes when fused CE returns logits=None. So
|
|
610
|
+
# every SFT run materializes dense logits, even for long context / >=3B models where the old
|
|
611
|
+
# allocator assumed a fused CE path. Size SFT with fused CE OFF up front or long-context Qwen SFT
|
|
612
|
+
# routes to consumer cards and OOMs on the first backward.
|
|
613
|
+
sft_fused_ce = None if is_grpo else False
|
|
571
614
|
if info is not None:
|
|
572
615
|
params_b = info.params_b # curated, authoritative (required field) — no string parsing
|
|
573
616
|
quant = getattr(info, "quant", "bf16") or "bf16"
|
|
@@ -620,29 +663,39 @@ def model_required_vram_gb(
|
|
|
620
663
|
else:
|
|
621
664
|
floor += grpo_seq_escalation_gb(active_b or params_b, seq_len)
|
|
622
665
|
need = max(need, floor)
|
|
623
|
-
if
|
|
666
|
+
if is_vllm_rollout and use_vllm:
|
|
624
667
|
floor_gb = 24 if (params_b or 0.0) <= 1.0 else int(_VLLM_COLOCATE_FLOOR_GB)
|
|
668
|
+
if is_opd and (params_b or 0.0) >= 2.0:
|
|
669
|
+
floor_gb = max(floor_gb, int(_OPD_VLLM_COLOCATE_FLOOR_GB))
|
|
625
670
|
need = max(need, floor_gb)
|
|
626
671
|
# vLLM KV-cache init preflight: the card must leave a viable cache-block pool
|
|
627
672
|
# under the colocate utilization cap, or the engine dies at init ("No available
|
|
628
673
|
# memory for the cache blocks") on a card the training-peak estimate accepted.
|
|
629
674
|
need = max(
|
|
630
675
|
need,
|
|
631
|
-
grpo_kv_floor_gb(
|
|
676
|
+
grpo_kv_floor_gb(
|
|
677
|
+
params_b or 4.0,
|
|
678
|
+
seq_len,
|
|
679
|
+
vllm_concurrency,
|
|
680
|
+
active_params_b=active_b,
|
|
681
|
+
),
|
|
632
682
|
)
|
|
633
683
|
return need
|
|
634
684
|
params_b = fetch_hf_params_b(model_id)
|
|
635
685
|
if params_b is None:
|
|
636
686
|
return 24
|
|
637
687
|
# Size the uncataloged (model_policy="allow") fallback with the ACTUAL algorithm, not a hardcoded
|
|
638
|
-
# "grpo".
|
|
639
|
-
#
|
|
640
|
-
#
|
|
641
|
-
# _need; do the same here (codex[bot]). The grpo-only escalations below stay gated on is_grpo.
|
|
688
|
+
# "grpo". The cataloged path above already threads `algorithm` through _need; do the same here so
|
|
689
|
+
# open-model OPD uses its own dense-logit + colocated-vLLM estimator. The grpo-only sequence
|
|
690
|
+
# escalation stays gated on is_grpo.
|
|
642
691
|
need = _need(params_b, algorithm, vocab=model_vocab)
|
|
643
692
|
if is_grpo:
|
|
644
693
|
need += grpo_seq_escalation_gb(params_b, seq_len)
|
|
645
|
-
|
|
694
|
+
if is_vllm_rollout:
|
|
695
|
+
floor_gb = 24 if params_b <= 1.0 else int(_VLLM_COLOCATE_FLOOR_GB)
|
|
696
|
+
if is_opd and params_b >= 2.0:
|
|
697
|
+
floor_gb = max(floor_gb, int(_OPD_VLLM_COLOCATE_FLOOR_GB))
|
|
698
|
+
need = max(need, floor_gb, grpo_kv_floor_gb(params_b, seq_len, vllm_concurrency))
|
|
646
699
|
return need
|
|
647
700
|
|
|
648
701
|
|
|
@@ -137,7 +137,7 @@ def grpo_overrides() -> dict:
|
|
|
137
137
|
cfg = {
|
|
138
138
|
"group_size": train.group_size,
|
|
139
139
|
"temperature": train.temperature,
|
|
140
|
-
"max_tokens": train.
|
|
140
|
+
"max_tokens": train.max_completion_tokens,
|
|
141
141
|
"kl_penalty_coef": train.kl_penalty_coef,
|
|
142
142
|
"advantage_clip": train.advantage_clip,
|
|
143
143
|
"thinking_length_penalty_coef": train.thinking_length_penalty_coef,
|
|
@@ -173,7 +173,7 @@ def resolve_grpo_sleep_mode() -> tuple[bool, int, float, bool]:
|
|
|
173
173
|
spec = _w.JOB_SPEC
|
|
174
174
|
train = spec.train if spec else None
|
|
175
175
|
model_id = spec.model if spec else ""
|
|
176
|
-
ctx = int(train.
|
|
176
|
+
ctx = int(train.max_context_tokens if train and train.max_context_tokens else 0)
|
|
177
177
|
gcfg = _w.grpo_overrides()
|
|
178
178
|
group_size = int(gcfg.get("group_size") or RECIPE.rl.group_size)
|
|
179
179
|
lora_rank = int(train.lora_rank) if train and train.lora_rank else 32
|