Browse Source

Merge pull request #365 from ionite34/trigger-words

Added the download & display of trigger words for models
pull/324/head
JT 1 year ago committed by GitHub
parent
commit
8e450345e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      CHANGELOG.md
  2. 3
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  3. 18
      StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
  4. 6
      StabilityMatrix.Avalonia/Languages/Resources.resx
  5. 16
      StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs
  6. 10
      StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml
  7. 262
      StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
  8. 33
      StabilityMatrix.Core/Models/ConnectedModelInfo.cs

20
CHANGELOG.md

@ -5,6 +5,21 @@ 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.0-dev.3
### Added
#### Model Browser
- Right clicking anywhere on the model card will open the same menu as the three-dots button
- New model downloads will save trigger words in metadata, if available
#### Checkpoints Page
- Added "Copy Trigger Words" option to the three-dots menu on the Checkpoints page (when data is available)
- Added trigger words on checkpoint card and tooltip
### Changed
#### Model Browser
- Improved number formatting with K/M suffixes for download and favorite counts
- Animated zoom effect on hovering over model images
#### Checkpoints Page
- Rearranged top row layout to use CommandBar
## v2.7.0-dev.2
### Added
#### General
@ -38,11 +53,6 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2
## v2.6.3
### Fixed
- Fixed InvalidOperationException during prerequisite installs on certain platforms where process name and duration reporting are not supported
## v2.7.0-dev.3
## Changed
#### Model Browser
- Improved number formatting with K/M suffixes for download and favorite counts
- Animated zoom effect on hovering over model images
## v2.6.2
### Changed

3
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -206,7 +206,8 @@ public static class DesignData
Format = CivitModelFormat.SafeTensor,
Fp = CivitModelFpType.fp16,
Size = CivitModelSize.pruned,
}
},
TrainedWords = ["aurora", "lightning"]
}
},
new()

18
StabilityMatrix.Avalonia/Languages/Resources.Designer.cs generated

