Skip to content

Commit

Permalink
Merge pull request #852 from LykosAI/main
Browse files Browse the repository at this point in the history
v2.11.8
  • Loading branch information
mohnjiles authored Aug 21, 2024
2 parents dcf8a40 + bcbdd54 commit f4e3cbe
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 298 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ 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.11.8
### Added
- Added Flux & AuraFlow types to CivitAI Browser
- Added unet folder links for ComfyUI thanks to jeremydk
- Added CLIP folder links for Forge
### Changed
- Updated Brazilian Portuguese translations thanks to thiagojramos
### Fixed
- Fixed [#840](https://github.com/LykosAI/StabilityMatrix/issues/840) - CivitAI model browser not loading search results
- Fixed SwarmUI settings being overwritten on launch
- Fixed [#832](https://github.com/LykosAI/StabilityMatrix/issues/832) [#847](https://github.com/LykosAI/StabilityMatrix/issues/847) - Forge output folder links pointing to the incorrect folder
- Fixed errors when downloading models with invalid characters in the file name
- Fixed error when installing RuinedFooocus on nvidia GPUs
### Supporters
#### Pioneers
- A big shoutout to our Pioneer-tier patrons: **tankfox**, **tanangular**, **Mr. Unknown**, and **Szir777**! We deeply appreciate your ongoing support!

## v2.11.7
### Changed
- Forge will use the recommended pytorch version 2.3.1 the next time it is updated
Expand Down
12 changes: 6 additions & 6 deletions StabilityMatrix.Avalonia/DesignData/DesignData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ public static void Initialize()
FileMetadata = new CivitFileMetadata
{
Format = CivitModelFormat.SafeTensor,
Fp = CivitModelFpType.fp16,
Size = CivitModelSize.pruned,
Fp = "fp16",
Size = "pruned",
},
TrainedWords = ["aurora", "lightning"]
}
Expand Down Expand Up @@ -634,8 +634,8 @@ public static UpdateSettingsViewModel UpdateSettingsViewModel
Metadata = new CivitFileMetadata
{
Format = CivitModelFormat.SafeTensor,
Fp = CivitModelFpType.fp16,
Size = CivitModelSize.pruned
Fp = "fp16",
Size = "pruned"
}
},
new()
Expand All @@ -645,8 +645,8 @@ public static UpdateSettingsViewModel UpdateSettingsViewModel
Metadata = new CivitFileMetadata
{
Format = CivitModelFormat.SafeTensor,
Fp = CivitModelFpType.fp32,
Size = CivitModelSize.full
Fp = "fp32",
Size = "full"
},
Hashes = new CivitFileHashes { BLAKE3 = "ABCD" }
}
Expand Down
1 change: 1 addition & 0 deletions StabilityMatrix.Avalonia/Services/IModelImportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Task DoImport(
CivitFile? selectedFile = null,
IProgress<ProgressReport>? progress = null,
Func<Task>? onImportComplete = null,
Func<Task>? onImportCanceled = null,
Func<Task>? onImportFailed = null
);
}
101 changes: 15 additions & 86 deletions StabilityMatrix.Avalonia/Services/ModelDownloadLinkHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ public class ModelDownloadLinkHandler(
ICivitApi civitApi,
INotificationService notificationService,
ISettingsManager settingsManager,
IDownloadService downloadService,
ITrackedDownloadService trackedDownloadService
IModelImportService modelImportService
) : IAsyncDisposable, IModelDownloadLinkHandler
{
private IAsyncDisposable? uriHandlerSubscription;
Expand Down Expand Up @@ -127,14 +126,16 @@ private void UriReceivedHandler(Uri receivedUri)
x => x.Type == civitFileType && x.Metadata.Format == civitFormat
);

if (!string.IsNullOrWhiteSpace(fp) && Enum.TryParse<CivitModelFpType>(fp, out var fpType))
if (!string.IsNullOrWhiteSpace(fp))
{
possibleFiles = possibleFiles?.Where(x => x.Metadata.Fp == fpType);
possibleFiles = possibleFiles?.Where(
x => x.Metadata.Fp != null && x.Metadata.Fp.Equals(fp, StringComparison.OrdinalIgnoreCase)
);
}

if (!string.IsNullOrWhiteSpace(size) && Enum.TryParse<CivitModelSize>(size, out var modelSize))
if (!string.IsNullOrWhiteSpace(size))
{
possibleFiles = possibleFiles?.Where(x => x.Metadata.Size == modelSize);
possibleFiles = possibleFiles?.Where(x => x.Metadata.Size != null && x.Metadata.Size == size);
}

possibleFiles = possibleFiles?.ToList();
Expand All @@ -159,93 +160,21 @@ private void UriReceivedHandler(Uri receivedUri)

