Browse Source

Fixed python packages crash & show parent folder name for ipadapter/controlnets that have same name

also added sdxl turbo & svd
pull/365/head
JT 11 months ago
parent
commit
2475241492
  1. 9
      CHANGELOG.md
  2. 20
      StabilityMatrix.Avalonia/Assets/hf-packages.json
  3. 38
      StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
  4. 16
      StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/HuggingFacePageViewModel.cs
  5. 19
      StabilityMatrix.Avalonia/ViewModels/Inference/Modules/ControlNetModule.cs
  6. 21
      StabilityMatrix.Avalonia/ViewModels/Inference/SelectImageCardViewModel.cs
  7. 72
      StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
  8. 29
      StabilityMatrix.Core/Models/HybridModelFile.cs
  9. 1
      StabilityMatrix.Core/Python/PipPackageInfo.cs

9
CHANGELOG.md

@ -5,6 +5,15 @@ 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.7.6
### Added
- Added SDXL Turbo and Stable Video Diffusion to the Hugging Face tab
### Changed
- ControlNet model selector will now show the parent directory of a model when relevant
### Fixed
- Fixed Python Packages dialog crash
- Fixed Base Model downloads from the Hugging Face tab downloading to the wrong folder
## v2.7.5
### Fixed
- Fixed Python Packages manager crash when pip list returns warnings in json

20
StabilityMatrix.Avalonia/Assets/hf-packages.json

