From 8b5aed7a2b0ccf36ae5169f3f7940a5b8d08845c Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Wed, 21 Aug 2024 01:21:03 +0200 Subject: [PATCH] refac --- backend/apps/images/main.py | 18 +- src/lib/apis/images/index.ts | 290 +------- .../components/admin/Settings/Images.svelte | 632 +++++++++--------- 3 files changed, 329 insertions(+), 611 deletions(-) diff --git a/backend/apps/images/main.py b/backend/apps/images/main.py index 4db887f61..eea8bc2d5 100644 --- a/backend/apps/images/main.py +++ b/backend/apps/images/main.py @@ -37,6 +37,7 @@ from config import ( AUTOMATIC1111_API_AUTH, COMFYUI_BASE_URL, COMFYUI_WORKFLOW, + COMFYUI_WORKFLOW_NODES, IMAGES_OPENAI_API_BASE_URL, IMAGES_OPENAI_API_KEY, IMAGE_GENERATION_MODEL, @@ -75,6 +76,7 @@ app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL app.state.config.COMFYUI_WORKFLOW = COMFYUI_WORKFLOW +app.state.config.COMFYUI_WORKFLOW_NODES = COMFYUI_WORKFLOW_NODES app.state.config.IMAGE_SIZE = IMAGE_SIZE app.state.config.IMAGE_STEPS = IMAGE_STEPS @@ -211,9 +213,9 @@ def get_image_model(): class ImageConfigForm(BaseModel): - model: str - size: str - steps: int + MODEL: str + IMAGE_SIZE: str + IMAGE_STEPS: int @app.get("/image/config") @@ -227,19 +229,19 @@ async def get_image_config(user=Depends(get_admin_user)): @app.post("/image/config/update") async def update_image_config(form_data: ImageConfigForm, user=Depends(get_admin_user)): - app.state.config.MODEL = form_data.model + app.state.config.MODEL = form_data.MODEL pattern = r"^\d+x\d+$" - if re.match(pattern, form_data.size): - app.state.config.IMAGE_SIZE = form_data.size + if re.match(pattern, form_data.IMAGE_SIZE): + app.state.config.IMAGE_SIZE = form_data.IMAGE_SIZE else: raise HTTPException( status_code=400, detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 512x512)."), ) - if form_data.steps >= 0: - app.state.config.IMAGE_STEPS = form_data.steps + if form_data.IMAGE_STEPS >= 0: + app.state.config.IMAGE_STEPS = form_data.IMAGE_STEPS else: raise HTTPException( status_code=400, diff --git a/src/lib/apis/images/index.ts b/src/lib/apis/images/index.ts index 3f624704e..ee5cda7f2 100644 --- a/src/lib/apis/images/index.ts +++ b/src/lib/apis/images/index.ts @@ -1,6 +1,6 @@ import { IMAGES_API_BASE_URL } from '$lib/constants'; -export const getImageGenerationConfig = async (token: string = '') => { +export const getConfig = async (token: string = '') => { let error = null; const res = await fetch(`${IMAGES_API_BASE_URL}/config`, { @@ -32,11 +32,7 @@ export const getImageGenerationConfig = async (token: string = '') => { return res; }; -export const updateImageGenerationConfig = async ( - token: string = '', - engine: string, - enabled: boolean -) => { +export const updateConfig = async (token: string = '', config: object) => { let error = null; const res = await fetch(`${IMAGES_API_BASE_URL}/config/update`, { @@ -47,8 +43,7 @@ export const updateImageGenerationConfig = async ( ...(token && { authorization: `Bearer ${token}` }) }, body: JSON.stringify({ - engine, - enabled + ...config }) }) .then(async (res) => { @@ -72,10 +67,10 @@ export const updateImageGenerationConfig = async ( return res; }; -export const getOpenAIConfig = async (token: string = '') => { +export const getImageGenerationConfig = async (token: string = '') => { let error = null; - const res = await fetch(`${IMAGES_API_BASE_URL}/openai/config`, { + const res = await fetch(`${IMAGES_API_BASE_URL}/image/config`, { method: 'GET', headers: { Accept: 'application/json', @@ -104,20 +99,17 @@ export const getOpenAIConfig = async (token: string = '') => { return res; }; -export const updateOpenAIConfig = async (token: string = '', url: string, key: string) => { +export const updateImageGenerationConfig = async (token: string = '', config: object) => { let error = null; - const res = await fetch(`${IMAGES_API_BASE_URL}/openai/config/update`, { + const res = await fetch(`${IMAGES_API_BASE_URL}/image/config/update`, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...(token && { authorization: `Bearer ${token}` }) }, - body: JSON.stringify({ - url: url, - key: key - }) + body: JSON.stringify({ ...config }) }) .then(async (res) => { if (!res.ok) throw await res.json(); @@ -140,205 +132,6 @@ export const updateOpenAIConfig = async (token: string = '', url: string, key: s return res; }; -export const getImageGenerationEngineUrls = async (token: string = '') => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/url`, { - method: 'GET', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - } - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res; -}; - -export const updateImageGenerationEngineUrls = async (token: string = '', urls: object = {}) => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/url/update`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - }, - body: JSON.stringify({ - ...urls - }) - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res; -}; - -export const getImageSize = async (token: string = '') => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/size`, { - method: 'GET', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - } - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.IMAGE_SIZE; -}; - -export const updateImageSize = async (token: string = '', size: string) => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/size/update`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - }, - body: JSON.stringify({ - size: size - }) - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.IMAGE_SIZE; -}; - -export const getImageSteps = async (token: string = '') => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/steps`, { - method: 'GET', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - } - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.IMAGE_STEPS; -}; - -export const updateImageSteps = async (token: string = '', steps: number) => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/steps/update`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - }, - body: JSON.stringify({ steps }) - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.IMAGE_STEPS; -}; - export const getImageGenerationModels = async (token: string = '') => { let error = null; @@ -371,73 +164,6 @@ export const getImageGenerationModels = async (token: string = '') => { return res; }; -export const getDefaultImageGenerationModel = async (token: string = '') => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/models/default`, { - method: 'GET', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - } - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.model; -}; - -export const updateDefaultImageGenerationModel = async (token: string = '', model: string) => { - let error = null; - - const res = await fetch(`${IMAGES_API_BASE_URL}/models/default/update`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...(token && { authorization: `Bearer ${token}` }) - }, - body: JSON.stringify({ - model: model - }) - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - return res.json(); - }) - .catch((err) => { - console.log(err); - if ('detail' in err) { - error = err.detail; - } else { - error = 'Server connection failed'; - } - return null; - }); - - if (error) { - throw error; - } - - return res.model; -}; - export const imageGenerations = async (token: string = '', prompt: string) => { let error = null; diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index 12451ef7d..2748b2b10 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -2,23 +2,16 @@ import { toast } from 'svelte-sonner'; import { createEventDispatcher, onMount, getContext } from 'svelte'; - import { config, user } from '$lib/stores'; + import { config as backendConfig, user } from '$lib/stores'; + + import { getBackendConfig } from '$lib/apis'; import { getImageGenerationModels, - getDefaultImageGenerationModel, - updateDefaultImageGenerationModel, - getImageSize, getImageGenerationConfig, updateImageGenerationConfig, - getImageGenerationEngineUrls, - updateImageGenerationEngineUrls, - updateImageSize, - getImageSteps, - updateImageSteps, - getOpenAIConfig, - updateOpenAIConfig + getConfig, + updateConfig } from '$lib/apis/images'; - import { getBackendConfig } from '$lib/apis'; import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; import Switch from '$lib/components/common/Switch.svelte'; const dispatch = createEventDispatcher(); @@ -27,128 +20,78 @@ let loading = false; - let imageGenerationEngine = 'openai'; - let enableImageGeneration = false; + let config = null; + let imageGenerationConfig = null; - let AUTOMATIC1111_BASE_URL = ''; - let AUTOMATIC1111_API_AUTH = ''; - let COMFYUI_BASE_URL = ''; - - let OPENAI_API_BASE_URL = ''; - let OPENAI_API_KEY = ''; - - let selectedModel = ''; let models = null; - let imageSize = ''; - let steps = 50; + let inputFiles = null; const getModels = async () => { models = await getImageGenerationModels(localStorage.token).catch((error) => { toast.error(error); return null; }); - selectedModel = await getDefaultImageGenerationModel(localStorage.token).catch((error) => { - return ''; - }); }; - const updateUrlHandler = async () => { - if (imageGenerationEngine === 'comfyui') { - const res = await updateImageGenerationEngineUrls(localStorage.token, { - COMFYUI_BASE_URL: COMFYUI_BASE_URL - }).catch((error) => { - toast.error(error); - - console.log(error); - return null; - }); - - if (res) { - COMFYUI_BASE_URL = res.COMFYUI_BASE_URL; - - await getModels(); - - if (models) { - toast.success($i18n.t('Server connection verified')); - } - } else { - ({ COMFYUI_BASE_URL } = await getImageGenerationEngineUrls(localStorage.token)); - } - } else { - const res = await updateImageGenerationEngineUrls(localStorage.token, { - AUTOMATIC1111_BASE_URL: AUTOMATIC1111_BASE_URL, - AUTOMATIC1111_API_AUTH: AUTOMATIC1111_API_AUTH - }).catch((error) => { - toast.error(error); - return null; - }); - - if (res) { - AUTOMATIC1111_BASE_URL = res.AUTOMATIC1111_BASE_URL; - AUTOMATIC1111_API_AUTH = res.AUTOMATIC1111_API_AUTH; - - await getModels(); - - if (models) { - toast.success($i18n.t('Server connection verified')); - } - } else { - ({ AUTOMATIC1111_BASE_URL, AUTOMATIC1111_API_AUTH } = await getImageGenerationEngineUrls( - localStorage.token - )); - } - } - }; - const updateImageGeneration = async () => { - const res = await updateImageGenerationConfig( - localStorage.token, - imageGenerationEngine, - enableImageGeneration - ).catch((error) => { + const updateConfigHandler = async () => { + const res = await updateConfig(localStorage.token, config).catch((error) => { toast.error(error); return null; }); if (res) { - imageGenerationEngine = res.engine; - enableImageGeneration = res.enabled; + config = res; } - if (enableImageGeneration) { - config.set(await getBackendConfig(localStorage.token)); + if (config.enabled) { + backendConfig.set(await getBackendConfig()); getModels(); } }; + const saveHandler = async () => { + loading = true; + + await updateConfig(localStorage.token, config).catch((error) => { + toast.error(error); + loading = false; + return null; + }); + + await updateImageGenerationConfig(localStorage.token, imageGenerationConfig).catch((error) => { + toast.error(error); + loading = false; + return null; + }); + + dispatch('save'); + loading = false; + }; + onMount(async () => { if ($user.role === 'admin') { - const res = await getImageGenerationConfig(localStorage.token).catch((error) => { + const res = await getConfig(localStorage.token).catch((error) => { toast.error(error); return null; }); if (res) { - imageGenerationEngine = res.engine ?? 'automatic1111'; - enableImageGeneration = res.enabled; + config = res; } - const URLS = await getImageGenerationEngineUrls(localStorage.token); - AUTOMATIC1111_BASE_URL = URLS.AUTOMATIC1111_BASE_URL; - AUTOMATIC1111_API_AUTH = URLS.AUTOMATIC1111_API_AUTH; - COMFYUI_BASE_URL = URLS.COMFYUI_BASE_URL; - - const config = await getOpenAIConfig(localStorage.token); - - OPENAI_API_KEY = config.OPENAI_API_KEY; - OPENAI_API_BASE_URL = config.OPENAI_API_BASE_URL; - - imageSize = await getImageSize(localStorage.token); - steps = await getImageSteps(localStorage.token); - - if (enableImageGeneration) { + if (config.enabled) { getModels(); } + + const imageConfigRes = await getImageGenerationConfig(localStorage.token).catch((error) => { + toast.error(error); + return null; + }); + + if (imageConfigRes) { + imageGenerationConfig = imageConfigRes; + } } }); @@ -156,205 +99,267 @@
{ - loading = true; - - if (imageGenerationEngine === 'openai') { - await updateOpenAIConfig(localStorage.token, OPENAI_API_BASE_URL, OPENAI_API_KEY); - } - - await updateDefaultImageGenerationModel(localStorage.token, selectedModel); - - await updateImageSize(localStorage.token, imageSize).catch((error) => { - toast.error(error); - return null; - }); - await updateImageSteps(localStorage.token, steps).catch((error) => { - toast.error(error); - return null; - }); - - dispatch('save'); - loading = false; + saveHandler(); }} > -
-
-
{$i18n.t('Image Settings')}
- +
+ {#if config && imageGenerationConfig}
-
-
- {$i18n.t('Image Generation (Experimental)')} -
+
{$i18n.t('Image Settings')}
-
- { - const enabled = e.detail; +
+
+
+ {$i18n.t('Image Generation (Experimental)')} +
- if (enabled) { - if (imageGenerationEngine === 'automatic1111' && AUTOMATIC1111_BASE_URL === '') { - toast.error($i18n.t('AUTOMATIC1111 Base URL is required.')); - enableImageGeneration = false; - } else if (imageGenerationEngine === 'comfyui' && COMFYUI_BASE_URL === '') { - toast.error($i18n.t('ComfyUI Base URL is required.')); - enableImageGeneration = false; - } else if (imageGenerationEngine === 'openai' && OPENAI_API_KEY === '') { - toast.error($i18n.t('OpenAI API Key is required.')); - enableImageGeneration = false; +
+ { + const enabled = e.detail; + + if (enabled) { + if ( + config.engine === 'automatic1111' && + config.automatic1111.AUTOMATIC1111_BASE_URL === '' + ) { + toast.error($i18n.t('AUTOMATIC1111 Base URL is required.')); + config.enabled = false; + } else if ( + config.engine === 'comfyui' && + config.comfyui.COMFYUI_BASE_URL === '' + ) { + toast.error($i18n.t('ComfyUI Base URL is required.')); + config.enabled = false; + } else if (config.engine === 'openai' && config.openai.OPENAI_API_KEY === '') { + toast.error($i18n.t('OpenAI API Key is required.')); + config.enabled = false; + } } - } - updateImageGeneration(); + updateConfigHandler(); + }} + /> +
+
+
+ +
+
{$i18n.t('Image Generation Engine')}
+
+
- -
-
{$i18n.t('Image Generation Engine')}
-
- -
-
-
-
- - {#if imageGenerationEngine === 'automatic1111'} -
{$i18n.t('AUTOMATIC1111 Base URL')}
-
-
- -
- -
- -
- {$i18n.t('Include `--api` flag when running stable-diffusion-webui')} - - {$i18n.t('(e.g. `sh webui.sh --api`)')} - -
- -
{$i18n.t('AUTOMATIC1111 Api Auth String')}
- - -
- {$i18n.t('Include `--api-auth` flag when running stable-diffusion-webui')} - - {$i18n.t('(e.g. `sh webui.sh --api --api-auth username_password`)').replace('_', ':')} - -
- {:else if imageGenerationEngine === 'comfyui'} -
{$i18n.t('ComfyUI Base URL')}
-
-
- -
- -
- {:else if imageGenerationEngine === 'openai'} -
-
{$i18n.t('OpenAI API Config')}
- -
- - - -
-
- {/if} - - {#if enableImageGeneration}
-
-
{$i18n.t('Set Default Model')}
-
-
- {#if imageGenerationEngine === 'openai' && !OPENAI_API_BASE_URL.includes('https://api.openai.com')} +
+ {#if (config?.engine ?? 'automatic1111') === 'automatic1111'} +
+
{$i18n.t('AUTOMATIC1111 Base URL')}
+
+
+ +
+ +
+ +
+ {$i18n.t('Include `--api` flag when running stable-diffusion-webui')} + + {$i18n.t('(e.g. `sh webui.sh --api`)')} + +
+
+ +
+
+ {$i18n.t('AUTOMATIC1111 Api Auth String')} +
+ + +
+ {$i18n.t('Include `--api-auth` flag when running stable-diffusion-webui')} + + {$i18n + .t('(e.g. `sh webui.sh --api --api-auth username_password`)') + .replace('_', ':')} + +
+
+ {:else if config?.engine === 'comfyui'} +
+
{$i18n.t('ComfyUI Base URL')}
+
+
+ +
+ +
+
+ +
+
{$i18n.t('ComfyUI Workflow')}
+ + {#if config.comfyui.COMFYUI_WORKFLOW} +