freesolo-flash-dev 1.2.87__tar.gz → 1.2.89__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.87 → freesolo_flash_dev-1.2.89}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/artifacts.py +4 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/fused_experts.py +62 -32
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/lora_rank.py +82 -30
- freesolo_flash_dev-1.2.89/flash/adapters/targets.py +61 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/__init__.py +7 -14
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/push.py +13 -29
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test.py +5 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/train_cost.py +28 -63
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/scaffold/TRAINING.md +14 -2
- freesolo_flash_dev-1.2.89/flash/content/image_descriptors.py +363 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/multimodal.py +261 -253
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/catalog.py +27 -1
- freesolo_flash_dev-1.2.89/flash/core/grpo.py +63 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/spec.py +128 -72
- freesolo_flash_dev-1.2.89/flash/core/spec_persistence.py +109 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/analytical.py +1 -4
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/facts.py +1 -89
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/spec.py +9 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/types.py +6 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/model_config_probe.py +3 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/recipe.py +4 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/image_tokens.py +16 -10
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/reasoning_render.py +4 -10
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/tokenizer.py +9 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/__init__.py +42 -11
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/sft.py +2 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/heartbeat.py +0 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/prefetch.py +3 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/adapter.py +31 -8
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/lora.py +115 -33
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/opd_train.py +35 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/opd_train_runner.py +113 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/rl_train.py +40 -19
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/rl_train_runner.py +181 -20
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/sft_train.py +27 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/sft_train_runner.py +31 -3
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/client.py +35 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/glue.py +455 -30
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/runtime.py +171 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/batching.py +5 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/bridge.py +131 -106
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/bridge.py +167 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/multiturn.py +62 -22
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/replay_guard.py +12 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/runtime.py +3 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/failures.py +11 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/gkd.py +16 -1
- freesolo_flash_dev-1.2.89/flash/engine/worker/train/opd/multiturn_media.py +132 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/overrides.py +14 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/prompts.py +28 -8
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/scoring.py +11 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/state.py +3 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/checkpoints.py +8 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/multiturn.py +152 -87
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/patches.py +253 -24
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/plugin.py +27 -0
- freesolo_flash_dev-1.2.89/flash/engine/worker/train/rl/identity.py +306 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/inputs.py +27 -13
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/multi_turn.py +324 -88
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/reward_module.py +4 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/verl_config.py +39 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/checkpoints.py +48 -10
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/child/plugin.py +7 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/config.py +1 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/checkpoints.py +374 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/child_io.py +9 -0
- freesolo_flash_dev-1.2.89/flash/engine/worker/verl/process_census.py +470 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/adapter.py +3 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/base.py +4 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/identity.py +12 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/loader.py +114 -23
- freesolo_flash_dev-1.2.89/flash/envs/staged.py +490 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap.py +16 -15
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_pip.py +6 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/poll.py +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/worker.py +9 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/weight_cache.py +4 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/realized.py +10 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/__init__.py +6 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/api.py +153 -22
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/jobs.py +1 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/serverless/endpoints.py +3 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/__init__.py +1 -13
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/artifacts.py +114 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/costs.py +0 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/preparation.py +85 -50
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/reconciliation.py +118 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/status.py +34 -27
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/submit.py +17 -21
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/attach.py +39 -11
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/deploy.py +18 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/lifecycle.py +52 -52
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/recovery.py +86 -8
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/seed_submission.py +1 -12
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/transitions.py +0 -3
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/schema/__init__.py +21 -25
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/schema/fields.py +6 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/deploy.py +6 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/export.py +78 -185
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/reconcile.py +8 -10
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/repo_cleanup.py +4 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_broker.py +20 -15
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_errors.py +17 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/db.py +20 -26
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/deps.py +4 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving.py +14 -47
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_revisions.py +25 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_smoke.py +160 -26
- freesolo_flash_dev-1.2.89/flash/teacher/provider_status.py +35 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/retry_contract.py +8 -27
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/pyproject.toml +2 -2
- freesolo_flash_dev-1.2.89/scripts/check_rollout_identity_actor.py +53 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/runner.py +1 -0
- freesolo_flash_dev-1.2.89/tests/fixtures/qwen35_08b_target_metadata.json +101 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_adapter_shard_completeness.py +7 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_agent_flash_cli_contract.py +0 -29
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_allocator.py +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_backend_common.py +30 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_billing_retry.py +2 -94
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cancel_remote.py +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_checkpoints.py +7 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_commands.py +0 -60
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_estimate.py +117 -45
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_render_coverage.py +2 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_controlled_experiment_repairs.py +23 -80
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_analytical.py +0 -16
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_equation.py +2 -10
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_estimate.py +4 -165
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_hardware.py +11 -74
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_dataset_profile.py +87 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_disk_gb.py +30 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_evaluations.py +23 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_push.py +24 -22
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_rate_limit_resolve.py +15 -23
- freesolo_flash_dev-1.2.89/tests/test_env_ref_pinning.py +73 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_test.py +21 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_export.py +103 -277
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flash_worker.py +56 -10
- freesolo_flash_dev-1.2.89/tests/test_fused_expert_warmstart.py +1894 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_params.py +1 -1
- freesolo_flash_dev-1.2.89/tests/test_grpo_process_census.py +561 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_reward_batching.py +12 -1
- freesolo_flash_dev-1.2.89/tests/test_grpo_rollout_contract.py +458 -0
- freesolo_flash_dev-1.2.89/tests/test_grpo_rollout_identity.py +824 -0
- freesolo_flash_dev-1.2.89/tests/test_image_environment_capability.py +92 -0
- freesolo_flash_dev-1.2.89/tests/test_image_incremental_processor.py +583 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_tokens.py +10 -15
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_instance_bootstrap_coverage.py +73 -6
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_jobs.py +201 -4
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lambda_runner.py +23 -7
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lora_rank_coverage.py +43 -0
- freesolo_flash_dev-1.2.89/tests/test_lora_rank_nested_rung.py +84 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lora_rank_preflight.py +52 -10
- freesolo_flash_dev-1.2.89/tests/test_lora_targeting.py +757 -0
- freesolo_flash_dev-1.2.89/tests/test_lora_targeting_pinned_verl.py +240 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_multi_gpu_gate.py +3 -3
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_multimodal_training.py +404 -26
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_oom_escalate_gpu.py +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd.py +44 -14
- freesolo_flash_dev-1.2.89/tests/test_opd_multiturn_failure_exit.py +449 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_replay_guard.py +24 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_resume_safety.py +24 -21
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_train.py +874 -22
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_parasail_teacher.py +317 -29
- freesolo_flash_dev-1.2.89/tests/test_persisted_spec_envelope.py +93 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_routing.py +47 -41
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_teardown_robustness.py +0 -12
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_providers_symmetry.py +40 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_realized_cost.py +48 -44
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_repo_cleanup.py +2 -2
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_resume_on_retry.py +1 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_rl_train.py +1621 -104
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runmgmt.py +300 -58
- freesolo_flash_dev-1.2.89/tests/test_runpod_api_delete.py +155 -0
- freesolo_flash_dev-1.2.89/tests/test_runpod_key_fingerprint.py +400 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serve.py +37 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_api.py +84 -154
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_billing.py +10 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_envs_coverage.py +476 -32
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_train.py +387 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_spec_and_validation.py +278 -87
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_spec_contract_bytes.py +2 -1
- freesolo_flash_dev-1.2.89/tests/test_staged_environment.py +916 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_metrics.py +70 -3
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_timing.py +15 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_teacher_broker.py +514 -58
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_training_controls.py +46 -9
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verifiers.py +96 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_checkpoint_export.py +103 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_child_plugins.py +31 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vl_warmstart_adapter_keys.py +61 -42
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_adapter_download.py +43 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_cross_repo.py +292 -83
- freesolo_flash_dev-1.2.89/tests/test_warmstart_image_adapters.py +222 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_weight_cache.py +3 -1
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_stack.py +7 -5
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_workload_profile.py +1 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/uv.lock +7 -7
- freesolo_flash_dev-1.2.87/flash/core/spec_persistence.py +0 -414
- freesolo_flash_dev-1.2.87/tests/fixtures/math_eval.jsonl +0 -3
- freesolo_flash_dev-1.2.87/tests/fixtures/math_train.jsonl +0 -2
- freesolo_flash_dev-1.2.87/tests/test_env_ref_pinning.py +0 -313
- freesolo_flash_dev-1.2.87/tests/test_fused_expert_warmstart.py +0 -778
- freesolo_flash_dev-1.2.87/tests/test_opd_multiturn_failure_exit.py +0 -170
- freesolo_flash_dev-1.2.87/tests/test_persisted_spec_envelope.py +0 -255
- freesolo_flash_dev-1.2.87/tests/test_runpod_api_delete.py +0 -67
- freesolo_flash_dev-1.2.87/tests/test_runpod_key_fingerprint.py +0 -122
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.env.example +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/dev-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/production-kernel-cache-ready.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/README.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/setup_wandb.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/huggingface.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/sft_image_rows.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/chatml_mask.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/direct_tokens.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/capture_image_sft_processor_oracle.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/fixtures/image_sft_processor_oracle.json +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_sft_markers.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_image_sft_processor_parity.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_source_attestation_flow.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.87 → freesolo_flash_dev-1.2.89}/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.89
|
|
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
|
|
@@ -5,15 +5,13 @@ by it, and the two never share a call stack to check. Spelling one on each side
|
|
|
5
5
|
coincidence, so they are defined once, here.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors", "adapter_model.bin")
|
|
8
|
+
# the peft adapter weights file a deployable adapter must carry.
|
|
9
|
+
ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors",)
|
|
11
10
|
|
|
12
|
-
#
|
|
11
|
+
# a peft save past its shard size splits the weights across `adapter_model-0000N-of-0000M.<ext>`
|
|
13
12
|
# beside an `adapter_model.<ext>.index.json` mapping every tensor key to the shard holding it.
|
|
14
13
|
ADAPTER_SHARD_PREFIX = "adapter_model-"
|
|
15
|
-
ADAPTER_WEIGHT_SUFFIXES = (".safetensors",
|
|
16
|
-
ADAPTER_WEIGHT_INDEX_FILES = tuple(f"{name}.index.json" for name in ADAPTER_WEIGHT_FILES)
|
|
14
|
+
ADAPTER_WEIGHT_SUFFIXES = (".safetensors",)
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
def is_adapter_weight_filename(filename: str) -> bool:
|
|
@@ -9,8 +9,8 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
from flash.adapters.lora_rank import (
|
|
11
11
|
_rank_for_module,
|
|
12
|
-
declared_lora_ranks,
|
|
13
12
|
lora_tensor_rank_disagrees,
|
|
13
|
+
strict_declared_lora_ranks,
|
|
14
14
|
)
|
|
15
15
|
from flash.core.catalog import get_model
|
|
16
16
|
|
|
@@ -31,10 +31,23 @@ _QWEN36_FUSED_TARGET_RUNGS = {
|
|
|
31
31
|
}
|
|
32
32
|
_FUSED_EXPERT_SYNTHETIC_MODULES = frozenset({"experts", "base_layer"})
|
|
33
33
|
_FUSED_EXPERT_WRAPPER_MODULES = ("mlp.experts", "mlp.experts.base_layer")
|
|
34
|
+
_NON_LANGUAGE_LORA_SEGMENTS = frozenset(
|
|
35
|
+
{
|
|
36
|
+
"mtp",
|
|
37
|
+
"multi_modal_projector",
|
|
38
|
+
"patch_embed",
|
|
39
|
+
"visual",
|
|
40
|
+
"vision",
|
|
41
|
+
"vision_encoder",
|
|
42
|
+
"vision_model",
|
|
43
|
+
"vision_tower",
|
|
44
|
+
}
|
|
45
|
+
)
|
|
34
46
|
_INVALID_FUSED_LOCATION = object()
|
|
35
47
|
|
|
36
48
|
_LoraTensor = tuple[str, str, str, tuple[int, ...]]
|
|
37
49
|
_LoraPair = tuple[tuple[int, ...], tuple[int, ...]]
|
|
50
|
+
_LoraPairKeys = tuple[str, str]
|
|
38
51
|
|
|
39
52
|
|
|
40
53
|
def lora_target_parameters(model_id: str | None) -> list[str] | None:
|
|
@@ -67,9 +80,7 @@ def validate_fused_expert_adapter_config(config: Mapping[str, Any], model_id: st
|
|
|
67
80
|
f"adapter for {model_id} must declare exactly the fused expert targets {required}"
|
|
68
81
|
)
|
|
69
82
|
|
|
70
|
-
|
|
71
|
-
_validate_rank_pattern(rank_pattern, model_id)
|
|
72
|
-
declared = declared_lora_ranks(config)
|
|
83
|
+
declared = strict_declared_lora_ranks(config, source=f"adapter for {model_id}")
|
|
73
84
|
unresolved = [target for target in required if _rank_for_module(target, declared) is None]
|
|
74
85
|
if unresolved:
|
|
75
86
|
raise ValueError(
|
|
@@ -109,31 +120,6 @@ def validate_fused_expert_adapter_config(config: Mapping[str, Any], model_id: st
|
|
|
109
120
|
)
|
|
110
121
|
|
|
111
122
|
|
|
112
|
-
def _validate_rank_pattern(rank_pattern: Any, model_id: str) -> None:
|
|
113
|
-
"""Validate positive ranks and PEFT's anchored regex pattern syntax."""
|
|
114
|
-
message = (
|
|
115
|
-
f"adapter for {model_id} rank_pattern must map valid non-empty string patterns "
|
|
116
|
-
"to positive integer ranks"
|
|
117
|
-
)
|
|
118
|
-
if rank_pattern is None:
|
|
119
|
-
return
|
|
120
|
-
if not isinstance(rank_pattern, Mapping):
|
|
121
|
-
raise ValueError(message)
|
|
122
|
-
for pattern, rank in rank_pattern.items():
|
|
123
|
-
if (
|
|
124
|
-
not isinstance(pattern, str)
|
|
125
|
-
or not pattern.strip()
|
|
126
|
-
or not isinstance(rank, int)
|
|
127
|
-
or isinstance(rank, bool)
|
|
128
|
-
or rank <= 0
|
|
129
|
-
):
|
|
130
|
-
raise ValueError(message)
|
|
131
|
-
try:
|
|
132
|
-
re.compile(rf"(.*\.)?({pattern})$")
|
|
133
|
-
except re.error as exc:
|
|
134
|
-
raise ValueError(message) from exc
|
|
135
|
-
|
|
136
|
-
|
|
137
123
|
def _targets_fused_expert_wrapper(module: str) -> bool:
|
|
138
124
|
"""Return whether PEFT suffix matching binds this target to an expert wrapper."""
|
|
139
125
|
return any(
|
|
@@ -161,6 +147,33 @@ def normalize_verl_fused_expert_export(config: dict[str, Any], model_id: str) ->
|
|
|
161
147
|
]
|
|
162
148
|
|
|
163
149
|
|
|
150
|
+
def is_non_language_lora_key(key: str) -> bool:
|
|
151
|
+
"""whether a LoRA tensor key names a non-language (vision, projector, mtp) module."""
|
|
152
|
+
return bool(set(key.lower().split(".")) & _NON_LANGUAGE_LORA_SEGMENTS)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def fused_expert_lora_tensor_pairs(
|
|
156
|
+
tensors: Mapping[str, tuple[int, ...]], config: Mapping[str, Any], model_id: str
|
|
157
|
+
) -> dict[str, _LoraPairKeys] | None:
|
|
158
|
+
"""Return complete canonical pair keys when fused and ordinary topology is exact."""
|
|
159
|
+
expected = _expected_fused_expert_rungs(config, model_id)
|
|
160
|
+
if expected is None:
|
|
161
|
+
return None
|
|
162
|
+
lora_keys = {key: shape for key, shape in tensors.items() if _LORA_FACTOR_PATTERN.search(key)}
|
|
163
|
+
parsed = [
|
|
164
|
+
tensor
|
|
165
|
+
for key, shape in lora_keys.items()
|
|
166
|
+
if (tensor := _parse_lora_tensor(key, shape)) is not None
|
|
167
|
+
]
|
|
168
|
+
if not parsed or len(parsed) != len(lora_keys):
|
|
169
|
+
return None
|
|
170
|
+
if not _has_complete_fused_rungs(parsed, expected, model_id) or not _has_ordinary_evidence(
|
|
171
|
+
parsed, config, expected
|
|
172
|
+
):
|
|
173
|
+
return None
|
|
174
|
+
return _complete_lora_pair_keys(parsed)
|
|
175
|
+
|
|
176
|
+
|
|
164
177
|
def has_complete_fused_expert_tensors(
|
|
165
178
|
tensors: Mapping[str, tuple[int, ...]], config: Mapping[str, Any], model_id: str
|
|
166
179
|
) -> bool:
|
|
@@ -225,7 +238,7 @@ def _expected_fused_expert_rungs(
|
|
|
225
238
|
if catalog_dimensions != Counter(_QWEN36_FUSED_TARGET_DIMENSIONS.values()):
|
|
226
239
|
return None
|
|
227
240
|
|
|
228
|
-
declared =
|
|
241
|
+
declared = strict_declared_lora_ranks(config)
|
|
229
242
|
expected: dict[str, dict[str, _LoraPair]] = {}
|
|
230
243
|
for target in targets:
|
|
231
244
|
rank = _rank_for_module(target, declared)
|
|
@@ -315,15 +328,17 @@ def _has_ordinary_evidence(
|
|
|
315
328
|
for module_path, factor, key, shape in tensors:
|
|
316
329
|
if _is_fused_rung(module_path, fused_rungs):
|
|
317
330
|
continue
|
|
331
|
+
if not module_path.startswith("base_model.model."):
|
|
332
|
+
return False
|
|
318
333
|
matched = tuple(target for target in targets if _anchored_suffix_match(module_path, target))
|
|
319
334
|
if not all_linear and not matched:
|
|
320
|
-
|
|
335
|
+
return False
|
|
321
336
|
evidence.update(matched)
|
|
322
337
|
groups.setdefault(module_path, {})[factor] = (key, shape)
|
|
323
338
|
if not groups or (not all_linear and evidence != set(targets)):
|
|
324
339
|
return False
|
|
325
340
|
|
|
326
|
-
declared =
|
|
341
|
+
declared = strict_declared_lora_ranks(config)
|
|
327
342
|
for module_path, factors in groups.items():
|
|
328
343
|
if _rank_for_module(module_path, declared) is None:
|
|
329
344
|
return False
|
|
@@ -335,6 +350,21 @@ def _has_ordinary_evidence(
|
|
|
335
350
|
return True
|
|
336
351
|
|
|
337
352
|
|
|
353
|
+
def _complete_lora_pair_keys(
|
|
354
|
+
tensors: list[_LoraTensor],
|
|
355
|
+
) -> dict[str, _LoraPairKeys] | None:
|
|
356
|
+
"""Return every canonical module pair without orphan factors."""
|
|
357
|
+
groups: dict[str, dict[str, str]] = {}
|
|
358
|
+
for module_path, factor, key, _shape in tensors:
|
|
359
|
+
factors = groups.setdefault(module_path, {})
|
|
360
|
+
if factor in factors:
|
|
361
|
+
return None
|
|
362
|
+
factors[factor] = key
|
|
363
|
+
if not groups or any(set(factors) != {"A", "B"} for factors in groups.values()):
|
|
364
|
+
return None
|
|
365
|
+
return {module_path: (factors["A"], factors["B"]) for module_path, factors in groups.items()}
|
|
366
|
+
|
|
367
|
+
|
|
338
368
|
def _is_fused_rung(module_path: str, fused_rungs: Mapping[str, Mapping[str, _LoraPair]]) -> bool:
|
|
339
369
|
"""Return whether a module path is one of the exact fused wrapper rungs."""
|
|
340
370
|
return any(
|
|
@@ -105,13 +105,16 @@ def _positive_int(value: Any, *, source: str, field: str) -> int:
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
def _file_identity(file_info: Any) -> str:
|
|
108
|
+
# the producer is `HfApi.list_repo_tree`, which yields `RepoFile` -- whose `__init__` always
|
|
109
|
+
# sets `path`/`size`/`blob_id` and builds `lfs` as a `BlobLfsInfo` (field `sha256`, no `oid`).
|
|
110
|
+
# verified at the declared floor `huggingface-hub>=1.2.0` and at the installed 1.27.0, so the
|
|
111
|
+
# mapping-shaped `lfs` and the `lfs.oid` spelling have no producer in the supported range.
|
|
112
|
+
# `getattr` stays only on `lfs` itself, which is legitimately optional (non-LFS files), and on
|
|
113
|
+
# the entry object, because a listing also yields `RepoFolder` -- no size, no blob_id -- which
|
|
114
|
+
# must fail closed rather than hash to a folder's tree id.
|
|
108
115
|
lfs = getattr(file_info, "lfs", None)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
size = lfs.get("size")
|
|
112
|
-
else:
|
|
113
|
-
oid = getattr(lfs, "sha256", None) or getattr(lfs, "oid", None)
|
|
114
|
-
size = getattr(lfs, "size", None)
|
|
116
|
+
oid = getattr(lfs, "sha256", None)
|
|
117
|
+
size = getattr(lfs, "size", None)
|
|
115
118
|
blob_id = getattr(file_info, "blob_id", None)
|
|
116
119
|
size = size if size is not None else getattr(file_info, "size", None)
|
|
117
120
|
immutable = oid or blob_id
|
|
@@ -281,6 +284,8 @@ def rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
|
|
|
281
284
|
|
|
282
285
|
_LORA_A_INFIX = ".lora_A."
|
|
283
286
|
_LORA_B_INFIX = ".lora_B."
|
|
287
|
+
# PEFT appends this rung for every parameter wrapper nested inside another one.
|
|
288
|
+
_NESTED_WRAPPER_RUNG = ".base_layer"
|
|
284
289
|
|
|
285
290
|
|
|
286
291
|
@dataclass(frozen=True)
|
|
@@ -296,26 +301,9 @@ class DeclaredLoraRanks:
|
|
|
296
301
|
return self.default is not None or bool(self.by_module)
|
|
297
302
|
|
|
298
303
|
|
|
299
|
-
def
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return DeclaredLoraRanks()
|
|
303
|
-
try:
|
|
304
|
-
default = _positive_int(config["r"], source="adapter_config.json", field="r")
|
|
305
|
-
except (KeyError, ValueError):
|
|
306
|
-
default = None
|
|
307
|
-
|
|
308
|
-
by_module: dict[str, int] = {}
|
|
309
|
-
pattern = config.get("rank_pattern")
|
|
310
|
-
if isinstance(pattern, Mapping):
|
|
311
|
-
for module, value in pattern.items():
|
|
312
|
-
try:
|
|
313
|
-
by_module[str(module)] = _positive_int(
|
|
314
|
-
value, source="adapter_config.json", field="rank_pattern"
|
|
315
|
-
)
|
|
316
|
-
except ValueError:
|
|
317
|
-
continue
|
|
318
|
-
|
|
304
|
+
def _declared_lora_rank_context(
|
|
305
|
+
config: Mapping[str, Any], *, default: int | None, by_module: Mapping[str, int]
|
|
306
|
+
) -> DeclaredLoraRanks:
|
|
319
307
|
stacked_rank_modules: list[str] = []
|
|
320
308
|
targets = config.get("target_parameters")
|
|
321
309
|
if isinstance(targets, list):
|
|
@@ -335,6 +323,41 @@ def declared_lora_ranks(config: Mapping[str, Any]) -> DeclaredLoraRanks:
|
|
|
335
323
|
)
|
|
336
324
|
|
|
337
325
|
|
|
326
|
+
def strict_declared_lora_ranks(
|
|
327
|
+
config: Mapping[str, Any], *, source: str = "adapter_config.json"
|
|
328
|
+
) -> DeclaredLoraRanks:
|
|
329
|
+
"""validate and preserve PEFT rank declarations for an authoritative load boundary."""
|
|
330
|
+
if not isinstance(config, Mapping):
|
|
331
|
+
raise ValueError(f"{source} must be an object")
|
|
332
|
+
|
|
333
|
+
default = None
|
|
334
|
+
if "r" in config:
|
|
335
|
+
value = config["r"]
|
|
336
|
+
if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
|
|
337
|
+
raise ValueError(f"{source} r must be a positive integer")
|
|
338
|
+
default = value
|
|
339
|
+
|
|
340
|
+
by_module: dict[str, int] = {}
|
|
341
|
+
if "rank_pattern" in config:
|
|
342
|
+
pattern = config["rank_pattern"]
|
|
343
|
+
if not isinstance(pattern, Mapping):
|
|
344
|
+
raise ValueError(f"{source} rank_pattern must be an object")
|
|
345
|
+
for module, value in pattern.items():
|
|
346
|
+
if not isinstance(module, str) or not module.strip():
|
|
347
|
+
raise ValueError(f"{source} rank_pattern keys must be non-empty strings")
|
|
348
|
+
if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
|
|
349
|
+
raise ValueError(f"{source} rank_pattern values must be positive integers")
|
|
350
|
+
try:
|
|
351
|
+
re.compile(rf"(.*\.)?({module})$")
|
|
352
|
+
except re.error as exc:
|
|
353
|
+
raise ValueError(
|
|
354
|
+
f"{source} rank_pattern contains invalid regex {module!r}"
|
|
355
|
+
) from exc
|
|
356
|
+
by_module[module] = value
|
|
357
|
+
|
|
358
|
+
return _declared_lora_rank_context(config, default=default, by_module=by_module)
|
|
359
|
+
|
|
360
|
+
|
|
338
361
|
def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | None:
|
|
339
362
|
"""Resolve a module's rank with PEFT's ordered, anchored ``rank_pattern`` matching."""
|
|
340
363
|
for module, rank in declared.by_module.items():
|
|
@@ -350,9 +373,27 @@ def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | Non
|
|
|
350
373
|
|
|
351
374
|
|
|
352
375
|
def _module_uses_target_parameters(module_path: str, declared: DeclaredLoraRanks) -> bool:
|
|
353
|
-
"""Whether this serialized module came from one of PEFT's targeted parameters.
|
|
376
|
+
"""Whether this serialized module came from one of PEFT's targeted parameters.
|
|
377
|
+
|
|
378
|
+
PEFT wraps the module that *owns* a targeted parameter, keeping the parameter name off the
|
|
379
|
+
serialized path. When several targeted parameters share one owner, the wrappers nest and every
|
|
380
|
+
wrapper after the first appends a ``base_layer`` rung, so a single owner produces keys like::
|
|
381
|
+
|
|
382
|
+
mlp.experts (the outermost wrapper)
|
|
383
|
+
mlp.experts.base_layer (the one nested inside it)
|
|
384
|
+
|
|
385
|
+
Those inner rungs carry the same stacked axis as the outer one, so peeling the ``base_layer``
|
|
386
|
+
rungs off before matching is what keeps a valid adapter from being measured against the scalar
|
|
387
|
+
rank.
|
|
388
|
+
"""
|
|
389
|
+
candidates = [module_path]
|
|
390
|
+
trimmed = module_path
|
|
391
|
+
while trimmed.endswith(_NESTED_WRAPPER_RUNG):
|
|
392
|
+
trimmed = trimmed[: -len(_NESTED_WRAPPER_RUNG)]
|
|
393
|
+
candidates.append(trimmed)
|
|
354
394
|
return any(
|
|
355
|
-
|
|
395
|
+
candidate == module or candidate.endswith(f".{module}")
|
|
396
|
+
for candidate in candidates
|
|
356
397
|
for module in declared.stacked_rank_modules
|
|
357
398
|
)
|
|
358
399
|
|
|
@@ -409,11 +450,22 @@ def inspect_adapter_config(
|
|
|
409
450
|
raise ValueError(f"could not verify adapter metadata: {source} is not a JSON object")
|
|
410
451
|
if str(config.get("peft_type") or "").strip().upper() != "LORA":
|
|
411
452
|
raise ValueError(f"could not verify adapter metadata: {source} peft_type must be LORA")
|
|
453
|
+
# both fields are REQUIRED, not "checked when present": every warm-start source is a
|
|
454
|
+
# flash-owned adapter resolved from a run or checkpoint reference, and the one exporter every
|
|
455
|
+
# publish path funnels through stamps `base_model_name_or_path = model_id` unconditionally
|
|
456
|
+
# (engine/worker/verl/checkpoints.py) while the builder always sets `task_type = CAUSAL_LM`
|
|
457
|
+
# (engine/worker/model/adapter.py). treating a blank value as "no opinion" made the base-model
|
|
458
|
+
# match SKIP itself, so an adapter trained on a different base passed preflight and was
|
|
459
|
+
# inherited into the run -- the check failing open is worse than an old artifact failing loudly.
|
|
412
460
|
task_type = str(config.get("task_type") or "").strip().upper()
|
|
413
|
-
if task_type
|
|
461
|
+
if task_type != "CAUSAL_LM":
|
|
414
462
|
raise ValueError(f"could not verify adapter metadata: {source} task_type must be CAUSAL_LM")
|
|
415
463
|
base_model = _normalized_model(config.get("base_model_name_or_path"))
|
|
416
|
-
if
|
|
464
|
+
if not base_model:
|
|
465
|
+
raise ValueError(
|
|
466
|
+
f"could not verify adapter metadata: {source} does not name its base model"
|
|
467
|
+
)
|
|
468
|
+
if base_model != _normalized_model(target_model):
|
|
417
469
|
raise ValueError(
|
|
418
470
|
f"train.init_from_adapter base model {base_model!r} does not match target model "
|
|
419
471
|
f"{target_model!r}"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Resolve the exact LoRA module surface for one training job."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from flash.adapters.fused_experts import lora_target_parameters
|
|
11
|
+
from flash.core.catalog import validate_model_for_algorithm
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class LoraTargeting:
|
|
16
|
+
target_modules: str
|
|
17
|
+
target_parameters: list[str] | None
|
|
18
|
+
exclude_modules: str | None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def require_modality_marker(config: Mapping[str, Any], *, source: str) -> None:
|
|
22
|
+
"""Reject an adapter config that carries no ``exclude_modules`` modality marker.
|
|
23
|
+
|
|
24
|
+
Homed here, beside the resolver that WRITES the marker, so the control plane and the worker
|
|
25
|
+
decide this identically -- and called from both. The control plane already downloads this exact
|
|
26
|
+
config during warm-start preparation, so rejecting there costs a submit-time error, while the
|
|
27
|
+
worker-only check that used to be the sole gate could not fire until a GPU had been allocated
|
|
28
|
+
and the adapter re-downloaded. Same rejection, no paid allocation.
|
|
29
|
+
|
|
30
|
+
The worker keeps its own call because it validates the config it actually loads: the two
|
|
31
|
+
processes never share a call stack, so a marker present at preparation is not proof of one in
|
|
32
|
+
the bytes the trainer opens.
|
|
33
|
+
|
|
34
|
+
Every supported install writes the key -- ``peft>=0.19`` serializes ``exclude_modules`` on every
|
|
35
|
+
``LoraConfig``, as null for a multimodal run -- so an absent key means the artifact predates the
|
|
36
|
+
marker entirely and its modality is unknowable. Guessing it is what this rejects: a text-only
|
|
37
|
+
adapter continued as multimodal (or the reverse) trains the wrong module surface and silently
|
|
38
|
+
produces an adapter that serves as a no-op.
|
|
39
|
+
"""
|
|
40
|
+
if "exclude_modules" not in config:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
f"{source} is missing the required exclude_modules modality marker; "
|
|
43
|
+
"unmarked artifacts are unsupported"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def resolve_lora_targeting(model_id: str, *, algorithm: str, multimodal: bool) -> LoraTargeting:
|
|
48
|
+
"""Resolve fresh-training targets without changing an authored warm-start adapter."""
|
|
49
|
+
model = validate_model_for_algorithm(model_id, algorithm)
|
|
50
|
+
exclude_modules = None
|
|
51
|
+
if not multimodal:
|
|
52
|
+
prefix = model.lora_language_prefix.strip(".")
|
|
53
|
+
if not prefix:
|
|
54
|
+
raise ValueError(f"{model_id} has no cataloged text-only LoRA language module prefix")
|
|
55
|
+
escaped = re.escape(prefix)
|
|
56
|
+
exclude_modules = rf"^(?!{escaped}(?:\.|$)).*$"
|
|
57
|
+
return LoraTargeting(
|
|
58
|
+
target_modules="all-linear",
|
|
59
|
+
target_parameters=lora_target_parameters(model_id),
|
|
60
|
+
exclude_modules=exclude_modules,
|
|
61
|
+
)
|
|
@@ -15,12 +15,12 @@ from flash.cli.ui import render
|
|
|
15
15
|
from flash.cli.ui.tty import TtyStatusLine
|
|
16
16
|
from flash.client import (
|
|
17
17
|
ApiClient,
|
|
18
|
-
ApiError,
|
|
19
18
|
ClientError,
|
|
20
19
|
client_from_config,
|
|
21
20
|
save_credentials,
|
|
22
21
|
verify_freesolo_key,
|
|
23
22
|
)
|
|
23
|
+
from flash.client import ApiError as ApiError
|
|
24
24
|
|
|
25
25
|
# `shadowed_login_warning` has no call site left here since the cost quote moved to
|
|
26
26
|
# `.train_cost`, but the estimate tests patch it on THIS module and that quote reads it back
|
|
@@ -380,18 +380,12 @@ def cmd_train(args) -> int:
|
|
|
380
380
|
# dry-run runs submit-time server preflights without allocating a training gpu or charging
|
|
381
381
|
# for training. a rejection surfaces as the server's error with exit status 1. for sft the
|
|
382
382
|
# server reads the packaged dataset file and builds the quote without executing environment.py.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
)
|
|
390
|
-
except ApiError as exc:
|
|
391
|
-
detail = _legacy_train_key_rejection_detail(exc, authored_train_keys)
|
|
392
|
-
if detail is None:
|
|
393
|
-
raise
|
|
394
|
-
raise ApiError(exc.status, detail, detail=detail) from exc
|
|
383
|
+
status = client.create_run(
|
|
384
|
+
payload,
|
|
385
|
+
runtime_secrets=runtime_secrets,
|
|
386
|
+
dry_run=True,
|
|
387
|
+
client_train_schema=client_train_schema,
|
|
388
|
+
)
|
|
395
389
|
compatibility = status.pop("train_schema_compatibility", None)
|
|
396
390
|
_print_train_schema_compatibility(compatibility)
|
|
397
391
|
# the server fails open on a billing-infra problem, so "cost" is only in the validated list
|
|
@@ -979,7 +973,6 @@ from flash.cli.commands.train_cost import ( # noqa: E402,F401
|
|
|
979
973
|
_cmd_train_cost,
|
|
980
974
|
_cmd_train_cost_offline,
|
|
981
975
|
_cmd_train_cost_sft,
|
|
982
|
-
_legacy_train_key_rejection_detail,
|
|
983
976
|
_print_reasoning_loss_warning,
|
|
984
977
|
_print_sft_cost,
|
|
985
978
|
_print_train_schema_compatibility,
|
|
@@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Literal, TypeAlias
|
|
|
18
18
|
from flash._internal.channel import CLI_NAME
|
|
19
19
|
from flash.cli.ui import render
|
|
20
20
|
from flash.cli.ui.tty import TtyStatusLine
|
|
21
|
+
from flash.envs.package.limits import ARCHIVE_MEMBER_LIMIT as _ENV_PUSH_MAX_FILES
|
|
21
22
|
|
|
22
23
|
if TYPE_CHECKING:
|
|
23
24
|
from flash.client.http import ProgressCallback
|
|
@@ -336,11 +337,6 @@ _ENV_PUSH_SECRET_PATTERNS = (
|
|
|
336
337
|
_ENV_PUSH_CODE_SUFFIXES = frozenset({".py", ".pyi"})
|
|
337
338
|
_ENV_PUSH_MAX_TOTAL_BYTES = 256 * 1024 * 1024
|
|
338
339
|
|
|
339
|
-
try:
|
|
340
|
-
from flash.envs.package.limits import ARCHIVE_MEMBER_LIMIT as _ENV_PUSH_MAX_FILES
|
|
341
|
-
except ImportError:
|
|
342
|
-
_ENV_PUSH_MAX_FILES = 5000
|
|
343
|
-
|
|
344
340
|
|
|
345
341
|
def _normalize_env_name(raw: str) -> str | None:
|
|
346
342
|
"""Normalize only the NAME segment; a ``<namespace>/<project>`` prefix passes through verbatim.
|
|
@@ -634,30 +630,18 @@ def _resolve_local_env_entrypoint(path: str | Path) -> tuple[Path, Path, Path, b
|
|
|
634
630
|
include_full_tree = src.is_dir()
|
|
635
631
|
if include_full_tree:
|
|
636
632
|
canonical_entrypoint = src / _ENV_ENTRYPOINT
|
|
637
|
-
if canonical_entrypoint.is_file():
|
|
638
|
-
entrypoint
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
for p in sorted(src.glob("*.py"))
|
|
650
|
-
if not p.name.startswith("__") and p.name != _ENV_EVALUATIONS_SIDECAR
|
|
651
|
-
]
|
|
652
|
-
if len(modules) != 1:
|
|
653
|
-
raise ValueError(
|
|
654
|
-
f"{src} has no environment.py and "
|
|
655
|
-
f"{'no' if not modules else 'multiple'} top-level .py module(s); "
|
|
656
|
-
"add an environment.py entrypoint or pass the exact .py file "
|
|
657
|
-
"for a single-file smoke test."
|
|
658
|
-
)
|
|
659
|
-
env_root = src
|
|
660
|
-
entrypoint = modules[0]
|
|
633
|
+
if not canonical_entrypoint.is_file():
|
|
634
|
+
# a directory package names its entrypoint `environment.py`. that is what `flash env
|
|
635
|
+
# setup` scaffolds and the only layout the docs describe, so a directory without one is
|
|
636
|
+
# rejected rather than guessed at: inferring the entrypoint from "the sole top-level
|
|
637
|
+
# module" made the resolution depend on which OTHER files happened to be present, so
|
|
638
|
+
# adding a second module turned a working push into a rejection.
|
|
639
|
+
raise ValueError(
|
|
640
|
+
f"{src} has no {_ENV_ENTRYPOINT} entrypoint; add one, "
|
|
641
|
+
"or pass the exact .py file for a single-file smoke test."
|
|
642
|
+
)
|
|
643
|
+
entrypoint = canonical_entrypoint
|
|
644
|
+
env_root = src
|
|
661
645
|
elif src.is_file() and src.suffix == ".py":
|
|
662
646
|
env_root = src.parent
|
|
663
647
|
entrypoint = src
|
|
@@ -270,7 +270,11 @@ def _drive_single_turn(env, example: dict, record: dict, *, force_echo: bool = F
|
|
|
270
270
|
|
|
271
271
|
def _new_multi_turn_replay_state(env, example: dict, record: dict) -> dict:
|
|
272
272
|
state = env.new_rollout_state(example)
|
|
273
|
-
|
|
273
|
+
# `prompt` only, never `messages`: the two are not spellings of one field. `new_rollout_state`
|
|
274
|
+
# seeds `messages` with a COPY of `prompt` and appends each turn onto it, so falling back to it
|
|
275
|
+
# records the growing transcript where the frozen initial prefix belongs. every producer sets
|
|
276
|
+
# both, so an absent `prompt` is a corrupt state and `_check_messages` rejects it by name.
|
|
277
|
+
record["prompt"] = _check_messages(state.get("prompt"), "prompt")
|
|
274
278
|
_normalize_prompt_images(env, example, record["prompt"])
|
|
275
279
|
return state
|
|
276
280
|
|