From 5e4d4172757d006edf7b07fdded7ad9da38c7e9c Mon Sep 17 00:00:00 2001 From: e-nord Date: Tue, 29 Sep 2026 21:25:32 -0700 Subject: [PATCH 1/9] feat: add Fizgig LoRA training studio package Fizgig (shootthesound/Fizgig) is an Apache-2.0 LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1. It is a Tkinter desktop app rather than a web UI, so it follows the same shape as OneTrainer. Notes on the less obvious choices: - LaunchCommand is lora_trainer_gui.py, not launch.pyw. The latter re-spawns itself under venv/Scripts/pythonw.exe and exits, which would drop the process we track (no console output, no working Stop button) and leave the GUI orphaned. lora_trainer_gui.py has a standalone main() and is what upstream's run_fizgig.sh invokes directly. - VcBuildTools is a prerequisite so triton / torch.compile's inductor backend can compile kernels on Windows, which Fizgig's Compile Blocks speedup needs. - DISABLE_CUDA=1 is set around the requirements install. hqq ships as an sdist whose setup.py kicks off a CUDA kernel build during egg_info without it; Fizgig's own requirements.txt warns never to install that line otherwise. - The requirements exclude pattern spells out the version specifiers. The pattern is anchored against the whole entry, so the default "(torch|torchvision|...)" only catches bare, unpinned names and would let Fizgig's pinned torch==2.10.0 through - pulling multi-GB PyPI wheels right before the cu128 build force-reinstalls over them. - Torch pins carry the == operator ("==2.10.0"), since GetTorchPipArgs appends the version string directly to the package name. - CudaIndex is cu128; torch 2.10 has no wheels on SM's default cu130. Shared folders default to None, matching the other trainers. Symlink is offered as an opt-in (Package Manager -> Shared Model Strategy) that junctions output_loras into the shared Lora folder, so a freshly trained LoRA is immediately visible to ComfyUI and friends. Only output_loras is mapped: Fizgig flattens every weight it downloads into a single models/ directory, and junctions are directory-level, so DiffusionModels, TextEncoders and VAE would all collide on the same target path. ROCm is deliberately left out of this change and will follow separately. Co-Authored-By: Claude Opus 5.5 --- README.md | 2 + .../Services/DiscordRichPresenceService.cs | 1 + .../Helper/Factory/PackageFactory.cs | 8 + .../Models/Packages/Fizgig.cs | 171 ++++++++++++++++++ docs/advanced/hardware-support.md | 2 +- docs/package-manager/supported-packages.md | 3 +- 6 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 StabilityMatrix.Core/Models/Packages/Fizgig.cs diff --git a/README.md b/README.md index e7d8cb099..ec20f9ac6 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ [reforge]: https://github.com/Panchovix/stable-diffusion-webui-reForge [simplesdxl]: https://github.com/metercai/SimpleSDXL/ [fluxgym]: https://github.com/cocktailpeanut/fluxgym +[fizgig]: https://github.com/shootthesound/Fizgig [cogvideo]: https://github.com/THUDM/CogVideo [cogstudio]: https://github.com/pinokiofactory/cogstudio [amdforge]: https://github.com/lshqqytiger/stable-diffusion-webui-amdgpu-forge @@ -63,6 +64,7 @@ See the [documentation index](docs/README.md) for installation, package manageme - [Kohya's GUI][kohya-ss] - [OneTrainer][onetrainer] - [FluxGym][fluxgym] + - [Fizgig][fizgig] - [CogVideo][cogvideo] via [CogStudio][cogstudio] - Manage plugins / extensions for supported packages ([Automatic1111][auto1111], [Comfy UI][comfy], [SD Web UI-UX][webui-ux], and [SD.Next][sdnext]) - Easily install or update Python dependencies for each package diff --git a/StabilityMatrix.Avalonia/Services/DiscordRichPresenceService.cs b/StabilityMatrix.Avalonia/Services/DiscordRichPresenceService.cs index 19de6aed3..958ffc064 100644 --- a/StabilityMatrix.Avalonia/Services/DiscordRichPresenceService.cs +++ b/StabilityMatrix.Avalonia/Services/DiscordRichPresenceService.cs @@ -96,6 +96,7 @@ private void OnRunningPackageStatusChanged(object? sender, RunningPackageStatusC var packageTitle = args.CurrentPackagePair.BasePackage switch { + Fizgig => "Fizgig", FluxGym => "FluxGym", Fooocus => "Fooocus", Reforge => "SD WebUI reForge", diff --git a/StabilityMatrix.Core/Helper/Factory/PackageFactory.cs b/StabilityMatrix.Core/Helper/Factory/PackageFactory.cs index c23051fac..ca1b68828 100644 --- a/StabilityMatrix.Core/Helper/Factory/PackageFactory.cs +++ b/StabilityMatrix.Core/Helper/Factory/PackageFactory.cs @@ -278,6 +278,14 @@ public BasePackage GetNewBasePackage(InstalledPackage installedPackage) pyInstallationManager, pipWheelService ), + "Fizgig" => new Fizgig( + githubApiCache, + settingsManager, + downloadService, + prerequisiteHelper, + pyInstallationManager, + pipWheelService + ), "ai-toolkit" => new AiToolkit( githubApiCache, settingsManager, diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs new file mode 100644 index 000000000..91cfcadc9 --- /dev/null +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -0,0 +1,171 @@ +using Injectio.Attributes; +using StabilityMatrix.Core.Helper; +using StabilityMatrix.Core.Helper.Cache; +using StabilityMatrix.Core.Helper.HardwareInfo; +using StabilityMatrix.Core.Models.Progress; +using StabilityMatrix.Core.Processes; +using StabilityMatrix.Core.Python; +using StabilityMatrix.Core.Services; + +namespace StabilityMatrix.Core.Models.Packages; + +[RegisterSingleton(Duplicate = DuplicateStrategy.Append)] +public class Fizgig( + IGithubApiCache githubApi, + ISettingsManager settingsManager, + IDownloadService downloadService, + IPrerequisiteHelper prerequisiteHelper, + IPyInstallationManager pyInstallationManager, + IPipWheelService pipWheelService +) + : BaseGitPackage( + githubApi, + settingsManager, + downloadService, + prerequisiteHelper, + pyInstallationManager, + pipWheelService + ) +{ + public override string Name => "Fizgig"; + public override string DisplayName { get; set; } = "Fizgig"; + public override string Author => "shootthesound"; + + public override string Blurb => + "LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1 — train, profile, repair and extract"; + + public override string LicenseType => "Apache-2.0"; + public override string LicenseUrl => "https://github.com/shootthesound/Fizgig/blob/master/LICENSE"; + + // NOT launch.pyw: that launcher re-spawns itself under venv/Scripts/pythonw.exe and exits, + // which would drop the process we track (no console output, no working Stop button) and + // leave the GUI orphaned. lora_trainer_gui.py has a standalone main() and is what upstream's + // run_fizgig.sh invokes directly. + public override string LaunchCommand => "lora_trainer_gui.py"; + + public override Uri PreviewImageUri => + new("https://github.com/shootthesound/Fizgig/blob/master/icon.png?raw=true"); + + public override string MainBranch => "master"; + public override PackageType PackageType => PackageType.SdTraining; + public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Advanced; + public override bool OfferInOneClickInstaller => false; + public override bool IsCompatible => HardwareHelper.HasNvidiaGpu(); + public override IEnumerable AvailableTorchIndices => [TorchIndex.Cuda]; + + public override TorchIndex GetRecommendedTorchVersion() => TorchIndex.Cuda; + + public override PyVersion RecommendedPythonVersion => Python.PyInstallationManager.Python_3_12_10; + + // Tkinter for the GUI itself; VcBuildTools for triton / torch.compile's inductor backend, + // which the Compile Blocks speedup needs on Windows. + public override IEnumerable Prerequisites => + base.Prerequisites.Concat([PackagePrerequisite.Tkinter, PackagePrerequisite.VcBuildTools]); + + public override List LaunchOptions => [LaunchOptionDefinition.Extras]; + + // Trained LoRAs, not images. + public override string OutputFolderName => string.Empty; + public override Dictionary>? SharedOutputFolders => null; + + /// + /// Defaults to None, matching the other trainers. Opting in to Symlink (Package Manager -> + /// ... -> Shared Model Strategy) junctions output_loras into the shared Lora folder, so a + /// freshly trained LoRA is immediately visible to ComfyUI and friends. + /// + public override SharedFolderMethod RecommendedSharedFolderMethod => SharedFolderMethod.None; + + public override IEnumerable AvailableSharedFolderMethods => + [SharedFolderMethod.None, SharedFolderMethod.Symlink]; + + /// + /// Only output_loras is mapped. Fizgig's models/ directory deliberately flattens every + /// weight it downloads into one folder — DiTs, text encoders, VAEs, turbo LoRAs and training + /// adapters all land there as bare filenames (see src/fizgig/scripts/fetch_models.py) — and + /// junctions are directory-level, so there is no way to fan that single directory out to + /// DiffusionModels/TextEncoders/VAE without them colliding on the same target path. + /// + public override SharedFolderLayout SharedFolderLayout => + new() + { + Rules = + [ + new SharedFolderLayoutRule + { + SourceTypes = [SharedFolderType.Lora], + TargetRelativePaths = ["output_loras"], + }, + ], + }; + + public override async Task InstallPackage( + string installLocation, + InstalledPackage installedPackage, + InstallPackageOptions options, + IProgress? progress = null, + Action? onConsoleOutput = null, + CancellationToken cancellationToken = default + ) + { + progress?.Report(new ProgressReport(-1f, "Setting up venv", isIndeterminate: true)); + + await using var venvRunner = await SetupVenvPure( + installLocation, + pythonVersion: options.PythonOptions.PythonVersion + ) + .ConfigureAwait(false); + + // hqq ships as an sdist whose setup.py kicks off a CUDA kernel build during egg_info + // unless DISABLE_CUDA is set. Fizgig only uses its pure-PyTorch path, and its own + // requirements.txt warns never to install that line without this. + venvRunner.UpdateEnvironmentVariables(env => env.SetItem("DISABLE_CUDA", "1")); + + var config = new PipInstallConfig + { + RequirementsFilePaths = ["requirements.txt"], + // Drop the torch pins and the cu128 index line from the file so the torch install + // below is the single source of truth for which build lands in the venv. The pattern + // is anchored against the whole entry by the caller, so the version specifier has to + // be matched too - the default pattern only catches bare, unpinned names. + RequirementsExcludePattern = + @"(--extra-index-url.*|(torch|torchvision|torchaudio|xformers)([=<>!~].*)?)", + TorchVersion = "==2.10.0", + TorchvisionVersion = "==0.25.0", + // torch 2.10 pairs with cu128 here; SM's default cu130 has no matching wheels. + CudaIndex = "cu128", + }; + + await StandardPipInstallProcessAsync( + venvRunner, + options, + installedPackage, + config, + onConsoleOutput, + progress, + cancellationToken + ) + .ConfigureAwait(false); + + venvRunner.UpdateEnvironmentVariables(env => env.Remove("DISABLE_CUDA")); + } + + public override async Task RunPackage( + string installLocation, + InstalledPackage installedPackage, + RunPackageOptions options, + Action? onConsoleOutput = null, + CancellationToken cancellationToken = default + ) + { + await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage.PythonVersion)) + .ConfigureAwait(false); + + // Desktop Tkinter app - there is no local URL to wait for, so startup is complete + // as soon as the process is up. + VenvRunner.RunDetached( + [Path.Combine(installLocation, options.Command ?? LaunchCommand), .. options.Arguments], + onConsoleOutput, + OnExit + ); + } +} diff --git a/docs/advanced/hardware-support.md b/docs/advanced/hardware-support.md index ad74692cb..87b3621f3 100644 --- a/docs/advanced/hardware-support.md +++ b/docs/advanced/hardware-support.md @@ -36,7 +36,7 @@ The lists below describe what the code checks for. Because hardware detection wo - **Caveats:** - The `cu130` wheels require an NVIDIA driver of version 580 or newer. ComfyUI checks the installed driver on launch and warns if it is older than 580.x while `cu130` torch is installed, suggesting either a driver update or manually downgrading to an older torch index such as `cu128`. - Turing (RTX 2000-series) or newer is the practical recommendation; older cards may still work but are treated as legacy. -- **Packages:** CUDA is the most broadly supported backend. Every inference package that lists a GPU backend supports CUDA, and CUDA-only packages include Fooocus, SimpleSDXL, ForgeClassic, FramePack, and the training tools (Kohya's GUI, OneTrainer, FluxGym, AI Toolkit). +- **Packages:** CUDA is the most broadly supported backend. Every inference package that lists a GPU backend supports CUDA, and CUDA-only packages include Fooocus, SimpleSDXL, ForgeClassic, FramePack, and the training tools (Kohya's GUI, OneTrainer, FluxGym, AI Toolkit, Fizgig). ## AMD on Windows diff --git a/docs/package-manager/supported-packages.md b/docs/package-manager/supported-packages.md index 0a244d23b..540729246 100644 --- a/docs/package-manager/supported-packages.md +++ b/docs/package-manager/supported-packages.md @@ -40,8 +40,9 @@ Training packages are used to fine-tune or train AI models such as LoRAs, checkp |---|---| | **AI-Toolkit** | An all-in-one training suite for diffusion models supporting LoRA, full fine-tune, and more. | | **OneTrainer** | A comprehensive one-stop solution for Stable Diffusion model training with a graphical interface. | -| **kohya_ss** | A Windows-focused Gradio GUI wrapping Kohya's popular Stable Diffusion trainer scripts. Windows only.| +| **kohya_ss** | A Windows-focused Gradio GUI wrapping Kohya's popular Stable Diffusion trainer scripts. Windows only. | | **FluxGym** | A simple, low-VRAM Flux LoRA training UI designed for quick fine-tuning workflows. | +| **Fizgig** | A LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1, with block profiling, repair and extraction tools. NVIDIA only. | --- From ed47e1f4f025900c252eaf54de29c977b8bd11a7 Mon Sep 17 00:00:00 2001 From: e-nord Date: Wed, 30 Sep 2026 23:00:54 -0700 Subject: [PATCH 2/9] fix(fizgig): install CUDA torch before requirements, disclose VS Build Tools Address review feedback on the Fizgig package: - Install torch 2.10.0 / torchvision 0.25.0 from cu128 via PrePipInstallArgs, so it lands before the requirements, and skip the standard torch step. accelerate (and others) depend on torch transitively; previously that pulled a PyPI torch build during the requirements step which the cu128 install then had to force-reinstall over. - Re-state the torch/torchvision pins alongside the requirements. The installed +cu128 build satisfies them, and a conflicting requirement fails loudly instead of swapping torch. - Add a Windows-only Disclaimer, shown in the install browser before installing, stating that VS Build Tools are installed system-wide and remain after Fizgig is uninstalled. The change is Fizgig-specific; shared install code is untouched. Co-Authored-By: Claude Opus 5.5 --- .../Models/Packages/Fizgig.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 91cfcadc9..6163173c2 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -34,6 +34,13 @@ IPipWheelService pipWheelService public override string Blurb => "LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1 — train, profile, repair and extract"; + // Shown in the install browser before the user commits to installing. + public override string Disclaimer => + Compat.IsWindows + ? "Visual Studio Build Tools for C++ Desktop Development will be installed system-wide if not already present (may require admin privileges). " + + "They are shared with other software and remain installed after Fizgig is uninstalled." + : string.Empty; + public override string LicenseType => "Apache-2.0"; public override string LicenseUrl => "https://github.com/shootthesound/Fizgig/blob/master/LICENSE"; @@ -120,19 +127,35 @@ public override async Task InstallPackage( // requirements.txt warns never to install that line without this. venvRunner.UpdateEnvironmentVariables(env => env.SetItem("DISABLE_CUDA", "1")); + const string torchVersion = "==2.10.0"; + const string torchvisionVersion = "==0.25.0"; + var config = new PipInstallConfig { RequirementsFilePaths = ["requirements.txt"], - // Drop the torch pins and the cu128 index line from the file so the torch install + // Drop the torch pins and the cu128 index line from the file so the pre-install step // below is the single source of truth for which build lands in the venv. The pattern // is anchored against the whole entry by the caller, so the version specifier has to // be matched too - the default pattern only catches bare, unpinned names. RequirementsExcludePattern = @"(--extra-index-url.*|(torch|torchvision|torchaudio|xformers)([=<>!~].*)?)", - TorchVersion = "==2.10.0", - TorchvisionVersion = "==0.25.0", + // Install the cu128 build before the requirements. accelerate (and friends) depend on + // torch transitively, so installing it afterwards would let the requirements step + // pull a default PyPI build that then has to be force-reinstalled over. // torch 2.10 pairs with cu128 here; SM's default cu130 has no matching wheels. - CudaIndex = "cu128", + PrePipInstallArgs = + [ + $"torch{torchVersion}", + $"torchvision{torchvisionVersion}", + "--extra-index-url", + "https://download.pytorch.org/whl/cu128", + "--force-reinstall", + ], + // Re-state the pins alongside the requirements: pip then treats the installed + // 2.10.0+cu128 as satisfying them instead of resolving its own torch from PyPI, and + // fails loudly rather than swapping it if anything conflicts. + ExtraPipArgs = [$"torch{torchVersion}", $"torchvision{torchvisionVersion}"], + SkipTorchInstall = true, }; await StandardPipInstallProcessAsync( From 128e8e95bc8e112b2c4034d7390d5e2e67702c15 Mon Sep 17 00:00:00 2001 From: e-nord Date: Fri, 2 Oct 2026 18:49:22 -0700 Subject: [PATCH 3/9] docs(fizgig): note Linux support for the NVIDIA/CUDA path Fizgig already works on Linux with NVIDIA GPUs; no code change is needed. The package is CUDA-only and gated on HasNvidiaGpu on every platform, and the CUDA install carries over unchanged: requirements.txt scopes triton-windows to win32, pytorch.org publishes Linux cu128 wheels for torch 2.10.0, insightface ships a pure-Python wheel, and the Unix prerequisite helper skips the Windows-only Tkinter / VS Build Tools prerequisites. The VS Build Tools disclaimer is already gated on Windows. Linux ROCm is left out. Upstream labels it highly experimental and installs it from AMD's TheRock wheels, which do not fit Stability Matrix's existing Linux ROCm path. Co-Authored-By: Claude Opus 5.5 --- docs/package-manager/supported-packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package-manager/supported-packages.md b/docs/package-manager/supported-packages.md index 540729246..49d65167e 100644 --- a/docs/package-manager/supported-packages.md +++ b/docs/package-manager/supported-packages.md @@ -42,7 +42,7 @@ Training packages are used to fine-tune or train AI models such as LoRAs, checkp | **OneTrainer** | A comprehensive one-stop solution for Stable Diffusion model training with a graphical interface. | | **kohya_ss** | A Windows-focused Gradio GUI wrapping Kohya's popular Stable Diffusion trainer scripts. Windows only. | | **FluxGym** | A simple, low-VRAM Flux LoRA training UI designed for quick fine-tuning workflows. | -| **Fizgig** | A LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1, with block profiling, repair and extraction tools. NVIDIA only. | +| **Fizgig** | A LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1, with block profiling, repair and extraction tools. NVIDIA only, on Windows and Linux. | --- From 0b9f9612d028db7707030b9bbbc13ae5f51a9840 Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:50:53 -0700 Subject: [PATCH 4/9] chore(fizgig): remove UTF-8 BOM from Fizgig.cs Co-Authored-By: Claude Opus 5.5 --- StabilityMatrix.Core/Models/Packages/Fizgig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 6163173c2..aece9b969 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -1,4 +1,4 @@ -using Injectio.Attributes; +using Injectio.Attributes; using StabilityMatrix.Core.Helper; using StabilityMatrix.Core.Helper.Cache; using StabilityMatrix.Core.Helper.HardwareInfo; From d2444fc8011044657facfc91da7b922624b15f0a Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:51:09 -0700 Subject: [PATCH 5/9] fix(fizgig): remove em dash from package blurb Co-Authored-By: Claude Opus 5.5 --- StabilityMatrix.Core/Models/Packages/Fizgig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index aece9b969..8e695c39c 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -32,7 +32,7 @@ IPipWheelService pipWheelService public override string Author => "shootthesound"; public override string Blurb => - "LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1 — train, profile, repair and extract"; + "LoRA training studio for Flux 2 Klein 9B, Krea 2, MiniMax H3 and Qwen Image 2.1. Train, profile, repair and extract"; // Shown in the install browser before the user commits to installing. public override string Disclaimer => From 9944d2cca2105fc2670ba9f446213be06fe1b484 Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:51:18 -0700 Subject: [PATCH 6/9] refactor(fizgig): drop redundant DISABLE_CUDA cleanup The install venv runner is local and disposed by its await using, and RunPackage builds a fresh one, so the variable cannot leak. Co-Authored-By: Claude Opus 5.5 --- StabilityMatrix.Core/Models/Packages/Fizgig.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 8e695c39c..8e38f2f25 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -168,8 +168,6 @@ await StandardPipInstallProcessAsync( cancellationToken ) .ConfigureAwait(false); - - venvRunner.UpdateEnvironmentVariables(env => env.Remove("DISABLE_CUDA")); } public override async Task RunPackage( From 0aa7e97686d9aa2f1dd2f218fe4980f9ecceeb67 Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:51:26 -0700 Subject: [PATCH 7/9] fix(fizgig): stop force-reinstalling torch on every update On a fresh install there is nothing to force over, and on updates the flag redownloaded torch, torchvision and every nvidia-* CUDA wheel even when the matching build was already present. Without it a matching build is kept and a mismatched one is still replaced. Co-Authored-By: Claude Opus 5.5 --- StabilityMatrix.Core/Models/Packages/Fizgig.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 8e38f2f25..1fe927e21 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -149,7 +149,6 @@ public override async Task InstallPackage( $"torchvision{torchvisionVersion}", "--extra-index-url", "https://download.pytorch.org/whl/cu128", - "--force-reinstall", ], // Re-state the pins alongside the requirements: pip then treats the installed // 2.10.0+cu128 as satisfying them instead of resolving its own torch from PyPI, and From 888fa3049a8050eb5a78d5cd05b3ed18602ec169 Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:51:43 -0700 Subject: [PATCH 8/9] fix(fizgig): drop Symlink shared folder option output_loras also receives sample images and resume-state folders (optimizer + weights, often several GB). Junctioning it into the shared Lora folder would surface those in other packages' LoRA lists and the Checkpoint Manager. Offer None only, like the other trainers; users can point Fizgig's Output Directory at the shared folder themselves. Co-Authored-By: Claude Opus 5.5 --- .../Models/Packages/Fizgig.cs | 35 +++++-------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 1fe927e21..3f7edb04a 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -75,35 +75,16 @@ IPipWheelService pipWheelService public override string OutputFolderName => string.Empty; public override Dictionary>? SharedOutputFolders => null; - /// - /// Defaults to None, matching the other trainers. Opting in to Symlink (Package Manager -> - /// ... -> Shared Model Strategy) junctions output_loras into the shared Lora folder, so a - /// freshly trained LoRA is immediately visible to ComfyUI and friends. - /// - public override SharedFolderMethod RecommendedSharedFolderMethod => SharedFolderMethod.None; - - public override IEnumerable AvailableSharedFolderMethods => - [SharedFolderMethod.None, SharedFolderMethod.Symlink]; - /// - /// Only output_loras is mapped. Fizgig's models/ directory deliberately flattens every - /// weight it downloads into one folder — DiTs, text encoders, VAEs, turbo LoRAs and training - /// adapters all land there as bare filenames (see src/fizgig/scripts/fetch_models.py) — and - /// junctions are directory-level, so there is no way to fan that single directory out to - /// DiffusionModels/TextEncoders/VAE without them colliding on the same target path. + /// None only, like the other trainers. output_loras also receives sample images and multi-GB + /// resume-state folders, so linking it into the shared Lora folder would leak those into other + /// packages. Users who want trained LoRAs there can point Fizgig's Output Directory at it. + /// models/ can't be shared either: Fizgig flattens every weight it downloads into that one + /// directory, which doesn't map onto the per-type shared folders. /// - public override SharedFolderLayout SharedFolderLayout => - new() - { - Rules = - [ - new SharedFolderLayoutRule - { - SourceTypes = [SharedFolderType.Lora], - TargetRelativePaths = ["output_loras"], - }, - ], - }; + public override SharedFolderMethod RecommendedSharedFolderMethod => SharedFolderMethod.None; + + public override IEnumerable AvailableSharedFolderMethods => [SharedFolderMethod.None]; public override async Task InstallPackage( string installLocation, From 136e0781c7df11a8c9bc207c79f13275de175382 Mon Sep 17 00:00:00 2001 From: e-nord Date: Sun, 4 Oct 2026 21:53:56 -0700 Subject: [PATCH 9/9] fix(fizgig): read torch pins and index from upstream requirements.txt The torch/torchvision pins and the cu128 index were hardcoded while the exclude pattern stripped upstream's own lines, so an upstream torch bump would keep installing 2.10.0 next to a newer triton-windows range, the mismatch upstream's requirements warn hangs Krea 2 previews. Port upstream's uv_install_deps._parse_requirements: install the torch-ecosystem lines first from the file's --extra-index-url, then the rest of requirements.txt without that index, keeping the torch pins so the CUDA build can't be swapped for a PyPI one. As upstream does, the torch-first step only runs when both an index and torch lines exist, and a second --extra-index-url is an error. Co-Authored-By: Claude Opus 5.5 --- .../Models/Packages/Fizgig.cs | 88 ++++++++++++++----- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/Fizgig.cs b/StabilityMatrix.Core/Models/Packages/Fizgig.cs index 3f7edb04a..7e6483e14 100644 --- a/StabilityMatrix.Core/Models/Packages/Fizgig.cs +++ b/StabilityMatrix.Core/Models/Packages/Fizgig.cs @@ -1,3 +1,4 @@ +using System.Text.RegularExpressions; using Injectio.Attributes; using StabilityMatrix.Core.Helper; using StabilityMatrix.Core.Helper.Cache; @@ -10,7 +11,7 @@ namespace StabilityMatrix.Core.Models.Packages; [RegisterSingleton(Duplicate = DuplicateStrategy.Append)] -public class Fizgig( +public partial class Fizgig( IGithubApiCache githubApi, ISettingsManager settingsManager, IDownloadService downloadService, @@ -108,33 +109,23 @@ public override async Task InstallPackage( // requirements.txt warns never to install that line without this. venvRunner.UpdateEnvironmentVariables(env => env.SetItem("DISABLE_CUDA", "1")); - const string torchVersion = "==2.10.0"; - const string torchvisionVersion = "==0.25.0"; + // Mirrors upstream's uv_install_deps.py: torch goes in first from the CUDA index, then + // the rest of requirements.txt without that index. The torch pins stay in the second + // step so nothing can swap the CUDA build for a PyPI one. + var (extraIndexUrl, torchSpecs) = await ParseRequirementsAsync( + Path.Combine(installLocation, "requirements.txt"), + cancellationToken + ) + .ConfigureAwait(false); var config = new PipInstallConfig { RequirementsFilePaths = ["requirements.txt"], - // Drop the torch pins and the cu128 index line from the file so the pre-install step - // below is the single source of truth for which build lands in the venv. The pattern - // is anchored against the whole entry by the caller, so the version specifier has to - // be matched too - the default pattern only catches bare, unpinned names. - RequirementsExcludePattern = - @"(--extra-index-url.*|(torch|torchvision|torchaudio|xformers)([=<>!~].*)?)", - // Install the cu128 build before the requirements. accelerate (and friends) depend on - // torch transitively, so installing it afterwards would let the requirements step - // pull a default PyPI build that then has to be force-reinstalled over. - // torch 2.10 pairs with cu128 here; SM's default cu130 has no matching wheels. + RequirementsExcludePattern = "--extra-index-url.*", PrePipInstallArgs = - [ - $"torch{torchVersion}", - $"torchvision{torchvisionVersion}", - "--extra-index-url", - "https://download.pytorch.org/whl/cu128", - ], - // Re-state the pins alongside the requirements: pip then treats the installed - // 2.10.0+cu128 as satisfying them instead of resolving its own torch from PyPI, and - // fails loudly rather than swapping it if anything conflicts. - ExtraPipArgs = [$"torch{torchVersion}", $"torchvision{torchvisionVersion}"], + extraIndexUrl is not null && torchSpecs.Count > 0 + ? [.. torchSpecs, "--extra-index-url", extraIndexUrl] + : [], SkipTorchInstall = true, }; @@ -150,6 +141,57 @@ await StandardPipInstallProcessAsync( .ConfigureAwait(false); } + private static readonly string[] TorchEcosystem = ["torch", "torchvision", "torchaudio"]; + + /// + /// Port of _parse_requirements in upstream's uv_install_deps.py: returns the single + /// --extra-index-url and the torch-ecosystem requirement lines. + /// + private static async Task<(string? ExtraIndexUrl, List TorchSpecs)> ParseRequirementsAsync( + string requirementsPath, + CancellationToken cancellationToken + ) + { + string? extraIndexUrl = null; + var torchSpecs = new List(); + + var lines = await File.ReadAllLinesAsync(requirementsPath, cancellationToken).ConfigureAwait(false); + foreach (var raw in lines) + { + var code = raw.Split('#', 2)[0].Trim(); + if (code.StartsWith("--extra-index-url", StringComparison.Ordinal)) + { + if (extraIndexUrl is not null) + { + throw new InvalidOperationException( + "Fizgig's requirements.txt declares more than one --extra-index-url" + ); + } + + var parts = code.Split((char[]?)null, 2, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length == 2) + { + extraIndexUrl = parts[1]; + } + continue; + } + + if (code.Length > 0) + { + var pkg = RequirementNameEndRegex().Split(code, 2)[0]; + if (TorchEcosystem.Contains(pkg)) + { + torchSpecs.Add(code); + } + } + } + + return (extraIndexUrl, torchSpecs); + } + + [GeneratedRegex(@"[=<>!~\s\[;]")] + private static partial Regex RequirementNameEndRegex(); + public override async Task RunPackage( string installLocation, InstalledPackage installedPackage,