Merge pull request #1215 from cmdr2/beta

Beta
This commit is contained in:
cmdr2 2023-04-27 15:50:06 +05:30 committed by GitHub
commit 9a01e917c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 479 additions and 339 deletions

View File

@ -2,7 +2,7 @@
## v2.5 ## v2.5
### Major Changes ### Major Changes
- **Nearly twice as fast** - significantly faster speed of image generation. We're now pretty close to automatic1111's speed. Code contributions are welcome to make our project even faster: https://github.com/easydiffusion/sdkit/#is-it-fast - **Nearly twice as fast** - significantly faster speed of image generation. Code contributions are welcome to make our project even faster: https://github.com/easydiffusion/sdkit/#is-it-fast
- **Mac M1/M2 support** - Experimental support for Mac M1/M2. Thanks @michaelgallacher, @JeLuf and vishae. - **Mac M1/M2 support** - Experimental support for Mac M1/M2. Thanks @michaelgallacher, @JeLuf and vishae.
- **Full support for Stable Diffusion 2.1 (including CPU)** - supports loading v1.4 or v2.0 or v2.1 models seamlessly. No need to enable "Test SD2", and no need to add `sd2_` to your SD 2.0 model file names. Works on CPU as well. - **Full support for Stable Diffusion 2.1 (including CPU)** - supports loading v1.4 or v2.0 or v2.1 models seamlessly. No need to enable "Test SD2", and no need to add `sd2_` to your SD 2.0 model file names. Works on CPU as well.
- **Memory optimized Stable Diffusion 2.1** - you can now use Stable Diffusion 2.1 models, with the same low VRAM optimizations that we've always had for SD 1.4. Please note, the SD 2.0 and 2.1 models require more GPU and System RAM, as compared to the SD 1.4 and 1.5 models. - **Memory optimized Stable Diffusion 2.1** - you can now use Stable Diffusion 2.1 models, with the same low VRAM optimizations that we've always had for SD 1.4. Please note, the SD 2.0 and 2.1 models require more GPU and System RAM, as compared to the SD 1.4 and 1.5 models.
@ -21,7 +21,10 @@
Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed. Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed.
### Detailed changelog ### Detailed changelog
* 2.5.34 - 22 Apr 2023 - Don't start the browser in an incognito new profile (on Windows). Thanks @JeLuf.
* 2.5.33 - 21 Apr 2023 - Install PyTorch 2.0 on new installations (on Windows and Linux).
* 2.5.32 - 19 Apr 2023 - Automatically check for black images, and set full-precision if necessary (for attn). This means custom models based on Stable Diffusion v2.1 will just work, without needing special command-line arguments or editing of yaml config files. * 2.5.32 - 19 Apr 2023 - Automatically check for black images, and set full-precision if necessary (for attn). This means custom models based on Stable Diffusion v2.1 will just work, without needing special command-line arguments or editing of yaml config files.
* 2.5.32 - 18 Apr 2023 - Automatic support for AMD graphics cards on Linux. Thanks @DianaNites and @JeLuf.
* 2.5.31 - 10 Apr 2023 - Reduce VRAM usage while upscaling. * 2.5.31 - 10 Apr 2023 - Reduce VRAM usage while upscaling.
* 2.5.31 - 6 Apr 2023 - Allow seeds upto `4,294,967,295`. Thanks @ogmaresca. * 2.5.31 - 6 Apr 2023 - Allow seeds upto `4,294,967,295`. Thanks @ogmaresca.
* 2.5.31 - 6 Apr 2023 - Buttons to show the previous/next image in the image popup. Thanks @ogmaresca. * 2.5.31 - 6 Apr 2023 - Buttons to show the previous/next image in the image popup. Thanks @ogmaresca.

View File