@ -38,6 +38,26 @@
"LicenseType": "Open RAIL++",
"LicensePath": "LICENSE.md"
},
{
"ModelCategory": "BaseModel",
"ModelName": "SDXL Turbo",
"RepositoryPath": "stabilityai/sdxl-turbo",
"Files": [
"sd_xl_turbo_1.0_fp16.safetensors"
],
"LicenseType": "SAI-NC-Community",
"LicensePath": "LICENSE.TXT"
},
{
"ModelCategory": "BaseModel",
"ModelName": "Stable Video Diffusion",
"RepositoryPath": "stabilityai/stable-video-diffusion-img2vid",
"Files": [
"svd.safetensors"
],
"LicenseType": "Stable-Video-Diffusion-NC-Community",
"LicensePath": "LICENSE"
},
{
"ModelCategory": "ControlNet",
"ModelName": "Canny",

38
StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj

@ -23,29 +23,29 @@
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" />
<PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/>
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.5" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0" />
<PackageReference Include="Avalonia" Version="11.0.5" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.5" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.5" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.2" />
<PackageReference Include="Avalonia" Version="11.0.6" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.6" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.6" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.6" />
<PackageReference Include="Avalonia.HtmlRenderer" Version="11.0.0" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.5" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.6" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.0.5" />
<PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.0.5.1" />
<PackageReference Include="bodong.PropertyModels" Version="11.0.5.1" />
<PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.0.6.1" />
<PackageReference Include="bodong.PropertyModels" Version="11.0.6.1" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Dock.Avalonia" Version="11.0.0.3" />
<PackageReference Include="Dock.Model.Avalonia" Version="11.0.0.3" />
<PackageReference Include="Dock.Serializer" Version="11.0.0.3" />
<PackageReference Include="DynamicData" Version="8.1.1" />
<PackageReference Include="Dock.Avalonia" Version="11.0.0.5" />
<PackageReference Include="Dock.Model.Avalonia" Version="11.0.0.5" />
<PackageReference Include="Dock.Serializer" Version="11.0.0.5" />
<PackageReference Include="DynamicData" Version="8.3.27" />
<PackageReference Include="Exceptionless.DateTimeExtensions" Version="3.4.3" />
<PackageReference Include="FluentAvalonia.BreadcrumbBar" Version="2.0.2" />
<PackageReference Include="FluentAvaloniaUI" Version="2.0.4" />
<PackageReference Include="FluentIcons.Avalonia" Version="1.1.222" />
<PackageReference Include="FluentIcons.FluentAvalonia" Version="1.1.222" />
<PackageReference Include="FluentIcons.Avalonia" Version="1.1.224" />
<PackageReference Include="FluentIcons.FluentAvalonia" Version="1.1.224" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Markdown.Avalonia" Version="11.0.2" />
@ -59,16 +59,16 @@
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="NLog" Version="5.2.5" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.5" />
<PackageReference Include="NLog" Version="5.2.7" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.7" />
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="Polly" Version="8.2.0" />
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="8.3.0" />
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.0.1" />
<PackageReference Include="RockLib.Reflection.Optimized" Version="2.0.0" />
<PackageReference Include="Sentry" Version="3.41.0" />
<PackageReference Include="Sentry.NLog" Version="3.41.0" />
<PackageReference Include="Sentry" Version="3.41.3" />
<PackageReference Include="Sentry.NLog" Version="3.41.3" />
<PackageReference Include="SpacedGrid-Avalonia" Version="11.0.0" />
<PackageReference Include="Sylvan.Common" Version="0.4.3" />
<PackageReference Include="Sylvan.Data" Version="0.2.12" />

16
StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/HuggingFacePageViewModel.cs

@ -41,7 +41,8 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
private readonly ISettingsManager settingsManager;
private readonly INotificationService notificationService;
public SourceCache<HuggingfaceItem, string> ItemsCache { get; } = new(i => i.RepositoryPath + i.ModelName);
public SourceCache<HuggingfaceItem, string> ItemsCache { get; } =
new(i => i.RepositoryPath + i.ModelName);
public IObservableCollection<CategoryViewModel> Categories { get; set; } =
new ObservableCollectionExtended<CategoryViewModel>();
@ -76,7 +77,13 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
.Connect()
.DeferUntilLoaded()
.Group(i => i.ModelCategory)
.Transform(g => new CategoryViewModel(g.Cache.Items) { Title = g.Key.GetDescription() ?? g.Key.ToString() })
.Transform(
g =>
new CategoryViewModel(g.Cache.Items)
{
Title = g.Key.GetDescription() ?? g.Key.ToString()
}
)
.SortBy(vm => vm.Title)
.Bind(Categories)
.WhenAnyPropertyChanged()
@ -137,12 +144,13 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
{
foreach (var file in viewModel.Item.Files)
{
var url = $"https://huggingface.co/{viewModel.Item.RepositoryPath}/resolve/main/{file}?download=true";
var url =
$"https://huggingface.co/{viewModel.Item.RepositoryPath}/resolve/main/{file}?download=true";
var sharedFolderType = viewModel.Item.ModelCategory.ConvertTo<SharedFolderType>();
var downloadPath = new FilePath(
Path.Combine(
settingsManager.ModelsDirectory,
sharedFolderType.GetDescription() ?? sharedFolderType.ToString(),
sharedFolderType.ToString(),
viewModel.Item.Subfolder ?? string.Empty,
file
)

19
StabilityMatrix.Avalonia/ViewModels/Inference/Modules/ControlNetModule.cs

@ -42,9 +42,8 @@ public class ControlNetModule : ModuleBase
{
Name = e.Nodes.GetUniqueName("ControlNet_LoadImage"),
Image =
card.SelectImageCardViewModel.ImageSource?.GetHashGuidFileNameCached(
"Inference"
) ?? throw new ValidationException("No ImageSource")
card.SelectImageCardViewModel.ImageSource?.GetHashGuidFileNameCached("Inference")
?? throw new ValidationException("No ImageSource")
}
);
@ -53,8 +52,7 @@ public class ControlNetModule : ModuleBase
{
Name = e.Nodes.GetUniqueName("ControlNetLoader"),
ControlNetName =
card.SelectedModel?.FileName
?? throw new ValidationException("No SelectedModel"),
card.SelectedModel?.RelativePath ?? throw new ValidationException("No SelectedModel"),
}
);
@ -64,10 +62,8 @@ public class ControlNetModule : ModuleBase
Name = e.Nodes.GetUniqueName("ControlNetApply"),
Image = imageLoad.Output1,
ControlNet = controlNetLoader.Output,
Positive =
e.Temp.Conditioning?.Positive ?? throw new ArgumentException("No Conditioning"),
Negative =
e.Temp.Conditioning?.Negative ?? throw new ArgumentException("No Conditioning"),
Positive = e.Temp.Conditioning?.Positive ?? throw new ArgumentException("No Conditioning"),
Negative = e.Temp.Conditioning?.Negative ?? throw new ArgumentException("No Conditioning"),
Strength = card.Strength,
StartPercent = card.StartPercent,
EndPercent = card.EndPercent,
@ -93,10 +89,7 @@ public class ControlNetModule : ModuleBase
}
);
e.Temp.RefinerConditioning = (
controlNetRefinerApply.Output1,
controlNetRefinerApply.Output2
);
e.Temp.RefinerConditioning = (controlNetRefinerApply.Output1, controlNetRefinerApply.Output2);
}
}
}

