Add Krea portrait models and write appearance as prose.
New schools default to Realism v2.5; living saves keep their catalog. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -85,7 +85,8 @@ public class PortraitApiTests(AppHostFixture fixture)
|
||||
var payload = await response.Content.ReadFromJsonAsync<PortraitPromptPayload>(TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(payload);
|
||||
Assert.Equal("avatar", payload!.Kind);
|
||||
Assert.Contains("age", payload.Positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("years old", payload.Positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.DoesNotContain("age ", payload.Positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.False(string.IsNullOrWhiteSpace(payload.Negative));
|
||||
Assert.False(string.IsNullOrWhiteSpace(payload.PresetId));
|
||||
}
|
||||
@@ -103,6 +104,8 @@ public class PortraitApiTests(AppHostFixture fixture)
|
||||
Assert.NotNull(settings);
|
||||
Assert.NotEmpty(settings!.Presets);
|
||||
Assert.NotEmpty(settings.Models);
|
||||
Assert.Contains(settings.Models, model => model.Id == "museByStableYogi_v30TurboGguf.gguf");
|
||||
Assert.Contains(settings.Models, model => model.Id == "realismByStableYogi_v25INT8Turbo.safetensors");
|
||||
Assert.False(string.IsNullOrWhiteSpace(settings.ActivePresetId));
|
||||
}
|
||||
|
||||
@@ -122,6 +125,14 @@ public class PortraitApiTests(AppHostFixture fixture)
|
||||
Assert.True(list.GetArrayLength() > 0);
|
||||
Assert.True(presets.TryGetProperty("models", out var models));
|
||||
Assert.True(models.GetArrayLength() > 0);
|
||||
var ids = models.EnumerateArray().Select(model => model.GetProperty("id").GetString()).ToList();
|
||||
Assert.Contains("museByStableYogi_v30TurboGguf.gguf", ids);
|
||||
Assert.Contains("realismByStableYogi_v25INT8Turbo.safetensors", ids);
|
||||
var defaultPreset = presets.GetProperty("presets").EnumerateArray()
|
||||
.First(preset => preset.GetProperty("id").GetString() == "default");
|
||||
Assert.Equal(
|
||||
"realismByStableYogi_v25INT8Turbo.safetensors",
|
||||
defaultPreset.GetProperty("model").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -7,18 +7,20 @@ namespace HSchool.Server.Tests;
|
||||
public class PortraitPromptBuilderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Build_IncludesAgeHairAndWornClothing()
|
||||
public void Build_DescribesAppearanceAndClothingInProse()
|
||||
{
|
||||
var profile = SamplePreset().ToProfile(PortraitKind.Avatar);
|
||||
|
||||
var card = SampleCard();
|
||||
var (positive, _) = PortraitPromptBuilder.Build(card, profile, PortraitKind.Avatar);
|
||||
|
||||
Assert.Contains("age 12", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("black", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("shirt", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("white", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("12 years old", positive, StringComparison.Ordinal);
|
||||
Assert.Contains("black hair", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("wearing a white shirt", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("Head and shoulders.", positive, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("age 12", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.DoesNotContain("Hair colour", positive, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("wearing shirt in white", positive, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -66,7 +68,7 @@ public class PortraitPromptBuilderTests
|
||||
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);
|
||||
var clothesAt = positive.IndexOf("wearing a white shirt", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
Assert.True(modelAt >= 0 && styleAt > modelAt && shotAt > styleAt && subjectAt > shotAt && clothesAt > subjectAt);
|
||||
Assert.DoesNotContain("pose", positive, StringComparison.OrdinalIgnoreCase);
|
||||
@@ -80,6 +82,31 @@ public class PortraitPromptBuilderTests
|
||||
var (positive, _) = PortraitPromptBuilder.Build(child, profile, PortraitKind.Avatar);
|
||||
|
||||
Assert.Contains("young girl", positive, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("8 years old", positive, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_TornClothing_PrefixesCondition()
|
||||
{
|
||||
var profile = SamplePreset().ToProfile(PortraitKind.Avatar);
|
||||
var card = SampleCard() with
|
||||
{
|
||||
Worn =
|
||||
[
|
||||
new WornItemResponse(
|
||||
"Shirt",
|
||||
"Shirt",
|
||||
"White",
|
||||
"White",
|
||||
[new DefLabelResponse(ApparelLayers.Top, "Top")],
|
||||
0.2f,
|
||||
"torn",
|
||||
[ApparelLayers.Underwear]),
|
||||
],
|
||||
};
|
||||
var (positive, _) = PortraitPromptBuilder.Build(card, profile, PortraitKind.Avatar);
|
||||
|
||||
Assert.Contains("wearing a torn white shirt", positive, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static SwarmUiPresetDefinition SamplePreset()
|
||||
|
||||
@@ -23,9 +23,11 @@ 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);
|
||||
Assert.Equal(1.5, profile.CfgScale);
|
||||
Assert.Equal(SwarmUiModelDefinition.RealismV25Id, profile.Model);
|
||||
Assert.Equal(8, profile.Steps);
|
||||
Assert.Equal(1, profile.CfgScale);
|
||||
Assert.Equal("euler", profile.Sampler);
|
||||
Assert.Equal("simple", profile.Scheduler);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -196,7 +198,7 @@ public class SwarmUiSettingsStoreTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDefault_SeedsEveryKnownSwarmModel()
|
||||
public void CreateDefault_SeedsCatalogModels()
|
||||
{
|
||||
var config = SwarmUiConfigFile.CreateDefault();
|
||||
var ids = config.Models.Select(model => model.Id).ToList();
|
||||
@@ -205,5 +207,20 @@ public class SwarmUiSettingsStoreTests
|
||||
Assert.Contains(SwarmUiModelDefinition.DreamShaperId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.EpicRealismId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.LustifyId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.MuseId, ids);
|
||||
Assert.Contains(SwarmUiModelDefinition.RealismV25Id, ids);
|
||||
Assert.DoesNotContain("realismByStableYogi_v20TurboGGUF.gguf", ids);
|
||||
|
||||
var realism = Assert.Single(config.Models, model => model.Id == SwarmUiModelDefinition.RealismV25Id);
|
||||
Assert.Equal(8, realism.Steps);
|
||||
Assert.Equal(1, realism.CfgScale);
|
||||
Assert.Equal("euler", realism.Sampler);
|
||||
Assert.Equal("simple", realism.Scheduler);
|
||||
|
||||
var muse = Assert.Single(config.Models, model => model.Id == SwarmUiModelDefinition.MuseId);
|
||||
Assert.Equal(8, muse.Steps);
|
||||
Assert.Equal(1, muse.CfgScale);
|
||||
Assert.Equal("euler", muse.Sampler);
|
||||
Assert.Equal("simple", muse.Scheduler);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user