-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for caching
- Loading branch information
Showing
65 changed files
with
4,896 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,3 +169,9 @@ cython_debug/ | |
|
||
# PyPI configuration file | ||
.pypirc | ||
|
||
# Other | ||
*.npz | ||
test/output | ||
uv.lock | ||
musubi_tuner_gui.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
[submodule "musubi-tuner"] | ||
path = musubi-tuner | ||
url = https://github.com/kohya-ss/musubi-tuner.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
3.10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,57 @@ | ||
# musubi-tuner-gui | ||
GUI for the new musubi-tuner | ||
|
||
Anyone who want to contribute to the GUI code are welcome. I will make this one use uv: https://github.com/astral-sh/uv as the python package manager to facilitate cross platform use. Will aim to support Linux and Windows. Not sure about MacOS. Those interested to the MacOS support side are welcome to contribute code to ensure proper support. | ||
GUI for the new musubi-tuner. | ||
|
||
Work until a viable Minimum Viable Product is ready will be found in the dev branch. Main will remain empty until contributors feel there is something work merging for a 1st release. | ||
Contributions to the GUI code are welcome. This project uses [uv](https://github.com/astral-sh/uv) as the Python package manager to facilitate cross-platform use. The aim is to support Linux and Windows, with potential MacOS support pending contributions. | ||
|
||
Work towards a Minimum Viable Product (MVP) will be done in the `dev` branch. The `main` branch will remain empty until there is a consensus on a viable first release. | ||
|
||
## Installation | ||
|
||
The installation process will be improved and automated in the future. For now, follow these steps: | ||
|
||
1. Install uv (if not already present on your OS). | ||
|
||
### Linux/MacOS | ||
|
||
```sh | ||
curl -LsSf https://astral.sh/uv/install.sh | sh | ||
``` | ||
|
||
### Windows | ||
|
||
```powershell | ||
powershell -c "irm https://astral.sh/uv/install.ps1 | iex" | ||
``` | ||
|
||
To add `C:\Users\berna\.local\bin` to your PATH, either restart your system or run: | ||
|
||
#### CMD | ||
|
||
```cmd | ||
set Path=C:\Users\berna\.local\bin;%Path% | ||
``` | ||
|
||
#### Powershell | ||
|
||
```powershell | ||
$env:Path = "C:\Users\berna\.local\bin;$env:Path" | ||
``` | ||
|
||
## Starting the GUI | ||
|
||
```shell | ||
git clone --recursive https://github.com/bmaltais/musubi-tuner-gui.git | ||
cd musubi-tuner-gui | ||
uv run gui.py | ||
``` | ||
|
||
## Caching generation | ||
|
||
Until the GUI automastically ng, you have to do it manuallUse the followingtwo commands you ache images and txt prompts:e | ||
|
||
```shell | ||
uv run ./musubi-tuner/cache_latents.py --dataset_config "./test/config/dataset.toml" --vae "C:\Users\berna\Downloads\pytorch_model.pt" --vae_chunk_size 32 --vae_tiling | ||
|
||
uv run ./musubi-tuner/cache_text_encoder_outputs.py --dataset_config "./test/config/dataset.toml" --text_encoder1 "C:\Users\berna\Downloads\llava_llama3_fp16.safetensors" --text_encoder2 "C:\Users\berna\Downloads\clip_l.safetensors" --batch_size 1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
var re_num = /^[.\d]+$/; | ||
var re_emoji = /[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u; | ||
|
||
var original_lines = {}; | ||
var translated_lines = {}; | ||
|
||
function hasLocalization() { | ||
return window.localization && Object.keys(window.localization).length > 0; | ||
} | ||
|
||
function textNodesUnder(el) { | ||
var n, a = [], walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false); | ||
while ((n = walk.nextNode())) a.push(n); | ||
return a; | ||
} | ||
|
||
function canBeTranslated(node, text) { | ||
if (!text) return false; | ||
if (!node.parentElement) return false; | ||
|
||
var parentType = node.parentElement.nodeName; | ||
if (parentType == 'SCRIPT' || parentType == 'STYLE' || parentType == 'TEXTAREA') return false; | ||
|
||
if (parentType == 'OPTION' || parentType == 'SPAN') { | ||
var pnode = node; | ||
for (var level = 0; level < 4; level++) { | ||
pnode = pnode.parentElement; | ||
if (!pnode) break; | ||
} | ||
} | ||
|
||
if (re_num.test(text)) return false; | ||
if (re_emoji.test(text)) return false; | ||
return true; | ||
} | ||
|
||
function getTranslation(text) { | ||
if (!text) return undefined; | ||
|
||
if (translated_lines[text] === undefined) { | ||
original_lines[text] = 1; | ||
} | ||
|
||
var tl = localization[text]; | ||
if (tl !== undefined) { | ||
translated_lines[tl] = 1; | ||
} | ||
|
||
return tl; | ||
} | ||
|
||
function processTextNode(node) { | ||
var text = node.textContent.trim(); | ||
|
||
if (!canBeTranslated(node, text)) return; | ||
|
||
var tl = getTranslation(text); | ||
if (tl !== undefined) { | ||
node.textContent = tl; | ||
} | ||
} | ||
|
||
function processNode(node) { | ||
console.log(node.nodeType + " " + node.nodeName + " " + node.nodeValue) | ||
if (node.nodeType == 3) { | ||
processTextNode(node); | ||
return; | ||
} | ||
|
||
if (node.title) { | ||
let tl = getTranslation(node.title); | ||
if (tl !== undefined) { | ||
node.title = tl; | ||
} | ||
} | ||
|
||
if (node.placeholder) { | ||
let tl = getTranslation(node.placeholder); | ||
if (tl !== undefined) { | ||
node.placeholder = tl; | ||
} | ||
} | ||
|
||
textNodesUnder(node).forEach(function(node) { | ||
processTextNode(node); | ||
}); | ||
} | ||
|
||
document.addEventListener("DOMContentLoaded", function() { | ||
if (!hasLocalization()) { | ||
return; | ||
} | ||
|
||
onUiUpdate(function(m) { | ||
m.forEach(function(mutation) { | ||
mutation.addedNodes.forEach(function(node) { | ||
processNode(node); | ||
}); | ||
}); | ||
}); | ||
|
||
processNode(gradioApp()); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
function gradioApp() { | ||
const elems = document.getElementsByTagName('gradio-app'); | ||
const elem = elems.length == 0 ? document : elems[0]; | ||
|
||
if (elem !== document) { | ||
elem.getElementById = function(id) { | ||
return document.getElementById(id); | ||
}; | ||
} | ||
return elem.shadowRoot ? elem.shadowRoot : elem; | ||
} | ||
|
||
/** | ||
* Get the currently selected top-level UI tab button (e.g. the button that says "Extras"). | ||
*/ | ||
function get_uiCurrentTab() { | ||
return gradioApp().querySelector('#tabs > .tab-nav > button.selected'); | ||
} | ||
|
||
/** | ||
* Get the first currently visible top-level UI tab content (e.g. the div hosting the "txt2img" UI). | ||
*/ | ||
function get_uiCurrentTabContent() { | ||
return gradioApp().querySelector('#tabs > .tabitem[id^=tab_]:not([style*="display: none"])'); | ||
} | ||
|
||
var uiUpdateCallbacks = []; | ||
var uiAfterUpdateCallbacks = []; | ||
var uiLoadedCallbacks = []; | ||
var uiTabChangeCallbacks = []; | ||
var uiAfterUpdateTimeout = null; | ||
var uiCurrentTab = null; | ||
|
||
/** | ||
* Register callback to be called at each UI update. | ||
* The callback receives an array of MutationRecords as an argument. | ||
*/ | ||
function onUiUpdate(callback) { | ||
uiUpdateCallbacks.push(callback); | ||
} | ||
|
||
|
||
|
||
function executeCallbacks(queue, arg) { | ||
for (const callback of queue) { | ||
try { | ||
callback(arg); | ||
} catch (e) { | ||
console.error("error running callback", callback, ":", e); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Schedule the execution of the callbacks registered with onAfterUiUpdate. | ||
* The callbacks are executed after a short while, unless another call to this function | ||
* is made before that time. IOW, the callbacks are executed only once, even | ||
* when there are multiple mutations observed. | ||
*/ | ||
function scheduleAfterUiUpdateCallbacks() { | ||
clearTimeout(uiAfterUpdateTimeout); | ||
uiAfterUpdateTimeout = setTimeout(function() { | ||
executeCallbacks(uiAfterUpdateCallbacks); | ||
}, 200); | ||
} | ||
|
||
var executedOnLoaded = false; | ||
|
||
document.addEventListener("DOMContentLoaded", function() { | ||
var mutationObserver = new MutationObserver(function(m) { | ||
if (!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')) { | ||
executedOnLoaded = true; | ||
executeCallbacks(uiLoadedCallbacks); | ||
} | ||
|
||
executeCallbacks(uiUpdateCallbacks, m); | ||
scheduleAfterUiUpdateCallbacks(); | ||
const newTab = get_uiCurrentTab(); | ||
if (newTab && (newTab !== uiCurrentTab)) { | ||
uiCurrentTab = newTab; | ||
executeCallbacks(uiTabChangeCallbacks); | ||
} | ||
}); | ||
mutationObserver.observe(gradioApp(), {childList: true, subtree: true}); | ||
}); | ||
|
||
/** | ||
* Add a ctrl+enter as a shortcut to start a generation | ||
*/ | ||
document.addEventListener('keydown', function(e) { | ||
var handled = false; | ||
if (e.key !== undefined) { | ||
if ((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; | ||
} else if (e.keyCode !== undefined) { | ||
if ((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; | ||
} | ||
if (handled) { | ||
var button = get_uiCurrentTabContent().querySelector('button[id$=_generate]'); | ||
if (button) { | ||
button.click(); | ||
} | ||
e.preventDefault(); | ||
} | ||
}); |
Oops, something went wrong.