inline-core 1.2.65__tar.gz → 1.2.66__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.
- {inline_core-1.2.65 → inline_core-1.2.66}/CLAUDE.md +16 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/PKG-INFO +3 -3
- {inline_core-1.2.65 → inline_core-1.2.66}/pyproject.toml +13 -5
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/models.py +9 -6
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/trainer.py +20 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_minimaxh3_training.py +12 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_training_models.py +29 -4
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_webui_install.py +37 -2
- {inline_core-1.2.65 → inline_core-1.2.66}/webui.bat +11 -18
- {inline_core-1.2.65 → inline_core-1.2.66}/webui.sh +10 -23
- {inline_core-1.2.65 → inline_core-1.2.66}/.gitignore +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/.python-version +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/README.md +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/main.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/scripts/flux2_train_matrix.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/scripts/minimax_h3_lora_check.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/scripts/minimax_h3_train_matrix.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/scripts/reference.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/components/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/components/conditioning.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/components/interfaces.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/config.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/auto.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/detect.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/memory.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/policy.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/probe.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/device/types.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/errors.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/api.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/constraints.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/fetch.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/handlers.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/importer.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/install.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/loader.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/manifest.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/models.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/paths.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/scanner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/state.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/extensions/tools.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/ffmpeg.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/cache.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/descriptor.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/executor.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/loader_runners.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/primitives.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/registry.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/runners.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/schema.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/topo.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/graph/validate.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/media.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/catalog.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/checkpoint.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/controlspace.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/controlnet.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/embeds.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/provider.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/flux2/variants.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/keymap.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/convert.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/depth_control.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/img2img.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/provider.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/krea2/runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/loaders.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/lora.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/adaln.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/keys.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/load.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/pipeline.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/provider.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vae_keys.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/autoencoder_kl_minimax_h3.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/autoencoder_kl_minimax_h3_audio.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/before_denoise.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/before_encoder.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/decoders.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/denoise.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/encoders.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/modular_blocks_minimax_h3.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/modular_pipeline.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/packing.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/packing_ref2va.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/scheduling_minimax_h3.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/minimaxh3/vendor/transformer_minimax_h3.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/offload.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/pipeline_runtime.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/prepared.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/preprocess/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/preprocess/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/preprocess/runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/references.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/sampling.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/video_params.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/zimage/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/zimage/primitives.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/zimage/provider.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/zimage/requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/models/zimage/runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/config.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/group.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/launch.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/protocol.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/registry.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/parallel/worker.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/context.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/file_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/progress.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/run.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/runtime/video_encode.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/sampling/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/sampling/batch.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/__main__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/app.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/assets.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/bootstrap.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/frontend.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/manager.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/rpc.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/run_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/server/serialize.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/assets.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/config.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/fal.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/frames.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/generation.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/graph_build.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/handlers.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/image_meta.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/models.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/moodboard.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/peaks.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/recipe.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/schema.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/system_stats.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/timeline/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/timeline/compose.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/timeline/ffmpeg.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/timeline/render.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/timeline/resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/training.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/studio/training_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/takes.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/__init__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/__main__.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/arch.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/cache.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/caption.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/dataset.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/h3.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/src/inline_core/training/protocol.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/conftest.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/helpers.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_cache.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_catalog.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_checkpoint.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_config.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_device_detect.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_executor.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_api.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_install.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_manifest.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_scanner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_spine.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_extension_state.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_file_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_controlnet.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_folder.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_training.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_flux2_variants.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_frontend_serving.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_hidden_nodes.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_keymap.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_krea2_convert.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_krea2_depth_control.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_krea2_requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_krea2_runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_loader_runners.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_loaders.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_lora.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_lora_download.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_memory_policy.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_minimaxh3_adaln.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_minimaxh3_keys.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_minimaxh3_load.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_minimaxh3_nodes.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_model_requirements.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_offload_prepared.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_output_kind_contract.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_parallel_group.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_pipeline_cache.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_primitives.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_recipe.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_references.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_rpc_bridge.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_run_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_sampling.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_schema.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_server.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_staged_residency.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_assets.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_fal.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_frames.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_generation.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_graph_build.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_models.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_moodboard.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_multi_reference.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_node_size.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_peaks.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_rpc.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_schema.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_store.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_timeline.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_studio_training.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_take_bytes.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_topo.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_training_arch.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_training_dataset.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_training_resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_validate.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_video_encode.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_video_params.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_xfuser_sampler.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_zimage_primitives.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_zimage_resolve.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/tests/test_zimage_runner.py +0 -0
- {inline_core-1.2.65 → inline_core-1.2.66}/uv.lock +0 -0
|
@@ -126,6 +126,8 @@ between nodes and are never takes.
|
|
|
126
126
|
every stop/start**, taking the models and leaving dangling symlinks in `models/`. This has cost two
|
|
127
127
|
full re-downloads of MiniMax H3 at ~130 GB each. Weights go on the persistent root volume, or on an
|
|
128
128
|
attached volume that survives a restart. Scratch is fine for logs and temporary output only.
|
|
129
|
+
- **`huggingface_hub>=0.32`** - below it `hf_xet` is only an extra, and files over ~50GB (every
|
|
130
|
+
H3 transformer) refuse to download at all.
|
|
129
131
|
- **Models root** - `INLINE_MODELS_DIR`, else `./models`. **Bring your own weights; nothing is
|
|
130
132
|
downloaded.** ComfyUI-style category subfolders (`diffusion_models/`, `vae/`, `text_encoders/`,
|
|
131
133
|
`loras/`, `controlnet/`, `checkpoints/`, `clip_vision/`, `upscale_models/`, `embeddings/`). The
|
|
@@ -233,6 +235,20 @@ real codec that moves tensors lives with the model runner.
|
|
|
233
235
|
vision-language encoder loaded in place of a text one, an unnormalized latent, and a control context
|
|
234
236
|
cast to a quantized weight's `uint8` storage dtype. A unit test cannot see a plausible-but-wrong
|
|
235
237
|
image. Render something and look at it.
|
|
238
|
+
- **Launchers are twins.** `webui.sh` and `webui.bat` change together; only the `launcher` CI job
|
|
239
|
+
can prove the `.bat`, since it cannot run on a dev box.
|
|
240
|
+
- **Match CUDA arches by within-major compatibility, never exactly.** An `sm_8x` cubin runs on any
|
|
241
|
+
`sm_8y` where `y >= x`, so `sm_86` covers Ada's `sm_89`.
|
|
242
|
+
- **Pass the widest `uv` flag that works.** `--no-sources-package` needs uv 0.10+; `--no-sources`
|
|
243
|
+
works back to 0.4 and means the same while torch is the only `[tool.uv.sources]` entry.
|
|
244
|
+
- **An explicit user setting beats a heuristic.** Test `on`/`off` before any auto rule, or the
|
|
245
|
+
control is silently dead for whichever arch the rule excludes.
|
|
246
|
+
- **Report a phase before the slow work, not after.** Progress emitted only on completion makes a
|
|
247
|
+
slow step look like a hung previous phase.
|
|
248
|
+
- **In a `.bat`, `call` anything that might be a `.bat`.** `nvidia-smi` is sometimes a shim, and
|
|
249
|
+
without `call` it takes over the script and never returns.
|
|
250
|
+
- **Log allocated AND reserved VRAM.** `nvidia-smi` shows only reserved, so allocator cache and a
|
|
251
|
+
leaked reference look identical from outside.
|
|
236
252
|
- **Tests (pytest).** Cover the logic that matters: graph validate/topo/executor/cache, the catalog
|
|
237
253
|
scan, the run store + server contract, the device/memory policy, the parallel group + xfuser seam,
|
|
238
254
|
and each model runner (import-guarded, no GPU needed). See `tests/`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: inline-core
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.66
|
|
4
4
|
Summary: The generation engine behind Inline Studio.
|
|
5
5
|
License-Expression: GPL-3.0-or-later
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -14,7 +14,7 @@ Requires-Dist: controlnet-aux>=0.0.7; extra == 'all'
|
|
|
14
14
|
Requires-Dist: diffusers==0.39.0; extra == 'all'
|
|
15
15
|
Requires-Dist: einops>=0.7; extra == 'all'
|
|
16
16
|
Requires-Dist: fastapi>=0.110; extra == 'all'
|
|
17
|
-
Requires-Dist: huggingface-hub>=0.
|
|
17
|
+
Requires-Dist: huggingface-hub>=0.32; extra == 'all'
|
|
18
18
|
Requires-Dist: imageio-ffmpeg>=0.4; extra == 'all'
|
|
19
19
|
Requires-Dist: nvidia-ml-py>=12; extra == 'all'
|
|
20
20
|
Requires-Dist: onnxruntime>=1.17; extra == 'all'
|
|
@@ -41,7 +41,7 @@ Requires-Dist: accelerate>=0.30; extra == 'runtime'
|
|
|
41
41
|
Requires-Dist: av>=12; extra == 'runtime'
|
|
42
42
|
Requires-Dist: controlnet-aux>=0.0.7; extra == 'runtime'
|
|
43
43
|
Requires-Dist: diffusers==0.39.0; extra == 'runtime'
|
|
44
|
-
Requires-Dist: huggingface-hub>=0.
|
|
44
|
+
Requires-Dist: huggingface-hub>=0.32; extra == 'runtime'
|
|
45
45
|
Requires-Dist: onnxruntime>=1.17; extra == 'runtime'
|
|
46
46
|
Requires-Dist: safetensors>=0.4; extra == 'runtime'
|
|
47
47
|
Requires-Dist: scipy>=1.11; extra == 'runtime'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
# PyPI name; the import package is `inline_core` (src/inline_core).
|
|
3
3
|
name = "inline-core"
|
|
4
|
-
version = "1.2.
|
|
4
|
+
version = "1.2.66"
|
|
5
5
|
description = "The generation engine behind Inline Studio."
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "GPL-3.0-or-later"
|
|
@@ -29,7 +29,10 @@ runtime = [
|
|
|
29
29
|
# Backs the Beta sigma schedule (diffusers gates use_beta_sigmas on scipy).
|
|
30
30
|
"scipy>=1.11",
|
|
31
31
|
# We call snapshot_download directly for the model popup, so pin it rather than rely on transit.
|
|
32
|
-
|
|
32
|
+
# 0.32 is where hf_xet became a hard dependency rather than an extra. Below it, Hugging Face
|
|
33
|
+
# refuses the largest files outright ("too large to be downloaded using the regular download
|
|
34
|
+
# method"), which is every H3 transformer at 66GB.
|
|
35
|
+
"huggingface_hub>=0.32",
|
|
33
36
|
# ControlNet preprocessors (the Apply ControlNet node): OpenPose/DWPose, MiDaS/Zoe depth, canny,
|
|
34
37
|
# HED, lineart, MLSD, scribble, normal. DWPose runs its detector on ONNX Runtime.
|
|
35
38
|
"controlnet-aux>=0.0.7",
|
|
@@ -85,7 +88,10 @@ all = [
|
|
|
85
88
|
# Clip decode for MiniMax H3 LoRA training, and H3's reference node.
|
|
86
89
|
"av>=12",
|
|
87
90
|
"scipy>=1.11",
|
|
88
|
-
|
|
91
|
+
# 0.32 is where hf_xet became a hard dependency rather than an extra. Below it, Hugging Face
|
|
92
|
+
# refuses the largest files outright ("too large to be downloaded using the regular download
|
|
93
|
+
# method"), which is every H3 transformer at 66GB.
|
|
94
|
+
"huggingface_hub>=0.32",
|
|
89
95
|
"controlnet-aux>=0.0.7",
|
|
90
96
|
"onnxruntime>=1.17",
|
|
91
97
|
# server
|
|
@@ -111,8 +117,10 @@ name = "pytorch-cu126"
|
|
|
111
117
|
url = "https://download.pytorch.org/whl/cu126"
|
|
112
118
|
explicit = true
|
|
113
119
|
|
|
114
|
-
# Launcher installs pass `--no-sources
|
|
115
|
-
#
|
|
120
|
+
# Launcher installs pass `--no-sources` so their detected index wins over this pin. That flag is
|
|
121
|
+
# broad rather than per-package because the per-package form is too new for the uv versions people
|
|
122
|
+
# have. torch being the ONLY entry here is what makes that equivalent: adding another would silently
|
|
123
|
+
# start ignoring it on launcher installs too.
|
|
116
124
|
[tool.uv.sources]
|
|
117
125
|
torch = [{ index = "pytorch-cu126", marker = "sys_platform == 'win32'" }]
|
|
118
126
|
|
|
@@ -325,20 +325,23 @@ def resolve_offload(
|
|
|
325
325
|
) -> bool:
|
|
326
326
|
"""Whether to stream saved activations to host RAM this run.
|
|
327
327
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
328
|
+
``auto`` was written for a full-precision base: keep the 26GB Krea 2 base resident and put the
|
|
329
|
+
~21GB of 1024 activations elsewhere, rather than dropping the frozen base to NF4. Under a
|
|
330
|
+
quantized base ``auto`` stays off, because there the base is the whole story and offload would
|
|
331
|
+
buy PCIe traffic for nothing.
|
|
332
|
+
|
|
333
|
+
``on``/``off`` are tested before the quant rule, or the control is dead for MiniMax H3 (always
|
|
334
|
+
4-bit), whose base is small and whose clip activations are what overflow the card."""
|
|
332
335
|
from ..device.policy import Quantization
|
|
333
336
|
|
|
334
337
|
if pref == "off":
|
|
335
338
|
return False
|
|
336
|
-
if quant is not Quantization.NONE:
|
|
337
|
-
return False # a quantized base already fits; offload would only slow it down
|
|
338
339
|
if pref == "on":
|
|
339
340
|
return True
|
|
340
341
|
if pref not in ("auto", ""):
|
|
341
342
|
raise RuntimeError(f"Unknown offload preference {pref!r}.")
|
|
343
|
+
if quant is not Quantization.NONE:
|
|
344
|
+
return False # auto only: a quantized base already fits, so do not pay for offload
|
|
342
345
|
|
|
343
346
|
import torch
|
|
344
347
|
|
|
@@ -119,6 +119,20 @@ def _peak_vram_gb() -> float | None:
|
|
|
119
119
|
return round(torch.cuda.max_memory_allocated() / 1e9, 2)
|
|
120
120
|
|
|
121
121
|
|
|
122
|
+
def _vram_note(label: str) -> str:
|
|
123
|
+
"""Both numbers: nvidia-smi shows only reserved, so allocator cache and a leaked reference look
|
|
124
|
+
identical from outside."""
|
|
125
|
+
import torch
|
|
126
|
+
|
|
127
|
+
if not torch.cuda.is_available():
|
|
128
|
+
return label
|
|
129
|
+
gb = 1e9
|
|
130
|
+
return (
|
|
131
|
+
f"{label}: allocated {torch.cuda.memory_allocated() / gb:.1f}GB, "
|
|
132
|
+
f"reserved {torch.cuda.memory_reserved() / gb:.1f}GB"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
122
136
|
def _activation_offload(enabled: bool) -> Any:
|
|
123
137
|
"""A context that streams saved activations to host RAM (pinned) for the forward, pulling them
|
|
124
138
|
back on backward. Keeps a full-precision base resident on a card that could not otherwise hold
|
|
@@ -205,9 +219,11 @@ def train(manifest: dict[str, Any]) -> str | None:
|
|
|
205
219
|
)
|
|
206
220
|
plan = quant.value + (" + cpu offload" if offload else "")
|
|
207
221
|
protocol.progress(0, steps, status=f"loading model ({plan})")
|
|
222
|
+
print(_vram_note("VRAM after caching, before the base loads"), flush=True)
|
|
208
223
|
transformer = models.load_transformer(
|
|
209
224
|
manifest["modelsDir"], arch.key, manifest["baseMode"], str(device), dtype, quant
|
|
210
225
|
)
|
|
226
|
+
print(_vram_note("VRAM after the base loaded"), flush=True)
|
|
211
227
|
transformer.requires_grad_(False)
|
|
212
228
|
# PEFT picks its bitsandbytes-aware LoRA layer off this one attribute. Without it, and because
|
|
213
229
|
# bnb's Linear4bit subclasses nn.Linear, the generic dispatcher matches instead: grads still
|
|
@@ -237,6 +253,10 @@ def train(manifest: dict[str, Any]) -> str | None:
|
|
|
237
253
|
signal.signal(signal.SIGTERM, stop)
|
|
238
254
|
|
|
239
255
|
transformer.train()
|
|
256
|
+
# Before the first step, not after: emitting only on completion makes a slow step one look like
|
|
257
|
+
# the loader is still running.
|
|
258
|
+
print(_vram_note("VRAM entering the training loop"), flush=True)
|
|
259
|
+
protocol.progress(start, steps, status="training")
|
|
240
260
|
for step in range(start, steps):
|
|
241
261
|
if stop.flagged:
|
|
242
262
|
break
|
|
@@ -475,3 +475,15 @@ def test_clip_window_defaults_to_the_start(tmp_path) -> None:
|
|
|
475
475
|
assert h3._clip_frames(clip, clip_frames=24)[0].getpixel((0, 0)) == (
|
|
476
476
|
h3._clip_frames(clip, clip_frames=24, window="start")[0].getpixel((0, 0))
|
|
477
477
|
)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def test_the_loop_reports_training_before_the_first_step(monkeypatch) -> None:
|
|
481
|
+
"""Emitted only on completion, a slow step one reads as a hung loader."""
|
|
482
|
+
import inspect
|
|
483
|
+
|
|
484
|
+
from inline_core.training import trainer
|
|
485
|
+
|
|
486
|
+
source = inspect.getsource(trainer.train)
|
|
487
|
+
enters_loop = source.index("for step in range(start, steps):")
|
|
488
|
+
announces = source.index('status="training"')
|
|
489
|
+
assert announces < enters_loop, "the training status must be sent before the loop, not after"
|
|
@@ -97,8 +97,8 @@ def test_auto_quantization_accounts_for_resolution(monkeypatch, tmp_path) -> Non
|
|
|
97
97
|
|
|
98
98
|
def test_offload_fits_a_bf16_base_that_would_not_otherwise(monkeypatch, tmp_path) -> None:
|
|
99
99
|
"""bf16 1024 on a 45GB card: base (26GB) + activations (~21GB) overflow, so auto-offload turns
|
|
100
|
-
on to keep the base full precision rather than dropping it to NF4.
|
|
101
|
-
|
|
100
|
+
on to keep the base full precision rather than dropping it to NF4. Under a quantized base AUTO
|
|
101
|
+
stays off, but an explicit on/off is the user's answer and wins."""
|
|
102
102
|
root = tmp_path / "models"
|
|
103
103
|
(root / "diffusion_models").mkdir(parents=True)
|
|
104
104
|
(root / "diffusion_models" / "krea2_raw_bf16.safetensors").write_bytes(b"")
|
|
@@ -120,8 +120,10 @@ def test_offload_fits_a_bf16_base_that_would_not_otherwise(monkeypatch, tmp_path
|
|
|
120
120
|
assert off("auto", Quantization.NONE, str(root), archs.KREA2, "raw", 512) is False
|
|
121
121
|
assert off("on", Quantization.NONE, str(root), archs.KREA2, "raw", 512) is True
|
|
122
122
|
assert off("off", Quantization.NONE, str(root), archs.KREA2, "raw", 1024) is False
|
|
123
|
-
#
|
|
124
|
-
assert off("
|
|
123
|
+
# Auto stays off under a quantized base; an explicit choice wins.
|
|
124
|
+
assert off("auto", Quantization.NF4, str(root), archs.KREA2, "raw", 1024) is False
|
|
125
|
+
assert off("on", Quantization.NF4, str(root), archs.KREA2, "raw", 1024) is True
|
|
126
|
+
assert off("off", Quantization.NF4, str(root), archs.KREA2, "raw", 1024) is False
|
|
125
127
|
|
|
126
128
|
|
|
127
129
|
def test_zimage_has_no_four_bit_path_and_says_so(tmp_path) -> None:
|
|
@@ -198,3 +200,26 @@ def test_fails_open_when_the_machine_cannot_be_read(monkeypatch) -> None:
|
|
|
198
200
|
_fake_env(monkeypatch, mode=0, ram_gib=30, size_gib=62)
|
|
199
201
|
monkeypatch.setattr(models, "_base_size", lambda *a: 0)
|
|
200
202
|
models.check_base_mappable("/m", "minimax-h3", "raw")
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_an_explicit_offload_choice_beats_the_quant_heuristic(monkeypatch, tmp_path) -> None:
|
|
206
|
+
"""Dead for H3, always 4-bit, whose clip activations are what overflow the card."""
|
|
207
|
+
from inline_core.device.policy import Quantization
|
|
208
|
+
|
|
209
|
+
root = tmp_path / "models"
|
|
210
|
+
(root / "diffusion_models").mkdir(parents=True)
|
|
211
|
+
monkeypatch.setattr(models, "_base_size", lambda *a: 12 * 1024**3)
|
|
212
|
+
off = models.resolve_offload
|
|
213
|
+
|
|
214
|
+
assert off("on", Quantization.NF4, str(root), archs.MINIMAX_H3, "raw", 512) is True
|
|
215
|
+
assert off("off", Quantization.NF4, str(root), archs.MINIMAX_H3, "raw", 512) is False
|
|
216
|
+
assert off("auto", Quantization.NF4, str(root), archs.MINIMAX_H3, "raw", 512) is False
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_an_unknown_offload_preference_still_raises(monkeypatch, tmp_path) -> None:
|
|
220
|
+
"""The reorder must not let a typo fall through to the auto path and silently mean 'off'."""
|
|
221
|
+
from inline_core.device.policy import Quantization
|
|
222
|
+
|
|
223
|
+
monkeypatch.setattr(models, "_base_size", lambda *a: 12 * 1024**3)
|
|
224
|
+
with pytest.raises(RuntimeError):
|
|
225
|
+
models.resolve_offload("yes", Quantization.NF4, str(tmp_path), archs.MINIMAX_H3, "raw", 512)
|
|
@@ -190,8 +190,10 @@ def test_blackwell_gets_an_index_that_has_sm_120_wheels(sandbox: Sandbox) -> Non
|
|
|
190
190
|
assert done.returncode == 0, done.stderr
|
|
191
191
|
install = sandbox.project_install()
|
|
192
192
|
assert f"{_WHL}/cu130" in install
|
|
193
|
-
# Without this the pyproject pin wins and the detected index is silently ignored.
|
|
194
|
-
|
|
193
|
+
# Without this the pyproject pin wins and the detected index is silently ignored. The broad
|
|
194
|
+
# flag, not --no-sources-package torch: that one is too new for the uv versions people have and
|
|
195
|
+
# hard-errored their install. See test_every_uv_flag_the_launcher_passes_is_real.
|
|
196
|
+
assert "--no-sources" in install
|
|
195
197
|
|
|
196
198
|
|
|
197
199
|
def test_older_cards_get_the_index_that_still_covers_them(sandbox: Sandbox) -> None:
|
|
@@ -336,3 +338,36 @@ def test_an_explicit_index_is_reported_as_an_override(sandbox: Sandbox) -> None:
|
|
|
336
338
|
got = _decision(sandbox, "--torch-index", "cu126")
|
|
337
339
|
assert got["torch-index"] == "cu126"
|
|
338
340
|
assert got["reason"] == "override"
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
# --- the flags we pass must exist in the uv we are talking to ------------------------------------
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def test_every_uv_flag_the_launcher_passes_is_real(sandbox: Sandbox) -> None:
|
|
347
|
+
"""A stubbed uv accepts anything, so a flag that does not exist sails through every other test
|
|
348
|
+
here and hard-errors on a user's machine. `--no-sources-package torch` did exactly that: valid
|
|
349
|
+
in current uv, absent from the version people had, and the install died at the first command.
|
|
350
|
+
|
|
351
|
+
Checked against the real uv's help rather than a hardcoded list, so it tracks whatever is
|
|
352
|
+
installed.
|
|
353
|
+
"""
|
|
354
|
+
uv = shutil.which("uv")
|
|
355
|
+
if uv is None:
|
|
356
|
+
pytest.skip("uv is not installed; nothing to validate the launcher's flags against")
|
|
357
|
+
help_text = subprocess.run( # noqa: S603 - fixed argv
|
|
358
|
+
[uv, "pip", "install", "--help"], capture_output=True, text=True, check=True, timeout=60
|
|
359
|
+
).stdout
|
|
360
|
+
|
|
361
|
+
sandbox.pretend_windows()
|
|
362
|
+
sandbox.pretend_nvidia_gpu("8.6", driver="580.82")
|
|
363
|
+
sandbox.run("--install", "--extra", "runtime")
|
|
364
|
+
|
|
365
|
+
passed = {
|
|
366
|
+
word
|
|
367
|
+
for call in sandbox.uv_calls()
|
|
368
|
+
for word in call.split()
|
|
369
|
+
if word.startswith("--")
|
|
370
|
+
}
|
|
371
|
+
assert passed, "the launcher ran no uv command, so this test proves nothing"
|
|
372
|
+
missing = sorted(flag for flag in passed if flag not in help_text)
|
|
373
|
+
assert not missing, f"webui.sh passes flags this uv does not have: {missing}"
|
|
@@ -162,12 +162,11 @@ if !CAP_MAJOR! GEQ 10 if !DRIVER_MAJOR! GTR 0 if !DRIVER_MAJOR! LSS 580 (
|
|
|
162
162
|
if /i "!TORCH_CHOICE!"=="cpu" goto install_cpu_forced
|
|
163
163
|
set "TORCH_URL=https://download.pytorch.org/whl/!TORCH_CHOICE!"
|
|
164
164
|
if /i "!TORCH_CHOICE:~0,4!"=="http" set "TORCH_URL=!TORCH_CHOICE!"
|
|
165
|
-
rem unsafe-best-match: torchao
|
|
166
|
-
rem
|
|
167
|
-
rem
|
|
168
|
-
rem
|
|
169
|
-
|
|
170
|
-
set "TORCH_ARGS=--extra-index-url !TORCH_URL! --index-strategy unsafe-best-match --no-sources-package torch"
|
|
165
|
+
rem unsafe-best-match: without it uv stops at the older torchao on the CUDA index, and PyPI's plain
|
|
166
|
+
rem torch outranks the +cuXXX build on Windows.
|
|
167
|
+
rem no-sources: the pyproject pin names one index, and the card decides here. The broad flag, not
|
|
168
|
+
rem --no-sources-package, which needs uv 0.10+; torch is the only entry so they are equivalent.
|
|
169
|
+
set "TORCH_ARGS=--extra-index-url !TORCH_URL! --index-strategy unsafe-best-match --no-sources"
|
|
171
170
|
echo NVIDIA GPU detected - installing the CUDA build of PyTorch (!TORCH_CHOICE!).
|
|
172
171
|
goto install_pkgs
|
|
173
172
|
|
|
@@ -213,10 +212,8 @@ if /i "!PROBE_STATUS!"=="uncovered" (
|
|
|
213
212
|
:install_run
|
|
214
213
|
echo + uv pip install --python "!TARGET_PY!" !TORCH_ARGS! -e ".[!EXTRAS!]"
|
|
215
214
|
uv pip install --python "!TARGET_PY!" !TORCH_ARGS! -e ".[!EXTRAS!]" || goto fail
|
|
216
|
-
rem Torch LAST
|
|
217
|
-
rem
|
|
218
|
-
rem on win32, and --extra-index-url with unsafe-best-match picks the highest version ACROSS indexes,
|
|
219
|
-
rem which lands back on PyPI's CPU wheel whenever PyPI leads.
|
|
215
|
+
rem Torch LAST and through --index-url (exclusive): [tool.uv.sources] pins it to cu126 on win32,
|
|
216
|
+
rem and --extra-index-url picks the highest version ACROSS indexes, so PyPI's CPU wheel can win.
|
|
220
217
|
if "!TORCH_FORCE!"=="1" if defined TORCH_CHOICE (
|
|
221
218
|
set "TORCH_PINS=torch torchvision"
|
|
222
219
|
rem cu128 is frozen, so the current pair does not exist there. Pin the last one it has.
|
|
@@ -240,18 +237,14 @@ echo .\webui.bat --install --torch-index !TORCH_CHOICE! --recreate
|
|
|
240
237
|
echo Installed extras: !EXTRAS!. Start with: .\webui.bat
|
|
241
238
|
exit /b 0
|
|
242
239
|
|
|
243
|
-
rem
|
|
244
|
-
rem
|
|
245
|
-
rem and `if LSS` would STRING-compare it, so "Unknown" would rank above 10 and win. set /a reads a
|
|
246
|
-
rem bare word as an undefined variable and yields 0, which is exactly what we want here, so do not
|
|
247
|
-
rem "fix" it back into a guard later.
|
|
240
|
+
rem One query for both, keeping the highest capability. set /a not a findstr guard: `if LSS` would
|
|
241
|
+
rem string-compare an error string like "Unknown" above 10; set /a yields 0 for it, as intended.
|
|
248
242
|
:read_gpu_probe
|
|
249
243
|
set "CAP_MAJOR=0"
|
|
250
244
|
set "DRIVER_MAJOR=0"
|
|
251
245
|
set "GPU_PROBE_RAW="
|
|
252
|
-
rem
|
|
253
|
-
rem
|
|
254
|
-
rem fire. The majors are taken off each field by the inner loops.
|
|
246
|
+
rem Comma ONLY: adding "." would cut "12.0, 610.88" into 12/0/610/88, making token 2 the minor
|
|
247
|
+
rem rather than the driver, so the R580 floor could never fire.
|
|
255
248
|
for /f "usebackq tokens=1,2 delims=," %%c in (`nvidia-smi --query-gpu^=compute_cap^,driver_version --format^=csv^,noheader 2^>nul`) do (
|
|
256
249
|
rem Reset every iteration: set /a errors on garbage and would otherwise leave the previous line's
|
|
257
250
|
rem value in place, double-counting a good line followed by a bad one.
|
|
@@ -200,17 +200,9 @@ read_gpu_probe() {
|
|
|
200
200
|
#: | override | no-gpu.
|
|
201
201
|
TORCH_INDEX_REASON="autodetect"
|
|
202
202
|
|
|
203
|
-
#
|
|
204
|
-
# is
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
# Verified 2026-02 and load-bearing: cu128 still SERVES but is frozen at torch 2.11.0, and it was the
|
|
208
|
-
# first index with sm_120. So a Blackwell card on a pre-R580 driver (CUDA 13's floor) gets cu128
|
|
209
|
-
# rather than an error, because it has exactly one workable choice. Re-check that ceiling before
|
|
210
|
-
# trusting this comment in a year.
|
|
211
|
-
# Assigns TORCH_CHOICE and TORCH_INDEX_REASON rather than printing them. It must NOT be called
|
|
212
|
-
# through $(...): a command substitution is a subshell, so the probe globals and the reason would be
|
|
213
|
-
# discarded and only the index would survive. That is what the tests caught.
|
|
203
|
+
# cu126 is the last index built for Maxwell..Volta; sm_100/sm_120 need cu128 or newer. cu128 serves
|
|
204
|
+
# but is frozen at torch 2.11 (checked 2026-02), so it is only for Blackwell below CUDA 13's R580.
|
|
205
|
+
# Assigns rather than prints: through $(...) the probe globals would die in the subshell.
|
|
214
206
|
pick_torch_index() {
|
|
215
207
|
read_gpu_probe
|
|
216
208
|
if [[ -z "$GPU_CAP_MAJOR" ]]; then TORCH_CHOICE="cu126"; return 0; fi
|
|
@@ -340,14 +332,12 @@ if [[ "$RUN_INSTALL" -eq 1 ]]; then
|
|
|
340
332
|
elif [[ -z "$TORCH_CHOICE" ]]; then
|
|
341
333
|
echo "NVIDIA GPU detected - installing the CUDA build of PyTorch."
|
|
342
334
|
else
|
|
343
|
-
# unsafe-best-match:
|
|
344
|
-
#
|
|
345
|
-
#
|
|
346
|
-
#
|
|
347
|
-
# no-sources-package: the pyproject pin names one fixed index, and the whole point here is that
|
|
348
|
-
# the card decides.
|
|
335
|
+
# unsafe-best-match: without it uv stops at the older torchao on the CUDA index, and PyPI's
|
|
336
|
+
# plain torch outranks the +cuXXX build on Windows.
|
|
337
|
+
# no-sources: the pyproject pin names one index, and the card decides here. The broad flag, not
|
|
338
|
+
# --no-sources-package, which needs uv 0.10+; torch is the only entry so they are equivalent.
|
|
349
339
|
TORCH_INDEX=(--extra-index-url "$(torch_index_url "$TORCH_CHOICE")" \
|
|
350
|
-
--index-strategy unsafe-best-match --no-sources
|
|
340
|
+
--index-strategy unsafe-best-match --no-sources)
|
|
351
341
|
echo "NVIDIA GPU detected - installing the CUDA build of PyTorch ($TORCH_CHOICE)."
|
|
352
342
|
fi
|
|
353
343
|
# A venv reused from a bad install keeps its torch: uv leaves a satisfying version alone, so
|
|
@@ -371,11 +361,8 @@ if [[ "$RUN_INSTALL" -eq 1 ]]; then
|
|
|
371
361
|
|
|
372
362
|
echo "+ uv pip install --python $TARGET_PY ${TORCH_INDEX[*]} -e .[$EXTRAS]"
|
|
373
363
|
uv pip install --python "$TARGET_PY" "${TORCH_INDEX[@]}" -e ".[$EXTRAS]"
|
|
374
|
-
# Torch LAST
|
|
375
|
-
#
|
|
376
|
-
# cu126 index on win32, and --extra-index-url with unsafe-best-match picks the highest version
|
|
377
|
-
# ACROSS indexes, which lands back on PyPI's CPU wheel whenever PyPI leads. Costs one possibly
|
|
378
|
-
# wasted download on a path that is rare and deliberate.
|
|
364
|
+
# Torch LAST and through --index-url (exclusive): [tool.uv.sources] pins it to cu126 on win32,
|
|
365
|
+
# and --extra-index-url picks the highest version ACROSS indexes, so PyPI's CPU wheel can win.
|
|
379
366
|
if [[ "$TORCH_FORCE" -eq 1 && -n "$TORCH_CHOICE" ]]; then
|
|
380
367
|
read -r -a TORCH_PINS <<<"$(torch_pins_for "$TORCH_CHOICE")"
|
|
381
368
|
TORCH_URL="$(torch_index_url "$TORCH_CHOICE")"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|