Skip to content

Commit 2c73d4f

Browse files
authored
Merge pull request LykosAI#944 from ionite34/downmerge
Downmerge from public
2 parents e2bd539 + 0b622fa commit 2c73d4f

File tree

4 files changed

+311
-61
lines changed

4 files changed

+311
-61
lines changed

StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,12 @@ out var res
486486
)
487487
? res
488488
: null;
489+
490+
if (sampler is null && SelectedSampler is not null && SelectedScheduler is not null)
491+
{
492+
sampler = $"{SelectedSampler?.DisplayName} {SelectedScheduler?.DisplayName}";
493+
}
494+
489495
return parameters with
490496
{
491497
Width = Width,

StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,26 @@
1515
d:DesignWidth="450"
1616
x:DataType="progress:ProgressManagerViewModel"
1717
mc:Ignorable="d">
18-
<ScrollViewer>
19-
<Grid RowDefinitions="Auto, *">
20-
<TextBlock
21-
Grid.Row="0"
22-
VerticalAlignment="Center"
23-
FontSize="16"
24-
Text="Downloads"
25-
TextAlignment="Left"
26-
TextDecorations="Underline" />
27-
<Button
28-
Grid.Row="0"
29-
Margin="0,0,8,0"
30-
Padding="4"
31-
HorizontalAlignment="Right"
32-
Classes="transparent"
33-
Command="{Binding ClearDownloads}"
34-
Content="Clear Finished"
35-
IsVisible="{Binding !!ProgressItems.Count}" />
18+
<Grid RowDefinitions="Auto, *">
19+
<TextBlock
20+
Grid.Row="0"
21+
VerticalAlignment="Center"
22+
FontSize="16"
23+
Text="Downloads"
24+
TextAlignment="Left"
25+
TextDecorations="Underline" />
26+
<Button
27+
Grid.Row="0"
28+
Margin="0,0,8,0"
29+
Padding="4"
30+
HorizontalAlignment="Right"
31+
Classes="transparent"
32+
Command="{Binding ClearDownloads}"
33+
Content="Clear Finished"
34+
IsVisible="{Binding !!ProgressItems.Count}" />
3635

37-
<ItemsControl
38-
Grid.Row="1"
39-
Margin="0,4,0,0"
40-
ItemsSource="{Binding ProgressItems, Mode=OneWay}">
36+
<ScrollViewer Grid.Row="1" Margin="0,4,0,0">
37+
<ItemsControl ItemsSource="{Binding ProgressItems, Mode=OneWay}">
4138
<ItemsControl.DataTemplates>
4239

4340
<DataTemplate DataType="{x:Type vmBase:PausableProgressItemViewModelBase}">
@@ -264,6 +261,6 @@
264261
</DataTemplate>
265262
</ItemsControl.DataTemplates>
266263
</ItemsControl>
267-
</Grid>
268-
</ScrollViewer>
264+
</ScrollViewer>
265+
</Grid>
269266
</controls:UserControlBase>

StabilityMatrix.Core/Models/GenerationParameters.cs

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
using System.ComponentModel.DataAnnotations;
22
using System.Diagnostics.CodeAnalysis;
3-
using System.Text.Json.Nodes;
43
using System.Text.Json.Serialization;
5-
using System.Text.RegularExpressions;
64
using StabilityMatrix.Core.Models.Api.Comfy;
75

86
namespace StabilityMatrix.Core.Models;
97

108
[JsonSerializable(typeof(GenerationParameters))]
11-
public partial record GenerationParameters
9+
public record GenerationParameters
1210
{
1311
public string? PositivePrompt { get; set; }
1412
public string? NegativePrompt { get; set; }
@@ -124,36 +122,139 @@ public static GenerationParameters Parse(string text)
124122
/// fields are separated by commas and key-value pairs are separated by colons.
125123
/// i.e. "key1: value1, key2: value2"
126124
/// </summary>
127-
internal static Dictionary<string, string> ParseLine(string fields)
125+
internal static Dictionary<string, string> ParseLine(string line)
128126
{
129127
var dict = new Dictionary<string, string>();
130128

131-
// Values main contain commas or colons
132-
foreach (var match in ParametersFieldsRegex().Matches(fields).Cast<Match>())
129+
var quoteStack = new Stack<char>();
130+
// the Range for the key
131+
Range? currentKeyRange = null;
132+
// the start of the key or value
133+
Index currentStart = 0;
134+
135+
for (var i = 0; i < line.Length; i++)
133136
{
134-
if (!match.Success)
135-
continue;
137+
var c = line[i];
136138

137-
var key = match.Groups[1].Value.Trim();
138-
var value = UnquoteValue(match.Groups[2].Value.Trim());
139+
switch (c)
140+
{
141+
case '"':
142+
// if we are in a " quote, pop the stack
143+
if (quoteStack.Count > 0 && quoteStack.Peek() == '"')
144+
{
145+
quoteStack.Pop();
146+
}
147+
else
148+
{
149+
// start of a new quoted section
150+
quoteStack.Push(c);
151+
}
152+
break;
139153

140-
dict.Add(key, value);
141-
}
154+
case '[':
155+
case '{':
156+
case '(':
157+
case '<':
158+
quoteStack.Push(c);
159+
break;
142160

143-
return dict;
144-
}
161+
case ']':
162+
if (quoteStack.Count > 0 && quoteStack.Peek() == '[')
163+
{
164+
quoteStack.Pop();
165+
}
166+
break;
167+
case '}':
168+
if (quoteStack.Count > 0 && quoteStack.Peek() == '{')
169+
{
170+
quoteStack.Pop();
171+
}
172+
break;
173+
case ')':
174+
if (quoteStack.Count > 0 && quoteStack.Peek() == '(')
175+
{
176+
quoteStack.Pop();
177+
}
178+
break;
179+
case '>':
180+
if (quoteStack.Count > 0 && quoteStack.Peek() == '<')
181+
{
182+
quoteStack.Pop();
183+
}
184+
break;
145185

146-
/// <summary>
147-
/// Unquotes a quoted value field if required
148-
/// </summary>
149-
private static string UnquoteValue(string quotedField)
150-
{
151-
if (!(quotedField.StartsWith('"') && quotedField.EndsWith('"')))
186+
case ':':
187+
// : marks the end of the key
188+
189+
// if we already have a key, ignore this colon as it is part of the value
190+
// if we are not in a quote, we have a key
191+
if (!currentKeyRange.HasValue && quoteStack.Count == 0)
192+
{
193+
currentKeyRange = new Range(currentStart, i);
194+
currentStart = i + 1;
195+
}
196+
break;
197+
198+
case ',':
199+
// , marks the end of a key-value pair
200+
// if we are not in a quote, we have a value
201+
if (quoteStack.Count != 0)
202+
{
203+
break;
204+
}
205+
206+
if (!currentKeyRange.HasValue)
207+
{
208+
// unexpected comma, reset and start from current position
209+
currentStart = i + 1;
210+
break;
211+
}
212+
213+
try
214+
{
215+
// extract the key and value
216+
var key = new string(line.AsSpan()[currentKeyRange!.Value].Trim());
217+
var value = new string(line.AsSpan()[currentStart..i].Trim());
218+
219+
// check duplicates and prefer the first occurrence
220+
if (!string.IsNullOrWhiteSpace(key) && !dict.ContainsKey(key))
221+
{
222+
dict[key] = value;
223+
}
224+
}
225+
catch (Exception)
226+
{
227+
// ignore individual key-value pair errors
228+
}
229+
230+
currentKeyRange = null;
231+
currentStart = i + 1;
232+
break;
233+
default:
234+
break;
235+
} // end of switch
236+
} // end of for
237+
238+
// if we have a key-value pair at the end of the string
239+
if (currentKeyRange.HasValue)
152240
{
153-
return quotedField;
241+
try
242+
{
243+
var key = new string(line.AsSpan()[currentKeyRange!.Value].Trim());
244+
var value = new string(line.AsSpan()[currentStart..].Trim());
245+
246+
if (!string.IsNullOrWhiteSpace(key) && !dict.ContainsKey(key))
247+
{
248+
dict[key] = value;
249+
}
250+
}
251+
catch (Exception)
252+
{
253+
// ignore individual key-value pair errors
254+
}
154255
}
155256

156-
return JsonNode.Parse(quotedField)?.GetValue<string>() ?? "";
257+
return dict;
157258
}
158259

159260
/// <summary>
@@ -213,7 +314,4 @@ public static GenerationParameters GetSample()
213314
Sampler = "DPM++ 2M Karras"
214315
};
215316
}
216-
217-
[GeneratedRegex("""\s*([\w ]+):\s*("(?:\\.|[^\\"])+"|[^,]*)(?:,|$)""")]
218-
private static partial Regex ParametersFieldsRegex();
219317
}

0 commit comments

Comments
 (0)