@ -18,7 +18,7 @@ os_name = platform.system()
modules_to_check = { modules_to_check = {
"torch": ("1.11.0", "1.13.1", "2.0.0"), "torch": ("1.11.0", "1.13.1", "2.0.0"),
"torchvision": ("0.12.0", "0.14.1", "0.15.1"), "torchvision": ("0.12.0", "0.14.1", "0.15.1"),
"sdkit": "1.0.80", "sdkit": "1.0.81",
"stable-diffusion-sdkit": "2.1.4", "stable-diffusion-sdkit": "2.1.4",
"rich": "12.6.0", "rich": "12.6.0",
"uvicorn": "0.19.0", "uvicorn": "0.19.0",

45
scripts/get_config.py Normal file
View File

@ -0,0 +1,45 @@
import os
import argparse
# The config file is in the same directory as this script
config_directory = os.path.dirname(__file__)
config_yaml = os.path.join(config_directory, "config.yaml")
config_json = os.path.join(config_directory, "config.json")
parser = argparse.ArgumentParser(description='Get values from config file')
parser.add_argument('--default', dest='default', action='store',
help='default value, to be used if the setting is not defined in the config file')
parser.add_argument('key', metavar='key', nargs='+',
help='config key to return')
args = parser.parse_args()
if os.path.isfile(config_yaml):
import yaml
with open(config_yaml, 'r') as configfile:
try:
config = yaml.safe_load(configfile)
except Exception as e:
print(e)
exit()
elif os.path.isfile(config_json):
import json
with open(config_json, 'r') as configfile:
try:
config = json.load(configfile)
except Exception as e:
print(e)
exit()
else:
config = {}
for k in args.key:
if k in config:
config = config[k]
else:
if args.default != None:
print(args.default)
exit()
print(config)

View File

@ -12,6 +12,16 @@ if exist "scripts\user_config.bat" (
@call scripts\user_config.bat @call scripts\user_config.bat
) )
if exist "stable-diffusion\env" (
@set PYTHONPATH=%PYTHONPATH%;%cd%\stable-diffusion\env\lib\site-packages
)
if exist "scripts\get_config.py" (
@FOR /F "tokens=* USEBACKQ" %%F IN (`python scripts\get_config.py --default=main update_branch`) DO (
@SET update_branch=%%F
)
)
if "%update_branch%"=="" ( if "%update_branch%"=="" (
set update_branch=main set update_branch=main
) )
@ -58,6 +68,7 @@ if "%update_branch%"=="" (
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y @copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y @copy sd-ui-files\scripts\check_modules.py scripts\ /Y
@copy sd-ui-files\scripts\check_models.py scripts\ /Y @copy sd-ui-files\scripts\check_models.py scripts\ /Y
@copy sd-ui-files\scripts\get_config.py scripts\ /Y
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y @copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y @copy "sd-ui-files\scripts\Developer Console.cmd" . /Y

View File

@ -4,6 +4,8 @@ source ./scripts/functions.sh
printf "\n\nEasy Diffusion\n\n" printf "\n\nEasy Diffusion\n\n"
export PYTHONNOUSERSITE=y
if [ -f "scripts/config.sh" ]; then if [ -f "scripts/config.sh" ]; then
source scripts/config.sh source scripts/config.sh
fi fi
@ -12,6 +14,11 @@ if [ -f "scripts/user_config.sh" ]; then
source scripts/user_config.sh source scripts/user_config.sh
fi fi
export PYTHONPATH=$(pwd)/installer_files/env/lib/python3.8/site-packages:$(pwd)/stable-diffusion/env/lib/python3.8/site-packages
if [ -f "scripts/get_config.py" ]; then
export update_branch="$( python scripts/get_config.py --default=main update_branch )"
fi
if [ "$update_branch" == "" ]; then if [ "$update_branch" == "" ]; then
export update_branch="main" export update_branch="main"
@ -44,6 +51,7 @@ cp sd-ui-files/scripts/on_sd_start.sh scripts/
cp sd-ui-files/scripts/bootstrap.sh scripts/ cp sd-ui-files/scripts/bootstrap.sh scripts/
cp sd-ui-files/scripts/check_modules.py scripts/ cp sd-ui-files/scripts/check_modules.py scripts/
cp sd-ui-files/scripts/check_models.py scripts/ cp sd-ui-files/scripts/check_models.py scripts/
cp sd-ui-files/scripts/get_config.py scripts/
cp sd-ui-files/scripts/start.sh . cp sd-ui-files/scripts/start.sh .
cp sd-ui-files/scripts/developer_console.sh . cp sd-ui-files/scripts/developer_console.sh .
cp sd-ui-files/scripts/functions.sh scripts/ cp sd-ui-files/scripts/functions.sh scripts/

View File

@ -6,9 +6,10 @@
@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y @copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y @copy sd-ui-files\scripts\check_modules.py scripts\ /Y
@copy sd-ui-files\scripts\check_models.py scripts\ /Y @copy sd-ui-files\scripts\check_models.py scripts\ /Y
@copy sd-ui-files\scripts\get_config.py scripts\ /Y
if exist "%cd%\profile" ( if exist "%cd%\profile" (
set USERPROFILE=%cd%\profile set HF_HOME=%cd%\profile\.cache\huggingface
) )
@rem set the correct installer path (current vs legacy) @rem set the correct installer path (current vs legacy)
@ -103,14 +104,25 @@ call python --version
@cd .. @cd ..
@set SD_UI_PATH=%cd%\ui @set SD_UI_PATH=%cd%\ui
@FOR /F "tokens=* USEBACKQ" %%F IN (`python scripts\get_config.py --default=9000 net listen_port`) DO (
@SET ED_BIND_PORT=%%F
)
@FOR /F "tokens=* USEBACKQ" %%F IN (`python scripts\get_config.py --default=False net listen_to_network`) DO (
if "%%F" EQU "True" (
@SET ED_BIND_IP=0.0.0.0
) else (
@SET ED_BIND_IP=127.0.0.1
)
)
@cd stable-diffusion @cd stable-diffusion
@rem set any overrides @rem set any overrides
set HF_HUB_DISABLE_SYMLINKS_WARNING=true set HF_HUB_DISABLE_SYMLINKS_WARNING=true
@if NOT DEFINED SD_UI_BIND_PORT set SD_UI_BIND_PORT=9000 @uvicorn main:server_api --app-dir "%SD_UI_PATH%" --port %ED_BIND_PORT% --host %ED_BIND_IP% --log-level error
@if NOT DEFINED SD_UI_BIND_IP set SD_UI_BIND_IP=0.0.0.0
@uvicorn main:server_api --app-dir "%SD_UI_PATH%" --port %SD_UI_BIND_PORT% --host %SD_UI_BIND_IP% --log-level error
@pause @pause

View File

@ -5,6 +5,7 @@ cp sd-ui-files/scripts/on_env_start.sh scripts/
cp sd-ui-files/scripts/bootstrap.sh scripts/ cp sd-ui-files/scripts/bootstrap.sh scripts/
cp sd-ui-files/scripts/check_modules.py scripts/ cp sd-ui-files/scripts/check_modules.py scripts/
cp sd-ui-files/scripts/check_models.py scripts/ cp sd-ui-files/scripts/check_models.py scripts/
cp sd-ui-files/scripts/get_config.py scripts/
source ./scripts/functions.sh source ./scripts/functions.sh
@ -74,8 +75,17 @@ python --version
cd .. cd ..
export SD_UI_PATH=`pwd`/ui export SD_UI_PATH=`pwd`/ui
export ED_BIND_PORT="$( python scripts/get_config.py --default=9000 net listen_port )"
case "$( python scripts/get_config.py --default=False net listen_to_network )" in
"True")
export ED_BIND_IP=0.0.0.0
;;
"False")
export ED_BIND_IP=127.0.0.1
;;
esac
cd stable-diffusion cd stable-diffusion
uvicorn main:server_api --app-dir "$SD_UI_PATH" --port ${SD_UI_BIND_PORT:-9000} --host ${SD_UI_BIND_IP:-0.0.0.0} --log-level error uvicorn main:server_api --app-dir "$SD_UI_PATH" --port "$ED_BIND_PORT" --host "$ED_BIND_IP" --log-level error
read -p "Press any key to continue" read -p "Press any key to continue"