var rootModelsDirectory = new DirectoryPath(settingsManager.ModelsDirectory);
var downloadDirectory = rootModelsDirectory.JoinDir(
selectedFile.Type == CivitFileType.VAE
selectedFile?.Type == CivitFileType.VAE
? SharedFolderType.VAE.GetStringValue()
: model.Type.ConvertTo<SharedFolderType>().GetStringValue()
);

downloadDirectory.Create();
var downloadPath = downloadDirectory.JoinFile(selectedFile.Name);

// Create tracked download
var download = trackedDownloadService.NewDownload(selectedFile.DownloadUrl, downloadPath);

// Download model info and preview first
var saveCmInfoTask = SaveCmInfo(model, modelVersion, selectedFile, downloadDirectory);
var savePreviewImageTask = SavePreviewImage(modelVersion, downloadPath);

Task.WaitAll([saveCmInfoTask, savePreviewImageTask]);

var cmInfoPath = saveCmInfoTask.Result;
var previewImagePath = savePreviewImageTask.Result;

// Add hash info
download.ExpectedHashSha256 = selectedFile.Hashes.SHA256;

// Add files to cleanup list
download.ExtraCleanupFileNames.Add(cmInfoPath);
if (previewImagePath is not null)
{
download.ExtraCleanupFileNames.Add(previewImagePath);
}

// Add hash context action
download.ContextAction = CivitPostDownloadContextAction.FromCivitFile(selectedFile);

download.Start();
var importTask = modelImportService.DoImport(
model,
downloadDirectory,
selectedVersion: modelVersion,
selectedFile: selectedFile
);
importTask.Wait();

Dispatcher.UIThread.Post(
() => notificationService.Show("Download Started", $"Downloading {selectedFile.Name}")
);
}

private static async Task<FilePath> SaveCmInfo(
CivitModel model,
CivitModelVersion modelVersion,
CivitFile modelFile,
DirectoryPath downloadDirectory
)
{
var modelFileName = Path.GetFileNameWithoutExtension(modelFile.Name);
var modelInfo = new ConnectedModelInfo(model, modelVersion, modelFile, DateTime.UtcNow);

await modelInfo.SaveJsonToDirectory(downloadDirectory, modelFileName);

var jsonName = $"{modelFileName}.cm-info.json";
return downloadDirectory.JoinFile(jsonName);
}

