├── README-zh_CN.md ├── README.md ├── config.json ├── fileConfig.json ├── images ├── 1.png ├── 2.png ├── 3.png ├── 4.png └── 5.png └── scripts └── main.py /README-zh_CN.md: -------------------------------------------------------------------------------- 1 | # [sd-webui-models-manager](https://github.com/dhs964057117/sd-webui-models-manager) 2 | 3 | ## 插件作用? 4 | 5 | 这是一款为 [Stable Diffusion web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 设计的插件,主要用于修改模型文件的保存路径。 6 | 7 | 面临以下情况时,将模型移动到另一个位置可能会很有用: 8 | 9 | - 主磁盘磁盘空间不足 10 | 11 | - 您正在多个工具中使用模型,不想将它们存储两次 12 | 13 | Web UI默认的模型文件夹是 `stable-diffusion-webui/models` 14 | 15 | ## 插件安装 16 | 17 | 1. 打开“扩展”选项卡 18 | 2. 打开扩展选项卡中的 "从URL下载(Install from URL)" 选项卡 19 | 3. 在"URL for extension's git repository"这一项中输入插件地址 . 20 | 4. 点击下载(install. 21 | 5. 刷新模型或者重启 Web UI. 22 | 23 | ## 如何使用? 24 | 25 | ​ 1. 把你的模型全部移动到一个你想存放的文件夹里 26 | 27 | 例如: 28 | 29 | 我的Web UI的安装路径是 "D:\stable-diffusion-webui" 30 | 31 | 然后我的模型文件路径是 "D:\stable-diffusion-webui\models" 32 | 33 | 将models下你想移动的模型文件。 34 | 35 | 例如Lora的模型文件"D:\stable-diffusion-webui\models\Lora" 中的全部文件移动到 36 | 37 | 新建的文件"E:\AI_Project\sd_models\lora"中 38 | 39 | 2. 选择 "models Manager"选项卡,并在对应模型的输入框中 输入你更改后的新路径 40 | 41 | ![image-20230815113434311](./images/2.png) 42 | 43 | 点击按钮应用,此时刷新模型或者重启Web UI即可正常使用模型 44 | 45 | ## Windows问题!!(Linux无该问题) 46 | 47 |

注意!!!!如果你的Lora文件下面是文件夹。例如下图情况1“真人写实LORA”

48 | 49 | 则 **可以直接运行。** 50 | 51 | ![5](./images/5.png) 52 | 53 |

如果你的Lora文件下面是文件。例如下图情况2

