Merge branch 'phase/60-portrait-models'
# Conflicts: # docs/phases/off-queue/README.md
This commit is contained in:
@@ -34,7 +34,7 @@ public class PortraitPromptBuilderTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Custom_UsesPromptExtraInsteadOfPreset()
|
||||
public void Build_Custom_KeepsShotTypeAndAppendsPromptExtra()
|
||||
{
|
||||
var profile = SamplePreset().ToProfile(PortraitKind.Custom);
|
||||
const string extra = "standing in a school hallway, soft window light";
|
||||
@@ -45,9 +45,31 @@ public class PortraitPromptBuilderTests
|
||||
extra);
|
||||
|
||||
Assert.Contains("School photo.", customPositive, StringComparison.Ordinal);
|
||||
Assert.Contains("Hallway light.", customPositive, StringComparison.Ordinal);
|
||||
Assert.Contains(extra, customPositive, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("Head and shoulders.", customPositive, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("Standing full body.", customPositive, StringComparison.Ordinal);
|
||||
Assert.True(
|
||||
customPositive.IndexOf("Hallway light.", StringComparison.Ordinal)
|
||||
< customPositive.IndexOf(extra, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_OrdersLayers_ModelStyleShotAppearanceClothing()
|
||||
{
|
||||
var preset = SamplePreset();
|
||||
var model = new SwarmUiModelDefinition { Id = preset.Model, Positive = "Model base." };
|
||||
var profile = preset.ToProfile(PortraitKind.Avatar, model);
|
||||
var (positive, _) = PortraitPromptBuilder.Build(SampleCard(), profile, PortraitKind.Avatar);
|
||||
|
||||
var modelAt = positive.IndexOf("Model base.", StringComparison.Ordinal);
|
||||
var styleAt = positive.IndexOf("School photo.", StringComparison.Ordinal);
|
||||
var shotAt = positive.IndexOf("Head and shoulders.", StringComparison.Ordinal);
|
||||
var subjectAt = positive.IndexOf("teenage girl", StringComparison.OrdinalIgnoreCase);
|
||||
var clothesAt = positive.IndexOf("wearing shirt", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
Assert.True(modelAt >= 0 && styleAt > modelAt && shotAt > styleAt && subjectAt > shotAt && clothesAt > subjectAt);
|
||||
Assert.DoesNotContain("pose", positive, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -63,18 +85,24 @@ public class PortraitPromptBuilderTests
|
||||
private static SwarmUiPresetDefinition SamplePreset()
|
||||
{
|
||||
var preset = SwarmUiPresetDefinition.CreateDefault();
|
||||
preset.Positive = "School photo.";
|
||||
preset.Style = "School photo.";
|
||||
preset.Avatar = new SwarmUiKindPreset
|
||||
{
|
||||
Width = 512,
|
||||
Height = 512,
|
||||
Positive = "Head and shoulders.",
|
||||
ShotType = "Head and shoulders.",
|
||||
};
|
||||
preset.Custom = new SwarmUiKindPreset
|
||||
{
|
||||
Width = 512,
|
||||
Height = 768,
|
||||
ShotType = "Hallway light.",
|
||||
};
|
||||
preset.FullBody = new SwarmUiKindPreset
|
||||
{
|
||||
Width = 512,
|
||||
Height = 768,
|
||||
Positive = "Standing full body.",
|
||||
ShotType = "Standing full body.",
|
||||
};
|
||||
return preset;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class PortraitVisibleWornTests
|
||||
public void Build_OmitsCoveredShirtFromPrompt()
|
||||
{
|
||||
var preset = SwarmUiPresetDefinition.CreateDefault();
|
||||
preset.Positive = "School photo.";
|
||||
preset.Style = "School photo.";
|
||||
var card = SampleCard(
|
||||
[
|
||||
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear], color: "White", colorLabel: "White"),
|
||||
|
||||
@@ -11,6 +11,8 @@ public class SwarmUiSettingsStoreTests
|
||||
var profile = config.Resolve(8, PortraitKind.Avatar);
|
||||
|
||||
Assert.Equal("child", profile.PresetId);
|
||||
Assert.Equal(SwarmUiModelDefinition.DreamShaperId, profile.Model);
|
||||
Assert.Equal(4, profile.Steps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -20,6 +22,23 @@ public class SwarmUiSettingsStoreTests
|
||||
var profile = config.Resolve(34, PortraitKind.Full);
|
||||
|
||||
Assert.Equal("default", profile.PresetId);
|
||||
Assert.Equal(SwarmUiModelDefinition.BabesId, profile.Model);
|
||||
Assert.Equal(7, profile.Steps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_PresetOverrideBeatsModelDefaults()
|
||||
{
|
||||
var config = SwarmUiConfigFile.CreateDefault();
|
||||
var preset = config.Presets[0];
|
||||
preset.Steps = 12;
|
||||
preset.CfgScale = 3.5;
|
||||
|
||||
var profile = config.Resolve(34, PortraitKind.Avatar);
|
||||
|
||||
Assert.Equal(12, profile.Steps);
|
||||
Assert.Equal(3.5, profile.CfgScale);
|
||||
Assert.Equal(0, profile.ClipSkip);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -30,7 +49,7 @@ public class SwarmUiSettingsStoreTests
|
||||
Model = "legacy.safetensors",
|
||||
Steps = 12,
|
||||
Positive = "legacy prompt",
|
||||
Avatar = new SwarmUiKindPreset { Width = 640, Height = 640 },
|
||||
Avatar = new SwarmUiKindPreset { Width = 640, Height = 640, Positive = "close up." },
|
||||
};
|
||||
|
||||
config.NormalizeAfterLoad();
|
||||
@@ -38,7 +57,77 @@ public class SwarmUiSettingsStoreTests
|
||||
Assert.Single(config.Presets);
|
||||
Assert.Equal("default", config.Presets[0].Id);
|
||||
Assert.Equal("legacy.safetensors", config.Presets[0].Model);
|
||||
Assert.Equal(12, config.Presets[0].Steps);
|
||||
Assert.Equal("legacy prompt", config.Presets[0].Style);
|
||||
Assert.Null(config.Presets[0].Positive);
|
||||
Assert.Null(config.Presets[0].Steps);
|
||||
var model = Assert.Single(config.Models, entry => entry.Id == "legacy.safetensors");
|
||||
Assert.Equal(12, model.Steps);
|
||||
Assert.Equal("close up.", config.Presets[0].Avatar!.ShotType);
|
||||
Assert.Null(config.Presets[0].Avatar!.Positive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NormalizeAfterLoad_LiftsLegacyPresetPositiveIntoStyleAndShotType()
|
||||
{
|
||||
var config = new SwarmUiConfigFile
|
||||
{
|
||||
Presets =
|
||||
[
|
||||
new SwarmUiPresetDefinition
|
||||
{
|
||||
Id = "default",
|
||||
Label = "Default",
|
||||
Model = "a.safetensors",
|
||||
Steps = 6,
|
||||
CfgScale = 2,
|
||||
Positive = "was base prompt",
|
||||
Negative = "old neg",
|
||||
Avatar = new SwarmUiKindPreset { Width = 512, Height = 512, Positive = "was kind" },
|
||||
Custom = new SwarmUiKindPreset { Width = 512, Height = 512 },
|
||||
FullBody = new SwarmUiKindPreset { Width = 512, Height = 768 },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
config.NormalizeAfterLoad();
|
||||
|
||||
Assert.Equal("was base prompt", config.Presets[0].Style);
|
||||
Assert.Equal("was kind", config.Presets[0].Avatar!.ShotType);
|
||||
Assert.Contains(config.Models, model => model.Id == "a.safetensors");
|
||||
Assert.Equal("", Assert.Single(config.Models).Positive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AllowedModelIds_IntersectsSwarmWithCatalog()
|
||||
{
|
||||
var config = SwarmUiConfigFile.CreateDefault();
|
||||
var discovery = new SwarmUiDiscovery(
|
||||
true,
|
||||
[
|
||||
SwarmUiModelDefinition.BabesId,
|
||||
"not-in-config.safetensors",
|
||||
SwarmUiModelDefinition.EpicRealismId,
|
||||
],
|
||||
[],
|
||||
[],
|
||||
[]);
|
||||
|
||||
var allowed = config.AllowedModelIds(discovery);
|
||||
|
||||
Assert.Equal(
|
||||
[SwarmUiModelDefinition.BabesId, SwarmUiModelDefinition.EpicRealismId],
|
||||
allowed);
|
||||
Assert.DoesNotContain("not-in-config.safetensors", allowed);
|
||||
Assert.DoesNotContain(SwarmUiModelDefinition.DreamShaperId, allowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AllowedModelIds_WhenSwarmOffline_ReturnsCatalog()
|
||||
{
|
||||
var config = SwarmUiConfigFile.CreateDefault();
|
||||
var allowed = config.AllowedModelIds(SwarmUiDiscovery.Offline);
|
||||
|
||||
Assert.Equal(config.Models.Select(model => model.Id), allowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -46,6 +135,7 @@ public class SwarmUiSettingsStoreTests
|
||||
{
|
||||
var source = SwarmUiConfigFile.CreateDefault();
|
||||
source.Presets[0].Model = "mutated.safetensors";
|
||||
source.Models[0].Id = "mutated.safetensors";
|
||||
|
||||
var copy = SwarmUiConfigFile.Clone(source);
|
||||
copy.Presets[0].Model = "other.safetensors";
|
||||
@@ -54,4 +144,16 @@ public class SwarmUiSettingsStoreTests
|
||||
Assert.Equal("other.safetensors", copy.Presets[0].Model);
|
||||
Assert.Equal(source.ActivePresetId, copy.ActivePresetId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDefault_SeedsEveryKnownSwarmModel()
|
||||
{
|
||||
var config = SwarmUiConfigFile.CreateDefault();
|
||||
var ids = config.Models.Select(model => model.Id).ToList();
|
||||
|
||||
Assert.Contains(SwarmUiModelDefinition.BabesId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.DreamShaperId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.EpicRealismId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.LustifyId, ids);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user