freesolo-flash-dev 0.2.41__tar.gz → 0.2.42__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.41 → freesolo_flash_dev-0.2.42}/PKG-INFO +1 -1
- freesolo_flash_dev-0.2.42/docs/cli-style/env-setup-survey-dark.png +0 -0
- freesolo_flash_dev-0.2.42/docs/cli-style/env-setup-survey-light.png +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/__init__.py +25 -1
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/commands.py +106 -15
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/render.py +32 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_worker.py +5 -4
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/pyproject.toml +2 -2
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_commands.py +103 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_flash_worker.py +1 -1
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/uv.lock +1 -1
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.dockerignore +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.env.example +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.gitignore +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/Dockerfile +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/LICENSE +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/README.md +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/README.md +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/generate.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/index.html +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/preview.png +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/themed-errors.png +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/train-config-error-after.png +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/train-config-error-before.png +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/kernel-cache.md +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/_channel.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/_fileio.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/_logging.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/_update_check.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/adapter_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/catalog.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/_tty.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/envpush.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cli/training_doc.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/client/config.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/client/http.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/accounting.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/recipe.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/vram.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/adapter.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/finalize.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/gpu_setup.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/grpo.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/hf.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/kernel_warmup.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/lora.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/packing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/rl.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/sft.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/archive_policy.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/envs/registry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/lora_rank.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_hf_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_hf_retry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_http.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_instance.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_instance_bootstrap.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_instance_poll.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_instance_provider.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/_poll.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/lambdalabs/pricing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/preload.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/train/deps.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/runpod/train/endpoints.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/py.typed +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/runner/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/runner/deploy.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/runner/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/serve/pricing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/_locks.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/_runtime.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/app.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/auth.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/billing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/db.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/reconcile.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/server/run_registry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/spec.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/conftest.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_b200_rollout_opt.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_client.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_export.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_grpo_sleep_gate.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_version.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vl_warmstart_recombine.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_vl_weight_sync.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/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.42
|
|
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
|
|
Binary file
|
|
Binary file
|
|
@@ -249,7 +249,31 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
249
249
|
const="multi",
|
|
250
250
|
help="scaffold a multi-turn environment (bounded episode with step_episode / score_episode).",
|
|
251
251
|
)
|
|
252
|
-
setup.
|
|
252
|
+
setup_reason = setup.add_mutually_exclusive_group()
|
|
253
|
+
setup_reason.add_argument(
|
|
254
|
+
"--reasoning",
|
|
255
|
+
dest="reasoning",
|
|
256
|
+
action="store_const",
|
|
257
|
+
const=True,
|
|
258
|
+
help="scaffold configs with reasoning enabled (thinking = true, with a raised token budget).",
|
|
259
|
+
)
|
|
260
|
+
setup_reason.add_argument(
|
|
261
|
+
"--no-reasoning",
|
|
262
|
+
dest="reasoning",
|
|
263
|
+
action="store_const",
|
|
264
|
+
const=False,
|
|
265
|
+
help="scaffold configs without reasoning. This is the default.",
|
|
266
|
+
)
|
|
267
|
+
setup.add_argument(
|
|
268
|
+
"-y",
|
|
269
|
+
"--yes",
|
|
270
|
+
dest="yes",
|
|
271
|
+
action="store_true",
|
|
272
|
+
help="accept defaults without prompting (single-turn, no reasoning).",
|
|
273
|
+
)
|
|
274
|
+
# turn_mode / reasoning default to None (unset) so the scaffold can tell an explicit flag
|
|
275
|
+
# apart from "not chosen yet" and, on an interactive terminal, ask instead of assuming.
|
|
276
|
+
setup.set_defaults(func=cmd_env_setup, turn_mode=None, reasoning=None, yes=False)
|
|
253
277
|
|
|
254
278
|
env_list = env_sub.add_parser("list", help="list local environment sources")
|
|
255
279
|
env_list.set_defaults(func=cmd_env_list)
|
|
@@ -330,14 +330,40 @@ _STARTER_DATASET_MULTITURN_JSONL = """\
|
|
|
330
330
|
"""
|
|
331
331
|
|
|
332
332
|
|
|
333
|
+
_TURN_OPTIONS = [
|
|
334
|
+
("single", "single-turn", "one prompt -> one response"),
|
|
335
|
+
("multi", "multi-turn", "bounded episode: step_episode / score_episode"),
|
|
336
|
+
]
|
|
337
|
+
_REASONING_OPTIONS = [
|
|
338
|
+
("off", "no reasoning", "the model answers directly"),
|
|
339
|
+
("on", "reasoning", "thinking = true; spends more tokens per answer"),
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def _setup_interactive(args) -> bool:
|
|
344
|
+
"""Whether to ask the setup questions interactively.
|
|
345
|
+
|
|
346
|
+
Prompt only on a real terminal a human can answer from. Fall back to defaults (no prompt) when
|
|
347
|
+
--yes is passed, under CI, or when stdin is closed/redirected, so automation never blocks on an
|
|
348
|
+
unanswered prompt. A pseudo-TTY in CI can report isatty()=True, so CI is checked explicitly; a
|
|
349
|
+
closed fd 0 can make sys.stdin None, so that is guarded before .isatty()."""
|
|
350
|
+
if getattr(args, "yes", False):
|
|
351
|
+
return False
|
|
352
|
+
if os.environ.get("CI", "").strip().lower() not in ("", "0", "false", "no"):
|
|
353
|
+
return False
|
|
354
|
+
stdin = sys.stdin
|
|
355
|
+
if stdin is None or not stdin.isatty():
|
|
356
|
+
return False
|
|
357
|
+
return render.styled()
|
|
358
|
+
|
|
359
|
+
|
|
333
360
|
def cmd_env_setup(args) -> int:
|
|
334
|
-
requested_multi = getattr(args, "turn_mode", "single") == "multi"
|
|
335
361
|
starter_env = Path("environment.py")
|
|
336
362
|
dataset = Path("dataset/train.jsonl")
|
|
337
363
|
# An existing environment.py is the authoritative signal for which turn mode this
|
|
338
364
|
# scaffold already uses (the dataset is plain JSONL with no reliable mode marker).
|
|
339
365
|
# Anchor to it so a re-run never leaves a single-turn env beside a multi-turn
|
|
340
|
-
# dataset (or vice versa); the flag only decides the mode when starting fresh.
|
|
366
|
+
# dataset (or vice versa); the flag/answer only decides the mode when starting fresh.
|
|
341
367
|
existing_multi: bool | None = None
|
|
342
368
|
anchor = "environment.py"
|
|
343
369
|
if starter_env.exists():
|
|
@@ -347,15 +373,59 @@ def cmd_env_setup(args) -> int:
|
|
|
347
373
|
# distinctive prompt; use it so we don't drop a single-turn env beside it.
|
|
348
374
|
existing_multi = "secret whole number" in dataset.read_text(encoding="utf-8")
|
|
349
375
|
anchor = "dataset/train.jsonl"
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
376
|
+
|
|
377
|
+
# Resolve the turn mode. An existing scaffold wins (warn if a flag disagrees); otherwise an
|
|
378
|
+
# explicit --single-turn/--multi-turn flag wins; otherwise ask on a terminal, else single-turn.
|
|
379
|
+
flag_mode = getattr(args, "turn_mode", None)
|
|
380
|
+
if existing_multi is not None:
|
|
381
|
+
if flag_mode is not None and (flag_mode == "multi") != existing_multi:
|
|
382
|
+
have = "multi-turn" if existing_multi else "single-turn"
|
|
383
|
+
want = "multi-turn" if flag_mode == "multi" else "single-turn"
|
|
384
|
+
msg = (
|
|
385
|
+
f"existing {anchor} is {have}; keeping it and ignoring --{want}. "
|
|
386
|
+
f"Delete environment.py and dataset/train.jsonl first to re-scaffold as {want}."
|
|
387
|
+
)
|
|
388
|
+
print(render.warn(msg) if render.styled() else f"warning: {msg}", file=sys.stderr)
|
|
389
|
+
multi_turn = existing_multi
|
|
390
|
+
elif flag_mode is not None:
|
|
391
|
+
multi_turn = flag_mode == "multi"
|
|
392
|
+
elif _setup_interactive(args):
|
|
393
|
+
multi_turn = (
|
|
394
|
+
render.select("How does the model interact with your task?", _TURN_OPTIONS) == "multi"
|
|
356
395
|
)
|
|
357
|
-
|
|
358
|
-
|
|
396
|
+
else:
|
|
397
|
+
multi_turn = False
|
|
398
|
+
|
|
399
|
+
# Resolve reasoning. Like the turn mode, an existing config is authoritative: configs are only
|
|
400
|
+
# written when absent, so applying a reasoning flag to an already-scaffolded project would
|
|
401
|
+
# silently no-op (or write one config with reasoning and leave the other without). Anchor to the
|
|
402
|
+
# existing config's `thinking` state and warn if a flag disagrees; otherwise the flag wins;
|
|
403
|
+
# otherwise ask on a terminal; else off.
|
|
404
|
+
rl = Path("configs/rl.toml")
|
|
405
|
+
sft = Path("configs/sft.toml")
|
|
406
|
+
existing_reasoning: bool | None = None
|
|
407
|
+
for cfg in (rl, sft):
|
|
408
|
+
if cfg.exists():
|
|
409
|
+
existing_reasoning = "thinking = true" in cfg.read_text(encoding="utf-8")
|
|
410
|
+
break
|
|
411
|
+
flag_reason = getattr(args, "reasoning", None)
|
|
412
|
+
if existing_reasoning is not None:
|
|
413
|
+
if flag_reason is not None and flag_reason != existing_reasoning:
|
|
414
|
+
have = "reasoning" if existing_reasoning else "no reasoning"
|
|
415
|
+
want = "reasoning" if flag_reason else "no-reasoning"
|
|
416
|
+
msg = (
|
|
417
|
+
f"existing configs are {have}; keeping them and ignoring --{want}. "
|
|
418
|
+
f"Delete configs/rl.toml and configs/sft.toml first to re-scaffold with --{want}."
|
|
419
|
+
)
|
|
420
|
+
print(render.warn(msg) if render.styled() else f"warning: {msg}", file=sys.stderr)
|
|
421
|
+
reasoning = existing_reasoning
|
|
422
|
+
elif flag_reason is not None:
|
|
423
|
+
reasoning = flag_reason
|
|
424
|
+
elif _setup_interactive(args):
|
|
425
|
+
reasoning = render.select("Train with reasoning (thinking)?", _REASONING_OPTIONS) == "on"
|
|
426
|
+
else:
|
|
427
|
+
reasoning = False
|
|
428
|
+
|
|
359
429
|
env_py = _STARTER_ENV_MULTITURN_PY if multi_turn else _STARTER_ENV_PY
|
|
360
430
|
dataset_jsonl = _STARTER_DATASET_MULTITURN_JSONL if multi_turn else _STARTER_DATASET_JSONL
|
|
361
431
|
Path("configs").mkdir(exist_ok=True)
|
|
@@ -373,28 +443,47 @@ def cmd_env_setup(args) -> int:
|
|
|
373
443
|
'id = ""\n\n'
|
|
374
444
|
'# secrets = ["SERPAPI_API_KEY"]\n\n'
|
|
375
445
|
)
|
|
376
|
-
|
|
446
|
+
# `thinking = true` opts the run into reasoning mode. Reasoning shares the generation budget with
|
|
447
|
+
# the answer, so GRPO also gets a raised max_tokens. These strings are empty when reasoning is
|
|
448
|
+
# off, keeping the default scaffold byte-for-byte identical.
|
|
449
|
+
thinking_line = "thinking = true\n" if reasoning else ""
|
|
450
|
+
rl_reasoning_train = (
|
|
451
|
+
"max_tokens = 2048 # reasoning shares this budget with the answer; raised so it isn't truncated\n"
|
|
452
|
+
if reasoning
|
|
453
|
+
else ""
|
|
454
|
+
)
|
|
455
|
+
sft_reasoning_note = (
|
|
456
|
+
"# reasoning is on (thinking = true): each gold `output` must contain a <think>...</think>\n"
|
|
457
|
+
"# block; validate locally with freesolo.datasets.warn_missing_think_tags before a real run.\n"
|
|
458
|
+
if reasoning
|
|
459
|
+
else ""
|
|
460
|
+
)
|
|
377
461
|
if not rl.exists():
|
|
378
462
|
rl.write_text(
|
|
379
463
|
'model = "Qwen/Qwen3.5-4B"\n'
|
|
380
|
-
'algorithm = "grpo"\n
|
|
464
|
+
'algorithm = "grpo"\n'
|
|
465
|
+
f"{thinking_line}"
|
|
466
|
+
"\n"
|
|
381
467
|
f"{env_comment}"
|
|
382
468
|
"[train]\n"
|
|
383
469
|
"steps = 150\n"
|
|
470
|
+
f"{rl_reasoning_train}"
|
|
384
471
|
"lora_rank = 32\n"
|
|
385
472
|
"# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
|
|
386
473
|
"# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
|
|
387
474
|
)
|
|
388
|
-
sft = Path("configs/sft.toml")
|
|
389
475
|
if not sft.exists():
|
|
390
476
|
sft.write_text(
|
|
391
477
|
'model = "Qwen/Qwen3.5-4B"\n'
|
|
392
|
-
'algorithm = "sft"\n
|
|
478
|
+
'algorithm = "sft"\n'
|
|
479
|
+
f"{thinking_line}"
|
|
480
|
+
"\n"
|
|
393
481
|
f"{env_comment}"
|
|
394
482
|
"[train]\n"
|
|
395
483
|
"epochs = 1\n"
|
|
396
484
|
"max_examples = 2 # rows to train on; the starter dataset has 2 (raise as your dataset grows)\n"
|
|
397
485
|
"lora_rank = 32\n"
|
|
486
|
+
f"{sft_reasoning_note}"
|
|
398
487
|
"# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
|
|
399
488
|
"# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
|
|
400
489
|
)
|
|
@@ -768,7 +857,9 @@ def cmd_deploy(args) -> int:
|
|
|
768
857
|
f"OpenAI-compatible base URL: {openai_base} — point clients at this /v1 base, "
|
|
769
858
|
"not the bare endpoint (which 404s on /chat/completions)."
|
|
770
859
|
)
|
|
771
|
-
print(
|
|
860
|
+
print(
|
|
861
|
+
render.arrow(url_note) if render.styled() else f"note: {url_note}", file=sys.stderr
|
|
862
|
+
)
|
|
772
863
|
if dep.get("state") != "dry_run":
|
|
773
864
|
state = dep.get("state", "deploying")
|
|
774
865
|
if state == "failed":
|
|
@@ -273,6 +273,38 @@ def arrow(msg: str) -> str:
|
|
|
273
273
|
return _safe(f"{_paint(_glyph('→', '->'), _ACCENT2)} {_dim(msg)}")
|
|
274
274
|
|
|
275
275
|
|
|
276
|
+
def select(title: str, options: list[tuple[str, str, str]], default: int = 0) -> str:
|
|
277
|
+
"""Themed single-choice prompt; returns the chosen option's value.
|
|
278
|
+
|
|
279
|
+
``options`` is a list of ``(value, label, hint)``. The default option is marked and taken on
|
|
280
|
+
an empty answer (enter). Reads via ``input()`` so it is easy to drive in tests; the caller
|
|
281
|
+
decides *when* to prompt (interactive stdin), so this always prompts when called. On EOF the
|
|
282
|
+
default is returned so a closed stdin never hangs the scaffold."""
|
|
283
|
+
q = _paint(_glyph("?", "?"), _ACCENT, "1")
|
|
284
|
+
print(f"{q} {_bold(_safe(title))}")
|
|
285
|
+
for i, (_value, label, hint) in enumerate(options):
|
|
286
|
+
num = _paint(f"{i + 1})", _ACCENT2)
|
|
287
|
+
lab = _bold(label) if i == default else label
|
|
288
|
+
tail = f" {_dim(_safe(hint))}" if hint else ""
|
|
289
|
+
mark = _paint(" (default)", _GREEN) if i == default else ""
|
|
290
|
+
print(f" {num} {_safe(lab)}{tail}{mark}")
|
|
291
|
+
pointer = _paint(_glyph("›", ">"), _ACCENT2) # noqa: RUF001 (the glyph is the point)
|
|
292
|
+
for _ in range(5):
|
|
293
|
+
try:
|
|
294
|
+
raw = input(f"{pointer} ").strip()
|
|
295
|
+
except EOFError:
|
|
296
|
+
print()
|
|
297
|
+
return options[default][0]
|
|
298
|
+
if not raw:
|
|
299
|
+
return options[default][0]
|
|
300
|
+
if raw.isdigit():
|
|
301
|
+
idx = int(raw) - 1
|
|
302
|
+
if 0 <= idx < len(options):
|
|
303
|
+
return options[idx][0]
|
|
304
|
+
print(note(f"enter 1-{len(options)}, or press enter for the default"))
|
|
305
|
+
return options[default][0]
|
|
306
|
+
|
|
307
|
+
|
|
276
308
|
def money(value: float, decimals: int = 4) -> str:
|
|
277
309
|
return _paint(f"${value:.{decimals}f}", _TEAL)
|
|
278
310
|
|
|
@@ -110,12 +110,13 @@ def _effective_worker_env(spec=None) -> dict[str, str]:
|
|
|
110
110
|
# Chalk is published to PUBLIC PyPI on every version bump (chalk .github/workflows/publish.yml).
|
|
111
111
|
# Pin the exact PUBLIC version so worker + kernel-cache-bake pods install with NO GitHub auth — the
|
|
112
112
|
# chalk repo is INTERNAL, so a git+https default made installs fail wherever GITHUB_TOKEN is absent
|
|
113
|
-
# (bake pod, tokenless workers). freesolo-chalk 0.5.
|
|
114
|
-
# replaced
|
|
115
|
-
DEFAULT_CHALK_VERSION
|
|
113
|
+
# (bake pod, tokenless workers). freesolo-chalk 0.5.2 = chalk dev->main sync #44 (standalone, Liger
|
|
114
|
+
# fully replaced; adds arch-TUNED gdn_gated_rmsnorm + lora on sm89/sm90/sm100, MoE grouped-GEMM,
|
|
115
|
+
# serving surface, MiniCPM/Llama kernels). Bump DEFAULT_CHALK_VERSION when the merged kernel surface moves.
|
|
116
|
+
DEFAULT_CHALK_VERSION = "0.5.2"
|
|
116
117
|
DEFAULT_CHALK_SPEC = f"freesolo-chalk=={DEFAULT_CHALK_VERSION}"
|
|
117
118
|
# Provenance only (kernel-cache fingerprint / traceability): the chalk commit this version was cut from.
|
|
118
|
-
LATEST_CHALK_MAIN_SHA = "
|
|
119
|
+
LATEST_CHALK_MAIN_SHA = "37b2fb9e1a123ceb902ba6ffc4ed182182c6e7d7"
|
|
119
120
|
|
|
120
121
|
|
|
121
122
|
def chalk_extra_pip(spec=None) -> list[str]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.42"
|
|
4
4
|
description = "Flash — managed LoRA post-training (SFT/GRPO) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -106,7 +106,7 @@ artifacts = ["flash/py.typed"]
|
|
|
106
106
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
107
107
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
108
108
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
109
|
-
version = "0.2.
|
|
109
|
+
version = "0.2.42"
|
|
110
110
|
|
|
111
111
|
[tool.pytest.ini_options]
|
|
112
112
|
pythonpath = ["."]
|
|
@@ -8,6 +8,7 @@ the remaining commands are covered without a server.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import io
|
|
11
|
+
import types
|
|
11
12
|
|
|
12
13
|
import pytest
|
|
13
14
|
|
|
@@ -474,6 +475,108 @@ def test_env_setup_scaffolds_grpo_and_sft_configs(monkeypatch, tmp_path, capsys)
|
|
|
474
475
|
assert "TRAINING.md" in out
|
|
475
476
|
|
|
476
477
|
|
|
478
|
+
def test_env_setup_default_omits_reasoning(monkeypatch, tmp_path) -> None:
|
|
479
|
+
# Non-interactive (pytest stdin is not a tty) with no flags stays on today's scaffold: no
|
|
480
|
+
# reasoning knobs land in either config.
|
|
481
|
+
monkeypatch.chdir(tmp_path)
|
|
482
|
+
assert _run(["env", "setup"]) == 0
|
|
483
|
+
rl = (tmp_path / "configs/rl.toml").read_text()
|
|
484
|
+
sft = (tmp_path / "configs/sft.toml").read_text()
|
|
485
|
+
assert "thinking = true" not in rl
|
|
486
|
+
assert "thinking = true" not in sft
|
|
487
|
+
assert "max_tokens" not in rl
|
|
488
|
+
assert "EnvironmentSingleTurn" in (tmp_path / "environment.py").read_text()
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def test_env_setup_reasoning_flag_enables_thinking(monkeypatch, tmp_path) -> None:
|
|
492
|
+
monkeypatch.chdir(tmp_path)
|
|
493
|
+
assert _run(["env", "setup", "--reasoning"]) == 0
|
|
494
|
+
rl = (tmp_path / "configs/rl.toml").read_text()
|
|
495
|
+
sft = (tmp_path / "configs/sft.toml").read_text()
|
|
496
|
+
assert "thinking = true" in rl
|
|
497
|
+
assert "thinking = true" in sft
|
|
498
|
+
# GRPO raises the generation budget so reasoning does not truncate the answer.
|
|
499
|
+
assert "max_tokens = 2048" in rl
|
|
500
|
+
# SFT can't share a token budget it doesn't generate; it gets the gold think-tag guidance instead.
|
|
501
|
+
assert "warn_missing_think_tags" in sft
|
|
502
|
+
assert "max_tokens" not in sft
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def test_env_setup_no_reasoning_flag_is_explicit_off(monkeypatch, tmp_path) -> None:
|
|
506
|
+
monkeypatch.chdir(tmp_path)
|
|
507
|
+
assert _run(["env", "setup", "--no-reasoning"]) == 0
|
|
508
|
+
assert "thinking = true" not in (tmp_path / "configs/rl.toml").read_text()
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def test_env_setup_multi_turn_flag_scaffolds_multiturn(monkeypatch, tmp_path) -> None:
|
|
512
|
+
monkeypatch.chdir(tmp_path)
|
|
513
|
+
assert _run(["env", "setup", "--multi-turn"]) == 0
|
|
514
|
+
assert "EnvironmentMultiTurn" in (tmp_path / "environment.py").read_text()
|
|
515
|
+
assert "secret whole number" in (tmp_path / "dataset/train.jsonl").read_text()
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def test_env_setup_interactive_survey_picks_multi_and_reasoning(monkeypatch, tmp_path) -> None:
|
|
519
|
+
# A real terminal: the two survey questions are asked and answered "2" (multi-turn) then
|
|
520
|
+
# "2" (reasoning). FLASH_STYLE forces the themed path; a fake stdin reports a tty; input()
|
|
521
|
+
# is stubbed so no real keypress is read. CI is cleared so the guard doesn't force defaults.
|
|
522
|
+
monkeypatch.chdir(tmp_path)
|
|
523
|
+
monkeypatch.delenv("CI", raising=False)
|
|
524
|
+
monkeypatch.setenv("FLASH_STYLE", "1")
|
|
525
|
+
monkeypatch.setattr("sys.stdin", types.SimpleNamespace(isatty=lambda: True))
|
|
526
|
+
answers = iter(["2", "2"])
|
|
527
|
+
monkeypatch.setattr("builtins.input", lambda *a, **k: next(answers))
|
|
528
|
+
assert _run(["env", "setup"]) == 0
|
|
529
|
+
assert "EnvironmentMultiTurn" in (tmp_path / "environment.py").read_text()
|
|
530
|
+
rl = (tmp_path / "configs/rl.toml").read_text()
|
|
531
|
+
assert "thinking = true" in rl
|
|
532
|
+
assert "max_tokens = 2048" in rl
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def test_env_setup_interactive_enter_takes_defaults(monkeypatch, tmp_path) -> None:
|
|
536
|
+
# Pressing enter (empty answer) at both questions selects the marked defaults: single-turn,
|
|
537
|
+
# no reasoning — identical to the non-interactive scaffold.
|
|
538
|
+
monkeypatch.chdir(tmp_path)
|
|
539
|
+
monkeypatch.delenv("CI", raising=False)
|
|
540
|
+
monkeypatch.setenv("FLASH_STYLE", "1")
|
|
541
|
+
monkeypatch.setattr("sys.stdin", types.SimpleNamespace(isatty=lambda: True))
|
|
542
|
+
monkeypatch.setattr("builtins.input", lambda *a, **k: "")
|
|
543
|
+
assert _run(["env", "setup"]) == 0
|
|
544
|
+
env_py = (tmp_path / "environment.py").read_text()
|
|
545
|
+
assert "EnvironmentSingleTurn" in env_py
|
|
546
|
+
assert "EnvironmentMultiTurn" not in env_py
|
|
547
|
+
assert "thinking = true" not in (tmp_path / "configs/rl.toml").read_text()
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def test_env_setup_under_ci_never_prompts(monkeypatch, tmp_path) -> None:
|
|
551
|
+
# Even with a tty and themed output, CI=true must fall back to defaults instead of blocking on
|
|
552
|
+
# a prompt. input() raises so a regression (actually prompting) fails loudly.
|
|
553
|
+
monkeypatch.chdir(tmp_path)
|
|
554
|
+
monkeypatch.setenv("CI", "true")
|
|
555
|
+
monkeypatch.setenv("FLASH_STYLE", "1")
|
|
556
|
+
monkeypatch.setattr("sys.stdin", types.SimpleNamespace(isatty=lambda: True))
|
|
557
|
+
|
|
558
|
+
def _boom(*a, **k):
|
|
559
|
+
raise AssertionError("prompted under CI")
|
|
560
|
+
|
|
561
|
+
monkeypatch.setattr("builtins.input", _boom)
|
|
562
|
+
assert _run(["env", "setup"]) == 0
|
|
563
|
+
assert "EnvironmentSingleTurn" in (tmp_path / "environment.py").read_text()
|
|
564
|
+
assert "thinking = true" not in (tmp_path / "configs/rl.toml").read_text()
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def test_env_setup_reasoning_flag_warns_when_configs_exist(monkeypatch, tmp_path, capsys) -> None:
|
|
568
|
+
# First scaffold (no reasoning), then re-run with --reasoning: the existing configs win and the
|
|
569
|
+
# command warns instead of silently ignoring the flag or writing mismatched configs.
|
|
570
|
+
monkeypatch.chdir(tmp_path)
|
|
571
|
+
assert _run(["env", "setup"]) == 0
|
|
572
|
+
capsys.readouterr()
|
|
573
|
+
assert _run(["env", "setup", "--reasoning"]) == 0
|
|
574
|
+
err = capsys.readouterr().err
|
|
575
|
+
assert "existing configs are no reasoning" in err
|
|
576
|
+
assert "ignoring --reasoning" in err
|
|
577
|
+
assert "thinking = true" not in (tmp_path / "configs/rl.toml").read_text()
|
|
578
|
+
|
|
579
|
+
|
|
477
580
|
def test_unknown_run_errors_surface_as_nonzero_exit(monkeypatch, capsys) -> None:
|
|
478
581
|
from flash.client import ApiError
|
|
479
582
|
|
|
@@ -166,7 +166,7 @@ def test_chalk_extra_pip_defaults_to_latest_main_without_spec(monkeypatch):
|
|
|
166
166
|
assert chalk_extra_pip() == [DEFAULT_CHALK_SPEC]
|
|
167
167
|
# public PyPI pin so tokenless bake/worker pods can pip-install (chalk repo is internal)
|
|
168
168
|
assert DEFAULT_CHALK_SPEC.startswith("freesolo-chalk==")
|
|
169
|
-
assert DEFAULT_CHALK_SPEC == "freesolo-chalk==0.5.
|
|
169
|
+
assert DEFAULT_CHALK_SPEC == "freesolo-chalk==0.5.2"
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def test_chalk_extra_pip_adds_spec_when_set(monkeypatch):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/bake-kernel-cache.yml
RENAMED
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/main-source-guard.yml
RENAMED
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/notify-tests-repo.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/.github/workflows/version-parity.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docker/Dockerfile.kernelcache.relayer
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/train-config-error-after.png
RENAMED
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/docs/cli-style/train-config-error-before.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/kernel_warmup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.41 → freesolo_flash_dev-0.2.42}/flash/engine/worker/perf/__init__.py
RENAMED
|
File without changes
|