View File

@ -101,51 +101,6 @@ def setConfig(config):
except: except:
log.error(traceback.format_exc()) log.error(traceback.format_exc())
try: # config.bat
config_bat_path = os.path.join(CONFIG_DIR, "config.bat")
config_bat = []
if "update_branch" in config:
config_bat.append(f"@set update_branch={config['update_branch']}")
config_bat.append(f"@set SD_UI_BIND_PORT={config['net']['listen_port']}")
bind_ip = "0.0.0.0" if config["net"]["listen_to_network"] else "127.0.0.1"
config_bat.append(f"@set SD_UI_BIND_IP={bind_ip}")
# Preserve these variables if they are set
for var in PRESERVE_CONFIG_VARS:
if os.getenv(var) is not None:
config_bat.append(f"@set {var}={os.getenv(var)}")
if len(config_bat) > 0:
with open(config_bat_path, "w", encoding="utf-8") as f:
f.write("\n".join(config_bat))
except:
log.error(traceback.format_exc())
try: # config.sh
config_sh_path = os.path.join(CONFIG_DIR, "config.sh")
config_sh = ["#!/bin/bash"]
if "update_branch" in config:
config_sh.append(f"export update_branch={config['update_branch']}")
config_sh.append(f"export SD_UI_BIND_PORT={config['net']['listen_port']}")
bind_ip = "0.0.0.0" if config["net"]["listen_to_network"] else "127.0.0.1"
config_sh.append(f"export SD_UI_BIND_IP={bind_ip}")
# Preserve these variables if they are set
for var in PRESERVE_CONFIG_VARS:
if os.getenv(var) is not None:
config_bat.append(f'export {var}="{shlex.quote(os.getenv(var))}"')
if len(config_sh) > 1:
with open(config_sh_path, "w", encoding="utf-8") as f:
f.write("\n".join(config_sh))
except:
log.error(traceback.format_exc())
def save_to_config(ckpt_model_name, vae_model_name, hypernetwork_model_name, vram_usage_level): def save_to_config(ckpt_model_name, vae_model_name, hypernetwork_model_name, vram_usage_level):
config = getConfig() config = getConfig()
if "model" not in config: if "model" not in config:

View File

@ -30,7 +30,7 @@
<h1> <h1>
<img id="logo_img" src="/media/images/icon-512x512.png" > <img id="logo_img" src="/media/images/icon-512x512.png" >
Easy Diffusion Easy Diffusion
<small>v2.5.33 <span id="updateBranchLabel"></span></small> <small>v2.5.34 <span id="updateBranchLabel"></span></small>
</h1> </h1>
</div> </div>
<div id="server-status"> <div id="server-status">

View File

@ -720,9 +720,140 @@ Array.prototype.addEventListener = function(method, callback) {
const originalFunction = this[method] const originalFunction = this[method]
if (originalFunction) { if (originalFunction) {
this[method] = function() { this[method] = function() {
console.log(`Array.${method}()`, arguments)
originalFunction.apply(this, arguments) originalFunction.apply(this, arguments)
callback.apply(this, arguments) callback.apply(this, arguments)
} }
} }
} }
/**
* @typedef {object} TabOpenDetails
* @property {HTMLElement} contentElement
* @property {HTMLElement} labelElement
* @property {number} timesOpened
* @property {boolean} firstOpen
*/
/**
* @typedef {object} CreateTabRequest
* @property {string} id
* @property {string | Node | (() => (string | Node))} label
* Label text or an HTML element
* @property {string} icon
* @property {string | Node | Promise<string | Node> | (() => (string | Node | Promise<string | Node>)) | undefined} content
* HTML string or HTML element
* @property {((TabOpenDetails, Event) => (undefined | string | Node | Promise<string | Node>)) | undefined} onOpen
* If an HTML string or HTML element is returned, then that will replace the tab content
* @property {string | undefined} css
*/
/**
* @param {CreateTabRequest} request
*/
function createTab(request) {
if (!request?.id) {
console.error('createTab() error - id is required', Error().stack)
return
}
if (!request.label) {
console.error('createTab() error - label is required', Error().stack)
return
}
if (!request.icon) {
console.error('createTab() error - icon is required', Error().stack)
return
}
if (!request.content && !request.onOpen) {
console.error('createTab() error - content or onOpen required', Error().stack)
return
}
const tabsContainer = document.querySelector('.tab-container')
if (!tabsContainer) {
return
}
const tabsContentWrapper = document.querySelector('#tab-content-wrapper')
if (!tabsContentWrapper) {
return
}
// console.debug('creating tab: ', request)
if (request.css) {
document.querySelector('body').insertAdjacentElement(
'beforeend',
createElement('style', { id: `tab-${request.id}-css` }, undefined, request.css),
)
}
const label = typeof request.label === 'function' ? request.label() : request.label
const labelElement = label instanceof Node ? label : createElement('span', undefined, undefined, label)
const tab = createElement(
'span',
{ id: `tab-${request.id}`, 'data-times-opened': 0 },
['tab'],
createElement(
'span',
undefined,
undefined,
[
createElement(
'i',
{ style: 'margin-right: 0.25em' },
['fa-solid', `${request.icon.startsWith('fa-') ? '' : 'fa-'}${request.icon}`, 'icon'],
),
labelElement,
],
)
)
tabsContainer.insertAdjacentElement('beforeend', tab)
const wrapper = createElement('div', { id: request.id }, ['tab-content-inner'], 'Loading..')
const tabContent = createElement('div', { id: `tab-content-${request.id}` }, ['tab-content'], wrapper)
tabsContentWrapper.insertAdjacentElement('beforeend', tabContent)
linkTabContents(tab)
function replaceContent(resultFactory) {
if (resultFactory === undefined || resultFactory === null) {
return
}
const result = typeof resultFactory === 'function' ? resultFactory() : resultFactory
if (result instanceof Promise) {
result.then(replaceContent)
} else if (result instanceof Node) {
wrapper.replaceChildren(result)
} else {
wrapper.innerHTML = result
}
}
replaceContent(request.content)
tab.addEventListener('click', (e) => {
const timesOpened = +(tab.dataset.timesOpened || 0) + 1
tab.dataset.timesOpened = timesOpened
if (request.onOpen) {
const result = request.onOpen(
{
contentElement: wrapper,
labelElement,
timesOpened,
firstOpen: timesOpened === 1,
},
e,
)
replaceContent(result)
}
})
}