21
StabilityMatrix.Avalonia/ViewModels/Inference/SelectImageCardViewModel.cs

@ -71,7 +71,9 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
{
e.Builder.SetupImagePrimarySource(
ImageSource ?? throw new ValidationException("Input Image is required"),
!CurrentBitmapSize.IsEmpty ? CurrentBitmapSize : throw new ValidationException("CurrentBitmapSize is null"),
!CurrentBitmapSize.IsEmpty
? CurrentBitmapSize
: throw new ValidationException("CurrentBitmapSize is null"),
e.Builder.Connections.BatchIndex
);
}
@ -98,7 +100,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
private async Task SelectImageFromFilePickerAsync()
{
var files = await App.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions { FileTypeFilter = [FilePickerFileTypes.ImagePng, FilePickerFileTypes.ImageJpg] }
new FilePickerOpenOptions
{
FileTypeFilter = [FilePickerFileTypes.ImagePng, FilePickerFileTypes.ImageJpg]
}
);
if (files.FirstOrDefault()?.TryGetLocalPath() is { } path)
@ -112,7 +117,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
/// </summary>
public void DragOver(object? sender, DragEventArgs e)
{
if (e.Data.GetDataFormats().Contains(DataFormats.Files) || e.Data.GetContext<LocalImageFile>() is not null)
if (
e.Data.GetDataFormats().Contains(DataFormats.Files)
|| e.Data.GetContext<LocalImageFile>() is not null
)
{
e.Handled = true;
return;
@ -134,7 +142,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
return;
}
// 2. OS Files
if (e.Data.GetFiles() is { } files && files.Select(f => f.TryGetLocalPath()).FirstOrDefault() is { } path)
if (
e.Data.GetFiles() is { } files
&& files.Select(f => f.TryGetLocalPath()).FirstOrDefault() is { } path
)
{
e.Handled = true;
@ -154,7 +165,7 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
catch (Exception e)
{
Logger.Warn(e, "Error loading image");
notificationService.ShowPersistent("Error loading image", e.Message);
notificationService.Show("Error loading image", e.Message);
}
}

72
StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs

@ -132,15 +132,16 @@ public partial class MainWindow : AppWindowBase
return;
// Navigate to first page
Dispatcher
.UIThread
.Post(
() =>
navigationService.NavigateTo(
vm.Pages[0],
new BetterSlideNavigationTransition { Effect = SlideNavigationTransitionEffect.FromBottom }
)
);
Dispatcher.UIThread.Post(
() =>
navigationService.NavigateTo(
vm.Pages[0],
new BetterSlideNavigationTransition
{
Effect = SlideNavigationTransitionEffect.FromBottom
}
)
);
// Check show update teaching tip
if (vm.UpdateViewModel.IsUpdateAvailable)
@ -165,27 +166,24 @@ public partial class MainWindow : AppWindowBase
var mainViewModel = (MainWindowViewModel)DataContext!;
mainViewModel.SelectedCategory = mainViewModel
.Pages
.Concat(mainViewModel.FooterPages)
.Pages.Concat(mainViewModel.FooterPages)
.FirstOrDefault(x => x.GetType() == e.ViewModelType);
}
private void OnUpdateAvailable(object? sender, UpdateInfo? updateInfo)
{
Dispatcher
.UIThread
.Post(() =>
Dispatcher.UIThread.Post(() =>
{
if (DataContext is MainWindowViewModel vm && vm.ShouldShowUpdateAvailableTeachingTip(updateInfo))
{
if (DataContext is MainWindowViewModel vm && vm.ShouldShowUpdateAvailableTeachingTip(updateInfo))
{
var target = this.FindControl<NavigationViewItem>("FooterUpdateItem")!;
var tip = this.FindControl<TeachingTip>("UpdateAvailableTeachingTip")!;
var target = this.FindControl<NavigationViewItem>("FooterUpdateItem")!;
var tip = this.FindControl<TeachingTip>("UpdateAvailableTeachingTip")!;
tip.Target = target;
tip.Subtitle = $"{Compat.AppVersion.ToDisplayString()} -> {updateInfo.Version}";
tip.IsOpen = true;
}
});
tip.Target = target;
tip.Subtitle = $"{Compat.AppVersion.ToDisplayString()} -> {updateInfo.Version}";
tip.IsOpen = true;
}
});
}
public void SetDefaultFonts()
@ -282,18 +280,16 @@ public partial class MainWindow : AppWindowBase
private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e)
{
Dispatcher
.UIThread
.Post(() =>
{
var fileName = Path.GetFileName(e.Url);
var displayName = string.IsNullOrEmpty(fileName) ? e.Url : fileName;
notificationService.ShowPersistent(
"Failed to load image",
$"Could not load '{displayName}'\n({e.Exception.Message})",
NotificationType.Warning
);
});
Dispatcher.UIThread.Post(() =>
{
var fileName = Path.GetFileName(e.Url);
var displayName = string.IsNullOrEmpty(fileName) ? e.Url : fileName;
notificationService.Show(
"Failed to load image",
$"Could not load '{displayName}'\n({e.Exception.Message})",
NotificationType.Warning
);
});
}
private void TryEnableMicaEffect()
@ -319,7 +315,11 @@ public partial class MainWindow : AppWindowBase
else if (ActualThemeVariant == ThemeVariant.Light)
{
// Similar effect here
var color = this.TryFindResource("SolidBackgroundFillColorBase", ThemeVariant.Light, out var value)
var color = this.TryFindResource(
"SolidBackgroundFillColorBase",
ThemeVariant.Light,
out var value
)
? (Color2)(Color)value!
: new Color2(243, 243, 243);

29
StabilityMatrix.Core/Models/HybridModelFile.cs

@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using StabilityMatrix.Core.Models.Database;
using StabilityMatrix.Core.Models.FileInterfaces;
namespace StabilityMatrix.Core.Models;
@ -67,7 +68,27 @@ public record HybridModelFile
return "Default";
}
return Path.GetFileNameWithoutExtension(RelativePath);
var fileName = Path.GetFileNameWithoutExtension(RelativePath);
if (
!fileName.Equals("diffusion_pytorch_model", StringComparison.OrdinalIgnoreCase)
&& !fileName.Equals("ip_adapter", StringComparison.OrdinalIgnoreCase)
)
{
return Path.GetFileNameWithoutExtension(RelativePath);
}
// show a friendlier name when models have the same name like ip_adapter or diffusion_pytorch_model
var directoryName = Path.GetDirectoryName(RelativePath);
if (directoryName is null)
return Path.GetFileNameWithoutExtension(RelativePath);
var lastIndex = directoryName.LastIndexOf(Path.DirectorySeparatorChar);
if (lastIndex < 0)
return $"{fileName} ({directoryName})";
var parentDirectoryName = directoryName.Substring(lastIndex + 1);
return $"{fileName} ({parentDirectoryName})";
}
}
@ -83,11 +104,7 @@ public record HybridModelFile
public static HybridModelFile FromDownloadable(RemoteResource resource)
{
return new HybridModelFile
{
DownloadableResource = resource,
Type = HybridModelType.Downloadable
};
return new HybridModelFile { DownloadableResource = resource, Type = HybridModelType.Downloadable };
}
public string GetId()

1
StabilityMatrix.Core/Python/PipPackageInfo.cs

@ -10,4 +10,5 @@ public readonly record struct PipPackageInfo(
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)]
[JsonSerializable(typeof(PipPackageInfo))]
[JsonSerializable(typeof(List<PipPackageInfo>))]
internal partial class PipPackageInfoSerializerContext : JsonSerializerContext;

Loading…
Cancel
Save