AkinoKaze commited on
Commit
0d7237b
·
verified ·
1 Parent(s): 328f5b7

Upload 2 files

Browse files
Files changed (2) hide show
  1. scripts/colab_sd_models.py +174 -0
  2. style.css +32 -0
scripts/colab_sd_models.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from concurrent.futures import ThreadPoolExecutor, as_completed
3
+ from pathlib import Path
4
+ from re import search
5
+ from shutil import disk_usage
6
+ from subprocess import PIPE, Popen, STDOUT, run
7
+ from time import sleep
8
+
9
+ import gradio as gr
10
+ from requests import get as requests_get, head as requests_head
11
+ from modules import script_callbacks, sd_models, shared
12
+ from modules.paths_internal import data_path
13
+
14
+ DL_COMMAND = 'wget -nv -t 10 --show-progress --progress=bar:force -q --content-disposition "{link}" -P {dl_path}'
15
+ WEBUI_ROOT = Path(data_path)
16
+ LINKS_FILE = WEBUI_ROOT / 'links.txt'
17
+ MODELS_FOLDER_PATH = Path(sd_models.model_path)
18
+ LORAS_FOLDER_PATH = Path(shared.cmd_opts.lora_dir)
19
+ EMBEDDINGS_FOLDER_PATH = Path(shared.cmd_opts.embeddings_dir)
20
+ CIVITAI_TOKEN = '542c1d6077168822e1b49e30e3437a5d'
21
+
22
+
23
+ def del_null_model():
24
+ null_model_path = MODELS_FOLDER_PATH / 'nullModel.ckpt'
25
+ if null_model_path.exists():
26
+ try:
27
+ null_model_path.unlink(missing_ok=True)
28
+ except:
29
+ pass
30
+
31
+ def find_mount_point():
32
+ path = Path(__file__).resolve()
33
+ while not path.is_mount():
34
+ path = path.parent
35
+ return path
36
+
37
+ def free_space():
38
+ total, used, free = disk_usage(find_mount_point())
39
+ power = 2 ** 10
40
+ n = 0
41
+ power_labels = {0: '', 1: 'Кило', 2: 'Мега', 3: 'Гига', 4: 'Тера'}
42
+ while free > power:
43
+ free /= power
44
+ n += 1
45
+ return f'{free:.2f} {power_labels[n]}байт'
46
+
47
+ def extract_url(command_eith_url):
48
+ pattern = r'["\']?((?:https?|ftp|ftps)://[^\s"\'<>]+)["\']?'
49
+ match = search(pattern, command_eith_url)
50
+ return match.group(1) if match else None
51
+
52
+ def hf_size(url: str) -> int:
53
+ try:
54
+ modified_url = url.replace('resolve', 'raw')
55
+ response = requests_get(modified_url, timeout=10)
56
+ response.raise_for_status()
57
+ content = response.text
58
+ size_str = content.split('size')[-1].strip().split()[0]
59
+ return int(size_str) if size_str.isdigit() else 0
60
+ except:
61
+ return 0
62
+
63
+ def cv_size(url: str) -> int:
64
+ try:
65
+ model_version_id = url.split('/')[-1]
66
+ response = requests_get(f'https://civitai.com/api/v1/model-versions/{model_version_id}?token={CIVITAI_TOKEN}', timeout=10)
67
+ response.raise_for_status()
68
+ files = response.json().get('files', [])
69
+ if files:
70
+ size_kb = files[0].get('sizeKB', 0)
71
+ return int(size_kb * 1024)
72
+ return 0
73
+ except:
74
+ return 0
75
+
76
+ def get_file_size(command_with_url: str) -> int:
77
+ url = extract_url(command_with_url)
78
+ if not url:
79
+ print(f'в строке `{command_with_url}` ссылка не найдена')
80
+ return 0
81
+ file_size = 0
82
+ if 'huggingface' in url:
83
+ file_size = hf_size(url)
84
+ elif 'civitai' in url:
85
+ file_size = cv_size(url)
86
+ if file_size:
87
+ return file_size
88
+ try:
89
+ response = requests_head(url, allow_redirects=True, timeout=10)
90
+ response.raise_for_status()
91
+ content_length = response.headers.get('Content-Length')
92
+ if content_length and content_length.isdigit():
93
+ return int(content_length)
94
+ except Exception:
95
+ pass
96
+ return 0
97
+
98
+ def get_total_file_size(urls: list):
99
+ total = 0
100
+ sizes = []
101
+ with ThreadPoolExecutor(max_workers=len(urls)) as executor:
102
+ futures = [executor.submit(get_file_size, url) for url in urls]
103
+ for future in as_completed(futures):
104
+ size = future.result()
105
+ sizes.append(size)
106
+ total += size
107
+ return total, sizes
108
+
109
+ def bytes_convert(size_bytes):
110
+ if size_bytes >= 1073741824:
111
+ return f'{round(size_bytes / 1073741824, 2)} ГБ'
112
+ else:
113
+ return f'{round(size_bytes / 1048576, 2)} МБ'
114
+
115
+ def get_own_links(ownmodels, ownloras, ownembeddings):
116
+ dl_commands = []
117
+ for text, dlpath in zip([ownmodels, ownloras, ownembeddings], [MODELS_FOLDER_PATH, LORAS_FOLDER_PATH, EMBEDDINGS_FOLDER_PATH]):
118
+ lines = text.split('\n')
119
+ for line in lines:
120
+ if line.strip():
121
+ link = line.strip() + (f"?token={CIVITAI_TOKEN}" if "?" not in line else f"&token={CIVITAI_TOKEN}") if "civitai" in line else line.strip()
122
+ dl_command = DL_COMMAND.format(link=link, dl_path=dlpath.resolve().as_posix())
123
+ dl_commands.append(dl_command)
124
+ LINKS_FILE.write_text('\n'.join(dl_commands).strip(), encoding='utf-8')
125
+ print('список загрузки сформирован...')
126
+
127
+ def on_ui_tabs():
128
+ with gr.Blocks() as models_list:
129
+ gr.HTML('<h1>Загрузка моделей</h1>')
130
+ ownmodels = gr.Textbox(label="Модели", lines=5)
131
+ ownloras = gr.Textbox(label="LoRA", lines=5)
132
+ ownembeddings = gr.Textbox(label="Внедрения", lines=5)
133
+
134
+ progress_slider = gr.Slider(minimum=0, maximum=100, value=0, label="Прогресс загрузки", interactive=False)
135
+ dl_result_box = gr.Textbox(label='Результ��т')
136
+
137
+ button = gr.Button("Сформировать ссылки")
138
+ button.click(get_own_links, inputs=[ownmodels, ownloras, ownembeddings])
139
+
140
+ def start_download():
141
+ try:
142
+ urls = LINKS_FILE.read_text(encoding='utf-8').splitlines()
143
+ LINKS_FILE.unlink(missing_ok=True)
144
+ total_file_size, sizes = get_total_file_size(urls)
145
+ total, used, free = disk_usage(find_mount_point())
146
+
147
+ if total_file_size > (free - 1073741824):
148
+ msg = f'Недостаточно места! Нужно: {bytes_convert(total_file_size)}, доступно: {bytes_convert(free)}'
149
+ print(msg)
150
+ return gr.update(value=0), msg
151
+
152
+ print(f'Загрузка {bytes_convert(total_file_size)} началась...')
153
+ total_urls = len(urls)
154
+ downloaded_size = 0
155
+
156
+ for idx, (command, size) in enumerate(zip(urls, sizes)):
157
+ for line in downloader(command):
158
+ print(line)
159
+ downloaded_size += size
160
+ progress = int(((idx + 1) / total_urls) * 100)
161
+ progress_text = f"Загружено {bytes_convert(downloaded_size)} из {bytes_convert(total_file_size)}"
162
+ yield gr.update(value=progress), progress_text
163
+
164
+ del_null_model()
165
+ return gr.update(value=100), "Загрузка завершена!"
166
+ except Exception as e:
167
+ return gr.update(value=0), f"ОШИБКА: {e}"
168
+
169
+ download_button = gr.Button("Скачать")
170
+ download_button.click(start_download, outputs=[progress_slider, dl_result_box])
171
+
172
+ return (models_list, 'Модели', 'models_list'),
173
+
174
+ script_callbacks.on_ui_tabs(on_ui_tabs)
style.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /* Показываем элементы, скрытые ранее */
3
+ #free_space_area,
4
+ #free_space_button,
5
+ #files_area,
6
+ #delete_area,
7
+ #files_button,
8
+ #delete_button,
9
+ #ownlinks_download_button,
10
+ #checkboxes_download_button,
11
+ #dlresultbox,
12
+ #downloads_result_text,
13
+ #downloads_start_text,
14
+ .models_porgress_loader {
15
+ display: block !important;
16
+ }
17
+
18
+ /* Стилизация для прогресс-бара (gr.Slider как визуальный индикатор) */
19
+ input[type="range"][aria-label="Прогресс загрузки"] {
20
+ height: 10px;
21
+ background: linear-gradient(to right, #60d43d 0%, #60d43d var(--value, 0%), #ccc var(--value, 0%), #ccc 100%);
22
+ border-radius: 5px;
23
+ outline: none;
24
+ }
25
+
26
+ /* Скрываем бегунок у неинтерактивного слайдера */
27
+ input[type="range"][aria-label="Прогресс загрузки"]::-webkit-slider-thumb {
28
+ display: none;
29
+ }
30
+ input[type="range"][aria-label="Прогресс загрузки"]::-moz-range-thumb {
31
+ display: none;
32
+ }