View File

@ -130,34 +130,11 @@
} }
drawDiagram(fn) drawDiagram(fn)
} }
createTab({
/////////////////////// Tab implementation id: 'merge',
document.querySelector('.tab-container')?.insertAdjacentHTML('beforeend', ` icon: 'fa-code-merge',
<span id="tab-merge" class="tab"> label: 'Merge models',
<span><i class="fa fa-code-merge icon"></i> Merge models</span> css: `
</span>
`)
document.querySelector('#tab-content-wrapper')?.insertAdjacentHTML('beforeend', `
<div id="tab-content-merge" class="tab-content">
<div id="merge" class="tab-content-inner">
Loading..
</div>
</div>
`)
const tabMerge = document.querySelector('#tab-merge')
if (tabMerge) {
linkTabContents(tabMerge)
}
const merge = document.querySelector('#merge')
if (!merge) {
// merge tab not found, dont exec plugin code.
return
}
document.querySelector('body').insertAdjacentHTML('beforeend', `
<style>
#tab-content-merge .tab-content-inner { #tab-content-merge .tab-content-inner {
max-width: 100%; max-width: 100%;
padding: 10pt; padding: 10pt;
@ -233,11 +210,8 @@
} }
.merge-container #merge-warning { .merge-container #merge-warning {
color: rgb(153, 153, 153); color: rgb(153, 153, 153);
} }`,
</style> content: `
`)
merge.innerHTML = `
<div class="merge-container panel-box"> <div class="merge-container panel-box">
<div class="merge-input"> <div class="merge-input">
<p><label for="#mergeModelA">Select Model A:</label></p> <p><label for="#mergeModelA">Select Model A:</label></p>
@ -327,7 +301,11 @@
<div class="merge-buttons"> <div class="merge-buttons">
<button id="merge-button" class="primaryButton">Merge models</button> <button id="merge-button" class="primaryButton">Merge models</button>
</div> </div>
</div>` </div>`,
onOpen: ({ firstOpen }) => {
if (!firstOpen) {
return
}
const tabSettingsSingle = document.querySelector('#tab-merge-opts-single') const tabSettingsSingle = document.querySelector('#tab-merge-opts-single')
const tabSettingsBatch = document.querySelector('#tab-merge-opts-batch') const tabSettingsBatch = document.querySelector('#tab-merge-opts-batch')
@ -454,5 +432,7 @@
hypernetworkModelField.innerHTML = '' hypernetworkModelField.innerHTML = ''
await getModels() await getModels()
}) })
},
})
})() })()

View File

@ -9,41 +9,21 @@
} }
} }
document.querySelector('.tab-container')?.insertAdjacentHTML('beforeend', ` createTab({
<span id="tab-news" class="tab"> id: 'news',
<span><i class="fa fa-bolt icon"></i> What's new?</span> icon: 'fa-bolt',
</span> label: "What's new",
`) css: `
document.querySelector('#tab-content-wrapper')?.insertAdjacentHTML('beforeend', `
<div id="tab-content-news" class="tab-content">
<div id="news" class="tab-content-inner">
Loading..
</div>
</div>
`)
const tabNews = document.querySelector('#tab-news')
if (tabNews) {
linkTabContents(tabNews)
}
const news = document.querySelector('#news')
if (!news) {
// news tab not found, dont exec plugin code.
return
}
document.querySelector('body').insertAdjacentHTML('beforeend', `
<style>
#tab-content-news .tab-content-inner { #tab-content-news .tab-content-inner {
max-width: 100%; max-width: 100%;
text-align: left; text-align: left;
padding: 10pt; padding: 10pt;
} }
</style> `,
`) onOpen: async ({ firstOpen }) => {
if (firstOpen) {
const loadMarkedScriptPromise = loadScript('/media/js/marked.min.js')
loadScript('/media/js/marked.min.js').then(async function() {
let appConfig = await fetch('/get/app_config') let appConfig = await fetch('/get/app_config')
if (!appConfig.ok) { if (!appConfig.ok) {
console.error('[release-notes] Failed to get app_config.') console.error('[release-notes] Failed to get app_config.')
@ -59,6 +39,11 @@
return return
} }
releaseNotes = await releaseNotes.text() releaseNotes = await releaseNotes.text()
news.innerHTML = marked.parse(releaseNotes)
await loadMarkedScriptPromise
return marked.parse(releaseNotes)
}
},
}) })
})() })()