diff --git a/CHANGELOG.md b/CHANGELOG.md index ea3dd143e..a5f918e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,29 @@ All notable changes to Stability Matrix will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.15.1 +### Changed +- Upgraded ComfyUI-Zluda and Stable Diffusion WebUI AMDGPU Forge packages to install and use HIP SDK 6.4.2 +- Changed ComfyUI torch index from `cu129` back to `cu128` for better compatibility with custom nodes +- Updated SageAttention installer to install v2.2.0-windows.post3 +- Updated Nunchaku installer to install v1.0.1 +- Updated Windows ROCm ComfyUI installs to use recommended environment variables by default +### Fixed +- Fixed [#1372](https://github.com/LykosAI/StabilityMatrix/issues/1372), [#1399](https://github.com/LykosAI/StabilityMatrix/issues/1399) - LiteAsyncException upon starting Stability Matrix v2.15.0 +- Fixed [#1391](https://github.com/LykosAI/StabilityMatrix/issues/1391) - "Failed to parse" error when upgrading pip packages with extra index url +- Fixed [#1401](https://github.com/LykosAI/StabilityMatrix/issues/1401) - "Python was not found and/or failed to install" errors when path contains special characters +- Fixed [#1403](https://github.com/LykosAI/StabilityMatrix/issues/1403) - Checkpoint Manager filters not being saved correctly +- Fixed [#1411](https://github.com/LykosAI/StabilityMatrix/issues/1411) - SD.Next installs not using correct torch version +- Fixed "cannot access local variable 'job' where it is not associated with a value" error when running jobs in AI Toolkit +- Fixed Civitai browser not always returning at least 30 results when possible on initial search +- Fixed model browser crashing when downloading a file with invalid characters in the name +- Fixed model browser crashing when no author exists for a model +### Supporters +#### 🌟 Visionaries +To our guiding stars, the Visionaries! Thank you **Waterclouds**, **JungleDragon**, **bluepopsicle**, **Bob S**, **Ibixat**, and **whudunit**! While this release is focused on fixes and stability, your foundational support is what empowers us to build a reliable and robust platform for everyone. +#### 🚀 Pioneers +A huge round of applause for our fantastic Pioneers! Your steady support helps us smooth out the rough edges and deliver a better experience with every update. Our deepest thanks to: **Szir777**, **Tigon**, **Noah M**, **USATechDude**, **Thom**, **SeraphOfSalem**, **Desert Viber**, **Tundra Everquill**, **Adam**, and **Droolguy**. We're also thrilled to welcome our newest Pioneers to the crew: **Philip R.**, **ACTUALLY_the_Real_Willem_Dafoe**, and **takyamtom**! + ## v2.15.0 ### Added - Added new package - [AI Toolkit](https://github.com/ostris/ai-toolkit/) diff --git a/StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs b/StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs index 77e5e1ec0..ed16218c1 100644 --- a/StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs +++ b/StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs @@ -45,7 +45,7 @@ IPyInstallationManager pyInstallationManager private const string CppBuildToolsUrl = "https://aka.ms/vs/17/release/vs_BuildTools.exe"; private const string HipSdkDownloadUrl = - "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-24.Q4-Win10-Win11-For-HIP.exe"; + "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-25.Q3-Win10-Win11-For-HIP.exe"; private const string PythonLibsDownloadUrl = "https://cdn.lykos.ai/python_libs_for_sage.zip"; private const string UvWindowsDownloadUrl = @@ -110,7 +110,7 @@ private string GetPythonLibraryZipPath(PyVersion version) => private string HipSdkDownloadPath => Path.Combine(AssetsDir, "AMD-HIP-SDK.exe"); private string HipInstalledPath => - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "AMD", "ROCm", "6.2"); + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "AMD", "ROCm", "6.4"); private string UvDownloadPath => Path.Combine(AssetsDir, "uv.zip"); private string UvExtractPath => Path.Combine(AssetsDir, "uv"); @@ -189,7 +189,7 @@ private async Task RunNode( result.EnsureSuccessExitCode(); return result.StandardOutput ?? result.StandardError ?? string.Empty; - } + } public async Task RunNpm( ProcessArgs args, @@ -997,15 +997,11 @@ private async Task PatchHipSdkIfNecessary(IProgress? progress) var zipFolderName = downloadUrl switch { - _ when downloadUrl.Contains("gfx1201") => null, - _ when downloadUrl.Contains("gfx1150") => "rocm gfx1150 for hip skd 6.2.4", - _ when downloadUrl.Contains("gfx1103.AMD") => - "rocm gfx1103 AMD 780M phoenix V5.0 for hip skd 6.2.4", - _ when downloadUrl.Contains("gfx1034") => "rocm gfx1034-gfx1035-gfx1036 for hip sdk 6.2.4", - _ when downloadUrl.Contains("gfx1032") => "rocm gfx1032 for hip skd 6.2.4(navi21 logic)", - _ when downloadUrl.Contains("gfx1031") => "rocm gfx1031 for hip skd 6.2.4 (littlewu's logic)", - _ when downloadUrl.Contains("gfx1010") => - "rocm gfx1010-xnack-gfx1011-xnack-gfx1012-xnack- for hip sdk 6.2.4", + _ when downloadUrl.Contains("gfx1103.for.hip") => "rocm gfx1103 for hip 6.4.2", + _ when downloadUrl.Contains("gfx1034") => "rocm gfx1034.gfx1035.gfx1036 for hip 6.4.2", + _ when downloadUrl.Contains("gfx1032") => "rocm gfx1032 for hip 6.4.2", + _ when downloadUrl.Contains("gfx1031") => "rocm gfx1031 for hip 6.4.2", + _ when downloadUrl.Contains("gfx1010") => "rocm gfx1010-xnack-gfx1012-xnack-.for.hip6.4.2", _ => null, }; @@ -1035,27 +1031,29 @@ _ when downloadUrl.Contains("gfx1010") => private string? GetDownloadUrlFromGpuName(string name) { + // not used anymore but good to know for gfx -> name reference // gfx1201 - if (name.Contains("9060") || name.Contains("9070")) - { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1201.for.hip.skd.6.2.4-no-optimized.7z"; - } + // if (name.Contains("9060") || name.Contains("9070")) + // { + // return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1201.for.hip.skd.6.2.4-no-optimized.7z"; + // } + // not used anymore but good to know for gfx -> name reference // gfx1150 - if ( - name.Contains("8050S") - || name.Contains("8060S") - || name.Contains("880M") - || name.Contains("890M") - ) - { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1150.for.hip.skd.6.2.4.7z"; - } + // if ( + // name.Contains("8050S") + // || name.Contains("8060S") + // || name.Contains("880M") + // || name.Contains("890M") + // ) + // { + // return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1150.for.hip.skd.6.2.4.7z"; + // } // gfx1103 if (name.Contains("740M") || name.Contains("760M") || name.Contains("780M") || name.Contains("Z1")) { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1103.AMD.780M.phoenix.V5.0.for.hip.sdk.6.2.4.7z"; + return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.4.2/rocm.gfx1103.for.hip.6.4.2.7z"; } // gfx1034, gfx1035, gfx1036 @@ -1070,7 +1068,7 @@ _ when downloadUrl.Contains("gfx1010") => || name.Contains("Graphics 128SP") ) { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1034-gfx1035-gfx1036.for.hip.sdk.6.2.4.7z"; + return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.4.2/rocm.gfx1034.gfx1035.gfx1036.for.hip.6.4.2.7z"; } // gfx1032 @@ -1081,7 +1079,7 @@ _ when downloadUrl.Contains("gfx1010") => || name.Contains("6650") ) { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1032.for.hip.sdk.6.2.4.navi21.logic.7z"; + return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.4.2/rocm.gfx1032.for.hip.6.4.2.7z"; } // gfx1031 @@ -1092,13 +1090,13 @@ _ when downloadUrl.Contains("gfx1010") => || name.Contains("6850M") ) { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1031.for.hip.sdk.6.2.4.littlewu.s.logic.7z"; + return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.4.2/rocm.gfx1031.for.hip.6.4.2.7z"; } // gfx1010/1012 if (name.Contains("5700") || name.Contains("5600") || name.Contains("5300") || name.Contains("5500")) { - return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.2.4/rocm.gfx1010-xnack-gfx1011-xnack-gfx1012-xnack-.for.hip.sdk.6.2.4.7z"; + return "https://github.com/likelovewant/ROCmLibs-for-gfx1103-AMD780M-APU/releases/download/v0.6.4.2/rocm.gfx1010-xnack-gfx1012-xnack-.for.hip6.4.2.7z"; } return null; diff --git a/StabilityMatrix.Avalonia/Models/Inference/FileNameFormat.cs b/StabilityMatrix.Avalonia/Models/Inference/FileNameFormat.cs index f4caa98dd..f60938831 100644 --- a/StabilityMatrix.Avalonia/Models/Inference/FileNameFormat.cs +++ b/StabilityMatrix.Avalonia/Models/Inference/FileNameFormat.cs @@ -37,7 +37,20 @@ public string GetFileName() return Prefix + string.Join( "", - Parts.Select(part => part.Match(constant => constant, substitution => substitution.Invoke())) + Parts.Select(part => + part.Match( + constant => constant, + substitution => + { + // Filter invalid path chars + var result = substitution.Invoke(); + return result is null + ? null + : Path.GetInvalidFileNameChars() + .Aggregate(result, (current, c) => current.Replace(c, '_')); + } + ) + ) ) + Postfix; } diff --git a/StabilityMatrix.Avalonia/Models/Inference/FileNameFormatProvider.cs b/StabilityMatrix.Avalonia/Models/Inference/FileNameFormatProvider.cs index 73bc2a2d4..23afb3c82 100644 --- a/StabilityMatrix.Avalonia/Models/Inference/FileNameFormatProvider.cs +++ b/StabilityMatrix.Avalonia/Models/Inference/FileNameFormatProvider.cs @@ -47,7 +47,7 @@ public partial class FileNameFormatProvider { "project_name", () => ProjectName }, { "date", () => DateTime.Now.ToString("yyyy-MM-dd") }, { "time", () => DateTime.Now.ToString("HH-mm-ss") }, - { "author", () => CivitModel?.Creator.Username }, + { "author", () => CivitModel?.Creator?.Username }, { "base_model", () => CivitModelVersion?.BaseModel }, { "file_name", () => Path.GetFileNameWithoutExtension(CivitFile?.Name) }, { "file_id", () => CivitFile?.Id.ToString() }, diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs index dc4f2f754..d8480cc34 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs @@ -212,7 +212,7 @@ private void ToggleFavorite() [RelayCommand] public void SearchAuthor() { - EventManager.Instance.OnNavigateAndFindCivitAuthorRequested(CivitModel.Creator.Username); + EventManager.Instance.OnNavigateAndFindCivitAuthorRequested(CivitModel.Creator?.Username); } private async Task DoImport( diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs index e3490bda5..ecab4e7ba 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs @@ -52,6 +52,8 @@ public sealed partial class CivitAiBrowserViewModel : TabViewModelBase, IInfinit private readonly SourceCache, int> modelCache = new(static ov => ov.Value.Id); + private const int TargetPageItemCount = 30; + [ObservableProperty] private IObservableCollection modelCards = new ObservableCollectionExtended(); @@ -453,8 +455,46 @@ private async Task CivitModelQuery(CivitModelsRequest request, bool isInfiniteSc } else { - modelsResponse = await civitApi.GetModels(request); - models = modelsResponse.Items; + // Auto-paginate via cursor until we fill the target page size or run out + var collectedById = new HashSet(); + var targetCount = request.Limit ?? TargetPageItemCount; + var safetyGuard = 0; + + while (true) + { + var resp = await civitApi.GetModels(request); + modelsResponse = resp; + + if (resp.Items != null) + { + foreach (var item in resp.Items) + { + if (collectedById.Add(item.Id)) + { + models.Add(item); + } + } + } + + // Check how many items survive local filtering + var filteredCount = models + .Where(m => m.Type.ConvertTo() > 0) + .Count(m => m.Mode == null); + + var next = resp.Metadata?.NextCursor; + if (filteredCount >= targetCount || string.IsNullOrEmpty(next)) + { + break; + } + + request.Cursor = next; + + if (++safetyGuard >= 10) + { + // Avoid unbounded looping on unexpected cursors + break; + } + } } if (models is null) @@ -513,7 +553,7 @@ private async Task CivitModelQuery(CivitModelsRequest request, bool isInfiniteSc var doesBaseModelTypeMatch = SelectedBaseModels.Count == 0 ? request.BaseModels == null || request.BaseModels.Length == 0 - : SelectedBaseModels.SequenceEqual(request.BaseModels); + : SelectedBaseModels.SequenceEqual(request.BaseModels ?? []); var doesModelTypeMatch = SelectedModelType == CivitModelType.All ? request.Types == null || request.Types.Length == 0 @@ -634,6 +674,7 @@ private async Task SearchModels(bool isInfiniteScroll = false) // Build request var modelRequest = new CivitModelsRequest { + Limit = TargetPageItemCount + 20, // Fetch a few extra to account for local filtering Nsfw = "true", // Handled by local view filter Sort = SortMode, Period = SelectedPeriod, diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitDetailsPageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitDetailsPageViewModel.cs index fbe12c8c3..c29c1dbce 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitDetailsPageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitDetailsPageViewModel.cs @@ -651,7 +651,7 @@ private async Task ShowImageDialog(ImageSource? image) private void SearchByAuthor() { navigationService.GoBack(); - EventManager.Instance.OnNavigateAndFindCivitAuthorRequested(CivitModel.Creator.Username); + EventManager.Instance.OnNavigateAndFindCivitAuthorRequested(CivitModel.Creator?.Username); } [RelayCommand] diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs index 9cb84a4d7..d99a1fb4e 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs @@ -160,8 +160,6 @@ protected override async Task OnInitialLoadedAsync() await base.OnInitialLoadedAsync(); - var settingsSelectedBaseModels = settingsManager.Settings.SelectedBaseModels; - AddDisposable( BaseModelCache .Connect() @@ -169,7 +167,7 @@ protected override async Task OnInitialLoadedAsync() .Transform(baseModel => new BaseModelOptionViewModel { ModelType = baseModel, - IsSelected = settingsSelectedBaseModels.Contains(baseModel), + IsSelected = settingsManager.Settings.SelectedBaseModels.Contains(baseModel), }) .SortAndBind( BaseModelOptions, @@ -179,10 +177,15 @@ protected override async Task OnInitialLoadedAsync() .ObserveOn(SynchronizationContext.Current) .Subscribe(next => { - if (next.Sender.IsSelected) - SelectedBaseModels.Add(next.Sender.ModelType); - else - SelectedBaseModels.Remove(next.Sender.ModelType); + switch (next.Sender.IsSelected) + { + case true when !SelectedBaseModels.Contains(next.Sender.ModelType): + SelectedBaseModels.Add(next.Sender.ModelType); + break; + case false when SelectedBaseModels.Contains(next.Sender.ModelType): + SelectedBaseModels.Remove(next.Sender.ModelType); + break; + } OnPropertyChanged(nameof(ClearButtonText)); OnPropertyChanged(nameof(SelectedBaseModels)); @@ -191,6 +194,7 @@ protected override async Task OnInitialLoadedAsync() var settingsTransactionObservable = this.WhenPropertyChanged(x => x.SelectedBaseModels) .Throttle(TimeSpan.FromMilliseconds(50)) + .Skip(1) .ObserveOn(SynchronizationContext.Current) .Subscribe(_ => { diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/PythonPackagesViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/PythonPackagesViewModel.cs index 3575abd9c..81bf8e256 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/PythonPackagesViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/PythonPackagesViewModel.cs @@ -239,7 +239,7 @@ private async Task UpgradePackageVersion( if (extraIndexUrl != null) { - args = args.AddArg(("--extra-index-url", extraIndexUrl)); + args = args.AddArgs("--extra-index-url", extraIndexUrl); } var steps = new List diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/ModelCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/ModelCardViewModel.cs index 141a1c58d..3daa6618f 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/ModelCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/ModelCardViewModel.cs @@ -309,7 +309,7 @@ public override void LoadStateFromJsonObject(JsonObject state) ? HybridModelFile.None : ClientManager.ClipModels.FirstOrDefault(x => x.RelativePath == model.SelectedClip3Name); - SelectedClip4 = model.SelectedClip3Name is null + SelectedClip4 = model.SelectedClip4Name is null ? HybridModelFile.None : ClientManager.ClipModels.FirstOrDefault(x => x.RelativePath == model.SelectedClip4Name); diff --git a/StabilityMatrix.Core/Database/LiteDbContext.cs b/StabilityMatrix.Core/Database/LiteDbContext.cs index cdd2156b7..3eb6a3a90 100644 --- a/StabilityMatrix.Core/Database/LiteDbContext.cs +++ b/StabilityMatrix.Core/Database/LiteDbContext.cs @@ -10,6 +10,7 @@ using StabilityMatrix.Core.Models.Api; using StabilityMatrix.Core.Models.Configs; using StabilityMatrix.Core.Models.Database; +using StabilityMatrix.Core.Models.FileInterfaces; using StabilityMatrix.Core.Services; namespace StabilityMatrix.Core.Database; @@ -63,18 +64,25 @@ IOptions debugOptions private LiteDatabaseAsync CreateDatabase() { - LiteDatabaseAsync? db = null; + // Try at most twice: + // - attempt 0: open/repair if needed + // - on "Detected loop in FindAll": dispose, delete file, try once more + const int maxAttempts = 2; + var dbPath = Path.Combine(settingsManager.LibraryDir, "StabilityMatrix.db"); - if (debugOptions.TempDatabase) + for (var attempt = 0; attempt < maxAttempts; attempt++) { - db = new LiteDatabaseAsync(":temp:"); - } - else - { - // Attempt to create connection, might be in use + LiteDatabaseAsync? db = null; + try { - var dbPath = Path.Combine(settingsManager.LibraryDir, "StabilityMatrix.db"); + if (debugOptions.TempDatabase) + { + db = new LiteDatabaseAsync(":temp:"); + RegisterRefs(); + return db; + } + db = new LiteDatabaseAsync( new ConnectionString { Filename = dbPath, Connection = ConnectionType.Shared } ); @@ -86,33 +94,73 @@ private LiteDatabaseAsync CreateDatabase() "Database collation is not Ordinal ({SortOption}), rebuilding...", sortOption ); - var options = new RebuildOptions { Collation = new Collation(CultureInfo.InvariantCulture.LCID, CompareOptions.Ordinal), }; - db.RebuildAsync(options).GetAwaiter().GetResult(); } + + RegisterRefs(); + return db; } - catch (IOException e) + catch (LiteAsyncException ex) + when (ex.InnerException is LiteException e + && e.Message.Contains("Detected loop in FindAll", StringComparison.OrdinalIgnoreCase) + ) + { + logger.LogWarning("Database corruption detected ({Message}), rebuilding...", e.Message); + + try + { + db?.Dispose(); + } + catch + { + // ignored + } + + try + { + // Backup then delete, in case we want to inspect later. + var corruptPath = dbPath + ".old-" + DateTime.UtcNow.ToString("yyyyMMddHHmmss"); + if (File.Exists(dbPath)) + { + File.Copy(dbPath, corruptPath, overwrite: false); + File.Delete(dbPath); + } + } + catch (Exception delEx) + { + logger.LogWarning("Failed to delete corrupt DB: {Message}", delEx.Message); + // If we can't delete, no point retrying; break to fallback. + break; + } + } + catch (IOException ioEx) { logger.LogWarning( "Database in use or not accessible ({Message}), using temporary database", - e.Message + ioEx.Message ); + break; // fall through to temp } } // Fallback to temporary database - db ??= new LiteDatabaseAsync(":temp:"); - - // Register reference fields - LiteDBExtensions.Register(m => m.ModelVersions, "CivitModelVersions"); - LiteDBExtensions.Register(e => e.Items, "CivitModels"); - LiteDBExtensions.Register(e => e.LatestModelInfo, "CivitModels"); + var tempDb = new LiteDatabaseAsync(":temp:"); + RegisterRefs(); + return tempDb; - return db; + void RegisterRefs() + { + LiteDBExtensions.Register( + m => m.ModelVersions, + "CivitModelVersions" + ); + LiteDBExtensions.Register(e => e.Items, "CivitModels"); + LiteDBExtensions.Register(e => e.LatestModelInfo, "CivitModels"); + } } public async Task<(CivitModel?, CivitModelVersion?)> FindCivitModelFromFileHashAsync(string hashBlake3) diff --git a/StabilityMatrix.Core/Models/Api/CivitModel.cs b/StabilityMatrix.Core/Models/Api/CivitModel.cs index 43d283e3d..26de130b7 100644 --- a/StabilityMatrix.Core/Models/Api/CivitModel.cs +++ b/StabilityMatrix.Core/Models/Api/CivitModel.cs @@ -27,7 +27,7 @@ public class CivitModel public CivitMode? Mode { get; set; } [JsonPropertyName("creator")] - public CivitCreator Creator { get; set; } + public CivitCreator? Creator { get; set; } [JsonPropertyName("stats")] public CivitModelStats Stats { get; set; } diff --git a/StabilityMatrix.Core/Models/PackageModification/InstallNunchakuStep.cs b/StabilityMatrix.Core/Models/PackageModification/InstallNunchakuStep.cs index 3b450b033..e6d570e9a 100644 --- a/StabilityMatrix.Core/Models/PackageModification/InstallNunchakuStep.cs +++ b/StabilityMatrix.Core/Models/PackageModification/InstallNunchakuStep.cs @@ -50,6 +50,7 @@ await pyInstallationManager.GetInstallationAsync(pyVersion).ConfigureAwait(false 10 => "cp310", 11 => "cp311", 12 => "cp312", + 13 => "cp313", _ => throw new ArgumentOutOfRangeException("Invalid Python version"), }; var platform = Compat.IsWindows ? "win_amd64" : "linux_x86_64"; @@ -65,13 +66,13 @@ var v when v.StartsWith("2.5") => "2.5", var v when v.StartsWith("2.6") => "2.6", var v when v.StartsWith("2.7") => "2.7", var v when v.StartsWith("2.8") => "2.8", + var v when v.StartsWith("2.10") => "2.10", _ => throw new InvalidOperationException( "No compatible torch version found in the virtual environment." ), }; - var downloadUrl = - $"https://github.com/mit-han-lab/nunchaku/releases/download/v0.3.1/nunchaku-0.3.1+torch{torchVersion}-{shortPythonVersionString}-{shortPythonVersionString}-{platform}.whl"; + $"https://github.com/nunchaku-tech/nunchaku/releases/download/v1.0.1/nunchaku-1.0.1+torch{torchVersion}-{shortPythonVersionString}-{shortPythonVersionString}-{platform}.whl"; progress?.Report( new ProgressReport(-1f, message: "Installing Nunchaku backend", isIndeterminate: true) ); @@ -82,31 +83,43 @@ var v when v.StartsWith("2.8") => "2.8", new ProgressReport(1f, message: "Nunchaku backend installed successfully", isIndeterminate: false) ); - var nunchakuNodePath = WorkingDirectory.JoinDir("custom_nodes", "ComfyUI-nunchaku"); - if (nunchakuNodePath.Exists) - { - progress?.Report( - new ProgressReport( - 1f, - message: "Nunchaku extension installed successfully.", - isIndeterminate: false - ) - ); - return; - } - var extensions = await ComfyExtensionManager .GetManifestExtensionsAsync(ComfyExtensionManager.DefaultManifests) .ConfigureAwait(false); var nunchakuExtension = extensions.FirstOrDefault(e => e.Title.Equals("ComfyUI-nunchaku", StringComparison.OrdinalIgnoreCase) ); + if (nunchakuExtension is null) return; - await ComfyExtensionManager - .InstallExtensionAsync(nunchakuExtension, InstalledPackage, null, progress) + var installedExtensions = await ComfyExtensionManager + .GetInstalledExtensionsLiteAsync(InstalledPackage) .ConfigureAwait(false); + var installedNunchakuExtension = installedExtensions.FirstOrDefault(e => + e.Title.Equals("ComfyUI-nunchaku", StringComparison.OrdinalIgnoreCase) + ); + + if (installedNunchakuExtension is not null) + { + var installedNunchakuExtensionWithVersion = await ComfyExtensionManager + .GetInstalledExtensionInfoAsync(installedNunchakuExtension) + .ConfigureAwait(false); + installedNunchakuExtensionWithVersion = installedNunchakuExtensionWithVersion with + { + Definition = nunchakuExtension, + }; + + await ComfyExtensionManager + .UpdateExtensionAsync(installedNunchakuExtensionWithVersion, InstalledPackage, null, progress) + .ConfigureAwait(false); + } + else + { + await ComfyExtensionManager + .InstallExtensionAsync(nunchakuExtension, InstalledPackage, null, progress) + .ConfigureAwait(false); + } progress?.Report( new ProgressReport( diff --git a/StabilityMatrix.Core/Models/PackageModification/InstallSageAttentionStep.cs b/StabilityMatrix.Core/Models/PackageModification/InstallSageAttentionStep.cs index 202a3cfdb..723f1afba 100644 --- a/StabilityMatrix.Core/Models/PackageModification/InstallSageAttentionStep.cs +++ b/StabilityMatrix.Core/Models/PackageModification/InstallSageAttentionStep.cs @@ -67,12 +67,12 @@ await pyInstallationManager.GetInstallationAsync(pyVersion).ConfigureAwait(false else if (torchInfo.Version.Contains("2.5.1") && torchInfo.Version.Contains("cu124")) { sageWheelUrl = - "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post2/sageattention-2.2.0+cu124torch2.5.1.post2-cp39-abi3-win_amd64.whl"; + "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post3/sageattention-2.2.0+cu124torch2.5.1.post3-cp39-abi3-win_amd64.whl"; } else if (torchInfo.Version.Contains("2.6.0") && torchInfo.Version.Contains("cu126")) { sageWheelUrl = - $"https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post2/sageattention-2.2.0+cu126torch2.6.0.post2-cp39-abi3-win_amd64.whl"; + "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post3/sageattention-2.2.0+cu126torch2.6.0.post3-cp39-abi3-win_amd64.whl"; } else if (torchInfo.Version.Contains("2.7.0") && torchInfo.Version.Contains("cu128")) { @@ -82,20 +82,20 @@ await pyInstallationManager.GetInstallationAsync(pyVersion).ConfigureAwait(false else if (torchInfo.Version.Contains("2.7.1") && torchInfo.Version.Contains("cu128")) { sageWheelUrl = - $"https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post2/sageattention-2.2.0+cu128torch2.7.1.post2-cp39-abi3-win_amd64.whl"; + "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post3/sageattention-2.2.0+cu128torch2.7.1.post3-cp39-abi3-win_amd64.whl"; } else if (torchInfo.Version.Contains("2.8.0") && torchInfo.Version.Contains("cu128")) { sageWheelUrl = - $"https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post2/sageattention-2.2.0+cu128torch2.8.0.post2-cp39-abi3-win_amd64.whl"; + "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post3/sageattention-2.2.0+cu128torch2.8.0.post3-cp39-abi3-win_amd64.whl"; } - - var pipArgs = new PipInstallArgs(); - if (IsBlackwellGpu) + else if (torchInfo.Version.Contains("2.9.0") && torchInfo.Version.Contains("cu128")) { - pipArgs = pipArgs.AddArg("--pre"); + sageWheelUrl = + "https://github.com/woct0rdho/SageAttention/releases/download/v2.2.0-windows.post3/sageattention-2.2.0+cu128torch2.9.0.post3-cp39-abi3-win_amd64.whl"; } - pipArgs = pipArgs.AddArg("triton-windows"); + + var pipArgs = new PipInstallArgs("triton-windows"); if (!string.IsNullOrWhiteSpace(sageWheelUrl)) { diff --git a/StabilityMatrix.Core/Models/Packages/AiToolkit.cs b/StabilityMatrix.Core/Models/Packages/AiToolkit.cs index 7b2c13bb3..24009cef2 100644 --- a/StabilityMatrix.Core/Models/Packages/AiToolkit.cs +++ b/StabilityMatrix.Core/Models/Packages/AiToolkit.cs @@ -183,6 +183,9 @@ await npmProcess private ImmutableDictionary GetEnvVars(ImmutableDictionary env) { + // set SETUPTOOLS_USE_DISTUTILS=setuptools to avoid job errors + env = env.SetItem("SETUPTOOLS_USE_DISTUTILS", "setuptools"); + var pathBuilder = new EnvPathBuilder(); if (env.TryGetValue("PATH", out var value)) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index dbce07e0e..504e3392f 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Collections.Immutable; +using System.Text.Json; using System.Text.RegularExpressions; using Injectio.Attributes; using NLog; @@ -411,7 +412,7 @@ _ when gfxArch.StartsWith("gfx120") => "https://rocm.nightlies.amd.com/v2/gfx120 RequirementsFilePaths = ["requirements.txt"], ExtraPipArgs = ["numpy<2"], TorchaudioVersion = " ", // Request torchaudio without a specific version - CudaIndex = isLegacyNvidia ? "cu126" : "cu129", + CudaIndex = isLegacyNvidia ? "cu126" : "cu128", RocmIndex = "rocm6.4", UpgradePackages = true, }; @@ -443,6 +444,8 @@ public override async Task RunPackage( await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage.PythonVersion)) .ConfigureAwait(false); + VenvRunner.UpdateEnvironmentVariables(GetEnvVars); + VenvRunner.RunDetached( [Path.Combine(installLocation, options.Command ?? LaunchCommand), .. options.Arguments], HandleConsoleOutput, @@ -808,4 +811,20 @@ private async Task InstallNunchaku(InstalledPackage? installedPackage) EventManager.Instance.OnPackageInstallProgressAdded(runner); await runner.ExecuteSteps([installNunchaku]).ConfigureAwait(false); } + + private ImmutableDictionary GetEnvVars(ImmutableDictionary env) + { + // if we're not on windows or we don't have a windows rocm gpu, return original env + var hasRocmGpu = + SettingsManager.Settings.PreferredGpu?.IsWindowsRocmSupportedGpu() + ?? HardwareHelper.HasWindowsRocmSupportedGpu(); + + if (!Compat.IsWindows || !hasRocmGpu) + return env; + + // set some experimental speed improving env vars for Windows ROCm + return env.SetItem("PYTORCH_TUNABLEOP_ENABLED", "1") + .SetItem("MIOPEN_FIND_MODE", "2") + .SetItem("TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL", "1"); + } } diff --git a/StabilityMatrix.Core/Models/Packages/ComfyZluda.cs b/StabilityMatrix.Core/Models/Packages/ComfyZluda.cs index 2ff3f4ef1..9fbe88721 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyZluda.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyZluda.cs @@ -68,39 +68,15 @@ public override async Task InstallPackage( { if (!PrerequisiteHelper.IsHipSdkInstalled) // for updates { - progress?.Report(new ProgressReport(-1, "Installing HIP SDK 6.2", isIndeterminate: true)); + progress?.Report(new ProgressReport(-1, "Installing HIP SDK 6.4", isIndeterminate: true)); await PrerequisiteHelper .InstallPackageRequirements(this, options.PythonOptions.PythonVersion, progress) .ConfigureAwait(false); } - // download & setup hip sdk extension if not already done - var hipPath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), - "AMD", - "ROCm", - "6.2" - ); - var hipblasltPath = new DirectoryPath(hipPath, "hipblaslt"); - var otherHipPath = new DirectoryPath(hipPath, "include", "hipblaslt"); - - if (!hipblasltPath.Exists || !otherHipPath.Exists) + if (options.IsUpdate) { - var hipSdkExtensionPath = new FilePath( - SettingsManager.LibraryDir, - "Assets", - "hip-sdk-extension.7z" - ); - await DownloadService - .DownloadToFileAsync( - HipSdkExtensionDownloadUrl, - hipSdkExtensionPath, - progress, - cancellationToken: cancellationToken - ) - .ConfigureAwait(false); - - await ArchiveHelper.Extract7Z(hipSdkExtensionPath, hipPath, progress).ConfigureAwait(false); + return; } progress?.Report(new ProgressReport(-1, "Setting up venv", isIndeterminate: true)); @@ -110,139 +86,34 @@ await DownloadService ) .ConfigureAwait(false); - var config = new PipInstallConfig - { - RequirementsFilePaths = ["requirements.txt"], - RequirementsExcludePattern = "(torch|numpy)", // Keep numpy excluded for specific install below - TorchVersion = "==2.7.0", - TorchvisionVersion = "==0.22.0", - TorchaudioVersion = "==2.7.0", - CudaIndex = "cu118", - ForceReinstallTorch = true, - ExtraPipArgs = ["numpy==1.26.0"], - }; - - await StandardPipInstallProcessAsync( - venvRunner, - options, - installedPackage, - config, - onConsoleOutput, - progress, - cancellationToken - ) - .ConfigureAwait(false); - - progress?.Report(new ProgressReport(1, "Installed Package Requirements", isIndeterminate: false)); + var installNBatPath = new FilePath(installLocation, "install-n.bat"); + var newInstallBatPath = new FilePath(installLocation, "install-sm.bat"); - progress?.Report(new ProgressReport(-1f, "Setting up ZLUDA...", isIndeterminate: true)); + var installNText = await installNBatPath.ReadAllTextAsync(cancellationToken).ConfigureAwait(false); + var installNLines = installNText.Split(Environment.NewLine); + var cutoffIndex = Array.FindIndex(installNLines, line => line.Contains("Installation is completed")); - // patch zluda - var zludaPatchPath = new FilePath(installLocation, "zluda.zip"); - var zludaExtractPath = new DirectoryPath(installLocation, "zluda"); - if (zludaExtractPath.Exists) + IEnumerable filtered = installNLines; + if (cutoffIndex >= 0) { - await zludaExtractPath.DeleteAsync(true).ConfigureAwait(false); + filtered = installNLines.Take(cutoffIndex); } - zludaExtractPath.Create(); - - await downloadService - .DownloadToFileAsync( - ZludaPatchDownloadUrl, - zludaPatchPath, - progress, - cancellationToken: cancellationToken - ) + + newInstallBatPath.Create(); + await newInstallBatPath + .WriteAllTextAsync(string.Join(Environment.NewLine, filtered), cancellationToken) .ConfigureAwait(false); - await ArchiveHelper.Extract(zludaPatchPath, zludaExtractPath, progress).ConfigureAwait(false); - await zludaPatchPath.DeleteAsync(cancellationToken).ConfigureAwait(false); - - // copy some stuff into the venv - var cublasSourcePath = new FilePath(installLocation, "zluda", "cublas.dll"); - var cusparseSourcePath = new FilePath(installLocation, "zluda", "cusparse.dll"); - var nvrtc112SourcePath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "nvrtc64_112_0.dll" - ); - var nvrtcSourcePath = new FilePath(installLocation, "zluda", "nvrtc.dll"); - var cudnnSourcePath = new FilePath(installLocation, "zluda", "cudnn.dll"); - var cufftSourcePath = new FilePath(installLocation, "zluda", "cufft.dll"); - var cufftwSourcePath = new FilePath(installLocation, "zluda", "cufftw.dll"); - var zludaPySourcePath = new FilePath(installLocation, "comfy", "customzluda", "zluda.py"); - - var cublasDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "cublas64_11.dll" - ); - var cusparseDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "cusparse64_11.dll" - ); - var nvrtc112DestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "nvrtc_cuda.dll" - ); - var nvrtcDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "nvrtc64_112_0.dll" - ); - var cudnnDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "cudnn64_9.dll" - ); - var cufftDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "cufft64_10.dll" - ); - var cufftwDestPath = new FilePath( - venvRunner.RootPath, - "Lib", - "site-packages", - "torch", - "lib", - "cufftw64_10.dll" + var installProcess = ProcessRunner.StartAnsiProcess( + newInstallBatPath, + [], + installLocation, + onConsoleOutput, + GetEnvVars(true) ); - var zludaPyDestPath = new FilePath(installLocation, "comfy", "zluda.py"); - - await cublasSourcePath.CopyToAsync(cublasDestPath, true).ConfigureAwait(false); - await cusparseSourcePath.CopyToAsync(cusparseDestPath, true).ConfigureAwait(false); - await nvrtc112SourcePath.CopyToAsync(nvrtc112DestPath, true).ConfigureAwait(false); - await nvrtcSourcePath.CopyToAsync(nvrtcDestPath, true).ConfigureAwait(false); - await cudnnSourcePath.CopyToAsync(cudnnDestPath, true).ConfigureAwait(false); - await cufftSourcePath.CopyToAsync(cufftDestPath, true).ConfigureAwait(false); - await cufftwSourcePath.CopyToAsync(cufftwDestPath, true).ConfigureAwait(false); - await zludaPySourcePath.CopyToAsync(zludaPyDestPath, true).ConfigureAwait(false); - - progress?.Report(new ProgressReport(1, "Installed ZLUDA", isIndeterminate: false)); + await installProcess.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + + progress?.Report(new ProgressReport(1, "Installed Successfully", isIndeterminate: false)); } public override async Task RunPackage( @@ -257,36 +128,11 @@ public override async Task RunPackage( { throw new MissingPrerequisiteException( "HIP SDK", - "Your package has not yet been upgraded to use HIP SDK 6.2. To continue, please update this package or select \"Change Version\" from the 3-dots menu to have it upgraded automatically for you" + "Your package has not yet been upgraded to use HIP SDK 6.4. To continue, please update this package or select \"Change Version\" from the 3-dots menu to have it upgraded automatically for you" ); } await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage.PythonVersion)) .ConfigureAwait(false); - var portableGitBin = new DirectoryPath(PrerequisiteHelper.GitBinPath); - var hipPath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), - "AMD", - "ROCm", - "6.2" - ); - var hipBinPath = Path.Combine(hipPath, "bin"); - var envVars = new Dictionary - { - ["ZLUDA_COMGR_LOG_LEVEL"] = "1", - ["HIP_PATH"] = hipPath, - ["HIP_PATH_62"] = hipPath, - ["GIT"] = portableGitBin.JoinFile("git.exe"), - }; - envVars.Update(settingsManager.Settings.EnvironmentVariables); - - if (envVars.TryGetValue("PATH", out var pathValue)) - { - envVars["PATH"] = Compat.GetEnvPathWithExtensions(hipBinPath, portableGitBin, pathValue); - } - else - { - envVars["PATH"] = Compat.GetEnvPathWithExtensions(hipBinPath, portableGitBin); - } var zludaPath = Path.Combine(installLocation, LaunchCommand); ProcessArgs args = ["--", VenvRunner.PythonPath.ToString(), "main.py", .. options.Arguments]; @@ -295,7 +141,7 @@ await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage args, installLocation, HandleConsoleOutput, - envVars + GetEnvVars(false) ); return; @@ -337,4 +183,42 @@ await zludaProcess zludaProcess = null; GC.SuppressFinalize(this); } + + private Dictionary GetEnvVars(bool isInstall) + { + var portableGitBin = new DirectoryPath(PrerequisiteHelper.GitBinPath); + var hipPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), + "AMD", + "ROCm", + "6.4" + ); + var hipBinPath = Path.Combine(hipPath, "bin"); + var envVars = new Dictionary + { + ["ZLUDA_COMGR_LOG_LEVEL"] = "1", + ["HIP_PATH"] = hipPath, + ["HIP_PATH_64"] = hipPath, + ["GIT"] = portableGitBin.JoinFile("git.exe"), + }; + envVars.Update(settingsManager.Settings.EnvironmentVariables); + + if (envVars.TryGetValue("PATH", out var pathValue)) + { + envVars["PATH"] = Compat.GetEnvPathWithExtensions(hipBinPath, portableGitBin, pathValue); + } + else + { + envVars["PATH"] = Compat.GetEnvPathWithExtensions(hipBinPath, portableGitBin); + } + + if (isInstall) + return envVars; + + envVars["FLASH_ATTENTION_TRITON_AMD_ENABLE"] = "TRUE"; + envVars["MIOPEN_FIND_MODE"] = "2"; + envVars["MIOPEN_LOG_LEVEL"] = "3"; + + return envVars; + } } diff --git a/StabilityMatrix.Core/Models/Packages/ForgeAmdGpu.cs b/StabilityMatrix.Core/Models/Packages/ForgeAmdGpu.cs index b90bc63aa..b19c5d893 100644 --- a/StabilityMatrix.Core/Models/Packages/ForgeAmdGpu.cs +++ b/StabilityMatrix.Core/Models/Packages/ForgeAmdGpu.cs @@ -57,6 +57,14 @@ IPyInstallationManager pyInstallationManager InitialValue = HardwareHelper.PreferDirectMLOrZluda(), Options = ["--use-zluda"], }, + new LaunchOptionDefinition + { + Name = "Use DirectML", + Description = "Use DirectML for DirectML acceleration on compatible GPUs", + Type = LaunchOptionType.Bool, + InitialValue = false, + Options = ["--use-directml"], + }, ] ) .ToList(); @@ -78,7 +86,7 @@ public override async Task InstallPackage( { if (!PrerequisiteHelper.IsHipSdkInstalled) // for updates { - progress?.Report(new ProgressReport(-1, "Installing HIP SDK 6.2", isIndeterminate: true)); + progress?.Report(new ProgressReport(-1, "Installing HIP SDK 6.4", isIndeterminate: true)); await PrerequisiteHelper .InstallPackageRequirements(this, options.PythonOptions.PythonVersion, progress) .ConfigureAwait(false); @@ -106,7 +114,7 @@ public override async Task RunPackage( { throw new MissingPrerequisiteException( "HIP SDK", - "Your package has not yet been upgraded to use HIP SDK 6.2. To continue, please update this package or select \"Change Version\" from the 3-dots menu to have it upgraded automatically for you" + "Your package has not yet been upgraded to use HIP SDK 6.4. To continue, please update this package or select \"Change Version\" from the 3-dots menu to have it upgraded automatically for you" ); } await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage.PythonVersion)) @@ -116,14 +124,14 @@ await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "AMD", "ROCm", - "6.2" + "6.4" ); var hipBinPath = Path.Combine(hipPath, "bin"); var envVars = new Dictionary { ["ZLUDA_COMGR_LOG_LEVEL"] = "1", ["HIP_PATH"] = hipPath, - ["HIP_PATH_62"] = hipPath, + ["HIP_PATH_64"] = hipPath, ["GIT"] = portableGitBin.JoinFile("git.exe"), }; envVars.Update(settingsManager.Settings.EnvironmentVariables); diff --git a/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs b/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs index abfbe9e9f..e42c9d078 100644 --- a/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs +++ b/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs @@ -223,12 +223,6 @@ IPyInstallationManager pyInstallationManager Options = ["--autolaunch"], }, new() - { - Name = "Force use of Intel OneAPI XPU backend", - Type = LaunchOptionType.Bool, - Options = ["--use-ipex"], - }, - new() { Name = "Use DirectML if no compatible GPU is detected", Type = LaunchOptionType.Bool, @@ -310,15 +304,11 @@ public override async Task InstallPackage( ); } - var requirementsContent = await new FilePath(installLocation, "requirements.txt") - .ReadAllTextAsync(cancellationToken) - .ConfigureAwait(false); - var pipArgs = new PipInstallArgs("--upgrade").WithParsedFromRequirementsTxt(requirementsContent); - if (installedPackage.PipOverrides != null) + if (installedPackage.PipOverrides is { Count: > 0 }) { - pipArgs = pipArgs.WithUserOverrides(installedPackage.PipOverrides); + var pipArgs = new PipInstallArgs().WithUserOverrides(installedPackage.PipOverrides); + await venvRunner.PipInstall(pipArgs, onConsoleOutput).ConfigureAwait(false); } - await venvRunner.PipInstall(pipArgs, onConsoleOutput).ConfigureAwait(false); var torchVersion = options.PythonOptions.TorchIndex ?? GetRecommendedTorchVersion(); switch (torchVersion) diff --git a/StabilityMatrix.Core/Processes/ProcessRunner.cs b/StabilityMatrix.Core/Processes/ProcessRunner.cs index 3c146ff64..ed8f9e48b 100644 --- a/StabilityMatrix.Core/Processes/ProcessRunner.cs +++ b/StabilityMatrix.Core/Processes/ProcessRunner.cs @@ -166,7 +166,7 @@ public static async Task GetProcessOutputAsync( Arguments = arguments, UseShellExecute = false, RedirectStandardOutput = true, - CreateNoWindow = true + CreateNoWindow = true, }; if (environmentVariables != null) @@ -196,7 +196,8 @@ public static async Task GetProcessResultAsync( string fileName, ProcessArgs arguments, string? workingDirectory = null, - IReadOnlyDictionary? environmentVariables = null + IReadOnlyDictionary? environmentVariables = null, + bool useUtf8Encoding = false ) { Logger.Debug($"Starting process '{fileName}' with arguments '{arguments}'"); @@ -208,9 +209,15 @@ public static async Task GetProcessResultAsync( UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, - CreateNoWindow = true + CreateNoWindow = true, }; + if (useUtf8Encoding) + { + info.StandardOutputEncoding = Encoding.UTF8; + info.StandardErrorEncoding = Encoding.UTF8; + } + if (environmentVariables != null) { foreach (var (key, value) in environmentVariables) @@ -255,7 +262,7 @@ public static async Task GetProcessResultAsync( StandardOutput = stdout, StandardError = stderr, ProcessName = processName, - Elapsed = elapsed + Elapsed = elapsed, }; } @@ -410,7 +417,7 @@ public static Process StartProcess( UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, - CreateNoWindow = true + CreateNoWindow = true, }; if (environmentVariables != null) @@ -458,7 +465,7 @@ public static AnsiProcess StartAnsiProcess( UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, - CreateNoWindow = true + CreateNoWindow = true, }; if (environmentVariables != null) @@ -544,7 +551,7 @@ public static async Task RunBashCommand( { ExitCode = process.ExitCode, StandardOutput = stdout.ToString(), - StandardError = stderr.ToString() + StandardError = stderr.ToString(), }; } diff --git a/StabilityMatrix.Core/Python/UvManager.cs b/StabilityMatrix.Core/Python/UvManager.cs index 23ee86bb0..db76a1f0a 100644 --- a/StabilityMatrix.Core/Python/UvManager.cs +++ b/StabilityMatrix.Core/Python/UvManager.cs @@ -1,6 +1,8 @@ +using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; +using System.Text.Unicode; using Injectio.Attributes; using NLog; using StabilityMatrix.Core.Helper; @@ -20,6 +22,7 @@ public partial class UvManager : IUvManager { Converters = { new JsonStringEnumConverter() }, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), }; private string? uvExecutablePath; private DirectoryPath? uvPythonInstallPath; @@ -120,7 +123,7 @@ public async Task> ListAvailablePythonsAsync( var uvDirectory = Path.GetDirectoryName(uvExecutablePath); var result = await ProcessRunner - .GetProcessResultAsync(uvExecutablePath, args, uvDirectory, envVars) + .GetProcessResultAsync(uvExecutablePath, args, uvDirectory, envVars, useUtf8Encoding: true) .ConfigureAwait(false); if (!result.IsSuccessExitCode)