/// <summary>
/// Saves the preview image to the same directory as the model file
/// </summary>
/// <param name="modelVersion"></param>
/// <param name="modelFilePath"></param>
/// <returns>The file path of the saved preview image</returns>
private async Task<FilePath?> SavePreviewImage(CivitModelVersion modelVersion, FilePath modelFilePath)
{
// Skip if model has no images
if (modelVersion.Images == null || modelVersion.Images.Count == 0)
{
return null;
}

var image = modelVersion.Images.FirstOrDefault(x => x.Type == "image");
if (image is null)
return null;

var imageExtension = Path.GetExtension(image.Url).TrimStart('.');
if (imageExtension is "jpg" or "jpeg" or "png")
{
var imageDownloadPath = modelFilePath.Directory!.JoinFile(
$"{modelFilePath.NameWithoutExtension}.preview.{imageExtension}"
);

var imageTask = downloadService.DownloadToFileAsync(image.Url, imageDownloadPath);
await notificationService.TryAsync(imageTask, "Could not download preview image");

return imageDownloadPath;
}

return null;
}
}
7 changes: 6 additions & 1 deletion StabilityMatrix.Avalonia/Services/ModelImportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public async Task DoImport(
CivitFile? selectedFile = null,
IProgress<ProgressReport>? progress = null,
Func<Task>? onImportComplete = null,
Func<Task>? onImportCanceled = null,
Func<Task>? onImportFailed = null
)
{
Expand Down Expand Up @@ -112,6 +113,10 @@ public async Task DoImport(
// Folders might be missing if user didn't install any packages yet
downloadFolder.Create();

// Fix invalid chars in FileName
modelFile.Name = Path.GetInvalidFileNameChars()
.Aggregate(modelFile.Name, (current, c) => current.Replace(c, '_'));

var downloadPath = downloadFolder.JoinFile(modelFile.Name);

// Download model info and preview first
Expand Down Expand Up @@ -145,7 +150,7 @@ public async Task DoImport(
}
else if (e == ProgressState.Cancelled)
{
// todo?
onImportCanceled?.Invoke().SafeFireAndForget();
}
else if (e == ProgressState.Failed)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public partial class CheckpointBrowserCardViewModel : Base.ProgressViewModel
private readonly ServiceManager<ViewModelBase> dialogFactory;
private readonly INotificationService notificationService;
private readonly IModelIndexService modelIndexService;
private readonly IModelImportService modelImportService;

public Action<CheckpointBrowserCardViewModel>? OnDownloadStart { get; set; }

Expand Down Expand Up @@ -82,7 +83,8 @@ public CheckpointBrowserCardViewModel(
ISettingsManager settingsManager,
ServiceManager<ViewModelBase> dialogFactory,
INotificationService notificationService,
IModelIndexService modelIndexService
IModelIndexService modelIndexService,
IModelImportService modelImportService
)
{
this.downloadService = downloadService;
Expand All @@ -91,6 +93,7 @@ IModelIndexService modelIndexService
this.dialogFactory = dialogFactory;
this.notificationService = notificationService;
this.modelIndexService = modelIndexService;
this.modelImportService = modelImportService;

// Update image when nsfw setting changes
settingsManager.RegisterPropertyChangedHandler(
Expand Down Expand Up @@ -263,56 +266,6 @@ private async Task ShowVersionDialog(CivitModel model)
await DoImport(model, downloadPath, selectedVersion, selectedFile);
}

private static async Task<FilePath> SaveCmInfo(
CivitModel model,
CivitModelVersion modelVersion,
CivitFile modelFile,
DirectoryPath downloadDirectory
)
{
var modelFileName = Path.GetFileNameWithoutExtension(modelFile.Name);
var modelInfo = new ConnectedModelInfo(model, modelVersion, modelFile, DateTime.UtcNow);

await modelInfo.SaveJsonToDirectory(downloadDirectory, modelFileName);

var jsonName = $"{modelFileName}.cm-info.json";
return downloadDirectory.JoinFile(jsonName);
}

/// <summary>
/// Saves the preview image to the same directory as the model file
/// </summary>
/// <param name="modelVersion"></param>
/// <param name="modelFilePath"></param>
/// <returns>The file path of the saved preview image</returns>
private async Task<FilePath?> SavePreviewImage(CivitModelVersion modelVersion, FilePath modelFilePath)
{
// Skip if model has no images
if (modelVersion.Images == null || modelVersion.Images.Count == 0)
{
return null;
}

var image = modelVersion.Images.FirstOrDefault(x => x.Type == "image");
if (image is null)
return null;

var imageExtension = Path.GetExtension(image.Url).TrimStart('.');
if (imageExtension is "jpg" or "jpeg" or "png")
{
var imageDownloadPath = modelFilePath.Directory!.JoinFile(
$"{modelFilePath.NameWithoutExtension}.preview.{imageExtension}"
);

var imageTask = downloadService.DownloadToFileAsync(image.Url, imageDownloadPath);
await notificationService.TryAsync(imageTask, "Could not download preview image");

return imageDownloadPath;
}

return null;
}

private async Task DoImport(
CivitModel model,
DirectoryPath downloadFolder,
Expand Down Expand Up @@ -356,69 +309,37 @@ private async Task DoImport(
return;
}

// Folders might be missing if user didn't install any packages yet
downloadFolder.Create();

var downloadPath = downloadFolder.JoinFile(modelFile.Name);

// Download model info and preview first
var cmInfoPath = await SaveCmInfo(model, modelVersion, modelFile, downloadFolder);
var previewImagePath = await SavePreviewImage(modelVersion, downloadPath);

// Create tracked download
var download = trackedDownloadService.NewDownload(modelFile.DownloadUrl, downloadPath);

// Add hash info
download.ExpectedHashSha256 = modelFile.Hashes.SHA256;

// Add files to cleanup list
download.ExtraCleanupFileNames.Add(cmInfoPath);
if (previewImagePath is not null)
{
download.ExtraCleanupFileNames.Add(previewImagePath);
}

// Attach for progress updates
download.ProgressUpdate += (s, e) =>
{
Value = e.Percentage;
if (e.Type == ProgressType.Hashing)
{
Text = $"Validating... {e.Percentage}%";
}
else
{
Text = $"Downloading... {e.Percentage}%";
}
};

download.ProgressStateChanged += (s, e) =>
{
if (e == ProgressState.Success)
await modelImportService.DoImport(
model,
downloadFolder,
modelVersion,
modelFile,
onImportComplete: () =>
{
Text = "Import Complete";

IsIndeterminate = false;
Value = 100;
CheckIfInstalled();
DelayedClearProgress(TimeSpan.FromMilliseconds(800));
}
else if (e == ProgressState.Cancelled)

return Task.CompletedTask;
},
onImportCanceled: () =>
{
Text = "Cancelled";
DelayedClearProgress(TimeSpan.FromMilliseconds(500));
}
else if (e == ProgressState.Failed)

return Task.CompletedTask;
},
onImportFailed: () =>
{
Text = "Download Failed";
DelayedClearProgress(TimeSpan.FromMilliseconds(800));
}
};

// Add hash context action
download.ContextAction = CivitPostDownloadContextAction.FromCivitFile(modelFile);

download.Start();
return Task.CompletedTask;
}
);
}

private void DelayedClearProgress(TimeSpan delay)
Expand Down
Loading

0 comments on commit f4e3cbe

Please sign in to comment.