freesolo-flash-dev 1.2.60__tar.gz → 1.2.61__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/multimodal.py +12 -3
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/backend_common.py +1 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/glue.py +58 -3
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/overrides.py +2 -26
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/multiturn.py +26 -7
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/multi_turn.py +82 -5
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/verl_config.py +2 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/capabilities.py +10 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/adapter.py +7 -4
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/pyproject.toml +2 -2
- freesolo_flash_dev-1.2.61/tests/test_catalog_only_models.py +88 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_train.py +4 -22
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_rl_train.py +246 -1
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_spec_and_validation.py +0 -11
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verifiers.py +48 -1
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/uv.lock +1 -1
- freesolo_flash_dev-1.2.60/tests/test_catalog_only_models.py +0 -357
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.env.example +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/README.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/fused_experts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/spec_persistence.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/chatml_mask.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/patches.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/reward_module.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/preparation.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_fused_expert_warmstart.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_multiturn_failure_exit.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_persisted_spec_envelope.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_spec_contract_bytes.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_child_plugins.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_zero2_sharding_gate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.61
|
|
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
|
|
@@ -250,13 +250,22 @@ def record_has_images(record: dict, messages: list[dict] | None = None) -> bool:
|
|
|
250
250
|
return True
|
|
251
251
|
for message in messages or []:
|
|
252
252
|
content = message.get("content") if isinstance(message, dict) else None
|
|
253
|
-
if
|
|
254
|
-
isinstance(block, dict) and block.get("type") in _IMAGE_BLOCK_TYPES for block in content
|
|
255
|
-
):
|
|
253
|
+
if content_has_images(content):
|
|
256
254
|
return True
|
|
257
255
|
return False
|
|
258
256
|
|
|
259
257
|
|
|
258
|
+
def content_has_images(content: object) -> bool:
|
|
259
|
+
"""Whether one message's ``content`` carries an image block.
|
|
260
|
+
|
|
261
|
+
The single definition of "this message shows the model an image", so a path that cannot carry
|
|
262
|
+
media (the multi-turn GRPO bridge) recognises exactly what the paths that can do.
|
|
263
|
+
"""
|
|
264
|
+
return isinstance(content, list) and any(
|
|
265
|
+
isinstance(block, dict) and block.get("type") in _IMAGE_BLOCK_TYPES for block in content
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
260
269
|
def text_only_prompt_messages(messages: list[dict]) -> list[dict]:
|
|
261
270
|
"""Drop image content blocks while preserving the teacher's message order and text."""
|
|
262
271
|
stripped: list[dict] = []
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/backend_common.py
RENAMED
|
@@ -935,6 +935,7 @@ from flash.engine.worker.verl.capabilities import ( # noqa: E402,F401
|
|
|
935
935
|
resolve_rollout_enforce_eager,
|
|
936
936
|
resolve_verl_loggers,
|
|
937
937
|
resolve_verl_python,
|
|
938
|
+
rollout_mm_processor_cache_overrides,
|
|
938
939
|
rollout_resident_overrides,
|
|
939
940
|
rollout_sleep_unsupported,
|
|
940
941
|
strict_gdn_probe_module,
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/glue.py
RENAMED
|
@@ -20,6 +20,12 @@ from uuid import uuid4
|
|
|
20
20
|
|
|
21
21
|
_ALLOWED_MESSAGE_KEYS = frozenset({"role", "content"})
|
|
22
22
|
_PROBE_PREFIX = "flash-env-glue-probe"
|
|
23
|
+
# the media block types verl's own dataset parser substitutes for a placeholder, and the exact set
|
|
24
|
+
# it then extracts (rl_dataset.py `_build_messages`: `<image>`/`<video>`/`<audio>` become blocks of
|
|
25
|
+
# the matching type, and `_process_multi_modal_info` returns images, videos, audios). duplicated
|
|
26
|
+
# here as literals rather than imported from flash.content.multimodal because this module is copied
|
|
27
|
+
# into the verl child, where flash is not importable -- see the module docstring.
|
|
28
|
+
_MEDIA_BLOCK_TYPES = frozenset({"image", "video", "audio"})
|
|
23
29
|
|
|
24
30
|
|
|
25
31
|
def normalize_token_ids(value) -> list[int]:
|
|
@@ -39,8 +45,53 @@ def normalize_token_ids(value) -> list[int]:
|
|
|
39
45
|
return [int(token_id.item() if hasattr(token_id, "item") else token_id) for token_id in value]
|
|
40
46
|
|
|
41
47
|
|
|
42
|
-
def
|
|
43
|
-
"""
|
|
48
|
+
def content_block_text(content, *, source: str, position: int) -> str:
|
|
49
|
+
"""flatten one openai-style content block list to the text the transcript represents.
|
|
50
|
+
|
|
51
|
+
an image-bearing prompt does NOT reach the child as a string. verl's RLHFDataset rewrites the
|
|
52
|
+
parquet's string content into blocks -- it splits on the `<image>` placeholder and replaces that
|
|
53
|
+
segment with an image block (rl_dataset.py `_build_messages`) -- so `raw_prompt` arrives as
|
|
54
|
+
[{"type": "image", ...}, {"type": "text", "text": ...}] for exactly the multimodal rows flash
|
|
55
|
+
writes. validating that shape as text-only would reject every image episode at turn one.
|
|
56
|
+
|
|
57
|
+
the media blocks are dropped rather than rendered here: they are carried separately, as decoded
|
|
58
|
+
pixels in `multi_modal_data`, and the prompt ids come from the chat template applied to the
|
|
59
|
+
ORIGINAL block list. this text view exists for the transcript and the inter-turn glue, which are
|
|
60
|
+
token-level text operations. a block whose type is neither text nor known media is an error
|
|
61
|
+
rather than a silent drop -- it would mean the model saw something this transcript cannot show.
|
|
62
|
+
"""
|
|
63
|
+
parts = []
|
|
64
|
+
for block in content:
|
|
65
|
+
if not isinstance(block, dict):
|
|
66
|
+
raise ValueError(
|
|
67
|
+
f"{source} message {position} has a content block that is not an object"
|
|
68
|
+
)
|
|
69
|
+
block_type = block.get("type")
|
|
70
|
+
if block_type in _MEDIA_BLOCK_TYPES:
|
|
71
|
+
continue
|
|
72
|
+
if block_type != "text":
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"{source} message {position} has an unsupported content block type "
|
|
75
|
+
f"{block_type!r}; a multi-turn transcript can represent text and media blocks only"
|
|
76
|
+
)
|
|
77
|
+
text = block.get("text")
|
|
78
|
+
if not isinstance(text, str):
|
|
79
|
+
raise ValueError(f"{source} message {position} has a text block without text")
|
|
80
|
+
parts.append(text)
|
|
81
|
+
return "".join(parts)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def validate_transcript_messages(
|
|
85
|
+
messages: list[dict], *, source: str, allow_content_blocks: bool = False
|
|
86
|
+
) -> list[dict]:
|
|
87
|
+
"""require the exact role/content transcript shape the child rollout loops can represent.
|
|
88
|
+
|
|
89
|
+
``allow_content_blocks`` flattens openai-style block lists to their text instead of rejecting
|
|
90
|
+
them. it is OFF by default and opted into only by a caller that has already extracted the media
|
|
91
|
+
out of the ORIGINAL blocks, because dropping to text is lossless only once the pixels are held
|
|
92
|
+
somewhere else. a caller that has not done that extraction must keep raising: silently training
|
|
93
|
+
on a caption whose image was discarded is the failure this default exists to prevent.
|
|
94
|
+
"""
|
|
44
95
|
if not isinstance(messages, list):
|
|
45
96
|
raise ValueError(f"{source} messages must be a list")
|
|
46
97
|
normalized = []
|
|
@@ -62,7 +113,11 @@ def validate_transcript_messages(messages: list[dict], *, source: str) -> list[d
|
|
|
62
113
|
content = message.get("content")
|
|
63
114
|
if not isinstance(role, str) or not role.strip():
|
|
64
115
|
raise ValueError(f"{source} message {position} has an invalid role")
|
|
65
|
-
if
|
|
116
|
+
if allow_content_blocks and isinstance(content, list):
|
|
117
|
+
# a multimodal prompt arrives as content BLOCKS, not a string; flatten to the text this
|
|
118
|
+
# transcript can represent. the media rides separately as decoded pixels.
|
|
119
|
+
content = content_block_text(content, source=source, position=position)
|
|
120
|
+
elif not isinstance(content, str):
|
|
66
121
|
raise ValueError(f"{source} message {position} content must be text for multi-turn")
|
|
67
122
|
normalized.append({"role": role, "content": content})
|
|
68
123
|
return normalized
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/overrides.py
RENAMED
|
@@ -17,6 +17,7 @@ from flash.content.structured_outputs import reasoning_parser_for
|
|
|
17
17
|
from flash.engine.worker.backend_common import (
|
|
18
18
|
agent_loop_workers,
|
|
19
19
|
ray_num_cpus,
|
|
20
|
+
rollout_mm_processor_cache_overrides,
|
|
20
21
|
rollout_resident_overrides,
|
|
21
22
|
shim_marker_file,
|
|
22
23
|
trainer_dtype_overrides,
|
|
@@ -177,32 +178,7 @@ def _actor_rollout_overrides(config: dict, *, max_tokens: int) -> list[str]:
|
|
|
177
178
|
if config.get("mm_encoder_attn_backend")
|
|
178
179
|
else []
|
|
179
180
|
),
|
|
180
|
-
|
|
181
|
-
#
|
|
182
|
-
# the cache is split across two processes. a SENDER half in the frontend replaces an image
|
|
183
|
-
# it has already seen with just its hash; a RECEIVER half in the engine core is supposed to
|
|
184
|
-
# still hold the item that hash names. correctness depends on the two halves staying
|
|
185
|
-
# mirrored, and opd's rollout lifecycle breaks that: every sleep/pause reaches
|
|
186
|
-
# `EngineCore._reset_caches()`, which clears the RECEIVER only. vllm says so in its own
|
|
187
|
-
# source -- "we don't attempt to re-sync the internal caches (P0 sender, P1 receiver)".
|
|
188
|
-
# the sender then keeps sending hash-only requests for images the receiver has dropped, and
|
|
189
|
-
# each one dies on `assert mm_item is not None, f"Expected a cached item for {mm_hash=}"`.
|
|
190
|
-
#
|
|
191
|
-
# that assertion kills the request rather than the run, so the failure surfaces nowhere near
|
|
192
|
-
# the cause: the rollouts come back EMPTY, and verl indexes [-1] into a zero-length reward
|
|
193
|
-
# tensor, so the visible error is an IndexError with no mention of images.
|
|
194
|
-
#
|
|
195
|
-
# 0 is vllm's own disable value -- it assigns exactly this internally -- and it gates BOTH
|
|
196
|
-
# halves, so no hash-only request can be constructed and there is nothing left to desync.
|
|
197
|
-
# the cost is re-preprocessing a repeated image, which is the right trade: an opd rollout
|
|
198
|
-
# batch is small and this is the difference between working and not.
|
|
199
|
-
#
|
|
200
|
-
# it stays unconditional, like `data.image_key` and `limit_images` above, because it is
|
|
201
|
-
# inert on a text job -- with no mm items there is no cache to disable.
|
|
202
|
-
#
|
|
203
|
-
# `mm_processor_cache_gb`, NOT the older `disable_mm_preprocessor_cache`: that argument was
|
|
204
|
-
# removed in vllm 0.13.0, and passing it now aborts server startup as an unknown cli flag.
|
|
205
|
-
"+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb=0",
|
|
181
|
+
*rollout_mm_processor_cache_overrides(),
|
|
206
182
|
# keep the rollout engine RESIDENT for models whose vLLM wake/reload HANGS (catalog
|
|
207
183
|
# sleep_unsupported), exactly as the grpo path does. opd is NOT exempt: main_ppo_sync calls
|
|
208
184
|
# checkpoint_manager.sleep_replicas() during init_workers and again around validation, which
|
|
@@ -209,19 +209,41 @@ class _EpisodePrompt:
|
|
|
209
209
|
|
|
210
210
|
|
|
211
211
|
async def _prepare_episode_prompt(loop_self, raw_prompt) -> _EpisodePrompt:
|
|
212
|
-
"""
|
|
213
|
-
|
|
212
|
+
"""extract the media and render the ids from the ORIGINAL blocks, then validate the transcript.
|
|
213
|
+
|
|
214
|
+
ORDER MATTERS, which is why all three steps live in one function rather than as statements a
|
|
215
|
+
caller could reorder or forget. an image prompt does not arrive as text: verl's RLHFDataset
|
|
216
|
+
rewrites the parquet's string content into blocks, splitting on the `<image>` placeholder and
|
|
217
|
+
substituting an image block (rl_dataset.py `_build_messages`), so `raw_prompt` is
|
|
218
|
+
[{"type": "image", ...}, {"type": "text", ...}] for exactly the rows flash writes for a
|
|
219
|
+
multimodal job. the media has to come out of those ORIGINAL blocks first, or the pixels are gone
|
|
220
|
+
by the time the rollout asks for them -- and validating first would reject the block shape
|
|
221
|
+
outright, which is how multi-turn image rollouts died before the order was pinned here.
|
|
222
|
+
|
|
223
|
+
the media extraction and the chat template both read those original blocks: the pixels live in
|
|
224
|
+
the image/video/audio blocks, and the template needs them in place to emit the placeholder
|
|
225
|
+
tokens the decoded pixels expand into.
|
|
226
|
+
|
|
227
|
+
the validation is a GATE, not a value: this loop generates from `prompt_ids`, so the flattened
|
|
228
|
+
text is discarded. it still runs, because it is what rejects a transcript this loop cannot
|
|
229
|
+
represent (unsupported blocks, tool-call metadata) before the episode is paid for. blocks are
|
|
230
|
+
permitted in that check precisely because the steps above already hold the media and the
|
|
231
|
+
block-rendered ids.
|
|
232
|
+
"""
|
|
233
|
+
messages = [dict(message) for message in raw_prompt]
|
|
234
|
+
multi_modal_data = await loop_self.process_multi_modal_info(messages)
|
|
214
235
|
images = multi_modal_data.get("images")
|
|
215
236
|
videos = multi_modal_data.get("videos")
|
|
216
237
|
audios = multi_modal_data.get("audios")
|
|
217
238
|
mm_processor_kwargs = loop_self._get_mm_processor_kwargs(audios)
|
|
218
239
|
prompt_ids = await loop_self.apply_chat_template(
|
|
219
|
-
|
|
240
|
+
messages,
|
|
220
241
|
images=images,
|
|
221
242
|
videos=videos,
|
|
222
243
|
audios=audios,
|
|
223
244
|
mm_processor_kwargs=mm_processor_kwargs,
|
|
224
245
|
)
|
|
246
|
+
validate_transcript_messages(messages, source="initial prompt", allow_content_blocks=True)
|
|
225
247
|
return _EpisodePrompt(multi_modal_data, mm_processor_kwargs, prompt_ids)
|
|
226
248
|
|
|
227
249
|
|
|
@@ -330,10 +352,7 @@ async def _grpo_run(
|
|
|
330
352
|
agent_loop_output,
|
|
331
353
|
**kwargs,
|
|
332
354
|
):
|
|
333
|
-
|
|
334
|
-
[dict(message) for message in kwargs["raw_prompt"]], source="initial prompt"
|
|
335
|
-
)
|
|
336
|
-
prompt = await _prepare_episode_prompt(self, raw_prompt)
|
|
355
|
+
prompt = await _prepare_episode_prompt(self, kwargs["raw_prompt"])
|
|
337
356
|
prompt_ids = prompt.prompt_ids
|
|
338
357
|
mm_processor_kwargs = prompt.mm_processor_kwargs
|
|
339
358
|
settings = _EpisodeSettings()
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/multi_turn.py
RENAMED
|
@@ -19,6 +19,7 @@ import time
|
|
|
19
19
|
from collections.abc import Callable
|
|
20
20
|
from http.server import BaseHTTPRequestHandler
|
|
21
21
|
|
|
22
|
+
from flash.content.multimodal import content_has_images, message_content_text
|
|
22
23
|
from flash.engine.worker.backend_common import BoundedThreadingHTTPServer
|
|
23
24
|
from flash.engine.worker.score_batcher import ScoreBatcher
|
|
24
25
|
from flash.engine.worker.train.rl.scoring import RolloutScoreRequest, score_rollouts
|
|
@@ -68,6 +69,17 @@ class _BadSession(_BadRequest, KeyError):
|
|
|
68
69
|
return self.args[0] if self.args else ""
|
|
69
70
|
|
|
70
71
|
|
|
72
|
+
class _BadEnvReply(_BadRequest, ValueError):
|
|
73
|
+
"""A reply the environment produced that this transcript cannot carry. Also a ValueError.
|
|
74
|
+
|
|
75
|
+
The property the handler splits on is PERMANENT versus TRANSIENT, and this is permanent: the
|
|
76
|
+
environment will produce the same unrepresentable block on every retry, so it belongs with the
|
|
77
|
+
deliberate rejections rather than with the capacity faults. A bare ValueError here would fall
|
|
78
|
+
to the 503 branch and tell the reader the bridge had a resource problem, when the fix is to
|
|
79
|
+
change the environment's reply -- the same misdirection the 400/503 split exists to prevent.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
|
|
71
83
|
def _request_field(payload: dict, key: str):
|
|
72
84
|
"""Read one required payload field, or reject the request.
|
|
73
85
|
|
|
@@ -104,6 +116,66 @@ def request_session_id(payload: dict) -> str:
|
|
|
104
116
|
# and anything else reaching the handler is this side failing to serve a well-formed request.
|
|
105
117
|
_BAD_REQUEST_ERRORS = (_BadRequest,)
|
|
106
118
|
|
|
119
|
+
|
|
120
|
+
def _reject_unrepresentable_reply_blocks(content: list) -> None:
|
|
121
|
+
"""Refuse every reply block this transcript cannot carry, not just the image ones.
|
|
122
|
+
|
|
123
|
+
``message_content_text`` keeps ``type == "text"`` blocks and joins them, which means any OTHER
|
|
124
|
+
block -- video, audio, a tool-use payload, a type this code has never heard of -- contributes
|
|
125
|
+
nothing and vanishes without a trace. that is the same silent corruption as the stringified
|
|
126
|
+
image: the environment intended the model to see something, the model never saw it, and every
|
|
127
|
+
metric still reports a healthy run. so the flattening below is only allowed to run once the
|
|
128
|
+
content is known to be text and nothing but text.
|
|
129
|
+
"""
|
|
130
|
+
for position, block in enumerate(content):
|
|
131
|
+
if not isinstance(block, dict):
|
|
132
|
+
raise _BadEnvReply(
|
|
133
|
+
f"environment reply content block {position} must be an object, not "
|
|
134
|
+
f"{type(block).__name__}"
|
|
135
|
+
)
|
|
136
|
+
block_type = block.get("type")
|
|
137
|
+
if block_type != "text":
|
|
138
|
+
raise _BadEnvReply(
|
|
139
|
+
f"environment reply content block {position} has unsupported type {block_type!r}; "
|
|
140
|
+
"a multi-turn GRPO environment reply can carry text blocks only"
|
|
141
|
+
)
|
|
142
|
+
if not isinstance(block.get("text"), str):
|
|
143
|
+
raise _BadEnvReply(f"environment reply text block {position} is missing its text")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _env_reply_message(message: dict) -> dict:
|
|
147
|
+
"""one environment reply message, as the role/content text the child transcript can carry.
|
|
148
|
+
|
|
149
|
+
the adapter lets an environment return arbitrary message dicts from ``step_episode``, so a reply
|
|
150
|
+
may carry openai-style content BLOCKS rather than a string. ``str()`` on a block list does not
|
|
151
|
+
fail -- it produces the python repr, and the model then reads a literal
|
|
152
|
+
``[{'type': 'image_url', ...}]`` as its prompt text while every metric reports a healthy run.
|
|
153
|
+
|
|
154
|
+
a block the transcript cannot represent is refused outright instead. the media a rollout
|
|
155
|
+
conditions on is fixed from the initial prompt (see ``_EpisodePrompt``), so a mid-episode image
|
|
156
|
+
cannot reach the engine no matter what this returns; stringifying it would train on the repr of
|
|
157
|
+
a dropped image, and dropping it would train on a turn the environment never wrote. refusing is
|
|
158
|
+
the interim contract until per-turn media is threaded into the rollout, and it is LOUD -- the
|
|
159
|
+
bridge turns a raise into a 400 that fails the episode -- because silence is the actual defect.
|
|
160
|
+
"""
|
|
161
|
+
content = message.get("content")
|
|
162
|
+
if isinstance(content, list):
|
|
163
|
+
# images get their own message ahead of the generic guard: it is the one unsupported block
|
|
164
|
+
# with an action attached, so saying which one it is beats naming the type alone.
|
|
165
|
+
if content_has_images(content):
|
|
166
|
+
raise _BadEnvReply(
|
|
167
|
+
"environment reply carries an image block; multi-turn GRPO conditions every turn on "
|
|
168
|
+
"the media from the INITIAL prompt, so an image returned by step_episode cannot "
|
|
169
|
+
"reach the model. return text, or put the image in the initial prompt"
|
|
170
|
+
)
|
|
171
|
+
_reject_unrepresentable_reply_blocks(content)
|
|
172
|
+
# text-only blocks are a shape this transcript CAN represent exactly, so flatten them
|
|
173
|
+
# through the same definition of "the text of a message" the graders and reward path use.
|
|
174
|
+
return {"role": str(message.get("role", "")), "content": message_content_text(content)}
|
|
175
|
+
# unchanged for every non-block reply, which is what every existing multi-turn env returns.
|
|
176
|
+
return {"role": str(message.get("role", "")), "content": str(message.get("content", ""))}
|
|
177
|
+
|
|
178
|
+
|
|
107
179
|
# size the listen backlog for the full prompts_per_step * group_size connection burst.
|
|
108
180
|
# socketserver's default of 5 resets overflowed clients, and bridge_post intentionally does not retry.
|
|
109
181
|
# a fixed backlog only moves the cliff; linux may clamp this value to somaxconn.
|
|
@@ -263,12 +335,17 @@ class MultiTurnBridge:
|
|
|
263
335
|
return {"terminal": True, "messages": []}
|
|
264
336
|
replies = self._env_call("env_reply", list(state.get("messages") or ()), state)
|
|
265
337
|
terminal = bool(self._env_call("rollout_done", state, self._max_turns))
|
|
338
|
+
if terminal:
|
|
339
|
+
# nothing here is ever shown to the model: the child breaks on `terminal` BEFORE it
|
|
340
|
+
# reads `messages`. env_reply has already recorded these replies into the state that
|
|
341
|
+
# score_episodes reads, so the episode is scored on them either way. validating them
|
|
342
|
+
# for transcript representability would turn a completed episode whose env signed off
|
|
343
|
+
# with an image or a tool payload into a 400 with no reward -- refusing a turn the
|
|
344
|
+
# model was never going to see.
|
|
345
|
+
return {"terminal": True, "messages": []}
|
|
266
346
|
return {
|
|
267
|
-
"terminal":
|
|
268
|
-
"messages": [
|
|
269
|
-
{"role": str(message.get("role", "")), "content": str(message.get("content", ""))}
|
|
270
|
-
for message in replies
|
|
271
|
-
],
|
|
347
|
+
"terminal": False,
|
|
348
|
+
"messages": [_env_reply_message(message) for message in replies],
|
|
272
349
|
}
|
|
273
350
|
|
|
274
351
|
def _score_batch(self, requests: list) -> list:
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/verl_config.py
RENAMED
|
@@ -17,6 +17,7 @@ from flash.engine.profiling.sft_workload import _multimodal_messages_with_images
|
|
|
17
17
|
from flash.engine.worker.backend_common import (
|
|
18
18
|
agent_loop_workers,
|
|
19
19
|
ray_num_cpus,
|
|
20
|
+
rollout_mm_processor_cache_overrides,
|
|
20
21
|
rollout_resident_overrides,
|
|
21
22
|
rollout_sleep_unsupported,
|
|
22
23
|
trainer_dtype_overrides,
|
|
@@ -332,6 +333,7 @@ def _rollout_overrides(cfg: dict) -> list[str]:
|
|
|
332
333
|
),
|
|
333
334
|
# safetensors load format is required for lora rollout on vllm.
|
|
334
335
|
"actor_rollout_ref.rollout.load_format=safetensors",
|
|
336
|
+
*rollout_mm_processor_cache_overrides(),
|
|
335
337
|
# keep the rollout engine RESIDENT for models whose vLLM wake/reload HANGS (catalog
|
|
336
338
|
# sleep_unsupported). shared with the opd driver, which runs the same verl sleep path.
|
|
337
339
|
*rollout_resident_overrides(bool(cfg.get("sleep_unsupported"))),
|
{freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/capabilities.py
RENAMED
|
@@ -758,6 +758,16 @@ def rollout_resident_overrides(sleep_unsupported: bool) -> list[str]:
|
|
|
758
758
|
]
|
|
759
759
|
|
|
760
760
|
|
|
761
|
+
def rollout_mm_processor_cache_overrides() -> list[str]:
|
|
762
|
+
"""disable vllm's split multimodal processor cache for every verl rollout.
|
|
763
|
+
|
|
764
|
+
verl sleep resets the engine-side receiver without resynchronizing the frontend sender, so a
|
|
765
|
+
repeated image can become a hash-only request for an item the receiver no longer holds. zero is
|
|
766
|
+
vllm's disable value for both halves and is inert when a rollout has no multimodal items.
|
|
767
|
+
"""
|
|
768
|
+
return ["+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb=0"]
|
|
769
|
+
|
|
770
|
+
|
|
761
771
|
def trainer_dtype_overrides() -> list[str]:
|
|
762
772
|
"""verl overrides that store the frozen base in bf16 instead of verl's fp32 default.
|
|
763
773
|
|
|
@@ -665,13 +665,16 @@ class FreesoloEnvironment(BaseEnvironment):
|
|
|
665
665
|
state["turn"] = int(state.get("turn", 0)) + 1
|
|
666
666
|
if step.metadata:
|
|
667
667
|
state.setdefault("step_metadata", []).append(step.metadata)
|
|
668
|
-
replies = [dict(message) for message in step.messages]
|
|
669
|
-
|
|
670
|
-
|
|
668
|
+
replies = [deepcopy(dict(message)) for message in step.messages]
|
|
669
|
+
scored_replies = deepcopy(replies)
|
|
670
|
+
state.setdefault("messages", []).extend(scored_replies)
|
|
671
|
+
for message in scored_replies:
|
|
672
|
+
# score_episode receives a structural copy of the environment's raw chat content. the
|
|
673
|
+
# parent bridge flattens only the separate child-bound reply returned below.
|
|
671
674
|
state.setdefault("turns", []).append(
|
|
672
675
|
self._EnvironmentTurn(
|
|
673
676
|
role=str(message.get("role", "")),
|
|
674
|
-
content=
|
|
677
|
+
content=deepcopy(message.get("content", "")),
|
|
675
678
|
)
|
|
676
679
|
)
|
|
677
680
|
return replies
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.61"
|
|
4
4
|
description ="Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -137,7 +137,7 @@ artifacts = ["flash/py.typed"]
|
|
|
137
137
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
138
138
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
139
139
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
140
|
-
version = "1.2.
|
|
140
|
+
version = "1.2.61"
|
|
141
141
|
|
|
142
142
|
[tool.pytest.ini_options]
|
|
143
143
|
pythonpath = ["."]
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Only curated catalog models are trainable + VRAM estimator unit tests (CPU-only, no network).
|
|
2
|
+
|
|
3
|
+
Adding a model means forking Flash and adding a ModelInfo entry to flash/core/catalog.py. There is no
|
|
4
|
+
config key that accepts an uncataloged model: the rejection is catalog membership itself, so it
|
|
5
|
+
holds identically on a managed and a self-hosted plane.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from flash.core.catalog import resolve_model
|
|
13
|
+
from flash.engine.plan.vram import estimate_vram_gb
|
|
14
|
+
from flash.providers.base import get_gpu_info
|
|
15
|
+
from flash.schema import ConfigError, spec_from_dict
|
|
16
|
+
from tests._helpers.specs import raw_spec as _raw
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_an_uncataloged_model_is_rejected_with_the_fork_instruction():
|
|
20
|
+
# The error is the primary documentation for the new workflow -- it is what every rejected
|
|
21
|
+
# user sees, so it must name the concrete next step, not just refuse.
|
|
22
|
+
with pytest.raises(ValueError, match="unsupported model") as ei:
|
|
23
|
+
resolve_model("some-org/some-model", "sft")
|
|
24
|
+
message = str(ei.value)
|
|
25
|
+
assert "fork" in message.lower()
|
|
26
|
+
assert "flash/core/catalog.py" in message
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_catalog_model_resolves_normally():
|
|
30
|
+
info = resolve_model("Qwen/Qwen3.5-4B", "grpo")
|
|
31
|
+
assert info.id == "Qwen/Qwen3.5-4B"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_the_parser_rejects_an_uncataloged_model_before_submit():
|
|
35
|
+
# Rejecting client-side means a fork with a new catalog entry works without touching the
|
|
36
|
+
# plane, and a typo fails locally instead of after a network round trip.
|
|
37
|
+
with pytest.raises(ConfigError) as ei:
|
|
38
|
+
spec_from_dict(_raw(model="acme/unlisted"))
|
|
39
|
+
assert "unsupported model" in str(ei.value)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_model_policy_is_no_longer_an_accepted_config_key():
|
|
43
|
+
# The key is gone, not merely ignored: a config carrying it must fail loudly rather than
|
|
44
|
+
# silently training something other than what it asked for.
|
|
45
|
+
with pytest.raises(ConfigError, match="unknown config key"):
|
|
46
|
+
spec_from_dict(_raw(model="Qwen/Qwen3.5-4B", model_policy="allow"))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_a_catalog_spec_round_trips_without_a_policy_field():
|
|
50
|
+
spec = spec_from_dict(_raw(model="Qwen/Qwen3.5-4B"))
|
|
51
|
+
payload = spec.to_dict()
|
|
52
|
+
assert "model_policy" not in payload
|
|
53
|
+
assert spec_from_dict(payload).model == "Qwen/Qwen3.5-4B"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
# Estimator sanity: calibrated against catalog anchors
|
|
58
|
+
# ---------------------------------------------------------------------------
|
|
59
|
+
def _headroom(params_b: float, algo: str, quant: str, gpu: str) -> str:
|
|
60
|
+
"""The advisory fits/tight/too_big banding, applied straight to the sizing equations.
|
|
61
|
+
|
|
62
|
+
The bands below calibrate live sizing decisions directly against managed GPU capacities.
|
|
63
|
+
"""
|
|
64
|
+
est = estimate_vram_gb(params_b, algo, quant)
|
|
65
|
+
gpu_gb = get_gpu_info(gpu).vram_gb
|
|
66
|
+
if est > gpu_gb * 1.15:
|
|
67
|
+
return "too_big"
|
|
68
|
+
return "tight" if est > gpu_gb * 0.85 else "fits"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.parametrize(
|
|
72
|
+
("params_b", "algo", "quant", "gpu", "expected"),
|
|
73
|
+
[
|
|
74
|
+
(4.0, "grpo", "bf16", "RTX 5090", "fits"), # Qwen3-4B colocate on 32 GB (measured)
|
|
75
|
+
(4.0, "sft", "bf16", "RTX 4090", "fits"),
|
|
76
|
+
(9.65, "sft", "bf16", "RTX 5090", "tight"), # Qwen3.5-9B SFT real logits peak
|
|
77
|
+
(36.0, "sft", "bf16", "RTX 5090", "too_big"), # 72 GB of weights
|
|
78
|
+
(36.0, "grpo", "bf16", "RTX 5090", "too_big"), # 2 bf16 copies + KV >> 32 GB
|
|
79
|
+
],
|
|
80
|
+
)
|
|
81
|
+
def test_estimator_anchors(params_b, algo, quant, gpu, expected):
|
|
82
|
+
# params_b is supplied directly, so this calibrates the SIZING EQUATIONS against known anchors
|
|
83
|
+
# and never resolves the id through the catalog.
|
|
84
|
+
assert _headroom(params_b, algo, quant, gpu) == expected
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_grpo_needs_more_than_sft():
|
|
88
|
+
assert estimate_vram_gb(4.0, "grpo") > estimate_vram_gb(4.0, "sft")
|
|
@@ -21,7 +21,7 @@ from types import SimpleNamespace
|
|
|
21
21
|
|
|
22
22
|
import pytest
|
|
23
23
|
|
|
24
|
-
from flash.engine.worker import opd_train, rl_train, score_batcher
|
|
24
|
+
from flash.engine.worker import backend_common, opd_train, rl_train, score_batcher
|
|
25
25
|
from flash.engine.worker.opd_train import (
|
|
26
26
|
_OPD_PARQUET_WRITE_BATCH_ROWS,
|
|
27
27
|
_BridgePrompt,
|
|
@@ -6064,27 +6064,9 @@ def test_opd_pins_the_blackwell_attention_backends_like_grpo_does():
|
|
|
6064
6064
|
), on
|
|
6065
6065
|
|
|
6066
6066
|
|
|
6067
|
-
def
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
vLLM splits the mm processor cache across two processes: the frontend SENDER replaces an image
|
|
6072
|
-
it has seen before with just its hash, and the engine-core RECEIVER is supposed to still hold
|
|
6073
|
-
the item. OPD's rollout lifecycle clears the receiver on every sleep/pause without clearing the
|
|
6074
|
-
sender, so the sender keeps sending hashes for items the receiver dropped and each request dies
|
|
6075
|
-
on `assert mm_item is not None`. That kills requests, not the run, so what surfaces is empty
|
|
6076
|
-
rollouts and then an IndexError on a zero-length reward tensor.
|
|
6077
|
-
|
|
6078
|
-
Asserted on the parsed VALUE rather than substring presence, because the two ways this
|
|
6079
|
-
regresses are both silent: a nonzero size re-enables the cache, and the pre-0.13 flag name is
|
|
6080
|
-
rejected by vLLM's arg parser at startup, long after the GPU is paid for.
|
|
6081
|
-
"""
|
|
6082
|
-
emitted = build_opd_overrides(_config())
|
|
6083
|
-
overrides = dict(value.split("=", 1) for value in emitted)
|
|
6084
|
-
assert overrides["+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb"] == "0"
|
|
6085
|
-
# `disable_mm_preprocessor_cache` was REMOVED in vllm 0.13.0. it reads like the right knob and
|
|
6086
|
-
# still appears in older verl examples, so pin it out rather than trusting review to catch it.
|
|
6087
|
-
assert not any("disable_mm_preprocessor_cache" in override for override in emitted)
|
|
6067
|
+
def test_opd_unconditionally_disables_the_vllm_multimodal_processor_cache():
|
|
6068
|
+
overrides = build_opd_overrides(_config())
|
|
6069
|
+
assert set(backend_common.rollout_mm_processor_cache_overrides()) <= set(overrides)
|
|
6088
6070
|
|
|
6089
6071
|
|
|
6090
6072
|
def test_both_ray_rollouts_pin_blackwell_attention_from_the_same_resolver():
|