54 | 55 | 则 **需要打开开发者模式后才能正常使用!** 56 | 57 | ![1](./images/1.png) 58 | 59 | 如果你点击后出现类似下面的错误: 60 | 61 | ![3](./images/3.png) 62 | 63 | 需要你在开始菜单旁边的搜索中搜索**开发者选项**。打开后重新配置即可正常使用 64 | 65 | ![4](./images/4.png) 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [sd-webui-models-manager](https://github.com/dhs964057117/sd-webui-models-manager) 2 | 3 | ·English · [简体中文](./README-zh_CN.md) 4 | 5 | ## What it is? 6 | 7 | it is an extension for [Stable Diffusion web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) to manager your models path 8 | 9 | can change your models save path. 10 | 11 | Sometimes it might be useful to move your models to another location. Reasons for this could be: 12 | 13 | - Main disk has low disk space 14 | - You are using models in multiple tools and don't want to store them twice 15 | 16 | The default model folder is `stable-diffusion-webui/models` 17 | 18 | ## Installation 19 | 20 | 1. Open "Extensions" tab. 21 | 2. Open "Install from URL" tab in the tab. 22 | 3. Enter URL of this repo to "URL for extension's git repository". 23 | 4. Press "Install" button. 24 | 5. Restart Web UI. 25 | 26 | ## How to use it? 27 | 28 | 1.move yours models dir to another path 29 | 30 | eg: 31 | 32 | my webui workspace is "D:\stable-diffusion-webui" 33 | 34 | then i move the lora models to "E:\AI_Project\sd_models\lora" 35 | 36 | ![1](./images/1.png) 37 | 38 | 2.next select the tab "models Manager" input your new path 39 | 40 | ![image-20230815113434311](./images/2.png) 41 | 42 | click the enable and change。 43 | 44 | if your system is Windows maybe got some errors info like this: 45 | 46 | ![3](./images/3.png) 47 | 48 | now you should open the developer mode and try again 49 | 50 | ![4](./images/4.png) 51 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Lora": "", 3 | "Stable-diffusion": "" 4 | } -------------------------------------------------------------------------------- /fileConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "file_config": [ 3 | ".pth", 4 | ".safetensors", 5 | ".th", 6 | ".ckpt", 7 | ".onnx", 8 | ".pt" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhs964057117/sd-webui-models-manager/0fd20ddff9e75082b43e5420b263b9f3538e0ecc/images/1.png -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhs964057117/sd-webui-models-manager/0fd20ddff9e75082b43e5420b263b9f3538e0ecc/images/2.png -------------------------------------------------------------------------------- /images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhs964057117/sd-webui-models-manager/0fd20ddff9e75082b43e5420b263b9f3538e0ecc/images/3.png -------------------------------------------------------------------------------- /images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhs964057117/sd-webui-models-manager/0fd20ddff9e75082b43e5420b263b9f3538e0ecc/images/4.png -------------------------------------------------------------------------------- /images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhs964057117/sd-webui-models-manager/0fd20ddff9e75082b43e5420b263b9f3538e0ecc/images/5.png -------------------------------------------------------------------------------- /scripts/main.py: -------------------------------------------------------------------------------- 1 | import modules.ui 2 | import subprocess 3 | import functools 4 | import os 5 | import json 6 | import gradio as gr 7 | from pathlib import Path 8 | from modules import script_callbacks, paths 9 | from modules import errors 10 | # Webui root path 11 | ROOT_DIR = Path().absolute() 12 | # 获取当前文件的根目录 13 | root_directory = os.path.dirname(os.path.abspath(__file__)) 14 | 15 | # 获取根目录的父目录 16 | parent_directory = os.path.dirname(root_directory) 17 | 18 | # 调用函数并传入文件夹路径和config.json文件路径 19 | folder_path = parent_directory+"\models" 20 | config_file = parent_directory+"\config.json" 21 | file_config = parent_directory+"\fileConfig.json" 22 | 23 | 24 | def update_config(folder_path, config_file): 25 | # 遍历文件夹 26 | for root, dirs, files in os.walk(folder_path): 27 | for dir_name in dirs: 28 | # dir_path = os.path.join(root, dir_name) 29 | has_required_files = "" 30 | 31 | # # 检查文件夹中是否有指定后缀的文件 32 | # for file_name in os.listdir(dir_path): 33 | # if file_name.endswith(json.loads(file_config)["fileConfig"]): 34 | # has_required_files = "" 35 | # break 36 | 37 | # 更新config.json文件 38 | config_data = {} 39 | if os.path.exists(config_file): 40 | with open(config_file, 'r') as f: 41 | config_data = json.load(f) 42 | 43 | config_data[dir_name] = str(has_required_files) 44 | 45 | with open(config_file, 'w') as f: 46 | json.dump(config_data, f, indent=4) 47 | 48 | print(f"文件夹 {dir_name} 更新成功") 49 | 50 | 51 | # 获取json里面数据 52 | def get_json_data(src): 53 | with open(src, 'rb') as f: # 使用只读模型,并定义名称为f 54 | params = json.load(f) # 加载json文件 55 | # params["code"] = "404" # code字段对应的值修改为404 56 | # print("params", params) # 打印 57 | return params # 返回修改后的内容 58 | 59 | 60 | # 写入json文件 61 | def write_json_data(params): 62 | # 使用写模式,名称定义为r 63 | # 其中路径如果和读json方法中的名称不一致,会重新创建一个名称为该方法中写的文件名 64 | with open(config_file, 'w') as r: 65 | # 将dict写入名称为r的文件中 66 | json.dump(params, r) 67 | 68 | 69 | # 定义回调函数,用于获取CheckBox的选中状态 70 | def get_checkbox_values(*checkboxes): 71 | values = {} 72 | for checkbox in checkboxes: 73 | checkbox_id = checkbox.elem_id 74 | value = gr.Interface(inputs=checkboxes).get_instances 75 | values[checkbox_id] = value 76 | return values 77 | 78 | 79 | def create_link(source_path, target_path, info): 80 | # 创建符号链接 81 | try: 82 | os.symlink(source_path, target_path, os.path.isdir(source_path)) 83 | info.append(f"target {target_path} create link success") 84 | print(f"Created symbolic link for {source_path}") 85 | except OSError as e: 86 | info.append(f"{e}") 87 | info.append( 88 | f"target {target_path} create link fail, if your system is windows please open developer mode and try agin") 89 | print( 90 | f"{e}--Created symbolic link for {source_path} fail, if your system is windows please open developer mode and try agin") 91 | except Exception as e: 92 | info.append(f"{e}") 93 | info.append( 94 | f"Some unexpected exceptions have occurred. Please save the information and ask the question to : https://github.com/dhs964057117/sd-webui-models-manager") 95 | print("{e}--Some unexpected exceptions have occurred. Please save the information and ask the question to : https://github.com/dhs964057117/sd-webui-models-manager") 96 | 97 | 98 | def create_symbolic_links(source_folder, target_folder, info): 99 | # 获取源文件夹中的所有文件 100 | files = os.listdir(source_folder) 101 | 102 | # 遍历每个文件,并创建符号链接到目标文件夹 103 | for file in files: 104 | source_path = os.path.join(source_folder, file) 105 | target_path = os.path.join(target_folder, file) 106 | # 检查目标路径是否已经存在 107 | if os.path.lexists(target_path): 108 | info.append( 109 | f"target {target_path} has exist , skip create link") 110 | print("目标路径已存在,跳过创建符号链接") 111 | elif os.path.isdir(source_path): 112 | create_junction(source_path, target_path, info) 113 | # os.symlink(source_path, target_path) 114 | # info.append(f"target {target_path} create link success") 115 | print( 116 | f"Created junction for {file} src {source_path} target {target_path}") 117 | else: 118 | create_link(source_path, target_path, info) 119 | 120 | 121 | def create_junction(src, dst, info): 122 | import platform 123 | if platform.system() == "Windows": 124 | with open(os.devnull, 'w') as devnull: 125 | try: 126 | subprocess.call('cmd.exe /c mklink /J "%s" "%s"' % 127 | (dst, src), shell=True, stdout=devnull, stderr=devnull) 128 | info.append(f"target {dst} create link success") 129 | print("创建目录链接成功!!") 130 | except Exception as e: 131 | info.append(f"{e}") 132 | info.append(f"target {dst} create link fail") 133 | print(e) 134 | else: 135 | create_link(src, dst, info) 136 | 137 | 138 | def getTextWithColor(text): 139 | if (text.find("Error") != -1): 140 | return "color:red;" 141 | elif (text.find("fail") != -1): 142 | return "color:#FFCC00;" 143 | elif (text.find("success") != -1): 144 | return "color:green;" 145 | else: 146 | return "color:green;" 147 | 148 | 149 | def create_symbol_link(checkboxes, textboxs): 150 | success = False 151 | selectKey = [] 152 | selectPath = [] 153 | info = [] 154 | for checkbox, textbox in zip(checkboxes, textboxs): 155 | if checkbox.value: 156 | selectKey.append(textbox.label) 157 | selectPath.append(textbox.value) 158 | for i in range(len(selectKey)): 159 | print(f"------{selectKey[i]}:{selectPath[i]}") 160 | create_symbolic_links(selectPath[i], os.path.join( 161 | paths.models_path, selectKey[i]), info) 162 | # j.elem_id == i.elem_id and get_checkbox_values(checkboxes=checkboxes) 163 | lines = "" 164 | for line in info: 165 | if (line.find("create link success") != -1): 166 | success = True 167 | lines = lines + \ 168 | f'

' + f"{line}" + "

" 169 | if (success): 170 | lines += f'

' + \ 171 | "models dir has update, use to refresh models or reload webui

" 172 | return [f"""{lines}"""] 173 | 174 | 175 | def checkbox_callback(checkbox_value): 176 | if checkbox_value: 177 | print("Checkbox is checked") 178 | else: 179 | print("Checkbox is unchecked") 180 | 181 | 182 | def list_folders_to_json(path, output_file): 183 | folders = {} 184 | for folder in os.listdir(path): 185 | if os.path.isdir(os.path.join(path, folder)): 186 | folders[folder] = str("") 187 | with open(output_file, "w") as f: 188 | json.dump(folders, f) 189 | 190 | 191 | def on_before_ui(): 192 | try: 193 | list_folders_to_json(paths.models_path, config_file) 194 | except Exception as e: 195 | errors.display(e) 196 | 197 | 198 | def on_ui_tabs(): 199 | # 创建多个CheckBox 200 | checkboxes = [] 201 | textboxs = [] 202 | 203 | def on_checkbox_change(key, checkbox): 204 | if key is not None: 205 | for cb in checkboxes: 206 | if cb.elem_id == key: 207 | cb.value = checkbox 208 | print(cb.elem_id, checkbox, "find") 209 | break 210 | 211 | def on_textbox_change(key, checkbox): 212 | if key is not None: 213 | for cb in textboxs: 214 | if cb.elem_id == key: 215 | cb.value = checkbox 216 | print(cb.elem_id, checkbox, "find") 217 | break 218 | 219 | file_json = get_json_data(config_file) 220 | with gr.Blocks(analytics_enabled=False) as ModelsPath_Blocks: 221 | gr.HTML( 222 | "

input custom path for models

") 223 | with gr.Column(): 224 | for key, value in file_json.items(): 225 | print(key, value) 226 | with gr.Row(scale=45): 227 | textbox_info = gr.Textbox(label=key, value=value, 228 | readonly=False, elem_id=key) 229 | textbox_info.change(functools.partial( 230 | on_textbox_change, textbox_info.elem_id), textbox_info) 231 | textboxs.append(textbox_info) 232 | checkBox = gr.Checkbox( 233 | value=value != '', elem_id=key, label='Enable') 234 | checkBox.change(functools.partial( 235 | on_checkbox_change, checkBox.elem_id), checkBox) 236 | checkboxes.append(checkBox) 237 | with gr.Column(scale=80): 238 | change_btn = gr.Button( 239 | value="Apply settings", variant='primary', elem_id="change_btn") 240 | update_result = gr.HTML(elem_id="update_result") 241 | change_btn.click(fn=modules.ui.wrap_gradio_call(functools.partial( 242 | create_symbol_link, checkboxes, textboxs), extra_outputs=[gr.update()]), outputs=[update_result]) 243 | return [(ModelsPath_Blocks, "Models Manager", "Models Manager")] 244 | 245 | 246 | script_callbacks.on_ui_tabs(on_ui_tabs) 247 | script_callbacks.on_before_ui(on_before_ui) 248 | --------------------------------------------------------------------------------