@ -167,6 +167,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Copy Trigger Words.
/// </summary>
public static string Action_CopyTriggerWords {
get {
return ResourceManager.GetString("Action_CopyTriggerWords", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Delete.
/// </summary>
@ -1796,6 +1805,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Trigger words:.
/// </summary>
public static string Label_TriggerWords {
get {
return ResourceManager.GetString("Label_TriggerWords", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An unexpected error occurred.
/// </summary>

6
StabilityMatrix.Avalonia/Languages/Resources.resx

@ -804,4 +804,10 @@
<data name="TextTemplate_LastChecked" xml:space="preserve">
<value>Last checked: {0}</value>
</data>
<data name="Action_CopyTriggerWords" xml:space="preserve">
<value>Copy Trigger Words</value>
</data>
<data name="Label_TriggerWords" xml:space="preserve">
<value>Trigger words:</value>
</data>
</root>

16
StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs

@ -60,6 +60,9 @@ public partial class CheckpointFile : ViewModelBase
public string FileName => Path.GetFileName(FilePath);
public bool CanShowTriggerWords =>
ConnectedModel != null && !string.IsNullOrWhiteSpace(ConnectedModel.TrainedWordsString);
public ObservableCollection<string> Badges { get; set; } = new();
public static readonly string[] SupportedCheckpointExtensions =
@ -215,6 +218,19 @@ public partial class CheckpointFile : ViewModelBase
ProcessRunner.OpenUrl($"https://civitai.com/models/{ConnectedModel.ModelId}");
}
[RelayCommand]
private Task CopyTriggerWords()
{
if (ConnectedModel == null)
return Task.CompletedTask;
var words = ConnectedModel.TrainedWordsString;
if (string.IsNullOrWhiteSpace(words))
return Task.CompletedTask;
return App.Clipboard.SetTextAsync(words);
}
/// <summary>
/// Indexes directory and yields all checkpoint files.
/// First we match all files with supported extensions.

10
StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml

@ -78,6 +78,16 @@
Margin="8"
ClipToBounds="True"
CornerRadius="8">
<Border.ContextFlyout>
<MenuFlyout>
<MenuItem Header="{x:Static lang:Resources.Action_OpenOnCivitAi}"
Command="{Binding OpenModelCommand}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Open" />
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</Border.ContextFlyout>
<Button
Name="ModelCard"
Classes="transparent-full"

262
StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml

@ -1,20 +1,21 @@
<controls:UserControlBase xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:checkpointManager="clr-namespace:StabilityMatrix.Avalonia.ViewModels.CheckpointManager"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static mocks:DesignData.CheckpointsPageViewModel}"
x:CompileBindings="True"
x:DataType="vm:CheckpointsPageViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="StabilityMatrix.Avalonia.Views.CheckpointsPage">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:checkpointManager="clr-namespace:StabilityMatrix.Avalonia.ViewModels.CheckpointManager"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
xmlns:avalonia="https://github.com/projektanker/icons.avalonia"
d:DataContext="{x:Static mocks:DesignData.CheckpointsPageViewModel}"
x:CompileBindings="True"
x:DataType="vm:CheckpointsPageViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="650"
x:Class="StabilityMatrix.Avalonia.Views.CheckpointsPage">
<controls:UserControlBase.Resources>
<!--Direction="0"
ShadowDepth="0"-->
@ -23,7 +24,7 @@
Color="#FF000000"
Opacity="0.2"
x:Key="TextDropShadowEffect" />
<!-- Template for a single badge -->
<DataTemplate DataType="{x:Type system:String}" x:Key="BadgeTemplate">
<controls:Card
@ -40,7 +41,7 @@
VerticalAlignment="Center" />
</controls:Card>
</DataTemplate>
<!-- Checkpoint File Card -->
<DataTemplate DataType="{x:Type checkpointManager:CheckpointFile}" x:Key="CheckpointFileDataTemplate">
<Border
@ -50,28 +51,33 @@
Margin="4">
<Interaction.Behaviors>
<BehaviorCollection>
<ContextDragBehavior HorizontalDragThreshold="6" VerticalDragThreshold="6"/>
<ContextDragBehavior HorizontalDragThreshold="6" VerticalDragThreshold="6" />
</BehaviorCollection>
</Interaction.Behaviors>
<controls:Card MaxWidth="330" Width="330"
CornerRadius="12">
<!-- Right click menu for a checkpoint file -->
<controls:Card.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem Command="{Binding RenameCommand}"
<ui:MenuFlyoutItem Command="{Binding RenameCommand}"
Text="{x:Static lang:Resources.Action_Rename}" IconSource="Rename" />
<ui:MenuFlyoutItem Command="{Binding DeleteCommand}"
<ui:MenuFlyoutItem Command="{Binding DeleteCommand}"
Text="{x:Static lang:Resources.Action_Delete}" IconSource="Delete" />
<ui:MenuFlyoutItem Command="{Binding OpenOnCivitAiCommand}"
<ui:MenuFlyoutItem Command="{Binding OpenOnCivitAiCommand}"
Text="{x:Static lang:Resources.Action_OpenOnCivitAi}" IconSource="Link"
IsVisible="{Binding IsConnectedModel}"/>
IsVisible="{Binding IsConnectedModel}" />
<ui:MenuFlyoutItem Command="{Binding CopyTriggerWordsCommand}"
IsVisible="{Binding CanShowTriggerWords}"
Text="{x:Static lang:Resources.Action_CopyTriggerWords}"
IconSource="Copy" />
</ui:FAMenuFlyout>
</controls:Card.ContextFlyout>
<Grid>
<!-- Main contents, hidden when IsLoading is true -->
<StackPanel MinHeight="70">
<Grid ColumnDefinitions="*, Auto" RowDefinitions="Auto,*,Auto" IsVisible="{Binding !IsLoading}">
<Grid ColumnDefinitions="*, Auto" RowDefinitions="Auto,*,Auto,Auto"
IsVisible="{Binding !IsLoading}">
<StackPanel
Grid.ColumnSpan="2"
HorizontalAlignment="Left"
@ -106,6 +112,17 @@
Source="{Binding PreviewImagePath}"
Stretch="Uniform"
IsVisible="{Binding IsConnectedModel}" />
<TextBlock
FontSize="13"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
HorizontalAlignment="Left"
Margin="0,0,0,4"
TextWrapping="WrapWithOverflow"
IsVisible="{Binding CanShowTriggerWords}">
<Run Text="{x:Static lang:Resources.Label_TriggerWords}" />
<Run
Text="{Binding ConnectedModel.TrainedWordsString, FallbackValue=''}" />
</TextBlock>
</StackPanel>
</ToolTip.Tip>
<TextBlock
@ -136,7 +153,7 @@
Height="300"
Width="300"
IsVisible="{Binding $parent[ItemsControl].((vm:CheckpointsPageViewModel)DataContext).ShowConnectedModelImages}" />
<Grid Grid.Column="1" Grid.Row="0">
<Button
Background="Transparent"
@ -179,7 +196,7 @@
Grid.Column="0"
Grid.Row="2"
IsEnabled="True"
Margin="4,4"
Margin="0,4"
Text="{Binding FileName}"
TextTrimming="CharacterEllipsis"
ToolTip.Tip="{Binding FileName}"
@ -191,14 +208,28 @@
ItemTemplate="{StaticResource BadgeTemplate}"
ItemsSource="{Binding Badges}"
VerticalAlignment="Bottom">
<ItemsRepeater.Layout>
<UniformGridLayout />
</ItemsRepeater.Layout>
<ItemsRepeater.Layout>
<UniformGridLayout />
</ItemsRepeater.Layout>
</ItemsRepeater>
<TextBlock Grid.Row="3" Grid.Column="0"
Grid.ColumnSpan="2"
FontSize="11"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Margin="0,4,0,0"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
ToolTip.Tip="{Binding ConnectedModel.TrainedWordsString, FallbackValue=''}"
IsVisible="{Binding CanShowTriggerWords}">
<Run Text="{x:Static lang:Resources.Label_TriggerWords}" />
<Run Text="{Binding ConnectedModel.TrainedWordsString, FallbackValue=''}" />
</TextBlock>
</Grid>
</StackPanel>
<!-- Progress ring -->
<controls:ProgressRing
Grid.Row="0"
@ -216,7 +247,7 @@
</controls:Card>
</Border>
</DataTemplate>
<!-- Checkpoint Folder Expander -->
<DataTemplate DataType="{x:Type checkpointManager:CheckpointFolder}" x:Key="CheckpointFolderGridDataTemplate">
<Expander
@ -226,51 +257,52 @@
Margin="4"
Padding="8,8,8,8"
IsVisible="{Binding IsCategoryEnabled, FallbackValue=True}">
<!-- Right click menu for a checkpoint folder -->
<Expander.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Action_ShowInExplorer}" IconSource="Open"
Command="{Binding ShowInExplorerCommand}"
CommandParameter="{Binding DirectoryPath}"/>
CommandParameter="{Binding DirectoryPath}" />
<!-- Only allow deletion of non-root folders (Parent is not null) -->
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Action_Delete}" IconSource="Delete"
IsEnabled="{Binding ParentFolder, Converter={x:Static ObjectConverters.IsNotNull}}"
IsVisible="{Binding ParentFolder, Converter={x:Static ObjectConverters.IsNotNull}}"
Command="{Binding DeleteCommand}"/>
<ui:MenuFlyoutSeparator/>
Command="{Binding DeleteCommand}" />
<ui:MenuFlyoutSeparator />
<ui:MenuFlyoutSubItem Text="{x:Static lang:Resources.Action_New}" IconSource="Add">
<ui:MenuFlyoutSubItem.Items>
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Label_Folder}" IconSource="OpenFolder"
Command="{Binding CreateSubFolderCommand}"/>
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Label_Folder}"
IconSource="OpenFolder"
Command="{Binding CreateSubFolderCommand}" />
</ui:MenuFlyoutSubItem.Items>
</ui:MenuFlyoutSubItem>
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Label_FindConnectedMetadata}"
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Label_FindConnectedMetadata}"
IconSource="Find"
Command="{Binding FindConnectedMetadata}"/>
Command="{Binding FindConnectedMetadata}" />
</ui:FAMenuFlyout>
</Expander.ContextFlyout>
<!-- Editable header -->
<Expander.Header>
<Grid>
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Title}" VerticalAlignment="Center" />
</Grid>
</Expander.Header>
<Grid RowDefinitions="Auto, Auto">
<!-- Subfolders -->
<ItemsRepeater Grid.Row="0"
HorizontalAlignment="Stretch"
ItemTemplate="{DynamicResource CheckpointFolderGridDataTemplate}"
ItemsSource="{Binding SubFolders, Mode=OneWay}"
Margin="8,0,8,8" >
HorizontalAlignment="Stretch"
ItemTemplate="{DynamicResource CheckpointFolderGridDataTemplate}"
ItemsSource="{Binding SubFolders, Mode=OneWay}"
Margin="8,0,8,8">
<ItemsRepeater.Layout>
<StackLayout Orientation="Vertical"/>
<StackLayout Orientation="Vertical" />
</ItemsRepeater.Layout>
</ItemsRepeater>
<!-- Files Grid -->
<Grid Grid.Row="1" Name="FilesGrid"
<Grid Grid.Row="1" Name="FilesGrid"
Background="Transparent"
DragDrop.AllowDrop="True">
<ItemsRepeater
@ -278,17 +310,17 @@
ItemTemplate="{StaticResource CheckpointFileDataTemplate}"
ItemsSource="{Binding DisplayedCheckpointFiles}">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal"
MinColumnSpacing="4" MinRowSpacing="4"/>
<UniformGridLayout Orientation="Horizontal"
MinColumnSpacing="4" MinRowSpacing="4" />
</ItemsRepeater.Layout>
<TextBlock Text="Hi"/>
<TextBlock Text="Hi" />
</ItemsRepeater>
<TextBlock VerticalAlignment="Center"
TextAlignment="Center"
HorizontalAlignment="Center"
Margin="8,8,8,16"
Text="{x:Static lang:Resources.Label_DragAndDropCheckpointsHereToImport}"
IsVisible="{Binding !CheckpointFiles.Count}"/>
IsVisible="{Binding !CheckpointFiles.Count}" />
<!-- Blurred background for drag and drop -->
<Border
CornerRadius="4"
@ -332,7 +364,7 @@
</Grid>
</Expander>
</DataTemplate>
<!-- Template for dropdown box -->
<ControlTemplate x:Key="CategoryDropDownTemplate">
<Grid>
@ -370,37 +402,16 @@
</Grid>
</Grid>
</Border>
</Grid>
</Grid>
</ControlTemplate>
</controls:UserControlBase.Resources>
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,*" Margin="4, 0"
x:Name="ParentGrid">
<!-- Top settings bar -->
<StackPanel Grid.Column="0" Grid.Row="0">
<ToggleSwitch
OffContent="{x:Static lang:Resources.Label_ImportAsConnected}"
OnContent="{x:Static lang:Resources.Label_ImportAsConnected}"
IsChecked="{Binding IsImportAsConnected}"
Margin="24,4,24,-4"
ToolTip.Tip="{x:Static lang:Resources.Label_ImportAsConnectedExplanation}" />
<ToggleSwitch
OffContent="{x:Static lang:Resources.Label_ShowModelImages}"
OnContent="{x:Static lang:Resources.Label_ShowModelImages}"
IsChecked="{Binding ShowConnectedModelImages}"
Margin="24,-4,24,4" />
</StackPanel>
<StackPanel
Grid.Column="1"
Grid.Row="0"
Spacing="8"
HorizontalAlignment="Right"
Margin="16,0"
Orientation="Horizontal">
<TextBox Margin="8, 16"
<StackPanel Orientation="Horizontal">
<TextBox Margin="16, 16, 8, 16"
Watermark="{x:Static lang:Resources.Action_Search}"
Height="16"
MinWidth="220"
@ -421,38 +432,81 @@
</Grid>
</TextBox.InnerRightContent>
</TextBox>
<controls:ProgressRing
Width="16"
Height="16"
BorderThickness="4"
IsIndeterminate="True"
IsVisible="{Binding IsIndexing}"/>
<TextBlock Text="{x:Static lang:Resources.Label_Indexing}" FontSize="11"
VerticalAlignment="Center"
IsVisible="{Binding IsIndexing}"/>
<Button
Command="{Binding OpenModelsFolderCommand}">
<TextBlock Text="{x:Static lang:Resources.Label_ModelsFolder}"/>
</Button>
<DropDownButton
Content="{x:Static lang:Resources.Label_Categories}"
Margin="8"
Margin="8,0"
VerticalAlignment="Center"
HorizontalAlignment="Right">
<DropDownButton.Flyout>
<ui:FAMenuFlyout
<ui:FAMenuFlyout
ItemsSource="{Binding CheckpointFolders}">
<ui:FAMenuFlyout.ItemTemplate>
<DataTemplate DataType="{x:Type checkpointManager:CheckpointFolder}">
<ui:ToggleMenuFlyoutItem
Text="{Binding TitleWithFilesCount}"
IsChecked="{Binding IsCategoryEnabled, Mode=TwoWay}"/>
<ui:ToggleMenuFlyoutItem
Text="{Binding TitleWithFilesCount}"
IsChecked="{Binding IsCategoryEnabled, Mode=TwoWay}" />
</DataTemplate>
</ui:FAMenuFlyout.ItemTemplate>
</ui:FAMenuFlyout>
</DropDownButton.Flyout>
</DropDownButton>
</StackPanel>
<ui:CommandBar
Grid.Row="0"
Grid.Column="1"
x:Name="CommandBar"
Margin="8,0,0,0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
DefaultLabelPosition="Right">
<ui:CommandBar.PrimaryCommands>
<ui:CommandBarButton
IconSource="OpenFolder"
VerticalAlignment="Center"
Label="{x:Static lang:Resources.Label_ModelsFolder}"
Command="{Binding OpenModelsFolderCommand}" />
<ui:CommandBarButton
IconSource="Refresh"
VerticalAlignment="Center"
Command="{Binding OnLoaded}"
Label="{x:Static lang:Resources.Action_Refresh}" />
<ui:CommandBarToggleButton
IconSource="Image"
Label="{x:Static lang:Resources.Label_ShowModelImages}"
IsChecked="{Binding ShowConnectedModelImages, Mode=TwoWay}">
</ui:CommandBarToggleButton>
</ui:CommandBar.PrimaryCommands>
<ui:CommandBar.SecondaryCommands>
<ui:CommandBarToggleButton
IconSource="Cloud"
Label="{x:Static lang:Resources.Label_ImportAsConnected}"
IsChecked="{Binding IsImportAsConnected, Mode=TwoWay}">
</ui:CommandBarToggleButton>
</ui:CommandBar.SecondaryCommands>
</ui:CommandBar>
<StackPanel
IsVisible="False"
Grid.Column="1"
Grid.Row="0"
Spacing="8"
HorizontalAlignment="Right"
Margin="16,0"
Orientation="Horizontal">
<controls:ProgressRing
Width="16"
Height="16"
BorderThickness="4"
IsIndeterminate="True"
IsVisible="{Binding IsIndexing}" />
<TextBlock Text="{x:Static lang:Resources.Label_Indexing}" FontSize="11"
VerticalAlignment="Center"
IsVisible="{Binding IsIndexing}" />
</StackPanel>
<!-- Main view with model cards -->
<ScrollViewer
@ -463,14 +517,14 @@
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<Grid>
<controls:ProgressRing
<controls:ProgressRing
Width="128"
Height="128"
BorderThickness="8"
IsIndeterminate="True"
IsVisible="{Binding IsLoading}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
VerticalAlignment="Center" />
<StackPanel Orientation="Vertical">
<ItemsControl
HorizontalAlignment="Stretch"
@ -482,10 +536,10 @@
</StackPanel>
</Grid>
</ScrollViewer>
<!-- Overlay for draggable file panels -->
<Panel Name="OverlayPanel"
<Panel Name="OverlayPanel"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
</controls:UserControlBase>

