From 4c9c92e9c805cf671d8c6fc68344ce5b5ff6eb7d Mon Sep 17 00:00:00 2001 From: xModo99 <xmodo999@gmail.com> Date: Sat, 16 Mar 2024 13:21:02 +0000 Subject: [PATCH] [Ai Art] Decouple SD client from cache control --- src/art/artJS.js | 2 +- src/art/genAI/openPose.js | 4 ++-- src/art/genAI/stableDiffusion.js | 35 ++++++++++++++++++++------------ src/endWeek/nextWeek/nextWeek.js | 4 ++-- src/gui/options/options.js | 14 ++++++------- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/art/artJS.js b/src/art/artJS.js index 9973e60eb11..1cdb2551559 100644 --- a/src/art/artJS.js +++ b/src/art/artJS.js @@ -679,7 +679,7 @@ App.Art.aiArtElement = function(slave, imageSize, isEventImage = null) { function updateAndRefresh(index = null) { container.classList.add("refreshing"); - App.Art.GenAI.client.updateSlave(slave, index, isEventImage).then(() => { + App.Art.GenAI.staticCache.updateSlave(slave, index, isEventImage).then(() => { refresh(); }).catch(error => { console.log(error.message || error); diff --git a/src/art/genAI/openPose.js b/src/art/genAI/openPose.js index e2bcaa6ab97..df339675474 100644 --- a/src/art/genAI/openPose.js +++ b/src/art/genAI/openPose.js @@ -17,7 +17,7 @@ App.Art.GenAI.getOpenPoseData = (function() { .then(value => { return value.text(); }).then(obj => { - return App.Art.GenAI.client.renderOpenPoseJSON(obj); + return App.Art.GenAI.sdClient.renderOpenPoseJSON(obj); }); case "PNG": return fetch(`resources/poses/${slave.custom.aiPose.filename}.png`) @@ -49,7 +49,7 @@ App.Art.GenAI.getOpenPoseData = (function() { throw new Error(`Could not find pose in library: ${name}`); } if (!entry.cache) { - entry.cache = await App.Art.GenAI.client.renderOpenPoseJSON(entry.poseData); + entry.cache = await App.Art.GenAI.sdClient.renderOpenPoseJSON(entry.poseData); } return entry.cache; } diff --git a/src/art/genAI/stableDiffusion.js b/src/art/genAI/stableDiffusion.js index 48975e582bd..6e891f8eeb4 100644 --- a/src/art/genAI/stableDiffusion.js +++ b/src/art/genAI/stableDiffusion.js @@ -506,11 +506,26 @@ App.Art.GenAI.StableDiffusionClient = class { return obj.images[0]; }); } +}; + + +App.Art.GenAI.sdClient = new App.Art.GenAI.StableDiffusionClient(); + + +/** + * Determines whether the current passage has the "temporary-images" tag + * @returns {boolean} + */ +function isTemporaryImage() { + return $(`[data-tags*=temporary-images]`).length > 0; +} + +App.Art.GenAI.StaticCaching = class { /** * @param {FC.SlaveState} slave * @param {boolean | null} isEventImage - Whether request is canceled on passage change and which step setting to use. true => V.aiSamplingStepsEvent, false => V.aiSamplingSteps, null => chosen based on passage tags - * @returns {Promise<string>} - Base 64 encoded image (could be a jpeg or png) + * @returns {Promise<string>} - Base 64 encoded image (could be a jpeg, png, or webp) */ async fetchImageForSlave(slave, isEventImage = null) { let steps = V.aiSamplingSteps; @@ -519,17 +534,17 @@ App.Art.GenAI.StableDiffusionClient = class { isEventImage = false; } if (isEventImage === null) { - isEventImage = this.isTemporaryImage(); + isEventImage = isTemporaryImage(); } if (isEventImage === true) { steps = V.aiSamplingStepsEvent; } - const settings = await this.buildStableDiffusionSettings(slave, steps); + const settings = await App.Art.GenAI.sdClient.buildStableDiffusionSettings(slave, steps); const body = JSON.stringify(settings); // set up a passage switch handler to clear queued generation of event and temporary images upon passage change const oldHandler = App.Utils.PassageSwitchHandler.get(); - if (isEventImage || this.isTemporaryImage()) { + if (isEventImage || isTemporaryImage()) { App.Utils.PassageSwitchHandler.set(() => { // find where this request is in the queue let rIndex = App.Art.GenAI.sdQueue.queue.findIndex(r => r.slaveID === slave.ID && r.body === body); @@ -593,17 +608,11 @@ App.Art.GenAI.StableDiffusionClient = class { slave.custom.aiDisplayImageIdx = imagePreexisting; } } - - /** - * Determines whether the current passage has the "temporary-images" tag - * @returns {boolean} - */ - isTemporaryImage() { - return $(`[data-tags*=temporary-images]`).length > 0; - } }; -App.Art.GenAI.client = new App.Art.GenAI.StableDiffusionClient(); +App.Art.GenAI.staticCache = new App.Art.GenAI.StaticCaching(); + + /** * Search slave's existing images for a match with the new image. diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js index 4cc2007b645..96013a19548 100644 --- a/src/endWeek/nextWeek/nextWeek.js +++ b/src/endWeek/nextWeek/nextWeek.js @@ -448,12 +448,12 @@ App.EndWeek.nextWeek = function() { // executing this between DOM loads still picks up the "temporary-images" tag of the event passages, so we'll queue auto regeneration for a DOM to load without the tag. (We're not calling this from the "Main" passage to ensure it isn't over-called by reloading saves) (async () => { const sleep = () => new Promise(r => setTimeout(r, 100)); - while (App.Art.GenAI.client.isTemporaryImage()) { + while (isTemporaryImage()) { await sleep(); } V.slaves.forEach(s => { if ((V.week - s.weekAcquired) % V.aiAutoGenFrequency === 0){ - App.Art.GenAI.client.updateSlave(s, null, false) + App.Art.GenAI.staticCache.updateSlave(s, null, false) .catch(error => { console.log(error.message || error); }); diff --git a/src/gui/options/options.js b/src/gui/options/options.js index 81973925685..d943c552a9b 100644 --- a/src/gui/options/options.js +++ b/src/gui/options/options.js @@ -1334,7 +1334,7 @@ App.UI.artOptions = function() { } const samplerListSpan = App.UI.DOM.makeElement('span', `Fetching options, please wait...`); - App.Art.GenAI.client.getSamplerList().then(list => { + App.Art.GenAI.sdClient.getSamplerList().then(list => { if (list.length === 0) { samplerListSpan.textContent = `Could not fetch valid samplers. Check your configuration.`; samplerListSpan.classList.add('error'); @@ -1381,7 +1381,7 @@ App.UI.artOptions = function() { .addComment("The width of the image."); const rfCheckSpan = App.UI.DOM.makeElement('span', `Validating Restore Faces...`); - App.Art.GenAI.client.canRestoreFaces().then(result => { + App.Art.GenAI.sdClient.canRestoreFaces().then(result => { if (result) { if (V.aiAdetailerFace && V.aiRestoreFaces) { rfCheckSpan.textContent = `Do not use Restore Faces and ADetailer Restore Face at the same time. Pick one.`; @@ -1399,7 +1399,7 @@ App.UI.artOptions = function() { .addComment(App.UI.DOM.combineNodes("Use a model to restore faces after the image has been generated. May result in 'samey' faces. ", rfCheckSpan)); const adCheckSpan = App.UI.DOM.makeElement('span', `Validating ADetailer setup...`); - App.Art.GenAI.client.hasAdetailer().then(result => { + App.Art.GenAI.sdClient.hasAdetailer().then(result => { if (result) { adCheckSpan.textContent = ""; } else { @@ -1419,7 +1419,7 @@ App.UI.artOptions = function() { .addComment("Scales the dimensions of the image by this factor. Defaults to 1.75."); const upscalerListSpan = App.UI.DOM.makeElement('span', `Fetching options, please wait...`); - App.Art.GenAI.client.getUpscalerList().then(list => { + App.Art.GenAI.sdClient.getUpscalerList().then(list => { if (list.length === 0) { upscalerListSpan.textContent = `Could not fetch valid upscalers. Check your configuration.`; upscalerListSpan.classList.add('error'); @@ -1436,7 +1436,7 @@ App.UI.artOptions = function() { } const opCheckSpan = App.UI.DOM.makeElement('span', `Validating ControlNet and OpenPose setup...`); - App.Art.GenAI.client.hasOpenPose().then(result => { + App.Art.GenAI.sdClient.hasOpenPose().then(result => { if (result) { opCheckSpan.textContent = ""; } else { @@ -1449,7 +1449,7 @@ App.UI.artOptions = function() { .addComment(App.UI.DOM.combineNodes(`Use the ControlNet extension's OpenPose module to strictly control slave poses. `, opCheckSpan)); if (V.aiOpenPose) { const opModelList = App.UI.DOM.makeElement('span', `Fetching options, please wait...`); - App.Art.GenAI.client.getOpenPoseModelList().then(list => { + App.Art.GenAI.sdClient.getOpenPoseModelList().then(list => { if (list.length === 0) { opModelList.textContent = `Could not fetch valid OpenPose models. Check your configuration.`; opModelList.classList.add('error'); @@ -1491,7 +1491,7 @@ App.UI.artOptions = function() { }) .addButton("Regenerate images for all slaves", () => { // queue all slaves for regeneration in the background - V.slaves.forEach(s => App.Art.GenAI.client.updateSlave(s) + V.slaves.forEach(s => App.Art.GenAI.staticCache.updateSlave(s) .catch(error => { console.log(error.message || error); })); -- GitLab