diff --git a/KIKunstKirstenKlöckner/Data/ImageGenerator.cs b/KIKunstKirstenKlöckner/Data/ImageGenerator.cs index 55569c3..69c1dd6 100644 --- a/KIKunstKirstenKlöckner/Data/ImageGenerator.cs +++ b/KIKunstKirstenKlöckner/Data/ImageGenerator.cs @@ -12,7 +12,7 @@ public class ImageGenerator private readonly IConfiguration _config; - private string ModelName => _config.GetValue("StableDiffusionModel") ?? "No Model Defined"; + //private string ModelName => _config.GetValue("StableDiffusionModel") ?? "No Model Defined"; public ImageGenerator(IConfiguration config, BildInfoData bildInfoData) { @@ -34,7 +34,7 @@ public class ImageGenerator /// Die höhe des zu generierenden Bildes. für Standardhöhe des Modells /// Begriffe, die explizit nicht generiert werden sollen. /// Die BildInfo des generierten Bildes; oder null, wenn ein Fehler auftrat. - public async Task GenerateImageAsync(string imagePrompt, WunschInfoModel wunschInfo, int? width = null, int? height = null, string negativePromt = "") + public async Task GenerateImageAsync(string imagePrompt, string modelName, WunschInfoModel wunschInfo, int? width = null, int? height = null, string negativePromt = "") { var postData = new { @@ -60,7 +60,7 @@ public class ImageGenerator try { - var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{ModelName}"; + var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{modelName}"; var response = await _client.PostAsync(inferenceModelUrl, content); @@ -75,7 +75,7 @@ public class ImageGenerator // Die tatsächliche Url wird in SaveImageStreamAsync gesetzt. Dateiname = "PlaceHolder", Datum = imageDate, - ImageModel = ModelName, + ImageModel = modelName, WunschId = wunschInfo.Id, Prompt = imagePrompt }; diff --git a/KIKunstKirstenKlöckner/Pages/AiArt.razor b/KIKunstKirstenKlöckner/Pages/AiArt.razor index 50f46a8..4aed877 100644 --- a/KIKunstKirstenKlöckner/Pages/AiArt.razor +++ b/KIKunstKirstenKlöckner/Pages/AiArt.razor @@ -44,9 +44,9 @@ AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap"> Resolution: - + x - + + @* *@ + + + + + @@ -81,25 +87,41 @@ - @_imagePromts[0] + + @_imagePromts[0] +
+ Model: @_bildInfos[0]?.ImageModel +
- @_imagePromts[1] + Click="() => ShowImageDialog(_imageUrls[1])" /> + + @_imagePromts[1] +
+ Model: @_bildInfos[1]?.ImageModel +
- @_imagePromts[2] + Click="() => ShowImageDialog(_imageUrls[2])" /> + + @_imagePromts[2] +
+ Model: @_bildInfos[2]?.ImageModel +
- @_imagePromts[3] + Click="() => ShowImageDialog(_imageUrls[3])" /> + + @_imagePromts[3] +
+ Model: @_bildInfos[3]?.ImageModel +
@@ -125,6 +147,7 @@ private string?[] _imageUrls = new string?[4]; private string?[] _imagePromts = new string?[4]; + private BildInfoModel?[] _bildInfos = new BildInfoModel?[4]; private ImageState[] _imageStates = new ImageState[4]; enum ImageState @@ -153,8 +176,8 @@ private string _imageIdea = ""; private float _temperature = 0.9f; - private int? width = 1024; - private int? height = 1024; + private int? _imageWidth = null; + private int? _imageHeight = null; private string _userIdea = ""; private string _updateRequest = ""; private OpenAIAPI _openAiApi; @@ -167,11 +190,6 @@ private WunschInfoModel? _wunschInfo; - //protected override async Task OnInitializedAsync() - //{ - // _basePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"\wwwroot\prompt.txt"}"); - //} - async Task UpdateBusyMessage(string newMessage) { BusyMessage = newMessage; @@ -180,12 +198,26 @@ private string _openAiApiKey = ""; + class ModelInfo + { + public string Name { get; set; } + public string StableDiffusionModel { get; set; } + public string PromptFormat { get; set; } + } + + private List _imageModels; + + private ModelInfo? _selectedImageModel = null; + protected override async Task OnInitializedAsync() { _openAiApiKey = Config.GetValue("API:OpenAI"); _openAiApi = new OpenAIAPI(_openAiApiKey); + _imageModels = Config.GetSection("ImageModels").Get>(); + //_selectedImageModel = _imageModels[0]; + await base.OnInitializedAsync(); } @@ -251,21 +283,24 @@ /// Der Wunsch für den ein Bild erzeugt wird. private async Task RequestImagePromptAndGenerateImageAsync(int index, WunschInfoModel wunschInfo) { + ModelInfo imageModel = _selectedImageModel ?? _imageModels[Random.Shared.Next(_imageModels.Count)]; + // Bild Prompt von ChatGPT anfordern string imagePrompt = await _conversation!.GetResponseFromChatbotAsync(); // Keywords anhängen um Kirstens Stil zu aktivieren. // TODO: Gucken, ob wir dem Watercolor bums brauchen - imagePrompt = "kkkk " + imagePrompt;// + " kkkk Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique. "; + imagePrompt = string.Format(imageModel.PromptFormat, imagePrompt);//"kkkk " + imagePrompt;// + " kkkk Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique. "; // Debug only: Promt anzeigen _imagePromts[index] = imagePrompt; await InvokeAsync(StateHasChanged); - string? imageUrl = await GenerateImageAsync(imagePrompt, wunschInfo); + BildInfoModel? bildInfo = await GenerateImageAsync(imagePrompt, imageModel.StableDiffusionModel, wunschInfo); // TODO: Fehler im UI anzeigen (zur Zeit bleibt einfach Ladebalken) - _imageUrls[index] = imageUrl; + _imageUrls[index] = bildInfo?.Dateiname; + _bildInfos[index] = bildInfo; _imageStates[index] = ImageState.FadeIn; await InvokeAsync(StateHasChanged); } @@ -276,14 +311,14 @@ /// Der Bild Prompt /// Der Wunsch. /// Die URL, falls das Bild generiert wurde; oder null, wenn kein Bild generiert werden konnte. - private async Task GenerateImageAsync(string imagePrompt, WunschInfoModel wunschInfo) + private async Task GenerateImageAsync(string imagePrompt, string modelName, WunschInfoModel wunschInfo) { try { - string? imageUrl = (await ImageGenerator.GenerateImageAsync(imagePrompt, wunschInfo, width, height))?.Dateiname; + BildInfoModel? bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight); // Kein Bild -> Fehler - if (imageUrl == null) + if (bildInfo == null) { bool? retry = await DialogService.Confirm( "Leider konnte das Bild nicht gemalt werden. Möchtest du es noch eimal versuchen?", @@ -292,11 +327,11 @@ if (retry == true) { - imageUrl = (await ImageGenerator.GenerateImageAsync(imagePrompt, wunschInfo, width, height))?.Dateiname; + bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight); } } - return imageUrl; + return bildInfo; } catch (Exception e) { diff --git a/KIKunstKirstenKlöckner/appsettings.json b/KIKunstKirstenKlöckner/appsettings.json index 4935601..571fe50 100644 --- a/KIKunstKirstenKlöckner/appsettings.json +++ b/KIKunstKirstenKlöckner/appsettings.json @@ -10,7 +10,23 @@ "OpenAI": "", "HF_Inference": "" }, - "StableDiffusionModel": "Nacken/kkk-sdxl-18000", + "ImageModels": [ + { + "Name": "Gen 6", + "StableDiffusionModel": "Nacken/Gen6", + "PromptFormat": "{0}" + }, + { + "Name": "Der O.G.", + "StableDiffusionModel": "Nacken/ki-kunst-kirsten-kloeckner-colab", + "PromptFormat": "{0} kkkk" + }, + { + "Name": "SDXL 18000", + "StableDiffusionModel": "Nacken/kkk-sdxl-18000", + "PromptFormat": "kkkk {0}" + } + ], "ConnectionStrings": { "Default": "" }