33
StabilityMatrix.Core/Models/ConnectedModelInfo.cs

@ -8,7 +8,7 @@ public class ConnectedModelInfo
{
[JsonIgnore]
public const string FileExtension = ".cm-info.json";
public int ModelId { get; set; }
public string ModelName { get; set; }
public string ModelDescription { get; set; }
@ -22,16 +22,20 @@ public class ConnectedModelInfo
public CivitFileMetadata FileMetadata { get; set; }
public DateTimeOffset ImportedAt { get; set; }
public CivitFileHashes Hashes { get; set; }
public string[]? TrainedWords { get; set; }
// User settings
public string? UserTitle { get; set; }
public string? ThumbnailImageUrl { get; set; }
public ConnectedModelInfo()
{
}
public ConnectedModelInfo(CivitModel civitModel, CivitModelVersion civitModelVersion, CivitFile civitFile, DateTimeOffset importedAt)
public ConnectedModelInfo() { }
public ConnectedModelInfo(
CivitModel civitModel,
CivitModelVersion civitModelVersion,
CivitFile civitFile,
DateTimeOffset importedAt
)
{
ModelId = civitModel.Id;
ModelName = civitModel.Name;
@ -46,11 +50,18 @@ public class ConnectedModelInfo
BaseModel = civitModelVersion.BaseModel;
FileMetadata = civitFile.Metadata;
Hashes = civitFile.Hashes;
TrainedWords = civitModelVersion.TrainedWords;
}
public static ConnectedModelInfo? FromJson(string json)
{
return JsonSerializer.Deserialize<ConnectedModelInfo>(json, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull } );
return JsonSerializer.Deserialize<ConnectedModelInfo>(
json,
new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
}
);
}
/// <summary>
@ -65,4 +76,8 @@ public class ConnectedModelInfo
var json = JsonSerializer.Serialize(this);
await File.WriteAllTextAsync(Path.Combine(directoryPath, name), json);
}
[JsonIgnore]
public string TrainedWordsString =>
TrainedWords != null ? string.Join(", ", TrainedWords) : string.Empty;
}

Loading…
Cancel
Save