freesolo-flash-dev 1.2.61__tar.gz → 1.2.63__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.61 → freesolo_flash_dev-1.2.63}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/multimodal.py +135 -19
- freesolo_flash_dev-1.2.63/flash/engine/huggingface.py +61 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/dataset_profile.py +4 -7
- freesolo_flash_dev-1.2.63/flash/engine/profiling/image_tokens.py +294 -0
- freesolo_flash_dev-1.2.63/flash/engine/profiling/sft_image_rows.py +226 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/sft_workload.py +144 -156
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/tokenizer.py +1 -4
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/sft.py +41 -2
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/prefetch.py +3 -37
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/chatml_mask.py +73 -42
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/prompts.py +2 -2
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/verl_config.py +2 -2
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/runs.py +7 -5
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/pyproject.toml +2 -2
- freesolo_flash_dev-1.2.63/tests/capture_image_sft_processor_oracle.py +23 -0
- freesolo_flash_dev-1.2.63/tests/fixtures/image_sft_processor_oracle.json +1 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_controlled_experiment_repairs.py +4 -1
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_dataset_profile.py +255 -11
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flash_worker.py +7 -5
- freesolo_flash_dev-1.2.63/tests/test_image_sft_markers.py +337 -0
- freesolo_flash_dev-1.2.63/tests/test_image_sft_processor_parity.py +549 -0
- freesolo_flash_dev-1.2.63/tests/test_image_tokens.py +464 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_multimodal_training.py +1 -1
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_train.py +97 -6
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.env.example +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/README.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/fused_experts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/spec_persistence.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/patches.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/reward_module.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/preparation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_fused_expert_warmstart.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_multiturn_failure_exit.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_persisted_spec_envelope.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_spec_contract_bytes.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_child_plugins.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/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.63
|
|
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
|
|
@@ -9,6 +9,7 @@ import json
|
|
|
9
9
|
import urllib.parse
|
|
10
10
|
from dataclasses import dataclass
|
|
11
11
|
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
12
13
|
|
|
13
14
|
MAX_IMAGES_PER_EXAMPLE = 8
|
|
14
15
|
MAX_IMAGE_SOURCE_BYTES = 20 * 1024 * 1024
|
|
@@ -140,20 +141,32 @@ def _validate_dimensions(width: int, height: int) -> int:
|
|
|
140
141
|
return pixels * 3
|
|
141
142
|
|
|
142
143
|
|
|
143
|
-
def
|
|
144
|
+
def inspect_image_bytes(data: bytes) -> tuple[int, int, int]:
|
|
145
|
+
"""Validate one image's header and return its (decoded_rgb_bytes, width, height).
|
|
146
|
+
|
|
147
|
+
Reads the header only: the pixels are not decoded here.
|
|
148
|
+
"""
|
|
144
149
|
try:
|
|
145
150
|
from PIL import Image
|
|
146
151
|
except ImportError as exc:
|
|
147
152
|
raise RuntimeError("Pillow is required for multimodal image training") from exc
|
|
148
153
|
try:
|
|
149
154
|
with Image.open(io.BytesIO(data)) as image:
|
|
150
|
-
return
|
|
155
|
+
return (
|
|
156
|
+
_validate_dimensions(image.width, image.height),
|
|
157
|
+
image.width,
|
|
158
|
+
image.height,
|
|
159
|
+
)
|
|
151
160
|
except ValueError:
|
|
152
161
|
raise
|
|
153
162
|
except Exception as exc:
|
|
154
163
|
raise ValueError("image source is not a valid image") from exc
|
|
155
164
|
|
|
156
165
|
|
|
166
|
+
def _inspect_image_bytes(data: bytes) -> int:
|
|
167
|
+
return inspect_image_bytes(data)[0]
|
|
168
|
+
|
|
169
|
+
|
|
157
170
|
def _pil_descriptor(image: object) -> str:
|
|
158
171
|
width = int(getattr(image, "width", 0) or 0)
|
|
159
172
|
height = int(getattr(image, "height", 0) or 0)
|
|
@@ -165,14 +178,26 @@ def _pil_descriptor(image: object) -> str:
|
|
|
165
178
|
return _descriptor("bytes", base64.b64encode(data).decode("ascii"))
|
|
166
179
|
|
|
167
180
|
|
|
168
|
-
def normalize_image_source(
|
|
169
|
-
|
|
181
|
+
def normalize_image_source(
|
|
182
|
+
source: object,
|
|
183
|
+
package_root: str | Path | None,
|
|
184
|
+
*,
|
|
185
|
+
defer_validation: bool = False,
|
|
186
|
+
) -> str:
|
|
187
|
+
"""Convert one supported image source to an Arrow-safe descriptor.
|
|
188
|
+
|
|
189
|
+
``defer_validation`` skips the per-source pixel inspection for EVERY source kind, for a caller
|
|
190
|
+
that validates the resulting descriptors itself. Profiling does exactly that, through one cached
|
|
191
|
+
pass that bounds total decode work; inspecting here as well would decode each image twice and
|
|
192
|
+
charge only some kinds to that budget. Every other caller validates eagerly.
|
|
193
|
+
"""
|
|
170
194
|
root = Path(package_root) if package_root is not None else None
|
|
171
195
|
if isinstance(source, bytearray):
|
|
172
196
|
source = bytes(source)
|
|
173
197
|
if isinstance(source, bytes):
|
|
174
198
|
_check_source_size(len(source))
|
|
175
|
-
|
|
199
|
+
if not defer_validation:
|
|
200
|
+
_inspect_image_bytes(source)
|
|
176
201
|
return _descriptor("bytes", base64.b64encode(source).decode("ascii"))
|
|
177
202
|
if _is_pil_image(source):
|
|
178
203
|
return _pil_descriptor(source)
|
|
@@ -183,7 +208,8 @@ def normalize_image_source(source: object, package_root: str | Path | None) -> s
|
|
|
183
208
|
scheme = parsed.scheme.lower()
|
|
184
209
|
if scheme == "data":
|
|
185
210
|
data = _data_uri_bytes(value)
|
|
186
|
-
|
|
211
|
+
if not defer_validation:
|
|
212
|
+
_inspect_image_bytes(data)
|
|
187
213
|
return _descriptor("data_uri", value)
|
|
188
214
|
if scheme in {"http", "https"}:
|
|
189
215
|
# flash never fetches a user-supplied URL server-side. download the image ahead of time
|
|
@@ -198,8 +224,10 @@ def normalize_image_source(source: object, package_root: str | Path | None) -> s
|
|
|
198
224
|
if scheme:
|
|
199
225
|
raise ValueError(f"unsupported image URL scheme: {scheme}")
|
|
200
226
|
path = _package_image_path(value, root)
|
|
201
|
-
|
|
202
|
-
|
|
227
|
+
descriptor = _descriptor("path", path.relative_to(root.resolve()).as_posix())
|
|
228
|
+
if not defer_validation:
|
|
229
|
+
_inspect_image_bytes(path.read_bytes())
|
|
230
|
+
return descriptor
|
|
203
231
|
|
|
204
232
|
|
|
205
233
|
def _image_source_from_block(block: dict) -> object | None:
|
|
@@ -284,7 +312,11 @@ def text_only_prompt_messages(messages: list[dict]) -> list[dict]:
|
|
|
284
312
|
return stripped
|
|
285
313
|
|
|
286
314
|
|
|
287
|
-
def _reject_literal_image_placeholder(
|
|
315
|
+
def _reject_literal_image_placeholder(
|
|
316
|
+
text: str,
|
|
317
|
+
message_index: int,
|
|
318
|
+
markers: tuple[str, ...] = (IMAGE_TEACHER_PLACEHOLDER, IMAGE_PAD_TOKEN),
|
|
319
|
+
) -> None:
|
|
288
320
|
"""Reject prompt text that already contains a reserved image marker.
|
|
289
321
|
|
|
290
322
|
two distinct markers, one reason. the rendered prompt marks image positions with
|
|
@@ -298,8 +330,12 @@ def _reject_literal_image_placeholder(text: str, message_index: int) -> None:
|
|
|
298
330
|
contributes a run the renderer never produced -- and a run from text can make up for an image
|
|
299
331
|
the provider silently dropped, which is exactly the failure the guard exists to catch. keeping
|
|
300
332
|
it out of the source text is what makes "one run per image" mean what it says.
|
|
333
|
+
|
|
334
|
+
``markers`` narrows the set for callers where only one of the two is live. local sft training
|
|
335
|
+
never renders the teacher placeholder, so a literal ``<|media_pad|>`` there is ordinary text
|
|
336
|
+
for a qwen tokenizer and rejecting it would be a false refusal.
|
|
301
337
|
"""
|
|
302
|
-
for marker in
|
|
338
|
+
for marker in markers:
|
|
303
339
|
if marker in text:
|
|
304
340
|
raise ValueError(
|
|
305
341
|
f"message {message_index} text contains the reserved image marker "
|
|
@@ -364,8 +400,14 @@ def normalize_prompt_images(
|
|
|
364
400
|
record: dict,
|
|
365
401
|
messages: list[dict],
|
|
366
402
|
package_root: str | Path | None,
|
|
403
|
+
*,
|
|
404
|
+
defer_validation: bool = False,
|
|
367
405
|
) -> NormalizedImages:
|
|
368
|
-
"""Normalize prompt image blocks and top-level fields without mutating the record.
|
|
406
|
+
"""Normalize prompt image blocks and top-level fields without mutating the record.
|
|
407
|
+
|
|
408
|
+
``defer_validation`` is forwarded to :func:`normalize_image_source`; see it for when a caller
|
|
409
|
+
may skip the per-source pixel inspection.
|
|
410
|
+
"""
|
|
369
411
|
if not isinstance(messages, list) or not all(isinstance(message, dict) for message in messages):
|
|
370
412
|
raise ValueError("prompt messages must be a list of message objects")
|
|
371
413
|
pending = list(_top_level_sources(record))
|
|
@@ -381,14 +423,18 @@ def normalize_prompt_images(
|
|
|
381
423
|
f"example contains {image_count} images, exceeding the "
|
|
382
424
|
f"{MAX_IMAGES_PER_EXAMPLE}-image limit"
|
|
383
425
|
)
|
|
384
|
-
descriptor = normalize_image_source(
|
|
426
|
+
descriptor = normalize_image_source(
|
|
427
|
+
source,
|
|
428
|
+
package_root,
|
|
429
|
+
defer_validation=defer_validation,
|
|
430
|
+
)
|
|
385
431
|
descriptor_bytes += _descriptor_size(descriptor)
|
|
386
432
|
if descriptor_bytes > MAX_TOTAL_IMAGE_DESCRIPTOR_BYTES:
|
|
387
433
|
raise ValueError(
|
|
388
434
|
f"example encoded image descriptors total {descriptor_bytes} bytes, exceeding the "
|
|
389
435
|
f"{MAX_TOTAL_IMAGE_DESCRIPTOR_BYTES}-byte limit"
|
|
390
436
|
)
|
|
391
|
-
source_bytes +=
|
|
437
|
+
source_bytes += _descriptor_source_size(descriptor, package_root)
|
|
392
438
|
if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
|
|
393
439
|
raise ValueError(
|
|
394
440
|
f"example image sources total {source_bytes} bytes, exceeding the "
|
|
@@ -465,10 +511,27 @@ def normalize_prompt_images(
|
|
|
465
511
|
add_descriptor(source)
|
|
466
512
|
image_blocks.append({"type": "image"})
|
|
467
513
|
normalized[first_user]["content"] = [*content, *image_blocks]
|
|
514
|
+
# checked here, on the finished blocks, rather than inside the loop above: string content never
|
|
515
|
+
# enters that loop, and the top-level-image path appends to a message the loop already passed.
|
|
516
|
+
# this is the one point every shape has converged to the same form.
|
|
517
|
+
#
|
|
518
|
+
# the unit is a RUN of consecutive text blocks, not one block, for the reason the teacher
|
|
519
|
+
# renderer already documents: "<|image_" and "pad|>" are each harmless alone and only become
|
|
520
|
+
# the reserved marker once the template concatenates them. an image block ends a run, since the
|
|
521
|
+
# processor puts its own expansion there and user text cannot reach across it.
|
|
522
|
+
for message_index, message in enumerate(normalized):
|
|
523
|
+
text_run: list[str] = []
|
|
524
|
+
for block in message["content"]:
|
|
525
|
+
if block.get("type") == "text":
|
|
526
|
+
text_run.append(block["text"])
|
|
527
|
+
continue
|
|
528
|
+
_reject_literal_image_placeholder("".join(text_run), message_index, (IMAGE_PAD_TOKEN,))
|
|
529
|
+
text_run = []
|
|
530
|
+
_reject_literal_image_placeholder("".join(text_run), message_index, (IMAGE_PAD_TOKEN,))
|
|
468
531
|
return NormalizedImages(normalized, descriptors)
|
|
469
532
|
|
|
470
533
|
|
|
471
|
-
def
|
|
534
|
+
def _descriptor_source_size(descriptor: str, package_root: str | Path | None) -> int:
|
|
472
535
|
kind, value = _parse_descriptor(descriptor)
|
|
473
536
|
if kind == "bytes":
|
|
474
537
|
return len(base64.b64decode(value, validate=True))
|
|
@@ -481,7 +544,8 @@ def descriptor_source_size(descriptor: str, package_root: str | Path | None) ->
|
|
|
481
544
|
raise ValueError("invalid internal image descriptor kind")
|
|
482
545
|
|
|
483
546
|
|
|
484
|
-
def
|
|
547
|
+
def read_descriptor_source(descriptor: str, package_root: str | Path | None) -> bytes:
|
|
548
|
+
"""Read one descriptor's raw source bytes under the per-source size limit."""
|
|
485
549
|
kind, value = _parse_descriptor(descriptor)
|
|
486
550
|
if kind == "bytes":
|
|
487
551
|
try:
|
|
@@ -532,7 +596,7 @@ def image_descriptors_to_data_uris(
|
|
|
532
596
|
source_bytes = 0
|
|
533
597
|
decoded_bytes = 0
|
|
534
598
|
for descriptor in descriptors:
|
|
535
|
-
data =
|
|
599
|
+
data = read_descriptor_source(descriptor, package_root)
|
|
536
600
|
source_bytes += len(data)
|
|
537
601
|
if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
|
|
538
602
|
raise ValueError(
|
|
@@ -553,20 +617,65 @@ def _decode_image_bytes(data: bytes):
|
|
|
553
617
|
from PIL import Image
|
|
554
618
|
except ImportError as exc:
|
|
555
619
|
raise RuntimeError("Pillow is required for multimodal image training") from exc
|
|
620
|
+
converted = None
|
|
556
621
|
try:
|
|
557
622
|
with Image.open(io.BytesIO(data)) as image:
|
|
558
623
|
_validate_dimensions(image.width, image.height)
|
|
559
624
|
image.load()
|
|
560
|
-
|
|
625
|
+
converted = image.convert("RGB")
|
|
626
|
+
converted.load()
|
|
627
|
+
return converted
|
|
561
628
|
except ValueError:
|
|
629
|
+
if converted is not None:
|
|
630
|
+
converted.close()
|
|
562
631
|
raise
|
|
563
632
|
except Exception as exc:
|
|
633
|
+
if converted is not None:
|
|
634
|
+
converted.close()
|
|
564
635
|
raise ValueError("image source is not a valid image") from exc
|
|
565
636
|
|
|
566
637
|
|
|
638
|
+
def messages_with_decoded_images(messages: list[dict], images: list[object]) -> list[dict]:
|
|
639
|
+
"""Bind decoded images into a message list's image blocks, in order.
|
|
640
|
+
|
|
641
|
+
Shared by sft, opd, and grpo: each algorithm decodes the row's descriptors itself and then
|
|
642
|
+
needs the same binding into the chat-template input.
|
|
643
|
+
"""
|
|
644
|
+
image_iter = iter(images)
|
|
645
|
+
prepared = []
|
|
646
|
+
for message in messages:
|
|
647
|
+
copied = dict(message)
|
|
648
|
+
content = copied.get("content")
|
|
649
|
+
if isinstance(content, list):
|
|
650
|
+
blocks = []
|
|
651
|
+
for block in content:
|
|
652
|
+
copied_block = dict(block)
|
|
653
|
+
if copied_block.get("type") == "image":
|
|
654
|
+
copied_block["image"] = next(image_iter)
|
|
655
|
+
blocks.append(copied_block)
|
|
656
|
+
copied["content"] = blocks
|
|
657
|
+
prepared.append(copied)
|
|
658
|
+
try:
|
|
659
|
+
next(image_iter)
|
|
660
|
+
except StopIteration:
|
|
661
|
+
return prepared
|
|
662
|
+
raise ValueError("unused decoded image while preparing multimodal sft tokens")
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def decode_descriptor_pixels(data: bytes) -> None:
|
|
666
|
+
"""Fully decode one image's pixels for validation, then release it.
|
|
667
|
+
|
|
668
|
+
Header inspection accepts an image whose pixel data is truncated or corrupt; only a full decode
|
|
669
|
+
finds that, and the caller wants the failure, not the image.
|
|
670
|
+
"""
|
|
671
|
+
image = _decode_image_bytes(data)
|
|
672
|
+
image.close()
|
|
673
|
+
|
|
674
|
+
|
|
567
675
|
def decode_image_descriptors(
|
|
568
676
|
descriptors: list[str], package_root: str | Path | None
|
|
569
677
|
) -> list[object]:
|
|
678
|
+
"""decode one row to fully loaded rgb images under aggregate limits."""
|
|
570
679
|
if len(descriptors) > MAX_IMAGES_PER_EXAMPLE:
|
|
571
680
|
raise ValueError(
|
|
572
681
|
f"example contains {len(descriptors)} images, exceeding the {MAX_IMAGES_PER_EXAMPLE}-image limit"
|
|
@@ -575,7 +684,7 @@ def decode_image_descriptors(
|
|
|
575
684
|
source_bytes = 0
|
|
576
685
|
decoded_bytes = 0
|
|
577
686
|
for descriptor in descriptors:
|
|
578
|
-
data =
|
|
687
|
+
data = read_descriptor_source(descriptor, package_root)
|
|
579
688
|
source_bytes += len(data)
|
|
580
689
|
if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
|
|
581
690
|
raise ValueError(
|
|
@@ -587,7 +696,14 @@ def decode_image_descriptors(
|
|
|
587
696
|
f"example decoded images exceed the {MAX_TOTAL_DECODED_BYTES}-byte limit"
|
|
588
697
|
)
|
|
589
698
|
prepared.append(data)
|
|
590
|
-
|
|
699
|
+
images: list[Any] = []
|
|
700
|
+
try:
|
|
701
|
+
images.extend(_decode_image_bytes(data) for data in prepared)
|
|
702
|
+
except Exception:
|
|
703
|
+
for image in images:
|
|
704
|
+
image.close()
|
|
705
|
+
raise
|
|
706
|
+
return images
|
|
591
707
|
|
|
592
708
|
|
|
593
709
|
def resolve_image_pad_token_id(processor, tok) -> int:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""hugging face helpers shared across control-plane and worker boundaries."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ModelRevisionKwargs(TypedDict, total=False):
|
|
9
|
+
revision: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def model_revision_kwargs(revision: str = "") -> ModelRevisionKwargs:
|
|
13
|
+
"""return the hub revision keyword for a nonempty pinned revision."""
|
|
14
|
+
return {"revision": revision} if revision else {}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def hub_error_transience(exc: BaseException) -> bool | None:
|
|
18
|
+
"""classify known hub and transport failures, leaving unrelated errors unknown."""
|
|
19
|
+
import httpx
|
|
20
|
+
from huggingface_hub.errors import (
|
|
21
|
+
EntryNotFoundError,
|
|
22
|
+
GatedRepoError,
|
|
23
|
+
HfHubHTTPError,
|
|
24
|
+
LocalEntryNotFoundError,
|
|
25
|
+
RepositoryNotFoundError,
|
|
26
|
+
RevisionNotFoundError,
|
|
27
|
+
)
|
|
28
|
+
from requests.exceptions import ConnectionError as RequestsConnectionError
|
|
29
|
+
from requests.exceptions import RequestException
|
|
30
|
+
from requests.exceptions import Timeout as RequestsTimeout
|
|
31
|
+
|
|
32
|
+
if isinstance(exc, (RepositoryNotFoundError, RevisionNotFoundError, GatedRepoError)):
|
|
33
|
+
return False
|
|
34
|
+
if isinstance(exc, LocalEntryNotFoundError):
|
|
35
|
+
return True
|
|
36
|
+
if isinstance(exc, EntryNotFoundError):
|
|
37
|
+
return False
|
|
38
|
+
if isinstance(
|
|
39
|
+
exc,
|
|
40
|
+
(
|
|
41
|
+
RequestsConnectionError,
|
|
42
|
+
RequestsTimeout,
|
|
43
|
+
httpx.TimeoutException,
|
|
44
|
+
httpx.NetworkError,
|
|
45
|
+
httpx.RemoteProtocolError,
|
|
46
|
+
),
|
|
47
|
+
):
|
|
48
|
+
return True
|
|
49
|
+
if isinstance(exc, HfHubHTTPError):
|
|
50
|
+
response = getattr(exc, "response", None)
|
|
51
|
+
status = getattr(response, "status_code", None)
|
|
52
|
+
if status in {401, 403, 404}:
|
|
53
|
+
return False
|
|
54
|
+
return (
|
|
55
|
+
status is None
|
|
56
|
+
or status in {408, 425, 429}
|
|
57
|
+
or (isinstance(status, int) and 500 <= status <= 599)
|
|
58
|
+
)
|
|
59
|
+
if isinstance(exc, RequestException):
|
|
60
|
+
return False
|
|
61
|
+
return None
|
{freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/dataset_profile.py
RENAMED
|
@@ -333,18 +333,15 @@ def profile_packaged_sft_dataset(
|
|
|
333
333
|
package_root=base_dir,
|
|
334
334
|
contract_text=_contract_text(base_dir, params),
|
|
335
335
|
)
|
|
336
|
-
from flash.content.multimodal import record_has_images
|
|
337
|
-
|
|
338
|
-
if any(record_has_images(row, raw_environment.prompt_messages(row)) for row in rows):
|
|
339
|
-
raise PackagedDatasetUnavailable(
|
|
340
|
-
"image-bearing SFT datasets cannot be profiled on the torch-free control plane. "
|
|
341
|
-
"Use text-only SFT records."
|
|
342
|
-
)
|
|
343
336
|
return prepare_sft_workload(
|
|
344
337
|
spec,
|
|
345
338
|
raw_environment,
|
|
346
339
|
tokenizer_loader=tokenizer_loader,
|
|
347
340
|
producer_version=producer_version,
|
|
341
|
+
# no torch here, so no VL processor: image rows are counted arithmetically from the
|
|
342
|
+
# published vision geometry rather than tokenized through the processor. see
|
|
343
|
+
# flash/engine/profiling/image_tokens.py.
|
|
344
|
+
require_processor=False,
|
|
348
345
|
allow_packing=True,
|
|
349
346
|
packing_support=packing_support,
|
|
350
347
|
source_examples=source_examples,
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""torch-free image token accounting for control-plane sft profiling.
|
|
2
|
+
|
|
3
|
+
one rendered image placeholder expands to the published vision grid size:
|
|
4
|
+
|
|
5
|
+
pad_run = (resized_h // patch_size) * (resized_w // patch_size) // merge_size**2
|
|
6
|
+
|
|
7
|
+
the upstream differential pins the resize policy, and pixels are fully loaded before quoting.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import math
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from flash.content.multimodal import (
|
|
18
|
+
MAX_IMAGES_PER_EXAMPLE,
|
|
19
|
+
MAX_TOTAL_DECODED_BYTES,
|
|
20
|
+
MAX_TOTAL_IMAGE_SOURCE_BYTES,
|
|
21
|
+
decode_descriptor_pixels,
|
|
22
|
+
inspect_image_bytes,
|
|
23
|
+
read_descriptor_source,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# qwen VL publishes its pixel budget under `size`, older revisions under min_pixels/max_pixels.
|
|
27
|
+
# these defaults are the transformers fallbacks, used only when the config declares neither.
|
|
28
|
+
_DEFAULT_MIN_PIXELS = 56 * 56
|
|
29
|
+
_DEFAULT_MAX_PIXELS = 14 * 14 * 4 * 1280
|
|
30
|
+
# the same bound transformers enforces: beyond it smart_resize cannot hold the aspect ratio.
|
|
31
|
+
_MAX_ASPECT_RATIO = 200
|
|
32
|
+
# profile-wide unique full-decode work; per-row decoded bytes keep their separate bound.
|
|
33
|
+
MAX_PROFILE_DECODED_WORK_BYTES = MAX_TOTAL_DECODED_BYTES * MAX_IMAGES_PER_EXAMPLE
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(frozen=True)
|
|
37
|
+
class ImageDescriptorMetadata:
|
|
38
|
+
source_bytes: int
|
|
39
|
+
decoded_rgb_bytes: int
|
|
40
|
+
width: int
|
|
41
|
+
height: int
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class ImageProfileValidationState:
|
|
46
|
+
"""one profile's descriptor cache and cumulative decode budget.
|
|
47
|
+
|
|
48
|
+
a descriptor repeated across rows is validated and decoded ONCE; every occurrence still counts
|
|
49
|
+
toward the per-row limits below, so repetition cannot be used to smuggle a row past them.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
descriptor_metadata: dict[str, ImageDescriptorMetadata] = field(default_factory=dict)
|
|
53
|
+
decoded_work_bytes: int = 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def image_descriptor_metadata(
|
|
57
|
+
descriptors: list[str],
|
|
58
|
+
package_root: str | Path | None,
|
|
59
|
+
validation_state: ImageProfileValidationState,
|
|
60
|
+
*,
|
|
61
|
+
profile_decoded_work_limit: int,
|
|
62
|
+
) -> list[ImageDescriptorMetadata]:
|
|
63
|
+
"""return fully validated dimensions while bounding unique profile decode work."""
|
|
64
|
+
if len(descriptors) > MAX_IMAGES_PER_EXAMPLE:
|
|
65
|
+
raise ValueError(
|
|
66
|
+
f"example contains {len(descriptors)} images, exceeding the {MAX_IMAGES_PER_EXAMPLE}-image limit"
|
|
67
|
+
)
|
|
68
|
+
pending: dict[str, tuple[bytes, ImageDescriptorMetadata]] = {}
|
|
69
|
+
metadata = []
|
|
70
|
+
source_bytes = 0
|
|
71
|
+
decoded_bytes = 0
|
|
72
|
+
new_decoded_work = 0
|
|
73
|
+
for descriptor in descriptors:
|
|
74
|
+
item = validation_state.descriptor_metadata.get(descriptor)
|
|
75
|
+
if item is None:
|
|
76
|
+
prepared = pending.get(descriptor)
|
|
77
|
+
if prepared is None:
|
|
78
|
+
data = read_descriptor_source(descriptor, package_root)
|
|
79
|
+
decoded_rgb_bytes, width, height = inspect_image_bytes(data)
|
|
80
|
+
item = ImageDescriptorMetadata(
|
|
81
|
+
source_bytes=len(data),
|
|
82
|
+
decoded_rgb_bytes=decoded_rgb_bytes,
|
|
83
|
+
width=width,
|
|
84
|
+
height=height,
|
|
85
|
+
)
|
|
86
|
+
pending[descriptor] = data, item
|
|
87
|
+
new_decoded_work += item.decoded_rgb_bytes
|
|
88
|
+
else:
|
|
89
|
+
item = prepared[1]
|
|
90
|
+
metadata.append(item)
|
|
91
|
+
source_bytes += item.source_bytes
|
|
92
|
+
if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
|
|
93
|
+
raise ValueError(
|
|
94
|
+
f"example image sources exceed the {MAX_TOTAL_IMAGE_SOURCE_BYTES}-byte limit"
|
|
95
|
+
)
|
|
96
|
+
decoded_bytes += item.decoded_rgb_bytes
|
|
97
|
+
if decoded_bytes > MAX_TOTAL_DECODED_BYTES:
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"example decoded images exceed the {MAX_TOTAL_DECODED_BYTES}-byte limit"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
prospective_decoded_work = validation_state.decoded_work_bytes + new_decoded_work
|
|
103
|
+
if prospective_decoded_work > profile_decoded_work_limit:
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"profile decoded image work exceeds the {profile_decoded_work_limit}-byte limit"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# fully decode each new descriptor before committing anything: a header that parses but whose
|
|
109
|
+
# pixels are corrupt must fail the row, and must leave neither the cache nor the budget touched.
|
|
110
|
+
for data, _item in pending.values():
|
|
111
|
+
decode_descriptor_pixels(data)
|
|
112
|
+
validation_state.descriptor_metadata.update(
|
|
113
|
+
{descriptor: item for descriptor, (_data, item) in pending.items()}
|
|
114
|
+
)
|
|
115
|
+
validation_state.decoded_work_bytes = prospective_decoded_work
|
|
116
|
+
return metadata
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ImageGeometryUnavailable(ValueError):
|
|
120
|
+
"""the model's published preprocessor config does not describe its image geometry."""
|
|
121
|
+
|
|
122
|
+
def __init__(self, message: str, *, plane_fault: bool = False) -> None:
|
|
123
|
+
super().__init__(message)
|
|
124
|
+
self.plane_fault = plane_fault
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass(frozen=True)
|
|
128
|
+
class ImageGeometry:
|
|
129
|
+
"""the published vision geometry a checkpoint expands images with."""
|
|
130
|
+
|
|
131
|
+
patch_size: int
|
|
132
|
+
merge_size: int
|
|
133
|
+
min_pixels: int
|
|
134
|
+
max_pixels: int
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def factor(self) -> int:
|
|
138
|
+
return self.patch_size * self.merge_size
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def smart_resize(
|
|
142
|
+
height: int, width: int, factor: int, min_pixels: int, max_pixels: int
|
|
143
|
+
) -> tuple[int, int]:
|
|
144
|
+
"""resize dimensions to the qwen vision factor and pixel budget."""
|
|
145
|
+
if height <= 0 or width <= 0:
|
|
146
|
+
raise ValueError("image width and height must be positive")
|
|
147
|
+
if max(height, width) / min(height, width) > _MAX_ASPECT_RATIO:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"absolute aspect ratio must be smaller than {_MAX_ASPECT_RATIO}, "
|
|
150
|
+
f"got {max(height, width) / min(height, width)}"
|
|
151
|
+
)
|
|
152
|
+
h_bar = round(height / factor) * factor
|
|
153
|
+
w_bar = round(width / factor) * factor
|
|
154
|
+
if h_bar * w_bar > max_pixels:
|
|
155
|
+
beta = math.sqrt((height * width) / max_pixels)
|
|
156
|
+
h_bar = max(factor, math.floor(height / beta / factor) * factor)
|
|
157
|
+
w_bar = max(factor, math.floor(width / beta / factor) * factor)
|
|
158
|
+
elif h_bar * w_bar < min_pixels:
|
|
159
|
+
beta = math.sqrt(min_pixels / (height * width))
|
|
160
|
+
h_bar = math.ceil(height * beta / factor) * factor
|
|
161
|
+
w_bar = math.ceil(width * beta / factor) * factor
|
|
162
|
+
return h_bar, w_bar
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _positive_json_int(config: dict, field: str, *, required: bool = False) -> int | None:
|
|
166
|
+
if field not in config or config[field] is None:
|
|
167
|
+
if required:
|
|
168
|
+
raise ImageGeometryUnavailable(
|
|
169
|
+
f"preprocessor config must declare {field} as a positive JSON integer"
|
|
170
|
+
)
|
|
171
|
+
return None
|
|
172
|
+
value = config[field]
|
|
173
|
+
if type(value) is not int or value <= 0:
|
|
174
|
+
raise ImageGeometryUnavailable(
|
|
175
|
+
f"preprocessor config must declare {field} as a positive JSON integer"
|
|
176
|
+
)
|
|
177
|
+
return value
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def geometry_from_preprocessor_config(config: object) -> ImageGeometry:
|
|
181
|
+
"""read published patch, merge, and pixel-budget geometry."""
|
|
182
|
+
if not isinstance(config, dict):
|
|
183
|
+
raise ImageGeometryUnavailable("preprocessor config is not an object")
|
|
184
|
+
patch_size = _positive_json_int(config, "patch_size", required=True)
|
|
185
|
+
merge_size = _positive_json_int(config, "merge_size", required=True)
|
|
186
|
+
assert patch_size is not None
|
|
187
|
+
assert merge_size is not None
|
|
188
|
+
size_value = config.get("size")
|
|
189
|
+
if size_value is None:
|
|
190
|
+
size: dict = {}
|
|
191
|
+
elif isinstance(size_value, dict):
|
|
192
|
+
size = size_value
|
|
193
|
+
else:
|
|
194
|
+
raise ImageGeometryUnavailable("preprocessor config field size must be an object")
|
|
195
|
+
published_min = _positive_json_int(config, "min_pixels")
|
|
196
|
+
published_max = _positive_json_int(config, "max_pixels")
|
|
197
|
+
size_min = _positive_json_int(size, "shortest_edge")
|
|
198
|
+
size_max = _positive_json_int(size, "longest_edge")
|
|
199
|
+
min_pixels = published_min or size_min or _DEFAULT_MIN_PIXELS
|
|
200
|
+
max_pixels = published_max or size_max or _DEFAULT_MAX_PIXELS
|
|
201
|
+
if min_pixels > max_pixels:
|
|
202
|
+
raise ImageGeometryUnavailable(
|
|
203
|
+
f"preprocessor config declares min_pixels {min_pixels} above max_pixels {max_pixels}"
|
|
204
|
+
)
|
|
205
|
+
return ImageGeometry(
|
|
206
|
+
patch_size=patch_size,
|
|
207
|
+
merge_size=merge_size,
|
|
208
|
+
min_pixels=min_pixels,
|
|
209
|
+
max_pixels=max_pixels,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def load_image_geometry(model_id: str, revision: str = "") -> ImageGeometry:
|
|
214
|
+
"""Fetch the model's published image geometry from the hub without importing torch."""
|
|
215
|
+
import os
|
|
216
|
+
|
|
217
|
+
from huggingface_hub import hf_hub_download
|
|
218
|
+
|
|
219
|
+
from flash.engine.huggingface import hub_error_transience, model_revision_kwargs
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
path = hf_hub_download(
|
|
223
|
+
repo_id=model_id,
|
|
224
|
+
filename="preprocessor_config.json",
|
|
225
|
+
token=os.environ.get("HF_TOKEN"),
|
|
226
|
+
**model_revision_kwargs(revision),
|
|
227
|
+
)
|
|
228
|
+
with open(path, encoding="utf-8") as handle:
|
|
229
|
+
config = json.load(handle)
|
|
230
|
+
except ImageGeometryUnavailable:
|
|
231
|
+
raise
|
|
232
|
+
except Exception as exc:
|
|
233
|
+
transience = hub_error_transience(exc)
|
|
234
|
+
raise ImageGeometryUnavailable(
|
|
235
|
+
f"could not read the image geometry published by {model_id!r}; an image-bearing sft "
|
|
236
|
+
"dataset cannot be quoted without it",
|
|
237
|
+
# a downloaded local config that cannot be read is plane state, while generic worker
|
|
238
|
+
# prefetch os errors remain non-retriable at their caller boundary.
|
|
239
|
+
plane_fault=transience is True or (transience is None and isinstance(exc, OSError)),
|
|
240
|
+
) from exc
|
|
241
|
+
return geometry_from_preprocessor_config(config)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def image_pad_tokens(width: int, height: int, geometry: ImageGeometry) -> int:
|
|
245
|
+
"""The number of pad tokens one image of this size expands to."""
|
|
246
|
+
resized_h, resized_w = smart_resize(
|
|
247
|
+
height,
|
|
248
|
+
width,
|
|
249
|
+
geometry.factor,
|
|
250
|
+
geometry.min_pixels,
|
|
251
|
+
geometry.max_pixels,
|
|
252
|
+
)
|
|
253
|
+
patches = (resized_h // geometry.patch_size) * (resized_w // geometry.patch_size)
|
|
254
|
+
return patches // (geometry.merge_size * geometry.merge_size)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def descriptor_pad_tokens(
|
|
258
|
+
descriptors: list[str],
|
|
259
|
+
package_root: str | Path | None,
|
|
260
|
+
geometry: ImageGeometry,
|
|
261
|
+
validation_state: ImageProfileValidationState,
|
|
262
|
+
) -> list[int]:
|
|
263
|
+
"""return each descriptor occurrence's validated pad-token run length."""
|
|
264
|
+
metadata = image_descriptor_metadata(
|
|
265
|
+
descriptors,
|
|
266
|
+
package_root,
|
|
267
|
+
validation_state,
|
|
268
|
+
profile_decoded_work_limit=MAX_PROFILE_DECODED_WORK_BYTES,
|
|
269
|
+
)
|
|
270
|
+
return [image_pad_tokens(item.width, item.height, geometry) for item in metadata]
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def expand_image_pad_runs(
|
|
274
|
+
input_ids: list[int], pad_token_id: int, pad_counts: list[int]
|
|
275
|
+
) -> list[int]:
|
|
276
|
+
"""expand each rendered image placeholder to its processor pad run."""
|
|
277
|
+
expanded: list[int] = []
|
|
278
|
+
seen = 0
|
|
279
|
+
for token_id in input_ids:
|
|
280
|
+
if token_id == pad_token_id:
|
|
281
|
+
if seen >= len(pad_counts):
|
|
282
|
+
raise ValueError(
|
|
283
|
+
"the rendered prompt contains more image placeholders than the example "
|
|
284
|
+
"supplied images"
|
|
285
|
+
)
|
|
286
|
+
expanded.extend([pad_token_id] * pad_counts[seen])
|
|
287
|
+
seen += 1
|
|
288
|
+
else:
|
|
289
|
+
expanded.append(token_id)
|
|
290
|
+
if seen != len(pad_counts):
|
|
291
|
+
raise ValueError(
|
|
292
|
+
f"the rendered prompt contains {seen} image placeholder(s), expected {len(pad_counts)}"
|
|
293
|
+
)
|
|
294
|
+
return expanded
|