99using StabilityMatrix . Core . Extensions ;
1010using StabilityMatrix . Core . Models ;
1111using StabilityMatrix . Core . Models . Api ;
12+ using StabilityMatrix . Core . Models . Database ;
1213using StabilityMatrix . Core . Models . Inference ;
1314
1415namespace StabilityMatrix . Avalonia . Models . Inference ;
@@ -24,6 +25,25 @@ public partial class FileNameFormatProvider
2425 public CivitModel ? CivitModel { get ; init ; }
2526 public CivitModelVersion ? CivitModelVersion { get ; init ; }
2627 public CivitFile ? CivitFile { get ; init ; }
28+ public LocalModelFile ? LocalModelFile { get ; init ; }
29+
30+ public static ISet < string > LocalOrganizationVariables { get ; } =
31+ new HashSet < string > (
32+ [
33+ "date" ,
34+ "time" ,
35+ "author" ,
36+ "base_model" ,
37+ "file_name" ,
38+ "file_id" ,
39+ "model_id" ,
40+ "model_name" ,
41+ "model_version_id" ,
42+ "model_version_name" ,
43+ "model_type" ,
44+ ] ,
45+ StringComparer . Ordinal
46+ ) ;
2747
2848 private Dictionary < string , Func < string ? > > ? _substitutions ;
2949
@@ -35,7 +55,11 @@ public partial class FileNameFormatProvider
3555 { "negative_prompt" , ( ) => GenerationParameters ? . NegativePrompt } ,
3656 {
3757 "model_name" ,
38- ( ) => Path . GetFileNameWithoutExtension ( GenerationParameters ? . ModelName ) ?? CivitModel ? . Name
58+ ( ) =>
59+ Path . GetFileNameWithoutExtension ( GenerationParameters ? . ModelName )
60+ ?? CivitModel ? . Name
61+ ?? LocalModelFile ? . ConnectedModelInfo ? . ModelName
62+ ?? LocalModelFile ? . FileNameWithoutExtension
3963 } ,
4064 { "model_hash" , ( ) => GenerationParameters ? . ModelHash } ,
4165 { "sampler" , ( ) => GenerationParameters ? . Sampler } ,
@@ -47,14 +71,45 @@ public partial class FileNameFormatProvider
4771 { "project_name" , ( ) => ProjectName } ,
4872 { "date" , ( ) => DateTime . Now . ToString ( "yyyy-MM-dd" ) } ,
4973 { "time" , ( ) => DateTime . Now . ToString ( "HH-mm-ss" ) } ,
50- { "author" , ( ) => CivitModel ? . Creator ? . Username } ,
51- { "base_model" , ( ) => CivitModelVersion ? . BaseModel } ,
52- { "file_name" , ( ) => Path . GetFileNameWithoutExtension ( CivitFile ? . Name ) } ,
53- { "file_id" , ( ) => CivitFile ? . Id . ToString ( ) } ,
54- { "model_id" , ( ) => CivitModel ? . Id . ToString ( ) } ,
55- { "model_version_id" , ( ) => CivitModelVersion ? . Id . ToString ( ) } ,
56- { "model_version_name" , ( ) => CivitModelVersion ? . Name } ,
57- { "model_type" , ( ) => CivitModel ? . Type . ToString ( ) } ,
74+ {
75+ "author" ,
76+ ( ) => CivitModel ? . Creator ? . Username ?? LocalModelFile ? . ConnectedModelInfo ? . AuthorUsername
77+ } ,
78+ {
79+ "base_model" ,
80+ ( ) => CivitModelVersion ? . BaseModel ?? LocalModelFile ? . ConnectedModelInfo ? . BaseModel
81+ } ,
82+ {
83+ "file_name" ,
84+ ( ) =>
85+ Path . GetFileNameWithoutExtension ( CivitFile ? . Name )
86+ ?? Path . GetFileNameWithoutExtension ( LocalModelFile ? . ConnectedModelInfo ? . RemoteFileName )
87+ ?? LocalModelFile ? . FileNameWithoutExtension
88+ } ,
89+ {
90+ "file_id" ,
91+ ( ) => CivitFile ? . Id . ToString ( ) ?? LocalModelFile ? . ConnectedModelInfo ? . RemoteFileId ? . ToString ( )
92+ } ,
93+ {
94+ "model_id" ,
95+ ( ) => CivitModel ? . Id . ToString ( ) ?? LocalModelFile ? . ConnectedModelInfo ? . ModelId ? . ToString ( )
96+ } ,
97+ {
98+ "model_version_id" ,
99+ ( ) =>
100+ CivitModelVersion ? . Id . ToString ( )
101+ ?? LocalModelFile ? . ConnectedModelInfo ? . VersionId ? . ToString ( )
102+ } ,
103+ {
104+ "model_version_name" ,
105+ ( ) => CivitModelVersion ? . Name ?? LocalModelFile ? . ConnectedModelInfo ? . VersionName
106+ } ,
107+ {
108+ "model_type" ,
109+ ( ) =>
110+ CivitModel ? . Type . ToString ( )
111+ ?? ( LocalModelFile ? . ConnectedModelInfo is { } cmInfo ? cmInfo . ModelType . ToString ( ) : null )
112+ } ,
58113 } ;
59114
60115 /// <summary>
@@ -65,15 +120,13 @@ public partial class FileNameFormatProvider
65120 [ Pure ]
66121 public ValidationResult Validate ( string format )
67122 {
68- var regex = BracketRegex ( ) ;
69- var matches = regex . Matches ( format ) ;
70- var variables = matches . Select ( m => m . Groups [ 1 ] . Value ) ;
123+ var variables = GetVariableTexts ( format ) ;
71124
72125 foreach ( var variableText in variables )
73126 {
74127 try
75128 {
76- var ( variable , _ ) = ExtractVariableAndSlice ( variableText ) ;
129+ var variable = GetVariableName ( variableText ) ;
77130
78131 if ( ! Substitutions . ContainsKey ( variable ) )
79132 {
@@ -89,6 +142,47 @@ public ValidationResult Validate(string format)
89142 return ValidationResult . Success ! ;
90143 }
91144
145+ public IEnumerable < string > GetVariableTexts ( string template )
146+ {
147+ return BracketRegex ( ) . Matches ( template ) . Select ( m => m . Groups [ 1 ] . Value ) ;
148+ }
149+
150+ public string GetVariableName ( string variableText )
151+ {
152+ var ( variable , _) = ExtractVariableAndSlice ( variableText ) ;
153+ return variable ;
154+ }
155+
156+ public bool TryResolveVariable ( string variableText , out string ? value , out string ? error )
157+ {
158+ try
159+ {
160+ var ( variable , slice ) = ExtractVariableAndSlice ( variableText ) ;
161+ if ( ! Substitutions . TryGetValue ( variable , out var substitution ) )
162+ {
163+ value = null ;
164+ error = $ "Unknown variable '{ variable } '";
165+ return false ;
166+ }
167+
168+ value = ApplySlice ( substitution ( ) , slice ) ;
169+ if ( value is null )
170+ {
171+ error = $ "Variable '{ variable } ' is not available";
172+ return false ;
173+ }
174+
175+ error = null ;
176+ return true ;
177+ }
178+ catch ( Exception e )
179+ {
180+ value = null ;
181+ error = $ "Invalid variable '{ variableText } ': { e . Message } ";
182+ return false ;
183+ }
184+ }
185+
92186 public IEnumerable < FileNameFormatPart > GetParts ( string template )
93187 {
94188 var regex = BracketRegex ( ) ;
@@ -114,36 +208,7 @@ public IEnumerable<FileNameFormatPart> GetParts(string template)
114208 var ( variable , slice ) = ExtractVariableAndSlice ( result . Groups [ 1 ] . Value ) ;
115209 var substitution = Substitutions [ variable ] ;
116210
117- // Slice string if necessary
118- if ( slice is not null )
119- {
120- parts . Add (
121- ( FileNameFormatPart ) (
122- ( ) =>
123- {
124- var value = substitution ( ) ;
125- if ( value is null )
126- return null ;
127-
128- if ( slice . End is null )
129- {
130- value = value [ ( slice . Start ?? 0 ) ..] ;
131- }
132- else
133- {
134- var length = Math . Min ( value . Length , slice . End . Value ) - ( slice . Start ?? 0 ) ;
135- value = value . Substring ( slice . Start ?? 0 , length ) ;
136- }
137-
138- return value ;
139- }
140- )
141- ) ;
142- }
143- else
144- {
145- parts . Add ( substitution ) ;
146- }
211+ parts . Add ( ( FileNameFormatPart ) ( ( ) => ApplySlice ( substitution ( ) , slice ) ) ) ;
147212
148213 currentIndex += result . Length ;
149214 }
@@ -198,6 +263,35 @@ public static FileNameFormatProvider GetSampleForModelBrowser()
198263 } ;
199264 }
200265
266+ public static FileNameFormatProvider GetSampleForOrganization ( )
267+ {
268+ return new FileNameFormatProvider
269+ {
270+ LocalModelFile = new LocalModelFile
271+ {
272+ RelativePath = "StableDiffusion/sample_file.safetensors" ,
273+ SharedFolderType = SharedFolderType . StableDiffusion ,
274+ ConnectedModelInfo = new ConnectedModelInfo
275+ {
276+ ModelId = 1234 ,
277+ ModelName = "Sample Model" ,
278+ ModelDescription = string . Empty ,
279+ Nsfw = false ,
280+ Tags = [ ] ,
281+ ModelType = CivitModelType . Checkpoint ,
282+ VersionId = 5678 ,
283+ VersionName = "v1.0" ,
284+ AuthorUsername = "SampleUser" ,
285+ BaseModel = "Illustrious" ,
286+ RemoteFileName = "sample_file.safetensors" ,
287+ RemoteFileId = 910 ,
288+ Hashes = new CivitFileHashes ( ) ,
289+ Source = ConnectedModelSource . Civitai ,
290+ } ,
291+ } ,
292+ } ;
293+ }
294+
201295 /// <summary>
202296 /// Extract variable and index from a combined string
203297 /// </summary>
@@ -224,6 +318,20 @@ private static (string Variable, Slice? Slice) ExtractVariableAndSlice(string co
224318 return ( variable , slice ) ;
225319 }
226320
321+ private static string ? ApplySlice ( string ? value , Slice ? slice )
322+ {
323+ if ( value is null || slice is null )
324+ return value ;
325+
326+ if ( slice . End is null )
327+ {
328+ return value [ ( slice . Start ?? 0 ) ..] ;
329+ }
330+
331+ var length = Math . Min ( value . Length , slice . End . Value ) - ( slice . Start ?? 0 ) ;
332+ return value . Substring ( slice . Start ?? 0 , length ) ;
333+ }
334+
227335 /// <summary>
228336 /// Regex for matching contents within a curly brace.
229337 /// </summary>
0 commit comments