Skip to content

Commit bd35d4b

Browse files
authored
Merge pull request LykosAI#947 from ionite34/backport/main/pr-946
[dev to main] backport: Fix & redesign checkpoint manager base model filtering (946)
2 parents 2c73d4f + c0f4679 commit bd35d4b

File tree

11 files changed

+315
-196
lines changed

11 files changed

+315
-196
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
77

88
## v2.13.1
9+
### Changed
10+
- Redesigned the Checkpoint Manager Filter flyout to include more options and improve the layout
911
### Fixed
1012
- Fixed [#1078](https://github.com/LykosAI/StabilityMatrix/issues/1078) - "Call from invalid thread" error after one-click install finishes
13+
- Fixed [#1080](https://github.com/LykosAI/StabilityMatrix/issues/1080) - Some models not displayed in Checkpoint Manager
1114
- Fixed Inference image selector card buttons taking up the whole height of the card
1215

1316
## v2.13.0
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Text.Json.Nodes;
2+
using Injectio.Attributes;
3+
using Microsoft.Extensions.Logging;
4+
using StabilityMatrix.Core.Api;
5+
using StabilityMatrix.Core.Database;
6+
using StabilityMatrix.Core.Models.Api;
7+
using StabilityMatrix.Core.Models.Database;
8+
9+
namespace StabilityMatrix.Avalonia.Services;
10+
11+
[RegisterSingleton<ICivitBaseModelTypeService, CivitBaseModelTypeService>]
12+
public class CivitBaseModelTypeService(
13+
ILogger<CivitBaseModelTypeService> logger,
14+
ICivitApi civitApi,
15+
ILiteDbContext dbContext
16+
) : ICivitBaseModelTypeService
17+
{
18+
private const string CacheId = "BaseModelTypes";
19+
private static readonly TimeSpan CacheExpiration = TimeSpan.FromHours(24);
20+
21+
/// <summary>
22+
/// Gets the list of base model types, using cache if available and not expired
23+
/// </summary>
24+
public async Task<List<string>> GetBaseModelTypes(bool forceRefresh = false, bool includeAllOption = true)
25+
{
26+
List<string> civitBaseModels = [];
27+
28+
if (!forceRefresh)
29+
{
30+
var cached = await dbContext.GetCivitBaseModelTypeCacheEntry(CacheId);
31+
if (cached != null && DateTimeOffset.UtcNow.Subtract(cached.CreatedAt) < CacheExpiration)
32+
{
33+
civitBaseModels = cached.ModelTypes;
34+
}
35+
}
36+
37+
try
38+
{
39+
if (civitBaseModels.Count <= 0)
40+
{
41+
var baseModelsResponse = await civitApi.GetBaseModelList();
42+
var jsonContent = await baseModelsResponse.Content.ReadAsStringAsync();
43+
var baseModels = JsonNode.Parse(jsonContent);
44+
45+
var jArray =
46+
baseModels?["error"]?["issues"]?[0]?["unionErrors"]?[0]?["issues"]?[0]?["options"]
47+
as JsonArray;
48+
49+
civitBaseModels = jArray?.GetValues<string>().ToList() ?? [];
50+
51+
// Cache the results
52+
var cacheEntry = new CivitBaseModelTypeCacheEntry
53+
{
54+
Id = CacheId,
55+
ModelTypes = civitBaseModels,
56+
CreatedAt = DateTimeOffset.UtcNow
57+
};
58+
59+
await dbContext.UpsertCivitBaseModelTypeCacheEntry(cacheEntry);
60+
}
61+
62+
if (includeAllOption)
63+
{
64+
civitBaseModels.Insert(0, CivitBaseModelType.All.ToString());
65+
}
66+
67+
// Filter and sort results
68+
var filteredResults = civitBaseModels
69+
.Where(s => !s.Equals("odor", StringComparison.OrdinalIgnoreCase))
70+
.OrderBy(s => s)
71+
.ToList();
72+
73+
return filteredResults;
74+
}
75+
catch (Exception e)
76+
{
77+
logger.LogError(e, "Failed to get base model list");
78+
79+
// Return cached results if available, even if expired
80+
var expiredCache = await dbContext.GetCivitBaseModelTypeCacheEntry(CacheId);
81+
return expiredCache?.ModelTypes ?? [];
82+
}
83+
}
84+
85+
/// <summary>
86+
/// Clears the cached base model types
87+
/// </summary>
88+
public void ClearCache()
89+
{
90+
dbContext.CivitBaseModelTypeCache.DeleteAllAsync();
91+
}
92+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace StabilityMatrix.Avalonia.Services;
2+
3+
public interface ICivitBaseModelTypeService
4+
{
5+
Task<List<string>> GetBaseModelTypes(bool forceRefresh = false, bool includeAllOption = true);
6+
void ClearCache();
7+
}

StabilityMatrix.Avalonia/ViewModels/Base/PageViewModelBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace StabilityMatrix.Avalonia.ViewModels.Base;
55
/// <summary>
66
/// An abstract class for enabling page navigation.
77
/// </summary>
8-
public abstract class PageViewModelBase : ViewModelBase
8+
public abstract class PageViewModelBase : DisposableViewModelBase
99
{
1010
/// <summary>
1111
/// Gets if the user can navigate to the next page
@@ -16,7 +16,7 @@ public abstract class PageViewModelBase : ViewModelBase
1616
/// Gets if the user can navigate to the previous page
1717
/// </summary>
1818
public virtual bool CanNavigatePrevious { get; protected set; }
19-
19+
2020
public abstract string Title { get; }
2121
public abstract IconSource IconSource { get; }
2222
}

StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public sealed partial class CivitAiBrowserViewModel : TabViewModelBase, IInfinit
4545
private readonly ISettingsManager settingsManager;
4646
private readonly ILiteDbContext liteDbContext;
4747
private readonly INotificationService notificationService;
48+
private readonly ICivitBaseModelTypeService baseModelTypeService;
4849
private bool dontSearch = false;
4950

5051
private readonly SourceCache<OrderedValue<CivitModel>, int> modelCache = new(static ov => ov.Value.Id);
@@ -126,13 +127,15 @@ public CivitAiBrowserViewModel(
126127
ISettingsManager settingsManager,
127128
ServiceManager<ViewModelBase> dialogFactory,
128129
ILiteDbContext liteDbContext,
129-
INotificationService notificationService
130+
INotificationService notificationService,
131+
ICivitBaseModelTypeService baseModelTypeService
130132
)
131133
{
132134
this.civitApi = civitApi;
133135
this.settingsManager = settingsManager;
134136
this.liteDbContext = liteDbContext;
135137
this.notificationService = notificationService;
138+
this.baseModelTypeService = baseModelTypeService;
136139

137140
EventManager.Instance.NavigateAndFindCivitModelRequested += OnNavigateAndFindCivitModelRequested;
138141

@@ -727,31 +730,7 @@ private void UpdateResultsText()
727730
[Localizable(false)]
728731
private async Task<List<string>> GetBaseModelList()
729732
{
730-
try
731-
{
732-
var baseModelsResponse = await civitApi.GetBaseModelList();
733-
var jsonContent = await baseModelsResponse.Content.ReadAsStringAsync();
734-
var baseModels = JsonNode.Parse(jsonContent);
735-
736-
var jArray =
737-
baseModels?["error"]?["issues"]?[0]?["unionErrors"]?[0]?["issues"]?[0]?["options"]
738-
as JsonArray;
739-
var civitBaseModels = jArray?.GetValues<string>().ToList() ?? [];
740-
741-
civitBaseModels.Insert(0, CivitBaseModelType.All.ToString());
742-
743-
var filteredResults = civitBaseModels
744-
.Where(s => s.Equals("odor", StringComparison.OrdinalIgnoreCase) == false)
745-
.OrderBy(s => s)
746-
.ToList();
747-
748-
return filteredResults;
749-
}
750-
catch (Exception e)
751-
{
752-
Logger.Error(e, "Failed to get base model list");
753-
return [];
754-
}
733+
return await baseModelTypeService.GetBaseModelTypes();
755734
}
756735

757736
public override string Header => Resources.Label_CivitAi;

0 commit comments

Comments
 (0)