.gitattributes CHANGED
@@ -33,4 +33,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- frpc filter=lfs diff=lfs merge=lfs -text
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
README.md CHANGED
@@ -1,10 +1,3 @@
1
  ---
2
  license: unknown
3
  ---
4
- 这是一个在linux jupyter环境便捷启动[stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)的jupyter笔记
5
-
6
- 如果你需要使用,只需要下载 [sdwui-before-new.ipynb](https://huggingface.co/viyi/sdwui/resolve/main/sdwui-before-new.ipynb) 就行
7
-
8
- 主要逻辑都在 sdwui-start-new.ipynb 文件内,一般情况下有功能更新或修复bug都在这个文件,而sdwui-before-new.ipynb这个文件每次都会下载最新的sdwui-start-new.ipynb进行启动
9
-
10
- 现在只有 sdwui-start-util.ipynb 文件还在更新,用于kaggle平台的这个笔记 [stable-diffusion-webui & ComfyUI](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-comfyui)
 
1
  ---
2
  license: unknown
3
  ---
 
 
 
 
 
 
 
kaggle-util.ipynb DELETED
@@ -1 +0,0 @@
1
- {"cells":[{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":[]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["from pathlib import Path\n","import os\n","import time\n","import re\n","import subprocess\n","import threading\n","import sys\n","import socket\n","import torch\n","from typing import List\n","import uuid"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 内置参数默认值,当上下文有参数时可覆盖默认值\n","_runing = False\n","_useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n","\n","_useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n","\n","_server_port = locals().get('server_port') or globals().get('server_port') or 7860\n"," \n","_huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n","_huggingface_token = _huggingface_token\\\n"," .replace('{sdwui}','stable-diffusion-webui')\\\n"," .replace('{wui}',\"webui\")\n","\n","show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n","if show_shell_info is None: show_shell_info = False\n","\n","run_by_none_device = False\n","\n","_proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n","\n","_config_args:dict[str, str] = locals().get('config_args') or globals().get('config_args') or {}"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["\n","def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:\n"," global show_shell_info\n"," if desc is not None:\n"," print(desc)\n","\n"," run_kwargs = {\n"," \"args\": command,\n"," \"shell\": True,\n"," \"cwd\": cwd,\n"," \"env\": os.environ if custom_env is None else custom_env,\n"," \"encoding\": 'utf8',\n"," \"errors\": 'ignore',\n"," }\n","\n"," if not show_shell_info:\n"," run_kwargs[\"stdout\"] = run_kwargs[\"stderr\"] = subprocess.PIPE\n","\n"," result = subprocess.run(**run_kwargs)\n","\n"," if result.returncode != 0:\n"," error_bits = [\n"," f\"{errdesc or 'Error running command'}.\",\n"," f\"Command: {command}\",\n"," f\"Error code: {result.returncode}\",\n"," ]\n"," if result.stdout:\n"," error_bits.append(f\"stdout: {result.stdout}\")\n"," if result.stderr:\n"," error_bits.append(f\"stderr: {result.stderr}\")\n"," if try_error:\n"," print((RuntimeError(\"\\n\".join(error_bits))))\n"," else:\n"," raise RuntimeError(\"\\n\".join(error_bits))\n","\n"," if show_shell_info:\n"," print((result.stdout or \"\"))\n"," return (result.stdout or \"\")\n","\n","def mkdirs(path, exist_ok=True):\n"," if path and not Path(path).exists():\n"," os.makedirs(path,exist_ok=exist_ok)\n","\n","\n","# 检查网络\n","def check_service(host, port):\n"," try:\n"," socket.create_connection((host, port), timeout=5)\n"," return True\n"," except socket.error:\n"," return False\n","\n","\n","# 检查gpu是否存在\n","def check_gpu():\n"," if not run_by_none_device and torch.cuda.device_count() == 0:\n"," raise Exception('当前环境没有GPU')\n","\n","\n","def echoToFile(content:str,path:str):\n"," if path.find('/') >= 0:\n"," _path = '/'.join(path.split('/')[:-1])\n"," run(f'''mkdir -p {_path}''')\n"," with open(path,'w') as sh:\n"," sh.write(content)\n"," \n","def get_freefrp_confog(local_port):\n"," rd_str = uuid.uuid1()\n"," return (f'''\n","[common]\n","server_addr = frp.freefrp.net\n","server_port = 7000\n","token = freefrp.net\n","\n","[{rd_str}_http]\n","type = http\n","local_ip = 127.0.0.1\n","local_port = {local_port}\n","custom_domains = {rd_str}.frp.eaias.com\n","''',f'http://{rd_str}.frp.eaias.com')"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["\n","_install_path = f\"{os.environ['HOME']}/sd_webui\" # 安装目录\n","_output_path = '/kaggle/working' if os.path.exists('/kaggle/working/') else f\"{os.environ['HOME']}/.sdwui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\n","_input_path = '/kaggle/input' # 输入目录\n","_ui_dir_name = 'sd_main_dir'\n","\n","_install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n","_output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n","_input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n","_ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n","\n","install_path = _install_path\n","output_path = _output_path\n","input_path = _input_path\n","ui_dir_name = _ui_dir_name\n"," \n","google_drive = '' \n","\n","\n","_useGooglrDrive = locals().get('useGooglrDrive') or globals().get('useGooglrDrive') or True\n","\n","# 连接谷歌云\n","try:\n"," if _useGooglrDrive:\n"," from google.colab import drive\n"," drive.mount(f'~/google_drive')\n"," google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n"," _output_path = f'{google_drive}/sdwebui/Output'\n"," _input_path = f'{google_drive}/sdwebui/Input'\n"," run(f'''mkdir -p {_input_path}''')\n"," print('''\n","已经链接到谷歌云盘\n","已在云盘创建Input和Output目录\n"," ''')\n","except:\n"," _useGooglrDrive = False\n","\n","run(f'''mkdir -p {_install_path}''')\n","run(f'''mkdir -p {_output_path}''')\n","\n","\n","os.environ['install_path'] = _install_path\n","os.environ['output_path'] = _output_path\n","os.environ['google_drive'] = google_drive\n","os.environ['input_path'] = _input_path\n","\n","def replace_path(input_str:str):\n"," if not input_str: return ''\n"," for key in _config_args:\n"," input_str = input_str.replace(key,_config_args[key])\n"," \n"," return input_str.replace('$install_path',_install_path)\\\n"," .replace('{install_path}',_install_path)\\\n"," .replace('$input_path',_input_path)\\\n"," .replace('{input_path}',_input_path)\\\n"," .replace('$output_path',_output_path)\\\n"," .replace('{output_path}',_output_path)\\\n"," .replace('{sdwui}','stable-diffusion-webui')\\\n"," .replace('{wui}',\"webui\")\n","\n","space_string = ' \\n\\r\\t\\'\\\",'\n","\n","def config_reader(conf:str):\n"," args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\\n') if item.strip(space_string)]\n"," return [item.strip() for item in args if item.strip()]\n"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"i3LhnwYHLCtC","trusted":true},"outputs":[],"source":["ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n","frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n","# ss证书目录 下载nginx的版本,把pem格式改成crt格式\n","frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n","if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n"," frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n","# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n","frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n","# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n","\n","# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n","# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\n","kaggleApiTokenFile = locals().get('kaggle_api_token') or globals().get('kaggle_api_token') or os.path.join(_input_path,'configs/kaggle.json')\n","\n","requirements = []\n"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"a_GtG2ayLCtD","trusted":true},"outputs":[],"source":["# 这下面的是用于初始化一些值或者环境变量的,轻易别改\n","_setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or '/kaggle/working/configs/config.json')\n","\n","_ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or '/kaggle/working/configs/ui-config.json')\n","\n","# 设置文件路径\n","if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n"," if _setting_file == '/kaggle/working/configs/config.json':\n"," _setting_file = os.path.join(_output_path,'configs/config.json')\n"," if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n"," _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n"," \n","frpcStartArg = ''\n","freefrp_url = ''\n","_frp_temp_config_file = ''\n","_frp_config_or_file = replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or frpcConfigFile\n","run(f'''mkdir -p {_install_path}/configFiles''')\n","if _frp_config_or_file:\n"," if '[common]' in _frp_config_or_file:\n"," echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_webui.ini')\n"," _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_webui.ini'\n"," elif '.ini' in _frp_config_or_file:\n"," _frp_temp_config_file = _frp_config_or_file.strip()\n"," \n"," if _frp_temp_config_file:\n"," if Path(_frp_temp_config_file).exists():\n"," run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_webui.ini''')\n"," run(f'''sed -i \"s/local_port = .*/local_port = {_server_port}/g\" {_install_path}/configFiles/frpc_webui.ini''')\n"," frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n"," elif _frp_config_or_file.strip().startswith('-f'):\n"," frpcStartArg = _frp_config_or_file.strip()\n"," \n","if not frpcStartArg:\n"," conf,url = get_freefrp_confog(_server_port)\n"," echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n"," freefrp_url = url\n"," frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n","\n","ngrokToken=''\n","_ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n","if _ngrok_config_or_file:\n"," if Path(_ngrok_config_or_file.strip()).exists():\n"," ngrokTokenFile = _ngrok_config_or_file.strip()\n"," if Path(ngrokTokenFile).exists():\n"," with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n"," ngrokToken = nkfile.readline()\n"," elif not _ngrok_config_or_file.strip().startswith('/'):\n"," ngrokToken=_ngrok_config_or_file.strip()\n"," \n","huggingface_headers:dict = None "]},{"cell_type":"markdown","metadata":{},"source":["## 文件下载工具\n","\n","---\n","\n","link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',sync:bool=False,thread_num:int=None)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["import concurrent.futures\n","import importlib\n","import os\n","import pprint\n","import re\n","from pathlib import Path\n","from typing import List\n","\n","import requests\n","\n","show_shell_info = False\n","\n","def is_installed(package):\n"," try:\n"," spec = importlib.util.find_spec(package)\n"," except ModuleNotFoundError:\n"," return False\n","\n"," return spec is not None\n","\n","def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True,headers={}):\n"," # 获取文件的真实文件名\n"," if not filename:\n"," with requests.get(url, stream=True,headers=headers) as r:\n"," if 'Content-Disposition' in r.headers:\n"," filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n"," r.close()\n"," if not filename and re.search(r'/[^/]+\\.[^/]+$',url):\n"," filename = url.split('/')[-1].split('?')[0]\n"," \n"," filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n"," filename = re.sub(r'[\\s\\t]+', '_', filename)\n"," \n"," print(f'下载 {filename} url: {url} --> {dist_path}')\n"," \n"," # 创建目录\n"," if cache_path and not Path(cache_path).exists():\n"," os.makedirs(cache_path,exist_ok=True)\n"," if dist_path and not Path(dist_path).exists():\n"," os.makedirs(dist_path,exist_ok=True)\n"," \n"," # 拼接文件的完整路径\n"," filepath = os.path.join(dist_path, filename)\n","\n"," if cache_path:\n"," cache_path = os.path.join(cache_path, filename)\n"," \n"," # 判断文件是否已存在\n"," if Path(filepath).exists():\n"," print(f'文件 {filename} 已存在 {dist_path}')\n"," return\n"," \n"," if cache_path and Path(cache_path).exists():\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n"," print(f'文件缓存 {cache_path} --> {dist_path}')\n"," return\n"," # 下载文件\n"," with requests.get(url, stream=True, headers=headers) as r:\n"," r.raise_for_status()\n"," with open(cache_path or filepath, 'wb') as f:\n"," for chunk in r.iter_content(chunk_size=1024):\n"," if chunk:\n"," f.write(chunk)\n"," # 如果使用了缓存目录 需要复制或链接文件到目标目录\n"," if cache_path:\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n"," print(f'下载完成 {filename} --> {dist_path}')\n"," \n","def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n"," if not Path(dist_path).exists():\n"," os.makedirs(dist_path,exist_ok=True)\n"," if show_shell_info:\n"," print(f'git 下载 {url} --> {dist_path}')\n"," if cache_path and not Path(cache_path).exists():\n"," os.makedirs(cache_path,exist_ok=True)\n"," run(f'git clone {url}',cwd = cache_path)\n"," if cache_path:\n"," run(f'cp -n -r -f {cache_path}/* {dist_path}')\n"," else:\n"," run(f'git clone {url}',cwd = dist_path)\n"," if show_shell_info:\n"," print(f'git 下载完成 {url} --> {dist_path}')\n"," \n"," \n","def download_huggingface(url:str, filename:str, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n"," fileReg = r'^https:\\/\\/huggingface.co(\\/([^\\/]+\\/)?[^\\/]+\\/[^\\/]+\\/(resolve|blob)\\/[^\\/]+\\/|[^\\.]+\\.[^\\.]+$|download=true)'\n"," def isFile(url:str):\n"," if re.match(fileReg,url):\n"," return True\n"," return False\n"," if isFile(url):\n"," download_file(url,filename,dist_path,cache_path,_link_instead_of_copy,headers=huggingface_headers)\n"," else:\n"," download_git(url,dist_path,cache_path,_link_instead_of_copy)\n"," \n","# 加入文件到下载列表\n","def pause_url(url:str,dist_path:str):\n"," file_name = ''\n"," if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n"," file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n"," url = url[len(file_name)+1:]\n"," if not re.match(r'^(https?|ftps?)://',url):\n"," return\n"," file_name = re.sub(r'\\s+','_',file_name or '')\n"," path_hash = str(hash(url)).replace('-','')\n"," \n"," return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}\n","\n","def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5, \n"," cache_path:str=os.path.join(os.environ['HOME'],'.cache','download_util'),\n"," _link_instead_of_copy:bool=True,is_await:bool=False):\n"," if sync:\n"," for conf in download_list:\n"," cache_dir = os.path.join(cache_path,conf['path_hash'])\n"," if conf['url'].startswith('https://github.com'):\n"," download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n"," continue\n"," if conf['url'].startswith('https://huggingface.co'):\n"," download_huggingface(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n"," continue\n"," if conf['url'].startswith('https://civitai.com'):\n"," if not re.search(r'token=.+', conf['url']):\n"," if conf['url'].find('?') == -1:\n"," conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n"," else:\n"," conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n"," download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n"," else:\n"," executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)\n"," futures = []\n"," for conf in download_list:\n"," cache_dir = os.path.join(cache_path,conf['path_hash'])\n"," if conf['url'].startswith('https://github.com'):\n"," futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],\n"," cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n"," continue\n"," if conf['url'].startswith('https://huggingface.co'):\n"," futures.append(executor.submit(download_huggingface,conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n"," continue\n"," if conf['url'].startswith('https://civitai.com'):\n"," if not re.search(r'token=.+', conf['url']):\n"," if conf['url'].find('?') == -1:\n"," conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n"," else:\n"," conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n"," futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],\n"," cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n"," if is_await:\n"," concurrent.futures.wait(futures)\n"," \n"," \n","def parse_config(config:str):\n"," space_string = ' \\n\\r\\t\\'\\\",'\n"," other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\\n') if item.strip(space_string)]\n"," other_flie_list = [item.strip() for item in other_flie_list if item.strip()]\n"," other_flie_list_store = {}\n"," other_flie_list_store_name='default'\n"," other_flie_list_store_list_cache=[]\n"," \n"," for item in other_flie_list:\n"," if item.startswith('[') and item.endswith(']'):\n"," if not other_flie_list_store_name == 'default':\n"," other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n"," other_flie_list_store_list_cache = []\n"," other_flie_list_store_name = item[1:-1]\n"," else:\n"," other_flie_list_store_list_cache.append(item)\n"," other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n"," \n"," return other_flie_list_store\n","\n","\n","def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',\n"," sync:bool=False,thread_num:int=None, is_await:bool=False):\n"," store:dict[str,List[str]] = parse_config(config)\n"," download_list = []\n"," for dist_dir in store.keys():\n"," dist_path = os.path.join(base_path,dist_dir)\n"," os.makedirs(dist_path,exist_ok=True)\n"," for path in store[dist_dir]:\n"," if 'https://' in path or 'http://' in path:\n"," if skip_url:\n"," continue\n"," if sync:\n"," download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)\n"," continue\n"," download_list.append(pause_url(path,dist_path))\n"," else:\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {path} {dist_path}')\n"," if show_shell_info:\n"," print(f'{\"链接\" if _link_instead_of_copy else \"复制\"} {path} --> {dist_path}')\n"," run(f'rm -f {dist_path}/\\*.* ')\n"," if not skip_url:\n"," if show_shell_info:\n"," pprint.pprint(download_list)\n"," download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 3,is_await=is_await)"]},{"cell_type":"markdown","metadata":{"id":"p0uS-BLULCtD"},"source":["## kaggle public API\n","\n","**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"m8FJi4j0LCtD","trusted":true},"outputs":[],"source":["# 安装kaggle的api token文件\n","def initKaggleConfig():\n"," if Path('~/.kaggle/kaggle.json').exists():\n"," return True\n"," if Path(kaggleApiTokenFile).exists():\n"," run(f'''mkdir -p ~/.kaggle/''')\n"," run('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n"," run(f'''chmod 600 ~/.kaggle/kaggle.json''')\n"," return True\n"," print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n"," return False\n","\n","def getUserName():\n"," if not initKaggleConfig(): return\n"," import kaggle\n"," return kaggle.KaggleApi().read_config_file()['username']\n","\n","def createOrUpdateDataSet(path:str,datasetName:str):\n"," if not initKaggleConfig(): return\n"," print('创建或更新数据集 '+datasetName)\n"," import kaggle\n"," run(f'mkdir -p {_install_path}/kaggle_cache')\n"," run(f'rm -rf {_install_path}/kaggle_cache/*')\n"," datasetDirPath = _install_path+'/kaggle_cache/'+datasetName\n"," run('mkdir -p '+datasetDirPath)\n"," run('cp -f '+path+' '+datasetDirPath+'/')\n"," username = getUserName()\n"," print(\"kaggle username:\"+username)\n"," datasetPath = username+'/'+datasetName\n"," datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n"," print(datasetList)\n"," if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n"," run('kaggle datasets init -p' + datasetDirPath)\n"," metadataFile = datasetDirPath+'/dataset-metadata.json'\n"," run('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n"," run('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n"," run('cat '+metadataFile)\n"," run('kaggle datasets create -p '+datasetDirPath)\n"," print('create database done')\n"," else:\n"," kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n"," kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n"," print('upload database done')\n","\n","def downloadDatasetFiles(datasetName:str,outputPath:str):\n"," if not initKaggleConfig(): return\n"," print('下载数据集文件 '+datasetName)\n"," import kaggle\n"," username = getUserName()\n"," datasetPath = username+'/'+datasetName\n"," datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n"," if datasetPath not in [str(d) for d in datasetList]:\n"," return False\n"," run('mkdir -p '+outputPath)\n"," kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n"," return True\n","\n"]},{"cell_type":"markdown","metadata":{},"source":["## 同步文件夹到 huggingface\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 文件夹与 huggingface 同步\n","if _huggingface_token:\n"," if not is_installed('watchdog'):\n"," requirements.append('watchdog')\n"," if not is_installed('huggingface_hub'):\n"," requirements.append('huggingface_hub')\n"," else:\n"," try:\n"," from huggingface_hub import HfApi,login,snapshot_download\n"," except:\n"," requirements.append('huggingface_hub')\n","\n","huggingface_is_init = False\n","\n","def init_huggingface():\n"," if not _huggingface_token:\n"," return False\n","\n"," global huggingface_headers\n"," global huggingface_is_init\n"," \n"," from huggingface_hub import login\n"," token = replace_path(_huggingface_token)\n"," if not _huggingface_token.startswith('hf_') and Path(token).exists():\n"," with open(token,encoding = \"utf-8\") as nkfile:\n"," token = nkfile.readline()\n"," if not token.startswith('hf_'):\n"," print('huggingface token 不正确,请将 token ��� 仅存放token 的txt文件路径填入 _huggingface_token 配置')\n"," return False\n"," login(token,add_to_git_credential=True)\n"," huggingface_headers = {'Authorization': 'Bearer '+token}\n"," print('huggingface token 已经加载,可以下载私有仓库或文件')\n"," \n"," huggingface_is_init = True\n"," return True\n","\n","\n","def start_sync_log_to_huggingface(repo_id:str,directory_to_watch,repo_type='dataset',file_types=['.png','.jpg','.txt','.webp','.jpeg']):\n"," if not huggingface_is_init:\n"," print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n"," \n"," if not directory_to_watch:\n"," print('请指定需要同步的本地目录 directory_to_watch')\n"," return\n"," if not Path(directory_to_watch).exists():\n"," run(f'mkdir -p {directory_to_watch}')\n"," from watchdog.observers import Observer\n"," from watchdog.events import FileSystemEventHandler\n"," from huggingface_hub import HfApi,login,snapshot_download\n"," \n"," # 配置监视的目录和 Hugging Face 仓库信息\n"," class FileChangeHandler(FileSystemEventHandler):\n"," def __init__(self, api, repo_id, repo_type,directory_to_watch):\n"," self.api = api\n"," self.repo_id = repo_id\n"," self.repo_type = repo_type\n"," self.directory_to_watch = directory_to_watch\n"," def on_created(self, event):\n"," if not event.is_directory:\n"," # 上传新文件到 Hugging Face 仓库\n"," file_path = event.src_path\n"," file_name:str = os.path.basename(file_path)\n"," print(file_name)\n"," if file_name[file_name.rindex('.'):] not in file_types: return\n"," print(file_name,'>>','huggingface')\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(self.directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except IOError as error:\n"," print(error)\n","\n"," def on_deleted(self, event):\n"," if not event.is_directory:\n"," # 从 Hugging Face 仓库删除文件\n"," file_path = event.src_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[file_name.rindex('.'):] not in file_types: return\n"," try:\n"," self.api.delete_file(\n"," path_in_repo=file_path.replace(self.directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except IOError as error:\n"," print(error)\n","\n"," def on_modified(self, event):\n"," if not event.is_directory:\n"," # 更新 Hugging Face 仓库中的文件\n"," file_path = event.src_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(self.directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except IOError as error:\n"," print(error)\n","\n"," def on_moved(self, event):\n"," if not event.is_directory:\n"," file_path = event.dest_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[file_name.rindex('.'):] not in file_types: return\n"," if event.dest_path.startswith(self.directory_to_watch):\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(self.directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except IOError as error:\n"," print(error)\n","\n"," api = HfApi()\n"," \n"," # 创建观察者对象并注册文件变化处理程序\n"," event_handler = FileChangeHandler(api,repo_id,repo_type,directory_to_watch)\n"," observer = Observer()\n"," observer.schedule(event_handler, directory_to_watch, recursive=True)\n","\n"," # 启动观察者\n"," observer.name = \"solo_directory_to_watch\"\n"," print(f'启动目录同步,{directory_to_watch} 将自动同步到 huggingface {repo_type} : {repo_id}')\n"," observer.start()"]},{"cell_type":"markdown","metadata":{"id":"sswa04veLCtE"},"source":["## 工具函数\n","**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"trusted":true},"outputs":[],"source":["\n","def zipPath(path:str,zipName:str,format='tar'):\n"," if path.startswith('$install_path'):\n"," path = path.replace('$install_path',_install_path)\n"," if path.startswith('$output_path'):\n"," path = path.replace('$install_path',_output_path)\n"," if not path.startswith('/'):\n"," path = f'{_install_path}/{_ui_dir_name}/{path}'\n"," if Path(path).exists():\n"," if 'tar' == format:\n"," run(f'tar -cf {_output_path}/'+ zipName +'.tar -C '+ path +' . ')\n"," elif 'gz' == format:\n"," run(f'tar -czf {_output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')\n"," return\n"," print('指定的目录不存在:'+path)\n"]},{"cell_type":"markdown","metadata":{},"source":["## 内网穿透\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"id":"coqQvTSLLCtE","trusted":true},"outputs":[],"source":["def printUrl(url,name=''):\n"," print(f'{name} 访问地址:{url}')\n"," for key in sorted(_proxy_path.keys(), key=len)[::-1]:\n"," print(f'{name} 本地服务:{_proxy_path[key]} 访问地址:{url}{key}')\n","# ngrok\n","def startNgrok(ngrokToken:str,ngrokLocalPort:int):\n"," if not is_installed('pyngrok'):\n"," run('pip install pyngrok')\n"," from pyngrok import conf, ngrok\n"," try:\n"," conf.get_default().auth_token = ngrokToken\n"," conf.get_default().monitor_thread = False\n"," ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n"," url = ''\n"," if len(ssh_tunnels) == 0:\n"," ssh_tunnel = ngrok.connect(ngrokLocalPort)\n"," url = ssh_tunnel.public_url\n"," print('ngrok 访问地址:'+ssh_tunnel.public_url)\n"," else:\n"," print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n"," url = ssh_tunnels[0].public_url\n"," printUrl(url,'ngrok')\n"," def auto_request_ngrok():\n"," if url:\n"," while(_runing):\n"," time.sleep(60*1)\n"," try:\n"," res = requests.get(url+'/',headers={\"ngrok-skip-browser-warning\" : \"1\"},timeout=10)\n"," except:\n"," ''\n"," # print('自动调用ngrok链接以保存链接不会断开',res.status_code)\n","\n"," # threading.Thread(target = auto_request_ngrok,daemon=True,name='solo_auto_request_ngrok').start()\n"," except:\n"," print('启动ngrok出错')\n"," \n","def load_frpc_config(conf_or_file,dost_port=None):\n"," frpcStartArg = ''\n"," _frp_temp_config_file = ''\n"," _frp_config_or_file = conf_or_file\n"," run(f'''mkdir -p {_install_path}/configFiles''')\n"," if _frp_config_or_file:\n"," if '[common]' in _frp_config_or_file:\n"," echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_{dost_port or _server_port}.ini')\n"," _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_{dost_port or _server_port}.ini'\n"," elif '.ini' in _frp_config_or_file:\n"," _frp_temp_config_file = _frp_config_or_file.strip()\n"," \n"," if _frp_temp_config_file:\n"," if Path(_frp_temp_config_file).exists():\n"," run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini''')\n"," run(f'''sed -i \"s/local_port = .*/local_port = {dost_port or _server_port}/g\" {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini''')\n"," frpcStartArg = f' -c {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini'\n"," elif _frp_config_or_file.strip().startswith('-f'):\n"," frpcStartArg = _frp_config_or_file.strip()\n"," return frpcStartArg\n","\n","def startFrpc(name,configFile):\n"," if not Path(f'{_install_path}/frpc/frpc').exists():\n"," installFrpExe()\n"," if freefrp_url:\n"," printUrl(freefrp_url,'freefrp')\n"," echoToFile(f'''\n","cd {_install_path}/frpc/\n","{_install_path}/frpc/frpc {configFile}\n","''',f'{_install_path}/frpc/start.sh')\n"," get_ipython().system(f'''bash {_install_path}/frpc/start.sh''')\n"," \n","def installFrpExe():\n"," if _useFrpc:\n"," print('安装frpc')\n"," run(f'mkdir -p {_install_path}/frpc')\n"," if Path(frpcExePath).exists():\n"," run(f'cp -f -n {frpcExePath} {_install_path}/frpc/frpc')\n"," else:\n"," run(f'wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O {_install_path}/frpc/frpc')\n"," \n"," for ssl in frpcSSLFFlies:\n"," if Path(ssl).exists():\n"," run(f'cp -f -n {ssl}/* {_install_path}/frpc/')\n"," run(f'chmod +x {_install_path}/frpc/frpc')\n"," run(f'{_install_path}/frpc/frpc -v')\n","\n","def startProxy():\n"," if _useNgrok:\n"," startNgrok(ngrokToken,_server_port)\n"," if _useFrpc:\n"," startFrpc('frpc_proxy',frpcStartArg)"]},{"cell_type":"markdown","metadata":{},"source":["## NGINX 反向代理\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"outputs":[],"source":["\n","# nginx 反向代理配置文件\n","def localProxy():\n"," def getProxyLocation(subPath:str, localServer:str):\n"," return '''\n"," location '''+ subPath +'''\n"," {\n"," proxy_pass '''+ localServer +''';\n"," proxy_set_header Host $host;\n"," proxy_set_header X-Real-IP $remote_addr;\n"," proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"," proxy_set_header REMOTE-HOST $remote_addr;\n"," proxy_set_header Upgrade $http_upgrade;\n"," proxy_set_header Connection upgrade;\n"," proxy_http_version 1.1;\n"," proxy_connect_timeout 10m;\n"," proxy_read_timeout 10m;\n"," }\n"," \n"," '''\n"," \n"," conf = '''\n","server\n","{\n"," listen '''+str(_server_port)+''';\n"," listen [::]:'''+str(_server_port)+''';\n"," server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n"," \n"," if ($request_method = OPTIONS) {\n"," return 200;\n"," }\n"," fastcgi_send_timeout 10m;\n"," fastcgi_read_timeout 10m;\n"," fastcgi_connect_timeout 10m;\n"," \n"," '''+ ''.join([getProxyLocation(key,_proxy_path[key]) for key in sorted(_proxy_path.keys(), key=len)[::-1]]) +'''\n","}\n","'''\n"," echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n"," if not check_service('localhost',_server_port):\n"," run(f'''nginx -c /etc/nginx/nginx.conf''')\n"," run(f'''nginx -s reload''')"]},{"cell_type":"markdown","metadata":{},"source":["## 线程清理工具\n","\n","---\n","\n","清理线程名以 solo_ 开头的所有线程"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"trusted":true},"outputs":[],"source":["import inspect\n","import ctypes\n","\n","def _async_raise(tid, exctype):\n"," \"\"\"raises the exception, performs cleanup if needed\"\"\"\n"," tid = ctypes.c_long(tid)\n"," if not inspect.isclass(exctype):\n"," exctype = type(exctype)\n"," res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n"," if res == 0:\n"," raise ValueError(\"invalid thread id\")\n"," elif res != 1:\n"," # \"\"\"if it returns a number greater than one, you're in trouble,\n"," # and you should call it again with exc=NULL to revert the effect\"\"\"\n"," ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n"," raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n","\n","def stop_thread(thread):\n"," _async_raise(thread.ident, SystemExit)\n","\n","def stop_solo_threads():\n"," global _runing\n"," _runing = False\n"," # 获取当前所有活动的线程\n"," threads = threading.enumerate()\n"," # 关闭之前创建的子线程\n"," for thread in threads:\n"," if thread.name.startswith('solo_'):\n"," print(f'结束线程:{thread.name}')\n"," try:\n"," stop_thread(thread)\n"," except socket.error:\n"," print(f'结束线程:{thread.name} 执行失败')\n"," "]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["docs = '''\n","# 配置项\n","server_port int 本地服务端口,穿透使用的端口\n","huggingface_token string huggingface token,用于同步文件或者下载需要登录的文件\n","hidden_console_info bool 是否隐藏控制台信息\n","proxy_path {string:string} 将哪个路径映射到哪个服务,格式为:{'/':'http://127.0.0.1:5000/'}\n","kaggle_api_token string kaggle api token,用于访问kaggle的api\n","ngrok_config_or_file ngrok的token文件内容或者放token的文件的路径\n","frp_config_or_file frp的配置内容或者配置文件的路径\n","frp_ssl_dir frp的https证书存放目录\n","# 工具函数\n","执行cmd命令:\n","run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True)\n","检查网络是否可以访问\n","check_service(host, port)\n","检查gpu是否存在\n","check_gpu()\n","写入文本到文件\n","echoToFile(content:str,path:str)\n","获取一个免费frp配置\n","get_freefrp_confog(local_port)\n","\n","下载文件\n","link_or_download_flie(config:str, \n","skip_url:bool=False, \n","_link_instead_of_copy:bool=True, \n","base_path:str = '',\n","sync:bool=False, # 同步且按顺序下载\n","thread_num:int=None, \n","is_await:bool=False) # 异步不按顺序但等待下载完成\n","---- 下载文件功能的配置的格式\n","[目标目录] # 中括号必须写\n","下载链接1\n","名称:下载链接2 # 链接前面的名称可以用于对文件重命名\n","# 备注 井号后面的内容会被忽略\n","可以下载git仓库\n","可以下载huggingfacec仓库或者文件,会使用 huggingface_token 作为凭证下载\n","可以下载其他可以直接下载的互联网资源\n","可以作为文件链接功能,将某个目录或目录下的全部文件链接到目标目录\n","---- 下载文件功能结束结束\n","\n","创建kaggle数据集\n","createOrUpdateDataSet(path:str,datasetName:str)\n","下载kaggle数据集\n","downloadDatasetFiles(datasetName:str,outputPath:str)\n","同步目录到huggingface,可指定同步的文件类型\n","start_sync_log_to_huggingface(repo_id:str,directory_to_watch,repo_type='dataset',file_types=['.png','.jpg','.txt','.webp','.jpeg'])\n","压缩指定目录到指定位置\n","zipPath(path:str,zipName:str,format='tar') # 可用tar或gz\n","停止后台线程 # 仅停止线程名称前缀为 solo_ 的线程\n","stop_solo_threads()\n","'''\n","def get_docs():\n"," print(docs)\n"," \n","print('可以执行get_docs()查看文档')"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["if not (True if os.getenv('IS_INSTALL_NGINX','False') == 'True' else False):\n"," run('git lfs install')\n"," run('git config --global credential.helper store')\n"," run('sudo apt update -y')\n"," run('sudo apt install nginx -y')\n"," os.environ['IS_INSTALL_NGINX'] = 'True'\n","stop_solo_threads()\n","time.sleep(2)\n","threading.Thread(target = startProxy, daemon=True, name='solo_startProxy').start()\n","localProxy()\n","init_huggingface()"]}],"metadata":{"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"datasetId":2716934,"sourceId":6167400,"sourceType":"datasetVersion"},{"datasetId":3654544,"sourceId":6346544,"sourceType":"datasetVersion"},{"datasetId":2962375,"sourceId":6720235,"sourceType":"datasetVersion"},{"datasetId":3074484,"sourceId":6817788,"sourceType":"datasetVersion"}],"isGpuEnabled":true,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.13"}},"nbformat":4,"nbformat_minor":4}
 
 
lite-start.ipynb DELETED
@@ -1 +0,0 @@
1
- {"cells":[{"cell_type":"markdown","metadata":{},"source":["# NovelAi stable-diffusion-webui+api+sdxl\n","---\n","**version: 1.6.0  •  python: 3.10.6  •  torch: 2.0.1+cu118  •  xformers: 0.0.21  •  gradio: 3.41.2**\n","- 发布地址 [kaggle stable-diffusion-webui-novelai](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)\n","- 这是一个用于快速体验ai绘画项目 [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 的笔记本,你可以直接启动就能在线体验ai绘图的乐趣。 \n","- kaggle和colab都是AI学习平台,请勿浪费计算资源,如果有需求,可以考虑AutoDL这类租用显卡的平台或者colab付费使用。\n","- 在保持可以免配置直接启动的情况下也提供了很多可自定义的配置,在下方的配置项里,请自行查看。 \n","- 同时也为新人提供了一份基础的帮助文档,包含了一些使用中可能遇到的问题,如果使用过程中有什么疑问,不妨先看看帮助文档。\n","- 如果你需要在此脚本上修改再发布,请随意,但请遵守相关法律法规,文明使用。\n","- 使用时如果遇到问题,尽可能通过帮助文档或者参考已有内容尝试自己解决。\n","- Q群 [816545732](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=OGQydingTPku9M_myV_cscWv6MVaCSde&authKey=RFadQ18FgReFkx7CRs8SNk4vHpxHz%2FD2ojHL3433MehuQOBlnG0hhWFIo8AX%2BFRU&noverify=0&group_code=816545732) ,这是我建的新群,如果有需要,可以进群,其实这个笔记已经非常简洁了,进群大概也不会有啥帮助。\n","- 使用前可以看一下最后的更新日志,可能有功能更新需要注意"]},{"cell_type":"markdown","metadata":{},"source":["## 重要文件列表\n","\n","- **这个列表仅加载一次 且会等待加载完成再开始安装sd**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["before_downloading = '''# 这个列表仅加载一次 且会等待加载完成再开始安装sd\n","[extensions] # 插件\n","https://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\n","https://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\n","https://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\n","https://github.com/Mikubill/sd-webui-controlnet.git\n","https://github.com/ilian6806/stable-diffusion-webui-state.git\n","https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\n","https://github.com/Bing-su/adetailer.git\n","https://github.com/zanllp/sd-webui-infinite-image-browsing.git\n","https://github.com/viyiviyi/stable-diffusion-webui-zoomimage.git\n","https://github.com/viyiviyi/prompts-filter.git zz_prompts-filter\n","https://github.com/viyiviyi/sd-encrypt-image.git # 图片加密插件,解决涩图封号问题,需要在参数里设置你的密码开启\n","https://github.com/nonnonstop/sd-webui-3d-open-pose-editor.git\n","https://github.com/jexom/sd-webui-depth-lib.git\n","https://github.com/Elldreth/loopback_scaler.git\n","https://github.com/hnmr293/sd-webui-cutoff.git\n","https://github.com/hako-mikan/sd-webui-lora-block-weight.git\n","https://github.com/viyiviyi/Stable-Diffusion-Webui-Civitai-Helper.git # 修改过的c站助手,下载的缩略图可以被加密插件加密\n","https://github.com/viyiviyi/sd-civitai-browser-plus.git\n","https://github.com/adieyal/sd-dynamic-prompts.git\n","https://github.com/hako-mikan/sd-webui-supermerger.git\n","https://github.com/thisjam/sd-webui-oldsix-prompt.git\n","https://github.com/NoCrypt/sd-fast-pnginfo.git\n","https://github.com/ArtVentureX/sd-webui-agent-scheduler.git\n","https://github.com/continue-revolution/sd-webui-animatediff.git animatediff\n","https://github.com/mcmonkeyprojects/sd-dynamic-thresholding.git\n","\n","# 如果你有模型文件需要在启动前加载,可以写在这个下面对应位置\n","\n","[models/Stable-diffusion] # 大模型列表\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","\n","[models/VAE] # VAE文件列表\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","\n","# 通过这个功能安装一个ComfyUI\n","[{install_path}]\n","https://github.com/comfyanonymous/ComfyUI.git ComfyUI\n","\n","[{install_path}/ComfyUI/custom_nodes] # ComfyUI 节点模块\n","https://github.com/viyiviyi/comfyui-encrypt-image.git # 加密���件,安装后就会加密,默认密码123qwe,在utils下增加了一个预览和设置密码的节点\n","https://github.com/ltdrdata/ComfyUI-Manager.git\n","https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes.git\n","https://github.com/cubiq/ComfyUI_IPAdapter_plus.git\n","https://github.com/jags111/efficiency-nodes-comfyui.git\n","https://github.com/twri/sdxl_prompt_styler.git\n","https://github.com/ssitu/ComfyUI_UltimateSDUpscale --recursive\n","https://github.com/ltdrdata/ComfyUI-Impact-Pack.git\n","https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git\n","https://github.com/giriss/comfy-image-saver.git\n","https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git AnimateDiff\n","https://github.com/SLAPaper/ComfyUI-Image-Selector.git\n","https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git\n","https://github.com/Fannovel16/comfyui_controlnet_aux.git\n","https://github.com/mav-rik/facerestore_cf.git\n","https://github.com/FizzleDorf/ComfyUI_FizzNodes.git\n","https://github.com/BadCafeCode/masquerade-nodes-comfyui.git\n","https://github.com/WASasquatch/was-node-suite-comfyui.git\n","https://github.com/YMC-GitHub/ymc-node-suite-comfyui.git\n","https://github.com/coreyryanhanson/ComfyQR.git\n","https://github.com/melMass/comfy_mtb.git\n","https://github.com/sipherxyz/comfyui-art-venture.git\n","https://github.com/cubiq/ComfyUI_essentials.git\n","https://github.com/Gourieff/comfyui-reactor-node.git\n","\n","[{install_path}/ComfyUI/web/extensions] # ComfyUI web插件\n","https://github.com/viyiviyi/comfyui-mobile.git\n","https://github.com/viyiviyi/comfyui-popup-image-prevew.git\n","\n","'''"]},{"cell_type":"markdown","metadata":{},"source":["## 普通文件列表\n","\n","- **这个列表仅加载一次 且不会等待加载完成**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["async_downloading='''# 这个列表仅加载一次 且不会等待加载完成\n","[extensions] # 插件 如果你没有使用ngrok或者frpc,请不要把插件放在这里加载,因为这里的文件可能在webui启动后才加载完成\n","\n","[models/ESRGAN]\n","https://huggingface.co/lokCX/4x-Ultrasharp/blob/main/4x-UltraSharp.pth\n","\n","[models/VAE] # VAE文件列表\n","{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-ema-560000-ema-pruned.safetensors\n","{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-mse-840000-ema-pruned.safetensors\n","sdxl_vae.safetensors:https://huggingface.co/madebyollin/sdxl-vae-fp16-fix/resolve/main/sdxl_vae.safetensors?download=true # sdxl模型需要sdxl的vae\n","\n","[models/Stable-diffusion] # 大模型列表\n","# https://civitai.com/api/download/models/293564\n","/kaggle/input/anime-xl/animagineXLV3_v30.safetensors\n","/kaggle/input/kohakuxl/kohaku-xl-delta-rev.safetensors\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","https://civitai.com/api/download/models/116970\n","https://civitai.com/api/download/models/117151 # Clothing +/- Adjuster 衣物增/减 LoRA\n","https://civitai.com/api/download/models/62833 # Detail Tweaker LoRA (细节调整LoRA)\n","\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors\n","# https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors\n","\n","[extensions/animatediff/model] # animatediff 插件基本模型\n","# https://huggingface.co/guoyww/animatediff/resolve/cd71ae134a27ec6008b968d6419952b0c0494cf2/mm_sd_v15_v2.ckpt\n","\n","[models/Lora/animatediff] # animatediff lora模型\n","# https://huggingface.co/guoyww/animatediff/resolve/cd71ae134a27ec6008b968d6419952b0c0494cf2/v2_lora_PanLeft.ckpt\n","'''\n"]},{"cell_type":"markdown","metadata":{},"source":["## 按顺序加载的重要文件列表\n","\n","- **这个列表每次 run all 启动都会加载一次,且一定按照顺序加载后才启动webui**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["before_start_sync_downloading = ''' # 这个列表每次 run all 启动都会加载一次,且一定按照顺序加载\n","\n","# 如果你需要每次启动都加载一下文件,可以写在这。(比如测试路径是否正确的时候)\n","\n","[models/Stable-diffusion] # 大模型列表\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","\n","[models/VAE] # VAE文件列表\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","\n","'''"]},{"cell_type":"markdown","metadata":{},"source":["## webui 启动参数\n","- 所有的参数都会在启动时传入\n","- 可以在前面加```#```来屏蔽某个参数\n","- 端口参数需要在下一个代码块的```webuiPort```处修改"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["sd_start_args='''\n","# --ckpt=mg-Tender.safetensors # 默认模型名称,路径不能包含空格\n","--disable-safe-unpickle \n","--deepdanbooru \n","--no-hashing \n","--no-download-sd-model \n","--administrator\n","--skip-torch-cuda-test \n","--skip-version-check \n","--disable-nan-check\n","--opt-sdp-attention \n","--opt-sdp-no-mem-attention \n","--xformers-flash-attention\n","--xformers\n","--api \n","--listen\n","--lowram\n","#--no-gradio-queue\n","--encrypt-pass=123qwe # 图片加密插件的密码,如果要启用图片加密插件,删除这一行前面的#和将123qwe改成你的密码,也可以不改\n","# --share # 默认的内网穿透在kaggle和colab都已经不可用,请考虑其他方案\n","--disable-console-progressbars\n","--no-half-vae \n","# --no-half #关闭半精度\n","# --enable-console-prompts\n","# --nowebui # 如果只需要api服务,可以开启这个\n","# --api-auth=2333:6666 # api密码\n","# --gradio-auth=2333:6666 # webui密码\n","'''"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# 这个方法内的函数会在所有文件加载完成,准备启动前执行,可以放一些自定义的逻辑功能\n","def on_before_start():\n"," '''这是一个空的函数'''\n"," run(f'{_install_path}/{_ui_dir_name}/venv/bin/python3 -s -m pip install insightface',cwd=os.path.join(f'{install_path}/{ui_dir_name}',node))\n"," def get_folder_list(directory:str): \n"," folder_list = [] \n"," for item in os.listdir(directory): \n"," if os.path.isdir(os.path.join(directory, item)): \n"," folder_list.append(item) \n"," return folder_list \n"," # 启动 ComfyUI\n"," def start_comfyui():\n"," !rm -rf {install_path}/ComfyUI/models/checkpoints\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/Stable-diffusion {install_path}/ComfyUI/models/checkpoints\n"," !rm -rf {install_path}/ComfyUI/models/embeddings\n"," !ln -s -r {_install_path}/{_ui_dir_name}/embeddings {install_path}/ComfyUI/models/embeddings\n"," !rm -rf {install_path}/ComfyUI/models/loras\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/Lora {install_path}/ComfyUI/models/loras\n"," !rm -rf {install_path}/ComfyUI/models/vae\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/VAE {install_path}/ComfyUI/models/vae\n"," !rm -rf {install_path}/ComfyUI/models/hypernetworks\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/hypernetworks {install_path}/ComfyUI/models/hypernetworks\n"," !rm -rf {install_path}/ComfyUI/models/upscale_models\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/ESRGAN {install_path}/ComfyUI/models/upscale_models\n"," !rm -rf {install_path}/ComfyUI/models/controlnet\n"," !ln -s -r {_install_path}/{_ui_dir_name}/extensions/sd-webui-controlnet/models {install_path}/ComfyUI/models/controlnet\n"," !rm -rf {install_path}/ComfyUI/custom_nodes/AnimateDiff/models\n"," !ln -s -r {_install_path}/{_ui_dir_name}/extensions/animatediff/model {install_path}/ComfyUI/custom_nodes/AnimateDiff/models\n"," !rm -rf {install_path}/ComfyUI/custom_nodes/AnimateDiff/motion_lora\n"," !ln -s -r {_install_path}/{_ui_dir_name}/models/Lora/animatediff {install_path}/ComfyUI/custom_nodes/AnimateDiff/motion_lora\n"," _cwd = os.getcwd()\n"," \n"," def start(device:int):\n"," print(f'启动 comfyui {device}')\n"," %cd {install_path}/ComfyUI \n"," !{_install_path}/{_ui_dir_name}/venv/bin/python3 main.py --force-fp16 --cuda-device={device} --port={8188+device}\n"," %cd {_cwd}\n"," print(f'下载 comfyui 各节点的依赖')\n"," for node in get_folder_list(f'{install_path}/ComfyUI/custom_nodes'):\n"," print(os.path.join(f'{install_path}/ComfyUI/custom_nodes',node))\n"," if Path(os.path.join(f'{install_path}/ComfyUI/custom_nodes',node,'requirements.txt')).exists():\n"," run(f'{_install_path}/{_ui_dir_name}/venv/bin/python3 -s -m pip install -r requirements.txt',cwd=os.path.join(f'{install_path}/ComfyUI/custom_nodes',node))\n"," \n"," print(f'启动 comfyui')\n"," for device in range(torch.cuda.device_count() if _multi_case else 1):\n"," threading.Thread(target = start, daemon=True,args=([device]), name=f'solo_start_comfyui_{device}').start()\n"," \n"," threading.Thread(target = start_comfyui, daemon=True, name='solo_start_comfyui').start()\n"," \n"," # 安装一个文件浏览器 通过在访问地址后加 /fslist/ 访问\n"," def start_filebrower():\n"," !curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash\n"," !filebrowser -p 8012 --username admin -b /fslist -r {install_path}\n"," \n"," threading.Thread(target = start_filebrower, daemon=True, name='solo_start_filebrower').start()\n"," ## 下面可以写更多自定义逻辑"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才会生效\n","#Ngrok\n","useNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n","#Frpc\n","useFrpc=True # 开启frp将不能启动\n","\n","#可以填写文件路径 或 直接填 token 内容\n","ngrok_config_or_file = '''\n","{input_path}/configs/ngrok_token.txt\n","'''\n","frp_config_or_file = '''\n","{input_path}/configs/frpc_koishi.ini\n","'''\n","frp_ssl_dir = '''\n","{input_path}/configs/koishi_ssl\n","'''\n","\n","# 配置启动参数\n","server_port=7860 # webui 默认端口\n","\n","# 仓库地址 这是修改过界面布局顺序的webui,不定期同步到官方版本\n","# 如果要使用官方版本,改成这个: https://github.com/AUTOMATIC1111/stable-diffusion-webui\n","sd_git_repo='https://github.com/viyiviyi/stable-diffusion-webui.git -b local-1.9' \n","# 配置文件,包括webui的设置和UI默认值,如果要自定义,fork这个仓库后修改并把地址替换这个地址\n","sd_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git -b main-yiyiooo'\n","# 设置文件保存路径 当使用谷歌云盘时非常有用\n","setting_file = '{output_path}/configs/config.json'\n","ui_config_file = '{output_path}/configs/ui-config.json'\n","\n","# 这是配置文件夹同步的相关配置\n","# 需要在huggingface创建一个数据集(datasets) 然后把数据集的名称(在页面上有复制的按钮)填到 huggingface_repo \n","# 需要获取 token 填到 huggingface_token 获取的地址是: https://huggingface.co/settings/tokens\n","huggingface_token = '{input_path}/configs/huggingface_token.txt'\n","huggingface_repo = 'viyi/sdwui-log'\n","\n","# 自定义本地反向代理 这些配置将会成为nginx的反向代理配置,用于实现一个穿透访问多个实例\n","# 默认情况下 / 被代理到了webui;/1/ 被代理到了第二个webui\n","proxy_path={\n"," '/cui/':'http://127.0.0.1:8188/',\n"," '/cui2/':'http://127.0.0.1:8189/',\n"," '/fslist/':'http://127.0.0.1:8012/',\n","} # 增加一个comfyui的代理\n","\n","multi_case = True"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["link_instead_of_copy = True # 下载或加载Input的文件时是使用链接还是复制的方式加载到目标目录\n","hidden_console_info = True # 是否隐藏大部分的控制台内容"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 保存当前目录和启动时cd到之前保存的目录,可以减少sdwui-start-new.ipynb文件下载次数\n","import os\n","INIT_WORK_PATH = os.environ['HOME']\n","if os.getenv('INIT_WORK_PATH',''):\n"," INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\n","else:\n"," os.environ['INIT_WORK_PATH'] = os.getcwd()\n","%cd {INIT_WORK_PATH}"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["reLoad = True\n","# 如果需要重新安装,请注释下面这一行\n","reLoad = False"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import signal \n","import sys\n","\n","def auto_exit(signum,frame):\n"," print('自动结束运行')\n"," signal.alarm(0)\n"," sys.exit(0)\n","\n","signal.signal(signal.SIGALRM, auto_exit)\n","signal.alarm(3*60*60) # 定时关机时间,12小时 x 60分钟 x 60秒 当需要提前关机时可以修改数值"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["if not os.path.exists('sdwui-start-util.ipynb'):\n"," !wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start-util.ipynb -o log.log\n","%run sdwui-start-util.ipynb"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["try:\n"," check_gpu() # 检查是否存在gpu\n"," main()\n"," signal.alarm(0)\n","except KeyboardInterrupt:\n"," stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)\n"," signal.alarm(0)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 打包收藏文件夹 如果需要可以取消下面两行的注释\n","# zipPath('$install_path/sd_main_dir/log','log')\n","# !mv {output_path}/log.tar {output_path}/log.tar.bak\n","# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n","\n","# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n","# zipPath('$install_path/sd_main_dir/textual_inversion','训练输出') \n","# zipPath('$install_path/sd_main_dir/outputs','outputs')\n","\n","# 打包venv并上传到数据集\n","# zipPath('$install_path/sd_main_dir/venv','venv')\n","# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n","# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n","\n","# 打包命令参考,--exclude 可以排除不需要打包的目录\n","# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /sd_main_dir/ ."]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.7"}},"nbformat":4,"nbformat_minor":4}
 
 
sdwui-before-new.ipynb DELETED
@@ -1 +0,0 @@
1
- {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# NovelAi stable-diffusion-webui+api+sdxl\n---\n**version: 1.6.0  •  python: 3.10.6  •  torch: 2.0.1+cu118  •  xformers: 0.0.21  •  gradio: 3.41.2**\n- 发布地址 [kaggle stable-diffusion-webui-novelai](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)\n- 这是一个用于快速体验ai绘画项目 [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 的笔记本,你可以直接启动就能在线体验ai绘图的乐趣。 \n- 在保持可以免配置直接启动的情况下也提供了很多可自定义的配置,在下方的配置项里,请自行查看。 \n- 同时也为新人提供了一份基础的帮助文档,包含了一些使用中可能遇到的问题,如果使用过程中有什么疑问,不妨先看看帮助文档。\n- 如果你需要在此脚本上修改再发布,请随意,但请遵守相关法律法规,文明使用。\n- 交流群632428790 这是 [qq2575044704](https://www.kaggle.com/qq2575044704) 的群,感谢他为这个笔记做了一些宣传。\n","metadata":{}},{"cell_type":"markdown","source":"## 重要文件列表\n\n- **这个列表仅加载一次 且会等待加载完成**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"重要文件列表 = '''# 这个列表仅加载一次 且会等待加载完成\n[extensions] # 插件\nhttps://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\nhttps://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\nhttps://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\nhttps://github.com/Mikubill/sd-webui-controlnet.git\nhttps://github.com/LianZiZhou/sd-webui-pixink-console.git\nhttps://github.com/ilian6806/stable-diffusion-webui-state.git\nhttps://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\nhttps://github.com/Bing-su/adetailer.git\nhttps://github.com/civitai/sd_civitai_extension.git\nhttps://github.com/zanllp/sd-webui-infinite-image-browsing.git\nhttps://github.com/viyiviyi/stable-diffusion-webui-zoomimage.git\n\n# 如果你有模型文件需要在启动前加载,可以写在这个下面对应位置\n\n[models/Stable-diffusion] # 大模型列表\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\n\n[models/VAE] # VAE文件列表\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 普通文件列表\n\n- **这个列表仅加载一次 且不会等待加载完成**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"普通文件列表='''# 这个列表仅加载一次 且不会等待加载完成\n[extensions] # 插件 如果你没有使用ngrok或者frpc,请不要把插件放在这里加载,因为这里的文件可能在webui启动后才加载完成\n\n[models/Stable-diffusion] # 大模型列表\nmg-Tender.safetensors:https://civitai.com/api/download/models/75587\n容华_国风_SDXL.safetensors:https://civitai.com/api/download/models/151978\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\nGenshin_Impact_all-in-one.safetensors:https://civitai.com/api/download/models/116970\nhttps://civitai.com/api/download/models/117151 # Clothing +/- Adjuster 衣物增/减 LoRA\nhttps://civitai.com/api/download/models/62833 # Detail Tweaker LoRA (细节调整LoRA)\n\n[models/VAE] # VAE文件列表\n{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-ema-560000-ema-pruned.safetensors\n{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-mse-840000-ema-pruned.safetensors\nhttps://huggingface.co/stabilityai/sd-vae-ft-ema-original/resolve/main/vae-ft-ema-560000-ema-pruned.safetensors\nhttps://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\nsdxl_vae.safetensors:https://civitai.com/api/download/models/130720?type=VAE # sdxl模型需要sdxl的vae\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors\n'''\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 按顺序加载的重要文件列表\n\n- **这个列表每次 run all 启动都会加载一次,且一定按照顺序加载后才启动webui**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"按顺序加载的重要文件列表 = ''' # 这个列表每次 run all 启动都会加载一次,且一定按照顺序加载\n\n# 如果你需要每次启动都加载一下文件,可以写在这。(比如测试路径是否正确的时候)\n\n[models/Stable-diffusion] # 大模型列表\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\n\n[models/VAE] # VAE文件列表\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## webui 启动参数\n- 所有的参数都会在启动时传入\n- 可以在前面加```#```来屏蔽某个参数\n- 端口参数需要在下一个代码块的```webuiPort```处修改","metadata":{}},{"cell_type":"code","source":"参数列表='''\n# --ckpt=mg-Tender.safetensors # 默认模型名称,路径不能包含空格\n--disable-safe-unpickle \n--deepdanbooru \n--no-hashing \n--no-download-sd-model \n--administrator\n--skip-torch-cuda-test \n--skip-version-check \n--disable-nan-check\n# --opt-sdp-attention \n--opt-sdp-no-mem-attention \n--xformers-flash-attention\n--xformers\n--api \n--listen\n--lowram\n--no-gradio-queue\n--share\n--disable-console-progressbars\n--no-half-vae \n# --no-half #关闭半精度\n# --enable-console-prompts\n# --nowebui\n# --api-auth=2333:6666 # api密码\n# --gradio-auth=2333:6666 # webui密码\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才会生效\n#Ngrok\nuseNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n#Frpc\nuseFrpc=True # 开启frp将不能启动\n\n#文件或直接填配置\nngrok配置或文件地址='''\n{input_path}/configs/ngrok_token.txt\n'''\nfrp配置文件或配置='''\n{input_path}/configs/frpc_litechat.ini\n'''\nfrpSSL文件='''\n{input_path}/configs/litechat_nginx\n'''\n\n# 配置启动参数\nwebuiPort=7860 # webui默认端口\n\n# 仓库地址 这是修改过界面布局顺序的webui,不定期同步到官方版本\n# 如果要使用官方版本,改成这个: https://github.com/AUTOMATIC1111/stable-diffusion-webui\nwebui_git_repo='https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n# 配置文件,包括webui的设置和UI默认值,如果要自定义,fork这个仓库后修改并把地址替换这个地址\nwebui_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git'\n# 设置文件保存路径 当使用谷歌云盘时非常有用\nsetting_file = '{output_path}/configs/config.json'\nui_config_file = '{output_path}/configs/ui-config.json'\n\n# 这是配置文件夹同步的相关配置\n# 需要在huggingface创建一个数据集(datasets) 然后把数据集的名称(在页面上有复制的按钮)填到 huggingface_repo \n# 需要获取 token 填到 huggingface_token 获取的地址是: https://huggingface.co/settings/tokens\nhuggingface_token = '{input_path}/configs/huggingface_token.txt'\nhuggingface_repo = 'viyi/sdwui-log'\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"link_instead_of_copy = True # 下载或加载Input的文件时是使用链接还是复制的方式加载到目标目录\nhidden_console_info = True # 是否隐藏大部分的控制台内容","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 保存当前目录和启动时cd到之前保存的目录,可以减少sdwui-start-new.ipynb文件下载次数\nimport os\nINIT_WORK_PATH = os.environ['HOME']\nif os.getenv('INIT_WORK_PATH',''):\n INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\nelse:\n os.environ['INIT_WORK_PATH'] = os.getcwd()\n%cd {INIT_WORK_PATH}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reLoad = True\n# 如果需要重新安装,请注释下面这一行\nreLoad = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not os.path.exists('sdwui-start-new.ipynb'):\n !wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start-new.ipynb -o log.log\n%run sdwui-start-new.ipynb","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 打包收藏文件夹 如果需要可以取消下面两行的注释\n# zipPath('$install_path/stable-diffusion-webui/log','log')\n# !mv {output_path}/log.tar {output_path}/log.tar.bak\n# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n\n# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n# zipPath('$install_path/stable-diffusion-webui/textual_inversion','训练输出') \n# zipPath('$install_path/stable-diffusion-webui/outputs','outputs')\n\n# 打包venv并上传到数据集\n# zipPath('$install_path/stable-diffusion-webui/venv','venv')\n# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n\n# 打包命令参考,--exclude 可以排除不需要打包的目录\n# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /kaggle/stable-diffusion-webui/ .","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 使用帮助\n---\n**代码块不能删除也不能调换顺序,如果出现变量未定义,请检查是否按顺序执行了代码块**\n\n---\n\n## kaggle账号\n- 注册账号需要手机号,国内手机号也行,如果点击注册后没反应,估计是需要梯子,用于人机验证\n- 注册后点此笔记的 **Copy & Edit** 按钮就进到编辑界面\n\n## 准备工作\n1. 右侧面板 **Notebook options/ACCELERATOR** 需要选择GPU **T4x2**出图更快\n2. 右侧面板 **Notebook options/LANGUAGE** 需要选择Python\n2. 右侧面板 **Notebook options/PERSISTENCE** 建议选择 Files only **作用是保存Outpot目录内的文件,当前这个功能并没有任何作用**\n3. 右侧面板 **Notebook options/ENVIRONMENT** 建议不改这个配置,使用当前默认值就行\n4. 右侧面板 **Notebook options/INTERNET** 需要打开 用于联网\n\n## 启动\n#### 启动方式一 **直接点击页面上边的 RunAll**\n- 手机端可能会出现页面上边的工具栏不显示的情况,左侧菜单按钮里也有相关的操作\n- 长时间不操作页面会导致脚本停止 (应该是40分钟吧)\n\n#### 启动方式二 **使用页面上边的 Save Version 后台运行**\n- 后台运行不用担心长时间不操作脚本停止\n- Version Type 选择 **Save & Run All**\n- 在Save Version弹窗里需要选择使用**GPU**环境 (Advanced Settings 里最后一个选项)\n\n## 访问\n- 如果你使用了ngrok或者frpc,可以访问你这两对应的地址\n- 如果你不知道你的ngrok或者frpc的地址可以在控制台(页面最下方Console)的输出里面查看\n- 使用Run All方式启动,控制台在启动完成后会输出访问网址,网址内容包含**gradio.live**,可以在页面中搜索快速找到\n- 如果使用Save Verson的方式启动,点击左下角的**View Active Events**点击刚刚启动的脚步,在**Log**里找访问网址\n- 一般情况下第一次启动此脚本需要等待kaggle下载模型文件,进度在页面上方\n- 第二次及以后(不增加新的文件)需要3到5分钟\n\n## 增加模型\n- 可以直接写模型的下载链接,省去下面这些步骤\n1. 先创建数据集,也就是dataset\n2. 创建时需要添加文件,选择自己的模型文件就行\n3. 同类型文件放相同的数据集里面,一个数据集也不要太大\n4. 可以在dataset搜索其他人上传的模型\n5. 通过右侧的 **Add Data** 按钮选择已经上传的模型文件或者别人上传的模型文件\n - input 下面的列表就是模型文件,可以点击名称后面的复制按钮复制路径\n6. 将模型路径放在配置里的对应配置里即可,支持文件夹和文件路径,参考 **modelDirs**\n - 如果目录里还有子目录也是需要加载的,可以用*表示子目录 例子:比如Loras目录下还有角色、画风、涩涩的文件夹,那路径里写成 '/kaggle/input/Loras/*'就可以加载子目录里面的文件了\n - 模型加载使用的文件链接方式,如果你融模型的时候新模型名字和原有模型名字一样,会出现不能修改只读文件的错误\n - 同理,直接对模型做编辑的工具可能也会出现相同的错误\n \n \n- **受到kaggle内存大小的影响,切换多个模型后大概率爆内存导致停止运行**\n \n**下边的配置项都写了对应配置的作用和使用说明,不理解的话也不用改,用默认的就好**\n\n## 下载文件\n#### 方式一\n- 在浏览器直接下 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 你的访问地址是 https://123123123.gradio.live\n - 则可以在浏览器输入 https://123123123.gradio.live/file=/kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors 下载你的文件\n \n#### 方式二\n- 复制到Output目录下载 仅支持使用Run All方式运行的\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 先停止笔记本(不是关机,是停止)\n - 然后新建一个代码块,在里面输入 !cp -f /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 或者 新建一个代码块,在里面输入 !cp -f \\$install_path/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 你可能需要拼接路径 如果是在webui里面看到的路径,且路径里面没有带**stable-diffusion-webui**\n - 拼接方式是 **\\$install_path/stable-diffusion-webui** + **文件路径** 拼成类似前一条的样子\n - 就可以在右侧列表的Output目录看见复制出来的文件,点击下载即可\n\n## **一些可能没用的说明**\n- 配置说明 **True或者False**表示布尔值 **True**表示“**是**” **False**表示“**否**” 只有这两个值\n- 配置说明 **[]** 表示数组,里面可以存放内容,每个内容需要用**英语(半角)逗号**隔开\n- 配置说明 **''或者\"\"** 英语(半角)的双引号或者单引号包裹的内容是**字符串**,比如放在数组里面的路径就需要是一个字符串\n- 配置说明 **#** **#** 后面的内容是**注释**,是帮助性内容,对整个代码的执行不会有影响\n","metadata":{}},{"cell_type":"markdown","source":"# 更新记录\n#### 230910 v175\n- 增加了默认的sdxl模型\n- 修改了不合适的使用说明\n\n#### 230901 v173\n- 更新了依赖版本,可以加载sdxl模型了\n- 增加代码块内容说明,希望有用\n\n#### 230812 v171\n- 把关闭半精度的参数注释了,这是之前写错的,注释后不容易爆内存\n- 增加默认模型的参数,用于指定模型启动时默认的模型\n\n#### 230726 v170\n- 更新了整个配置,可以更加自由的下载和加载文件\n- 删除了大部分参数\n\n#### 230726 v169\n- 增加了一个文件加载配置,可以自定义把文件或下载地址加载到指定目录,配置方式见 [ 其他文件列表 ]\n- 增加了一个配置,可以隐藏部分控制台输出,但隐藏不完全,没啥用\n\n#### 230719 v168\n- 增加了同步收藏文件夹到 huggingface 数据集的功能,仅同步收藏文件夹,如果同步所有图片也太浪费资源了\n\n#### 230716 v167\n- 账号解封了\n- 已经更新为精简自动更新版,主要逻辑分离存放到 [huggingface](https://huggingface.co/viyi/sdwui),这边基本上不再需要更新\n- 如果增加了新功能需要��的配置,可以在输出内容的最前面查看到(暂定)\n\n#### 230302 v165\n- 可以修改disableShared=True来使用pm2启动,做到爆内存自动重启(需要使用frpc或者ngrok代理,否则无法访问界面)\n\n#### 230228 v156\n- 移除了koishi的相关功能 如需使用,可查看 [sd-webui-koishi](https://www.kaggle.com/code/yiyiooo/sd-webui-koishi)\n\n#### 230227 v147\n- 增加了nginx做反向代理,现在可以使用一个ngrok地址访问多个服务了 功能在版本156移除\n\n#### 230225 v139\n- 可以加载ssl证书,启动https的隧道了\n\n#### 230224 v134\n- 可以自动修改frp的本地端口\n\n#### 230224 v128\n- 修复默认模型文件不存在时不能启动的问题\n- 修复了多线程导致依赖等内容安装位置错乱的问题\n- 修复了第一次启动会更新koishi数据对应的数据集问题\n- 增加了配置检查功能,对一些配置项做了提示\n- 增加了可配置webui端口功能,现在可以配置webui、froc、ngrok的端口了\n\n#### 230223 v126\n- 修复了仅适用koishi数据目录无法启动koishi的问题\n- 修改了部分文档\n\n#### 230223 v124\n- 修复使用多线程后出现的文件安装下载目录失败的问题\n- 修复使用多线程后文件目录错乱问题\n\n#### 230222 v123\n- 使用多线程进行安装,节省安装时间\n\n#### 230222 v122\n- 更改了默认配置,现在训练的输出可以在Output下面查看了\n\n#### 230222 v118\n- 增加了自动上传koishi的数据到数据集且能自动下载的功能\n - 自动上传的数据集优先级高于手动上传的\n - 上一个版本的数据集与当前版本的目录结构有差异,如果更新后需要修改配置\n \n#### 230121 v111\n- 增加了koishi的部署相关功能 功能在版本156移除\n\n#### 230220 v110\n- 增加了ControlNet插件的一些说明\n\n#### 230220 v109\n- 修复第二次Run all时不能切换到新的frpc配置问题\n- 增加更新记录,用于记录每次更新 ","metadata":{}}]}
 
 
sdwui-before.ipynb CHANGED
@@ -1 +1 @@
1
- {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# NovelAi stable-diffusion-webui+api\n---\n**env版本: torch: 2.0+cu117  •  xformers: 0.0.19**\n- 发布地址 [kaggle stable-diffusion-webui-novelai](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)\n- 这是一个用于快速体验ai绘画项目 [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 的笔记本,你可以直接启动就能在线体验ai绘图的乐趣。 \n- 在保持可以免配置直接启动的情况下也提供了很多可自定义的配置,在下方的配置项里,请自行查看。 \n- 同时也为新人提供了一份基础的帮助文档,包含了一些使用中可能遇到的问题,如果使用过程中有什么疑问,不妨先看看帮助文档。\n- 如果你需要在此脚本上修改再发布,请随意,但请遵守相关法律法规,文明使用。\n- 交流群632428790 这是 [qq2575044704](https://www.kaggle.com/qq2575044704) 的群,感谢他为这个笔记做了一些宣传。\n","metadata":{}},{"cell_type":"markdown","source":"# 发布账号已经更换,这边不在更新了 [新地址](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)","metadata":{}},{"cell_type":"code","source":"useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才能开启","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 模型列表 一行一个 可以填文件 文件夹 和下载地址,如果需要自定义文件名,在url前写上文件名加:\n模型列表 = '''\nmg-Tender.safetensors:https://civitai.com/api/download/models/75587\n'''\n# 启动时默认加载的模型名称\nusedCkpt = 'mg-Tender'\nVAE列表 = '''\nhttps://huggingface.co/stabilityai/sd-vae-ft-ema-original/resolve/main/vae-ft-ema-560000-ema-pruned.safetensors\nhttps://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors\nhttps://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\n'''\n\nLora列表 = '''\nGenshin_Impact_all-in-one.safetensors:https://civitai.com/api/download/models/116970\nhttps://civitai.com/api/download/models/14856\n'''\n\nLyCORIS列表 = '''\nhttps://civitai.com/api/download/models/46821\n'''\n\nhypernetworks列表 = '''\n\n'''\n\nembeddings列表 = '''\n\n'''\n\ncontrolNet模型列表 = '''\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors\n'''\n# git仓库\n插件列表='''\nhttps://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\nhttps://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\nhttps://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\nhttps://github.com/Mikubill/sd-webui-controlnet.git\nhttps://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris.git\nhttps://github.com/ilian6806/stable-diffusion-webui-state.git\nhttps://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\nhttps://github.com/Bing-su/adetailer.git\nhttps://github.com/viyiviyi/prompts-filter.git # 这个插件会过滤空tag,如果不需要,请删除\nhttps://github.com/zanllp/sd-webui-infinite-image-browsing.git\nhttps://github.com/viyiviyi/stable-diffusion-webui-zoomimage.git\n'''\n#文件或直接填配置\nngrok配置或文件地址='''\n$input_path/configs/ngrok_token.txt\n'''\n\nfrp配置文件或配置='''\n-f **************************:7691619\n'''\n\nfrpSSL文件='''\n\n'''\n\n参数列表='''\n--disable-safe-unpickle \n--deepdanbooru \n--no-hashing \n--no-download-sd-model \n--administrator\n--skip-torch-cuda-test \n--skip-version-check \n--disable-nan-check\n--opt-sdp-attention \n--opt-sdp-no-mem-attention \n--xformers-flash-attention\n--xformers\n--api \n--listen\n--lowram\n--no-gradio-queue\n'''\n\n# --api-auth=2333:6666 --gradio-auth=2333:6666","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 手机端界面优化 使用了修改过界面布局顺序的webui,不定期同步到官方版本\nmobileOptimize=True\n# webui的配置文件\nwebui_settings = 'https://github.com/viyiviyi/sd-configs.git'\n# 设置文件路径\nsetting_file = '/kaggle/working/configs/config.json'\nui_config_file = '/kaggle/working/configs/ui-config.json'\n\n# 配置启动参数\nwebuiPort=7860 # webui默认端口\ndisableShared=False # 关闭默认的gradio.live穿透\nonlyApi=False # 无ui界面,仅提供api服务\nquickStart=True # 快速启动 使用下载好的python环境 开启后启动到可用需要4分钟,不开启需要8分钟\nvaeHalf=False # vae开启半精度,关闭效果更好,对速度没啥影响\nmodelHalf=True # 模型开启半精度,关闭效果更好,但生成速度减半\nconsoleProgressbars=False # 控制台显示进度条,关闭可以减少一些输出内容,查看日志时更快一点\nconsolePrompts=False # 同上 \nenableLoadByCopy=False # 是否使用copy的方式加载文件 启动变慢,且测试后没有提高模型切换速度\nenableThread=True # 启用多线程下载插件 依赖 和 模型\n#Ngrok\nuseNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n#Frpc\nuseFrpc=True # 开启frp将不能启动\n\nimport os\nINIT_WORK_PATH = os.environ['HOME']\nif os.getenv('INIT_WORK_PATH',''):\n INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\nelse:\n os.environ['INIT_WORK_PATH'] = os.getcwd()\n%cd {INIT_WORK_PATH}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 这是配置文件夹同步的相关配置\n# 需要在huggingface创建一个数据集(datasets) 然后把数据集的名称(在页面上有复制的按钮)填到 huggingface_repo \n# 需要获取 token 填到 huggingface_token 获取的地址是: https://huggingface.co/settings/tokens\n# 填了huggingface_token这个值的就不要在任何地方分享你的笔记,否则得到你的token的人可以随意的访问你的 huggingface 账号\n# 也可以填写一个存放了token的文件的目录,这样就能规避风险\nhuggingface_token = '{input_path}/configs/huggingface_token.txt'\nhuggingface_repo = 'viyi/sdwui-log'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reLoad = True\n# 如果需要重新安装,请注释这一行\nreLoad = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start.ipynb\n%run sdwui-start.ipynb","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# 打包收藏文件夹 如果需要可以取消下面两行的注释\n# zipPath('$install_path/stable-diffusion-webui/log','log')\n# !mv {output_path}/log.tar {output_path}/log.tar.bak\n# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n\n# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n# zipPath('$install_path/stable-diffusion-webui/textual_inversion','训练输出') \n# zipPath('$install_path/stable-diffusion-webui/outputs','outputs')\n# zipPath('$install_path/stable-diffusion-webui/venv','venv')\n# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /kaggle/stable-diffusion-webui/ .","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 使用帮助\n---\n**代码块不能删除也不能调换顺序,如果出现变量未定义,请检查是否按顺序执行了代码块**\n\n---\n\n## kaggle账号\n- 注册账号需要手机号,国内手机号也行,如果点击注册后没反应,估计是需要梯子,用于人机验证\n- 注册后点此笔记的 **Copy & Edit** 按钮就进到编辑界面\n\n## 准备工作\n1. 右侧面板 **Settings/ACCELERATOR** 需要选择GPU **T4x2**出图���快,且会自动开启两个webui\n2. 右侧面板 **Settings/LANGUAGE** 需要选择Python\n2. 右侧面板 **Settings/PERSISTENCE** 建议选择 Files only **作用是保存Outpot目录内的文件**\n3. 右侧面板 **Settings/ENVIRONMENT** 建议不改这个配置,使用当前默认值就行\n4. 右侧面板 **Settings/INTERNET** 需要打开 用于联网,没网跑不起来的啊\n\n## 启动\n#### 启动方式一 **直接点击页面上边的 RunAll**\n- 在没有关闭电源的情况下,后几次点击RunAll的输出在页面上端 (其实没有必要了,之前不知道代码块可以收起,很烦滚动到页面底端才能看见输出)\n- 手机端可能会出现页面上边的工具栏不显示的情况,左侧菜单按钮里也有相关的操作\n- 长时间不操作页面会导致脚本停止 (应该是40分钟吧)\n\n#### 启动方式二 **使用页面上边的 Save Version 后台运行**\n- 后台运行不用担心长时间不操作脚本停止\n- Version Type 选择 **Save & Run All**\n- 在Save Version弹窗里需要选择使用**GPU**环境 (Advanced Settings 里最后一个选项)\n- 后台运行的输出的图片可以在运行结束后下载(但是保存时间有限制,我就经常下不到,不够问题不大,喜欢的图在生成后就下载了)\n- 如果你需要下载运行后的图片,请不要把安装目录修改到 /kaggle/working 这个目录下,因为没有写打包功能,下载只能下载整个输出目录,也就是 /kaggle/working 目录\n\n## 访问\n- 如果你使用了ngrok或者frpc,可以访问你这两对应的地址\n- 如果你不知道你的ngrok或者frpc的地址可以在控制台(页面最下方Console)的输出里面查看\n- 使用Run All方式启动,控制台在启动完成后会输出访问网址,网址内容包含**gradio.live**,可以在页面中搜索快速找到\n- 如果使用Save Verson的方式启动,点击左下角的**View Active Events**点击刚刚启动的脚步,在**Log**里找访问网址\n- 一般情况下第一次启动此脚本需要等待kaggle下载模型文件,进度在页面上方\n- 第二次及以后(不增加新的文件)需要3到5分钟\n\n## 增加模型\n1. 先创建数据集,也就是dataset\n2. 创建时需要添加文件,选择自己的模型文件就行\n3. 同类型文件放相同的数据集里面,一个数据集也不要太大\n4. 可以在dataset搜索其他人上传的模型\n5. 通过右侧的 **Add Data** 按钮选择已经上传的模型文件或者别人上传的模型文件\n - input 下面的列表就是模型文件,可以点击名称后面的复制按钮复制路径\n6. 将模型路径放在配置里的对应配置里即可,支持文件夹和文件路径,参考 **modelDirs**\n - 如果目录里还有子目录也是需要加载的,可以用*表示子目录 例子:比如Loras目录下还有角色、画风、涩涩的文件夹,那路径里写成 '/kaggle/input/Loras/*'就可以加载子目录里面的文件了\n - 模型加载使用的文件链接方式,如果你融模型的时候新模型名字和原有模型名字一样,会出现不能修改只读文件的错误\n - 同理,直接对模型做编辑的工具可能也会出现相同的错误\n \n \n- **为了提高启动速度,导致切换模型过程较慢,点击切换模型后进度条大概率会一直存在,但模型在1分半左右基本能加载完。** \n- **受到kaggle内存大小的影响,切换多个模型后大概率爆内存导致停止运行**\n \n**下边的配置项都写了对应配置的作用和使用说明,不理解的话也不用改,用默认的就好**\n\n## 下载文件\n#### 方式一\n- 在浏览器直接下 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 你的访问地址是 https://123123123.gradio.live\n - 则可以在浏览器输入 https://123123123.gradio.live/file=/kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors 下载你的文件\n \n#### 方式二\n- 复制到Output目录下载 仅支持使用Run All方式运行的\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 先停止笔记本(不是关机,是停止)\n - 然后新建一个代码块,在里面输入 !cp -f /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 或者 新建一个代码块,在里面输入 !cp -f \\$install_path/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 你可能需要拼接路径 如果是在webui里面看到的路径,且路径里面没有带**stable-diffusion-webui**\n - 拼接方式是 **\\$install_path/stable-diffusion-webui** + **文件路径** 拼成类似前一条的样子\n - 就可以在右侧列表的Output目录看见复制出来的文件,点击下载即可\n \n#### 方式三\n- 开启链接输出目录的配置 (配置在第二个代码块,通过搜索**配置文件链接**快速查找)\n - 此方法会把已知的三个训练输出目录链接到Output目录下,直接去下载即可(两种启动方式都可以用)\n - 如果有新的目录需要链接,可以参考着自己写或者联系我\n \n#### 方式四\n- 将安装目录改到输出目录(配置在第二个代码块,通过搜索**安装目录**快速查找)\n - 此方式会把所有文件都放在安装目录,找到并下载即可\n - 如果使用这个方式,右侧的设置里**PERSISTENCE**这个设置项建议选No pensistence。如果选其他项,可能会出现关机特别慢的情况,因为需要上传输出目录的文件。\n\n## **一些可能没用的说明**\n- 配置说明 **True或者False**表示布尔值 **True**表示“**是**” **False**表示“**否**” 只有这两个值\n- 配置说明 **[]** 表示数组,里面可以存放内容,每个内容需要用**英语(半角)逗号**隔开\n- 配置说明 **''或者\"\"** 英语(半角)的双引号或者单引号包裹的内容是**字符串**,比如放在数组里面的路径就需要是一个字符串\n- 配置说明 **#** **#** 后面的内容是**注释**,是帮助性内容,对整个代码的执行不会有影响\n","metadata":{}},{"cell_type":"markdown","source":"# 更新记录\n#### 230719 v168\n- 增加了同步收藏文件夹到 huggingface 数据集的功能,仅同步收藏文件夹,如果同步所有图片也太浪费资源了\n\n#### 230716 v167\n- 账号解封了\n- 已经更新为精简自动更新版,主要逻辑分离存放到 [huggingface](https://huggingface.co/viyi/sdwui),这边基本上不再需要更新\n- 如果增加了新功能需要新的配置,可以在输出内容的最前面查看到(暂定)\n\n#### 230302 v165\n- 可以修改disableShared=True来使用pm2启动,做到爆内存自动重启(需要使用frpc或者ngrok代理,否则无法访问界面)\n\n#### 230228 v156\n- 移除了koishi的相关功能 如需使用,可查看 [sd-webui-koishi](https://www.kaggle.com/code/yiyiooo/sd-webui-koishi)\n\n#### 230227 v147\n- 增加了nginx做反向代理,现在可以使用一个ngrok地址访问多个服务了 功能在版本156移除\n\n#### 230225 v139\n- 可以加载ssl证书,启动https的隧道了\n\n#### 230224 v134\n- 可以自动修改frp的本地端口\n\n#### 230224 v128\n- 修复默认模型文件不存在时不能启动的问题\n- 修复了多线程导致依赖等内容安装位置错乱的问题\n- 修复了第一次启动会更新koishi数据对应的数据集问题\n- 增加了配置检查功能,对一些配置项做了提示\n- 增加了可配置webui端口功能,现在可以配置webui、froc、ngrok的端口了\n\n#### 230223 v126\n- 修复了仅适用koishi数据目录无法启动koishi的问题\n- 修改了部分文档\n\n#### 230223 v124\n- 修复使用多线程后出现的文件安装下载目录失败的问题\n- 修复使用多线程后文件目录错乱问题\n\n#### 230222 v123\n- 使用多线程进行安装,节省安装时间\n\n#### 230222 v122\n- 更改了默认配置,现在训练的输出可以在Output下面查看了\n\n#### 230222 v118\n- 增加了自动上传koishi的数据到数据集且能自动下载的功能\n - 自动上传的数据集优先级高于手动上传的\n - 上一个版本的数据集与当前版本的目录结构有差异,如果更新后需要修改配置\n \n#### 230121 v111\n- 增加了koishi的部署相关功能 功能在版本156移除\n\n#### 230220 v110\n- 增加了ControlNet插件的一些说明\n\n#### 230220 v109\n- 修复第二次Run all时不能切换到新的frpc配置问题\n- 增加更新记录,用于记录每次更新 ","metadata":{}}]}
 
1
+ {"cells":[{"cell_type":"markdown","metadata":{"id":"TcLs4cdaLCtB"},"source":["# 配置项 (修改这里的内容后直接启动就行了 run all 或者save version都可以)\n","\n","---\n","\n","**主要逻辑已经分离出去了,当有更新时也不需要更新这个文件**\n","- 所有的模型列表都支持填文件、文件夹、下载地址\n","- **如果需要在google colab运行**\n"," 1. 改好这个文件后下载下来\n"," 2. 在cloab新建一个脚本,然后上传这个文件\n"," 3. 新建单元格后填入```%run sdwui-before.ipynb```,然后直接执行新建的单元格。注意: sdwui-before.ipynb 需要替换成你上传时的文件名"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"swzyZ1_gLCs_","trusted":true},"outputs":[],"source":["useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才能开启"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"7tTWVxHDLCtB","trusted":true},"outputs":[],"source":["# 模型列表 一行一个 可以填文件 文件夹 和下载地址,如果需要自定义文件名,在url前写上文件名加:\n","模型列表 = '''\n","https://civitai.com/api/download/models/75587\n","'''\n","# 启动时默认加载的模型名称\n","usedCkpt = 'mg-Tender'\n","VAE列表 = '''\n","https://huggingface.co/stabilityai/sd-vae-ft-ema-original/resolve/main/vae-ft-ema-560000-ema-pruned.safetensors\n","https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors\n","https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\n","'''\n","Lora列表 = '''\n","https://civitai.com/api/download/models/14856\n","'''\n","LyCORIS列表 = '''\n","https://civitai.com/api/download/models/46821\n","'''\n","hypernetworks列表 = '''\n","\n","'''\n","embeddings列表 = '''\n","\n","'''\n","controlNet模型列表 = '''\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_canny-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_depth-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_hed-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_mlsd-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_normal-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_openpose-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_scribble-fp16.safetensors\n","https://huggingface.co/webui/ControlNet-modules-safetensors/resolve/main/control_seg-fp16.safetensors\n","'''\n","# git仓库\n","插件列表='''\n","https://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\n","https://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\n","https://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\n","https://github.com/Mikubill/sd-webui-controlnet.git\n","https://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris.git\n","https://github.com/LianZiZhou/sd-webui-pixink-console.git\n","https://github.com/ilian6806/stable-diffusion-webui-state.git\n","https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\n","https://github.com/Bing-su/adetailer.git\n","https://github.com/viyiviyi/filter-empty-prompts.git\n","https://github.com/civitai/sd_civitai_extension.git\n","https://github.com/zanllp/sd-webui-infinite-image-browsing.git\n","'''\n","#文件或直接填配置\n","ngrok配置或文件地址='''\n","/kaggle/input/configs/ngrok_token.txt\n","'''\n","frp配置文件或配置='''\n","-f **************************:7691619\n","'''\n","frpSSL文件='''\n","\n","'''\n","参数列表='''\n","--disable-safe-unpickle \n","--deepdanbooru \n","--no-hashing \n","--no-download-sd-model \n","--administrator\n","--skip-torch-cuda-test \n","--skip-version-check \n","--disable-nan-check\n","--opt-sdp-attention \n","--opt-sdp-no-mem-attention \n","--xformers-flash-attention\n","--xformers\n","--api \n","--listen\n","--lowram\n","--no-gradio-queue\n","'''\n","# --api-auth=2333:6666 --gradio-auth=2333:6666"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":false,"id":"r_lBDJdOLCtB","trusted":true},"outputs":[],"source":["# 手机端界面优化 使用了修改过界面布局顺序的webui,不定期同步到官方版本\n","mobileOptimize=True\n","# webui的配置文件\n","webui_settings = 'https://github.com/viyiviyi/sd-configs.git'\n","# 设置文件路径\n","setting_file = '/kaggle/working/configs/config.json'\n","ui_config_file = '/kaggle/working/configs/ui-config.json'\n","\n","# 配置启动参数\n","webuiPort=7860 # webui默认端口\n","disableShared=False # 关闭默认的gradio.live穿透\n","onlyApi=False # 无ui界面,仅提供api服务\n","quickStart=True # 快速启动 使用下载好的python环境 开启后启动到可用需要4分钟,不开启需要8分钟\n","vaeHalf=False # vae开启半精度,关闭效果更好,对速度没啥影响\n","modelHalf=True # 模型开启半精度,关闭效果更好,但生成速度减半\n","consoleProgressbars=False # 控制台显示进度条,关闭可以减少一些输出内容,查看日志时更快一点\n","consolePrompts=False # 同上 \n","enableLoadByCopy=False # 是否使用copy的方式加载文件 启动变慢,且测试后没有提高模型切换速度\n","enableThread=True # 启用多线程下载插件 依赖 和 模型\n","#Ngrok\n","useNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n","#Frpc\n","useFrpc=True # 开启frp将不能启动\n","\n","import os\n","INIT_WORK_PATH = os.environ['HOME']\n","if os.getenv('INIT_WORK_PATH',''):\n"," INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\n","else:\n"," os.environ['INIT_WORK_PATH'] = os.getcwd()\n","%cd {INIT_WORK_PATH}"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["reLoad = True\n","# 如果需要重新安装,请注释这一行\n","reLoad = False"]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"trusted":true},"outputs":[],"source":["!wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start.ipynb\n","%run sdwui-start.ipynb"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ePT_b-s9LCtF","scrolled":true,"trusted":true},"outputs":[],"source":["\n","# 打包收藏文件夹 如果需要可以取消下面两行的注释\n","# zipPath('$install_path/stable-diffusion-webui/log','log')\n","# !mv {output_path}/log.tar {output_path}/log.tar.bak\n","# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n","\n","# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n","# zipPath('$install_path/stable-diffusion-webui/textual_inversion','训练输出') \n","# zipPath('$install_path/stable-diffusion-webui/outputs','outputs')\n","# zipPath('$install_path/stable-diffusion-webui/venv','venv')\n","# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n","# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n","# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /kaggle/stable-diffusion-webui/ ."]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.12"}},"nbformat":4,"nbformat_minor":4}
sdwui-start-new.ipynb DELETED
@@ -1 +0,0 @@
1
- {"cells":[{"cell_type":"markdown","metadata":{"id":"6zE2QeUKLCtC"},"source":["# 这只是一个完整项目的一部分 不能运行的 \n","- 可以从这个地址运行 [点击打开](https://www.kaggle.com/viyiviyi/sdwui-before)\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":[]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["update_desc = '''\n","欢迎使用 stable-diffusion-webui 便捷启动脚本\n","\n","此脚本理论上可以在任何jupyter环境运行,但仅在 google colab 和 kaggle 测试。\n","此脚本的【前置脚本】发布地址 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai。\n","此脚本需配合 【前置脚本】 的脚本附带的配置项才能正常启动。\n","此脚本的内容会自动更新,你无需更新【前置脚本】就能获取到最新的功能。\n","如果新功能需要增加新的配置项,可以在更新日志中查看到。\n","\n","路径说明\n","* 为了解决平台差异,所有的安装目录和文件输出目录都被重新指定,如果你需要在配置中访问这些目录,请查看以下说明\n","*\n","* 如果链接了谷歌云盘,将会在云盘根目录创建 sdwebui 的文件夹,文件夹内的 Input 目录将会作为 输入目录; Output 将会作为输出目录\n","* 可以使用 $install_path 或 {install_path} 来访问安装目录,写在字符串内也会生效\n","* 项目跟目录固定是: {install_path}/sd_main_dir 或 $install_path/sd_main_dir\n","* $output_path 或 {output_path} 可以访问输出目录\n","* $input_path 或 {input_path} 可以访问输入目录 在kaggle是数据集根目录\n","\n","更新日志\n","* 23-09-13\n","* 修改了项目安装目录的文件夹名称,改为sd_main_dir,访问方式是{install_path}/sd_main_dir\n","*\n","* 23-08-02\n","* 需要增加配置 [多实例 = True] 来使用第二张显卡\n","*\n","* 23-08-01\n","* 估计是新的gradio的问题,需要禁用 --no-gradio-queue 启动参数才能正常访问,否则会一直处于加载界面,所以这个参数会被屏蔽不再生效\n","*\n","* 23-07-30\n","* 使用新的文件加载逻辑重写完成,文件加载和加载更加简单,可以支持自定义下载或加载文件的目标目录了\n","*\n","* 23-07-26\n","* 增加可隐藏启动时的不重要信息 通过增加配置 [hidden_console_info = True] 开启\n","*\n","* 23-07-22\n","* 更新了可自动同步收藏目录到 https://huggingface.co/ 的功能\n","* 可通过增加配置项 _huggingface_token = \"token\" 和 _huggingface_repo = “仓库id” 后使用此功能\n","*\n","* 23-07-18 \n","* 如果有两个GPU 第二个GPU将会启动api服务,可用api的方式调用,和webui互相独立,绘图时不会导致另外一边卡顿\n","* 通过/1/作为base url来访问这个api\n","* 没有启动两个webui是因为,很大概率爆内存\n","'''"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["from pathlib import Path\n","import os\n","import time\n","import re\n","import subprocess\n","import threading\n","import sys\n","import socket\n","import torch\n","from typing import List"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 内置参数默认值,当上下文有参数时可覆盖默认值\n","\n","_useFrpc = False\n","if 'useFrpc' in locals() or 'useFrpc' in globals():\n"," _useFrpc = useFrpc\n"," \n","_useNgrok = False\n","if 'useNgrok' in locals() or 'useNgrok' in globals():\n"," _useNgrok = useNgrok\n"," \n","_reLoad = False\n","if 'reLoad' in locals() or 'reLoad' in globals():\n"," _reLoad = reLoad\n"," \n","_普通文件列表 = ''\n","if '普通文件列表' in locals() or '普通文件列表' in globals():\n"," _普通文件列表 = 普通文件列表\n","\n","_重要文件列表 = ''\n","if '重要文件列表' in locals() or '重要文件列表' in globals():\n"," _重要文件列表 = 重要文件列表\n","\n","_按顺序加载的重要文件列表 = ''\n","if '按顺序加载的重要文件列表' in locals() or '按顺序加载的重要文件列表' in globals():\n"," _按顺序加载的重要文件列表 = 按顺序加载的重要文件列表\n"," \n","_webuiPort = 7860\n","if 'webuiPort' in locals() or 'webuiPort' in globals():\n"," _webuiPort = webuiPort\n"," \n","_webui_git_repo ='https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n","if 'webui_git_repo' in locals() or 'webui_git_repo' in globals():\n"," _webui_git_repo = webui_git_repo\\\n"," .replace('{sdui}','stable-diffusion-webui')\\\n"," .replace('{sdwui}',\"webui\")\n"," \n","_webui_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git'\n","if 'webui_config_git_repu' in locals() or 'webui_config_git_repu' in globals():\n"," _webui_config_git_repu = webui_config_git_repu\\\n"," .replace('{sdui}','stable-diffusion-webui')\\\n"," .replace('{sdwui}',\"webui\")\n"," \n"," \n","_huggingface_token = '{input_path}/configs/huggingface_token.txt'\n","if 'huggingface_token' in locals() or 'huggingface_token' in globals():\n"," _huggingface_token = huggingface_token\\\n"," .replace('{sdui}','stable-diffusion-webui')\\\n"," .replace('{sdwui}',\"webui\")\n"," \n","_huggingface_repo = ''\n","if 'huggingface_repo' in locals() or 'huggingface_repo' in globals():\n"," _huggingface_repo = huggingface_repo\\\n"," .replace('{sdui}','stable-diffusion-webui')\\\n"," .replace('{sdwui}',\"webui\")\n","\n","_link_instead_of_copy = True\n","if 'link_instead_of_copy' in locals() or 'link_instead_of_copy' in globals():\n"," _link_instead_of_copy = link_instead_of_copy\n"," \n","show_shell_info = False\n","if 'hidden_console_info' in locals() or 'hidden_console_info' in globals():\n"," show_shell_info = not hidden_console_info\n"," \n","_skip_start = False\n","if 'skip_start' in locals() or 'skip_start' in globals():\n"," _skip_start = skip_start\n"," \n","run_by_none_device = False"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["\n","def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:\n"," global show_shell_info\n"," if desc is not None:\n"," print(desc)\n","\n"," run_kwargs = {\n"," \"args\": command,\n"," \"shell\": True,\n"," \"cwd\": cwd,\n"," \"env\": os.environ if custom_env is None else custom_env,\n"," \"encoding\": 'utf8',\n"," \"errors\": 'ignore',\n"," }\n","\n"," if not show_shell_info:\n"," run_kwargs[\"stdout\"] = run_kwargs[\"stderr\"] = subprocess.PIPE\n","\n"," result = subprocess.run(**run_kwargs)\n","\n"," if result.returncode != 0:\n"," error_bits = [\n"," f\"{errdesc or 'Error running command'}.\",\n"," f\"Command: {command}\",\n"," f\"Error code: {result.returncode}\",\n"," ]\n"," if result.stdout:\n"," error_bits.append(f\"stdout: {result.stdout}\")\n"," if result.stderr:\n"," error_bits.append(f\"stderr: {result.stderr}\")\n"," if try_error:\n"," print(RuntimeError(\"\\n\".join(error_bits)))\n"," else:\n"," raise RuntimeError(\"\\n\".join(error_bits))\n","\n"," if show_shell_info:\n"," print(result.stdout or \"\")\n"," return (result.stdout or \"\")\n"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["\n","# 检查gpu是否存在\n","def check_gpu():\n"," if not run_by_none_device and torch.cuda.device_count() == 0:\n"," raise Exception('当前环境没有GPU')\n","\n","install_path=f\"{os.environ['HOME']}/sdwui\" # 安装目录\n","output_path=f\"{os.environ['HOME']}/.sdwui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\n","input_path = '/kaggle/input' # 输入目录\n","ui_dir_name = 'sd'\n","google_drive = '' \n","\n","_useGooglrDrive = True\n","if 'useGooglrDrive' in locals() or 'useGooglrDrive' in globals():\n"," _useGooglrDrive = useGooglrDrive\n","\n","# 连接谷歌云\n","try:\n"," if _useGooglrDrive:\n"," from google.colab import drive\n"," drive.mount(f'~/google_drive')\n"," google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n"," output_path = f'{google_drive}/sdwebui/Output'\n"," input_path = f'{google_drive}/sdwebui/Input'\n"," run(f'''mkdir -p {input_path}''')\n"," print('''\n","已经链接到谷歌云盘\n","云盘根目录/sdwebui/Output 被链接为输出目录,图片和设置文件将会保存在此文件夹\n","云盘根目录/sdwebui/Input 被链接为输入目录,环境变量名是 $input_path, 可以在任何一个配置内通过$input_path或{input_path}来读取文件\n"," ''')\n","except:\n"," _useGooglrDrive = False\n","\n","run(f'''mkdir -p {install_path}''')\n","run(f'''mkdir -p {output_path}''')\n","\n","os.environ['install_path'] = install_path\n","os.environ['output_path'] = output_path\n","os.environ['google_drive'] = google_drive\n","os.environ['input_path'] = input_path\n","\n","def replace_path(input_str:str):\n"," return input_str.replace('$install_path',install_path)\\\n"," .replace('{install_path}',install_path)\\\n"," .replace('$input_path',input_path)\\\n"," .replace('{input_path}',input_path)\\\n"," .replace('$output_path',output_path)\\\n"," .replace('{output_path}',output_path)\\\n"," .replace('{sdui}','stable-diffusion-webui')\\\n"," .replace('{sdwui}',\"webui\")\n","\n","space_string = ' \\n\\r\\t\\'\\\",'\n","\n","def config_reader(conf:str):\n"," args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\\n') if item.strip(space_string)]\n"," return [item.strip() for item in args if item.strip()]\n"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"i3LhnwYHLCtC","trusted":true},"outputs":[],"source":["ngrokTokenFile = os.path.join(input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n","frpcConfigFile = os.path.join(input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n","# ss证书目录 下载nginx的版本,把pem格式改成crt格式\n","frpcSSLFFlies =[os.path.join(input_path,'configs/koishi_ssl')]\n","if 'frpSSL文件' in locals() or 'frpSSL文件' in globals():\n"," frpcSSLFFlies = frpcSSLFFlies + config_reader(frpSSL文件)\n","# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n","frpcExePath = os.path.join(input_path,'utils-tools/frpc')\n","# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n","otherArgs = '--xformers'\n","if '参数列表' in locals() or '参数列表' in globals():\n"," otherArgs = ' '.join([item for item in config_reader(参数列表) if item != '--no-gradio-queue'])\n","venvPath = os.path.join(input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n","\n","# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n","# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\n","kaggleApiTokenFile = os.path.join(input_path,'configs/kaggle.json')\n","\n","requirements = []\n"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"a_GtG2ayLCtD","trusted":true},"outputs":[],"source":["# 这下面的是用于初始化一些值或者环境变量的,轻易别改\n","_setting_file = '/kaggle/working/configs/config.json'\n","if 'setting_file' in locals() or 'setting_file' in globals():\n"," _setting_file = replace_path(_setting_file)\n","_ui_config_file = '/kaggle/working/configs/ui-config.json'\n","if 'ui_config_file' in locals() or 'ui_config_file' in globals():\n"," _ui_config_file = replace_path(ui_config_file)\n","\n","# 设置文件路径\n","if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n"," if _setting_file == '/kaggle/working/configs/config.json':\n"," _setting_file = os.path.join(output_path,'configs/config.json')\n"," if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n"," _ui_config_file = os.path.join(output_path,'configs/ui-config.json')\n"," \n","frpcStartArg = ''\n","run(f'''mkdir -p {install_path}/configFiles''')\n","if 'frp配置文件或配置' in locals() or 'frp配置文件或配置' in globals():\n"," _frp配置文件或配置 = replace_path(frp配置文件或配置)\n"," if Path(_frp配置文件或配置.strip()).exists():\n"," frpcConfigFile = _frp配置文件或配置.strip()\n"," if not Path(frpcConfigFile).exists(): \n"," if _frp配置文件或配置.strip().startswith('-f'):\n"," frpcStartArg = _frp配置文件或配置.strip()\n"," else:\n"," print('没有frpcp配置')\n"," _useFrpc = False\n"," else:\n"," run(f'''cp -f {frpcConfigFile} {install_path}/configFiles/frpc_webui.ini''')\n"," frpcConfigFile = f'{install_path}/configFiles/frpc_webui.ini'\n"," run(f'''sed -i \"s/local_port = .*/local_port = {_webuiPort}/g\" {frpcConfigFile}''')\n"," frpcStartArg = f' -c {frpcConfigFile}'\n","\n","ngrokToken=''\n","if 'ngrok配置或文件地址' in locals() or 'ngrok配置或文件地址' in globals():\n"," _ngrok配置或文件地址 = replace_path(ngrok配置或文件地址)\n"," if Path(_ngrok配置或文件地址.strip()).exists():\n"," ngrokTokenFile = _ngrok配置或文件地址.strip()\n"," if Path(ngrokTokenFile).exists():\n"," with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n"," ngrokToken = nkfile.readline()\n"," elif not _ngrok配置或文件地址.strip().startswith('/'):\n"," ngrokToken=_ngrok配置或文件地址.strip()\n"," \n","if not Path(venvPath).exists():\n"," venvPath = os.path.join(input_path,'sd-webui-venv/venv.zip')\n"]},{"cell_type":"markdown","metadata":{},"source":["## 文件下载工具\n","\n","---\n","\n","link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',sync:bool=False,thread_num:int=None)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["import concurrent.futures\n","import importlib\n","import os\n","import pprint\n","import re\n","from pathlib import Path\n","from typing import List\n","\n","import requests\n","\n","show_shell_info = False\n","\n","def is_installed(package):\n"," try:\n"," spec = importlib.util.find_spec(package)\n"," except ModuleNotFoundError:\n"," return False\n","\n"," return spec is not None\n","\n","def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True):\n"," # 获取文件的真实文件名\n"," if not filename:\n"," with requests.get(url, stream=True) as r:\n"," if 'Content-Disposition' in r.headers:\n"," filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n"," r.close()\n"," if not filename and re.search(r'/[^/]+\\.[^/]+$',url):\n"," filename = url.split('/')[-1]\n"," \n"," filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n"," filename = re.sub(r'[\\s\\t]+', '_', filename)\n"," \n"," if show_shell_info:\n"," print(f'下载 {filename} url: {url} --> {dist_path}')\n"," \n"," # 创建目录\n"," if cache_path and not Path(cache_path).exists():\n"," os.makedirs(cache_path,exist_ok=True)\n"," if dist_path and not Path(dist_path).exists():\n"," os.makedirs(dist_path,exist_ok=True)\n"," \n"," # 拼接文件的完整路径\n"," filepath = os.path.join(dist_path, filename)\n","\n"," if cache_path:\n"," cache_path = os.path.join(cache_path, filename)\n"," \n"," # 判断文件是否已存在\n"," if Path(filepath).exists():\n"," print(f'文件 {filename} 已存在 {dist_path}')\n"," return\n"," \n"," if cache_path and Path(cache_path).exists():\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n"," if show_shell_info:\n"," print(f'文件缓存 {cache_path} --> {dist_path}')\n"," return\n"," # 下载文件\n"," with requests.get(url, stream=True) as r:\n"," r.raise_for_status()\n"," with open(cache_path or filepath, 'wb') as f:\n"," for chunk in r.iter_content(chunk_size=8192):\n"," if chunk:\n"," f.write(chunk)\n"," # 如果使用了缓存目录 需要复制或链接文件到目标目录\n"," if cache_path:\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n"," if show_shell_info:\n"," print(f'下载完成 {filename} --> {dist_path}')\n"," \n","def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n"," if not Path(dist_path).exists():\n"," os.makedirs(dist_path,exist_ok=True)\n"," if show_shell_info:\n"," print(f'git 下载 {url} --> {dist_path}')\n"," if cache_path and not Path(cache_path).exists():\n"," os.makedirs(cache_path,exist_ok=True)\n"," run(f'git clone {url}',cwd = cache_path)\n"," if cache_path:\n"," run(f'cp -n -r -f {cache_path}/* {dist_path}')\n"," else:\n"," run(f'git clone {url}',cwd = dist_path)\n"," if show_shell_info:\n"," print(f'git 下载完成 {url} --> {dist_path}')\n"," \n"," \n"," \n","# 加入文件到下载列表\n","def pause_url(url:str,dist_path:str):\n"," file_name = ''\n"," if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n"," file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n"," url = url[len(file_name)+1:]\n"," if not re.match(r'^(https?|ftps?)://',url):\n"," return\n"," file_name = re.sub(r'\\s+','_',file_name or '')\n"," path_hash = str(hash(url)).replace('-','')\n"," \n"," return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}\n","\n","def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5, \n"," cache_path:str=os.path.join(os.environ['HOME'],'.cache','download_util'),\n"," _link_instead_of_copy:bool=True,is_await:bool=False):\n"," if sync:\n"," for conf in download_list:\n"," cache_dir = os.path.join(cache_path,conf['path_hash'])\n"," if conf['url'].startswith('https://github.com'):\n"," download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n"," continue\n"," download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n"," else:\n"," executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)\n"," futures = []\n"," for conf in download_list:\n"," cache_dir = os.path.join(cache_path,conf['path_hash'])\n"," if conf['url'].startswith('https://github.com'):\n"," futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],\n"," cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n"," continue\n"," futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],\n"," cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n"," if is_await:\n"," concurrent.futures.wait(futures)\n"," \n"," \n","def parse_config(config:str):\n"," space_string = ' \\n\\r\\t\\'\\\",'\n"," other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\\n') if item.strip(space_string)]\n"," other_flie_list = [item.strip() for item in other_flie_list if item.strip()]\n"," other_flie_list_store = {}\n"," other_flie_list_store_name='default'\n"," other_flie_list_store_list_cache=[]\n"," \n"," for item in other_flie_list:\n"," if item.startswith('[') and item.endswith(']'):\n"," if not other_flie_list_store_name == 'default':\n"," other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n"," other_flie_list_store_list_cache = []\n"," other_flie_list_store_name = item[1:-1]\n"," else:\n"," other_flie_list_store_list_cache.append(item)\n"," other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n"," \n"," return other_flie_list_store\n","\n","\n","def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',\n"," sync:bool=False,thread_num:int=None, is_await:bool=False):\n"," store:dict[str,List[str]] = parse_config(config)\n"," download_list = []\n"," for dist_dir in store.keys():\n"," dist_path = os.path.join(base_path,dist_dir)\n"," os.makedirs(dist_path,exist_ok=True)\n"," for path in store[dist_dir]:\n"," if 'https://' in path or 'http://' in path:\n"," if skip_url:\n"," continue\n"," if sync:\n"," download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)\n"," continue\n"," download_list.append(pause_url(path,dist_path))\n"," else:\n"," run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {path} {dist_path}')\n"," if show_shell_info:\n"," print(f'{\"链接\" if _link_instead_of_copy else \"复制\"} {path} --> {dist_path}')\n"," run(f'rm -f {dist_path}/\\*.* ')\n"," if not skip_url:\n"," if show_shell_info:\n"," pprint.pprint(download_list)\n"," download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 2,is_await=is_await)"]},{"cell_type":"markdown","metadata":{"id":"p0uS-BLULCtD"},"source":["## kaggle public API\n","\n","**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"m8FJi4j0LCtD","trusted":true},"outputs":[],"source":["# 安装kaggle的api token文件\n","def initKaggleConfig():\n"," if Path('~/.kaggle/kaggle.json').exists():\n"," return True\n"," if Path(kaggleApiTokenFile).exists():\n"," run(f'''mkdir -p ~/.kaggle/''')\n"," run('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n"," run(f'''chmod 600 ~/.kaggle/kaggle.json''')\n"," return True\n"," print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n"," return False\n","\n","def getUserName():\n"," if not initKaggleConfig(): return\n"," import kaggle\n"," return kaggle.KaggleApi().read_config_file()['username']\n","\n","def createOrUpdateDataSet(path:str,datasetName:str):\n"," if not initKaggleConfig(): return\n"," print('创建或更新数据集 '+datasetName)\n"," import kaggle\n"," run(f'mkdir -p {install_path}/kaggle_cache')\n"," run(f'rm -rf {install_path}/kaggle_cache/*')\n"," datasetDirPath = install_path+'/kaggle_cache/'+datasetName\n"," run('mkdir -p '+datasetDirPath)\n"," run('cp -f '+path+' '+datasetDirPath+'/')\n"," username = getUserName()\n"," print(\"kaggle username:\"+username)\n"," datasetPath = username+'/'+datasetName\n"," datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n"," print(datasetList)\n"," if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n"," run('kaggle datasets init -p' + datasetDirPath)\n"," metadataFile = datasetDirPath+'/dataset-metadata.json'\n"," run('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n"," run('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n"," run('cat '+metadataFile)\n"," run('kaggle datasets create -p '+datasetDirPath)\n"," print('create database done')\n"," else:\n"," kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n"," kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n"," print('upload database done')\n","\n","def downloadDatasetFiles(datasetName:str,outputPath:str):\n"," if not initKaggleConfig(): return\n"," print('下载数据集文件 '+datasetName)\n"," import kaggle\n"," username = getUserName()\n"," datasetPath = username+'/'+datasetName\n"," datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n"," if datasetPath not in [str(d) for d in datasetList]:\n"," return False\n"," run('mkdir -p '+outputPath)\n"," kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n"," return True\n","\n"]},{"cell_type":"markdown","metadata":{},"source":["## 同步文件夹到 huggingface\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 文件夹与 huggingface 同步\n","if '_huggingface_token' in locals() and '_huggingface_repo' in locals():\n"," if not is_installed('watchdog'):\n"," requirements.append('watchdog')\n"," if not is_installed('huggingface_hub'):\n"," requirements.append('huggingface_hub')\n"," else:\n"," try:\n"," from huggingface_hub import HfApi,login,snapshot_download\n"," except:\n"," requirements.append('huggingface_hub')\n","\n","huggingface_is_init = False\n","\n","def init_huggingface():\n"," if '_huggingface_token' not in globals() or '_huggingface_repo' not in globals():\n"," print('请增加配置项 _huggingface_token = \"token\" 和 _huggingface_repo = “仓库id” 后使用 huggingface 功能')\n"," return False\n"," if not _huggingface_repo or not _huggingface_token:\n"," print('当前无huggingface配置,可配置huggingface仓库和token将收藏的图片保存到huggingface仓库')\n"," return False\n"," global huggingface_is_init\n"," from huggingface_hub import HfApi,login,snapshot_download\n"," token = replace_path(_huggingface_token)\n"," if Path(token).exists():\n"," with open(token,encoding = \"utf-8\") as nkfile:\n"," token = nkfile.readline()\n"," if not token.startswith('hf_'):\n"," print('huggingface token 不正确,请将 token 或 仅存放token 的txt文件路径填入 _huggingface_token 配置')\n"," return False\n"," login(token,add_to_git_credential=True)\n"," huggingface_is_init = True\n"," return True\n","\n","\n","def download__huggingface_repo(repo_id:str,dist_directory:str=None,repo_type='datasets',callback=None):\n"," if not huggingface_is_init:\n"," print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n"," \n"," if not dist_directory:\n"," dist_directory = f'{install_path}/sd_main_dir/log'\n"," \n"," from huggingface_hub import HfApi,login,snapshot_download\n"," \n"," api = HfApi()\n"," \n"," print('下载收藏的图片')\n"," run(f'''mkdir -p {install_path}/cache/huggingface''')\n"," if not Path(f'{install_path}/cache/huggingface/{repo_id.split(\"/\")[1]}').exists():\n"," run(f'git clone https://huggingface.co/{repo_type}/{repo_id}',cwd=f'{install_path}/cache/huggingface')\n"," run(f'cp -r -f -n -s {install_path}/cache/huggingface/{repo_id.split(\"/\")[1]}/* {dist_directory}')\n","# snapshot_download(repo_id = repo_id, local_dir = dist_directory, local_dir_use_symlinks = \"auto\", token=True, repo_type=repo_type )\n"," if callback:\n"," callback()\n","\n","def start_sync_log_to_huggingface(repo_id:str,directory_to_watch:str=None,repo_type='datasets'):\n"," if not huggingface_is_init:\n"," print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n"," \n"," from watchdog.observers import Observer\n"," from watchdog.events import FileSystemEventHandler\n"," from huggingface_hub import HfApi,login,snapshot_download\n"," \n"," # 配置监视的目录和 Hugging Face 仓库信息\n"," class FileChangeHandler(FileSystemEventHandler):\n"," def __init__(self, api, repo_id, repo_type):\n"," self.api = api\n"," self.repo_id = repo_id\n"," self.repo_type = repo_type\n"," def on_created(self, event):\n"," if not event.is_directory:\n"," # 上传新文件到 Hugging Face 仓库\n"," file_path = event.src_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[-4:] not in ['.png','.jpg','.txt']: return\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except Error as error:\n"," print(error)\n","\n"," def on_deleted(self, event):\n"," if not event.is_directory:\n"," # 从 Hugging Face 仓库删除文件\n"," file_path = event.src_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[-4:] not in ['.png','.jpg','.txt']: return\n"," try:\n"," self.api.delete_file(\n"," path_in_repo=file_path.replace(directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except Error as error:\n"," print(error)\n","\n"," def on_modified(self, event):\n"," if not event.is_directory:\n"," # 更新 Hugging Face 仓库中的文件\n"," file_path = event.src_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[-4:] not in ['.png','.jpg','.txt']: return\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except Error as error:\n"," print(error)\n","\n"," def on_moved(self, event):\n"," if not event.is_directory:\n"," file_path = event.dest_path\n"," file_name = os.path.basename(file_path)\n"," if file_name[-4:] not in ['.png','.jpg','.txt']: return\n"," if event.dest_path.startswith(directory_to_watch):\n"," try:\n"," self.api.upload_file(\n"," path_or_fileobj=file_path,\n"," path_in_repo=file_path.replace(directory_to_watch,''),\n"," repo_id=self.repo_id,\n"," repo_type=self.repo_type,\n"," )\n"," except Error as error:\n"," print(error)\n","\n"," api = HfApi()\n"," \n"," if not directory_to_watch:\n"," directory_to_watch = f'{install_path}/sd_main_dir/log'\n"," # 创建观察者对象并注册文件变化处理程序\n"," event_handler = FileChangeHandler(api,repo_id,repo_type)\n"," observer = Observer()\n"," observer.schedule(event_handler, directory_to_watch, recursive=True)\n","\n"," # 启动观察者\n"," observer.name = \"solo_directory_to_watch\"\n"," print(f'启动收藏图片文件夹监听,并自动同步到 huggingface {repo_type} : {repo_id}')\n"," observer.start()"]},{"cell_type":"markdown","metadata":{"id":"sswa04veLCtE"},"source":["## 工具函数\n","**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"trusted":true},"outputs":[],"source":["def echoToFile(content:str,path:str):\n"," if path.find('/') >= 0:\n"," _path = '/'.join(path.split('/')[:-1])\n"," run(f'''mkdir -p {_path}''')\n"," with open(path,'w') as sh:\n"," sh.write(content)\n","\n","def zipPath(path:str,zipName:str,format='tar'):\n"," if path.startswith('$install_path'):\n"," path = path.replace('$install_path',install_path)\n"," if path.startswith('$output_path'):\n"," path = path.replace('$install_path',output_path)\n"," if not path.startswith('/'):\n"," path = f'{install_path}/sd_main_dir/{path}'\n"," if Path(path).exists():\n"," if 'tar' == format:\n"," run(f'tar -cf {output_path}/'+ zipName +'.tar -C '+ path +' . ')\n"," elif 'gz' == format:\n"," run(f'tar -czf {output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')\n"," return\n"," print('指定的目录不存在:'+path)\n","\n","# 检查网络\n","def check_service(host, port):\n"," try:\n"," socket.create_connection((host, port), timeout=5)\n"," return True\n"," except socket.error:\n"," return False"]},{"cell_type":"markdown","metadata":{},"source":["## 内网穿透\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"id":"coqQvTSLLCtE","trusted":true},"outputs":[],"source":["# ngrok\n","def startNgrok(ngrokToken:str,ngrokLocalPort:int):\n"," if not is_installed('pyngrok'):\n"," run(f'pip install pyngrok')\n"," from pyngrok import conf, ngrok\n"," try:\n"," conf.get_default().auth_token = ngrokToken\n"," conf.get_default().monitor_thread = False\n"," ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n"," if len(ssh_tunnels) == 0:\n"," ssh_tunnel = ngrok.connect(ngrokLocalPort)\n"," print('ngrok 访问地址:'+ssh_tunnel.public_url)\n"," else:\n"," print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n"," except:\n"," print('启动ngrok出错')\n"," \n","def startFrpc(name,configFile):\n"," echoToFile(f'''\n","cd {install_path}/frpc/\n","{install_path}/frpc/frpc {configFile}\n","''',f'{install_path}/frpc/start.sh')\n"," get_ipython().system(f'''bash {install_path}/frpc/start.sh''')\n"," \n","def installProxyExe():\n"," if _useFrpc:\n"," print('安装frpc')\n"," run(f'mkdir -p {install_path}/frpc')\n"," if Path(frpcExePath).exists():\n"," run(f'cp -f -n {frpcExePath} {install_path}/frpc/frpc')\n"," else:\n"," run(f'wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O {install_path}/frpc/frpc')\n"," \n"," for ssl in frpcSSLFFlies:\n"," if Path(ssl).exists():\n"," run(f'cp -f -n {ssl}/* {install_path}/frpc/')\n"," run(f'chmod +x {install_path}/frpc/frpc')\n"," run(f'{install_path}/frpc/frpc -v')\n"," if _useNgrok and not is_installed('pyngrok'):\n"," run('pip install pyngrok')\n","\n","def startProxy():\n"," if _useNgrok:\n"," startNgrok(ngrokToken,_webuiPort)\n"," if _useFrpc:\n"," startFrpc('frpc_proxy',frpcStartArg)"]},{"cell_type":"markdown","metadata":{},"source":["## NGINX 反向代理\n","\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"outputs":[],"source":["\n","# nginx 反向代理配置文件\n","def localProxy():\n"," conf = '''\n","server\n","{\n"," listen '''+str(_webuiPort)+''';\n"," listen [::]:'''+str(_webuiPort)+''';\n"," server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n"," \n"," if ($request_method = OPTIONS) {\n"," return 200;\n"," }\n"," fastcgi_send_timeout 10m;\n"," fastcgi_read_timeout 10m;\n"," fastcgi_connect_timeout 10m;\n"," location /1/\n"," {\n"," proxy_pass http://127.0.0.1:'''+str(_webuiPort+2)+'''/;\n"," # add_header Set-Cookie \"subpath=1; expires=0; Path=/\";\n"," # proxy_set_header Set-Cookie \"subpath=1; expires=0; Path=/\";\n"," proxy_set_header Host $host;\n"," proxy_set_header X-Real-IP $remote_addr;\n"," proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"," proxy_set_header REMOTE-HOST $remote_addr;\n"," proxy_set_header Upgrade $http_upgrade;\n"," proxy_set_header Connection upgrade;\n"," proxy_http_version 1.1;\n"," proxy_connect_timeout 10m;\n"," proxy_read_timeout 10m;\n"," }\n"," location /\n"," {\n"," set $proxy_url http://127.0.0.1:'''+str(_webuiPort+1)+''';\n"," # if ($cookie_subpath = \"1\") {\n"," # set $proxy_url http://127.0.0.1:'''+str(_webuiPort+2)+''';\n"," # }\n"," proxy_pass $proxy_url;\n"," proxy_set_header Host $host;\n"," proxy_set_header X-Real-IP $remote_addr;\n"," proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"," proxy_set_header REMOTE-HOST $remote_addr;\n"," proxy_set_header Upgrade $http_upgrade;\n"," proxy_set_header Connection upgrade;\n"," proxy_http_version 1.1;\n"," proxy_connect_timeout 10m;\n"," proxy_read_timeout 10m;\n"," }\n","}\n","'''\n"," echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n"," if not check_service('localhost',_webuiPort):\n"," run(f'''nginx -c /etc/nginx/nginx.conf''')\n"," run(f'''nginx -s reload''')\n"," "]},{"cell_type":"markdown","metadata":{},"source":["## 线程清理工具\n","\n","---\n","\n","清理线程名以 solo_ 开头的所有线程"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"trusted":true},"outputs":[],"source":["import inspect\n","import ctypes\n","\n","def _async_raise(tid, exctype):\n"," \"\"\"raises the exception, performs cleanup if needed\"\"\"\n"," tid = ctypes.c_long(tid)\n"," if not inspect.isclass(exctype):\n"," exctype = type(exctype)\n"," res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n"," if res == 0:\n"," raise ValueError(\"invalid thread id\")\n"," elif res != 1:\n"," # \"\"\"if it returns a number greater than one, you're in trouble,\n"," # and you should call it again with exc=NULL to revert the effect\"\"\"\n"," ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n"," raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n","\n","def stop_thread(thread):\n"," _async_raise(thread.ident, SystemExit)\n","\n","def stop_solo_threads():\n"," # 获取当前所有活动的线程\n"," threads = threading.enumerate()\n"," # 关闭之前创建的子线程\n"," for thread in threads:\n"," if thread.name.startswith('solo_'):\n"," print(f'结束线程:{thread.name}')\n"," try:\n"," stop_thread(thread)\n"," except socket.error:\n"," print(f'结束线程:{thread.name} 执行失败')"]},{"cell_type":"markdown","metadata":{"id":"Ve3p8oOkLCtE"},"source":["# webui 安装和配置函数\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"GTjyBJihLCtE","trusted":true},"outputs":[],"source":["envInstalled=False\n","quickStart = True\n","#安装webui\n","def install():\n"," print('安装webui')\n"," os.chdir(f'''{install_path}''')\n"," run(f'''git lfs install''')\n"," run(f'''git config --global credential.helper store''')\n"," for requirement in requirements:\n"," run(f'pip install {requirement}')\n"," if _reLoad:\n"," run(f'''rm -rf sd_main_dir''')\n"," if Path(\"sd_main_dir\").exists():\n"," os.chdir(f'''{install_path}/sd_main_dir/''')\n"," run(f'''git checkout .''')\n"," run(f'''git pull''')\n"," else:\n"," run(f'''git clone {_webui_git_repo} sd_main_dir''')\n"," os.chdir(f'''{install_path}/sd_main_dir''')\n"," print('安装webui 完成')\n","\n","# 链接输出目录\n","def link_dir():\n"," print('链接输出目录')\n"," # 链接图片输出目录\n"," run(f'''mkdir -p {output_path}/outputs''')\n"," run(f'''rm -rf {install_path}/sd_main_dir/outputs''')\n"," run(f'''ln -s -r {output_path}/outputs {install_path}/sd_main_dir/''')\n"," # 输出收藏目录\n"," run(f'''mkdir -p {output_path}/log''')\n"," run(f'''rm -rf {install_path}/sd_main_dir/log''')\n"," run(f'''ln -s -r {output_path}/log {install_path}/sd_main_dir/''')\n"," # 链接训练输出目录 文件夹链接会导致功能不能用\n"," run(f'''rm -rf {install_path}/sd_main_dir/textual_inversion''')\n"," run(f'''mkdir -p {output_path}/textual_inversion/''')\n"," run(f'''ln -s -r {output_path}/textual_inversion {install_path}/sd_main_dir/''')\n"," print('链接输出目录 完成') \n","\n","def install_optimizing():\n"," run('sudo apt install nginx -y')\n"," run('env TF_CPP_MIN_LOG_LEVEL=1')\n"," run('apt -y update -qq')\n"," run('wget http://launchpadlibrarian.net/367274644/libgoogle-perftools-dev_2.5-2.2ubuntu3_amd64.deb')\n"," run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/google-perftools_2.5-2.2ubuntu3_all.deb')\n"," run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libtcmalloc-minimal4_2.5-2.2ubuntu3_amd64.deb')\n"," run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libgoogle-perftools4_2.5-2.2ubuntu3_amd64.deb')\n"," run('apt -y install -qq libunwind8-dev')\n"," run('dpkg -i *.deb')\n"," run('env LD_P_reLoad=libtcmalloc.so')\n"," run('rm *.deb')\n"," \n","#安装依赖\n","def install_dependencies():\n"," print('安装webui需要的python环境')\n"," global envInstalled\n"," global venvPath\n"," run(f'''rm -rf {install_path}/sd_main_dir/venv''')\n"," run(f'''mkdir -p {install_path}/sd_main_dir/venv''')\n"," if str(sys.version).startswith('3.10'):\n"," try:\n"," run('python3 -m venv venv' ,cwd=f'{install_path}/sd_main_dir',try_error=False)\n"," except:\n"," run('apt install python3.10-venv -y')\n"," run('python3 -m venv venv' ,cwd=f'{install_path}/sd_main_dir')\n"," else:\n"," run('add-apt-repository ppa:deadsnakes/ppa -y')\n"," run('apt update')\n"," run('apt install python3.10 -y')\n"," run('python3.10 -m venv venv',cwd=f'{install_path}/sd_main_dir')\n"," \n"," if quickStart:\n"," if not Path(venvPath).exists():\n"," run(f'''mkdir -p {install_path}/venv_cache''')\n"," if not Path(f'{install_path}/venv_cache/venv.tar.bak').exists():\n"," download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{install_path}/venv_cache')\n"," run(f'''unzip {install_path}/venv_cache/venv.zip -d {install_path}/venv_cache''')\n"," venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n"," run(f'''rm -rf {install_path}/venv_cache/venv.zip''')\n"," elif venvPath.endswith('.zip'):\n"," run(f'''mkdir -p {install_path}/venv_cache''')\n"," run(f'''unzip {venvPath} -d {install_path}/venv_cache''')\n"," venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n"," print('解压环境')\n"," run(f'tar -xf {venvPath} -C {install_path}/sd_main_dir/venv')\n"," if not Path(f'{install_path}/sd_main_dir/venv/bin/pip').exists():\n"," run('curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py')\n"," run(f'{install_path}/sd_main_dir/venv/bin/python3 get-pip.py')\n","\n"," get_ipython().system(f'''{install_path}/sd_main_dir/venv/bin/python3 -V''')\n"," get_ipython().system(f'''{install_path}/sd_main_dir/venv/bin/python3 -m pip -V''')\n","\n"," envInstalled = True\n"," print('安装webui需要的python环境 完成')\n"," \n","# 个性化配置 \n","def use_config():\n"," print('使用自定义配置 包括tag翻译 \\n')\n"," run(f'''mkdir -p {install_path}/temp''')\n"," run(f'git clone {_webui_config_git_repu} sd-configs',cwd=f'{install_path}/temp')\n"," run(f'cp -r -f -n {install_path}/temp/sd-configs/dist/* {install_path}/sd_main_dir')\n"," if not Path(_ui_config_file).exists(): # ui配置文件\n"," run(f'''mkdir -p {_ui_config_file[:_ui_config_file.rfind('/')]}''')\n"," run(f'cp -f -n {install_path}/sd_main_dir/ui-config.json {_ui_config_file}')\n"," if not Path(_setting_file).exists(): # 设置配置文件\n"," run(f'''mkdir -p {_setting_file[:_setting_file.rfind('/')]}''')\n"," run(f'cp -f -n {install_path}/sd_main_dir/config.json {_setting_file}')\n","\n","def copy_last_log_to_images():\n"," print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')\n"," img_list = os.listdir(f'{install_path}/sd_main_dir/log/images')\n"," last_img_path = ''\n"," last_img_num = 0\n"," for img in img_list:\n"," if re.findall(r'^\\d+-',str(img)):\n"," num = int(re.findall(r'^\\d+-',str(img))[0][:-1])\n"," if num > last_img_num:\n"," last_img_path = img\n"," last_img_num = num\n"," print(f'{install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/txt2img-images')\n"," run(f'''mkdir -p {install_path}/sd_main_dir/outputs/txt2img-images''')\n"," run(f'''cp -f {install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/txt2img-images/''')\n"," \n"," print(f'{install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/img2img-images')\n"," run(f'''mkdir -p {install_path}/sd_main_dir/outputs/img2img-images''')\n"," run(f'''cp -f {install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/img2img-images/''')\n"," \n","def start_webui(i):\n"," # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n"," print(i,'--port',str(_webuiPort+1+i))\n"," if i>0:\n"," print(f'使用第{i+1}张显卡启动第{i+1}个webui,通过frpc或nrgok地址后加/{i}/进行访问(不能使用同一个浏览器)')\n"," if _useFrpc:\n"," restart_times = 0\n"," last_restart_time = time.time()\n"," while True:\n"," get_ipython().system(f'''{install_path}/sd_main_dir/venv/bin/python3 launch.py --device-id={i} --port {str(_webuiPort+1+i)} {'' if i ==0 else '--nowebui'}''')\n"," print('5秒后重启webui')\n"," if time.time() - last_restart_time < 30:\n"," restart_times = restart_times + 1\n"," else:\n"," restart_times = 0\n"," last_restart_time = time.time()\n"," if restart_times >3 :\n"," # 如果90秒内重启了3此,将不再自动重启\n"," break\n"," time.sleep(5)\n"," else:\n"," get_ipython().system(f'''{install_path}/sd_main_dir/venv/bin/python3 launch.py --device-id={i} --port {str(_webuiPort+1+i)} {'' if i ==0 else '--nowebui'}''')\n"," \n","# 启动\n","def start():\n"," print('启动webui')\n"," os.chdir(f'''{install_path}/sd_main_dir''')\n"," args = ''\n"," if _ui_config_file is not None and _ui_config_file != '' and Path(_ui_config_file).exists(): # ui配置文件\n"," args += ' --ui-config-file=' + _ui_config_file\n"," if _setting_file is not None and _setting_file != '' and Path(_setting_file).exists(): # 设置配置文件\n"," args += ' --ui-settings-file=' + _setting_file\n"," args += ' ' + otherArgs\n"," os.environ['COMMANDLINE_ARGS']=args\n"," run(f'''echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS''')\n"," os.environ['REQS_FILE']='requirements.txt'\n","\n"," with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:\n"," for i in range(torch.cuda.device_count() if '多实例' in globals() and 多实例 else 1):\n"," executor.submit(start_webui,i)\n"," while not check_service('localhost',str(_webuiPort+1+i)): # 当当前服务启动完成才允许退出此次循环\n"," time.sleep(5)\n"," time.sleep(10)"]},{"cell_type":"markdown","metadata":{"id":"qLvsk8ByLCtF"},"source":["# 入口函数\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-input":true,"id":"IOKjaMlcLCtF","trusted":true},"outputs":[],"source":["\n","# 启动非webui相关的的内容,加快启动速度\n","def main():\n"," global envInstalled\n"," global huggingface_is_init\n"," startTicks = time.time()\n"," stop_solo_threads()\n"," isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n"," if isInstall is False or _reLoad: \n"," print('启动 安装webui和运行环境')\n"," install()\n"," link_dir()\n"," init_huggingface()\n"," threading.Thread(target = install_dependencies,daemon=True,name='solo_install_dependencies').start()\n"," threading.Thread(target = install_optimizing,daemon=True,name='solo_install_optimizing').start()\n"," threading.Thread(target = installProxyExe,daemon=True).start()\n"," link_or_download_flie(replace_path(_普通文件列表), _link_instead_of_copy=_link_instead_of_copy,\n"," base_path=f'{install_path}/sd_main_dir')\n"," if huggingface_is_init:\n"," threading.Thread(target = download__huggingface_repo,daemon=True,\n"," args=([_huggingface_repo]),\n"," kwargs={\"callback\":copy_last_log_to_images},\n"," name='solo_download__huggingface_repo').start()\n"," \n"," link_or_download_flie(replace_path(_重要文件列表), _link_instead_of_copy=_link_instead_of_copy,\n"," base_path=f'{install_path}/sd_main_dir',is_await=True)\n"," t = 0\n"," while not envInstalled:\n"," if t%10==0:\n"," print('等待python环境安装...')\n"," t = t+1\n"," time.sleep(1)\n"," use_config()\n"," localProxy()\n"," os.environ['IsInstall'] = 'True'\n"," else:\n"," envInstalled = True\n"," link_or_download_flie(replace_path(_按顺序加载的重要文件列表), _link_instead_of_copy=_link_instead_of_copy,\n"," base_path=f'{install_path}/sd_main_dir',sync=True)\n"," threading.Thread(target = startProxy, daemon=True, name='solo_startProxy').start()\n"," if init_huggingface():\n"," start_sync_log_to_huggingface(_huggingface_repo)\n"," ticks = time.time()\n"," print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n"," start()\n"]},{"cell_type":"markdown","metadata":{"id":"0oaCRs2gLCtF"},"source":["# 执行区域\n","---"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["print(update_desc)"]},{"cell_type":"code","execution_count":null,"metadata":{"_kg_hide-output":true,"id":"O3DR0DWHLCtF","scrolled":true,"trusted":true},"outputs":[],"source":["# 启动\n","# _reLoad = True\n","# hidden_console_info = False\n","# run_by_none_device = True\n","# show_shell_info = True\n","if _skip_start:\n"," print('已跳过自动启动,可手动执行 main() 进行启动。')\n"," print('''推荐的启动代码:\n","try:\n"," check_gpu() # 检查是否存在gpu\n"," main()\n","except KeyboardInterrupt:\n"," stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)\n"," ''')\n","else:\n"," try:\n"," check_gpu()\n"," main()\n"," except KeyboardInterrupt:\n"," stop_solo_threads()"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"}},"nbformat":4,"nbformat_minor":4}
 
 
sdwui-start-util.dev.ipynb DELETED
@@ -1,1737 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": null,
6
- "metadata": {
7
- "trusted": true
8
- },
9
- "outputs": [],
10
- "source": []
11
- },
12
- {
13
- "cell_type": "code",
14
- "execution_count": null,
15
- "metadata": {
16
- "trusted": true
17
- },
18
- "outputs": [],
19
- "source": [
20
- "update_desc = '''\n",
21
- "欢迎使用 stable-diffusion-webui 便捷启动工具\n",
22
- "\n",
23
- "此脚本理论上可以在任何jupyter环境运行,但仅在 google colab 和 kaggle 测试。 已经无法在 google colab 免费实例上运行。\n",
24
- "此脚本的【前置脚本】发布地址 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai-sdxl。\n",
25
- "此脚本需配合 【前置脚本】 的脚本附带的配置项才能正常启动。\n",
26
- "此脚本的内容会自动更新,你无需更新【前置脚本】就能获取到最新的功能。\n",
27
- "增加一个说明:为解决加密图片的解密和浏览的问题,开发了一个独立应用,可以在这里下载 https://github.com/viyiviyi/encrypt_gallery/releases/\n",
28
- "加密插件可解决生成nsfw图片后被平台封号问题\n",
29
- "\n",
30
- "路径说明\n",
31
- "* 为了解决平台差异,所有的安装目录和文件输出目录都被重新指定,如果你需要在配置中访问这些目录,请查看以下说明\n",
32
- "*\n",
33
- "* 可以使用 $install_path 或 {install_path} 来访问安装目录,写在字符串内也会生效\n",
34
- "* $output_path 或 {output_path} 可以访问输出目录\n",
35
- "* 如果你需要安装在自定义目录,也可以设置这些值 如: install_path = '新的路径'\n",
36
- "* 可自定义方法 on_before_start 并在方法内写上启动前需要的逻辑来实现在webui启动前执行自定义逻辑\n",
37
- "* 可以增加配置 multi_case = True 来控制是否使用多卡\n",
38
- "* 如果需要显示更多控制台输出 需配置 hidden_console_info = False\n",
39
- "\n",
40
- "********* 特别提示 *********\n",
41
- "* huggingface 的下载链接需要增加 ?download=true 参数才能正确下载到文件,如果你需要的文件里的下载链接没有这个参数,请自行增加。\n",
42
- "'''"
43
- ]
44
- },
45
- {
46
- "cell_type": "code",
47
- "execution_count": null,
48
- "metadata": {
49
- "trusted": true
50
- },
51
- "outputs": [],
52
- "source": [
53
- "from pathlib import Path\n",
54
- "import os\n",
55
- "import time\n",
56
- "import re\n",
57
- "import subprocess\n",
58
- "import threading\n",
59
- "import sys\n",
60
- "import socket\n",
61
- "import torch\n",
62
- "from typing import List\n",
63
- "import uuid\n",
64
- "import asyncio\n",
65
- "from urllib import request"
66
- ]
67
- },
68
- {
69
- "cell_type": "code",
70
- "execution_count": null,
71
- "metadata": {
72
- "trusted": true
73
- },
74
- "outputs": [],
75
- "source": [
76
- "# 内置参数默认值,当上下文有参数时可覆盖默认值\n",
77
- "_runing = False\n",
78
- "\n",
79
- "_useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n",
80
- "\n",
81
- "_useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n",
82
- "\n",
83
- "_reLoad = locals().get('reLoad') or globals().get('reLoad') or False\n",
84
- " \n",
85
- "_before_downloading = locals().get('before_downloading') or globals().get('before_downloading') or ''\n",
86
- "\n",
87
- "_async_downloading = locals().get('async_downloading') or globals().get('async_downloading') or ''\n",
88
- "\n",
89
- "_before_start_sync_downloading = locals().get('before_start_sync_downloading') or globals().get('before_start_sync_downloading') or ''\n",
90
- "\n",
91
- "_server_port = locals().get('server_port') or globals().get('server_port') or 7860\n",
92
- " \n",
93
- "_sd_git_repo = locals().get('sd_git_repo') or globals().get('sd_git_repo') or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n",
94
- "_sd_git_repo = _sd_git_repo\\\n",
95
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
96
- " .replace('{wui}',\"webui\")\n",
97
- " \n",
98
- "_sd_config_git_repu = locals().get('sd_config_git_repu') or globals().get('sd_config_git_repu') or 'https://github.com/viyiviyi/sd-configs.git'\n",
99
- "_sd_config_git_repu = _sd_config_git_repu\\\n",
100
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
101
- " .replace('{wui}',\"webui\")\n",
102
- " \n",
103
- " \n",
104
- "_huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n",
105
- "_huggingface_token = _huggingface_token\\\n",
106
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
107
- " .replace('{wui}',\"webui\")\n",
108
- " \n",
109
- "_huggingface_repo = locals().get('huggingface_repo') or globals().get('huggingface_repo') or ''\n",
110
- "_huggingface_repo = _huggingface_repo\\\n",
111
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
112
- " .replace('{wui}',\"webui\")\n",
113
- "\n",
114
- "_link_instead_of_copy = locals().get('link_instead_of_copy') or globals().get('link_instead_of_copy') or True\n",
115
- " \n",
116
- "show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n",
117
- "if show_shell_info is None: show_shell_info = False\n",
118
- "else: show_shell_info = not show_shell_info\n",
119
- "\n",
120
- "_multi_case = locals().get('multi_case') or globals().get('multi_case') or False\n",
121
- " \n",
122
- "_skip_start = locals().get('skip_start') or globals().get('skip_start') or True\n",
123
- "\n",
124
- "def before_start():\n",
125
- " pass\n",
126
- "\n",
127
- "def main_start():\n",
128
- " pass\n",
129
- "\n",
130
- "_on_before_start = locals().get('on_before_start') or globals().get('on_before_start') or before_start \n",
131
- "_skip_webui = locals().get('skip_webui') or globals().get('skip_webui') or False\n",
132
- " \n",
133
- "run_by_none_device = False\n",
134
- "\n",
135
- "_proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n",
136
- "\n",
137
- "_sub_path = locals().get('sub_path') or globals().get('sub_path') or ['/','/1/']\n",
138
- "if len(_sub_path) != 2:\n",
139
- " _sub_path = ['/','/1/']\n",
140
- " \n",
141
- "_config_args:dict[str, str] = locals().get('config_args') or globals().get('config_args') or {}"
142
- ]
143
- },
144
- {
145
- "cell_type": "code",
146
- "execution_count": null,
147
- "metadata": {
148
- "trusted": true
149
- },
150
- "outputs": [],
151
- "source": [
152
- "\n",
153
- "def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:\n",
154
- " global show_shell_info\n",
155
- " if desc is not None:\n",
156
- " print(desc)\n",
157
- "\n",
158
- " run_kwargs = {\n",
159
- " \"args\": command,\n",
160
- " \"shell\": True,\n",
161
- " \"cwd\": cwd,\n",
162
- " \"env\": os.environ if custom_env is None else custom_env,\n",
163
- " \"encoding\": 'utf8',\n",
164
- " \"errors\": 'ignore',\n",
165
- " }\n",
166
- "\n",
167
- " if not show_shell_info:\n",
168
- " run_kwargs[\"stdout\"] = run_kwargs[\"stderr\"] = subprocess.PIPE\n",
169
- "\n",
170
- " result = subprocess.run(**run_kwargs)\n",
171
- "\n",
172
- " if result.returncode != 0:\n",
173
- " error_bits = [\n",
174
- " f\"{errdesc or 'Error running command'}.\",\n",
175
- " f\"Command: {command}\",\n",
176
- " f\"Error code: {result.returncode}\",\n",
177
- " ]\n",
178
- " if result.stdout:\n",
179
- " error_bits.append(f\"stdout: {result.stdout}\")\n",
180
- " if result.stderr:\n",
181
- " error_bits.append(f\"stderr: {result.stderr}\")\n",
182
- " if try_error:\n",
183
- " print((RuntimeError(\"\\n\".join(error_bits))))\n",
184
- " else:\n",
185
- " raise RuntimeError(\"\\n\".join(error_bits))\n",
186
- "\n",
187
- " if show_shell_info:\n",
188
- " print((result.stdout or \"\"))\n",
189
- " return (result.stdout or \"\")\n",
190
- "\n",
191
- "def mkdirs(path, exist_ok=True):\n",
192
- " if path and not Path(path).exists():\n",
193
- " os.makedirs(path,exist_ok=exist_ok)\n",
194
- "\n",
195
- "\n",
196
- "# 检查网络\n",
197
- "def check_service(host, port):\n",
198
- " try:\n",
199
- " socket.create_connection((host, port), timeout=5)\n",
200
- " return True\n",
201
- " except socket.error:\n",
202
- " return False\n",
203
- "\n",
204
- "\n",
205
- "# 检查gpu是否存在\n",
206
- "def check_gpu():\n",
207
- " if not run_by_none_device and torch.cuda.device_count() == 0:\n",
208
- " raise Exception('当前环境没有GPU')\n",
209
- "\n",
210
- "\n",
211
- "def echoToFile(content:str,path:str):\n",
212
- " if path.find('/') >= 0:\n",
213
- " _path = '/'.join(path.split('/')[:-1])\n",
214
- " run(f'''mkdir -p {_path}''')\n",
215
- " with open(path,'w') as sh:\n",
216
- " sh.write(content)\n",
217
- " \n",
218
- "def get_freefrp_confog(local_port):\n",
219
- " rd_str = uuid.uuid1()\n",
220
- " return (f'''\n",
221
- "[common]\n",
222
- "server_addr = frp.freefrp.net\n",
223
- "server_port = 7000\n",
224
- "token = freefrp.net\n",
225
- "\n",
226
- "[{rd_str}_http]\n",
227
- "type = http\n",
228
- "local_ip = 127.0.0.1\n",
229
- "local_port = {local_port}\n",
230
- "custom_domains = {rd_str}.frp.eaias.com\n",
231
- "''',f'http://{rd_str}.frp.eaias.com')"
232
- ]
233
- },
234
- {
235
- "cell_type": "code",
236
- "execution_count": null,
237
- "metadata": {
238
- "trusted": true
239
- },
240
- "outputs": [],
241
- "source": [
242
- "\n",
243
- "_install_path = f\"/kaggle\" if os.path.exists('/kaggle/') else f\"{os.environ['HOME']}/sd_webui\" # 安装目录\n",
244
- "_output_path = '/kaggle/working' if os.path.exists('/kaggle/working/') else f\"{os.environ['HOME']}/.sdwui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\n",
245
- "_input_path = '/kaggle/input' # 输入目录\n",
246
- "_ui_dir_name = 'sd_main_dir'\n",
247
- "\n",
248
- "_install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
249
- "_output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
250
- "_input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
251
- "_ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
252
- "\n",
253
- "install_path = _install_path\n",
254
- "output_path = _output_path\n",
255
- "input_path = _input_path\n",
256
- "ui_dir_name = _ui_dir_name\n",
257
- " \n",
258
- "google_drive = '' \n",
259
- "\n",
260
- "\n",
261
- "_useGooglrDrive = locals().get('useGooglrDrive') or globals().get('useGooglrDrive') or True\n",
262
- "\n",
263
- "# 连接谷歌云\n",
264
- "try:\n",
265
- " if _useGooglrDrive:\n",
266
- " from google.colab import drive\n",
267
- " drive.mount(f'~/google_drive')\n",
268
- " google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n",
269
- " _output_path = f'{google_drive}/sdwebui/Output'\n",
270
- " _input_path = f'{google_drive}/sdwebui/Input'\n",
271
- " run(f'''mkdir -p {_input_path}''')\n",
272
- " print('''\n",
273
- "已经链接到谷歌云盘\n",
274
- "已在云盘创建Input和Output目录\n",
275
- " ''')\n",
276
- "except:\n",
277
- " _useGooglrDrive = False\n",
278
- "\n",
279
- "run(f'''mkdir -p {_install_path}''')\n",
280
- "run(f'''mkdir -p {_output_path}''')\n",
281
- "\n",
282
- "\n",
283
- "os.environ['install_path'] = _install_path\n",
284
- "os.environ['output_path'] = _output_path\n",
285
- "os.environ['google_drive'] = google_drive\n",
286
- "os.environ['input_path'] = _input_path\n",
287
- "\n",
288
- "def replace_path(input_str:str):\n",
289
- " if not input_str: return ''\n",
290
- " for key in _config_args:\n",
291
- " input_str = input_str.replace(key,_config_args[key])\n",
292
- " \n",
293
- " if not (locals().get('use_comfyui') or globals().get('use_comfyui') or False):\n",
294
- " input_str = input_str.replace('https://github.com/comfyanonymous/ComfyUI.git','https://github.com/comfyanonymous/ComfyUI.git')\n",
295
- " \n",
296
- " return input_str.replace('$install_path',_install_path)\\\n",
297
- " .replace('{install_path}',_install_path)\\\n",
298
- " .replace('$input_path',_input_path)\\\n",
299
- " .replace('{input_path}',_input_path)\\\n",
300
- " .replace('$output_path',_output_path)\\\n",
301
- " .replace('{output_path}',_output_path)\\\n",
302
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
303
- " .replace('{wui}',\"webui\")\n",
304
- "\n",
305
- "space_string = ' \\n\\r\\t\\'\\\",'\n",
306
- "\n",
307
- "def config_reader(conf:str):\n",
308
- " conf = conf or \"\"\n",
309
- " args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\\n') if item.strip(space_string)]\n",
310
- " return [item.strip() for item in args if item.strip()]\n"
311
- ]
312
- },
313
- {
314
- "cell_type": "code",
315
- "execution_count": null,
316
- "metadata": {
317
- "_kg_hide-input": true,
318
- "id": "i3LhnwYHLCtC",
319
- "trusted": true
320
- },
321
- "outputs": [],
322
- "source": [
323
- "ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
324
- "frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
325
- "# ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
326
- "frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
327
- "if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
328
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
329
- "# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
330
- "frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n",
331
- "# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n",
332
- "otherArgs = '--xformers'\n",
333
- "if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
334
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
335
- "venvPath = os.path.join(_input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n",
336
- "\n",
337
- "# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n",
338
- "# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\n",
339
- "kaggleApiTokenFile = os.path.join(_input_path,'configs/kaggle.json')\n",
340
- "\n",
341
- "requirements = []\n"
342
- ]
343
- },
344
- {
345
- "cell_type": "code",
346
- "execution_count": null,
347
- "metadata": {
348
- "_kg_hide-input": true,
349
- "id": "a_GtG2ayLCtD",
350
- "trusted": true
351
- },
352
- "outputs": [],
353
- "source": [
354
- "# 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
355
- "_setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
356
- "\n",
357
- "_ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
358
- "\n",
359
- "# 设置文件路径\n",
360
- "if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
361
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
362
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
363
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
364
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
365
- " \n",
366
- "frpcStartArg = ''\n",
367
- "freefrp_url = ''\n",
368
- "_frp_temp_config_file = ''\n",
369
- "_frp_config_or_file = replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or frpcConfigFile\n",
370
- "run(f'''mkdir -p {_install_path}/configFiles''')\n",
371
- "if _frp_config_or_file:\n",
372
- " if '[common]' in _frp_config_or_file:\n",
373
- " echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_webui.ini')\n",
374
- " _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_webui.ini'\n",
375
- " elif '.ini' in _frp_config_or_file:\n",
376
- " _frp_temp_config_file = _frp_config_or_file.strip()\n",
377
- " \n",
378
- " if _frp_temp_config_file:\n",
379
- " if Path(_frp_temp_config_file).exists():\n",
380
- " run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_webui.ini''')\n",
381
- " run(f'''sed -i \"s/local_port = .*/local_port = {_server_port}/g\" {_install_path}/configFiles/frpc_webui.ini''')\n",
382
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
383
- " elif _frp_config_or_file.strip().startswith('-f'):\n",
384
- " frpcStartArg = _frp_config_or_file.strip()\n",
385
- " \n",
386
- "if not frpcStartArg:\n",
387
- " conf,url = get_freefrp_confog(_server_port)\n",
388
- " echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n",
389
- " freefrp_url = url\n",
390
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
391
- "\n",
392
- "ngrokToken=''\n",
393
- "_ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
394
- "if _ngrok_config_or_file:\n",
395
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
396
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
397
- " if Path(ngrokTokenFile).exists():\n",
398
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
399
- " ngrokToken = nkfile.readline()\n",
400
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
401
- " ngrokToken=_ngrok_config_or_file.strip()\n",
402
- " \n",
403
- "if not Path(venvPath).exists():\n",
404
- " venvPath = os.path.join(_input_path,'sd-webui-venv/venv.zip')\n",
405
- " \n",
406
- "huggingface_headers:dict = None "
407
- ]
408
- },
409
- {
410
- "cell_type": "code",
411
- "execution_count": null,
412
- "metadata": {},
413
- "outputs": [],
414
- "source": [
415
- "def _init_conf():\n",
416
- " global _useFrpc\n",
417
- " global _useNgrok\n",
418
- " global _reLoad\n",
419
- " global _before_downloading\n",
420
- " global _async_downloading\n",
421
- " global _before_start_sync_downloading\n",
422
- " global _server_port\n",
423
- " global _sd_git_repo\n",
424
- " global _sd_config_git_repu\n",
425
- " global _huggingface_token\n",
426
- " global _huggingface_repo\n",
427
- " global _link_instead_of_copy\n",
428
- " global show_shell_info\n",
429
- " global _multi_case\n",
430
- " global _skip_start\n",
431
- " global _on_before_start\n",
432
- " global _skip_webui\n",
433
- " global _proxy_path\n",
434
- " global _sub_path\n",
435
- " global _config_args\n",
436
- " global _install_path\n",
437
- " global _output_path\n",
438
- " global _input_path\n",
439
- " global _ui_dir_name\n",
440
- " \n",
441
- " global ngrokTokenFile\n",
442
- " global frpcConfigFile\n",
443
- " global frpcSSLFFlies\n",
444
- " global frpcExePath\n",
445
- " global otherArgs\n",
446
- " global _setting_file\n",
447
- " global _ui_config_file\n",
448
- " global _frp_temp_config_file\n",
449
- " global _frp_config_or_file\n",
450
- " global ngrokToken\n",
451
- " global venvPath\n",
452
- " \n",
453
- " _useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n",
454
- " _useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n",
455
- " _reLoad = locals().get('reLoad') or globals().get('reLoad') or False\n",
456
- " _before_downloading = locals().get('before_downloading') or globals().get('before_downloading') or ''\n",
457
- " _async_downloading = locals().get('async_downloading') or globals().get('async_downloading') or ''\n",
458
- " _before_start_sync_downloading = locals().get('before_start_sync_downloading') or globals().get('before_start_sync_downloading') or ''\n",
459
- " _server_port = locals().get('server_port') or globals().get('server_port') or 7860\n",
460
- " _sd_git_repo = locals().get('sd_git_repo') or globals().get('sd_git_repo') or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n",
461
- " _sd_git_repo = _sd_git_repo\\\n",
462
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
463
- " .replace('{wui}',\"webui\") \n",
464
- " _sd_config_git_repu = locals().get('sd_config_git_repu') or globals().get('sd_config_git_repu') or 'https://github.com/viyiviyi/sd-configs.git'\n",
465
- " _sd_config_git_repu = _sd_config_git_repu\\\n",
466
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
467
- " .replace('{wui}',\"webui\")\n",
468
- " _huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n",
469
- " _huggingface_token = _huggingface_token\\\n",
470
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
471
- " .replace('{wui}',\"webui\")\n",
472
- " _huggingface_repo = locals().get('huggingface_repo') or globals().get('huggingface_repo') or ''\n",
473
- " _huggingface_repo = _huggingface_repo\\\n",
474
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
475
- " .replace('{wui}',\"webui\")\n",
476
- " _link_instead_of_copy = locals().get('link_instead_of_copy') or globals().get('link_instead_of_copy') or True\n",
477
- " show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n",
478
- " if show_shell_info is None: show_shell_info = False\n",
479
- " else: show_shell_info = not show_shell_info\n",
480
- " _multi_case = locals().get('multi_case') or globals().get('multi_case') or False\n",
481
- " _skip_start = locals().get('skip_start') or globals().get('skip_start') or True\n",
482
- " _on_before_start = locals().get('on_before_start') or globals().get('on_before_start') or before_start \n",
483
- " _skip_webui = locals().get('skip_webui') or globals().get('skip_webui') or False\n",
484
- " _proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n",
485
- " _sub_path = locals().get('sub_path') or globals().get('sub_path') or ['/','/1/']\n",
486
- " if len(_sub_path) != 2:\n",
487
- " _sub_path = ['/','/1/']\n",
488
- " \n",
489
- " _config_args = locals().get('config_args') or globals().get('config_args') or {}\n",
490
- " \n",
491
- " _install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
492
- " _output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
493
- " _input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
494
- " _ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
495
- " \n",
496
- " ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
497
- " frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
498
- " # ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
499
- " frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
500
- " if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
501
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
502
- " # frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
503
- " frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n",
504
- " # 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n",
505
- " otherArgs = '--xformers'\n",
506
- " if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
507
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
508
- "\n",
509
- " # 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
510
- " _setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
511
- "\n",
512
- " _ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
513
- "\n",
514
- " # 设置文件路径\n",
515
- " if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
516
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
517
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
518
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
519
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
520
- " \n",
521
- " frpcStartArg = ''\n",
522
- " freefrp_url = ''\n",
523
- " _frp_temp_config_file = ''\n",
524
- " _frp_config_or_file = replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or frpcConfigFile\n",
525
- " run(f'''mkdir -p {_install_path}/configFiles''')\n",
526
- " if _frp_config_or_file:\n",
527
- " if '[common]' in _frp_config_or_file:\n",
528
- " echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_webui.ini')\n",
529
- " _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_webui.ini'\n",
530
- " elif '.ini' in _frp_config_or_file:\n",
531
- " _frp_temp_config_file = _frp_config_or_file.strip()\n",
532
- " \n",
533
- " if _frp_temp_config_file:\n",
534
- " if Path(_frp_temp_config_file).exists():\n",
535
- " run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_webui.ini''')\n",
536
- " run(f'''sed -i \"s/local_port = .*/local_port = {_server_port}/g\" {_install_path}/configFiles/frpc_webui.ini''')\n",
537
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
538
- " elif _frp_config_or_file.strip().startswith('-f'):\n",
539
- " frpcStartArg = _frp_config_or_file.strip()\n",
540
- " \n",
541
- " if not frpcStartArg:\n",
542
- " conf,url = get_freefrp_confog(_server_port)\n",
543
- " echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n",
544
- " freefrp_url = url\n",
545
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
546
- "\n",
547
- " ngrokToken=''\n",
548
- " _ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
549
- " if _ngrok_config_or_file:\n",
550
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
551
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
552
- " if Path(ngrokTokenFile).exists():\n",
553
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
554
- " ngrokToken = nkfile.readline()\n",
555
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
556
- " ngrokToken=_ngrok_config_or_file.strip()\n",
557
- " \n",
558
- " if not Path(venvPath).exists():\n",
559
- " venvPath = os.path.join(_input_path,'sd-webui-venv/venv.zip')\n",
560
- " "
561
- ]
562
- },
563
- {
564
- "cell_type": "markdown",
565
- "metadata": {},
566
- "source": [
567
- "## 文件下载工具\n",
568
- "\n",
569
- "---\n",
570
- "\n",
571
- "link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',sync:bool=False,thread_num:int=None)"
572
- ]
573
- },
574
- {
575
- "cell_type": "code",
576
- "execution_count": null,
577
- "metadata": {
578
- "trusted": true
579
- },
580
- "outputs": [],
581
- "source": [
582
- "import concurrent.futures\n",
583
- "import importlib\n",
584
- "import os\n",
585
- "import pprint\n",
586
- "import re\n",
587
- "import venv\n",
588
- "from pathlib import Path\n",
589
- "from typing import List\n",
590
- "\n",
591
- "import requests\n",
592
- "\n",
593
- "show_shell_info = False\n",
594
- "\n",
595
- "def is_installed(package):\n",
596
- " try:\n",
597
- " spec = importlib.util.find_spec(package)\n",
598
- " except ModuleNotFoundError:\n",
599
- " return False\n",
600
- "\n",
601
- " return spec is not None\n",
602
- "\n",
603
- "def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True,headers={}):\n",
604
- " startTicks = time.time()\n",
605
- " # 获取文件的真实文件名\n",
606
- " if not filename:\n",
607
- " with requests.get(url, stream=True,headers=headers) as r:\n",
608
- " if 'Content-Disposition' in r.headers:\n",
609
- " filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n",
610
- " r.close()\n",
611
- " if not filename and re.search(r'/[^/]+\\.[^/]+$',url):\n",
612
- " filename = url.split('/')[-1].split('?')[0]\n",
613
- " \n",
614
- " filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n",
615
- " filename = re.sub(r'[\\s\\t]+', '_', filename)\n",
616
- " \n",
617
- " print(f'下载 {filename} url: {url} --> {dist_path}')\n",
618
- " \n",
619
- " # 创建目录\n",
620
- " if cache_path and not Path(cache_path).exists():\n",
621
- " os.makedirs(cache_path,exist_ok=True)\n",
622
- " if dist_path and not Path(dist_path).exists():\n",
623
- " os.makedirs(dist_path,exist_ok=True)\n",
624
- " \n",
625
- " # 拼接文件的完整路径\n",
626
- " filepath = os.path.join(dist_path, filename)\n",
627
- "\n",
628
- " if cache_path:\n",
629
- " cache_path = os.path.join(cache_path, filename)\n",
630
- " \n",
631
- " # 判断文件是否已存在\n",
632
- " if Path(filepath).exists():\n",
633
- " print(f'文件 {filename} 已存在 {dist_path}')\n",
634
- " return\n",
635
- " \n",
636
- " if cache_path and Path(cache_path).exists():\n",
637
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
638
- " print(f'文件缓存 {cache_path} --> {dist_path}')\n",
639
- " return\n",
640
- " # 下载文件\n",
641
- " size = 0\n",
642
- " with requests.get(url, stream=True, headers=headers) as r:\n",
643
- " r.raise_for_status()\n",
644
- " with open(cache_path or filepath, 'wb') as f:\n",
645
- " for chunk in r.iter_content(chunk_size=1024*1024):\n",
646
- " if chunk:\n",
647
- " size += len(chunk)\n",
648
- " f.write(chunk)\n",
649
- " # 如果使用了缓存目录 需要复制或链接文件到目标目录\n",
650
- " if cache_path:\n",
651
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
652
- " ticks = time.time()\n",
653
- " print(f'下载完成 {filename} --> {dist_path} 大小{round(size/1024/1024,2)}M 耗时:{round(ticks - startTicks,2)}秒')\n",
654
- " \n",
655
- "def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
656
- " if not Path(dist_path).exists():\n",
657
- " os.makedirs(dist_path,exist_ok=True)\n",
658
- " if show_shell_info:\n",
659
- " print(f'git 下载 {url} --> {dist_path}')\n",
660
- " if cache_path and not Path(cache_path).exists():\n",
661
- " os.makedirs(cache_path,exist_ok=True)\n",
662
- " run(f'git clone {url}',cwd = cache_path)\n",
663
- " if cache_path:\n",
664
- " run(f'cp -n -r -f {cache_path}/* {dist_path}')\n",
665
- " else:\n",
666
- " run(f'git clone {url}',cwd = dist_path)\n",
667
- " if show_shell_info:\n",
668
- " print(f'git 下载完成 {url} --> {dist_path}')\n",
669
- " \n",
670
- " \n",
671
- "def download_huggingface(url:str, filename:str, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
672
- " fileReg = r'^https:\\/\\/huggingface.co(\\/([^\\/]+\\/)?[^\\/]+\\/[^\\/]+\\/(resolve|blob)\\/[^\\/]+\\/|[^\\.]+\\.[^\\.]+$|download=true)'\n",
673
- " def isFile(url:str):\n",
674
- " if re.match(fileReg,url):\n",
675
- " return True\n",
676
- " return False\n",
677
- " if isFile(url):\n",
678
- " download_file(url,filename,dist_path,cache_path,_link_instead_of_copy,headers=huggingface_headers)\n",
679
- " else:\n",
680
- " download_git(url,dist_path,cache_path,_link_instead_of_copy)\n",
681
- " \n",
682
- "# 加入文件到下载列表\n",
683
- "def pause_url(url:str,dist_path:str):\n",
684
- " file_name = ''\n",
685
- " if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n",
686
- " file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n",
687
- " url = url[len(file_name)+1:]\n",
688
- " if not re.match(r'^(https?|ftps?)://',url):\n",
689
- " return\n",
690
- " file_name = re.sub(r'\\s+','_',file_name or '')\n",
691
- " path_hash = str(hash(url)).replace('-','')\n",
692
- " \n",
693
- " return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}\n",
694
- "\n",
695
- "def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5, \n",
696
- " cache_path:str=os.path.join(os.environ['HOME'],'.cache','download_util'),\n",
697
- " _link_instead_of_copy:bool=True,is_await:bool=False):\n",
698
- " if sync:\n",
699
- " for conf in download_list:\n",
700
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
701
- " if conf['url'].startswith('https://github.com'):\n",
702
- " try:\n",
703
- " download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
704
- " except:\n",
705
- " pass\n",
706
- " continue\n",
707
- " if conf['url'].startswith('https://huggingface.co'):\n",
708
- " try:\n",
709
- " download_huggingface(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
710
- " except:\n",
711
- " pass\n",
712
- " continue\n",
713
- " if conf['url'].startswith('https://civitai.com'):\n",
714
- " if not re.search(r'token=.+', conf['url']):\n",
715
- " if conf['url'].find('?') == -1:\n",
716
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
717
- " else:\n",
718
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
719
- " try:\n",
720
- " download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
721
- " except:\n",
722
- " pass\n",
723
- " else:\n",
724
- " executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)\n",
725
- " futures = []\n",
726
- " for conf in download_list:\n",
727
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
728
- " if conf['url'].startswith('https://github.com'):\n",
729
- " futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],\n",
730
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
731
- " continue\n",
732
- " if conf['url'].startswith('https://huggingface.co'):\n",
733
- " futures.append(executor.submit(download_huggingface,conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
734
- " continue\n",
735
- " if conf['url'].startswith('https://civitai.com'):\n",
736
- " if not re.search(r'token=.+', conf['url']):\n",
737
- " if conf['url'].find('?') == -1:\n",
738
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
739
- " else:\n",
740
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
741
- " futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],\n",
742
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
743
- " if is_await:\n",
744
- " concurrent.futures.wait(futures)\n",
745
- " \n",
746
- " \n",
747
- "def parse_config(config:str):\n",
748
- " space_string = ' \\n\\r\\t\\'\\\",'\n",
749
- " other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\\n') if item.strip(space_string)]\n",
750
- " other_flie_list = [item.strip() for item in other_flie_list if item.strip()]\n",
751
- " other_flie_list_store = {}\n",
752
- " other_flie_list_store_name='default'\n",
753
- " other_flie_list_store_list_cache=[]\n",
754
- " \n",
755
- " for item in other_flie_list:\n",
756
- " if item.startswith('[') and item.endswith(']'):\n",
757
- " if not other_flie_list_store_name == 'default':\n",
758
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
759
- " other_flie_list_store_list_cache = []\n",
760
- " other_flie_list_store_name = item[1:-1]\n",
761
- " else:\n",
762
- " other_flie_list_store_list_cache.append(item)\n",
763
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
764
- " \n",
765
- " return other_flie_list_store\n",
766
- "\n",
767
- "\n",
768
- "def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',\n",
769
- " sync:bool=False,thread_num:int=None, is_await:bool=False):\n",
770
- " store:dict[str,List[str]] = parse_config(config)\n",
771
- " download_list = []\n",
772
- " for dist_dir in store.keys():\n",
773
- " dist_path = os.path.join(base_path,dist_dir)\n",
774
- " os.makedirs(dist_path,exist_ok=True)\n",
775
- " for path in store[dist_dir]:\n",
776
- " if 'https://' in path or 'http://' in path:\n",
777
- " if skip_url:\n",
778
- " continue\n",
779
- " if sync:\n",
780
- " try:\n",
781
- " download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)\n",
782
- " except:\n",
783
- " pass\n",
784
- " continue\n",
785
- " download_list.append(pause_url(path,dist_path))\n",
786
- " else:\n",
787
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {path} {dist_path}')\n",
788
- " if show_shell_info:\n",
789
- " print(f'{\"链接\" if _link_instead_of_copy else \"复制\"} {path} --> {dist_path}')\n",
790
- " run(f'rm -f {dist_path}/\\*.* ')\n",
791
- " if not skip_url:\n",
792
- " if show_shell_info:\n",
793
- " pprint.pprint(download_list)\n",
794
- " try:\n",
795
- " download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 3,is_await=is_await)\n",
796
- " except:\n",
797
- " pass"
798
- ]
799
- },
800
- {
801
- "cell_type": "markdown",
802
- "metadata": {
803
- "id": "p0uS-BLULCtD"
804
- },
805
- "source": [
806
- "## kaggle public API\n",
807
- "\n",
808
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
809
- "\n",
810
- "---"
811
- ]
812
- },
813
- {
814
- "cell_type": "code",
815
- "execution_count": null,
816
- "metadata": {
817
- "_kg_hide-input": true,
818
- "id": "m8FJi4j0LCtD",
819
- "trusted": true
820
- },
821
- "outputs": [],
822
- "source": [
823
- "# 安装kaggle的api token文件\n",
824
- "def initKaggleConfig():\n",
825
- " if Path('~/.kaggle/kaggle.json').exists():\n",
826
- " return True\n",
827
- " if Path(kaggleApiTokenFile).exists():\n",
828
- " run(f'''mkdir -p ~/.kaggle/''')\n",
829
- " run('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n",
830
- " run(f'''chmod 600 ~/.kaggle/kaggle.json''')\n",
831
- " return True\n",
832
- " print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n",
833
- " return False\n",
834
- "\n",
835
- "def getUserName():\n",
836
- " if not initKaggleConfig(): return\n",
837
- " import kaggle\n",
838
- " return kaggle.KaggleApi().read_config_file()['username']\n",
839
- "\n",
840
- "def createOrUpdateDataSet(path:str,datasetName:str):\n",
841
- " if not initKaggleConfig(): return\n",
842
- " print('创建或更新数据集 '+datasetName)\n",
843
- " import kaggle\n",
844
- " run(f'mkdir -p {_install_path}/kaggle_cache')\n",
845
- " run(f'rm -rf {_install_path}/kaggle_cache/*')\n",
846
- " datasetDirPath = _install_path+'/kaggle_cache/'+datasetName\n",
847
- " run('mkdir -p '+datasetDirPath)\n",
848
- " run('cp -f '+path+' '+datasetDirPath+'/')\n",
849
- " username = getUserName()\n",
850
- " print(\"kaggle username:\"+username)\n",
851
- " datasetPath = username+'/'+datasetName\n",
852
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
853
- " print(datasetList)\n",
854
- " if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n",
855
- " run('kaggle datasets init -p' + datasetDirPath)\n",
856
- " metadataFile = datasetDirPath+'/dataset-metadata.json'\n",
857
- " run('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n",
858
- " run('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n",
859
- " run('cat '+metadataFile)\n",
860
- " run('kaggle datasets create -p '+datasetDirPath)\n",
861
- " print('create database done')\n",
862
- " else:\n",
863
- " kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n",
864
- " kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n",
865
- " print('upload database done')\n",
866
- "\n",
867
- "def downloadDatasetFiles(datasetName:str,outputPath:str):\n",
868
- " if not initKaggleConfig(): return\n",
869
- " print('下载数据集文件 '+datasetName)\n",
870
- " import kaggle\n",
871
- " username = getUserName()\n",
872
- " datasetPath = username+'/'+datasetName\n",
873
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
874
- " if datasetPath not in [str(d) for d in datasetList]:\n",
875
- " return False\n",
876
- " run('mkdir -p '+outputPath)\n",
877
- " kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n",
878
- " return True\n",
879
- "\n"
880
- ]
881
- },
882
- {
883
- "cell_type": "markdown",
884
- "metadata": {},
885
- "source": [
886
- "## 同步文件夹到 huggingface\n",
887
- "\n",
888
- "---"
889
- ]
890
- },
891
- {
892
- "cell_type": "code",
893
- "execution_count": null,
894
- "metadata": {
895
- "trusted": true
896
- },
897
- "outputs": [],
898
- "source": [
899
- "# 文件夹与 huggingface 同步\n",
900
- "if _huggingface_token and _huggingface_repo:\n",
901
- " if not is_installed('watchdog'):\n",
902
- " requirements.append('watchdog')\n",
903
- " if not is_installed('huggingface_hub'):\n",
904
- " requirements.append('huggingface_hub')\n",
905
- " else:\n",
906
- " try:\n",
907
- " from huggingface_hub import HfApi,login,snapshot_download\n",
908
- " except:\n",
909
- " requirements.append('huggingface_hub')\n",
910
- "\n",
911
- "huggingface_is_init = False\n",
912
- "\n",
913
- "def init_huggingface():\n",
914
- " if not _huggingface_token:\n",
915
- " return False\n",
916
- "\n",
917
- " global huggingface_headers\n",
918
- " global huggingface_is_init\n",
919
- " \n",
920
- " from huggingface_hub import login\n",
921
- " token = replace_path(_huggingface_token)\n",
922
- " if not _huggingface_token.startswith('hf_') and Path(token).exists():\n",
923
- " with open(token,encoding = \"utf-8\") as nkfile:\n",
924
- " token = nkfile.readline()\n",
925
- " if not token.startswith('hf_'):\n",
926
- " print('huggingface token 不正确,请将 token 或 仅存放token 的txt文件路径填入 _huggingface_token 配置')\n",
927
- " return False\n",
928
- " login(token,add_to_git_credential=True)\n",
929
- " huggingface_headers = {'Authorization': 'Bearer '+token}\n",
930
- " print('huggingface token 已经加载,可以下载私有仓库或文件')\n",
931
- " \n",
932
- " if not _huggingface_repo:\n",
933
- " print('huggingface 同步收藏图片功能不会启动,可增加配置项 huggingface_token = \"token\" 和 huggingface_repo = “仓库id” 后启用 huggingface 同步收藏图片功能')\n",
934
- " return False\n",
935
- " huggingface_is_init = True\n",
936
- " return True\n",
937
- "\n",
938
- "\n",
939
- "def download__huggingface_repo(repo_id:str,dist_directory:str=None,repo_type='dataset',callback=None):\n",
940
- " if not huggingface_is_init:\n",
941
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
942
- " \n",
943
- " if not dist_directory:\n",
944
- " dist_directory = f'{_install_path}/{_ui_dir_name}/log'\n",
945
- " \n",
946
- " print('下载收藏的图片')\n",
947
- " if not Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
948
- " mkdirs(f'{_install_path}/cache/huggingface')\n",
949
- " repo_path = ''\n",
950
- " if repo_type == 'dataset':\n",
951
- " repo_path = 'datasets'\n",
952
- " if repo_type == 'space':\n",
953
- " repo_path = 'spaces'\n",
954
- " if repo_path:\n",
955
- " run(f'git clone https://huggingface.co/{repo_path}/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
956
- " else:\n",
957
- " run(f'git clone https://huggingface.co/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
958
- " if Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
959
- " run(f'cp -r -f -n -s {_install_path}/cache/huggingface/huggingface_repo/* {dist_directory}')\n",
960
- " if callback:\n",
961
- " callback()\n",
962
- "\n",
963
- "def start_sync_log_to_huggingface(repo_id:str,directory_to_watch:str=None,repo_type='dataset'):\n",
964
- " if not huggingface_is_init:\n",
965
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
966
- " \n",
967
- " from watchdog.observers import Observer\n",
968
- " from watchdog.events import FileSystemEventHandler\n",
969
- " from huggingface_hub import HfApi,login,snapshot_download\n",
970
- " \n",
971
- " # 配置监视的目录和 Hugging Face 仓库信息\n",
972
- " class FileChangeHandler(FileSystemEventHandler):\n",
973
- " def __init__(self, api, repo_id, repo_type,directory_to_watch):\n",
974
- " self.api = api\n",
975
- " self.repo_id = repo_id\n",
976
- " self.repo_type = repo_type\n",
977
- " self.directory_to_watch = directory_to_watch\n",
978
- " def on_created(self, event):\n",
979
- " if not event.is_directory:\n",
980
- " # 上传新文件到 Hugging Face 仓库\n",
981
- " file_path = event.src_path\n",
982
- " file_name:str = os.path.basename(file_path)\n",
983
- " print(file_name)\n",
984
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
985
- " print(file_name,'>>','huggingface')\n",
986
- " try:\n",
987
- " self.api.upload_file(\n",
988
- " path_or_fileobj=file_path,\n",
989
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
990
- " repo_id=self.repo_id,\n",
991
- " repo_type=self.repo_type,\n",
992
- " )\n",
993
- " except IOError as error:\n",
994
- " print(error)\n",
995
- "\n",
996
- " def on_deleted(self, event):\n",
997
- " if not event.is_directory:\n",
998
- " # 从 Hugging Face 仓库删除文件\n",
999
- " file_path = event.src_path\n",
1000
- " file_name = os.path.basename(file_path)\n",
1001
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1002
- " try:\n",
1003
- " self.api.delete_file(\n",
1004
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1005
- " repo_id=self.repo_id,\n",
1006
- " repo_type=self.repo_type,\n",
1007
- " )\n",
1008
- " except IOError as error:\n",
1009
- " print(error)\n",
1010
- "\n",
1011
- " def on_modified(self, event):\n",
1012
- " if not event.is_directory:\n",
1013
- " # 更新 Hugging Face 仓库中的文件\n",
1014
- " file_path = event.src_path\n",
1015
- " file_name = os.path.basename(file_path)\n",
1016
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1017
- " try:\n",
1018
- " self.api.upload_file(\n",
1019
- " path_or_fileobj=file_path,\n",
1020
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1021
- " repo_id=self.repo_id,\n",
1022
- " repo_type=self.repo_type,\n",
1023
- " )\n",
1024
- " except IOError as error:\n",
1025
- " print(error)\n",
1026
- "\n",
1027
- " def on_moved(self, event):\n",
1028
- " if not event.is_directory:\n",
1029
- " file_path = event.dest_path\n",
1030
- " file_name = os.path.basename(file_path)\n",
1031
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1032
- " if event.dest_path.startswith(self.directory_to_watch):\n",
1033
- " try:\n",
1034
- " self.api.upload_file(\n",
1035
- " path_or_fileobj=file_path,\n",
1036
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1037
- " repo_id=self.repo_id,\n",
1038
- " repo_type=self.repo_type,\n",
1039
- " )\n",
1040
- " except IOError as error:\n",
1041
- " print(error)\n",
1042
- "\n",
1043
- " api = HfApi()\n",
1044
- " \n",
1045
- " if not directory_to_watch:\n",
1046
- " directory_to_watch = f'{_install_path}/{_ui_dir_name}/log'\n",
1047
- " # 创建观察者对象并注册文件变化处理程序\n",
1048
- " event_handler = FileChangeHandler(api,repo_id,repo_type,directory_to_watch)\n",
1049
- " observer = Observer()\n",
1050
- " observer.schedule(event_handler, directory_to_watch, recursive=True)\n",
1051
- "\n",
1052
- " # 启动观察者\n",
1053
- " observer.name = \"solo_directory_to_watch\"\n",
1054
- " print(f'启动收藏图片文件夹监听,并自动同步到 huggingface {repo_type} : {repo_id}')\n",
1055
- " observer.start()"
1056
- ]
1057
- },
1058
- {
1059
- "cell_type": "markdown",
1060
- "metadata": {
1061
- "id": "sswa04veLCtE"
1062
- },
1063
- "source": [
1064
- "## 工具函数\n",
1065
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
1066
- "\n",
1067
- "---"
1068
- ]
1069
- },
1070
- {
1071
- "cell_type": "code",
1072
- "execution_count": null,
1073
- "metadata": {
1074
- "_kg_hide-input": true,
1075
- "trusted": true
1076
- },
1077
- "outputs": [],
1078
- "source": [
1079
- "\n",
1080
- "def zipPath(path:str,zipName:str,format='tar'):\n",
1081
- " if path.startswith('$install_path'):\n",
1082
- " path = path.replace('$install_path',_install_path)\n",
1083
- " if path.startswith('$output_path'):\n",
1084
- " path = path.replace('$install_path',_output_path)\n",
1085
- " if not path.startswith('/'):\n",
1086
- " path = f'{_install_path}/{_ui_dir_name}/{path}'\n",
1087
- " if Path(path).exists():\n",
1088
- " if 'tar' == format:\n",
1089
- " run(f'tar -cf {_output_path}/'+ zipName +'.tar -C '+ path +' . ')\n",
1090
- " elif 'gz' == format:\n",
1091
- " run(f'tar -czf {_output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')\n",
1092
- " return\n",
1093
- " print('指定的目录不存在:'+path)\n",
1094
- " \n",
1095
- "def get_folder_list(directory:str): \n",
1096
- " folder_list = [] \n",
1097
- " for item in os.listdir(directory): \n",
1098
- " if os.path.isdir(os.path.join(directory, item)): \n",
1099
- " folder_list.append(item) \n",
1100
- " return folder_list\n",
1101
- "\n",
1102
- "def read_text_file(file_path:str):\n",
1103
- " if not Path(file_path).exists(): return ''\n",
1104
- " with open(file_path,\"r\") as f:\n",
1105
- " text = file.read()\n",
1106
- " if text: return text.strip()\n",
1107
- " return ''"
1108
- ]
1109
- },
1110
- {
1111
- "cell_type": "markdown",
1112
- "metadata": {},
1113
- "source": [
1114
- "## 内网穿透\n",
1115
- "\n",
1116
- "---"
1117
- ]
1118
- },
1119
- {
1120
- "cell_type": "code",
1121
- "execution_count": null,
1122
- "metadata": {
1123
- "_kg_hide-input": true,
1124
- "_kg_hide-output": true,
1125
- "id": "coqQvTSLLCtE",
1126
- "trusted": true
1127
- },
1128
- "outputs": [],
1129
- "source": [
1130
- "def printUrl(url,name=''):\n",
1131
- " print(f'{name} 访问地址:{url}')\n",
1132
- " for key in sorted(_proxy_path.keys(), key=len)[::-1]:\n",
1133
- " print(f'{name} 本地服务:{_proxy_path[key]} 访问地址:{url}{key}')\n",
1134
- "# ngrok\n",
1135
- "def startNgrok(ngrokToken:str,ngrokLocalPort:int):\n",
1136
- " if not is_installed('pyngrok'):\n",
1137
- " run('pip install pyngrok')\n",
1138
- " from pyngrok import conf, ngrok\n",
1139
- " try:\n",
1140
- " conf.get_default().auth_token = ngrokToken\n",
1141
- " conf.get_default().monitor_thread = False\n",
1142
- " ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n",
1143
- " url = ''\n",
1144
- " if len(ssh_tunnels) == 0:\n",
1145
- " ssh_tunnel = ngrok.connect(ngrokLocalPort)\n",
1146
- " url = ssh_tunnel.public_url\n",
1147
- " print('ngrok 访问地址:'+ssh_tunnel.public_url)\n",
1148
- " else:\n",
1149
- " print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n",
1150
- " url = ssh_tunnels[0].public_url\n",
1151
- " printUrl(url,'ngrok')\n",
1152
- " def auto_request_ngrok():\n",
1153
- " if url:\n",
1154
- " while(_runing):\n",
1155
- " time.sleep(60*1)\n",
1156
- " try:\n",
1157
- " res = requests.get(url+'/',headers={\"ngrok-skip-browser-warning\" : \"1\"},timeout=10)\n",
1158
- " except:\n",
1159
- " ''\n",
1160
- " # print('自动调用ngrok链接以保存链接不会断开',res.status_code)\n",
1161
- "\n",
1162
- " # threading.Thread(target = auto_request_ngrok,daemon=True,name='solo_auto_request_ngrok').start()\n",
1163
- " except:\n",
1164
- " print('启动ngrok出错')\n",
1165
- " \n",
1166
- "def startFrpc(name,configFile):\n",
1167
- " if not Path(f'{_install_path}/frpc/frpc').exists():\n",
1168
- " installFrpExe()\n",
1169
- " if freefrp_url:\n",
1170
- " printUrl(freefrp_url,'freefrp')\n",
1171
- " echoToFile(f'''\n",
1172
- "cd {_install_path}/frpc/\n",
1173
- "{_install_path}/frpc/frpc {configFile}\n",
1174
- "''',f'{_install_path}/frpc/start.sh')\n",
1175
- " get_ipython().system(f'''bash {_install_path}/frpc/start.sh''')\n",
1176
- " \n",
1177
- "def installFrpExe():\n",
1178
- " if _useFrpc:\n",
1179
- " print('安装frpc')\n",
1180
- " run(f'mkdir -p {_install_path}/frpc')\n",
1181
- " if Path(frpcExePath).exists():\n",
1182
- " run(f'cp -f -n {frpcExePath} {_install_path}/frpc/frpc')\n",
1183
- " else:\n",
1184
- " run(f'wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O {_install_path}/frpc/frpc')\n",
1185
- " \n",
1186
- " for ssl in frpcSSLFFlies:\n",
1187
- " if Path(ssl).exists():\n",
1188
- " run(f'cp -f -n {ssl}/* {_install_path}/frpc/')\n",
1189
- " run(f'chmod +x {_install_path}/frpc/frpc')\n",
1190
- " run(f'{_install_path}/frpc/frpc -v')\n",
1191
- "\n",
1192
- "def startProxy():\n",
1193
- " if _useNgrok:\n",
1194
- " startNgrok(ngrokToken,_server_port)\n",
1195
- " if _useFrpc:\n",
1196
- " startFrpc('frpc_proxy',frpcStartArg)"
1197
- ]
1198
- },
1199
- {
1200
- "cell_type": "markdown",
1201
- "metadata": {},
1202
- "source": [
1203
- "## NGINX 反向代理\n",
1204
- "\n",
1205
- "---"
1206
- ]
1207
- },
1208
- {
1209
- "cell_type": "code",
1210
- "execution_count": null,
1211
- "metadata": {
1212
- "_kg_hide-input": true,
1213
- "_kg_hide-output": true,
1214
- "trusted": true
1215
- },
1216
- "outputs": [],
1217
- "source": [
1218
- "\n",
1219
- "# nginx 反向代理配置文件\n",
1220
- "def localProxy():\n",
1221
- " def getProxyLocation(subPath:str, localServer:str):\n",
1222
- " return '''\n",
1223
- " location '''+ subPath +'''\n",
1224
- " {\n",
1225
- " proxy_pass '''+ localServer +''';\n",
1226
- " \n",
1227
- " client_max_body_size 1000m;\n",
1228
- " proxy_set_header Host $http_host;\n",
1229
- " proxy_set_header X-Real-IP $remote_addr;\n",
1230
- " proxy_set_header X-Real-Port $remote_port;\n",
1231
- " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",
1232
- " proxy_set_header X-Forwarded-Proto $scheme;\n",
1233
- " proxy_set_header X-Forwarded-Host $host;\n",
1234
- " proxy_set_header X-Forwarded-Port $server_port;\n",
1235
- " proxy_set_header REMOTE-HOST $remote_addr;\n",
1236
- " proxy_connect_timeout 3000s;\n",
1237
- " proxy_send_timeout 3000s;\n",
1238
- " proxy_read_timeout 3000s;\n",
1239
- " proxy_http_version 1.1;\n",
1240
- " proxy_set_header Upgrade $http_upgrade;\n",
1241
- " proxy_set_header Connection 'upgrade';\n",
1242
- " add_header Access-Control-Allow-Origin * always;\n",
1243
- " add_header Access-Control-Allow-Headers *;\n",
1244
- " add_header Access-Control-Allow-Methods \"GET, POST, PUT, OPTIONS\";\n",
1245
- " }\n",
1246
- " \n",
1247
- " '''\n",
1248
- " \n",
1249
- " conf = '''\n",
1250
- "server\n",
1251
- "{\n",
1252
- " listen '''+str(_server_port)+''';\n",
1253
- " listen [::]:'''+str(_server_port)+''';\n",
1254
- " server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n",
1255
- " \n",
1256
- " fastcgi_send_timeout 3000s;\n",
1257
- " fastcgi_read_timeout 3000s;\n",
1258
- " fastcgi_connect_timeout 3000s;\n",
1259
- " \n",
1260
- " if ($request_method = OPTIONS) {\n",
1261
- " return 200;\n",
1262
- " }\n",
1263
- " \n",
1264
- " '''+ ''.join([getProxyLocation(key,_proxy_path[key]) for key in sorted(_proxy_path.keys(), key=len)[::-1]]) +'''\n",
1265
- "}\n",
1266
- "'''\n",
1267
- " echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n",
1268
- " if not check_service('localhost',_server_port):\n",
1269
- " run(f'''nginx -c /etc/nginx/nginx.conf''')\n",
1270
- " run(f'''nginx -s reload''')"
1271
- ]
1272
- },
1273
- {
1274
- "cell_type": "markdown",
1275
- "metadata": {},
1276
- "source": [
1277
- "## 线程清理工具\n",
1278
- "\n",
1279
- "---\n",
1280
- "\n",
1281
- "清理线程名以 solo_ 开头的所有线程"
1282
- ]
1283
- },
1284
- {
1285
- "cell_type": "code",
1286
- "execution_count": null,
1287
- "metadata": {
1288
- "_kg_hide-input": true,
1289
- "trusted": true
1290
- },
1291
- "outputs": [],
1292
- "source": [
1293
- "import inspect\n",
1294
- "import ctypes\n",
1295
- "\n",
1296
- "def _async_raise(tid, exctype):\n",
1297
- " \"\"\"raises the exception, performs cleanup if needed\"\"\"\n",
1298
- " tid = ctypes.c_long(tid)\n",
1299
- " if not inspect.isclass(exctype):\n",
1300
- " exctype = type(exctype)\n",
1301
- " res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n",
1302
- " if res == 0:\n",
1303
- " raise ValueError(\"invalid thread id\")\n",
1304
- " elif res != 1:\n",
1305
- " # \"\"\"if it returns a number greater than one, you're in trouble,\n",
1306
- " # and you should call it again with exc=NULL to revert the effect\"\"\"\n",
1307
- " ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n",
1308
- " raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n",
1309
- "\n",
1310
- "def stop_thread(thread):\n",
1311
- " _async_raise(thread.ident, SystemExit)\n",
1312
- "\n",
1313
- "def stop_solo_threads():\n",
1314
- " global _runing\n",
1315
- " _runing = False\n",
1316
- " # 获取当前所有活动的线程\n",
1317
- " threads = threading.enumerate()\n",
1318
- " # 关闭之前创建的子线程\n",
1319
- " for thread in threads:\n",
1320
- " if thread.name.startswith('solo_'):\n",
1321
- " print(f'结束线程:{thread.name}')\n",
1322
- " try:\n",
1323
- " stop_thread(thread)\n",
1324
- " except socket.error:\n",
1325
- " print(f'结束线程:{thread.name} 执行失败')"
1326
- ]
1327
- },
1328
- {
1329
- "cell_type": "markdown",
1330
- "metadata": {
1331
- "id": "Ve3p8oOkLCtE"
1332
- },
1333
- "source": [
1334
- "# webui 安装和配置函数\n",
1335
- "---"
1336
- ]
1337
- },
1338
- {
1339
- "cell_type": "code",
1340
- "execution_count": null,
1341
- "metadata": {
1342
- "_kg_hide-input": true,
1343
- "id": "GTjyBJihLCtE",
1344
- "trusted": true
1345
- },
1346
- "outputs": [],
1347
- "source": [
1348
- "envInstalled=False\n",
1349
- "quickStart = False\n",
1350
- "#安装\n",
1351
- "def install():\n",
1352
- " print('安装')\n",
1353
- " os.chdir(f'''{_install_path}''')\n",
1354
- " run(f'''git lfs install''')\n",
1355
- " run(f'''git config --global credential.helper store''')\n",
1356
- " for requirement in requirements:\n",
1357
- " run(f'pip install {requirement}')\n",
1358
- " if _reLoad:\n",
1359
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}''')\n",
1360
- " if Path(f\"{_ui_dir_name}\").exists():\n",
1361
- " os.chdir(f'''{_install_path}/{_ui_dir_name}/''')\n",
1362
- " run(f'''git checkout .''')\n",
1363
- " run(f'''git pull''')\n",
1364
- " else:\n",
1365
- " run(f'''git clone --recursive {_sd_git_repo} {_ui_dir_name}''')\n",
1366
- " if not Path(f'''{_install_path}/{_ui_dir_name}''').exists():\n",
1367
- " print('sd-webui主程序安装失败,请检查 sd_git_repo 配置的值是否正确')\n",
1368
- " sys.exit(0)\n",
1369
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1370
- " print('安装 完成')\n",
1371
- "\n",
1372
- "# 链接输出目录\n",
1373
- "def link_dir():\n",
1374
- " print('链接输出目录')\n",
1375
- " # 链接图片输出目录\n",
1376
- " run(f'''mkdir -p {_output_path}/outputs''')\n",
1377
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/outputs''')\n",
1378
- " run(f'''ln -s -r {_output_path}/outputs {_install_path}/{_ui_dir_name}/''')\n",
1379
- " # 输出收藏目录\n",
1380
- " run(f'''mkdir -p {_output_path}/log''')\n",
1381
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/log''')\n",
1382
- " run(f'''ln -s -r {_output_path}/log {_install_path}/{_ui_dir_name}/''')\n",
1383
- " # 链接训练输出目录 文件夹链接会导致功能不能用\n",
1384
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/textual_inversion''')\n",
1385
- " run(f'''mkdir -p {_output_path}/textual_inversion/''')\n",
1386
- " run(f'''ln -s -r {_output_path}/textual_inversion {_install_path}/{_ui_dir_name}/''')\n",
1387
- " print('链接输出目录 完成') \n",
1388
- "\n",
1389
- "def install_optimizing():\n",
1390
- " run('add-apt-repository ppa:deadsnakes/ppa -y')\n",
1391
- " run('apt update -y')\n",
1392
- " run('apt install nginx -y')\n",
1393
- " # run('apt install python3.10 -y')\n",
1394
- " \n",
1395
- "#安装依赖\n",
1396
- "def install_dependencies():\n",
1397
- " print('安装需要的python环境')\n",
1398
- " global envInstalled\n",
1399
- " global venvPath\n",
1400
- " if Path(f'{_install_path}/{_ui_dir_name}/venv').exists():\n",
1401
- " print('跳过安装python环境')\n",
1402
- " envInstalled = True\n",
1403
- " return\n",
1404
- " \n",
1405
- " if quickStart:\n",
1406
- " if not Path(venvPath).exists():\n",
1407
- " mkdirs(f'{_install_path}/venv_cache',True)\n",
1408
- " if not Path(f'{_install_path}/venv_cache/venv.tar.bak').exists():\n",
1409
- " print('下载 venv.zip')\n",
1410
- " download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{_install_path}/venv_cache')\n",
1411
- " run(f'''unzip {_install_path}/venv_cache/venv.zip -d {_install_path}/venv_cache''')\n",
1412
- " venvPath = f'{_install_path}/venv_cache/venv.tar.bak'\n",
1413
- " run(f'''rm -rf {_install_path}/venv_cache/venv.zip''')\n",
1414
- " elif venvPath.endswith('.zip'):\n",
1415
- " mkdirs(f'{_install_path}/venv_cache',True)\n",
1416
- " run(f'''unzip {venvPath} -d {_install_path}/venv_cache''')\n",
1417
- " venvPath = f'{_install_path}/venv_cache/venv.tar.bak'\n",
1418
- " print('解压环境')\n",
1419
- " mkdirs(f'{_install_path}/{_ui_dir_name}/venv')\n",
1420
- "# run('python3.10 -m venv venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1421
- " run(f'tar -xf {venvPath} -C ./venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1422
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/pip*')\n",
1423
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/python*')\n",
1424
- " venv.create(f'{_install_path}/{_ui_dir_name}/venv')\n",
1425
- " if not Path(f'{_install_path}/{_ui_dir_name}/venv/bin/pip').exists():\n",
1426
- " run('curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py')\n",
1427
- " run(f'{_install_path}/{_ui_dir_name}/venv/bin/python3 get-pip.py')\n",
1428
- "\n",
1429
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -V''')\n",
1430
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip -V''')\n",
1431
- " \n",
1432
- " # if not quickStart:\n",
1433
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -V''')\n",
1434
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip -V''')\n",
1435
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install torch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 --index-url https://download.pytorch.org/whl/cu121''')\n",
1436
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install xformers==0.0.27''')\n",
1437
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install -r requirements_versions.txt''')\n",
1438
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install spandrel==0.3.0''')\n",
1439
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install opencv-python''')\n",
1440
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pydantic==1.10.15''')\n",
1441
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install transformers -U''')\n",
1442
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install llama-cpp-python''')\n",
1443
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pytorch_lightning==2.3.3 torchsde==0.2.6 spandrel==0.3.4''')\n",
1444
- " \n",
1445
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install open-clip-torch -U''')\n",
1446
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install protobuf==4.25.8''')\n",
1447
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install blendmodes==2022''')\n",
1448
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install Pillow==9.5.0''')\n",
1449
- " # run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr''')\n",
1450
- " \n",
1451
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr wrapt''')\n",
1452
- " \n",
1453
- " envInstalled = True\n",
1454
- " print('安装需要的python环境 完成')\n",
1455
- " \n",
1456
- "# 个性化配置 \n",
1457
- "def use_config():\n",
1458
- " print('使用自定义配置 包括tag翻译 \\n')\n",
1459
- " run(f'''mkdir -p {_install_path}/temp''')\n",
1460
- " run(f'git clone {_sd_config_git_repu} sd-configs',cwd=f'{_install_path}/temp')\n",
1461
- " run(f'cp -r -f -n {_install_path}/temp/sd-configs/dist/* {_install_path}/{_ui_dir_name}')\n",
1462
- " if not Path(_ui_config_file).exists() and _ui_config_file != 'ui-config.json': # ui配置文件\n",
1463
- " run(f'''mkdir -p {_ui_config_file[:_ui_config_file.rfind('/')]}''')\n",
1464
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/ui-config.json {_ui_config_file}')\n",
1465
- " if not Path(_setting_file).exists() and _setting_file != 'config.json': # 设置配置文件\n",
1466
- " run(f'''mkdir -p {_setting_file[:_setting_file.rfind('/')]}''')\n",
1467
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/config.json {_setting_file}')\n",
1468
- "\n",
1469
- "def copy_last_log_to_images():\n",
1470
- " if not Path(f'{_install_path}/{_ui_dir_name}/log/images').exists(): mkdirs(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1471
- " print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')\n",
1472
- " img_list = os.listdir(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1473
- " last_img_path = ''\n",
1474
- " last_img_num = 0\n",
1475
- " for img in img_list:\n",
1476
- " if re.findall(r'^\\d+-',str(img)):\n",
1477
- " num = int(re.findall(r'^\\d+-',str(img))[0][:-1])\n",
1478
- " if num > last_img_num:\n",
1479
- " last_img_path = img\n",
1480
- " last_img_num = num\n",
1481
- " \n",
1482
- " if not last_img_path: return\n",
1483
- " \n",
1484
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images')\n",
1485
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/txt2img-images''')\n",
1486
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images/''')\n",
1487
- " \n",
1488
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images')\n",
1489
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/img2img-images''')\n",
1490
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images/''')\n",
1491
- " \n",
1492
- "def start_webui(i):\n",
1493
- " # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n",
1494
- " print(i,'--port',str(_server_port+1+i))\n",
1495
- " if i>0:\n",
1496
- " print(f'使用第{i+1}张显卡启动第{i+1}个服务,通过frpc或nrgok地址后加{_sub_path[i]}进行访问')\n",
1497
- "\n",
1498
- " current_thread = threading.current_thread()\n",
1499
- " current_thread.name = f\"solo_webui__{i}\"\n",
1500
- " \n",
1501
- " restart_times = 0\n",
1502
- " last_restart_time = time.time()\n",
1503
- " while _runing:\n",
1504
- " os.chdir(f'{_install_path}/{_ui_dir_name}')\n",
1505
- " root_path = _sub_path[i]\n",
1506
- " if root_path.endswith('/'): root_path = root_path[:-1]\n",
1507
- " if torch.cuda.device_count() == 1 or not _multi_case:\n",
1508
- " get_ipython().system(f'''venv/bin/python3 launch.py --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1509
- " else: \n",
1510
- " get_ipython().system(f'''venv/bin/python3 launch.py --device-id={i} --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1511
- " print('10秒后重启服务')\n",
1512
- " if time.time() - last_restart_time < 60:\n",
1513
- " restart_times = restart_times + 1\n",
1514
- " else:\n",
1515
- " restart_times = 0\n",
1516
- " last_restart_time = time.time()\n",
1517
- " if restart_times >3 :\n",
1518
- " # 如果180秒内重启了3此,将不再自动重启\n",
1519
- " break\n",
1520
- " time.sleep(10)\n",
1521
- " \n",
1522
- "# 启动\n",
1523
- "def start():\n",
1524
- " print('启动webui')\n",
1525
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1526
- " args = ''\n",
1527
- " if _ui_config_file is not None and _ui_config_file != '' and Path(_ui_config_file).exists(): # ui配置文件\n",
1528
- " args += ' --ui-config-file=' + _ui_config_file\n",
1529
- " if _setting_file is not None and _setting_file != '' and Path(_setting_file).exists(): # 设置配置文件\n",
1530
- " args += ' --ui-settings-file=' + _setting_file\n",
1531
- " args += ' ' + otherArgs\n",
1532
- " os.environ['COMMANDLINE_ARGS']=args\n",
1533
- " run(f'''echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS''')\n",
1534
- " os.environ['REQS_FILE']='requirements_versions.txt'\n",
1535
- "\n",
1536
- " with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:\n",
1537
- " for i in range(torch.cuda.device_count() if _multi_case else 1):\n",
1538
- " executor.submit(start_webui,i)\n",
1539
- " while _runing and not check_service('localhost',str(_server_port+1+i)): # 当当前服务启动完成才允许退出此次循环\n",
1540
- " time.sleep(5)\n",
1541
- " if not _runing: break\n",
1542
- " time.sleep(10)"
1543
- ]
1544
- },
1545
- {
1546
- "cell_type": "markdown",
1547
- "metadata": {
1548
- "id": "qLvsk8ByLCtF"
1549
- },
1550
- "source": [
1551
- "# 入口函数\n",
1552
- "---"
1553
- ]
1554
- },
1555
- {
1556
- "cell_type": "code",
1557
- "execution_count": null,
1558
- "metadata": {
1559
- "_kg_hide-input": true,
1560
- "id": "IOKjaMlcLCtF",
1561
- "trusted": true
1562
- },
1563
- "outputs": [],
1564
- "source": [
1565
- "\n",
1566
- "# 启动非webui相关的的内容,加快启动速度\n",
1567
- "def main():\n",
1568
- " global envInstalled\n",
1569
- " global huggingface_is_init\n",
1570
- " global _runing\n",
1571
- " _init_conf()\n",
1572
- " stop_solo_threads()\n",
1573
- " print('启动...')\n",
1574
- " startTicks = time.time()\n",
1575
- " time.sleep(5)\n",
1576
- " _runing = True\n",
1577
- " isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n",
1578
- " _proxy_path[_sub_path[0]] = f'http://127.0.0.1:{_server_port+1}/'\n",
1579
- " _proxy_path[_sub_path[1]] = f'http://127.0.0.1:{_server_port+2}/'\n",
1580
- " proxy_thread = threading.Thread(target = startProxy, daemon=True, name='solo_startProxy')\n",
1581
- " proxy_thread.start()\n",
1582
- " if isInstall is False or _reLoad: \n",
1583
- " print('安装运行环境')\n",
1584
- " os.environ['MPLBACKEND'] = 'Agg'\n",
1585
- " install()\n",
1586
- " link_dir()\n",
1587
- " init_huggingface()\n",
1588
- " install_optimizing()\n",
1589
- " if not _skip_webui:\n",
1590
- " threading.Thread(target = install_dependencies,daemon=True,name='solo_install_dependencies').start()\n",
1591
- " else: envInstalled = True\n",
1592
- " link_or_download_flie(replace_path(_async_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1593
- " base_path=f'{_install_path}/{_ui_dir_name}')\n",
1594
- " if huggingface_is_init:\n",
1595
- " threading.Thread(target = download__huggingface_repo,daemon=True,\n",
1596
- " args=([_huggingface_repo]),\n",
1597
- " kwargs={\"callback\":copy_last_log_to_images},\n",
1598
- " name='solo_download__huggingface_repo').start()\n",
1599
- " \n",
1600
- " link_or_download_flie(replace_path(_before_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1601
- " base_path=f'{_install_path}/{_ui_dir_name}',is_await=True,sync=True)\n",
1602
- " t = 0\n",
1603
- " while _runing and not envInstalled:\n",
1604
- " if t%10==0:\n",
1605
- " print('等待python环境安装...')\n",
1606
- " t = t+1\n",
1607
- " time.sleep(1)\n",
1608
- " use_config()\n",
1609
- " os.environ['IsInstall'] = 'True'\n",
1610
- " else:\n",
1611
- " envInstalled = True\n",
1612
- " localProxy()\n",
1613
- " link_or_download_flie(replace_path(_before_start_sync_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1614
- " base_path=f'{_install_path}/{_ui_dir_name}',sync=True)\n",
1615
- " if init_huggingface():\n",
1616
- " start_sync_log_to_huggingface(_huggingface_repo)\n",
1617
- " ticks = time.time()\n",
1618
- " _on_before_start()\n",
1619
- " print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n",
1620
- " if _skip_webui:\n",
1621
- " print('跳过webui启动')\n",
1622
- " proxy_thread.join()\n",
1623
- " else:\n",
1624
- " start()\n"
1625
- ]
1626
- },
1627
- {
1628
- "cell_type": "markdown",
1629
- "metadata": {
1630
- "id": "0oaCRs2gLCtF"
1631
- },
1632
- "source": [
1633
- "# 执行区域\n",
1634
- "---"
1635
- ]
1636
- },
1637
- {
1638
- "cell_type": "code",
1639
- "execution_count": null,
1640
- "metadata": {
1641
- "_kg_hide-output": true,
1642
- "id": "O3DR0DWHLCtF",
1643
- "scrolled": true,
1644
- "trusted": true
1645
- },
1646
- "outputs": [],
1647
- "source": [
1648
- "# 启动\n",
1649
- "# _reLoad = True\n",
1650
- "# hidden_console_info = False\n",
1651
- "# run_by_none_device = True\n",
1652
- "# show_shell_info = True\n",
1653
- "\n",
1654
- "print(f'当前sd的安装路径是:{_install_path}/{_ui_dir_name}')\n",
1655
- "print(f'当前图片保存路径是:{_output_path}')\n",
1656
- "print(f'当前数据集路径是:{_input_path}')\n",
1657
- "\n",
1658
- "print(update_desc)\n",
1659
- "\n",
1660
- "if _skip_start:\n",
1661
- " print('已跳过自动启动,可手动执行 main() 进行启动。')\n",
1662
- " print('''推荐的启动代码:\n",
1663
- "try:\n",
1664
- " check_gpu() # 检查是否存在gpu\n",
1665
- " main()\n",
1666
- "except KeyboardInterrupt:\n",
1667
- " stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)\n",
1668
- " ''')\n",
1669
- "else:\n",
1670
- " try:\n",
1671
- " check_gpu()\n",
1672
- " main()\n",
1673
- " except KeyboardInterrupt:\n",
1674
- " stop_solo_threads()"
1675
- ]
1676
- },
1677
- {
1678
- "cell_type": "code",
1679
- "execution_count": null,
1680
- "metadata": {
1681
- "trusted": true
1682
- },
1683
- "outputs": [],
1684
- "source": []
1685
- }
1686
- ],
1687
- "metadata": {
1688
- "kaggle": {
1689
- "accelerator": "nvidiaTeslaT4",
1690
- "dataSources": [
1691
- {
1692
- "datasetId": 2716934,
1693
- "sourceId": 6167400,
1694
- "sourceType": "datasetVersion"
1695
- },
1696
- {
1697
- "datasetId": 3654544,
1698
- "sourceId": 6346544,
1699
- "sourceType": "datasetVersion"
1700
- },
1701
- {
1702
- "datasetId": 2962375,
1703
- "sourceId": 6720235,
1704
- "sourceType": "datasetVersion"
1705
- },
1706
- {
1707
- "datasetId": 3074484,
1708
- "sourceId": 6817788,
1709
- "sourceType": "datasetVersion"
1710
- }
1711
- ],
1712
- "isGpuEnabled": true,
1713
- "isInternetEnabled": true,
1714
- "language": "python",
1715
- "sourceType": "notebook"
1716
- },
1717
- "kernelspec": {
1718
- "display_name": "Python 3",
1719
- "language": "python",
1720
- "name": "python3"
1721
- },
1722
- "language_info": {
1723
- "codemirror_mode": {
1724
- "name": "ipython",
1725
- "version": 3
1726
- },
1727
- "file_extension": ".py",
1728
- "mimetype": "text/x-python",
1729
- "name": "python",
1730
- "nbconvert_exporter": "python",
1731
- "pygments_lexer": "ipython3",
1732
- "version": "3.10.13"
1733
- }
1734
- },
1735
- "nbformat": 4,
1736
- "nbformat_minor": 4
1737
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
sdwui-start-util.ipynb DELETED
@@ -1,1735 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": null,
6
- "metadata": {
7
- "trusted": true
8
- },
9
- "outputs": [],
10
- "source": []
11
- },
12
- {
13
- "cell_type": "code",
14
- "execution_count": null,
15
- "metadata": {
16
- "trusted": true
17
- },
18
- "outputs": [],
19
- "source": [
20
- "update_desc = '''\n",
21
- "欢迎使用 stable-diffusion-webui 便捷启动工具\n",
22
- "\n",
23
- "此脚本理论上可以在任何jupyter环境运行,但仅在 google colab 和 kaggle 测试。 已经无法在 google colab 免费实例上运行。\n",
24
- "此脚本的【前置脚本】发布地址 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai-sdxl。\n",
25
- "此脚本需配合 【前置脚本】 的脚本附带的配置项才能正常启动。\n",
26
- "此脚本的内容会自动更新,你无需更新【前置脚本】就能获取到最新的功能。\n",
27
- "增加一个说明:为解决加密图片的解密和浏览的问题,开发了一个独立应用,可以在这里下载 https://github.com/viyiviyi/encrypt_gallery/releases/\n",
28
- "加密插件可解决生成nsfw图片后被平台封号问题\n",
29
- "\n",
30
- "路径说明\n",
31
- "* 为了解决平台差异,所有的安装目录和文件输出目录都被重新指定,如果你需要在配置中访问这些目录,请查看以下说明\n",
32
- "*\n",
33
- "* 可以使用 $install_path 或 {install_path} 来访问安装目录,写在字符串内也会生效\n",
34
- "* $output_path 或 {output_path} 可以访问输出目录\n",
35
- "* 如果你需要安装在自定义目录,也可以设置这些值 如: install_path = '新的路径'\n",
36
- "* 可自定义方法 on_before_start 并在方法内写上启动前需要的逻辑来实现在webui启动前执行自定义逻辑\n",
37
- "* 可以增加配置 multi_case = True 来控制是否使用多卡\n",
38
- "* 如果需要显示更多控制台输出 需配置 hidden_console_info = False\n",
39
- "\n",
40
- "********* 特别提示 *********\n",
41
- "* huggingface 的下载链接需要增加 ?download=true 参数才能正确下载到文件,如果你需要的文件里的下载链接没有这个参数,请自行增加。\n",
42
- "'''"
43
- ]
44
- },
45
- {
46
- "cell_type": "code",
47
- "execution_count": null,
48
- "metadata": {
49
- "trusted": true
50
- },
51
- "outputs": [],
52
- "source": [
53
- "from pathlib import Path\n",
54
- "import os\n",
55
- "import time\n",
56
- "import re\n",
57
- "import subprocess\n",
58
- "import threading\n",
59
- "import sys\n",
60
- "import socket\n",
61
- "import torch\n",
62
- "from typing import List\n",
63
- "import uuid\n",
64
- "import asyncio\n",
65
- "from urllib import request"
66
- ]
67
- },
68
- {
69
- "cell_type": "code",
70
- "execution_count": null,
71
- "metadata": {
72
- "trusted": true
73
- },
74
- "outputs": [],
75
- "source": [
76
- "# 内置参数默认值,当上下文有参数时可覆盖默认值\n",
77
- "_runing = False\n",
78
- "\n",
79
- "_useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n",
80
- "\n",
81
- "_useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n",
82
- "\n",
83
- "_reLoad = locals().get('reLoad') or globals().get('reLoad') or False\n",
84
- " \n",
85
- "_before_downloading = locals().get('before_downloading') or globals().get('before_downloading') or ''\n",
86
- "\n",
87
- "_async_downloading = locals().get('async_downloading') or globals().get('async_downloading') or ''\n",
88
- "\n",
89
- "_before_start_sync_downloading = locals().get('before_start_sync_downloading') or globals().get('before_start_sync_downloading') or ''\n",
90
- "\n",
91
- "_server_port = locals().get('server_port') or globals().get('server_port') or 7860\n",
92
- " \n",
93
- "_sd_git_repo = locals().get('sd_git_repo') or globals().get('sd_git_repo') or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n",
94
- "_sd_git_repo = _sd_git_repo\\\n",
95
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
96
- " .replace('{wui}',\"webui\")\n",
97
- " \n",
98
- "_sd_config_git_repu = locals().get('sd_config_git_repu') or globals().get('sd_config_git_repu') or 'https://github.com/viyiviyi/sd-configs.git'\n",
99
- "_sd_config_git_repu = _sd_config_git_repu\\\n",
100
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
101
- " .replace('{wui}',\"webui\")\n",
102
- " \n",
103
- " \n",
104
- "_huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n",
105
- "_huggingface_token = _huggingface_token\\\n",
106
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
107
- " .replace('{wui}',\"webui\")\n",
108
- " \n",
109
- "_huggingface_repo = locals().get('huggingface_repo') or globals().get('huggingface_repo') or ''\n",
110
- "_huggingface_repo = _huggingface_repo\\\n",
111
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
112
- " .replace('{wui}',\"webui\")\n",
113
- "\n",
114
- "_link_instead_of_copy = locals().get('link_instead_of_copy') or globals().get('link_instead_of_copy') or True\n",
115
- " \n",
116
- "show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n",
117
- "if show_shell_info is None: show_shell_info = False\n",
118
- "else: show_shell_info = not show_shell_info\n",
119
- "\n",
120
- "_multi_case = locals().get('multi_case') or globals().get('multi_case') or False\n",
121
- " \n",
122
- "_skip_start = locals().get('skip_start') or globals().get('skip_start') or True\n",
123
- "\n",
124
- "def before_start():\n",
125
- " pass\n",
126
- "\n",
127
- "def main_start():\n",
128
- " pass\n",
129
- "\n",
130
- "_on_before_start = locals().get('on_before_start') or globals().get('on_before_start') or before_start \n",
131
- "_skip_webui = locals().get('skip_webui') or globals().get('skip_webui') or False\n",
132
- " \n",
133
- "run_by_none_device = False\n",
134
- "\n",
135
- "_proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n",
136
- "\n",
137
- "_sub_path = locals().get('sub_path') or globals().get('sub_path') or ['/','/1/']\n",
138
- "if len(_sub_path) != 2:\n",
139
- " _sub_path = ['/','/1/']\n",
140
- " \n",
141
- "_config_args:dict[str, str] = locals().get('config_args') or globals().get('config_args') or {}"
142
- ]
143
- },
144
- {
145
- "cell_type": "code",
146
- "execution_count": null,
147
- "metadata": {
148
- "trusted": true
149
- },
150
- "outputs": [],
151
- "source": [
152
- "\n",
153
- "def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:\n",
154
- " global show_shell_info\n",
155
- " if desc is not None:\n",
156
- " print(desc)\n",
157
- "\n",
158
- " run_kwargs = {\n",
159
- " \"args\": command,\n",
160
- " \"shell\": True,\n",
161
- " \"cwd\": cwd,\n",
162
- " \"env\": os.environ if custom_env is None else custom_env,\n",
163
- " \"encoding\": 'utf8',\n",
164
- " \"errors\": 'ignore',\n",
165
- " }\n",
166
- "\n",
167
- " if not show_shell_info:\n",
168
- " run_kwargs[\"stdout\"] = run_kwargs[\"stderr\"] = subprocess.PIPE\n",
169
- "\n",
170
- " result = subprocess.run(**run_kwargs)\n",
171
- "\n",
172
- " if result.returncode != 0:\n",
173
- " error_bits = [\n",
174
- " f\"{errdesc or 'Error running command'}.\",\n",
175
- " f\"Command: {command}\",\n",
176
- " f\"Error code: {result.returncode}\",\n",
177
- " ]\n",
178
- " if result.stdout:\n",
179
- " error_bits.append(f\"stdout: {result.stdout}\")\n",
180
- " if result.stderr:\n",
181
- " error_bits.append(f\"stderr: {result.stderr}\")\n",
182
- " if try_error:\n",
183
- " print((RuntimeError(\"\\n\".join(error_bits))))\n",
184
- " else:\n",
185
- " raise RuntimeError(\"\\n\".join(error_bits))\n",
186
- "\n",
187
- " if show_shell_info:\n",
188
- " print((result.stdout or \"\"))\n",
189
- " return (result.stdout or \"\")\n",
190
- "\n",
191
- "def mkdirs(path, exist_ok=True):\n",
192
- " if path and not Path(path).exists():\n",
193
- " os.makedirs(path,exist_ok=exist_ok)\n",
194
- "\n",
195
- "\n",
196
- "# 检查网络\n",
197
- "def check_service(host, port):\n",
198
- " try:\n",
199
- " socket.create_connection((host, port), timeout=5)\n",
200
- " return True\n",
201
- " except socket.error:\n",
202
- " return False\n",
203
- "\n",
204
- "\n",
205
- "# 检查gpu是否存在\n",
206
- "def check_gpu():\n",
207
- " if not run_by_none_device and torch.cuda.device_count() == 0:\n",
208
- " raise Exception('当前环境没有GPU')\n",
209
- "\n",
210
- "\n",
211
- "def echoToFile(content:str,path:str):\n",
212
- " if path.find('/') >= 0:\n",
213
- " _path = '/'.join(path.split('/')[:-1])\n",
214
- " run(f'''mkdir -p {_path}''')\n",
215
- " with open(path,'w') as sh:\n",
216
- " sh.write(content)\n",
217
- " \n",
218
- "def get_freefrp_confog(local_port):\n",
219
- " rd_str = uuid.uuid1()\n",
220
- " return (f'''\n",
221
- "[common]\n",
222
- "server_addr = frp.freefrp.net\n",
223
- "server_port = 7000\n",
224
- "token = freefrp.net\n",
225
- "\n",
226
- "[{rd_str}_http]\n",
227
- "type = http\n",
228
- "local_ip = 127.0.0.1\n",
229
- "local_port = {local_port}\n",
230
- "custom_domains = {rd_str}.frp.eaias.com\n",
231
- "''',f'http://{rd_str}.frp.eaias.com')"
232
- ]
233
- },
234
- {
235
- "cell_type": "code",
236
- "execution_count": null,
237
- "metadata": {
238
- "trusted": true
239
- },
240
- "outputs": [],
241
- "source": [
242
- "\n",
243
- "_install_path = f\"/kaggle\" if os.path.exists('/kaggle/') else f\"{os.environ['HOME']}/sd_webui\" # 安装目录\n",
244
- "_output_path = '/kaggle/working' if os.path.exists('/kaggle/working/') else f\"{os.environ['HOME']}/.sdwui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\n",
245
- "_input_path = '/kaggle/input' # 输入目录\n",
246
- "_ui_dir_name = 'sd_main_dir'\n",
247
- "\n",
248
- "_install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
249
- "_output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
250
- "_input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
251
- "_ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
252
- "\n",
253
- "install_path = _install_path\n",
254
- "output_path = _output_path\n",
255
- "input_path = _input_path\n",
256
- "ui_dir_name = _ui_dir_name\n",
257
- " \n",
258
- "google_drive = '' \n",
259
- "\n",
260
- "\n",
261
- "_useGooglrDrive = locals().get('useGooglrDrive') or globals().get('useGooglrDrive') or True\n",
262
- "\n",
263
- "# 连接谷歌云\n",
264
- "try:\n",
265
- " if _useGooglrDrive:\n",
266
- " from google.colab import drive\n",
267
- " drive.mount(f'~/google_drive')\n",
268
- " google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n",
269
- " _output_path = f'{google_drive}/sdwebui/Output'\n",
270
- " _input_path = f'{google_drive}/sdwebui/Input'\n",
271
- " run(f'''mkdir -p {_input_path}''')\n",
272
- " print('''\n",
273
- "已经链接到谷歌云盘\n",
274
- "已在云盘创建Input和Output目录\n",
275
- " ''')\n",
276
- "except:\n",
277
- " _useGooglrDrive = False\n",
278
- "\n",
279
- "run(f'''mkdir -p {_install_path}''')\n",
280
- "run(f'''mkdir -p {_output_path}''')\n",
281
- "\n",
282
- "\n",
283
- "os.environ['install_path'] = _install_path\n",
284
- "os.environ['output_path'] = _output_path\n",
285
- "os.environ['google_drive'] = google_drive\n",
286
- "os.environ['input_path'] = _input_path\n",
287
- "\n",
288
- "def replace_path(input_str:str):\n",
289
- " if not input_str: return ''\n",
290
- " for key in _config_args:\n",
291
- " input_str = input_str.replace(key,_config_args[key])\n",
292
- " \n",
293
- " if not (locals().get('use_comfyui') or globals().get('use_comfyui') or False):\n",
294
- " input_str = input_str.replace('https://github.com/comfyanonymous/ComfyUI.git','https://github.com/comfyanonymous/ComfyUI.git')\n",
295
- " \n",
296
- " return input_str.replace('$install_path',_install_path)\\\n",
297
- " .replace('{install_path}',_install_path)\\\n",
298
- " .replace('$input_path',_input_path)\\\n",
299
- " .replace('{input_path}',_input_path)\\\n",
300
- " .replace('$output_path',_output_path)\\\n",
301
- " .replace('{output_path}',_output_path)\\\n",
302
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
303
- " .replace('{wui}',\"webui\")\n",
304
- "\n",
305
- "space_string = ' \\n\\r\\t\\'\\\",'\n",
306
- "\n",
307
- "def config_reader(conf:str):\n",
308
- " conf = conf or \"\"\n",
309
- " args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\\n') if item.strip(space_string)]\n",
310
- " return [item.strip() for item in args if item.strip()]\n"
311
- ]
312
- },
313
- {
314
- "cell_type": "code",
315
- "execution_count": null,
316
- "metadata": {
317
- "_kg_hide-input": true,
318
- "id": "i3LhnwYHLCtC",
319
- "trusted": true
320
- },
321
- "outputs": [],
322
- "source": [
323
- "ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
324
- "frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
325
- "# ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
326
- "frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
327
- "if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
328
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
329
- "# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
330
- "frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n",
331
- "# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n",
332
- "otherArgs = '--xformers'\n",
333
- "if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
334
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
335
- "venvPath = os.path.join(_input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n",
336
- "\n",
337
- "# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n",
338
- "# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\n",
339
- "kaggleApiTokenFile = os.path.join(_input_path,'configs/kaggle.json')\n",
340
- "\n",
341
- "requirements = []\n"
342
- ]
343
- },
344
- {
345
- "cell_type": "code",
346
- "execution_count": null,
347
- "metadata": {
348
- "_kg_hide-input": true,
349
- "id": "a_GtG2ayLCtD",
350
- "trusted": true
351
- },
352
- "outputs": [],
353
- "source": [
354
- "# 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
355
- "_setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
356
- "\n",
357
- "_ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
358
- "\n",
359
- "# 设置文件路径\n",
360
- "if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
361
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
362
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
363
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
364
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
365
- " \n",
366
- "frpcStartArg = ''\n",
367
- "freefrp_url = ''\n",
368
- "_frp_temp_config_file = ''\n",
369
- "_frp_config_or_file = replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or frpcConfigFile\n",
370
- "run(f'''mkdir -p {_install_path}/configFiles''')\n",
371
- "if _frp_config_or_file:\n",
372
- " if '[common]' in _frp_config_or_file:\n",
373
- " echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_webui.ini')\n",
374
- " _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_webui.ini'\n",
375
- " elif '.ini' in _frp_config_or_file:\n",
376
- " _frp_temp_config_file = _frp_config_or_file.strip()\n",
377
- " \n",
378
- " if _frp_temp_config_file:\n",
379
- " if Path(_frp_temp_config_file).exists():\n",
380
- " run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_webui.ini''')\n",
381
- " run(f'''sed -i \"s/local_port = .*/local_port = {_server_port}/g\" {_install_path}/configFiles/frpc_webui.ini''')\n",
382
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
383
- " elif _frp_config_or_file.strip().startswith('-f'):\n",
384
- " frpcStartArg = _frp_config_or_file.strip()\n",
385
- " \n",
386
- "if not frpcStartArg:\n",
387
- " conf,url = get_freefrp_confog(_server_port)\n",
388
- " echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n",
389
- " freefrp_url = url\n",
390
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
391
- "\n",
392
- "ngrokToken=''\n",
393
- "_ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
394
- "if _ngrok_config_or_file:\n",
395
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
396
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
397
- " if Path(ngrokTokenFile).exists():\n",
398
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
399
- " ngrokToken = nkfile.readline()\n",
400
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
401
- " ngrokToken=_ngrok_config_or_file.strip()\n",
402
- " \n",
403
- "if not Path(venvPath).exists():\n",
404
- " venvPath = os.path.join(_input_path,'sd-webui-venv/venv.zip')\n",
405
- " \n",
406
- "huggingface_headers:dict = None "
407
- ]
408
- },
409
- {
410
- "cell_type": "code",
411
- "execution_count": null,
412
- "metadata": {},
413
- "outputs": [],
414
- "source": [
415
- "def _init_conf():\n",
416
- " global _useFrpc\n",
417
- " global _useNgrok\n",
418
- " global _reLoad\n",
419
- " global _before_downloading\n",
420
- " global _async_downloading\n",
421
- " global _before_start_sync_downloading\n",
422
- " global _server_port\n",
423
- " global _sd_git_repo\n",
424
- " global _sd_config_git_repu\n",
425
- " global _huggingface_token\n",
426
- " global _huggingface_repo\n",
427
- " global _link_instead_of_copy\n",
428
- " global show_shell_info\n",
429
- " global _multi_case\n",
430
- " global _skip_start\n",
431
- " global _on_before_start\n",
432
- " global _skip_webui\n",
433
- " global _proxy_path\n",
434
- " global _sub_path\n",
435
- " global _config_args\n",
436
- " global _install_path\n",
437
- " global _output_path\n",
438
- " global _input_path\n",
439
- " global _ui_dir_name\n",
440
- " \n",
441
- " global ngrokTokenFile\n",
442
- " global frpcConfigFile\n",
443
- " global frpcSSLFFlies\n",
444
- " global frpcExePath\n",
445
- " global otherArgs\n",
446
- " global _setting_file\n",
447
- " global _ui_config_file\n",
448
- " global _frp_temp_config_file\n",
449
- " global _frp_config_or_file\n",
450
- " global ngrokToken\n",
451
- " global venvPath\n",
452
- " \n",
453
- " _useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n",
454
- " _useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n",
455
- " _reLoad = locals().get('reLoad') or globals().get('reLoad') or False\n",
456
- " _before_downloading = locals().get('before_downloading') or globals().get('before_downloading') or ''\n",
457
- " _async_downloading = locals().get('async_downloading') or globals().get('async_downloading') or ''\n",
458
- " _before_start_sync_downloading = locals().get('before_start_sync_downloading') or globals().get('before_start_sync_downloading') or ''\n",
459
- " _server_port = locals().get('server_port') or globals().get('server_port') or 7860\n",
460
- " _sd_git_repo = locals().get('sd_git_repo') or globals().get('sd_git_repo') or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n",
461
- " _sd_git_repo = _sd_git_repo\\\n",
462
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
463
- " .replace('{wui}',\"webui\") \n",
464
- " _sd_config_git_repu = locals().get('sd_config_git_repu') or globals().get('sd_config_git_repu') or 'https://github.com/viyiviyi/sd-configs.git'\n",
465
- " _sd_config_git_repu = _sd_config_git_repu\\\n",
466
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
467
- " .replace('{wui}',\"webui\")\n",
468
- " _huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n",
469
- " _huggingface_token = _huggingface_token\\\n",
470
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
471
- " .replace('{wui}',\"webui\")\n",
472
- " _huggingface_repo = locals().get('huggingface_repo') or globals().get('huggingface_repo') or ''\n",
473
- " _huggingface_repo = _huggingface_repo\\\n",
474
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
475
- " .replace('{wui}',\"webui\")\n",
476
- " _link_instead_of_copy = locals().get('link_instead_of_copy') or globals().get('link_instead_of_copy') or True\n",
477
- " show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n",
478
- " if show_shell_info is None: show_shell_info = False\n",
479
- " else: show_shell_info = not show_shell_info\n",
480
- " _multi_case = locals().get('multi_case') or globals().get('multi_case') or False\n",
481
- " _skip_start = locals().get('skip_start') or globals().get('skip_start') or True\n",
482
- " _on_before_start = locals().get('on_before_start') or globals().get('on_before_start') or before_start \n",
483
- " _skip_webui = locals().get('skip_webui') or globals().get('skip_webui') or False\n",
484
- " _proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n",
485
- " _sub_path = locals().get('sub_path') or globals().get('sub_path') or ['/','/1/']\n",
486
- " if len(_sub_path) != 2:\n",
487
- " _sub_path = ['/','/1/']\n",
488
- " \n",
489
- " _config_args = locals().get('config_args') or globals().get('config_args') or {}\n",
490
- " \n",
491
- " _install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
492
- " _output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
493
- " _input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
494
- " _ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
495
- " \n",
496
- " ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
497
- " frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
498
- " # ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
499
- " frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
500
- " if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
501
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
502
- " # frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
503
- " frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n",
504
- " # 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n",
505
- " otherArgs = '--xformers'\n",
506
- " if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
507
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
508
- "\n",
509
- " # 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
510
- " _setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
511
- "\n",
512
- " _ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
513
- "\n",
514
- " # 设置文件路径\n",
515
- " if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
516
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
517
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
518
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
519
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
520
- " \n",
521
- " frpcStartArg = ''\n",
522
- " freefrp_url = ''\n",
523
- " _frp_temp_config_file = ''\n",
524
- " _frp_config_or_file = replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or frpcConfigFile\n",
525
- " run(f'''mkdir -p {_install_path}/configFiles''')\n",
526
- " if _frp_config_or_file:\n",
527
- " if '[common]' in _frp_config_or_file:\n",
528
- " echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_webui.ini')\n",
529
- " _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_webui.ini'\n",
530
- " elif '.ini' in _frp_config_or_file:\n",
531
- " _frp_temp_config_file = _frp_config_or_file.strip()\n",
532
- " \n",
533
- " if _frp_temp_config_file:\n",
534
- " if Path(_frp_temp_config_file).exists():\n",
535
- " run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_webui.ini''')\n",
536
- " run(f'''sed -i \"s/local_port = .*/local_port = {_server_port}/g\" {_install_path}/configFiles/frpc_webui.ini''')\n",
537
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
538
- " elif _frp_config_or_file.strip().startswith('-f'):\n",
539
- " frpcStartArg = _frp_config_or_file.strip()\n",
540
- " \n",
541
- " if not frpcStartArg:\n",
542
- " conf,url = get_freefrp_confog(_server_port)\n",
543
- " echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n",
544
- " freefrp_url = url\n",
545
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
546
- "\n",
547
- " ngrokToken=''\n",
548
- " _ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
549
- " if _ngrok_config_or_file:\n",
550
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
551
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
552
- " if Path(ngrokTokenFile).exists():\n",
553
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
554
- " ngrokToken = nkfile.readline()\n",
555
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
556
- " ngrokToken=_ngrok_config_or_file.strip()\n",
557
- " \n",
558
- " if not Path(venvPath).exists():\n",
559
- " venvPath = os.path.join(_input_path,'sd-webui-venv/venv.zip')\n",
560
- " "
561
- ]
562
- },
563
- {
564
- "cell_type": "markdown",
565
- "metadata": {},
566
- "source": [
567
- "## 文件下载工具\n",
568
- "\n",
569
- "---\n",
570
- "\n",
571
- "link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',sync:bool=False,thread_num:int=None)"
572
- ]
573
- },
574
- {
575
- "cell_type": "code",
576
- "execution_count": null,
577
- "metadata": {
578
- "trusted": true
579
- },
580
- "outputs": [],
581
- "source": [
582
- "import concurrent.futures\n",
583
- "import importlib\n",
584
- "import os\n",
585
- "import pprint\n",
586
- "import re\n",
587
- "import venv\n",
588
- "from pathlib import Path\n",
589
- "from typing import List\n",
590
- "\n",
591
- "import requests\n",
592
- "\n",
593
- "show_shell_info = False\n",
594
- "\n",
595
- "def is_installed(package):\n",
596
- " try:\n",
597
- " spec = importlib.util.find_spec(package)\n",
598
- " except ModuleNotFoundError:\n",
599
- " return False\n",
600
- "\n",
601
- " return spec is not None\n",
602
- "\n",
603
- "def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True,headers={}):\n",
604
- " startTicks = time.time()\n",
605
- " # 获取文件的真实文件名\n",
606
- " if not filename:\n",
607
- " with requests.get(url, stream=True,headers=headers) as r:\n",
608
- " if 'Content-Disposition' in r.headers:\n",
609
- " filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n",
610
- " r.close()\n",
611
- " if not filename and re.search(r'/[^/]+\\.[^/]+$',url):\n",
612
- " filename = url.split('/')[-1].split('?')[0]\n",
613
- " \n",
614
- " filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n",
615
- " filename = re.sub(r'[\\s\\t]+', '_', filename)\n",
616
- " \n",
617
- " print(f'下载 {filename} url: {url} --> {dist_path}')\n",
618
- " \n",
619
- " # 创建目录\n",
620
- " if cache_path and not Path(cache_path).exists():\n",
621
- " os.makedirs(cache_path,exist_ok=True)\n",
622
- " if dist_path and not Path(dist_path).exists():\n",
623
- " os.makedirs(dist_path,exist_ok=True)\n",
624
- " \n",
625
- " # 拼接文件的完整路径\n",
626
- " filepath = os.path.join(dist_path, filename)\n",
627
- "\n",
628
- " if cache_path:\n",
629
- " cache_path = os.path.join(cache_path, filename)\n",
630
- " \n",
631
- " # 判断文件是否已存在\n",
632
- " if Path(filepath).exists():\n",
633
- " print(f'文件 {filename} 已存在 {dist_path}')\n",
634
- " return\n",
635
- " \n",
636
- " if cache_path and Path(cache_path).exists():\n",
637
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
638
- " print(f'文件缓存 {cache_path} --> {dist_path}')\n",
639
- " return\n",
640
- " # 下载文件\n",
641
- " size = 0\n",
642
- " with requests.get(url, stream=True, headers=headers) as r:\n",
643
- " r.raise_for_status()\n",
644
- " with open(cache_path or filepath, 'wb') as f:\n",
645
- " for chunk in r.iter_content(chunk_size=1024*1024):\n",
646
- " if chunk:\n",
647
- " size += len(chunk)\n",
648
- " f.write(chunk)\n",
649
- " # 如果使用了缓存目录 需要复制或链接文件到目标目录\n",
650
- " if cache_path:\n",
651
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
652
- " ticks = time.time()\n",
653
- " print(f'下载完成 {filename} --> {dist_path} 大小{round(size/1024/1024,2)}M 耗时:{round(ticks - startTicks,2)}秒')\n",
654
- " \n",
655
- "def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
656
- " if not Path(dist_path).exists():\n",
657
- " os.makedirs(dist_path,exist_ok=True)\n",
658
- " if show_shell_info:\n",
659
- " print(f'git 下载 {url} --> {dist_path}')\n",
660
- " if cache_path and not Path(cache_path).exists():\n",
661
- " os.makedirs(cache_path,exist_ok=True)\n",
662
- " run(f'git clone {url}',cwd = cache_path)\n",
663
- " if cache_path:\n",
664
- " run(f'cp -n -r -f {cache_path}/* {dist_path}')\n",
665
- " else:\n",
666
- " run(f'git clone {url}',cwd = dist_path)\n",
667
- " if show_shell_info:\n",
668
- " print(f'git 下载完成 {url} --> {dist_path}')\n",
669
- " \n",
670
- " \n",
671
- "def download_huggingface(url:str, filename:str, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
672
- " fileReg = r'^https:\\/\\/huggingface.co(\\/([^\\/]+\\/)?[^\\/]+\\/[^\\/]+\\/(resolve|blob)\\/[^\\/]+\\/|[^\\.]+\\.[^\\.]+$|download=true)'\n",
673
- " def isFile(url:str):\n",
674
- " if re.match(fileReg,url):\n",
675
- " return True\n",
676
- " return False\n",
677
- " if isFile(url):\n",
678
- " download_file(url,filename,dist_path,cache_path,_link_instead_of_copy,headers=huggingface_headers)\n",
679
- " else:\n",
680
- " download_git(url,dist_path,cache_path,_link_instead_of_copy)\n",
681
- " \n",
682
- "# 加入文件到下载列表\n",
683
- "def pause_url(url:str,dist_path:str):\n",
684
- " file_name = ''\n",
685
- " if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n",
686
- " file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n",
687
- " url = url[len(file_name)+1:]\n",
688
- " if not re.match(r'^(https?|ftps?)://',url):\n",
689
- " return\n",
690
- " file_name = re.sub(r'\\s+','_',file_name or '')\n",
691
- " path_hash = str(hash(url)).replace('-','')\n",
692
- " \n",
693
- " return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}\n",
694
- "\n",
695
- "def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5, \n",
696
- " cache_path:str=os.path.join(os.environ['HOME'],'.cache','download_util'),\n",
697
- " _link_instead_of_copy:bool=True,is_await:bool=False):\n",
698
- " if sync:\n",
699
- " for conf in download_list:\n",
700
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
701
- " if conf['url'].startswith('https://github.com'):\n",
702
- " try:\n",
703
- " download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
704
- " except:\n",
705
- " pass\n",
706
- " continue\n",
707
- " if conf['url'].startswith('https://huggingface.co'):\n",
708
- " try:\n",
709
- " download_huggingface(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
710
- " except:\n",
711
- " pass\n",
712
- " continue\n",
713
- " if conf['url'].startswith('https://civitai.com'):\n",
714
- " if not re.search(r'token=.+', conf['url']):\n",
715
- " if conf['url'].find('?') == -1:\n",
716
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
717
- " else:\n",
718
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
719
- " try:\n",
720
- " download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
721
- " except:\n",
722
- " pass\n",
723
- " else:\n",
724
- " executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)\n",
725
- " futures = []\n",
726
- " for conf in download_list:\n",
727
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
728
- " if conf['url'].startswith('https://github.com'):\n",
729
- " futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],\n",
730
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
731
- " continue\n",
732
- " if conf['url'].startswith('https://huggingface.co'):\n",
733
- " futures.append(executor.submit(download_huggingface,conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
734
- " continue\n",
735
- " if conf['url'].startswith('https://civitai.com'):\n",
736
- " if not re.search(r'token=.+', conf['url']):\n",
737
- " if conf['url'].find('?') == -1:\n",
738
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
739
- " else:\n",
740
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
741
- " futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],\n",
742
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
743
- " if is_await:\n",
744
- " concurrent.futures.wait(futures)\n",
745
- " \n",
746
- " \n",
747
- "def parse_config(config:str):\n",
748
- " space_string = ' \\n\\r\\t\\'\\\",'\n",
749
- " other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\\n') if item.strip(space_string)]\n",
750
- " other_flie_list = [item.strip() for item in other_flie_list if item.strip()]\n",
751
- " other_flie_list_store = {}\n",
752
- " other_flie_list_store_name='default'\n",
753
- " other_flie_list_store_list_cache=[]\n",
754
- " \n",
755
- " for item in other_flie_list:\n",
756
- " if item.startswith('[') and item.endswith(']'):\n",
757
- " if not other_flie_list_store_name == 'default':\n",
758
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
759
- " other_flie_list_store_list_cache = []\n",
760
- " other_flie_list_store_name = item[1:-1]\n",
761
- " else:\n",
762
- " other_flie_list_store_list_cache.append(item)\n",
763
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
764
- " \n",
765
- " return other_flie_list_store\n",
766
- "\n",
767
- "\n",
768
- "def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',\n",
769
- " sync:bool=False,thread_num:int=None, is_await:bool=False):\n",
770
- " store:dict[str,List[str]] = parse_config(config)\n",
771
- " download_list = []\n",
772
- " for dist_dir in store.keys():\n",
773
- " dist_path = os.path.join(base_path,dist_dir)\n",
774
- " os.makedirs(dist_path,exist_ok=True)\n",
775
- " for path in store[dist_dir]:\n",
776
- " if 'https://' in path or 'http://' in path:\n",
777
- " if skip_url:\n",
778
- " continue\n",
779
- " if sync:\n",
780
- " try:\n",
781
- " download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)\n",
782
- " except:\n",
783
- " pass\n",
784
- " continue\n",
785
- " download_list.append(pause_url(path,dist_path))\n",
786
- " else:\n",
787
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {path} {dist_path}')\n",
788
- " if show_shell_info:\n",
789
- " print(f'{\"链接\" if _link_instead_of_copy else \"复制\"} {path} --> {dist_path}')\n",
790
- " run(f'rm -f {dist_path}/\\*.* ')\n",
791
- " if not skip_url:\n",
792
- " if show_shell_info:\n",
793
- " pprint.pprint(download_list)\n",
794
- " try:\n",
795
- " download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 3,is_await=is_await)\n",
796
- " except:\n",
797
- " pass"
798
- ]
799
- },
800
- {
801
- "cell_type": "markdown",
802
- "metadata": {
803
- "id": "p0uS-BLULCtD"
804
- },
805
- "source": [
806
- "## kaggle public API\n",
807
- "\n",
808
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
809
- "\n",
810
- "---"
811
- ]
812
- },
813
- {
814
- "cell_type": "code",
815
- "execution_count": null,
816
- "metadata": {
817
- "_kg_hide-input": true,
818
- "id": "m8FJi4j0LCtD",
819
- "trusted": true
820
- },
821
- "outputs": [],
822
- "source": [
823
- "# 安装kaggle的api token文件\n",
824
- "def initKaggleConfig():\n",
825
- " if Path('~/.kaggle/kaggle.json').exists():\n",
826
- " return True\n",
827
- " if Path(kaggleApiTokenFile).exists():\n",
828
- " run(f'''mkdir -p ~/.kaggle/''')\n",
829
- " run('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n",
830
- " run(f'''chmod 600 ~/.kaggle/kaggle.json''')\n",
831
- " return True\n",
832
- " print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n",
833
- " return False\n",
834
- "\n",
835
- "def getUserName():\n",
836
- " if not initKaggleConfig(): return\n",
837
- " import kaggle\n",
838
- " return kaggle.KaggleApi().read_config_file()['username']\n",
839
- "\n",
840
- "def createOrUpdateDataSet(path:str,datasetName:str):\n",
841
- " if not initKaggleConfig(): return\n",
842
- " print('创建或更新数据集 '+datasetName)\n",
843
- " import kaggle\n",
844
- " run(f'mkdir -p {_install_path}/kaggle_cache')\n",
845
- " run(f'rm -rf {_install_path}/kaggle_cache/*')\n",
846
- " datasetDirPath = _install_path+'/kaggle_cache/'+datasetName\n",
847
- " run('mkdir -p '+datasetDirPath)\n",
848
- " run('cp -f '+path+' '+datasetDirPath+'/')\n",
849
- " username = getUserName()\n",
850
- " print(\"kaggle username:\"+username)\n",
851
- " datasetPath = username+'/'+datasetName\n",
852
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
853
- " print(datasetList)\n",
854
- " if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n",
855
- " run('kaggle datasets init -p' + datasetDirPath)\n",
856
- " metadataFile = datasetDirPath+'/dataset-metadata.json'\n",
857
- " run('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n",
858
- " run('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n",
859
- " run('cat '+metadataFile)\n",
860
- " run('kaggle datasets create -p '+datasetDirPath)\n",
861
- " print('create database done')\n",
862
- " else:\n",
863
- " kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n",
864
- " kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n",
865
- " print('upload database done')\n",
866
- "\n",
867
- "def downloadDatasetFiles(datasetName:str,outputPath:str):\n",
868
- " if not initKaggleConfig(): return\n",
869
- " print('下载数据集文件 '+datasetName)\n",
870
- " import kaggle\n",
871
- " username = getUserName()\n",
872
- " datasetPath = username+'/'+datasetName\n",
873
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
874
- " if datasetPath not in [str(d) for d in datasetList]:\n",
875
- " return False\n",
876
- " run('mkdir -p '+outputPath)\n",
877
- " kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n",
878
- " return True\n",
879
- "\n"
880
- ]
881
- },
882
- {
883
- "cell_type": "markdown",
884
- "metadata": {},
885
- "source": [
886
- "## 同步文件夹到 huggingface\n",
887
- "\n",
888
- "---"
889
- ]
890
- },
891
- {
892
- "cell_type": "code",
893
- "execution_count": null,
894
- "metadata": {
895
- "trusted": true
896
- },
897
- "outputs": [],
898
- "source": [
899
- "# 文件夹与 huggingface 同步\n",
900
- "if _huggingface_token and _huggingface_repo:\n",
901
- " if not is_installed('watchdog'):\n",
902
- " requirements.append('watchdog')\n",
903
- " if not is_installed('huggingface_hub'):\n",
904
- " requirements.append('huggingface_hub')\n",
905
- " else:\n",
906
- " try:\n",
907
- " from huggingface_hub import HfApi,login,snapshot_download\n",
908
- " except:\n",
909
- " requirements.append('huggingface_hub')\n",
910
- "\n",
911
- "huggingface_is_init = False\n",
912
- "\n",
913
- "def init_huggingface():\n",
914
- " if not _huggingface_token:\n",
915
- " return False\n",
916
- "\n",
917
- " global huggingface_headers\n",
918
- " global huggingface_is_init\n",
919
- " \n",
920
- " from huggingface_hub import login\n",
921
- " token = replace_path(_huggingface_token)\n",
922
- " if not _huggingface_token.startswith('hf_') and Path(token).exists():\n",
923
- " with open(token,encoding = \"utf-8\") as nkfile:\n",
924
- " token = nkfile.readline()\n",
925
- " if not token.startswith('hf_'):\n",
926
- " print('huggingface token 不正确,请将 token 或 仅存放token 的txt文件路径填入 _huggingface_token 配置')\n",
927
- " return False\n",
928
- " login(token,add_to_git_credential=True)\n",
929
- " huggingface_headers = {'Authorization': 'Bearer '+token}\n",
930
- " print('huggingface token 已经加载,可以下载私有仓库或文件')\n",
931
- " \n",
932
- " if not _huggingface_repo:\n",
933
- " print('huggingface 同步收藏图片功能不会启动,可增加配置项 huggingface_token = \"token\" 和 huggingface_repo = “仓库id” 后启用 huggingface 同步收藏图片功能')\n",
934
- " return False\n",
935
- " huggingface_is_init = True\n",
936
- " return True\n",
937
- "\n",
938
- "\n",
939
- "def download__huggingface_repo(repo_id:str,dist_directory:str=None,repo_type='dataset',callback=None):\n",
940
- " if not huggingface_is_init:\n",
941
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
942
- " \n",
943
- " if not dist_directory:\n",
944
- " dist_directory = f'{_install_path}/{_ui_dir_name}/log'\n",
945
- " \n",
946
- " print('下载收藏的图片')\n",
947
- " if not Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
948
- " mkdirs(f'{_install_path}/cache/huggingface')\n",
949
- " repo_path = ''\n",
950
- " if repo_type == 'dataset':\n",
951
- " repo_path = 'datasets'\n",
952
- " if repo_type == 'space':\n",
953
- " repo_path = 'spaces'\n",
954
- " if repo_path:\n",
955
- " run(f'git clone https://huggingface.co/{repo_path}/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
956
- " else:\n",
957
- " run(f'git clone https://huggingface.co/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
958
- " if Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
959
- " run(f'cp -r -f -n -s {_install_path}/cache/huggingface/huggingface_repo/* {dist_directory}')\n",
960
- " if callback:\n",
961
- " callback()\n",
962
- "\n",
963
- "def start_sync_log_to_huggingface(repo_id:str,directory_to_watch:str=None,repo_type='dataset'):\n",
964
- " if not huggingface_is_init:\n",
965
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
966
- " \n",
967
- " from watchdog.observers import Observer\n",
968
- " from watchdog.events import FileSystemEventHandler\n",
969
- " from huggingface_hub import HfApi,login,snapshot_download\n",
970
- " \n",
971
- " # 配置监视的目录和 Hugging Face 仓库信息\n",
972
- " class FileChangeHandler(FileSystemEventHandler):\n",
973
- " def __init__(self, api, repo_id, repo_type,directory_to_watch):\n",
974
- " self.api = api\n",
975
- " self.repo_id = repo_id\n",
976
- " self.repo_type = repo_type\n",
977
- " self.directory_to_watch = directory_to_watch\n",
978
- " def on_created(self, event):\n",
979
- " if not event.is_directory:\n",
980
- " # 上传新文件到 Hugging Face 仓库\n",
981
- " file_path = event.src_path\n",
982
- " file_name:str = os.path.basename(file_path)\n",
983
- " print(file_name)\n",
984
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
985
- " print(file_name,'>>','huggingface')\n",
986
- " try:\n",
987
- " self.api.upload_file(\n",
988
- " path_or_fileobj=file_path,\n",
989
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
990
- " repo_id=self.repo_id,\n",
991
- " repo_type=self.repo_type,\n",
992
- " )\n",
993
- " except IOError as error:\n",
994
- " print(error)\n",
995
- "\n",
996
- " def on_deleted(self, event):\n",
997
- " if not event.is_directory:\n",
998
- " # 从 Hugging Face 仓库删除文件\n",
999
- " file_path = event.src_path\n",
1000
- " file_name = os.path.basename(file_path)\n",
1001
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1002
- " try:\n",
1003
- " self.api.delete_file(\n",
1004
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1005
- " repo_id=self.repo_id,\n",
1006
- " repo_type=self.repo_type,\n",
1007
- " )\n",
1008
- " except IOError as error:\n",
1009
- " print(error)\n",
1010
- "\n",
1011
- " def on_modified(self, event):\n",
1012
- " if not event.is_directory:\n",
1013
- " # 更新 Hugging Face 仓库中的文件\n",
1014
- " file_path = event.src_path\n",
1015
- " file_name = os.path.basename(file_path)\n",
1016
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1017
- " try:\n",
1018
- " self.api.upload_file(\n",
1019
- " path_or_fileobj=file_path,\n",
1020
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1021
- " repo_id=self.repo_id,\n",
1022
- " repo_type=self.repo_type,\n",
1023
- " )\n",
1024
- " except IOError as error:\n",
1025
- " print(error)\n",
1026
- "\n",
1027
- " def on_moved(self, event):\n",
1028
- " if not event.is_directory:\n",
1029
- " file_path = event.dest_path\n",
1030
- " file_name = os.path.basename(file_path)\n",
1031
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
1032
- " if event.dest_path.startswith(self.directory_to_watch):\n",
1033
- " try:\n",
1034
- " self.api.upload_file(\n",
1035
- " path_or_fileobj=file_path,\n",
1036
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
1037
- " repo_id=self.repo_id,\n",
1038
- " repo_type=self.repo_type,\n",
1039
- " )\n",
1040
- " except IOError as error:\n",
1041
- " print(error)\n",
1042
- "\n",
1043
- " api = HfApi()\n",
1044
- " \n",
1045
- " if not directory_to_watch:\n",
1046
- " directory_to_watch = f'{_install_path}/{_ui_dir_name}/log'\n",
1047
- " # 创建观察者对象并注册文件变化处理程序\n",
1048
- " event_handler = FileChangeHandler(api,repo_id,repo_type,directory_to_watch)\n",
1049
- " observer = Observer()\n",
1050
- " observer.schedule(event_handler, directory_to_watch, recursive=True)\n",
1051
- "\n",
1052
- " # 启动观察者\n",
1053
- " observer.name = \"solo_directory_to_watch\"\n",
1054
- " print(f'启动收藏图片文件夹监听,并自动同步到 huggingface {repo_type} : {repo_id}')\n",
1055
- " observer.start()"
1056
- ]
1057
- },
1058
- {
1059
- "cell_type": "markdown",
1060
- "metadata": {
1061
- "id": "sswa04veLCtE"
1062
- },
1063
- "source": [
1064
- "## 工具函数\n",
1065
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
1066
- "\n",
1067
- "---"
1068
- ]
1069
- },
1070
- {
1071
- "cell_type": "code",
1072
- "execution_count": null,
1073
- "metadata": {
1074
- "_kg_hide-input": true,
1075
- "trusted": true
1076
- },
1077
- "outputs": [],
1078
- "source": [
1079
- "\n",
1080
- "def zipPath(path:str,zipName:str,format='tar'):\n",
1081
- " if path.startswith('$install_path'):\n",
1082
- " path = path.replace('$install_path',_install_path)\n",
1083
- " if path.startswith('$output_path'):\n",
1084
- " path = path.replace('$install_path',_output_path)\n",
1085
- " if not path.startswith('/'):\n",
1086
- " path = f'{_install_path}/{_ui_dir_name}/{path}'\n",
1087
- " if Path(path).exists():\n",
1088
- " if 'tar' == format:\n",
1089
- " run(f'tar -cf {_output_path}/'+ zipName +'.tar -C '+ path +' . ')\n",
1090
- " elif 'gz' == format:\n",
1091
- " run(f'tar -czf {_output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')\n",
1092
- " return\n",
1093
- " print('指定的目录不存在:'+path)\n",
1094
- " \n",
1095
- "def get_folder_list(directory:str): \n",
1096
- " folder_list = [] \n",
1097
- " for item in os.listdir(directory): \n",
1098
- " if os.path.isdir(os.path.join(directory, item)): \n",
1099
- " folder_list.append(item) \n",
1100
- " return folder_list\n",
1101
- "\n",
1102
- "def read_text_file(file_path:str):\n",
1103
- " if not Path(file_path).exists(): return ''\n",
1104
- " with open(file_path,\"r\") as f:\n",
1105
- " text = file.read()\n",
1106
- " if text: return text.strip()\n",
1107
- " return ''"
1108
- ]
1109
- },
1110
- {
1111
- "cell_type": "markdown",
1112
- "metadata": {},
1113
- "source": [
1114
- "## 内网穿透\n",
1115
- "\n",
1116
- "---"
1117
- ]
1118
- },
1119
- {
1120
- "cell_type": "code",
1121
- "execution_count": null,
1122
- "metadata": {
1123
- "_kg_hide-input": true,
1124
- "_kg_hide-output": true,
1125
- "id": "coqQvTSLLCtE",
1126
- "trusted": true
1127
- },
1128
- "outputs": [],
1129
- "source": [
1130
- "def printUrl(url,name=''):\n",
1131
- " print(f'{name} 访问地址:{url}')\n",
1132
- " for key in sorted(_proxy_path.keys(), key=len)[::-1]:\n",
1133
- " print(f'{name} 本地服务:{_proxy_path[key]} 访问地址:{url}{key}')\n",
1134
- "# ngrok\n",
1135
- "def startNgrok(ngrokToken:str,ngrokLocalPort:int):\n",
1136
- " if not is_installed('pyngrok'):\n",
1137
- " run('pip install pyngrok')\n",
1138
- " from pyngrok import conf, ngrok\n",
1139
- " try:\n",
1140
- " conf.get_default().auth_token = ngrokToken\n",
1141
- " conf.get_default().monitor_thread = False\n",
1142
- " ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n",
1143
- " url = ''\n",
1144
- " if len(ssh_tunnels) == 0:\n",
1145
- " ssh_tunnel = ngrok.connect(ngrokLocalPort)\n",
1146
- " url = ssh_tunnel.public_url\n",
1147
- " print('ngrok 访问地址:'+ssh_tunnel.public_url)\n",
1148
- " else:\n",
1149
- " print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n",
1150
- " url = ssh_tunnels[0].public_url\n",
1151
- " printUrl(url,'ngrok')\n",
1152
- " def auto_request_ngrok():\n",
1153
- " if url:\n",
1154
- " while(_runing):\n",
1155
- " time.sleep(60*1)\n",
1156
- " try:\n",
1157
- " res = requests.get(url+'/',headers={\"ngrok-skip-browser-warning\" : \"1\"},timeout=10)\n",
1158
- " except:\n",
1159
- " ''\n",
1160
- " # print('自动调用ngrok链接以保存链接不会断开',res.status_code)\n",
1161
- "\n",
1162
- " # threading.Thread(target = auto_request_ngrok,daemon=True,name='solo_auto_request_ngrok').start()\n",
1163
- " except:\n",
1164
- " print('启动ngrok出错')\n",
1165
- " \n",
1166
- "def startFrpc(name,configFile):\n",
1167
- " if not Path(f'{_install_path}/frpc/frpc').exists():\n",
1168
- " installFrpExe()\n",
1169
- " if freefrp_url:\n",
1170
- " printUrl(freefrp_url,'freefrp')\n",
1171
- " echoToFile(f'''\n",
1172
- "cd {_install_path}/frpc/\n",
1173
- "{_install_path}/frpc/frpc {configFile}\n",
1174
- "''',f'{_install_path}/frpc/start.sh')\n",
1175
- " get_ipython().system(f'''bash {_install_path}/frpc/start.sh''')\n",
1176
- " \n",
1177
- "def installFrpExe():\n",
1178
- " if _useFrpc:\n",
1179
- " print('安装frpc')\n",
1180
- " run(f'mkdir -p {_install_path}/frpc')\n",
1181
- " if Path(frpcExePath).exists():\n",
1182
- " run(f'cp -f -n {frpcExePath} {_install_path}/frpc/frpc')\n",
1183
- " else:\n",
1184
- " run(f'wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O {_install_path}/frpc/frpc')\n",
1185
- " \n",
1186
- " for ssl in frpcSSLFFlies:\n",
1187
- " if Path(ssl).exists():\n",
1188
- " run(f'cp -f -n {ssl}/* {_install_path}/frpc/')\n",
1189
- " run(f'chmod +x {_install_path}/frpc/frpc')\n",
1190
- " run(f'{_install_path}/frpc/frpc -v')\n",
1191
- "\n",
1192
- "def startProxy():\n",
1193
- " if _useNgrok:\n",
1194
- " startNgrok(ngrokToken,_server_port)\n",
1195
- " if _useFrpc:\n",
1196
- " startFrpc('frpc_proxy',frpcStartArg)"
1197
- ]
1198
- },
1199
- {
1200
- "cell_type": "markdown",
1201
- "metadata": {},
1202
- "source": [
1203
- "## NGINX 反向代理\n",
1204
- "\n",
1205
- "---"
1206
- ]
1207
- },
1208
- {
1209
- "cell_type": "code",
1210
- "execution_count": null,
1211
- "metadata": {
1212
- "_kg_hide-input": true,
1213
- "_kg_hide-output": true,
1214
- "trusted": true
1215
- },
1216
- "outputs": [],
1217
- "source": [
1218
- "\n",
1219
- "# nginx 反向代理配置文件\n",
1220
- "def localProxy():\n",
1221
- " def getProxyLocation(subPath:str, localServer:str):\n",
1222
- " return '''\n",
1223
- " location '''+ subPath +'''\n",
1224
- " {\n",
1225
- " proxy_pass '''+ localServer +''';\n",
1226
- " \n",
1227
- " client_max_body_size 1000m;\n",
1228
- " proxy_set_header Host $http_host;\n",
1229
- " proxy_set_header X-Real-IP $remote_addr;\n",
1230
- " proxy_set_header X-Real-Port $remote_port;\n",
1231
- " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",
1232
- " proxy_set_header X-Forwarded-Proto $scheme;\n",
1233
- " proxy_set_header X-Forwarded-Host $host;\n",
1234
- " proxy_set_header X-Forwarded-Port $server_port;\n",
1235
- " proxy_set_header REMOTE-HOST $remote_addr;\n",
1236
- " proxy_connect_timeout 3000s;\n",
1237
- " proxy_send_timeout 3000s;\n",
1238
- " proxy_read_timeout 3000s;\n",
1239
- " proxy_http_version 1.1;\n",
1240
- " proxy_set_header Upgrade $http_upgrade;\n",
1241
- " proxy_set_header Connection 'upgrade';\n",
1242
- " add_header Access-Control-Allow-Origin * always;\n",
1243
- " add_header Access-Control-Allow-Headers *;\n",
1244
- " add_header Access-Control-Allow-Methods \"GET, POST, PUT, OPTIONS\";\n",
1245
- " }\n",
1246
- " \n",
1247
- " '''\n",
1248
- " \n",
1249
- " conf = '''\n",
1250
- "server\n",
1251
- "{\n",
1252
- " listen '''+str(_server_port)+''';\n",
1253
- " listen [::]:'''+str(_server_port)+''';\n",
1254
- " server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n",
1255
- " \n",
1256
- " fastcgi_send_timeout 3000s;\n",
1257
- " fastcgi_read_timeout 3000s;\n",
1258
- " fastcgi_connect_timeout 3000s;\n",
1259
- " \n",
1260
- " if ($request_method = OPTIONS) {\n",
1261
- " return 200;\n",
1262
- " }\n",
1263
- " \n",
1264
- " '''+ ''.join([getProxyLocation(key,_proxy_path[key]) for key in sorted(_proxy_path.keys(), key=len)[::-1]]) +'''\n",
1265
- "}\n",
1266
- "'''\n",
1267
- " echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n",
1268
- " if not check_service('localhost',_server_port):\n",
1269
- " run(f'''nginx -c /etc/nginx/nginx.conf''')\n",
1270
- " run(f'''nginx -s reload''')"
1271
- ]
1272
- },
1273
- {
1274
- "cell_type": "markdown",
1275
- "metadata": {},
1276
- "source": [
1277
- "## 线程清理工具\n",
1278
- "\n",
1279
- "---\n",
1280
- "\n",
1281
- "清理线程名以 solo_ 开头的所有线程"
1282
- ]
1283
- },
1284
- {
1285
- "cell_type": "code",
1286
- "execution_count": null,
1287
- "metadata": {
1288
- "_kg_hide-input": true,
1289
- "trusted": true
1290
- },
1291
- "outputs": [],
1292
- "source": [
1293
- "import inspect\n",
1294
- "import ctypes\n",
1295
- "\n",
1296
- "def _async_raise(tid, exctype):\n",
1297
- " \"\"\"raises the exception, performs cleanup if needed\"\"\"\n",
1298
- " tid = ctypes.c_long(tid)\n",
1299
- " if not inspect.isclass(exctype):\n",
1300
- " exctype = type(exctype)\n",
1301
- " res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n",
1302
- " if res == 0:\n",
1303
- " raise ValueError(\"invalid thread id\")\n",
1304
- " elif res != 1:\n",
1305
- " # \"\"\"if it returns a number greater than one, you're in trouble,\n",
1306
- " # and you should call it again with exc=NULL to revert the effect\"\"\"\n",
1307
- " ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n",
1308
- " raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n",
1309
- "\n",
1310
- "def stop_thread(thread):\n",
1311
- " _async_raise(thread.ident, SystemExit)\n",
1312
- "\n",
1313
- "def stop_solo_threads():\n",
1314
- " global _runing\n",
1315
- " _runing = False\n",
1316
- " # 获取当前所有活动的线程\n",
1317
- " threads = threading.enumerate()\n",
1318
- " # 关闭之前创建的子线程\n",
1319
- " for thread in threads:\n",
1320
- " if thread.name.startswith('solo_'):\n",
1321
- " print(f'结束线程:{thread.name}')\n",
1322
- " try:\n",
1323
- " stop_thread(thread)\n",
1324
- " except socket.error:\n",
1325
- " print(f'结束线程:{thread.name} 执行失败')"
1326
- ]
1327
- },
1328
- {
1329
- "cell_type": "markdown",
1330
- "metadata": {
1331
- "id": "Ve3p8oOkLCtE"
1332
- },
1333
- "source": [
1334
- "# webui 安装和配置函数\n",
1335
- "---"
1336
- ]
1337
- },
1338
- {
1339
- "cell_type": "code",
1340
- "execution_count": null,
1341
- "metadata": {
1342
- "_kg_hide-input": true,
1343
- "id": "GTjyBJihLCtE",
1344
- "trusted": true
1345
- },
1346
- "outputs": [],
1347
- "source": [
1348
- "envInstalled=False\n",
1349
- "quickStart = False\n",
1350
- "#安装\n",
1351
- "def install():\n",
1352
- " print('安装')\n",
1353
- " os.chdir(f'''{_install_path}''')\n",
1354
- " run(f'''git lfs install''')\n",
1355
- " run(f'''git config --global credential.helper store''')\n",
1356
- " for requirement in requirements:\n",
1357
- " run(f'pip install {requirement}')\n",
1358
- " if _reLoad:\n",
1359
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}''')\n",
1360
- " if Path(f\"{_ui_dir_name}\").exists():\n",
1361
- " os.chdir(f'''{_install_path}/{_ui_dir_name}/''')\n",
1362
- " run(f'''git checkout .''')\n",
1363
- " run(f'''git pull''')\n",
1364
- " else:\n",
1365
- " run(f'''git clone --recursive {_sd_git_repo} {_ui_dir_name}''')\n",
1366
- " if not Path(f'''{_install_path}/{_ui_dir_name}''').exists():\n",
1367
- " print('sd-webui主程序安装失败,请检查 sd_git_repo 配置的值是否正确')\n",
1368
- " sys.exit(0)\n",
1369
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1370
- " print('安装 完成')\n",
1371
- "\n",
1372
- "# 链接输出目录\n",
1373
- "def link_dir():\n",
1374
- " print('链接输出目录')\n",
1375
- " # 链接图片输出目录\n",
1376
- " run(f'''mkdir -p {_output_path}/outputs''')\n",
1377
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/outputs''')\n",
1378
- " run(f'''ln -s -r {_output_path}/outputs {_install_path}/{_ui_dir_name}/''')\n",
1379
- " # 输出收藏目录\n",
1380
- " run(f'''mkdir -p {_output_path}/log''')\n",
1381
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/log''')\n",
1382
- " run(f'''ln -s -r {_output_path}/log {_install_path}/{_ui_dir_name}/''')\n",
1383
- " # 链接训练输出目录 文件夹链接会导致功能不能用\n",
1384
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/textual_inversion''')\n",
1385
- " run(f'''mkdir -p {_output_path}/textual_inversion/''')\n",
1386
- " run(f'''ln -s -r {_output_path}/textual_inversion {_install_path}/{_ui_dir_name}/''')\n",
1387
- " print('链接输出目录 完成') \n",
1388
- "\n",
1389
- "def install_optimizing():\n",
1390
- " run('add-apt-repository ppa:deadsnakes/ppa -y')\n",
1391
- " run('apt update -y')\n",
1392
- " run('apt install nginx -y')\n",
1393
- " # run('apt install python3.10 -y')\n",
1394
- " \n",
1395
- "#安装依赖\n",
1396
- "def install_dependencies():\n",
1397
- " print('安装需要的python环境')\n",
1398
- " global envInstalled\n",
1399
- " global venvPath\n",
1400
- " if Path(f'{_install_path}/{_ui_dir_name}/venv').exists():\n",
1401
- " print('跳过安装python环境')\n",
1402
- " envInstalled = True\n",
1403
- " return\n",
1404
- " \n",
1405
- " if quickStart:\n",
1406
- " if not Path(venvPath).exists():\n",
1407
- " mkdirs(f'{_install_path}/venv_cache',True)\n",
1408
- " if not Path(f'{_install_path}/venv_cache/venv.tar.bak').exists():\n",
1409
- " print('下载 venv.zip')\n",
1410
- " download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{_install_path}/venv_cache')\n",
1411
- " run(f'''unzip {_install_path}/venv_cache/venv.zip -d {_install_path}/venv_cache''')\n",
1412
- " venvPath = f'{_install_path}/venv_cache/venv.tar.bak'\n",
1413
- " run(f'''rm -rf {_install_path}/venv_cache/venv.zip''')\n",
1414
- " elif venvPath.endswith('.zip'):\n",
1415
- " mkdirs(f'{_install_path}/venv_cache',True)\n",
1416
- " run(f'''unzip {venvPath} -d {_install_path}/venv_cache''')\n",
1417
- " venvPath = f'{_install_path}/venv_cache/venv.tar.bak'\n",
1418
- " print('解压环境')\n",
1419
- " mkdirs(f'{_install_path}/{_ui_dir_name}/venv')\n",
1420
- "# run('python3.10 -m venv venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1421
- " run(f'tar -xf {venvPath} -C ./venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1422
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/pip*')\n",
1423
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/python*')\n",
1424
- " venv.create(f'{_install_path}/{_ui_dir_name}/venv')\n",
1425
- " if not Path(f'{_install_path}/{_ui_dir_name}/venv/bin/pip').exists():\n",
1426
- " run('curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py')\n",
1427
- " run(f'{_install_path}/{_ui_dir_name}/venv/bin/python3 get-pip.py')\n",
1428
- "\n",
1429
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -V''')\n",
1430
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip -V''')\n",
1431
- " \n",
1432
- " if not quickStart:\n",
1433
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -V''')\n",
1434
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip -V''')\n",
1435
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install torch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 --index-url https://download.pytorch.org/whl/cu121''')\n",
1436
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install xformers==0.0.27''')\n",
1437
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install -r requirements_versions.txt''')\n",
1438
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install spandrel==0.3.0''')\n",
1439
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install opencv-python''')\n",
1440
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pydantic==1.10.15''')\n",
1441
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install transformers -U''')\n",
1442
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install llama-cpp-python''')\n",
1443
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pytorch_lightning==2.3.3 torchsde==0.2.6 spandrel==0.3.4''')\n",
1444
- " \n",
1445
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install open-clip-torch -U''')\n",
1446
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install protobuf==4.25.8''')\n",
1447
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install blendmodes==2022''')\n",
1448
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install Pillow==9.5.0''')\n",
1449
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr''')\n",
1450
- " \n",
1451
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr''')\n",
1452
- " \n",
1453
- " envInstalled = True\n",
1454
- " print('安装需要的python环境 完成')\n",
1455
- " \n",
1456
- "# 个性化配置 \n",
1457
- "def use_config():\n",
1458
- " print('使用自定义配置 包括tag翻译 \\n')\n",
1459
- " run(f'''mkdir -p {_install_path}/temp''')\n",
1460
- " run(f'git clone {_sd_config_git_repu} sd-configs',cwd=f'{_install_path}/temp')\n",
1461
- " run(f'cp -r -f -n {_install_path}/temp/sd-configs/dist/* {_install_path}/{_ui_dir_name}')\n",
1462
- " if not Path(_ui_config_file).exists() and _ui_config_file != 'ui-config.json': # ui配置文件\n",
1463
- " run(f'''mkdir -p {_ui_config_file[:_ui_config_file.rfind('/')]}''')\n",
1464
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/ui-config.json {_ui_config_file}')\n",
1465
- " if not Path(_setting_file).exists() and _setting_file != 'config.json': # 设置配置文件\n",
1466
- " run(f'''mkdir -p {_setting_file[:_setting_file.rfind('/')]}''')\n",
1467
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/config.json {_setting_file}')\n",
1468
- "\n",
1469
- "def copy_last_log_to_images():\n",
1470
- " if not Path(f'{_install_path}/{_ui_dir_name}/log/images').exists(): mkdirs(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1471
- " print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')\n",
1472
- " img_list = os.listdir(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1473
- " last_img_path = ''\n",
1474
- " last_img_num = 0\n",
1475
- " for img in img_list:\n",
1476
- " if re.findall(r'^\\d+-',str(img)):\n",
1477
- " num = int(re.findall(r'^\\d+-',str(img))[0][:-1])\n",
1478
- " if num > last_img_num:\n",
1479
- " last_img_path = img\n",
1480
- " last_img_num = num\n",
1481
- " \n",
1482
- " if not last_img_path: return\n",
1483
- " \n",
1484
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images')\n",
1485
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/txt2img-images''')\n",
1486
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images/''')\n",
1487
- " \n",
1488
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images')\n",
1489
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/img2img-images''')\n",
1490
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images/''')\n",
1491
- " \n",
1492
- "def start_webui(i):\n",
1493
- " # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n",
1494
- " print(i,'--port',str(_server_port+1+i))\n",
1495
- " if i>0:\n",
1496
- " print(f'使用第{i+1}张显卡启动第{i+1}个服务,通过frpc或nrgok地址后加{_sub_path[i]}进行访问')\n",
1497
- "\n",
1498
- " restart_times = 0\n",
1499
- " last_restart_time = time.time()\n",
1500
- " while _runing:\n",
1501
- " os.chdir(f'{_install_path}/{_ui_dir_name}')\n",
1502
- " root_path = _sub_path[i]\n",
1503
- " if root_path.endswith('/'): root_path = root_path[:-1]\n",
1504
- " if torch.cuda.device_count() == 2 and not _multi_case:\n",
1505
- " os.environ['CUDA_VISIBLE_DEVICES']='0,1'\n",
1506
- " get_ipython().system(f'''venv/bin/python3 launch.py --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1507
- " else: \n",
1508
- " get_ipython().system(f'''venv/bin/python3 launch.py --device-id={i} --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1509
- " print('10秒后重启服务')\n",
1510
- " if time.time() - last_restart_time < 60:\n",
1511
- " restart_times = restart_times + 1\n",
1512
- " else:\n",
1513
- " restart_times = 0\n",
1514
- " last_restart_time = time.time()\n",
1515
- " if restart_times >3 :\n",
1516
- " # 如果180秒内重启了3此,将不再自动重启\n",
1517
- " break\n",
1518
- " time.sleep(10)\n",
1519
- " \n",
1520
- "# 启动\n",
1521
- "def start():\n",
1522
- " print('启动webui')\n",
1523
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1524
- " args = ''\n",
1525
- " if _ui_config_file is not None and _ui_config_file != '' and Path(_ui_config_file).exists(): # ui配置文件\n",
1526
- " args += ' --ui-config-file=' + _ui_config_file\n",
1527
- " if _setting_file is not None and _setting_file != '' and Path(_setting_file).exists(): # 设置配置文件\n",
1528
- " args += ' --ui-settings-file=' + _setting_file\n",
1529
- " args += ' ' + otherArgs\n",
1530
- " os.environ['COMMANDLINE_ARGS']=args\n",
1531
- " run(f'''echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS''')\n",
1532
- " os.environ['REQS_FILE']='requirements_versions.txt'\n",
1533
- "\n",
1534
- " with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:\n",
1535
- " for i in range(torch.cuda.device_count() if _multi_case else 1):\n",
1536
- " executor.submit(start_webui,i)\n",
1537
- " while _runing and not check_service('localhost',str(_server_port+1+i)): # 当当前服务启动完成才允许退出此次循环\n",
1538
- " time.sleep(5)\n",
1539
- " if not _runing: break\n",
1540
- " time.sleep(10)"
1541
- ]
1542
- },
1543
- {
1544
- "cell_type": "markdown",
1545
- "metadata": {
1546
- "id": "qLvsk8ByLCtF"
1547
- },
1548
- "source": [
1549
- "# 入口函数\n",
1550
- "---"
1551
- ]
1552
- },
1553
- {
1554
- "cell_type": "code",
1555
- "execution_count": null,
1556
- "metadata": {
1557
- "_kg_hide-input": true,
1558
- "id": "IOKjaMlcLCtF",
1559
- "trusted": true
1560
- },
1561
- "outputs": [],
1562
- "source": [
1563
- "\n",
1564
- "# 启动非webui相关的的内容,加快启动速度\n",
1565
- "def main():\n",
1566
- " global envInstalled\n",
1567
- " global huggingface_is_init\n",
1568
- " global _runing\n",
1569
- " _init_conf()\n",
1570
- " stop_solo_threads()\n",
1571
- " print('启动...')\n",
1572
- " startTicks = time.time()\n",
1573
- " time.sleep(5)\n",
1574
- " _runing = True\n",
1575
- " isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n",
1576
- " _proxy_path[_sub_path[0]] = f'http://127.0.0.1:{_server_port+1}/'\n",
1577
- " _proxy_path[_sub_path[1]] = f'http://127.0.0.1:{_server_port+2}/'\n",
1578
- " proxy_thread = threading.Thread(target = startProxy, daemon=True, name='solo_startProxy')\n",
1579
- " proxy_thread.start()\n",
1580
- " if isInstall is False or _reLoad: \n",
1581
- " print('安装运行环境')\n",
1582
- " os.environ['MPLBACKEND'] = 'Agg'\n",
1583
- " install()\n",
1584
- " link_dir()\n",
1585
- " init_huggingface()\n",
1586
- " install_optimizing()\n",
1587
- " if not _skip_webui:\n",
1588
- " threading.Thread(target = install_dependencies,daemon=True,name='solo_install_dependencies').start()\n",
1589
- " else: envInstalled = True\n",
1590
- " link_or_download_flie(replace_path(_async_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1591
- " base_path=f'{_install_path}/{_ui_dir_name}')\n",
1592
- " if huggingface_is_init:\n",
1593
- " threading.Thread(target = download__huggingface_repo,daemon=True,\n",
1594
- " args=([_huggingface_repo]),\n",
1595
- " kwargs={\"callback\":copy_last_log_to_images},\n",
1596
- " name='solo_download__huggingface_repo').start()\n",
1597
- " \n",
1598
- " link_or_download_flie(replace_path(_before_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1599
- " base_path=f'{_install_path}/{_ui_dir_name}',is_await=True,sync=True)\n",
1600
- " t = 0\n",
1601
- " while _runing and not envInstalled:\n",
1602
- " if t%10==0:\n",
1603
- " print('等待python环境安装...')\n",
1604
- " t = t+1\n",
1605
- " time.sleep(1)\n",
1606
- " use_config()\n",
1607
- " os.environ['IsInstall'] = 'True'\n",
1608
- " else:\n",
1609
- " envInstalled = True\n",
1610
- " localProxy()\n",
1611
- " link_or_download_flie(replace_path(_before_start_sync_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1612
- " base_path=f'{_install_path}/{_ui_dir_name}',sync=True)\n",
1613
- " if init_huggingface():\n",
1614
- " start_sync_log_to_huggingface(_huggingface_repo)\n",
1615
- " ticks = time.time()\n",
1616
- " _on_before_start()\n",
1617
- " print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n",
1618
- " if _skip_webui:\n",
1619
- " print('跳过webui启动')\n",
1620
- " proxy_thread.join()\n",
1621
- " else:\n",
1622
- " start()\n"
1623
- ]
1624
- },
1625
- {
1626
- "cell_type": "markdown",
1627
- "metadata": {
1628
- "id": "0oaCRs2gLCtF"
1629
- },
1630
- "source": [
1631
- "# 执行区域\n",
1632
- "---"
1633
- ]
1634
- },
1635
- {
1636
- "cell_type": "code",
1637
- "execution_count": null,
1638
- "metadata": {
1639
- "_kg_hide-output": true,
1640
- "id": "O3DR0DWHLCtF",
1641
- "scrolled": true,
1642
- "trusted": true
1643
- },
1644
- "outputs": [],
1645
- "source": [
1646
- "# 启动\n",
1647
- "# _reLoad = True\n",
1648
- "# hidden_console_info = False\n",
1649
- "# run_by_none_device = True\n",
1650
- "# show_shell_info = True\n",
1651
- "\n",
1652
- "print(f'当前sd的安装路径是:{_install_path}/{_ui_dir_name}')\n",
1653
- "print(f'当前图片保存路径是:{_output_path}')\n",
1654
- "print(f'当前数据集路径是:{_input_path}')\n",
1655
- "\n",
1656
- "print(update_desc)\n",
1657
- "\n",
1658
- "if _skip_start:\n",
1659
- " print('已跳过自动启动,可手动执行 main() 进行启动。')\n",
1660
- " print('''推荐的启动代码:\n",
1661
- "try:\n",
1662
- " check_gpu() # 检查是否存在gpu\n",
1663
- " main()\n",
1664
- "except KeyboardInterrupt:\n",
1665
- " stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)\n",
1666
- " ''')\n",
1667
- "else:\n",
1668
- " try:\n",
1669
- " check_gpu()\n",
1670
- " main()\n",
1671
- " except KeyboardInterrupt:\n",
1672
- " stop_solo_threads()"
1673
- ]
1674
- },
1675
- {
1676
- "cell_type": "code",
1677
- "execution_count": null,
1678
- "metadata": {
1679
- "trusted": true
1680
- },
1681
- "outputs": [],
1682
- "source": []
1683
- }
1684
- ],
1685
- "metadata": {
1686
- "kaggle": {
1687
- "accelerator": "nvidiaTeslaT4",
1688
- "dataSources": [
1689
- {
1690
- "datasetId": 2716934,
1691
- "sourceId": 6167400,
1692
- "sourceType": "datasetVersion"
1693
- },
1694
- {
1695
- "datasetId": 3654544,
1696
- "sourceId": 6346544,
1697
- "sourceType": "datasetVersion"
1698
- },
1699
- {
1700
- "datasetId": 2962375,
1701
- "sourceId": 6720235,
1702
- "sourceType": "datasetVersion"
1703
- },
1704
- {
1705
- "datasetId": 3074484,
1706
- "sourceId": 6817788,
1707
- "sourceType": "datasetVersion"
1708
- }
1709
- ],
1710
- "isGpuEnabled": true,
1711
- "isInternetEnabled": true,
1712
- "language": "python",
1713
- "sourceType": "notebook"
1714
- },
1715
- "kernelspec": {
1716
- "display_name": "Python 3",
1717
- "language": "python",
1718
- "name": "python3"
1719
- },
1720
- "language_info": {
1721
- "codemirror_mode": {
1722
- "name": "ipython",
1723
- "version": 3
1724
- },
1725
- "file_extension": ".py",
1726
- "mimetype": "text/x-python",
1727
- "name": "python",
1728
- "nbconvert_exporter": "python",
1729
- "pygments_lexer": "ipython3",
1730
- "version": "3.10.13"
1731
- }
1732
- },
1733
- "nbformat": 4,
1734
- "nbformat_minor": 4
1735
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
sdwui-start-util.mini.ipynb DELETED
@@ -1,1652 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": null,
6
- "metadata": {
7
- "trusted": true
8
- },
9
- "outputs": [],
10
- "source": []
11
- },
12
- {
13
- "cell_type": "code",
14
- "execution_count": null,
15
- "metadata": {
16
- "trusted": true
17
- },
18
- "outputs": [],
19
- "source": [
20
- "update_desc = '''\n",
21
- "欢迎使用 stable-diffusion-webui 便捷启动工具\n",
22
- "\n",
23
- "此脚本理论上可以在任何jupyter环境运行,但仅在 google colab 和 kaggle 测试。 已经无法在 google colab 免费实例上运行。\n",
24
- "此脚本的【前置脚本】发布地址 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai-sdxl。\n",
25
- "此脚本需配合 【前置脚本】 的脚本附带的配置项才能正常启动。\n",
26
- "此脚本的内容会自动更新,你无需更新【前置脚本】就能获取到最新的功能。\n",
27
- "增加一个说明:为解决加密图片的解密和浏览的问题,开发了一个独立应用,可以在这里下载 https://github.com/viyiviyi/encrypt_gallery/releases/\n",
28
- "加密插件可解决生成nsfw图片后被平台封号问题\n",
29
- "\n",
30
- "路径说明\n",
31
- "* 为了解决平台差异,所有的安装目录和文件输出目录都被重新指定,如果你需要在配置中访问这些目录,请查看以下说明\n",
32
- "*\n",
33
- "* 可以使用 $install_path 或 {install_path} 来访问安装目录,写在字符串内也会生效\n",
34
- "* $output_path 或 {output_path} 可以访问输出目录\n",
35
- "* 如果你需要安装在自定义目录,也可以设置这些值 如: install_path = '新的路径'\n",
36
- "* 可自定义方法 on_before_start 并在方法内写上启动前需要的逻辑来实现在webui启动前执行自定义逻辑\n",
37
- "* 可以增加配置 multi_case = True 来控制是否使用多卡\n",
38
- "* 如果需要显示更多控制台输出 需配置 hidden_console_info = False\n",
39
- "\n",
40
- "********* 特别提示 *********\n",
41
- "* huggingface 的下载链接需要增加 ?download=true 参数才能正确下载到文件,如果你需要的文件里的下载链接没有这个参数,请自行增加。\n",
42
- "'''"
43
- ]
44
- },
45
- {
46
- "cell_type": "code",
47
- "execution_count": null,
48
- "metadata": {
49
- "trusted": true
50
- },
51
- "outputs": [],
52
- "source": [
53
- "from pathlib import Path\n",
54
- "import os\n",
55
- "import time\n",
56
- "import re\n",
57
- "import subprocess\n",
58
- "import threading\n",
59
- "import sys\n",
60
- "import socket\n",
61
- "import torch\n",
62
- "from typing import List\n",
63
- "import uuid\n",
64
- "import asyncio\n",
65
- "from urllib import request"
66
- ]
67
- },
68
- {
69
- "cell_type": "code",
70
- "execution_count": null,
71
- "metadata": {
72
- "trusted": true
73
- },
74
- "outputs": [],
75
- "source": [
76
- "# 内置参数默认值,当上下文有参数时可覆盖默认值\n",
77
- "_runing = False\n",
78
- "_useFrpc = True\n",
79
- "_useNgrok = True\n",
80
- "_reLoad = False\n",
81
- "_before_downloading = ''\n",
82
- "_async_downloading = ''\n",
83
- "_before_start_sync_downloading = ''\n",
84
- "_server_port = 7860\n",
85
- "_sd_git_repo = 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local'\n",
86
- "_sd_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git'\n",
87
- "_huggingface_token = '{input_path}/configs/huggingface_token.txt'\n",
88
- "_huggingface_repo = ''\n",
89
- "_link_instead_of_copy = True\n",
90
- "show_shell_info = False\n",
91
- "_multi_case = False\n",
92
- "_skip_start = True\n",
93
- "def before_start():\n",
94
- " pass\n",
95
- "\n",
96
- "def main_start():\n",
97
- " pass\n",
98
- " \n",
99
- "_on_before_start = before_start \n",
100
- "_skip_webui = False\n",
101
- "run_by_none_device = False\n",
102
- "_proxy_path = {}\n",
103
- "_sub_path = ['/','/1/']\n",
104
- "_config_args:dict[str, str] = {}"
105
- ]
106
- },
107
- {
108
- "cell_type": "code",
109
- "execution_count": null,
110
- "metadata": {
111
- "trusted": true
112
- },
113
- "outputs": [],
114
- "source": [
115
- "\n",
116
- "def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:\n",
117
- " global show_shell_info\n",
118
- " if desc is not None:\n",
119
- " print(desc)\n",
120
- "\n",
121
- " run_kwargs = {\n",
122
- " \"args\": command,\n",
123
- " \"shell\": True,\n",
124
- " \"cwd\": cwd,\n",
125
- " \"env\": os.environ if custom_env is None else custom_env,\n",
126
- " \"encoding\": 'utf8',\n",
127
- " \"errors\": 'ignore',\n",
128
- " }\n",
129
- "\n",
130
- " if not show_shell_info:\n",
131
- " run_kwargs[\"stdout\"] = run_kwargs[\"stderr\"] = subprocess.PIPE\n",
132
- "\n",
133
- " result = subprocess.run(**run_kwargs)\n",
134
- "\n",
135
- " if result.returncode != 0:\n",
136
- " error_bits = [\n",
137
- " f\"{errdesc or 'Error running command'}.\",\n",
138
- " f\"Command: {command}\",\n",
139
- " f\"Error code: {result.returncode}\",\n",
140
- " ]\n",
141
- " if result.stdout:\n",
142
- " error_bits.append(f\"stdout: {result.stdout}\")\n",
143
- " if result.stderr:\n",
144
- " error_bits.append(f\"stderr: {result.stderr}\")\n",
145
- " if try_error:\n",
146
- " print((RuntimeError(\"\\n\".join(error_bits))))\n",
147
- " else:\n",
148
- " raise RuntimeError(\"\\n\".join(error_bits))\n",
149
- "\n",
150
- " if show_shell_info:\n",
151
- " print((result.stdout or \"\"))\n",
152
- " return (result.stdout or \"\")\n",
153
- "\n",
154
- "def mkdirs(path, exist_ok=True):\n",
155
- " if path and not Path(path).exists():\n",
156
- " os.makedirs(path,exist_ok=exist_ok)\n",
157
- "\n",
158
- "\n",
159
- "# 检查网络\n",
160
- "def check_service(host, port):\n",
161
- " try:\n",
162
- " socket.create_connection((host, port), timeout=5)\n",
163
- " return True\n",
164
- " except socket.error:\n",
165
- " return False\n",
166
- "\n",
167
- "\n",
168
- "# 检查gpu是否存在\n",
169
- "def check_gpu():\n",
170
- " if not run_by_none_device and torch.cuda.device_count() == 0:\n",
171
- " raise Exception('当前环境没有GPU')\n",
172
- "\n",
173
- "\n",
174
- "def echoToFile(content:str,path:str):\n",
175
- " if path.find('/') >= 0:\n",
176
- " _path = '/'.join(path.split('/')[:-1])\n",
177
- " run(f'''mkdir -p {_path}''')\n",
178
- " with open(path,'w') as sh:\n",
179
- " sh.write(content)\n",
180
- " \n",
181
- "def get_freefrp_confog(local_port):\n",
182
- " rd_str = uuid.uuid1()\n",
183
- " return (f'''\n",
184
- "[common]\n",
185
- "server_addr = frp.freefrp.net\n",
186
- "server_port = 7000\n",
187
- "token = freefrp.net\n",
188
- "\n",
189
- "[{rd_str}_http]\n",
190
- "type = http\n",
191
- "local_ip = 127.0.0.1\n",
192
- "local_port = {local_port}\n",
193
- "custom_domains = {rd_str}.frp.eaias.com\n",
194
- "''',f'http://{rd_str}.frp.eaias.com')"
195
- ]
196
- },
197
- {
198
- "cell_type": "code",
199
- "execution_count": null,
200
- "metadata": {
201
- "trusted": true
202
- },
203
- "outputs": [],
204
- "source": [
205
- "\n",
206
- "_install_path = f\"/kaggle\" if os.path.exists('/kaggle/') else f\"{os.environ['HOME']}/sd_webui\" # 安装目录\n",
207
- "_output_path = '/kaggle/working' if os.path.exists('/kaggle/working/') else f\"{os.environ['HOME']}/.sdwui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\n",
208
- "_input_path = '/kaggle/input' # 输入目录\n",
209
- "_ui_dir_name = 'sd_main_dir'\n",
210
- "\n",
211
- "_install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
212
- "_output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
213
- "_input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
214
- "_ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
215
- "\n",
216
- "install_path = _install_path\n",
217
- "output_path = _output_path\n",
218
- "input_path = _input_path\n",
219
- "ui_dir_name = _ui_dir_name\n",
220
- " \n",
221
- "google_drive = '' \n",
222
- "\n",
223
- "\n",
224
- "_useGooglrDrive = locals().get('useGooglrDrive') or globals().get('useGooglrDrive') or True\n",
225
- "\n",
226
- "# 连接谷歌云\n",
227
- "try:\n",
228
- " if _useGooglrDrive:\n",
229
- " from google.colab import drive\n",
230
- " drive.mount(f'~/google_drive')\n",
231
- " google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n",
232
- " _output_path = f'{google_drive}/sdwebui/Output'\n",
233
- " _input_path = f'{google_drive}/sdwebui/Input'\n",
234
- " run(f'''mkdir -p {_input_path}''')\n",
235
- " print('''\n",
236
- "已经链接到谷歌云盘\n",
237
- "已在云盘创建Input和Output目录\n",
238
- " ''')\n",
239
- "except:\n",
240
- " _useGooglrDrive = False\n",
241
- "\n",
242
- "run(f'''mkdir -p {_install_path}''')\n",
243
- "run(f'''mkdir -p {_output_path}''')\n",
244
- "\n",
245
- "\n",
246
- "os.environ['install_path'] = _install_path\n",
247
- "os.environ['output_path'] = _output_path\n",
248
- "os.environ['google_drive'] = google_drive\n",
249
- "os.environ['input_path'] = _input_path\n",
250
- "\n",
251
- "space_string = ' \\n\\r\\t\\'\\\",'\n",
252
- "\n",
253
- "def replace_path(input_str:str):\n",
254
- " if not input_str: return ''\n",
255
- " for key in _config_args:\n",
256
- " input_str = input_str.replace(key,_config_args[key])\n",
257
- " \n",
258
- " if not (locals().get('use_comfyui') or globals().get('use_comfyui') or False):\n",
259
- " input_str = input_str.replace('https://github.com/comfyanonymous/ComfyUI.git','https://github.com/comfyanonymous/ComfyUI.git')\n",
260
- " \n",
261
- " return input_str.replace('$install_path',_install_path)\\\n",
262
- " .replace('{install_path}',_install_path)\\\n",
263
- " .replace('$input_path',_input_path)\\\n",
264
- " .replace('{input_path}',_input_path)\\\n",
265
- " .replace('$output_path',_output_path)\\\n",
266
- " .replace('{output_path}',_output_path)\\\n",
267
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
268
- " .replace('{wui}',\"webui\")\\\n",
269
- " .strip()\n",
270
- "\n",
271
- "\n",
272
- "def config_reader(conf:str):\n",
273
- " conf = conf or \"\"\n",
274
- " args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\\n') if item.strip(space_string)]\n",
275
- " return [item.strip() for item in args if item.strip()]\n",
276
- "\n",
277
- "def load_frpc_config(conf_or_file,dost_port=None):\n",
278
- " frpcStartArg = ''\n",
279
- " _frp_temp_config_file = ''\n",
280
- " _frp_config_or_file = conf_or_file\n",
281
- " run(f'''mkdir -p {_install_path}/configFiles''')\n",
282
- " if _frp_config_or_file:\n",
283
- " if '[common]' in _frp_config_or_file:\n",
284
- " echoToFile(_frp_config_or_file,f'{_install_path}/configFiles/temp_frpc_{dost_port or _server_port}.ini')\n",
285
- " _frp_temp_config_file = f'{_install_path}/configFiles/temp_frpc_{dost_port or _server_port}.ini'\n",
286
- " elif '.ini' in _frp_config_or_file:\n",
287
- " _frp_temp_config_file = _frp_config_or_file.strip()\n",
288
- " \n",
289
- " if _frp_temp_config_file:\n",
290
- " if Path(_frp_temp_config_file).exists():\n",
291
- " run(f'''cp -f {_frp_temp_config_file} {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini''')\n",
292
- " run(f'''sed -i \"s/local_port = .*/local_port = {dost_port or _server_port}/g\" {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini''')\n",
293
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_{dost_port or _server_port}.ini'\n",
294
- " elif _frp_config_or_file.strip().startswith('-f'):\n",
295
- " frpcStartArg = _frp_config_or_file.strip()\n",
296
- " return frpcStartArg"
297
- ]
298
- },
299
- {
300
- "cell_type": "code",
301
- "execution_count": null,
302
- "metadata": {
303
- "_kg_hide-input": true,
304
- "id": "i3LhnwYHLCtC",
305
- "trusted": true
306
- },
307
- "outputs": [],
308
- "source": [
309
- "ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
310
- "frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
311
- "# ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
312
- "frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
313
- "if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
314
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
315
- "# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
316
- "frpcExePath = os.path.join(_input_path,'utils-tools/frpc')\n",
317
- "# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\n",
318
- "otherArgs = '--xformers'\n",
319
- "if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
320
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
321
- "venvPath = os.path.join(_input_path,'sd-webui-venv-mini/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n",
322
- "if not Path(venvPath).exists():\n",
323
- " venvPath = os.path.join(_input_path,'sd-webui-venv-mini/venv.zip')\n",
324
- "\n",
325
- "# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n",
326
- "# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\n",
327
- "kaggleApiTokenFile = os.path.join(_input_path,'configs/kaggle.json')\n",
328
- "\n",
329
- "requirements = []\n"
330
- ]
331
- },
332
- {
333
- "cell_type": "code",
334
- "execution_count": null,
335
- "metadata": {
336
- "_kg_hide-input": true,
337
- "id": "a_GtG2ayLCtD",
338
- "trusted": true
339
- },
340
- "outputs": [],
341
- "source": [
342
- "# 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
343
- "_setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
344
- "\n",
345
- "_ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
346
- "\n",
347
- "# 设置文件路径\n",
348
- "if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
349
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
350
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
351
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
352
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
353
- " \n",
354
- "frpcStartArg = load_frpc_config(replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or '', _server_port)\n",
355
- "freefrp_url = ''\n",
356
- "ngrokToken=''\n",
357
- "_ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
358
- "if _ngrok_config_or_file:\n",
359
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
360
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
361
- " if Path(ngrokTokenFile).exists():\n",
362
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
363
- " ngrokToken = nkfile.readline()\n",
364
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
365
- " ngrokToken=_ngrok_config_or_file.strip()\n",
366
- " \n",
367
- " \n",
368
- "huggingface_headers:dict = None "
369
- ]
370
- },
371
- {
372
- "cell_type": "code",
373
- "execution_count": null,
374
- "metadata": {
375
- "trusted": true
376
- },
377
- "outputs": [],
378
- "source": [
379
- "def init_start_conf():\n",
380
- " global _useFrpc\n",
381
- " global _useNgrok\n",
382
- " global _reLoad\n",
383
- " global _before_downloading\n",
384
- " global _async_downloading\n",
385
- " global _before_start_sync_downloading\n",
386
- " global _server_port\n",
387
- " global _sd_git_repo\n",
388
- " global _sd_config_git_repu\n",
389
- " global _huggingface_token\n",
390
- " global _huggingface_repo\n",
391
- " global _link_instead_of_copy\n",
392
- " global show_shell_info\n",
393
- " global _multi_case\n",
394
- " global _skip_start\n",
395
- " global _on_before_start\n",
396
- " global _skip_webui\n",
397
- " global _proxy_path\n",
398
- " global _sub_path\n",
399
- " global _config_args\n",
400
- " global _install_path\n",
401
- " global _output_path\n",
402
- " global _input_path\n",
403
- " global _ui_dir_name\n",
404
- " global freefrp_url\n",
405
- " global ngrokTokenFile\n",
406
- " global frpcSSLFFlies\n",
407
- " global frpcExePath\n",
408
- " global frpcStartArg\n",
409
- " global otherArgs\n",
410
- " global _setting_file\n",
411
- " global _ui_config_file\n",
412
- " global ngrokToken\n",
413
- " global venvPath\n",
414
- " \n",
415
- " _useFrpc = locals().get('useFrpc') or globals().get('useFrpc') or True\n",
416
- " _useNgrok = locals().get('useNgrok') or globals().get('useNgrok') or True\n",
417
- " _reLoad = locals().get('reLoad') or globals().get('reLoad') or False\n",
418
- " _before_downloading = locals().get('before_downloading') or globals().get('before_downloading') or ''\n",
419
- " _async_downloading = locals().get('async_downloading') or globals().get('async_downloading') or ''\n",
420
- " _before_start_sync_downloading = locals().get('before_start_sync_downloading') or globals().get('before_start_sync_downloading') or ''\n",
421
- " _server_port = locals().get('server_port') or globals().get('server_port') or 7860\n",
422
- " _sd_git_repo = locals().get('sd_git_repo') or globals().get('sd_git_repo') or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n",
423
- " _sd_git_repo = _sd_git_repo\\\n",
424
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
425
- " .replace('{wui}',\"webui\") \n",
426
- " _sd_config_git_repu = locals().get('sd_config_git_repu') or globals().get('sd_config_git_repu') or 'https://github.com/viyiviyi/sd-configs.git'\n",
427
- " _sd_config_git_repu = _sd_config_git_repu\\\n",
428
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
429
- " .replace('{wui}',\"webui\")\n",
430
- " _huggingface_token = locals().get('huggingface_token') or globals().get('huggingface_token') or '{input_path}/configs/huggingface_token.txt'\n",
431
- " _huggingface_token = _huggingface_token\\\n",
432
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
433
- " .replace('{wui}',\"webui\")\n",
434
- " _huggingface_repo = locals().get('huggingface_repo') or globals().get('huggingface_repo') or ''\n",
435
- " _huggingface_repo = _huggingface_repo\\\n",
436
- " .replace('{sdwui}','stable-diffusion-webui')\\\n",
437
- " .replace('{wui}',\"webui\")\n",
438
- " _link_instead_of_copy = locals().get('link_instead_of_copy') or globals().get('link_instead_of_copy') or True\n",
439
- " show_shell_info = locals().get('hidden_console_info') or globals().get('hidden_console_info')\n",
440
- " if show_shell_info is None: show_shell_info = False\n",
441
- " else: show_shell_info = not show_shell_info\n",
442
- " _multi_case = locals().get('multi_case') or globals().get('multi_case') or False\n",
443
- " _skip_start = locals().get('skip_start') or globals().get('skip_start') or True\n",
444
- " _on_before_start = locals().get('on_before_start') or globals().get('on_before_start') or before_start \n",
445
- " _skip_webui = locals().get('skip_webui') or globals().get('skip_webui') or False\n",
446
- " _proxy_path = locals().get('proxy_path') or globals().get('proxy_path') or {}\n",
447
- " _sub_path = locals().get('sub_path') or globals().get('sub_path') or ['/','/1/']\n",
448
- " if len(_sub_path) != 2:\n",
449
- " _sub_path = ['/','/1/']\n",
450
- " \n",
451
- " _config_args = locals().get('config_args') or globals().get('config_args') or {}\n",
452
- " \n",
453
- " _install_path = locals().get('install_path') or globals().get('install_path') or _install_path\n",
454
- " _output_path = locals().get('output_path') or globals().get('output_path') or _output_path\n",
455
- " _input_path = locals().get('input_path') or globals().get('input_path') or _input_path\n",
456
- " _ui_dir_name = locals().get('ui_dir_name') or globals().get('ui_dir_name') or _ui_dir_name\n",
457
- " \n",
458
- " ngrokTokenFile = os.path.join(_input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\n",
459
- " frpcConfigFile = os.path.join(_input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n",
460
- " # ss证书目录 下载nginx的版本,把pem格式改成crt格式\n",
461
- " frpcSSLFFlies = [os.path.join(_input_path,'configs/koishi_ssl')]\n",
462
- " if 'frp_ssl_dir' in locals() or 'frp_ssl_dir' in globals():\n",
463
- " frpcSSLFFlies = frpcSSLFFlies + config_reader(locals().get('frp_ssl_dir') or globals().get('frp_ssl_dir'))\n",
464
- " # frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\n",
465
- " frpcExePath = replace_path(locals().get('frpc_exe_path') or globals().get('frpc_exe_path') or os.path.join(_input_path,'utils-tools/frpc_v0.51.0')) \n",
466
- " # 其他需要加载的webui启动参数 写到【参数列表】这个配置\n",
467
- " otherArgs = '--xformers'\n",
468
- " if 'sd_start_args' in locals() or 'sd_start_args' in globals():\n",
469
- " otherArgs = ' '.join([item for item in config_reader(locals().get('sd_start_args') or globals().get('sd_start_args')) if item != '--no-gradio-queue'])\n",
470
- "\n",
471
- " # 这下面的是用于初始化一些值或者环境变量的,轻易别改\n",
472
- " _setting_file = replace_path(locals().get('setting_file') or globals().get('setting_file') or 'config.json')\n",
473
- "\n",
474
- " _ui_config_file = replace_path(locals().get('ui_config_file') or globals().get('ui_config_file') or 'ui-config.json')\n",
475
- "\n",
476
- " # 设置文件路径\n",
477
- " if Path(f\"{os.environ['HOME']}/google_drive/MyDrive\").exists():\n",
478
- " if _setting_file == '/kaggle/working/configs/config.json':\n",
479
- " _setting_file = os.path.join(_output_path,'configs/config.json')\n",
480
- " if _ui_config_file == '/kaggle/working/configs/ui-config.json':\n",
481
- " _ui_config_file = os.path.join(_output_path,'configs/ui-config.json')\n",
482
- "\n",
483
- " frpcStartArg = load_frpc_config(replace_path(locals().get('frp_config_or_file') or globals().get('frp_config_or_file')) or '', _server_port)\n",
484
- " if not frpcStartArg:\n",
485
- " conf,url = get_freefrp_confog(_server_port)\n",
486
- " echoToFile(conf,f'{_install_path}/configFiles/frpc_webui.ini')\n",
487
- " freefrp_url = url\n",
488
- " frpcStartArg = f' -c {_install_path}/configFiles/frpc_webui.ini'\n",
489
- " ngrokToken=''\n",
490
- " _ngrok_config_or_file = replace_path(locals().get('ngrok_config_or_file') or globals().get('ngrok_config_or_file')) or ngrokTokenFile\n",
491
- " if _ngrok_config_or_file:\n",
492
- " if Path(_ngrok_config_or_file.strip()).exists():\n",
493
- " ngrokTokenFile = _ngrok_config_or_file.strip()\n",
494
- " if Path(ngrokTokenFile).exists():\n",
495
- " with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n",
496
- " ngrokToken = nkfile.readline()\n",
497
- " elif not _ngrok_config_or_file.strip().startswith('/'):\n",
498
- " ngrokToken=_ngrok_config_or_file.strip()\n",
499
- " \n",
500
- " venvPath = os.path.join(_input_path,'sd-webui-venv-mini/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n",
501
- " "
502
- ]
503
- },
504
- {
505
- "cell_type": "markdown",
506
- "metadata": {},
507
- "source": [
508
- "## 文件下载工具\n",
509
- "\n",
510
- "---\n",
511
- "\n",
512
- "link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',sync:bool=False,thread_num:int=None)"
513
- ]
514
- },
515
- {
516
- "cell_type": "code",
517
- "execution_count": null,
518
- "metadata": {
519
- "trusted": true
520
- },
521
- "outputs": [],
522
- "source": [
523
- "import concurrent.futures\n",
524
- "import importlib\n",
525
- "import os\n",
526
- "import pprint\n",
527
- "import re\n",
528
- "import venv\n",
529
- "from pathlib import Path\n",
530
- "from typing import List\n",
531
- "\n",
532
- "import requests\n",
533
- "\n",
534
- "show_shell_info = False\n",
535
- "\n",
536
- "def is_installed(package):\n",
537
- " try:\n",
538
- " spec = importlib.util.find_spec(package)\n",
539
- " except ModuleNotFoundError:\n",
540
- " return False\n",
541
- "\n",
542
- " return spec is not None\n",
543
- "\n",
544
- "def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True,headers={}):\n",
545
- " startTicks = time.time()\n",
546
- " # 获取文���的真实文件名\n",
547
- " if not filename:\n",
548
- " with requests.get(url, stream=True,headers=headers) as r:\n",
549
- " if 'Content-Disposition' in r.headers:\n",
550
- " filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n",
551
- " r.close()\n",
552
- " if not filename and re.search(r'/[^/]+\\.[^/]+$',url):\n",
553
- " filename = url.split('/')[-1].split('?')[0]\n",
554
- " \n",
555
- " filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n",
556
- " filename = re.sub(r'[\\s\\t]+', '_', filename)\n",
557
- " \n",
558
- " print(f'下载 {filename} url: {url} --> {dist_path}')\n",
559
- " \n",
560
- " # 创建目录\n",
561
- " if cache_path and not Path(cache_path).exists():\n",
562
- " os.makedirs(cache_path,exist_ok=True)\n",
563
- " if dist_path and not Path(dist_path).exists():\n",
564
- " os.makedirs(dist_path,exist_ok=True)\n",
565
- " \n",
566
- " # 拼接文件的完整路径\n",
567
- " filepath = os.path.join(dist_path, filename)\n",
568
- "\n",
569
- " if cache_path:\n",
570
- " cache_path = os.path.join(cache_path, filename)\n",
571
- " \n",
572
- " # 判断文件是否已存在\n",
573
- " if Path(filepath).exists():\n",
574
- " print(f'文件 {filename} 已存在 {dist_path}')\n",
575
- " return\n",
576
- " \n",
577
- " if cache_path and Path(cache_path).exists():\n",
578
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
579
- " print(f'文件缓存 {cache_path} --> {dist_path}')\n",
580
- " return\n",
581
- " # 下载文件\n",
582
- " size = 0\n",
583
- " with requests.get(url, stream=True, headers=headers) as r:\n",
584
- " r.raise_for_status()\n",
585
- " with open(cache_path or filepath, 'wb') as f:\n",
586
- " for chunk in r.iter_content(chunk_size=1024*1024):\n",
587
- " if chunk:\n",
588
- " size += len(chunk)\n",
589
- " f.write(chunk)\n",
590
- " # 如果使用了缓存目录 需要复制或链接文件到目标目录\n",
591
- " if cache_path:\n",
592
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {cache_path} {dist_path}')\n",
593
- " ticks = time.time()\n",
594
- " print(f'下载完成 {filename} --> {dist_path} 大小{round(size/1024/1024,2)}M 耗时:{round(ticks - startTicks,2)}秒')\n",
595
- " \n",
596
- "def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
597
- " if not Path(dist_path).exists():\n",
598
- " os.makedirs(dist_path,exist_ok=True)\n",
599
- " if show_shell_info:\n",
600
- " print(f'git 下载 {url} --> {dist_path}')\n",
601
- " if cache_path and not Path(cache_path).exists():\n",
602
- " os.makedirs(cache_path,exist_ok=True)\n",
603
- " run(f'git clone {url}',cwd = cache_path)\n",
604
- " if cache_path:\n",
605
- " run(f'cp -n -r -f {cache_path}/* {dist_path}')\n",
606
- " else:\n",
607
- " run(f'git clone {url}',cwd = dist_path)\n",
608
- " if show_shell_info:\n",
609
- " print(f'git 下载完成 {url} --> {dist_path}')\n",
610
- " \n",
611
- " \n",
612
- "def download_huggingface(url:str, filename:str, dist_path, cache_path = '',_link_instead_of_copy:bool=True):\n",
613
- " fileReg = r'^https:\\/\\/huggingface.co(\\/([^\\/]+\\/)?[^\\/]+\\/[^\\/]+\\/(resolve|blob)\\/[^\\/]+\\/|[^\\.]+\\.[^\\.]+$|download=true)'\n",
614
- " def isFile(url:str):\n",
615
- " if re.match(fileReg,url):\n",
616
- " return True\n",
617
- " return False\n",
618
- " if isFile(url):\n",
619
- " download_file(url,filename,dist_path,cache_path,_link_instead_of_copy,headers=huggingface_headers)\n",
620
- " else:\n",
621
- " download_git(url,dist_path,cache_path,_link_instead_of_copy)\n",
622
- " \n",
623
- "# 加入文件到下载列表\n",
624
- "def pause_url(url:str,dist_path:str):\n",
625
- " file_name = ''\n",
626
- " if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n",
627
- " file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n",
628
- " url = url[len(file_name)+1:]\n",
629
- " if not re.match(r'^(https?|ftps?)://',url):\n",
630
- " return\n",
631
- " file_name = re.sub(r'\\s+','_',file_name or '')\n",
632
- " path_hash = str(hash(url)).replace('-','')\n",
633
- " \n",
634
- " return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}\n",
635
- "\n",
636
- "def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5, \n",
637
- " cache_path:str=os.path.join(os.environ['HOME'],'.cache','download_util'),\n",
638
- " _link_instead_of_copy:bool=True,is_await:bool=False):\n",
639
- " if sync:\n",
640
- " for conf in download_list:\n",
641
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
642
- " if conf['url'].startswith('https://github.com'):\n",
643
- " try:\n",
644
- " download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
645
- " except:\n",
646
- " pass\n",
647
- " continue\n",
648
- " if conf['url'].startswith('https://huggingface.co'):\n",
649
- " try:\n",
650
- " download_huggingface(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
651
- " except:\n",
652
- " pass\n",
653
- " continue\n",
654
- " if conf['url'].startswith('https://civitai.com'):\n",
655
- " if not re.search(r'token=.+', conf['url']):\n",
656
- " if conf['url'].find('?') == -1:\n",
657
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
658
- " else:\n",
659
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
660
- " try:\n",
661
- " download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)\n",
662
- " except:\n",
663
- " pass\n",
664
- " else:\n",
665
- " executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)\n",
666
- " futures = []\n",
667
- " for conf in download_list:\n",
668
- " cache_dir = os.path.join(cache_path,conf['path_hash'])\n",
669
- " if conf['url'].startswith('https://github.com'):\n",
670
- " futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],\n",
671
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
672
- " continue\n",
673
- " if conf['url'].startswith('https://huggingface.co'):\n",
674
- " futures.append(executor.submit(download_huggingface,conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
675
- " continue\n",
676
- " if conf['url'].startswith('https://civitai.com'):\n",
677
- " if not re.search(r'token=.+', conf['url']):\n",
678
- " if conf['url'].find('?') == -1:\n",
679
- " conf['url'] = conf['url']+'?token=fee8bb78b75566eddfd04d061996185c'\n",
680
- " else:\n",
681
- " conf['url'] = conf['url']+'&token=fee8bb78b75566eddfd04d061996185c'\n",
682
- " futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],\n",
683
- " cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))\n",
684
- " if is_await:\n",
685
- " concurrent.futures.wait(futures)\n",
686
- " \n",
687
- " \n",
688
- "def parse_config(config:str):\n",
689
- " space_string = ' \\n\\r\\t\\'\\\",'\n",
690
- " other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\\n') if item.strip(space_string)]\n",
691
- " other_flie_list = [item.strip() for item in other_flie_list if item.strip()]\n",
692
- " other_flie_list_store = {}\n",
693
- " other_flie_list_store_name='default'\n",
694
- " other_flie_list_store_list_cache=[]\n",
695
- " \n",
696
- " for item in other_flie_list:\n",
697
- " if item.startswith('[') and item.endswith(']'):\n",
698
- " if not other_flie_list_store_name == 'default':\n",
699
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
700
- " other_flie_list_store_list_cache = []\n",
701
- " other_flie_list_store_name = item[1:-1]\n",
702
- " else:\n",
703
- " other_flie_list_store_list_cache.append(item)\n",
704
- " other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n",
705
- " \n",
706
- " return other_flie_list_store\n",
707
- "\n",
708
- "\n",
709
- "def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',\n",
710
- " sync:bool=False,thread_num:int=None, is_await:bool=False):\n",
711
- " store:dict[str,List[str]] = parse_config(config)\n",
712
- " download_list = []\n",
713
- " for dist_dir in store.keys():\n",
714
- " dist_path = os.path.join(base_path,dist_dir)\n",
715
- " os.makedirs(dist_path,exist_ok=True)\n",
716
- " for path in store[dist_dir]:\n",
717
- " if 'https://' in path or 'http://' in path:\n",
718
- " if skip_url:\n",
719
- " continue\n",
720
- " if sync:\n",
721
- " try:\n",
722
- " download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)\n",
723
- " except:\n",
724
- " pass\n",
725
- " continue\n",
726
- " download_list.append(pause_url(path,dist_path))\n",
727
- " else:\n",
728
- " run(f'cp -n -r -f {\"-s\" if _link_instead_of_copy else \"\"} {path} {dist_path}')\n",
729
- " if show_shell_info:\n",
730
- " print(f'{\"链接\" if _link_instead_of_copy else \"复制\"} {path} --> {dist_path}')\n",
731
- " run(f'rm -f {dist_path}/\\*.* ')\n",
732
- " if not skip_url:\n",
733
- " if show_shell_info:\n",
734
- " pprint.pprint(download_list)\n",
735
- " try:\n",
736
- " download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 3,is_await=is_await)\n",
737
- " except:\n",
738
- " pass"
739
- ]
740
- },
741
- {
742
- "cell_type": "markdown",
743
- "metadata": {
744
- "id": "p0uS-BLULCtD"
745
- },
746
- "source": [
747
- "## kaggle public API\n",
748
- "\n",
749
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
750
- "\n",
751
- "---"
752
- ]
753
- },
754
- {
755
- "cell_type": "code",
756
- "execution_count": null,
757
- "metadata": {
758
- "_kg_hide-input": true,
759
- "id": "m8FJi4j0LCtD",
760
- "trusted": true
761
- },
762
- "outputs": [],
763
- "source": [
764
- "# 安装kaggle的api token文件\n",
765
- "def initKaggleConfig():\n",
766
- " if Path('~/.kaggle/kaggle.json').exists():\n",
767
- " return True\n",
768
- " if Path(kaggleApiTokenFile).exists():\n",
769
- " run(f'''mkdir -p ~/.kaggle/''')\n",
770
- " run('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n",
771
- " run(f'''chmod 600 ~/.kaggle/kaggle.json''')\n",
772
- " return True\n",
773
- " print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n",
774
- " return False\n",
775
- "\n",
776
- "def getUserName():\n",
777
- " if not initKaggleConfig(): return\n",
778
- " import kaggle\n",
779
- " return kaggle.KaggleApi().read_config_file()['username']\n",
780
- "\n",
781
- "def createOrUpdateDataSet(path:str,datasetName:str):\n",
782
- " if not initKaggleConfig(): return\n",
783
- " print('创建或更新数据集 '+datasetName)\n",
784
- " import kaggle\n",
785
- " run(f'mkdir -p {_install_path}/kaggle_cache')\n",
786
- " run(f'rm -rf {_install_path}/kaggle_cache/*')\n",
787
- " datasetDirPath = _install_path+'/kaggle_cache/'+datasetName\n",
788
- " run('mkdir -p '+datasetDirPath)\n",
789
- " run('cp -f '+path+' '+datasetDirPath+'/')\n",
790
- " username = getUserName()\n",
791
- " print(\"kaggle username:\"+username)\n",
792
- " datasetPath = username+'/'+datasetName\n",
793
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
794
- " print(datasetList)\n",
795
- " if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n",
796
- " run('kaggle datasets init -p' + datasetDirPath)\n",
797
- " metadataFile = datasetDirPath+'/dataset-metadata.json'\n",
798
- " run('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n",
799
- " run('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n",
800
- " run('cat '+metadataFile)\n",
801
- " run('kaggle datasets create -p '+datasetDirPath)\n",
802
- " print('create database done')\n",
803
- " else:\n",
804
- " kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n",
805
- " kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n",
806
- " print('upload database done')\n",
807
- "\n",
808
- "def downloadDatasetFiles(datasetName:str,outputPath:str):\n",
809
- " if not initKaggleConfig(): return\n",
810
- " print('下载数据集文件 '+datasetName)\n",
811
- " import kaggle\n",
812
- " username = getUserName()\n",
813
- " datasetPath = username+'/'+datasetName\n",
814
- " datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n",
815
- " if datasetPath not in [str(d) for d in datasetList]:\n",
816
- " return False\n",
817
- " run('mkdir -p '+outputPath)\n",
818
- " kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n",
819
- " return True\n",
820
- "\n"
821
- ]
822
- },
823
- {
824
- "cell_type": "markdown",
825
- "metadata": {},
826
- "source": [
827
- "## 同步文件夹到 huggingface\n",
828
- "\n",
829
- "---"
830
- ]
831
- },
832
- {
833
- "cell_type": "code",
834
- "execution_count": null,
835
- "metadata": {
836
- "trusted": true
837
- },
838
- "outputs": [],
839
- "source": [
840
- "# 文件夹与 huggingface 同步\n",
841
- "if _huggingface_token and _huggingface_repo:\n",
842
- " if not is_installed('watchdog'):\n",
843
- " requirements.append('watchdog')\n",
844
- " if not is_installed('huggingface_hub'):\n",
845
- " requirements.append('huggingface_hub')\n",
846
- " else:\n",
847
- " try:\n",
848
- " from huggingface_hub import HfApi,login,snapshot_download\n",
849
- " except:\n",
850
- " requirements.append('huggingface_hub')\n",
851
- "\n",
852
- "huggingface_is_init = False\n",
853
- "\n",
854
- "def init_huggingface():\n",
855
- " if not _huggingface_token:\n",
856
- " return False\n",
857
- "\n",
858
- " global huggingface_headers\n",
859
- " global huggingface_is_init\n",
860
- " \n",
861
- " from huggingface_hub import login\n",
862
- " token = replace_path(_huggingface_token)\n",
863
- " if not _huggingface_token.startswith('hf_') and Path(token).exists():\n",
864
- " with open(token,encoding = \"utf-8\") as nkfile:\n",
865
- " token = nkfile.readline()\n",
866
- " if not token.startswith('hf_'):\n",
867
- " print('huggingface token 不正确,请将 token 或 仅存放token 的txt文件路径填入 _huggingface_token 配置')\n",
868
- " return False\n",
869
- " login(token,add_to_git_credential=True)\n",
870
- " huggingface_headers = {'Authorization': 'Bearer '+token}\n",
871
- " print('huggingface token 已经加载,可以下载私有仓库或文件')\n",
872
- " \n",
873
- " if not _huggingface_repo:\n",
874
- " print('huggingface 同步收藏图片功能不会启动,可增加配置项 huggingface_token = \"token\" 和 huggingface_repo = “仓库id” 后启用 huggingface 同步收藏图片功能')\n",
875
- " return False\n",
876
- " huggingface_is_init = True\n",
877
- " return True\n",
878
- "\n",
879
- "\n",
880
- "def download__huggingface_repo(repo_id:str,dist_directory:str=None,repo_type='dataset',callback=None):\n",
881
- " if not huggingface_is_init:\n",
882
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
883
- " \n",
884
- " if not dist_directory:\n",
885
- " dist_directory = f'{_install_path}/{_ui_dir_name}/log'\n",
886
- " \n",
887
- " print('下载收藏的图片')\n",
888
- " if not Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
889
- " mkdirs(f'{_install_path}/cache/huggingface')\n",
890
- " repo_path = ''\n",
891
- " if repo_type == 'dataset':\n",
892
- " repo_path = 'datasets'\n",
893
- " if repo_type == 'space':\n",
894
- " repo_path = 'spaces'\n",
895
- " if repo_path:\n",
896
- " run(f'git clone https://huggingface.co/{repo_path}/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
897
- " else:\n",
898
- " run(f'git clone https://huggingface.co/{repo_id} huggingface_repo',cwd=f'{_install_path}/cache/huggingface')\n",
899
- " if Path(f'{_install_path}/cache/huggingface/huggingface_repo').exists():\n",
900
- " run(f'cp -r -f -n -s {_install_path}/cache/huggingface/huggingface_repo/* {dist_directory}')\n",
901
- " if callback:\n",
902
- " callback()\n",
903
- "\n",
904
- "def start_sync_log_to_huggingface(repo_id:str,directory_to_watch:str=None,repo_type='dataset'):\n",
905
- " if not huggingface_is_init:\n",
906
- " print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n",
907
- " \n",
908
- " from watchdog.observers import Observer\n",
909
- " from watchdog.events import FileSystemEventHandler\n",
910
- " from huggingface_hub import HfApi,login,snapshot_download\n",
911
- " \n",
912
- " # 配置监视的目录和 Hugging Face 仓库信息\n",
913
- " class FileChangeHandler(FileSystemEventHandler):\n",
914
- " def __init__(self, api, repo_id, repo_type,directory_to_watch):\n",
915
- " self.api = api\n",
916
- " self.repo_id = repo_id\n",
917
- " self.repo_type = repo_type\n",
918
- " self.directory_to_watch = directory_to_watch\n",
919
- " def on_created(self, event):\n",
920
- " if not event.is_directory:\n",
921
- " # 上传新文件到 Hugging Face 仓库\n",
922
- " file_path = event.src_path\n",
923
- " file_name:str = os.path.basename(file_path)\n",
924
- " print(file_name)\n",
925
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
926
- " print(file_name,'>>','huggingface')\n",
927
- " try:\n",
928
- " self.api.upload_file(\n",
929
- " path_or_fileobj=file_path,\n",
930
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
931
- " repo_id=self.repo_id,\n",
932
- " repo_type=self.repo_type,\n",
933
- " )\n",
934
- " except IOError as error:\n",
935
- " print(error)\n",
936
- "\n",
937
- " def on_deleted(self, event):\n",
938
- " if not event.is_directory:\n",
939
- " # 从 Hugging Face 仓库删除文件\n",
940
- " file_path = event.src_path\n",
941
- " file_name = os.path.basename(file_path)\n",
942
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
943
- " try:\n",
944
- " self.api.delete_file(\n",
945
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
946
- " repo_id=self.repo_id,\n",
947
- " repo_type=self.repo_type,\n",
948
- " )\n",
949
- " except IOError as error:\n",
950
- " print(error)\n",
951
- "\n",
952
- " def on_modified(self, event):\n",
953
- " if not event.is_directory:\n",
954
- " # 更新 Hugging Face 仓库中的文件\n",
955
- " file_path = event.src_path\n",
956
- " file_name = os.path.basename(file_path)\n",
957
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
958
- " try:\n",
959
- " self.api.upload_file(\n",
960
- " path_or_fileobj=file_path,\n",
961
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
962
- " repo_id=self.repo_id,\n",
963
- " repo_type=self.repo_type,\n",
964
- " )\n",
965
- " except IOError as error:\n",
966
- " print(error)\n",
967
- "\n",
968
- " def on_moved(self, event):\n",
969
- " if not event.is_directory:\n",
970
- " file_path = event.dest_path\n",
971
- " file_name = os.path.basename(file_path)\n",
972
- " if file_name[file_name.rindex('.'):] not in ['.png','.jpg','.txt','.webp','.jpeg']: return\n",
973
- " if event.dest_path.startswith(self.directory_to_watch):\n",
974
- " try:\n",
975
- " self.api.upload_file(\n",
976
- " path_or_fileobj=file_path,\n",
977
- " path_in_repo=file_path.replace(self.directory_to_watch,''),\n",
978
- " repo_id=self.repo_id,\n",
979
- " repo_type=self.repo_type,\n",
980
- " )\n",
981
- " except IOError as error:\n",
982
- " print(error)\n",
983
- "\n",
984
- " api = HfApi()\n",
985
- " \n",
986
- " if not directory_to_watch:\n",
987
- " directory_to_watch = f'{_install_path}/{_ui_dir_name}/log'\n",
988
- " # 创建观察者对象并注册文件变化处理程序\n",
989
- " event_handler = FileChangeHandler(api,repo_id,repo_type,directory_to_watch)\n",
990
- " observer = Observer()\n",
991
- " observer.schedule(event_handler, directory_to_watch, recursive=True)\n",
992
- "\n",
993
- " # 启动观察者\n",
994
- " observer.name = \"solo_directory_to_watch\"\n",
995
- " print(f'启动收藏图片文件夹监听,并自动同步到 huggingface {repo_type} : {repo_id}')\n",
996
- " observer.start()"
997
- ]
998
- },
999
- {
1000
- "cell_type": "markdown",
1001
- "metadata": {
1002
- "id": "sswa04veLCtE"
1003
- },
1004
- "source": [
1005
- "## 工具函数\n",
1006
- "**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n",
1007
- "\n",
1008
- "---"
1009
- ]
1010
- },
1011
- {
1012
- "cell_type": "code",
1013
- "execution_count": null,
1014
- "metadata": {
1015
- "_kg_hide-input": true,
1016
- "trusted": true
1017
- },
1018
- "outputs": [],
1019
- "source": [
1020
- "\n",
1021
- "def zipPath(path:str,zipName:str,format='tar'):\n",
1022
- " if path.startswith('$install_path'):\n",
1023
- " path = path.replace('$install_path',_install_path)\n",
1024
- " if path.startswith('$output_path'):\n",
1025
- " path = path.replace('$install_path',_output_path)\n",
1026
- " if not path.startswith('/'):\n",
1027
- " path = f'{_install_path}/{_ui_dir_name}/{path}'\n",
1028
- " if Path(path).exists():\n",
1029
- " if 'tar' == format:\n",
1030
- " run(f'tar -cf {_output_path}/'+ zipName +'.tar -C '+ path +' . ')\n",
1031
- " elif 'gz' == format:\n",
1032
- " run(f'tar -czf {_output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')\n",
1033
- " return\n",
1034
- " print('指定的目录不存在:'+path)\n",
1035
- " \n",
1036
- "def get_folder_list(directory:str): \n",
1037
- " folder_list = [] \n",
1038
- " for item in os.listdir(directory): \n",
1039
- " if os.path.isdir(os.path.join(directory, item)): \n",
1040
- " folder_list.append(item) \n",
1041
- " return folder_list\n",
1042
- "\n",
1043
- "def read_text_file(file_path:str):\n",
1044
- " if not Path(file_path).exists(): return ''\n",
1045
- " with open(file_path,\"r\") as f:\n",
1046
- " text = file.read()\n",
1047
- " if text: return text.strip()\n",
1048
- " return ''"
1049
- ]
1050
- },
1051
- {
1052
- "cell_type": "markdown",
1053
- "metadata": {},
1054
- "source": [
1055
- "## 内网穿透\n",
1056
- "\n",
1057
- "---"
1058
- ]
1059
- },
1060
- {
1061
- "cell_type": "code",
1062
- "execution_count": null,
1063
- "metadata": {
1064
- "_kg_hide-input": true,
1065
- "_kg_hide-output": true,
1066
- "id": "coqQvTSLLCtE",
1067
- "trusted": true
1068
- },
1069
- "outputs": [],
1070
- "source": [
1071
- "def printUrl(url,name=''):\n",
1072
- " print(f'{name} 访问地址:{url}')\n",
1073
- " for key in sorted(_proxy_path.keys(), key=len)[::-1]:\n",
1074
- " print(f'{name} 本地服务:{_proxy_path[key]} 访问地址:{url}{key}')\n",
1075
- "# ngrok\n",
1076
- "def startNgrok(ngrokToken:str,ngrokLocalPort:int):\n",
1077
- " if not is_installed('pyngrok'):\n",
1078
- " run('pip install pyngrok')\n",
1079
- " from pyngrok import conf, ngrok\n",
1080
- " try:\n",
1081
- " conf.get_default().auth_token = ngrokToken\n",
1082
- " conf.get_default().monitor_thread = False\n",
1083
- " ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n",
1084
- " url = ''\n",
1085
- " if len(ssh_tunnels) == 0:\n",
1086
- " ssh_tunnel = ngrok.connect(ngrokLocalPort)\n",
1087
- " url = ssh_tunnel.public_url\n",
1088
- " print('ngrok 访问地址:'+ssh_tunnel.public_url)\n",
1089
- " else:\n",
1090
- " print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n",
1091
- " url = ssh_tunnels[0].public_url\n",
1092
- " printUrl(url,'ngrok')\n",
1093
- " def auto_request_ngrok():\n",
1094
- " if url:\n",
1095
- " while(_runing):\n",
1096
- " time.sleep(60*1)\n",
1097
- " try:\n",
1098
- " res = requests.get(url+'/',headers={\"ngrok-skip-browser-warning\" : \"1\"},timeout=10)\n",
1099
- " except:\n",
1100
- " ''\n",
1101
- " # print('自动调用ngrok链接以保存链接不会断开',res.status_code)\n",
1102
- "\n",
1103
- " # threading.Thread(target = auto_request_ngrok,daemon=True,name='solo_auto_request_ngrok').start()\n",
1104
- " except:\n",
1105
- " print('启动ngrok出错')\n",
1106
- " \n",
1107
- "def startFrpc(name,configFile):\n",
1108
- " if not Path(f'{_install_path}/frpc/frpc').exists():\n",
1109
- " installFrpExe()\n",
1110
- " if freefrp_url:\n",
1111
- " printUrl(freefrp_url,'freefrp')\n",
1112
- " echoToFile(f'''\n",
1113
- "cd {_install_path}/frpc/\n",
1114
- "{_install_path}/frpc/frpc {configFile}\n",
1115
- "''',f'{_install_path}/frpc/start.sh')\n",
1116
- " get_ipython().system(f'''bash {_install_path}/frpc/start.sh''')\n",
1117
- " \n",
1118
- "def installFrpExe():\n",
1119
- " if _useFrpc:\n",
1120
- " print('安装frpc')\n",
1121
- " run(f'mkdir -p {_install_path}/frpc')\n",
1122
- " if Path(frpcExePath).exists():\n",
1123
- " run(f'cp -f -n {frpcExePath} {_install_path}/frpc/frpc')\n",
1124
- " else:\n",
1125
- " run(f'wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O {_install_path}/frpc/frpc')\n",
1126
- " \n",
1127
- " for ssl in frpcSSLFFlies:\n",
1128
- " if Path(ssl).exists():\n",
1129
- " run(f'cp -f -n {ssl}/* {_install_path}/frpc/')\n",
1130
- " run(f'chmod +x {_install_path}/frpc/frpc')\n",
1131
- " run(f'{_install_path}/frpc/frpc -v')\n",
1132
- "\n",
1133
- "def startProxy():\n",
1134
- " if _useNgrok:\n",
1135
- " startNgrok(ngrokToken,_server_port)\n",
1136
- " if _useFrpc:\n",
1137
- " startFrpc('frpc_proxy',frpcStartArg)"
1138
- ]
1139
- },
1140
- {
1141
- "cell_type": "markdown",
1142
- "metadata": {},
1143
- "source": [
1144
- "## NGINX 反向代理\n",
1145
- "\n",
1146
- "---"
1147
- ]
1148
- },
1149
- {
1150
- "cell_type": "code",
1151
- "execution_count": null,
1152
- "metadata": {
1153
- "_kg_hide-input": true,
1154
- "_kg_hide-output": true,
1155
- "trusted": true
1156
- },
1157
- "outputs": [],
1158
- "source": [
1159
- "\n",
1160
- "# nginx 反向代理配置文件\n",
1161
- "def localProxy():\n",
1162
- " def getProxyLocation(subPath:str, localServer:str):\n",
1163
- " return '''\n",
1164
- " location '''+ subPath +'''\n",
1165
- " {\n",
1166
- " proxy_pass '''+ localServer +''';\n",
1167
- " \n",
1168
- " client_max_body_size 1000m;\n",
1169
- " proxy_set_header Host $http_host;\n",
1170
- " proxy_set_header X-Real-IP $remote_addr;\n",
1171
- " proxy_set_header X-Real-Port $remote_port;\n",
1172
- " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",
1173
- " proxy_set_header X-Forwarded-Proto $scheme;\n",
1174
- " proxy_set_header X-Forwarded-Host $host;\n",
1175
- " proxy_set_header X-Forwarded-Port $server_port;\n",
1176
- " proxy_set_header REMOTE-HOST $remote_addr;\n",
1177
- " proxy_connect_timeout 3000s;\n",
1178
- " proxy_send_timeout 3000s;\n",
1179
- " proxy_read_timeout 3000s;\n",
1180
- " proxy_http_version 1.1;\n",
1181
- " proxy_set_header Upgrade $http_upgrade;\n",
1182
- " proxy_set_header Connection 'upgrade';\n",
1183
- " add_header Access-Control-Allow-Origin * always;\n",
1184
- " add_header Access-Control-Allow-Headers *;\n",
1185
- " add_header Access-Control-Allow-Methods \"GET, POST, PUT, OPTIONS\";\n",
1186
- " }\n",
1187
- " \n",
1188
- " '''\n",
1189
- " \n",
1190
- " conf = '''\n",
1191
- "server\n",
1192
- "{\n",
1193
- " listen '''+str(_server_port)+''';\n",
1194
- " listen [::]:'''+str(_server_port)+''';\n",
1195
- " server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n",
1196
- " \n",
1197
- " fastcgi_send_timeout 3000s;\n",
1198
- " fastcgi_read_timeout 3000s;\n",
1199
- " fastcgi_connect_timeout 3000s;\n",
1200
- " \n",
1201
- " if ($request_method = OPTIONS) {\n",
1202
- " return 200;\n",
1203
- " }\n",
1204
- " \n",
1205
- " '''+ ''.join([getProxyLocation(key,_proxy_path[key]) for key in sorted(_proxy_path.keys(), key=len)[::-1]]) +'''\n",
1206
- "}\n",
1207
- "'''\n",
1208
- " echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n",
1209
- " if not check_service('localhost',_server_port):\n",
1210
- " run(f'''nginx -c /etc/nginx/nginx.conf''')\n",
1211
- " run(f'''nginx -s reload''')"
1212
- ]
1213
- },
1214
- {
1215
- "cell_type": "markdown",
1216
- "metadata": {},
1217
- "source": [
1218
- "## 线程清理工具\n",
1219
- "\n",
1220
- "---\n",
1221
- "\n",
1222
- "清理线程名以 solo_ 开头的所有线程"
1223
- ]
1224
- },
1225
- {
1226
- "cell_type": "code",
1227
- "execution_count": null,
1228
- "metadata": {
1229
- "_kg_hide-input": true,
1230
- "trusted": true
1231
- },
1232
- "outputs": [],
1233
- "source": [
1234
- "import inspect\n",
1235
- "import ctypes\n",
1236
- "\n",
1237
- "def _async_raise(tid, exctype):\n",
1238
- " \"\"\"raises the exception, performs cleanup if needed\"\"\"\n",
1239
- " tid = ctypes.c_long(tid)\n",
1240
- " if not inspect.isclass(exctype):\n",
1241
- " exctype = type(exctype)\n",
1242
- " res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n",
1243
- " if res == 0:\n",
1244
- " raise ValueError(\"invalid thread id\")\n",
1245
- " elif res != 1:\n",
1246
- " # \"\"\"if it returns a number greater than one, you're in trouble,\n",
1247
- " # and you should call it again with exc=NULL to revert the effect\"\"\"\n",
1248
- " ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n",
1249
- " raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n",
1250
- "\n",
1251
- "def stop_thread(thread):\n",
1252
- " _async_raise(thread.ident, SystemExit)\n",
1253
- "\n",
1254
- "def stop_solo_threads():\n",
1255
- " global _runing\n",
1256
- " _runing = False\n",
1257
- " # 获取当前所有活动的线程\n",
1258
- " threads = threading.enumerate()\n",
1259
- " # 关闭之前创建的子线程\n",
1260
- " for thread in threads:\n",
1261
- " if thread.name.startswith('solo_'):\n",
1262
- " print(f'结束线程:{thread.name}')\n",
1263
- " try:\n",
1264
- " stop_thread(thread)\n",
1265
- " except socket.error:\n",
1266
- " print(f'结束线程:{thread.name} 执行失败')"
1267
- ]
1268
- },
1269
- {
1270
- "cell_type": "markdown",
1271
- "metadata": {
1272
- "id": "Ve3p8oOkLCtE"
1273
- },
1274
- "source": [
1275
- "# webui 安装和配置函数\n",
1276
- "---"
1277
- ]
1278
- },
1279
- {
1280
- "cell_type": "code",
1281
- "execution_count": null,
1282
- "metadata": {
1283
- "_kg_hide-input": true,
1284
- "id": "GTjyBJihLCtE",
1285
- "trusted": true
1286
- },
1287
- "outputs": [],
1288
- "source": [
1289
- "envInstalled=False\n",
1290
- "quickStart = False\n",
1291
- "#安装\n",
1292
- "def install():\n",
1293
- " print('安装')\n",
1294
- " os.chdir(f'''{_install_path}''')\n",
1295
- " run(f'''git lfs install''')\n",
1296
- " run(f'''git config --global credential.helper store''')\n",
1297
- " for requirement in requirements:\n",
1298
- " run(f'pip install {requirement}')\n",
1299
- " if _reLoad:\n",
1300
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}''')\n",
1301
- " if Path(f\"{_ui_dir_name}\").exists():\n",
1302
- " os.chdir(f'''{_install_path}/{_ui_dir_name}/''')\n",
1303
- " run(f'''git checkout .''')\n",
1304
- " run(f'''git pull''')\n",
1305
- " else:\n",
1306
- " run(f'''git clone --recursive {_sd_git_repo} {_ui_dir_name}''')\n",
1307
- " if not Path(f'''{_install_path}/{_ui_dir_name}''').exists():\n",
1308
- " print('sd-webui主程序安装失败,请检查 sd_git_repo 配置的值是否正确')\n",
1309
- " sys.exit(0)\n",
1310
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1311
- " print('安装 完成')\n",
1312
- "\n",
1313
- "# 链接输出目录\n",
1314
- "def link_dir():\n",
1315
- " print('链接输出目录')\n",
1316
- " # 链接图片输出目录\n",
1317
- " run(f'''mkdir -p {_output_path}/outputs''')\n",
1318
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/outputs''')\n",
1319
- " run(f'''ln -s -r {_output_path}/outputs {_install_path}/{_ui_dir_name}/''')\n",
1320
- " # 输出收藏目录\n",
1321
- " run(f'''mkdir -p {_output_path}/log''')\n",
1322
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/log''')\n",
1323
- " run(f'''ln -s -r {_output_path}/log {_install_path}/{_ui_dir_name}/''')\n",
1324
- " # 链接训练输出目录 文件夹链接会导致功能不能用\n",
1325
- " run(f'''rm -rf {_install_path}/{_ui_dir_name}/textual_inversion''')\n",
1326
- " run(f'''mkdir -p {_output_path}/textual_inversion/''')\n",
1327
- " run(f'''ln -s -r {_output_path}/textual_inversion {_install_path}/{_ui_dir_name}/''')\n",
1328
- " print('链接输出目录 完成') \n",
1329
- "\n",
1330
- "def install_optimizing():\n",
1331
- " run('add-apt-repository ppa:deadsnakes/ppa -y')\n",
1332
- " run('apt update -y')\n",
1333
- " run('apt install nginx -y')\n",
1334
- " # run('apt install python3.10 -y')\n",
1335
- " \n",
1336
- "#安装依赖\n",
1337
- "def install_dependencies():\n",
1338
- " print('安装需要的python环境')\n",
1339
- " global envInstalled\n",
1340
- " global venvPath\n",
1341
- " if Path(f'{_install_path}/{_ui_dir_name}/venv').exists():\n",
1342
- " print('跳过安装python环境')\n",
1343
- " envInstalled = True\n",
1344
- " return\n",
1345
- " \n",
1346
- " if quickStart and Path(venvPath).exists():\n",
1347
- " print('解压环境')\n",
1348
- " mkdirs(f'{_install_path}/{_ui_dir_name}/venv')\n",
1349
- "# run('python3.10 -m venv venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1350
- " run(f'tar -xf {venvPath} -C ./venv',cwd=f'{_install_path}/{_ui_dir_name}')\n",
1351
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/pip*')\n",
1352
- " run(f'rm -f {_install_path}/{_ui_dir_name}/venv/bin/python*')\n",
1353
- " venv.create(f'{_install_path}/{_ui_dir_name}/venv')\n",
1354
- " if not Path(f'{_install_path}/{_ui_dir_name}/venv/bin/pip').exists():\n",
1355
- " run('curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py')\n",
1356
- " run(f'{_install_path}/{_ui_dir_name}/venv/bin/python3 get-pip.py')\n",
1357
- " \n",
1358
- " if not quickStart:\n",
1359
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -V''')\n",
1360
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip -V''')\n",
1361
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install torch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 --index-url https://download.pytorch.org/whl/cu121''')\n",
1362
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install xformers==0.0.27''')\n",
1363
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install -r requirements_versions.txt''')\n",
1364
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install spandrel==0.3.0''')\n",
1365
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install opencv-python''')\n",
1366
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pydantic==1.10.15''')\n",
1367
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install transformers -U''')\n",
1368
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install llama-cpp-python''')\n",
1369
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python -m pip install pytorch_lightning==2.3.3 torchsde==0.2.6 spandrel==0.3.4''')\n",
1370
- " \n",
1371
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install open-clip-torch -U''')\n",
1372
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install protobuf==4.25.8''')\n",
1373
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install blendmodes==2022''')\n",
1374
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install Pillow==9.5.0''')\n",
1375
- " run(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr''')\n",
1376
- " \n",
1377
- " get_ipython().system(f'''{_install_path}/{_ui_dir_name}/venv/bin/python3 -m pip install basicsr''')\n",
1378
- "\n",
1379
- " envInstalled = True\n",
1380
- " print('安装需要的python环境 完成')\n",
1381
- " \n",
1382
- "# 个性化配置 \n",
1383
- "def use_config():\n",
1384
- " print('使用自定义配置 包括tag翻译 \\n')\n",
1385
- " run(f'''mkdir -p {_install_path}/temp''')\n",
1386
- " run(f'git clone {_sd_config_git_repu} sd-configs',cwd=f'{_install_path}/temp')\n",
1387
- " run(f'cp -r -f -n {_install_path}/temp/sd-configs/dist/* {_install_path}/{_ui_dir_name}')\n",
1388
- " if not Path(_ui_config_file).exists() and _ui_config_file != 'ui-config.json': # ui配置文件\n",
1389
- " run(f'''mkdir -p {_ui_config_file[:_ui_config_file.rfind('/')]}''')\n",
1390
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/ui-config.json {_ui_config_file}')\n",
1391
- " if not Path(_setting_file).exists() and _setting_file != 'config.json': # 设置配置文件\n",
1392
- " run(f'''mkdir -p {_setting_file[:_setting_file.rfind('/')]}''')\n",
1393
- " run(f'cp -f -n {_install_path}/{_ui_dir_name}/config.json {_setting_file}')\n",
1394
- "\n",
1395
- "def copy_last_log_to_images():\n",
1396
- " if not Path(f'{_install_path}/{_ui_dir_name}/log/images').exists(): mkdirs(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1397
- " print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')\n",
1398
- " img_list = os.listdir(f'{_install_path}/{_ui_dir_name}/log/images')\n",
1399
- " last_img_path = ''\n",
1400
- " last_img_num = 0\n",
1401
- " for img in img_list:\n",
1402
- " if re.findall(r'^\\d+-',str(img)):\n",
1403
- " num = int(re.findall(r'^\\d+-',str(img))[0][:-1])\n",
1404
- " if num > last_img_num:\n",
1405
- " last_img_path = img\n",
1406
- " last_img_num = num\n",
1407
- " \n",
1408
- " if not last_img_path: return\n",
1409
- " \n",
1410
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images')\n",
1411
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/txt2img-images''')\n",
1412
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/txt2img-images/''')\n",
1413
- " \n",
1414
- " print(f'{_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images')\n",
1415
- " run(f'''mkdir -p {_install_path}/{_ui_dir_name}/outputs/img2img-images''')\n",
1416
- " run(f'''cp -f {_install_path}/{_ui_dir_name}/log/images/{last_img_path} {_install_path}/{_ui_dir_name}/outputs/img2img-images/''')\n",
1417
- " \n",
1418
- "def start_webui(i):\n",
1419
- " # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n",
1420
- " print(i,'--port',str(_server_port+1+i))\n",
1421
- " if i>0:\n",
1422
- " print(f'使用第{i+1}张显卡启动第{i+1}个服务,通过frpc或nrgok地址后加{_sub_path[i]}进行访问')\n",
1423
- "\n",
1424
- " restart_times = 0\n",
1425
- " last_restart_time = time.time()\n",
1426
- " while _runing:\n",
1427
- " os.chdir(f'{_install_path}/{_ui_dir_name}')\n",
1428
- " root_path = _sub_path[i]\n",
1429
- " if root_path.endswith('/'): root_path = root_path[:-1]\n",
1430
- " if torch.cuda.device_count() == 2 and not _multi_case:\n",
1431
- " os.environ['CUDA_VISIBLE_DEVICES']='0,1'\n",
1432
- " get_ipython().system(f'''venv/bin/python3 launch.py --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1433
- " else: \n",
1434
- " get_ipython().system(f'''venv/bin/python3 launch.py --device-id={i} --port {str(_server_port+1+i)} --subpath={_sub_path[i]}''')\n",
1435
- " print('10秒后重启服务')\n",
1436
- " if time.time() - last_restart_time < 60:\n",
1437
- " restart_times = restart_times + 1\n",
1438
- " else:\n",
1439
- " restart_times = 0\n",
1440
- " last_restart_time = time.time()\n",
1441
- " if restart_times >3 :\n",
1442
- " # 如果180秒内重启了3此,将不再自动重启\n",
1443
- " break\n",
1444
- " time.sleep(10)\n",
1445
- " \n",
1446
- "# 启动\n",
1447
- "def start():\n",
1448
- " print('启动webui')\n",
1449
- " os.chdir(f'''{_install_path}/{_ui_dir_name}''')\n",
1450
- " args = ''\n",
1451
- " if _ui_config_file is not None and _ui_config_file != '' and Path(_ui_config_file).exists(): # ui配置文件\n",
1452
- " args += ' --ui-config-file=' + _ui_config_file\n",
1453
- " if _setting_file is not None and _setting_file != '' and Path(_setting_file).exists(): # 设置配置文件\n",
1454
- " args += ' --ui-settings-file=' + _setting_file\n",
1455
- " args += ' ' + otherArgs\n",
1456
- " os.environ['COMMANDLINE_ARGS']=args\n",
1457
- " run(f'''echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS''')\n",
1458
- " os.environ['REQS_FILE']='requirements_versions.txt'\n",
1459
- "\n",
1460
- " with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:\n",
1461
- " for i in range(torch.cuda.device_count() if _multi_case else 1):\n",
1462
- " executor.submit(start_webui,i)\n",
1463
- " while _runing and not check_service('localhost',str(_server_port+1+i)): # 当当前服务启动完成才允许退出此次循环\n",
1464
- " time.sleep(5)\n",
1465
- " if not _runing: break\n",
1466
- " time.sleep(10)"
1467
- ]
1468
- },
1469
- {
1470
- "cell_type": "markdown",
1471
- "metadata": {
1472
- "id": "qLvsk8ByLCtF"
1473
- },
1474
- "source": [
1475
- "# 入口函数\n",
1476
- "---"
1477
- ]
1478
- },
1479
- {
1480
- "cell_type": "code",
1481
- "execution_count": null,
1482
- "metadata": {
1483
- "_kg_hide-input": true,
1484
- "id": "IOKjaMlcLCtF",
1485
- "trusted": true
1486
- },
1487
- "outputs": [],
1488
- "source": [
1489
- "\n",
1490
- "# 启动非webui相关的的内容,加快启动速度\n",
1491
- "def main():\n",
1492
- " global envInstalled\n",
1493
- " global huggingface_is_init\n",
1494
- " global _runing\n",
1495
- " init_start_conf()\n",
1496
- " stop_solo_threads()\n",
1497
- " print('启动...')\n",
1498
- " startTicks = time.time()\n",
1499
- " time.sleep(5)\n",
1500
- " _runing = True\n",
1501
- " isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n",
1502
- " _proxy_path[_sub_path[0]] = f'http://127.0.0.1:{_server_port+1}/'\n",
1503
- " _proxy_path[_sub_path[1]] = f'http://127.0.0.1:{_server_port+2}/'\n",
1504
- " proxy_thread = threading.Thread(target = startProxy, daemon=True, name='solo_startProxy')\n",
1505
- " proxy_thread.start()\n",
1506
- " if isInstall is False or _reLoad: \n",
1507
- " print('安装运行环境')\n",
1508
- " os.environ['MPLBACKEND'] = 'Agg'\n",
1509
- " install()\n",
1510
- " link_dir()\n",
1511
- " init_huggingface()\n",
1512
- " install_optimizing()\n",
1513
- " if not _skip_webui:\n",
1514
- " threading.Thread(target = install_dependencies,daemon=True,name='solo_install_dependencies').start()\n",
1515
- " else: envInstalled = True\n",
1516
- " link_or_download_flie(replace_path(_async_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1517
- " base_path=f'{_install_path}/{_ui_dir_name}')\n",
1518
- " if huggingface_is_init:\n",
1519
- " threading.Thread(target = download__huggingface_repo,daemon=True,\n",
1520
- " args=([_huggingface_repo]),\n",
1521
- " kwargs={\"callback\":copy_last_log_to_images},\n",
1522
- " name='solo_download__huggingface_repo').start()\n",
1523
- " \n",
1524
- " link_or_download_flie(replace_path(_before_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1525
- " base_path=f'{_install_path}/{_ui_dir_name}',is_await=True,sync=True)\n",
1526
- " t = 0\n",
1527
- " while _runing and not envInstalled:\n",
1528
- " if t%10==0:\n",
1529
- " print('等待python环境安装...')\n",
1530
- " t = t+1\n",
1531
- " time.sleep(1)\n",
1532
- " use_config()\n",
1533
- " os.environ['IsInstall'] = 'True'\n",
1534
- " else:\n",
1535
- " envInstalled = True\n",
1536
- " localProxy()\n",
1537
- " link_or_download_flie(replace_path(_before_start_sync_downloading), _link_instead_of_copy=_link_instead_of_copy,\n",
1538
- " base_path=f'{_install_path}/{_ui_dir_name}',sync=True)\n",
1539
- " if init_huggingface():\n",
1540
- " start_sync_log_to_huggingface(_huggingface_repo)\n",
1541
- " ticks = time.time()\n",
1542
- " _on_before_start()\n",
1543
- " print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n",
1544
- " if _skip_webui:\n",
1545
- " print('跳过webui启动')\n",
1546
- " proxy_thread.join()\n",
1547
- " else:\n",
1548
- " start()\n"
1549
- ]
1550
- },
1551
- {
1552
- "cell_type": "markdown",
1553
- "metadata": {
1554
- "id": "0oaCRs2gLCtF"
1555
- },
1556
- "source": [
1557
- "# 执行区域\n",
1558
- "---"
1559
- ]
1560
- },
1561
- {
1562
- "cell_type": "code",
1563
- "execution_count": null,
1564
- "metadata": {
1565
- "_kg_hide-output": true,
1566
- "id": "O3DR0DWHLCtF",
1567
- "scrolled": true,
1568
- "trusted": true
1569
- },
1570
- "outputs": [],
1571
- "source": [
1572
- "# 启动\n",
1573
- "# _reLoad = True\n",
1574
- "# hidden_console_info = False\n",
1575
- "# run_by_none_device = True\n",
1576
- "# show_shell_info = True\n",
1577
- "\n",
1578
- "print(f'当前sd的安装路径是:{_install_path}/{_ui_dir_name}')\n",
1579
- "print(f'当前图片保存路径是:{_output_path}')\n",
1580
- "print(f'当前数据集路径是:{_input_path}')\n",
1581
- "\n",
1582
- "print(update_desc)\n",
1583
- "\n",
1584
- "if _skip_start:\n",
1585
- " print('已跳过自动启动,可手动执行 main() 进行启动。')\n",
1586
- " print('''推荐的启动代码:\n",
1587
- "try:\n",
1588
- " check_gpu() # 检查是否存在gpu\n",
1589
- " main()\n",
1590
- "except KeyboardInterrupt:\n",
1591
- " stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)\n",
1592
- " ''')\n",
1593
- "else:\n",
1594
- " try:\n",
1595
- " check_gpu()\n",
1596
- " main()\n",
1597
- " except KeyboardInterrupt:\n",
1598
- " stop_solo_threads()"
1599
- ]
1600
- }
1601
- ],
1602
- "metadata": {
1603
- "kaggle": {
1604
- "accelerator": "nvidiaTeslaT4",
1605
- "dataSources": [
1606
- {
1607
- "datasetId": 2716934,
1608
- "sourceId": 6167400,
1609
- "sourceType": "datasetVersion"
1610
- },
1611
- {
1612
- "datasetId": 3654544,
1613
- "sourceId": 6346544,
1614
- "sourceType": "datasetVersion"
1615
- },
1616
- {
1617
- "datasetId": 2962375,
1618
- "sourceId": 6720235,
1619
- "sourceType": "datasetVersion"
1620
- },
1621
- {
1622
- "datasetId": 3074484,
1623
- "sourceId": 6817788,
1624
- "sourceType": "datasetVersion"
1625
- }
1626
- ],
1627
- "isGpuEnabled": true,
1628
- "isInternetEnabled": true,
1629
- "language": "python",
1630
- "sourceType": "notebook"
1631
- },
1632
- "kernelspec": {
1633
- "display_name": "Python 3",
1634
- "language": "python",
1635
- "name": "python3"
1636
- },
1637
- "language_info": {
1638
- "codemirror_mode": {
1639
- "name": "ipython",
1640
- "version": 3
1641
- },
1642
- "file_extension": ".py",
1643
- "mimetype": "text/x-python",
1644
- "name": "python",
1645
- "nbconvert_exporter": "python",
1646
- "pygments_lexer": "ipython3",
1647
- "version": "3.10.12"
1648
- }
1649
- },
1650
- "nbformat": 4,
1651
- "nbformat_minor": 4
1652
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
sdwui-start.ipynb CHANGED
@@ -1 +1 @@
1
- {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 这只是一个完整项目的一部分 不能运行的 \n- 可以从这个地址运行 [点击打开](https://www.kaggle.com/viyiviyi/sdwui-before)\n---","metadata":{"id":"6zE2QeUKLCtC"}},{"cell_type":"code","source":"print('''\n路径说明\n* 可以使用 $install_path 或 {install_path} 来访问安装目录,写在字符串内也会生效\n* $output_path 或 {output_path} 可以访问输出目录\n* $input_path 或 {input_path} 可以访问输入目录 在kaggle是数据集根目录\n* 如果链接了谷歌云盘,将会在云盘根目录创建 sdwebui 的文件夹,文件夹内的 Input 目录将会作为 输入目录 Output 将会作为输出目录\n\n发布地址 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai\n\n更新日志\n*\n* 23-07-26\n* 增加可隐藏启动时的不重要信息 通过增加配置 [hidden_console_info = True] 开启\n* 增加可自定义下载或链接文件到指定目录\n* 配置方式:查看 https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai 的 [其他文件列表]\n*\n* 23-07-22\n* 更新了可自动同步收藏目录到 https://huggingface.co/ 的功能\n* 可通过增加配置项 huggingface_token = \"token\" 和 huggingface_repo = “仓库id” 后使用此功能\n*\n* 23-07-18 \n* 如果有两个GPU 第二个GPU将会启动api服务,可用api的方式调用,和webui互相独立,绘图时不会导致另外一边卡顿\n* 通过/1/作为base url来访问这个api\n* 没有启动两个webui是因为,很大概率爆内存\n''')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\nimport os\nimport time\nimport re\nimport subprocess\nimport threading\nimport sys\nimport socket\nimport torch\nfrom typing import List\n\n# 检查gpu是否存在\nif torch.cuda.device_count() == 0:\n raise Exception('当前环境没有GPU')\n\ninstall_path=f\"{os.environ['HOME']}/sdwebui\" # 安装目录\noutput_path=f\"{os.environ['HOME']}/sdwebui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\ninput_path = '/kaggle/input' # 输入目录\n\ngoogle_drive = '' \n# 连接谷歌云\ntry:\n if useGooglrDrive:\n from google.colab import drive\n drive.mount(f'~/google_drive')\n google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n output_path = f'{google_drive}/sdwebui/Output'\n input_path = f'{google_drive}/sdwebui/Input'\n !mkdir -p {input_path}\n # 设置文件路径\n if setting_file== '/kaggle/working/configs/config.json':\n setting_file = os.path.join(output_path,'configs/config.json')\n if ui_config_file == '/kaggle/working/configs/ui-config.json':\n ui_config_file = os.path.join(output_path,'configs/ui-config.json')\n print('''\n已经链接到谷歌云盘\n云盘根目录/sdwebui/Output 被链接为输出目录,图片和设置文件将会保存在此文件夹\n云盘根目录/sdwebui/Input 被链接为输入目录,环境变量名是 $input_path\n ''')\nexcept:\n useGooglrDrive = False\n\n!mkdir -p {install_path}\n!mkdir -p {output_path}\n\nos.environ['install_path'] = install_path\nos.environ['output_path'] = output_path\nos.environ['google_drive'] = google_drive\nos.environ['input_path'] = input_path\n\ndef replace_path(input_str:str):\n return input_str.replace('$install_path',install_path)\\\n .replace('{install_path}',install_path)\\\n .replace('$input_path',input_path)\\\n .replace('{input_path}',input_path)\\\n .replace('$output_path',output_path)\\\n .replace('{output_path}',output_path)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 模型目录 文件名称:链接的方式指定文件名\nmodelDirs = []+[replace_path(item.strip()) for item in 模型列表.split('\\n') if item.strip() ]\n# vae列表\nmodelVaeDirs = []+[replace_path(item.strip()) for item in VAE列表.split('\\n') if item.strip()]\n# 此配置内的目录下所有文件将加载到hypernetworks文件夹\nhypernetworksModelDirs = []+[replace_path(item.strip()) for item in hypernetworks列表.split('\\n') if item.strip()] \n# 此配置内的目录下所有文件将加载到embeddings文件夹\nembeddingsModelDirs = [] +[replace_path(item.strip()) for item in embeddings列表.split('\\n') if item.strip()]\n# 此配置内的目录下所有文件将加载到Lora文件夹\nloraModelDirs = []+[replace_path(item.strip()) for item in Lora列表.split('\\n') if item.strip()] \n\nlyCORISModelDirs = []+[replace_path(item.strip()) for item in LyCORIS列表.split('\\n') if item.strip()] \n# controlNet��件模型列表\ncontrolNetModels=[] +[replace_path(item.strip()) for item in controlNet模型列表.split('\\n') if item.strip()]\n# 插件列表\nextensions=[]+[replace_path(item.strip()) for item in 插件列表.split('\\n') if item.strip()]\n# 配置文件链接\nlinkHypernetworksDir=False # 链接 hypernetworks 目录到输出目录\nlinkEmbeddingsDir=False # 链接 embeddings 目录到输出目录\nlinkTextual_inversionDir=False # 链接 textual_inversion 目录到输出目录 如果需要保存训练过程的产出文件时建议开启\n\nngrokTokenFile = os.path.join(input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\nfrpcConfigFile = os.path.join(input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n# ss证书目录 下载nginx的版本,把pem格式改成crt格式\nfrpcSSLFFlies =[os.path.join(input_path,'configs/koishi_ssl')]+[replace_path(item.strip()) for item in frpSSL文件.split('\\n') if item.strip() ]\n# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\nfrpcExePath = os.path.join(input_path,'utils-tools/frpc')\n# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\notherArgs = ' '.join([replace_path(item.strip()) for item in 参数列表.split('\\n') if item.strip()])\n\nvenvPath = os.path.join(input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n\n# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\nkaggleApiTokenFile = os.path.join(input_path,'configs/kaggle.json')\n\nrequirements = []","metadata":{"_kg_hide-input":true,"id":"i3LhnwYHLCtC","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 这下面的是用于初始化一些值或者环境变量的,轻易别改\nfrpcStartArg = ''\n\nfrp配置文件或配置 = replace_path(frp配置文件或配置)\nngrok配置或文件地址 = replace_path(ngrok配置或文件地址)\n\n!mkdir -p $install_path/configFiles\nif Path(frp配置文件或配置.strip()).exists():\n frpcConfigFile = frp配置文件或配置.strip()\nif not Path(frpcConfigFile).exists(): \n if frp配置文件或配置.strip().startswith('-f'):\n frpcStartArg = frp配置文件或配置.strip()\n else:\n print('没有frpcp配置')\n useFrpc = False\nelse:\n os.system(f'cp -f {frpcConfigFile} {install_path}/configFiles/frpc_webui.ini')\n frpcConfigFile = f'{install_path}/configFiles/frpc_webui.ini'\n os.system(f'sed -i \"s/local_port = .*/local_port = {webuiPort}/g\" {frpcConfigFile}')\n frpcStartArg = f' -c {frpcConfigFile}'\n\nngrokToken=''\nif Path(ngrok配置或文件地址.strip()).exists():\n ngrokTokenFile = ngrok配置或文件地址.strip()\nif Path(ngrokTokenFile).exists():\n with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n ngrokToken = nkfile.readline()\nelif not ngrok配置或文件地址.strip().startswith('/'):\n ngrokToken=ngrok配置或文件地址.strip()\n \nif not Path(venvPath).exists():\n venvPath = os.path.join(input_path,'sd-webui-venv/venv.zip')\n","metadata":{"_kg_hide-input":true,"id":"a_GtG2ayLCtD","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_other_files():\n if '其他文件列表' not in globals():\n return {}\n other_flie_list = [replace_path(item.split('#')[0].strip()) for item in 其他文件列表.split('\\n') if item.strip()]\n other_flie_list_store = {}\n other_flie_list_store_name='default'\n other_flie_list_store_list_cache=[]\n for item in other_flie_list:\n if item.startswith('[') and item.endswith(']'):\n if not other_flie_list_store_name == 'default':\n other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n other_flie_list_store_list_cache = []\n other_flie_list_store_name = item[1:-1]\n else:\n other_flie_list_store_list_cache.append(item)\n other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache\n return other_flie_list_store","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os,sys,io\nsys_sys_stdout = sys.stdout\nclass HiddenPrints:\n def __enter__(self):\n if 'hidden_console_info' not in globals(): return\n if hidden_console_info:\n self._stdout = sys.stdout\n sys.stdout = self._stringio = io.StringIO()\n\n def __exit__(self, *args):\n if 'hidden_console_info' not in globals(): return\n if hidden_console_info:\n sys.stdout = self._stdout","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# kaggle public API\n\n**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n\n---","metadata":{"id":"p0uS-BLULCtD"}},{"cell_type":"code","source":"# 安装kaggle的api token文件\ndef initKaggleConfig():\n if Path('~/.kaggle/kaggle.json').exists():\n return True\n if Path(kaggleApiTokenFile).exists():\n !mkdir -p ~/.kaggle/\n os.system('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n !chmod 600 ~/.kaggle/kaggle.json\n return True\n print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n return False\n\ndef getUserName():\n if not initKaggleConfig(): return\n import kaggle\n return kaggle.KaggleApi().read_config_file()['username']\n\ndef createOrUpdateDataSet(path:str,datasetName:str):\n if not initKaggleConfig(): return\n print('创建或更新数据集 '+datasetName)\n import kaggle\n os.system('mkdir -p $install_path/kaggle_cache')\n os.system('rm -rf $install_path/kaggle_cache/*')\n datasetDirPath = install_path+'/kaggle_cache/'+datasetName\n os.system('mkdir -p '+datasetDirPath)\n os.system('cp -f '+path+' '+datasetDirPath+'/')\n username = getUserName()\n print(\"kaggle username:\"+username)\n datasetPath = username+'/'+datasetName\n datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n print(datasetList)\n if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n os.system('kaggle datasets init -p' + datasetDirPath)\n metadataFile = datasetDirPath+'/dataset-metadata.json'\n os.system('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n os.system('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n os.system('cat '+metadataFile)\n os.system('kaggle datasets create -p '+datasetDirPath)\n print('create database done')\n else:\n kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n print('upload database done')\n\ndef downloadDatasetFiles(datasetName:str,outputPath:str):\n if not initKaggleConfig(): return\n print('下载数据集文件 '+datasetName)\n import kaggle\n username = getUserName()\n datasetPath = username+'/'+datasetName\n datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n if datasetPath not in [str(d) for d in datasetList]:\n return False\n os.system('mkdir -p '+outputPath)\n kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n return True\n\n","metadata":{"_kg_hide-input":true,"id":"m8FJi4j0LCtD","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 同步文件夹到 huggingface\n","metadata":{}},{"cell_type":"code","source":"# 文件夹与 huggingface 同步\nif 'huggingface_token' in locals() and 'huggingface_repo' in locals():\n requirements.append('watchdog')\n requirements.append('huggingface_hub')\n\n\nhuggingface_is_init = False\n\ndef init_huggingface():\n if 'huggingface_token' not in globals() or 'huggingface_repo' not in globals():\n print('请增加配置项 huggingface_token = \"token\" 和 huggingface_repo = “仓库id” 后使用 huggingface 功能')\n return False\n global huggingface_is_init\n from huggingface_hub import HfApi,login,snapshot_download\n token = replace_path(huggingface_token)\n if Path(token).exists():\n with open(token,encoding = \"utf-8\") as nkfile:\n token = nkfile.readline()\n if not token.startswith('hf_'):\n print('huggingface token 不正确,请将 token 或 仅存放token 的txt文件路径填入 huggingface_token 配置')\n return False\n login(token)\n huggingface_is_init = True\n return True\n\n\ndef download_huggingface_repo(repo_id:str,dist_directory:str=None,repo_type='dataset',callback=None):\n if not huggingface_is_init:\n print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n \n if not dist_directory:\n dist_directory = f'{install_path}/stable-diffusion-webui/log'\n \n from huggingface_hub import HfApi,login,snapshot_download\n \n api = HfApi()\n \n print('下载收藏的图片')\n snapshot_download(repo_id = huggingface_repo,\n local_dir = dist_directory,\n local_dir_use_symlinks = \"auto\",\n token=True,\n repo_type=repo_type\n )\n if callback:\n callback()\n\ndef start_sync_log_to_huggingface(repo_id:str,directory_to_watch:str=None,repo_type='dataset'):\n if not huggingface_is_init:\n print('huggingface 相关功能未初始化 请调用 init_huggingface() 初始化')\n \n from watchdog.observers import Observer\n from watchdog.events import FileSystemEventHandler\n from huggingface_hub import HfApi,login,snapshot_download\n \n # 配置监视的目录和 Hugging Face 仓库信息\n class FileChangeHandler(FileSystemEventHandler):\n def __init__(self, api, repo_id, repo_type):\n self.api = api\n self.repo_id = repo_id\n self.repo_type = repo_type\n def on_created(self, event):\n if not event.is_directory:\n # 上传新文件到 Hugging Face 仓库\n file_path = event.src_path\n file_name = os.path.basename(file_path)\n if file_name[-4:] not in ['.png','.jpg','.txt']: return\n try:\n self.api.upload_file(\n path_or_fileobj=file_path,\n path_in_repo=file_path.replace(directory_to_watch,''),\n repo_id=self.repo_id,\n repo_type=self.repo_type,\n )\n except Error as error:\n print(error)\n\n def on_deleted(self, event):\n if not event.is_directory:\n # 从 Hugging Face 仓库删除文件\n file_path = event.src_path\n file_name = os.path.basename(file_path)\n if file_name[-4:] not in ['.png','.jpg','.txt']: return\n try:\n self.api.delete_file(\n path_in_repo=file_path.replace(directory_to_watch,''),\n repo_id=self.repo_id,\n repo_type=self.repo_type,\n )\n except Error as error:\n print(error)\n\n def on_modified(self, event):\n if not event.is_directory:\n # 更新 Hugging Face 仓库中的文件\n file_path = event.src_path\n file_name = os.path.basename(file_path)\n if file_name[-4:] not in ['.png','.jpg','.txt']: return\n try:\n self.api.upload_file(\n path_or_fileobj=file_path,\n path_in_repo=file_path.replace(directory_to_watch,''),\n repo_id=self.repo_id,\n repo_type=self.repo_type,\n )\n except Error as error:\n print(error)\n\n def on_moved(self, event):\n if not event.is_directory:\n file_path = event.dest_path\n file_name = os.path.basename(file_path)\n if file_name[-4:] not in ['.png','.jpg','.txt']: return\n if event.dest_path.startswith(directory_to_watch):\n try:\n self.api.upload_file(\n path_or_fileobj=file_path,\n path_in_repo=file_path.replace(directory_to_watch,''),\n repo_id=self.repo_id,\n repo_type=self.repo_type,\n )\n except Error as error:\n print(error)\n\n api = HfApi()\n \n if not directory_to_watch:\n directory_to_watch = f'{install_path}/stable-diffusion-webui/log'\n # 创建观察者对象并注册文件变化处理程序\n event_handler = FileChangeHandler(api,repo_id,repo_type)\n observer = Observer()\n observer.schedule(event_handler, directory_to_watch, recursive=True)\n\n # 启动观察者\n observer.name = \"solo_directory_to_watch\"\n print(f'启动收藏图片文件夹监听,并自动同步到 huggingface {repo_type} : {repo_id}')\n observer.start()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 工具函数\n**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n\n---","metadata":{"id":"sswa04veLCtE"}},{"cell_type":"markdown","source":"一般工具函数","metadata":{}},{"cell_type":"code","source":"# 绕过 os.systen 的限制执行命令\ndef run(shell:str,shellName=''):\n if shellName == '': shellName = str(time.time())\n !mkdir -p $install_path/run_cache\n with open(install_path+'/run_cache/run_cache.'+shellName+'.sh','w') as sh:\n sh.write(shell)\n !bash {install_path}/run_cache/run_cache.{shellName}.sh\n\n# 连接多个路径字符串 让路径在shell命令中能正常的执行\ndef pathJoin(*paths:str):\n pathStr = ''\n for p in paths:\n pathStr += '\"'+p+'\"'\n pathStr = '\"*\"'.join(pathStr.split('*'))\n pathStr = '\"$\"'.join(pathStr.split('$'))\n pathStr = '\"(\"'.join(pathStr.split('('))\n pathStr = '\")\"'.join(pathStr.split(')'))\n pathStr = '\"{\"'.join(pathStr.split('{'))\n pathStr = '\"}\"'.join(pathStr.split('}'))\n pathStr = re.sub(r'\"\"','',pathStr)\n pathStr = re.sub(r'\\*{2,}','\"',pathStr)\n pathStr = re.sub(r'/{2,}','/',pathStr)\n pathStr = re.sub(r'/\\./','/',pathStr)\n return pathStr\n\n# 判断路径是不是一个文件或者可能指向一些文件\ndef pathIsFile(path):\n if Path(path).is_file():\n return True\n if re.search(r'\\.(ckpt|safetensors|png|jpg|txt|pt|pth|json|yaml|\\*)$',path):\n return True\n return False\n\ndef echoToFile(content:str,path:str):\n with open(path,'w') as sh:\n sh.write(content)\n\n# ngrok\ndef startNgrok(ngrokToken:str,ngrokLocalPort:int):\n from pyngrok import conf, ngrok\n try:\n conf.get_default().auth_token = ngrokToken\n conf.get_default().monitor_thread = False\n ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n if len(ssh_tunnels) == 0:\n ssh_tunnel = ngrok.connect(ngrokLocalPort)\n print('ngrok 访问地址:'+ssh_tunnel.public_url)\n else:\n print('ngrok 访问地址:'+ssh_tunnels[0].public_url)\n except:\n print('启动ngrok出错')\n \ndef startFrpc(name,configFile):\n run(f'''\ncd $install_path/frpc/\n$install_path/frpc/frpc {configFile}\n ''',name)\n \ndef installProxyExe():\n if useFrpc:\n print('安装frpc')\n !mkdir -p $install_path/frpc\n if Path(frpcExePath).exists():\n os.system(f'cp -f -n {frpcExePath} $install_path/frpc/frpc')\n else:\n !wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O $install_path/frpc/frpc\n \n for ssl in frpcSSLFFlies:\n if Path(ssl).exists():\n os.system('cp -f -n '+pathJoin(ssl,'/*')+' $install_path/frpc/')\n !chmod +x $install_path/frpc/frpc\n !$install_path/frpc/frpc -v\n if useNgrok:\n %pip install pyngrok\n\ndef startProxy():\n if useNgrok:\n startNgrok(ngrokToken,webuiPort)\n if useFrpc:\n startFrpc('frpc_proxy',frpcStartArg)\n\n \ndef zipPath(path:str,zipName:str,format='tar'):\n if path.startswith('$install_path'):\n path = path.replace('$install_path',install_path)\n if path.startswith('$output_path'):\n path = path.replace('$install_path',output_path)\n if not path.startswith('/'):\n path = pathJoin(install_path,'/stable-diffusion-webui','/',path)\n if Path(path).exists():\n if 'tar' == format:\n os.system('tar -cf $output_path/'+ zipName +'.tar -C '+ path +' . ')\n elif 'gz' == format:\n os.system('tar -czf $output_path/'+ zipName +'.tar.gz -C '+ path +' . ')\n return\n print('指定的目录不存在:'+path)\n\n \ndef check_service(host, port):\n try:\n socket.create_connection((host, port), timeout=5)\n return True\n except socket.error:\n return False","metadata":{"_kg_hide-input":true,"id":"coqQvTSLLCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"文件下载工具","metadata":{}},{"cell_type":"code","source":"import os\nimport re\nimport requests\n\ndef download_file(url, filename, path,cache_path = ''):\n # 获取文件的真实文件名\n if not filename:\n with requests.get(url, stream=True) as r:\n if 'Content-Disposition' in r.headers:\n filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n r.close()\n filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n # 拼接文件的完整路径\n filepath = os.path.join(path, filename)\n if cache_path:\n cache_path = os.path.join(cache_path, filename)\n # 判断文件是否已存在\n if os.path.exists(filepath):\n print(f'{filename} already exists in {path}')\n return\n if cache_path and os.path.exists(cache_path):\n !ln -s -f {cache_path} {filepath}\n # 下载文件\n with requests.get(url, stream=True) as r:\n r.raise_for_status()\n with open(filepath, 'wb') as f:\n for chunk in r.iter_content(chunk_size=8192):\n if chunk:\n f.write(chunk)\n print(f'{filename} has been downloaded to {path}')\n \n# 加入文件到下载列表\ndef putDownloadFile(url:str,distDir:str,file_name:str=None):\n if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n url = url[len(file_name)+1:]\n if not re.match(r'^(https?|ftps?)://',url):\n return\n file_name = re.sub(r'\\s+','_',file_name or '')\n dir = str(hash(url)).replace('-','')\n down_dir = f'{install_path}/down_cache/{dir}'\n !mkdir -p {down_dir}\n return [url,file_name,distDir,down_dir]\n\ndef get_file_size_in_gb(file_path):\n size_in_bytes = Path(file_path).stat().st_size\n size_in_gb = size_in_bytes / (1024 ** 3)\n return '%.2f' % size_in_gb\n \n# 下载文件\ndef startDownloadFiles(download_list):\n print('下载列表:\\n','\\n'.join([f'{item[0]} -> {item[2]}/{item[1]}' for item in download_list]))\n dist_list = []\n for dow_f in download_list:\n !mkdir -p {dow_f[3]}\n print('下载 名称:',dow_f[1],'url:',dow_f[0])\n download_file(dow_f[0],dow_f[1],dow_f[2],dow_f[3])\n \n\n","metadata":{"_kg_hide-input":true,"id":"THNUsEm_LCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"NGINX 反向代理","metadata":{}},{"cell_type":"code","source":"\n# nginx ���向代理配置文件\ndef localProxy():\n conf = '''\nserver\n{\n listen '''+str(webuiPort)+''';\n listen [::]:'''+str(webuiPort)+''';\n server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n \n if ($request_method = OPTIONS) {\n return 200;\n }\n fastcgi_send_timeout 10m;\n fastcgi_read_timeout 10m;\n fastcgi_connect_timeout 10m;\n location /1/\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+2)+'''/;\n # add_header Set-Cookie \"subpath=1; expires=0; Path=/\";\n # proxy_set_header Set-Cookie \"subpath=1; expires=0; Path=/\";\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n proxy_connect_timeout 10m;\n proxy_read_timeout 10m;\n }\n location /\n {\n set $proxy_url http://127.0.0.1:'''+str(webuiPort+1)+''';\n # if ($cookie_subpath = \"1\") {\n # set $proxy_url http://127.0.0.1:'''+str(webuiPort+2)+''';\n # }\n proxy_pass $proxy_url;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n proxy_connect_timeout 10m;\n proxy_read_timeout 10m;\n }\n}\n'''\n echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n if not check_service('localhost',webuiPort):\n !nginx -c /etc/nginx/nginx.conf\n !nginx -s reload\n ","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"线程清理工具","metadata":{}},{"cell_type":"code","source":"import inspect\nimport ctypes\n\ndef _async_raise(tid, exctype):\n \"\"\"raises the exception, performs cleanup if needed\"\"\"\n tid = ctypes.c_long(tid)\n if not inspect.isclass(exctype):\n exctype = type(exctype)\n res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n if res == 0:\n raise ValueError(\"invalid thread id\")\n elif res != 1:\n # \"\"\"if it returns a number greater than one, you're in trouble,\n # and you should call it again with exc=NULL to revert the effect\"\"\"\n ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n\ndef stop_thread(thread):\n _async_raise(thread.ident, SystemExit)\n\ndef stop_solo_threads():\n # 获取当前所有活动的线程\n threads = threading.enumerate()\n # 关闭之前创建的子线程\n for thread in threads:\n if thread.name.startswith('solo_'):\n print(thread.name)\n try:\n stop_thread(thread)\n except socket.error:\n print(f'结束进程:{thread.name} 执行失败')","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# webui 安装和配置函数\n---","metadata":{"id":"Ve3p8oOkLCtE"}},{"cell_type":"code","source":"envInstalled=False\nextensionsDone=False\n\n#安装webui\ndef install():\n print('安装webui')\n %cd $install_path\n with HiddenPrints():\n for requirement in requirements:\n !pip install {requirement}\n if reLoad:\n !rm -rf stable-diffusion-webui\n if Path(\"stable-diffusion-webui\").exists():\n %cd $install_path/stable-diffusion-webui/\n !git checkout .\n !git pull\n else:\n if mobileOptimize:\n !git clone https://github.com/viyiviyi/stable-diffusion-webui.git stable-diffusion-webui -b local # 修改了前端界面,手机使用更方便\n else:\n !git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui stable-diffusion-webui\n %cd {install_path}/stable-diffusion-webui\n print('安装webui 完成')\n\n# 链接输出目录\ndef link_dir():\n print('链接输出目录')\n # 链接输出目录 因为sd被部署在了stable-diffusion-webui目录,运行结束后为了方便下载就只有outputs目录放在output_path/目录下\n !mkdir -p $output_path/outputs\n !rm -rf $install_path/stable-diffusion-webui/outputs\n !ln -s -r $output_path/outputs $install_path/stable-diffusion-webui/ # 输出目录\n !mkdir -p $output_path/log\n !rm -rf $install_path/stable-diffusion-webui/log\n !ln -s -r $output_path/log $install_path/stable-diffusion-webui/\n # 链接 hypernetworks 目录\n if linkHypernetworksDir:\n !rm -rf $install_path/stable-diffusion-webui/models/hypernetworks\n !mkdir -p $output_path/hypernetworks\n !ln -s -r $output_path/hypernetworks $install_path/stable-diffusion-webui/models/\n # 链接 embeddings 目录\n if linkEmbeddingsDir:\n !rm -rf $install_path/stable-diffusion-webui/embeddings\n !mkdir -p $output_path/embeddings\n !ln -s -r $output_path/embeddings $install_path/stable-diffusion-webui/\n # 链接训练输出目录 文件夹链接会导致功能不能用\n if linkTextual_inversionDir:\n !rm -rf $install_path/stable-diffusion-webui/textual_inversion\n !mkdir -p $output_path/textual_inversion/\n !ln -s -r $output_path/textual_inversion $install_path/stable-diffusion-webui/\n print('链接输出目录 完成')\n \ndef link_or_download_flie(skip_down:bool,store:dict[str,List[str]]):\n download_list = []\n for dist_dir in store.keys():\n dist_path = os.path.join(f'{install_path}/stable-diffusion-webui',dist_dir)\n !mkdir -p {dist_path}\n for path in store[dist_dir]:\n if 'https://' in path or 'http://' in path:\n if skip_down:\n continue\n download_list.append(putDownloadFile(path,dist_path))\n elif pathIsFile(path):\n os.system(('cp -n' if enableLoadByCopy else 'ln -s')+' -f '+ pathJoin(path) +f' {dist_path}')\n else:\n os.system(('cp -n' if enableLoadByCopy else 'ln -s')+' -f '+ pathJoin(path,'/*.*') +f' {dist_path}')\n !rm -f {dist_path}/\\*.* \n startDownloadFiles(download_list)\n \n# 链接模型文件\ndef load_models(skip_url=False):\n print(('复制' if enableLoadByCopy else '链接') + '模型文件')\n if enableLoadByCopy:\n print('如果出现 No such file or directory 错误,可以忽略')\n store = get_other_files()\n store['models/Stable-diffusion'] = modelDirs + (store['models/Stable-diffusion'] if 'models/Stable-diffusion' in store else [])\n store['models/hypernetworks'] = hypernetworksModelDirs + (store['models/hypernetworks'] if 'models/hypernetworks' in store else [])\n store['models/embeddings'] = embeddingsModelDirs + (store['models/embeddings'] if 'models/embeddings' in store else [])\n store['models/Lora'] = loraModelDirs + (store['models/Lora'] if 'models/Lora' in store else [])\n store['models/LyCORIS'] = lyCORISModelDirs + (store['models/LyCORIS'] if 'models/LyCORIS' in store else [])\n store['models/VAE'] = modelVaeDirs + (store['models/VAE'] if 'models/VAE' in store else [])\n store['extensions/sd-webui-controlnet/models'] = controlNetModels + (store['extensions/sd-webui-controlnet/models'] if 'extensions/sd-webui-controlnet/models' in store else [])\n link_or_download_flie(skip_url,store)\n print(('复制' if enableLoadByCopy else '链接') + '模型文件 完成')\n\n#安装依赖\ndef install_dependencies():\n print('安装webui需要的python环境')\n global envInstalled\n global venvPath\n print(venvPath)\n \n with HiddenPrints():\n %env TF_CPP_MIN_LOG_LEVEL=1\n !apt -y update -qq\n !wget http://launchpadlibrarian.net/367274644/libgoogle-perftools-dev_2.5-2.2ubuntu3_amd64.deb\n !wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/google-perftools_2.5-2.2ubuntu3_all.deb\n !wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libtcmalloc-minimal4_2.5-2.2ubuntu3_amd64.deb\n !wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libgoogle-perftools4_2.5-2.2ubuntu3_amd64.deb\n !apt -y install -qq libunwind8-dev\n !dpkg -i *.deb\n %env LD_PRELOAD=libtcmalloc.so\n !rm *.deb\n !sudo apt install nginx -y\n\n sh = f'cd {install_path}/stable-diffusion-webui\\n'\n if str(sys.version).startswith('3.8') or str(sys.version).startswith('3.9') or str(sys.version).startswith('3.10'):\n sh += 'python -m venv venv\\n'\n else:\n sh += '''\nadd-apt-repository ppa:deadsnakes/ppa -y\napt update\napt install python3.10 -y\npython3.10 -m venv venv\n'''\n if quickStart:\n if not Path(venvPath).exists():\n !mkdir -p {install_path}/venv_cache\n if not Path(f'{install_path}/venv_cache/venv.tar.bak').exists():\n download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{install_path}/venv_cache')\n !unzip {install_path}/venv_cache/venv.zip -d {install_path}/venv_cache\n venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n !rm -rf {install_path}/venv_cache/venv.zip\n elif venvPath.endswith('.zip'):\n !mkdir -p {install_path}/venv_cache\n !unzip {venvPath} -d {install_path}/venv_cache\n venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n\n sh += 'echo \"unzip venv\"\\n'\n sh += f'tar -xf {venvPath} -C ./venv\\n'\n sh += '\\n'\n with HiddenPrints():\n run(sh,'dependencies')\n if not Path(f'{install_path}/stable-diffusion-webui/venv/bin/pip').exists():\n !curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py\n with HiddenPrints():\n !{install_path}/stable-diffusion-webui/venv/bin/python3 get-pip.py\n\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -V\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip -V\n\n if not quickStart or not Path(venvPath).exists():\n with HiddenPrints():\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip install -U torch==2.0.0+cu117 torchvision==0.15.1+cu117 torchaudio==2.0.1 --index-url https://download.pytorch.org/whl/cu117\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip install -U open-clip-torch xformers==0.0.19\n\n envInstalled = True\n print('安装webui需要的python环境 完成')\n\n# 安装插件\ndef install_extensions():\n global extensionsDone\n print('安装插件')\n sh = 'mkdir -p $install_path/stable-diffusion-webui/extensions \\n'\n sh = 'mkdir -p $install_path/cache/extensions \\n'\n sh += 'cd $install_path/cache/extensions \\n'\n for ex in extensions:\n sh += 'git clone ' + ex + ' \\n'\n sh += 'rsync -a $install_path/cache/extensions/* $install_path/stable-diffusion-webui/extensions \\n'\n sh += 'cd ../ && rm -rf $install_path/cache/extensions \\n'\n with HiddenPrints():\n run(sh,'extensions')\n extensionsDone = True\n print('安装插件 完成')\n \n# 个性化配置 \ndef use_config():\n print('使用自定义配置 包括tag翻译 \\n')\n %cd $install_path/stable-diffusion-webui\n !mkdir -p tmp\n %cd tmp\n !git clone {webui_settings} sd-configs\n !cp -rf sd-configs/dist/* $install_path/stable-diffusion-webui\n if not Path(ui_config_file).exists(): # ui配置文件\n !mkdir -p {ui_config_file[0:ui_config_file.rfind('/')]}\n os.system('cp -f -n $install_path/stable-diffusion-webui/ui-config.json '+ui_config_file)\n if not Path(setting_file).exists(): # 设置配置文件\n !mkdir -p {setting_file[0:setting_file.rfind('/')]}\n os.system('cp -f -n $install_path/stable-diffusion-webui/config.json '+setting_file)\n\ndef checkDefaultModel():\n print('检查默认模型文件是否存在 \\n')\n global usedCkpt\n if usedCkpt is not None and usedCkpt != '': # 设置启动时默认加载的模型\n if '.' in usedCkpt:\n if '/' in usedCkpt:\n usedCkpt = usedCkpt\n else:\n usedCkpt = install_path + '/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt\n else:\n for x in ['.ckpt','.safetensors']:\n if Path(install_path+'/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt+x).exists():\n usedCkpt = install_path+'/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt+x\n break\n if Path(usedCkpt).exists():\n return True\n else:\n if Path(usedCkpt).is_symlink():\n print('模型文件真实地址:'+os.readlink(usedCkpt))\n return False\n\ndef copy_last_log_to_images():\n print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')\n img_list = os.listdir(f'{install_path}/stable-diffusion-webui/log/images')\n last_img_path = ''\n last_img_num = 0\n for img in img_list:\n if re.findall(r'^\\d+-',str(img)):\n num = int(re.findall(r'^\\d+-',str(img))[0][:-1])\n if num > last_img_num:\n last_img_path = img\n last_img_num = num\n print(f'{install_path}/stable-diffusion-webui/log/images/{last_img_path} {install_path}/stable-diffusion-webui/outputs/txt2img-images')\n !mkdir -p {install_path}/stable-diffusion-webui/outputs/txt2img-images\n !cp -f {install_path}/stable-diffusion-webui/log/images/{last_img_path} {install_path}/stable-diffusion-webui/outputs/txt2img-images/\n \n print(f'{install_path}/stable-diffusion-webui/log/images/{last_img_path} {install_path}/stable-diffusion-webui/outputs/img2img-images')\n !mkdir -p {install_path}/stable-diffusion-webui/outputs/img2img-images\n !cp -f {install_path}/stable-diffusion-webui/log/images/{last_img_path} {install_path}/stable-diffusion-webui/outputs/img2img-images/\n \n \ndef start_webui(i):\n # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n print(i,'--port',str(webuiPort+1+i))\n if i>0:\n print(f'使用第{i+1}张显卡启动第{i+1}个webui,通过frpc或nrgok地址后加/{i}/进行访问(不能使用同一个浏览器)')\n if useFrpc:\n while True:\n !venv/bin/python3 launch.py --device-id={i} --port {str(webuiPort+1+i)} {'' if i ==0 else '--nowebui'} # {'' if i == 0 else '--subpath=/'+str(i)}\n print('5秒后重启webui')\n time.sleep(5)\n else:\n !venv/bin/python3 launch.py --device-id={i} --port {str(webuiPort+1+i)} {'' if i ==0 else '--nowebui'} # {'' if i == 0 else '--subpath=/'+str(i)}\n \n# 启动\ndef start():\n print('启动webui')\n %cd $install_path/stable-diffusion-webui\n args = '' # ' --port=' + str(webuiPort+1)\n if not disableShared:\n args += ' --share'\n if onlyApi:\n args += ' --nowebui'\n if ui_config_file is not None and ui_config_file != '' and Path(ui_config_file).exists(): # ui配置文件\n args += ' --ui-config-file=' + pathJoin(ui_config_file)\n if setting_file is not None and setting_file != '' and Path(setting_file).exists(): # 设置配置文件\n args += ' --ui-settings-file=' + pathJoin(setting_file)\n if not checkDefaultModel():\n print('默认模型文件不存在,请检查配置:'+usedCkpt)\n else:\n args += ' --ckpt='+ pathJoin(usedCkpt)\n if vaeHalf is False: \n args += ' --no-half-vae'\n if modelHalf is False:\n args += ' --no-half'\n if consoleProgressbars is False:\n args += ' --disable-console-progressbars'\n if consolePrompts is True:\n args += ' --enable-console-prompts'\n args += ' ' + otherArgs\n os.environ['COMMANDLINE_ARGS']=args\n !echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS\n %env REQS_FILE=requirements.txt\n \n threads = []\n for i in range(torch.cuda.device_count()):\n thread = threading.Thread(target = start_webui, name='solo_start_webui_'+str(i), daemon=True,args=([i]))\n thread.start()\n threads.append(thread)\n while thread.is_alive() and not check_service('localhost',str(webuiPort+1+i)): # 当当前服务启动完成才允许退出此次循环\n time.sleep(10)\n time.sleep(5)\n for thread in threads:\n thread.join()","metadata":{"_kg_hide-input":true,"id":"GTjyBJihLCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 入口函数\n---","metadata":{"id":"qLvsk8ByLCtF"}},{"cell_type":"code","source":"\n# 启动非webui相关的的内容,加快启动速度\ndef main():\n global envInstalled\n global extensionsDone\n global huggingface_is_init\n startTicks = time.time()\n isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n if isInstall is False or reLoad: \n print('启动 安装webui和运行环境')\n install()\n link_dir()\n init_huggingface()\n if enableThread:\n threading.Thread(target = install_extensions,daemon=True, name='solo_install_extensions').start()\n threading.Thread(target = load_models,daemon=True).start()\n threading.Thread(target = install_dependencies,daemon=True, name='solo_install_dependencies').start()\n if huggingface_is_init:\n threading.Thread(target = download_huggingface_repo,daemon=True,\n args=([huggingface_repo]),\n kwargs={\"callback\":copy_last_log_to_images},\n name='solo_download_huggingface_repo').start()\n\n else:\n install_extensions()\n load_models()\n install_dependencies()\n if huggingface_is_init:\n download_huggingface_repo(huggingface_repo,callback=copy_last_log_to_images)\n t = 0\n while not envInstalled or not extensionsDone:\n if t%10==0:\n print('等待python环境和插件安装...')\n t = t+1\n time.sleep(1)\n use_config()\n installProxyExe()\n os.environ['IsInstall'] = 'True'\n else:\n envInstalled = True\n extensionsDone = True\n sys.stdout = sys_sys_stdout\n stop_solo_threads()\n localProxy()\n threading.Thread(target = startProxy, daemon=True, name='solo_startProxy').start()\n if init_huggingface():\n start_sync_log_to_huggingface(huggingface_repo)\n load_models(True)\n ticks = time.time()\n print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n start()\n","metadata":{"_kg_hide-input":true,"id":"IOKjaMlcLCtF","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 执行区域\n---","metadata":{"id":"0oaCRs2gLCtF"}},{"cell_type":"code","source":"# 启动\n# reLoad = True\n# hidden_console_info = False\nsys.stdout = sys_sys_stdout\nmain()","metadata":{"_kg_hide-output":true,"id":"O3DR0DWHLCtF","scrolled":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 停止一些不必要的后台线程\nstop_solo_threads()","metadata":{"scrolled":true,"trusted":true},"execution_count":null,"outputs":[]}]}
 
1
+ {"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 这只是一个完整项目的一部分 不能运行的 \n- 可以从这个地址运行 [点击��开](https://www.kaggle.com/viyiviyi/sdwui-before)\n---","metadata":{"id":"6zE2QeUKLCtC"}},{"cell_type":"code","source":"from pathlib import Path\nimport os\nimport time\nimport re\nimport subprocess\nimport threading\nimport sys\nimport socket\n\ninstall_path=f\"{os.environ['HOME']}/sdwebui\" # 安装目录\noutput_path=f\"{os.environ['HOME']}/sdwebui/Output\" # 输出目录 如果使用google云盘 会在google云盘增加sdwebui/Output\ninput_path = '/kaggle/input' # 输入目录\n\ngoogle_drive = '' \n# 连接谷歌云\ntry:\n if useGooglrDrive:\n from google.colab import drive\n drive.mount(f'~/google_drive')\n google_drive = f\"{os.environ['HOME']}/google_drive/MyDrive\"\n output_path = f'{google_drive}/sdwebui/Output'\n input_path = f'{google_drive}/sdwebui/Input'\n !mkdir -p {input_path}\nexcept:\n useGooglrDrive = False\n\n!mkdir -p {install_path}\n!mkdir -p {output_path}\n\nos.environ['install_path'] = install_path\nos.environ['output_path'] = output_path\nos.environ['google_drive'] = google_drive\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 模型目录 文件名称:链接的方式指定文件名\nmodelDirs = []+[item.strip() for item in 模型列表.split('\\n') if item.strip() ]\n# vae列表\nmodelVaeDirs = []+[item.strip() for item in VAE列表.split('\\n') if item.strip()]\n# 此配置内的目录下所有文件将加载到hypernetworks文件夹\nhypernetworksModelDirs = []+[item.strip() for item in hypernetworks列表.split('\\n') if item.strip()] \n# 此配置内的目录下所有文件将加载到embeddings文件夹\nembeddingsModelDirs = [] +[item.strip() for item in embeddings列表.split('\\n') if item.strip()]\n# 此配置内的目录下所有文件将加载到Lora文件夹\nloraModelDirs = []+[item.strip() for item in Lora列表.split('\\n') if item.strip()] \n\nlyCORISModelDirs = []+[item.strip() for item in LyCORIS列表.split('\\n') if item.strip()] \n# controlNet插件模型列表\ncontrolNetModels=[] +[item.strip() for item in controlNet模型列表.split('\\n') if item.strip()]\n# 插件列表\nextensions=[]+[item.strip() for item in 插件列表.split('\\n') if item.strip()]\n# 配置文件链接\nlinkHypernetworksDir=False # 链接 hypernetworks 目录到输出目录\nlinkEmbeddingsDir=False # 链接 embeddings 目录到输出目录\nlinkTextual_inversionDir=False # 链接 textual_inversion 目录到输出目录 如果需要保存训练过程的产出文件时建议开启\n\nngrokTokenFile = os.path.join(input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径\nfrpcConfigFile = os.path.join(input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件\n# ss证书目录 下载nginx的版本,把pem格式改成crt格式\nfrpcSSLFFlies =[os.path.join(input_path,'configs/koishi_ssl')]+[item.strip() for item in frpSSL文件.split('\\n') if item.strip() ]\n# frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加\nfrpcExePath = os.path.join(input_path,'utils-tools/frpc')\n# 其他需要加载的webui启动参数 写到【参数列表】这个配置去\notherArgs = ' '.join([item.strip() for item in 参数列表.split('\\n') if item.strip()])\n\nvenvPath = os.path.join(input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加\n\n# 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api\n# 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件\nkaggleApiTokenFile = os.path.join(input_path,'configs/kaggle.json')","metadata":{"_kg_hide-input":true,"id":"i3LhnwYHLCtC","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 这下面的是用于初始化一些值或者环境变量的,轻易别改\nfrpcStartArg = ''\n\n!mkdir -p $install_path/configFiles\nif Path(frp配置文件或配置.strip()).exists():\n frpcConfigFile = frp配置文件或配置.strip()\nif not Path(frpcConfigFile).exists(): \n if frp配置文件或配置.strip().startswith('-f'):\n frpcStartArg = frp配置文件或配置.strip()\n else:\n useFrpc = False\nelse:\n os.system(f'cp -f {frpcConfigFile} {install_path}/configFiles/frpc_webui.ini')\n frpcConfigFile = f'{install_path}/configFiles/frpc_webui.ini'\n os.system(f'sed -i \"s/local_port = .*/local_port = {webuiPort}/g\" {frpcConfigFile}')\n frpcStartArg = f' -c {frpcConfigFile}'\n\nngrokToken=''\nif Path(ngrok配置或文件地址.strip()).exists():\n ngrokTokenFile = ngrok配置或文件地址.strip()\nif Path(ngrokTokenFile).exists():\n with open(ngrokTokenFile,encoding = \"utf-8\") as nkfile:\n ngrokToken = nkfile.readline()\nelif not ngrok配置或文件地址.strip().startswith('/'):\n ngrokToken=ngrok配置或文件地址.strip()\n \nif not Path(venvPath).exists():\n venvPath = os.path.join(input_path,'sd-webui-venv/venv.zip')","metadata":{"_kg_hide-input":true,"id":"a_GtG2ayLCtD","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# kaggle public API\n\n**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n\n---","metadata":{"id":"p0uS-BLULCtD"}},{"cell_type":"code","source":"# 安装kaggle的api token文件\ndef initKaggleConfig():\n if Path('~/.kaggle/kaggle.json').exists():\n return True\n if Path(kaggleApiTokenFile).exists():\n !mkdir -p ~/.kaggle/\n os.system('cp '+kaggleApiTokenFile+' ~/.kaggle/kaggle.json')\n !chmod 600 ~/.kaggle/kaggle.json\n return True\n print('缺少kaggle的apiToken文件,访问:https://www.kaggle.com/你的kaggle用户名/account 获取')\n return False\n\ndef getUserName():\n if not initKaggleConfig(): return\n import kaggle\n return kaggle.KaggleApi().read_config_file()['username']\n\ndef createOrUpdateDataSet(path:str,datasetName:str):\n if not initKaggleConfig(): return\n print('创建或更新数据集 '+datasetName)\n import kaggle\n os.system('mkdir -p $install_path/kaggle_cache')\n os.system('rm -rf $install_path/kaggle_cache/*')\n datasetDirPath = install_path+'/kaggle_cache/'+datasetName\n os.system('mkdir -p '+datasetDirPath)\n os.system('cp -f '+path+' '+datasetDirPath+'/')\n username = getUserName()\n print(\"kaggle username:\"+username)\n datasetPath = username+'/'+datasetName\n datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n print(datasetList)\n if len(datasetList) == 0 or datasetPath not in [str(d) for d in datasetList]: # 创建 create\n os.system('kaggle datasets init -p' + datasetDirPath)\n metadataFile = datasetDirPath+'/dataset-metadata.json'\n os.system('sed -i s/INSERT_TITLE_HERE/'+ datasetName + '/g ' + metadataFile)\n os.system('sed -i s/INSERT_SLUG_HERE/'+ datasetName + '/g ' + metadataFile)\n os.system('cat '+metadataFile)\n os.system('kaggle datasets create -p '+datasetDirPath)\n print('create database done')\n else:\n kaggle.api.dataset_metadata(datasetPath,datasetDirPath)\n kaggle.api.dataset_create_version(datasetDirPath, 'auto update',dir_mode='zip')\n print('upload database done')\n\ndef downloadDatasetFiles(datasetName:str,outputPath:str):\n if not initKaggleConfig(): return\n print('下载数据集文件 '+datasetName)\n import kaggle\n username = getUserName()\n datasetPath = username+'/'+datasetName\n datasetList = kaggle.api.dataset_list(mine=True,search=datasetPath)\n if datasetPath not in [str(d) for d in datasetList]:\n return False\n os.system('mkdir -p '+outputPath)\n kaggle.api.dataset_download_files(datasetPath,path=outputPath,unzip=True)\n return True\n\n","metadata":{"_kg_hide-input":true,"id":"m8FJi4j0LCtD","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 工具函数\n**不能使用%cd这种会改变当前工作目录的命令,会导致和其他线程冲突**\n\n---","metadata":{"id":"sswa04veLCtE"}},{"cell_type":"code","source":"# 绕过 os.systen 的限制执行命令\ndef run(shell:str,shellName=''):\n if shellName == '': shellName = str(time.time())\n !mkdir -p $install_path/run_cache\n with open(install_path+'/run_cache/run_cache.'+shellName+'.sh','w') as sh:\n sh.write(shell)\n !bash {install_path}/run_cache/run_cache.{shellName}.sh\n\n# 连接多个路径字符串 让路径在shell命令中能正常的执行\ndef pathJoin(*paths:str):\n pathStr = ''\n for p in paths:\n pathStr += '\"'+p+'\"'\n pathStr = '\"*\"'.join(pathStr.split('*'))\n pathStr = '\"$\"'.join(pathStr.split('$'))\n pathStr = '\"(\"'.join(pathStr.split('('))\n pathStr = '\")\"'.join(pathStr.split(')'))\n pathStr = '\"{\"'.join(pathStr.split('{'))\n pathStr = '\"}\"'.join(pathStr.split('}'))\n pathStr = re.sub(r'\"\"','',pathStr)\n pathStr = re.sub(r'\\*{2,}','\"',pathStr)\n pathStr = re.sub(r'/{2,}','/',pathStr)\n pathStr = re.sub(r'/\\./','/',pathStr)\n return pathStr\n\n# 判断路径是不是一个文件或者可能指向一些文件\ndef pathIsFile(path):\n if Path(path).is_file():\n return True\n if re.search(r'\\.(ckpt|safetensors|png|jpg|txt|pt|pth|json|yaml|\\*)$',path):\n return True\n return False\n\ndef echoToFile(content:str,path:str):\n with open(path,'w') as sh:\n sh.write(content)\n\n# ngrok\ndef startNgrok(ngrokToken:str,ngrokLocalPort:int):\n from pyngrok import conf, ngrok\n try:\n conf.get_default().auth_token = ngrokToken\n conf.get_default().monitor_thread = False\n ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n if len(ssh_tunnels) == 0:\n ssh_tunnel = ngrok.connect(ngrokLocalPort)\n print('address:'+ssh_tunnel.public_url)\n else:\n print('address:'+ssh_tunnels[0].public_url)\n except:\n print('启动ngrok出错')\n \ndef startFrpc(name,configFile):\n run(f'''\ncd $install_path/frpc/\n$install_path/frpc/frpc {configFile}\n ''',name)\n \ndef installProxyExe():\n if useFrpc:\n print('安装frpc')\n !mkdir -p $install_path/frpc\n if Path(frpcExePath).exists():\n os.system(f'cp -f -n {frpcExePath} $install_path/frpc/frpc')\n else:\n !wget \"https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc\" -O $install_path/frpc/frpc\n \n for ssl in frpcSSLFFlies:\n if Path(ssl).exists():\n os.system('cp -f -n '+pathJoin(ssl,'/*')+' $install_path/frpc/')\n !chmod +x $install_path/frpc/frpc\n !$install_path/frpc/frpc -v\n if useNgrok:\n %pip install pyngrok\n\ndef startProxy():\n if useNgrok:\n startNgrok(ngrokToken,webuiPort)\n if useFrpc:\n startFrpc('frpc_proxy',frpcStartArg)\n\n \ndef zipPath(path:str,zipName:str,format='tar'):\n if path.startswith('$install_path'):\n path = path.replace('$install_path',install_path)\n if path.startswith('$output_path'):\n path = path.replace('$install_path',output_path)\n if not path.startswith('/'):\n path = pathJoin(install_path,'/stable-diffusion-webui','/',path)\n if Path(path).exists():\n if 'tar' == format:\n os.system('tar -cf $output_path/'+ zipName +'.tar -C '+ path +' . ')\n elif 'gz' == format:\n os.system('tar -czf $output_path/'+ zipName +'.tar.gz -C '+ path +' . ')\n return\n print('指定的目录不存在:'+path)\n","metadata":{"_kg_hide-input":true,"id":"coqQvTSLLCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport re\nimport requests\n\ndef download_file(url, filename, path):\n # 获取文件的真实文件名\n if not filename:\n with requests.get(url, stream=True) as r:\n if 'Content-Disposition' in r.headers:\n filename = r.headers['Content-Disposition'].split('filename=')[1].strip('\"')\n r.close()\n filename = re.sub(r'[\\\\/:*?\"<>|;]', '', filename)\n # 拼接文件的完整路径\n filepath = os.path.join(path, filename)\n # 判断文件是否已存在\n if os.path.exists(filepath):\n print(f'{filename} already exists in {path}')\n return\n # 下载文件\n with requests.get(url, stream=True) as r:\n r.raise_for_status()\n with open(filepath, 'wb') as f:\n for chunk in r.iter_content(chunk_size=8192):\n if chunk:\n f.write(chunk)\n print(f'{filename} has been downloaded to {path}')\n \n# 加入文件到下载列表\ndef putDownloadFile(url:str,distDir:str,file_name:str=None):\n if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):\n file_name = re.findall(r'^[^:]+:',url)[0][:-1]\n url = url[len(file_name)+1:]\n if not re.match(r'^(https?|ftps?)://',url):\n return\n file_name = re.sub(r'\\s+','_',file_name or '')\n dir = str(hash(url)).replace('-','')\n down_dir = f'{install_path}/down_cache/{dir}'\n !mkdir -p {down_dir}\n return [url,file_name,distDir,down_dir]\n\ndef get_file_size_in_gb(file_path):\n size_in_bytes = Path(file_path).stat().st_size\n size_in_gb = size_in_bytes / (1024 ** 3)\n return '%.2f' % size_in_gb\n \n# 下载文件\ndef startDownloadFiles(download_list):\n print('下载列表:\\n','\\n'.join([f'{item[0]} -> {item[2]}/{item[1]}' for item in download_list]))\n dist_list = []\n for dow_f in download_list:\n !mkdir -p {dow_f[3]}\n print('下载 名称:',dow_f[1],'url:',dow_f[0])\n download_file(dow_f[0],dow_f[1],dow_f[2])","metadata":{"_kg_hide-input":true,"id":"THNUsEm_LCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# nginx 反向代理配置文件\ndef localProxy():\n conf = '''\nserver\n{\n listen '''+str(webuiPort)+''';\n listen [::]:'''+str(webuiPort)+''';\n server_name 127.0.0.1 localhost 0.0.0.0 \"\";\n location /\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+1)+'''/;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n }\n location /1/\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+2)+'''/;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n }\n location /2/\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+3)+'''/;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n }\n location /3/\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+4)+'''/;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n }\n location /4/\n {\n proxy_pass http://127.0.0.1:'''+str(webuiPort+5)+'''/;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header REMOTE-HOST $remote_addr;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection upgrade;\n proxy_http_version 1.1;\n }\n}\n '''\n echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')\n !nginx -c /etc/nginx/nginx.conf\n !nginx -s reload\n ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import inspect\nimport ctypes\n\ndef _async_raise(tid, exctype):\n \"\"\"raises the exception, performs cleanup if needed\"\"\"\n tid = ctypes.c_long(tid)\n if not inspect.isclass(exctype):\n exctype = type(exctype)\n res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))\n if res == 0:\n raise ValueError(\"invalid thread id\")\n elif res != 1:\n # \"\"\"if it returns a number greater than one, you're in trouble,\n # and you should call it again with exc=NULL to revert the effect\"\"\"\n ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)\n raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n\ndef stop_thread(thread):\n _async_raise(thread.ident, SystemExit)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# webui 安装和配置函数\n---","metadata":{"id":"Ve3p8oOkLCtE"}},{"cell_type":"code","source":"envInstalled=False\nextensionsDone=False\n\n#安装webui\ndef install():\n print('安装webui')\n %cd $install_path\n if reLoad:\n !rm -rf stable-diffusion-webui\n if Path(\"stable-diffusion-webui\").exists():\n %cd $install_path/stable-diffusion-webui/\n !git checkout .\n !git pull\n else:\n if mobileOptimize:\n !git clone https://github.com/viyiviyi/stable-diffusion-webui.git stable-diffusion-webui -b local # 修改了前端界面,手机使用更方便\n else:\n !git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui stable-diffusion-webui\n print('安装webui 完成')\n\n# 链接输出目录\ndef link_dir():\n print('链接输出目录')\n # 链接输出目录 因为sd被部署在了stable-diffusion-webui目录,运行结束后为了方便下载就只有outputs目录放在output_path/目录下\n !mkdir -p $output_path/outputs\n !rm -rf $install_path/stable-diffusion-webui/outputs\n !ln -s -r $output_path/outputs $install_path/stable-diffusion-webui/ # 输出目录\n !mkdir -p $output_path/log\n !rm -rf $install_path/stable-diffusion-webui/log\n !ln -s -r $output_path/log $install_path/stable-diffusion-webui/\n # 链接 hypernetworks 目录\n if linkHypernetworksDir:\n !rm -rf $install_path/stable-diffusion-webui/models/hypernetworks\n !mkdir -p $output_path/hypernetworks\n !ln -s -r $output_path/hypernetworks $install_path/stable-diffusion-webui/models/\n # 链接 embeddings 目录\n if linkEmbeddingsDir:\n !rm -rf $install_path/stable-diffusion-webui/embeddings\n !mkdir -p $output_path/embeddings\n !ln -s -r $output_path/embeddings $install_path/stable-diffusion-webui/\n # 链接训练输出目录 文件夹链接会导致功能不能用\n if linkTextual_inversionDir:\n !rm -rf $install_path/stable-diffusion-webui/textual_inversion\n !mkdir -p $output_path/textual_inversion/\n !ln -s -r $output_path/textual_inversion $install_path/stable-diffusion-webui/\n print('链接输出目录 完成')\n \n# 链接模型文件\ndef load_models(skip_url=False):\n print(('复制' if enableLoadByCopy else '链接') + '模型文件')\n if enableLoadByCopy:\n print('如果出现 No such file or directory 错误,可以忽略')\n download_list = []\n models_dir_path = f'{install_path}/stable-diffusion-webui/models/Stable-diffusion'\n hypernetworks_dir_path = f'{install_path}/stable-diffusion-webui/models/hypernetworks'\n embeddings_dir_path = f'{install_path}/stable-diffusion-webui/models/embeddings'\n lora_dir_path = f'{install_path}/stable-diffusion-webui/models/Lora'\n lycoris_dir_path = f'{install_path}/stable-diffusion-webui/models/LyCORIS'\n vae_dir_path = f'{install_path}/stable-diffusion-webui/models/VAE'\n control_net_dir_path = f'{install_path}/stable-diffusion-webui/extensions/sd-webui-controlnet/models'\n \n def link_file(source_paths,dist:str):\n !mkdir -p {dist}\n for path in source_paths:\n if 'https://' in path or 'http://' in path:\n if skip_url:\n continue\n download_list.append(putDownloadFile(path,dist))\n elif pathIsFile(path):\n os.system(('cp -n' if enableLoadByCopy else 'ln -s')+' -f '+ pathJoin(path) +f' {dist}')\n else:\n os.system(('cp -n' if enableLoadByCopy else 'ln -s')+' -f '+ pathJoin(path,'/*.*') +f' {dist}')\n !rm -f {dist}/\\*.* \n \n link_file(modelDirs,models_dir_path)\n link_file(hypernetworksModelDirs,hypernetworks_dir_path)\n link_file(embeddingsModelDirs,embeddings_dir_path)\n link_file(loraModelDirs,lora_dir_path)\n link_file(lyCORISModelDirs,lycoris_dir_path)\n link_file(modelVaeDirs,vae_dir_path)\n link_file(controlNetModels,control_net_dir_path)\n startDownloadFiles([item for item in download_list if item])\n print(('复制' if enableLoadByCopy else '链接') + '模型文件 完成')\n\n#安装依赖\ndef install_dependencies():\n print('安装webui需要的python环境')\n global envInstalled\n global venvPath\n !sudo apt install nginx -y\n sh = f'cd {install_path}/stable-diffusion-webui\\n'\n if str(sys.version).startswith('3.8') or str(sys.version).startswith('3.9') or str(sys.version).startswith('3.10'):\n sh += '''\npython3 -m venv venv\n'''\n else:\n sh += '''\nadd-apt-repository ppa:deadsnakes/ppa -y\napt update\napt install python3.10 -y\npython3.10 -m venv venv\n'''\n if quickStart:\n if not Path(venvPath).exists():\n !mkdir -p {install_path}/venv_cache\n if not Path(f'{install_path}/venv_cache/venv.tar.bak').exists():\n download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{install_path}/venv_cache')\n !unzip {install_path}/venv_cache/venv.zip -d {install_path}/venv_cache\n venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n !rm -rf {install_path}/venv_cache/venv.zip\n elif venvPath.endswith('.zip'):\n !mkdir -p {install_path}/venv_cache\n !unzip {venvPath} -d {install_path}/venv_cache\n venvPath = f'{install_path}/venv_cache/venv.tar.bak'\n \n sh += 'echo \"unzip venv\"\\n'\n sh += f'tar -xf {venvPath} -C ./venv\\n'\n sh += '\\n'\n run(sh,'dependencies')\n if not Path(f'{install_path}/stable-diffusion-webui/venv/bin/pip').exists():\n !curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py\n !{install_path}/stable-diffusion-webui/venv/bin/python3 get-pip.py\n \n !{install_path}/stable-diffusion-webui/venv/bin/python3 -V\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip -V\n \n if not quickStart or not Path(venvPath).exists():\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip install -U torch==2.0.0+cu117 torchvision==0.15.1+cu117 torchaudio==2.0.1 --index-url https://download.pytorch.org/whl/cu117\n !{install_path}/stable-diffusion-webui/venv/bin/python3 -m pip install -U open-clip-torch xformers==0.0.19\n \n envInstalled = True\n print('安装webui需要的python环境 完成')\n\n# 安装插件\ndef install_extensions():\n global extensionsDone\n print('安装插件')\n sh = 'mkdir -p $install_path/stable-diffusion-webui/extensions \\n'\n sh = 'mkdir -p $install_path/cache/extensions \\n'\n sh += 'cd $install_path/cache/extensions \\n'\n for ex in extensions:\n sh += 'git clone ' + ex + ' \\n'\n sh += 'rsync -a $install_path/cache/extensions/* $install_path/stable-diffusion-webui/extensions \\n'\n sh += 'cd ../ && rm -rf $install_path/cache/extensions \\n'\n run(sh,'extensions')\n extensionsDone = True\n print('安装插件 完成')\n \n# 个性化配置 \ndef use_config():\n print('使用自定义配置 包括tag翻译 \\n')\n %cd $install_path/stable-diffusion-webui\n !mkdir -p tmp\n %cd tmp\n !git clone {webui_settings} sd-configs\n !cp -rf sd-configs/dist/* $install_path/stable-diffusion-webui\n if not Path(ui_config_file).exists(): # ui配置文件\n !mkdir -p {ui_config_file[0:ui_config_file.rfind('/')]}\n os.system('cp -f -n $install_path/stable-diffusion-webui/ui-config.json '+ui_config_file)\n if not Path(setting_file).exists(): # 设置配置文件\n !mkdir -p {setting_file[0:setting_file.rfind('/')]}\n os.system('cp -f -n $install_path/stable-diffusion-webui/config.json '+setting_file)\n\ndef checkDefaultModel():\n print('检查默认模型文件是否存在 \\n')\n global usedCkpt\n if usedCkpt is not None and usedCkpt != '': # 设置启动时默认加载的模型\n if '.' in usedCkpt:\n if '/' in usedCkpt:\n usedCkpt = usedCkpt\n else:\n usedCkpt = install_path + '/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt\n else:\n for x in ['.ckpt','.safetensors']:\n if Path(install_path+'/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt+x).exists():\n usedCkpt = install_path+'/stable-diffusion-webui/models/Stable-diffusion/' + usedCkpt+x\n break\n if Path(usedCkpt).exists():\n return True\n else:\n if Path(usedCkpt).is_symlink():\n print('模型文件真实地址:'+os.readlink(usedCkpt))\n return False\n \ndef check_service(host, port):\n try:\n socket.create_connection((host, port), timeout=5)\n return True\n except socket.error:\n return False\n \ndef start_webui(i):\n # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化\n print(i,'--port',str(webuiPort+1+i))\n if i>0:\n print(f'使用第{i+1}张显卡启动第{i+1}个webui,通过frpc或nrgok地址后加/{i}/进行访问')\n if useFrpc:\n while True:\n !venv/bin/python3 launch.py --device-id={i} --port {str(webuiPort+1+i)}\n print('5秒后重启webui')\n time.sleep(5)\n else:\n !venv/bin/python3 launch.py --device-id={i} --port {str(webuiPort+1+i)}\n \n# 启动\ndef start():\n print('启动webui')\n %cd $install_path/stable-diffusion-webui\n args = '' # ' --port=' + str(webuiPort+1)\n if not disableShared:\n args += ' --share'\n if onlyApi:\n args += ' --nowebui'\n if ui_config_file is not None and ui_config_file != '' and Path(ui_config_file).exists(): # ui配置文件\n args += ' --ui-config-file=' + pathJoin(ui_config_file)\n if setting_file is not None and setting_file != '' and Path(setting_file).exists(): # 设置配置文件\n args += ' --ui-settings-file=' + pathJoin(setting_file)\n if not checkDefaultModel():\n print('默认模型文件不存在,请检查配置:'+usedCkpt)\n else:\n args += ' --ckpt='+ pathJoin(usedCkpt)\n if vaeHalf is False: \n args += ' --no-half-vae'\n if modelHalf is False:\n args += ' --no-half'\n if consoleProgressbars is False:\n args += ' --disable-console-progressbars'\n if consolePrompts is True:\n args += ' --enable-console-prompts'\n args += ' ' + otherArgs\n os.environ['COMMANDLINE_ARGS']=args\n !echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS\n %env REQS_FILE=requirements.txt\n import torch\n for i in range(torch.cuda.device_count()):\n threading.Thread(target = start_webui, name='solo_start_webui_'+str(i), daemon=True,args=([i])).start()\n while not check_service('localhost',str(webuiPort+1+i)): # 当当前服务启动完成才允许退出此次循环\n time.sleep(10)\n time.sleep(5)\n time.sleep(60*60*24)","metadata":{"_kg_hide-input":true,"id":"GTjyBJihLCtE","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 入口函数\n---","metadata":{"id":"qLvsk8ByLCtF"}},{"cell_type":"code","source":"\n# 启动非webui相关的的内容,加快启动速度\ndef main():\n global envInstalled\n global extensionsDone\n startTicks = time.time()\n isInstall = True if os.getenv('IsInstall','False') == 'True' else False\n if isInstall is False or reLoad: \n install()\n if enableThread:\n threading.Thread(target = install_extensions,daemon=True).start()\n threading.Thread(target = load_models,daemon=True).start()\n threading.Thread(target = install_dependencies,daemon=True).start()\n else:\n install_extensions()\n load_models()\n install_dependencies()\n t = 0\n while not envInstalled or not extensionsDone:\n if t%10==0:\n print('等待python环境和插件安装...')\n t = t+1\n time.sleep(1)\n link_dir()\n use_config()\n localProxy()\n installProxyExe()\n os.environ['IsInstall'] = 'True'\n else:\n envInstalled = True\n extensionsDone = True\n \n # 获取当前所有活动的线程\n threads = threading.enumerate()\n # 关闭之前创建的子线程\n for thread in threads:\n if thread.name.startswith('solo_'):\n print(thread.name)\n try:\n stop_thread(thread)\n except socket.error:\n print(f'结束进程:{thread.name} 执行失败')\n \n threading.Thread(target = startProxy, daemon=True, name='solo_startProxy').start()\n load_models(True)\n ticks = time.time()\n print(\"加载耗时:\",(ticks - startTicks),\"秒\")\n start()\n","metadata":{"_kg_hide-input":true,"id":"IOKjaMlcLCtF","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 执行区域\n---","metadata":{"id":"0oaCRs2gLCtF"}},{"cell_type":"code","source":"# 启动\nmain()","metadata":{"_kg_hide-output":true,"id":"O3DR0DWHLCtF","scrolled":true,"trusted":true},"execution_count":null,"outputs":[]}]}
sdwui_install.py DELETED
@@ -1,734 +0,0 @@
1
- #!/usr/bin/env python
2
- # coding: utf-8
3
-
4
- from pathlib import Path
5
- import os
6
- import time
7
- import re
8
- import subprocess
9
- import threading
10
- import sys
11
- import socket
12
- from typing import List
13
- import config
14
-
15
- def mkdirs(path, exist_ok=True):
16
- if path and not Path(path).exists():
17
- os.makedirs(path,exist_ok=exist_ok)
18
-
19
- # 内置参数默认值,当上下文有参数时可覆盖默认值
20
-
21
- _useFrpc = config.useFrpc
22
-
23
- _useNgrok = config.useNgrok
24
-
25
- _reLoad = config.reLoad
26
-
27
- _before_downloading = config.before_downloading
28
-
29
- _async_downloading = config.async_downloading
30
-
31
- _before_start_sync_downloading = config.before_start_sync_downloading
32
-
33
- _server_port = config.server_port or 7860
34
-
35
- _sd_git_repo = config.sd_git_repo\
36
- .replace('{sdwui}','stable-diffusion-webui')\
37
- .replace('{wui}',"webui") or 'https://github.com/viyiviyi/stable-diffusion-webui.git -b local'
38
-
39
- _sd_config_git_repu = config.sd_config_git_repu\
40
- .replace('{sdwui}','stable-diffusion-webui')\
41
- .replace('{wui}',"webui") or 'https://github.com/viyiviyi/sd-configs.git'
42
-
43
- _link_instead_of_copy = config.link_instead_of_copy
44
-
45
- show_shell_info = not config.hidden_console_info
46
-
47
- _skip_start = config.skip_start
48
-
49
- run_by_none_device = False
50
-
51
-
52
- def run(command, cwd=None, desc=None, errdesc=None, custom_env=None,try_error:bool=True) -> str:
53
- global show_shell_info
54
- if desc is not None:
55
- print(desc)
56
-
57
- run_kwargs = {
58
- "args": command,
59
- "shell": True,
60
- "cwd": cwd,
61
- "env": os.environ if custom_env is None else custom_env,
62
- "encoding": 'utf8',
63
- "errors": 'ignore',
64
- }
65
-
66
- if not show_shell_info:
67
- run_kwargs["stdout"] = run_kwargs["stderr"] = subprocess.PIPE
68
-
69
- result = subprocess.run(**run_kwargs)
70
-
71
- if result.returncode != 0:
72
- error_bits = [
73
- f"{errdesc or 'Error running command'}.",
74
- f"Command: {command}",
75
- f"Error code: {result.returncode}",
76
- ]
77
- if result.stdout:
78
- error_bits.append(f"stdout: {result.stdout}")
79
- if result.stderr:
80
- error_bits.append(f"stderr: {result.stderr}")
81
- if try_error:
82
- print(RuntimeError("\n".join(error_bits)))
83
- else:
84
- raise RuntimeError("\n".join(error_bits))
85
-
86
- if show_shell_info:
87
- print(result.stdout or "")
88
- return (result.stdout or "")
89
-
90
-
91
- install_path=f"{os.getcwd()}/sdwui" # 安装目录
92
- output_path= os.path.join(os.getcwd(), config.output_path or 'sdwui/Output')
93
- input_path = config.input_path or f'{os.getcwd()}/sdwui/Input'
94
-
95
- mkdirs(install_path,True)
96
- mkdirs(output_path,True)
97
-
98
- os.environ['install_path'] = install_path
99
- os.environ['output_path'] = output_path
100
- os.environ['input_path'] = input_path
101
-
102
- def replace_path(input_str:str):
103
- return input_str.replace('$install_path',install_path)\
104
- .replace('{install_path}',install_path)\
105
- .replace('$input_path',input_path)\
106
- .replace('{input_path}',input_path)\
107
- .replace('$output_path',output_path)\
108
- .replace('{output_path}',output_path)\
109
- .replace('{sdwui}','stable-diffusion-webui')\
110
- .replace('{wui}',"webui")
111
-
112
- space_string = ' \n\r\t\'\",'
113
-
114
- def config_reader(conf:str):
115
- args = [replace_path(item.split('#')[0].strip(space_string)) for item in conf.split('\n') if item.strip(space_string)]
116
- return [item.strip() for item in args if item.strip()]
117
-
118
-
119
- ngrokTokenFile = os.path.join(input_path,'configs/ngrok_token.txt') # 非必填 存放ngrokToken的文件的路径
120
- frpcConfigFile = os.path.join(input_path,'configs/frpc_koishi.ini') # 非必填 frp 配置文件
121
- # ss证书目录 下载nginx的版本,把pem格式改成crt格式
122
- frpcSSLFFlies = [os.path.join(input_path,'configs/koishi_ssl')] + config_reader(config.frp_ssl_dir)
123
-
124
- # frpc 文件目录 如果目录不存在,会自动下载,也可以在数据集搜索 viyiviyi/utils 添加
125
- frpcExePath = os.path.join(input_path,'utils-tools/frpc')
126
- # 其他需要加载的webui启动参数 写到【参数列表】这个配置去
127
- otherArgs = ' '.join([item for item in config_reader(config.sd_start_args) if item != '--no-gradio-queue']) or '--xformers'
128
-
129
- venvPath = os.path.join(input_path,'sd-webui-venv/venv.tar.bak') # 安装好的python环境 sd-webui-venv是一个公开是数据集 可以搜索添加
130
-
131
- # 用于使用kaggle api的token文件 参考 https://www.kaggle.com/docs/api
132
- # 此文件用于自动上传koishi的相关配置 也可以用于保存重要的输出文件
133
- kaggleApiTokenFile = os.path.join(input_path,'configs/kaggle.json')
134
-
135
- requirements = []
136
-
137
- frpcStartArg = ''
138
-
139
- _setting_file = replace_path(config.setting_file)
140
-
141
- _ui_config_file = replace_path(config.ui_config_file)
142
-
143
- mkdirs(f'{install_path}/configFiles',True)
144
-
145
- _frp_config_or_file = replace_path(config.frp_config_or_file)
146
- if Path(_frp_config_or_file.strip()).exists():
147
- frpcConfigFile = _frp_config_or_file.strip()
148
- if not Path(frpcConfigFile).exists():
149
- if _frp_config_or_file.strip().startswith('-f'):
150
- frpcStartArg = _frp_config_or_file.strip()
151
- else:
152
- print('没有frpcp配置')
153
- _useFrpc = False
154
- else:
155
- run(f'''cp -f {frpcConfigFile} {install_path}/configFiles/frpc_webui.ini''')
156
- frpcConfigFile = f'{install_path}/configFiles/frpc_webui.ini'
157
- run(f'''sed -i "s/local_port = .*/local_port = {_server_port}/g" {frpcConfigFile}''')
158
- frpcStartArg = f' -c {frpcConfigFile}'
159
-
160
-
161
- ngrokToken=''
162
- _ngrok_config_or_file = replace_path(config.ngrok_config_or_file)
163
- if Path(_ngrok_config_or_file.strip()).exists():
164
- ngrokTokenFile = _ngrok_config_or_file.strip()
165
- if Path(ngrokTokenFile).exists():
166
- with open(ngrokTokenFile,encoding = "utf-8") as nkfile:
167
- ngrokToken = nkfile.readline()
168
- elif not _ngrok_config_or_file.strip().startswith('/'):
169
- ngrokToken=_ngrok_config_or_file.strip()
170
-
171
- if not Path(venvPath).exists():
172
- venvPath = os.path.join(input_path,'sd-webui-venv/venv.zip')
173
-
174
- import concurrent.futures
175
- import importlib
176
- import os
177
- import pprint
178
- import re
179
- from pathlib import Path
180
- from typing import List
181
-
182
- import requests
183
-
184
- show_shell_info = False
185
-
186
-
187
- def is_installed(package):
188
- try:
189
- spec = importlib.util.find_spec(package)
190
- except ModuleNotFoundError:
191
- return False
192
-
193
- return spec is not None
194
-
195
- def download_file(url:str, filename:str, dist_path:str, cache_path = '',_link_instead_of_copy:bool=True):
196
- # 获取文件的真实文件名
197
- if not filename:
198
- with requests.get(url, stream=True) as r:
199
- if 'Content-Disposition' in r.headers:
200
- filename = r.headers['Content-Disposition'].split('filename=')[1].strip('"')
201
- r.close()
202
- if not filename and re.search(r'/[^/]+\.[^/]+$',url):
203
- filename = url.split('/')[-1]
204
-
205
- filename = re.sub(r'[\\/:*?"<>|;]', '', filename)
206
- filename = re.sub(r'[\s\t]+', '_', filename)
207
-
208
- if show_shell_info:
209
- print(f'下载 {filename} url: {url} --> {dist_path}')
210
-
211
- # 创建目录
212
- if cache_path and not Path(cache_path).exists():
213
- mkdirs(cache_path,exist_ok=True)
214
- if dist_path and not Path(dist_path).exists():
215
- mkdirs(dist_path,exist_ok=True)
216
-
217
- # 拼接文件的完整路径
218
- filepath = os.path.join(dist_path, filename)
219
-
220
- if cache_path:
221
- cache_path = os.path.join(cache_path, filename)
222
-
223
- # 判断文件是否已存在
224
- if Path(filepath).exists():
225
- print(f'文件 {filename} 已存在 {dist_path}')
226
- return
227
-
228
- if cache_path and Path(cache_path).exists():
229
- run(f'cp -n -r -f {"-s" if _link_instead_of_copy else ""} {cache_path} {dist_path}')
230
- if show_shell_info:
231
- print(f'文件缓存 {cache_path} --> {dist_path}')
232
- return
233
- # 下载文件
234
- with requests.get(url, stream=True) as r:
235
- r.raise_for_status()
236
- with open(cache_path or filepath, 'wb') as f:
237
- for chunk in r.iter_content(chunk_size=8192):
238
- if chunk:
239
- f.write(chunk)
240
- # 如果使用了缓存目录 需要复制或链接文件到目标目录
241
- if cache_path:
242
- run(f'cp -n -r -f {"-s" if _link_instead_of_copy else ""} {cache_path} {dist_path}')
243
- if show_shell_info:
244
- print(f'下载完成 {filename} --> {dist_path}')
245
-
246
- def download_git(url, dist_path, cache_path = '',_link_instead_of_copy:bool=True):
247
- if not Path(dist_path).exists():
248
- mkdirs(dist_path,exist_ok=True)
249
- if show_shell_info:
250
- print(f'git 下载 {url} --> {dist_path}')
251
- if cache_path and not Path(cache_path).exists():
252
- mkdirs(cache_path,exist_ok=True)
253
- run(f'git clone {config.git_proxy}{url}',cwd = cache_path)
254
- if cache_path:
255
- run(f'cp -n -r -f {cache_path}/* {dist_path}')
256
- else:
257
- run(f'git clone {config.git_proxy}{url}',cwd = dist_path)
258
- if show_shell_info:
259
- print(f'git 下载完成 {url} --> {dist_path}')
260
-
261
-
262
-
263
- # 加入文件到下载列表
264
- def pause_url(url:str,dist_path:str):
265
- file_name = ''
266
- if re.match(r'^[^:]+:(https?|ftps?)://', url, flags=0):
267
- file_name = re.findall(r'^[^:]+:',url)[0][:-1]
268
- url = url[len(file_name)+1:]
269
- if not re.match(r'^(https?|ftps?)://',url):
270
- return
271
- file_name = re.sub(r'\s+','_',file_name or '')
272
- path_hash = str(hash(url)).replace('-','')
273
-
274
- return {'file_name':file_name,'path_hash':path_hash,'url':url,'dist_path':dist_path}
275
-
276
- def download_urls(download_list:List[dict],sync:bool=False,thread_num:int=5,
277
- cache_path:str=os.path.join(os.getcwd(),'.cache','download_util'),
278
- _link_instead_of_copy:bool=True,is_await:bool=False):
279
- if sync:
280
- for conf in download_list:
281
- cache_dir = os.path.join(cache_path,conf['path_hash'])
282
- if conf['url'].startswith('https://github.com'):
283
- download_git(conf['url'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)
284
- continue
285
- download_file(conf['url'],conf['file_name'],conf['dist_path'],cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy)
286
- else:
287
- executor = concurrent.futures.ThreadPoolExecutor(max_workers=thread_num)
288
- futures = []
289
- for conf in download_list:
290
- cache_dir = os.path.join(cache_path,conf['path_hash'])
291
- if conf['url'].startswith('https://github.com'):
292
- futures.append(executor.submit(download_git, conf['url'],conf['dist_path'],
293
- cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))
294
- continue
295
- futures.append(executor.submit(download_file, conf['url'],conf['file_name'],conf['dist_path'],
296
- cache_path=cache_dir,_link_instead_of_copy=_link_instead_of_copy))
297
- if is_await:
298
- concurrent.futures.wait(futures)
299
-
300
-
301
- def parse_config(config:str):
302
- space_string = ' \n\r\t\'\",'
303
- other_flie_list = [item.split('#')[0].strip(space_string) for item in config.split('\n') if item.strip(space_string)]
304
- other_flie_list = [item.strip() for item in other_flie_list if item.strip()]
305
- other_flie_list_store = {}
306
- other_flie_list_store_name='default'
307
- other_flie_list_store_list_cache=[]
308
-
309
- for item in other_flie_list:
310
- if item.startswith('[') and item.endswith(']'):
311
- if not other_flie_list_store_name == 'default':
312
- other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache
313
- other_flie_list_store_list_cache = []
314
- other_flie_list_store_name = item[1:-1]
315
- else:
316
- other_flie_list_store_list_cache.append(item)
317
- other_flie_list_store[other_flie_list_store_name]=other_flie_list_store_list_cache
318
-
319
- return other_flie_list_store
320
-
321
-
322
- def link_or_download_flie(config:str, skip_url:bool=False, _link_instead_of_copy:bool=True, base_path:str = '',
323
- sync:bool=False,thread_num:int=None, is_await:bool=False):
324
- store:dict[str,List[str]] = parse_config(config)
325
- download_list = []
326
- for dist_dir in store.keys():
327
- dist_path = os.path.join(base_path,dist_dir)
328
- mkdirs(dist_path,exist_ok=True)
329
- for path in store[dist_dir]:
330
- if 'https://' in path or 'http://' in path:
331
- if skip_url:
332
- continue
333
- if sync:
334
- download_urls([pause_url(path,dist_path)],_link_instead_of_copy = _link_instead_of_copy, sync=sync)
335
- continue
336
- download_list.append(pause_url(path,dist_path))
337
- else:
338
- run(f'cp -n -r -f {"-s" if _link_instead_of_copy else ""} {path} {dist_path}')
339
- if show_shell_info:
340
- print(f'{"链接" if _link_instead_of_copy else "复制"} {path} --> {dist_path}')
341
- run(f'rm -f {dist_path}/\*.* ')
342
- if not skip_url:
343
- if show_shell_info:
344
- pprint.pprint(download_list)
345
- download_urls(download_list,_link_instead_of_copy = _link_instead_of_copy, sync=sync, thread_num=thread_num or 2,is_await=is_await)
346
-
347
-
348
- def echoToFile(content:str,path:str):
349
- if path.find('/') >= 0:
350
- _path = '/'.join(path.split('/')[:-1])
351
- mkdirs(f'{_path}',True)
352
- with open(path,'w') as sh:
353
- sh.write(content)
354
-
355
- def zipPath(path:str,zipName:str,format='tar'):
356
- if path.startswith('$install_path'):
357
- path = path.replace('$install_path',install_path)
358
- if path.startswith('$output_path'):
359
- path = path.replace('$install_path',output_path)
360
- if not path.startswith('/'):
361
- path = f'{install_path}/sd_main_dir/{path}'
362
- if Path(path).exists():
363
- if 'tar' == format:
364
- run(f'tar -cf {output_path}/'+ zipName +'.tar -C '+ path +' . ')
365
- elif 'gz' == format:
366
- run(f'tar -czf {output_path}/'+ zipName +'.tar.gz -C '+ path +' . ')
367
- return
368
- print('指定的目录不存在:'+path)
369
-
370
- # 检查网络
371
- def check_service(host, port):
372
- try:
373
- socket.create_connection((host, port), timeout=5)
374
- return True
375
- except socket.error:
376
- return False
377
-
378
- # ngrok
379
- def startNgrok(ngrokToken:str,ngrokLocalPort:int):
380
- if not is_installed('pyngrok'):
381
- run(f'pip install pyngrok')
382
- from pyngrok import conf, ngrok
383
- try:
384
- conf.get_default().auth_token = ngrokToken
385
- conf.get_default().monitor_thread = False
386
- ssh_tunnels = ngrok.get_tunnels(conf.get_default())
387
- if len(ssh_tunnels) == 0:
388
- ssh_tunnel = ngrok.connect(ngrokLocalPort)
389
- print('ngrok 访问地址:'+ssh_tunnel.public_url)
390
- else:
391
- print('ngrok 访问地址:'+ssh_tunnels[0].public_url)
392
- except:
393
- print('启动ngrok出错')
394
-
395
- def startFrpc(name,configFile):
396
- echoToFile(f'''
397
- cd {install_path}/frpc/
398
- {install_path}/frpc/frpc {configFile}
399
- ''',f'{install_path}/frpc/start.sh')
400
- os.system(f'''bash {install_path}/frpc/start.sh''')
401
-
402
- def installProxyExe():
403
- if _useFrpc:
404
- print('安装frpc')
405
- mkdirs(f'{install_path}/frpc',True)
406
- if Path(frpcExePath).exists():
407
- run(f'cp -f -n {frpcExePath} {install_path}/frpc/frpc')
408
- else:
409
- run(f'wget "https://huggingface.co/datasets/ACCA225/Frp/resolve/main/frpc" -O {install_path}/frpc/frpc')
410
-
411
- for ssl in frpcSSLFFlies:
412
- if Path(ssl).exists():
413
- run(f'cp -f -n {ssl}/* {install_path}/frpc/')
414
- run(f'chmod +x {install_path}/frpc/frpc')
415
- run(f'{install_path}/frpc/frpc -v')
416
- if _useNgrok and not is_installed('pyngrok'):
417
- run('pip install pyngrok')
418
-
419
- def startProxy():
420
- if _useNgrok:
421
- startNgrok(ngrokToken,_server_port)
422
- if _useFrpc:
423
- startFrpc('frpc_proxy',frpcStartArg)
424
-
425
-
426
- # nginx 反向代理配置文件
427
- def localProxy():
428
- conf = '''
429
- server
430
- {
431
- listen '''+str(_server_port)+''';
432
- listen [::]:'''+str(_server_port)+''';
433
- server_name 127.0.0.1 localhost 0.0.0.0 "";
434
-
435
- if ($request_method = OPTIONS) {
436
- return 200;
437
- }
438
- fastcgi_send_timeout 10m;
439
- fastcgi_read_timeout 10m;
440
- fastcgi_connect_timeout 10m;
441
- location /1/
442
- {
443
- proxy_pass http://127.0.0.1:'''+str(_server_port+2)+'''/;
444
- # add_header Set-Cookie "subpath=1; expires=0; Path=/";
445
- # proxy_set_header Set-Cookie "subpath=1; expires=0; Path=/";
446
- proxy_set_header Host $host;
447
- proxy_set_header X-Real-IP $remote_addr;
448
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
449
- proxy_set_header REMOTE-HOST $remote_addr;
450
- proxy_set_header Upgrade $http_upgrade;
451
- proxy_set_header Connection upgrade;
452
- proxy_http_version 1.1;
453
- proxy_connect_timeout 10m;
454
- proxy_read_timeout 10m;
455
- }
456
- location /
457
- {
458
- set $proxy_url http://127.0.0.1:'''+str(_server_port+1)+''';
459
- # if ($cookie_subpath = "1") {
460
- # set $proxy_url http://127.0.0.1:'''+str(_server_port+2)+''';
461
- # }
462
- proxy_pass $proxy_url;
463
- proxy_set_header Host $host;
464
- proxy_set_header X-Real-IP $remote_addr;
465
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
466
- proxy_set_header REMOTE-HOST $remote_addr;
467
- proxy_set_header Upgrade $http_upgrade;
468
- proxy_set_header Connection upgrade;
469
- proxy_http_version 1.1;
470
- proxy_connect_timeout 10m;
471
- proxy_read_timeout 10m;
472
- }
473
- }
474
- '''
475
- echoToFile(conf,'/etc/nginx/conf.d/proxy_nginx.conf')
476
- if not check_service('localhost',_server_port):
477
- run(f'''nginx -c /etc/nginx/nginx.conf''')
478
- os.system(f'''nginx -s reload''')
479
-
480
-
481
- import inspect
482
- import ctypes
483
-
484
- def _async_raise(tid, exctype):
485
- """raises the exception, performs cleanup if needed"""
486
- tid = ctypes.c_long(tid)
487
- if not inspect.isclass(exctype):
488
- exctype = type(exctype)
489
- res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
490
- if res == 0:
491
- raise ValueError("invalid thread id")
492
- elif res != 1:
493
- # """if it returns a number greater than one, you're in trouble,
494
- # and you should call it again with exc=NULL to revert the effect"""
495
- ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
496
- raise SystemError("PyThreadState_SetAsyncExc failed")
497
-
498
- def stop_thread(thread):
499
- _async_raise(thread.ident, SystemExit)
500
-
501
- def stop_solo_threads():
502
- # 获取当前所有活动的线程
503
- threads = threading.enumerate()
504
- # 关闭之前创建的子线程
505
- for thread in threads:
506
- if thread.name.startswith('solo_'):
507
- print(f'结束线程:{thread.name}')
508
- try:
509
- stop_thread(thread)
510
- except socket.error:
511
- print(f'结束线程:{thread.name} 执行失败')
512
-
513
-
514
- envInstalled=False
515
- quickStart = True
516
- #安装
517
- def install():
518
- print('安装')
519
- os.chdir(f'''{install_path}''')
520
- run(f'''git lfs install''')
521
- run(f'''git config --global credential.helper store''')
522
- for requirement in requirements:
523
- run(f'pip install {requirement}')
524
- if _reLoad:
525
- run(f'''rm -rf sd_main_dir''')
526
- if Path("sd_main_dir").exists():
527
- os.chdir(f'''{install_path}/sd_main_dir/''')
528
- run(f'''git checkout .''')
529
- run(f'''git pull''')
530
- else:
531
- run(f'''git clone {config.git_proxy}{_sd_git_repo} sd_main_dir''')
532
- os.chdir(f'''{install_path}/sd_main_dir''')
533
- print('安装 完成')
534
-
535
- # 链接输出目录
536
- def link_dir():
537
- print('链接输出目录')
538
- # 链接图片输出目录
539
- mkdirs(f'{output_path}/outputs',True)
540
- run(f'''rm -rf {install_path}/sd_main_dir/outputs''')
541
- run(f'''ln -s -r {output_path}/outputs {install_path}/sd_main_dir/''')
542
- # 输出收藏目录
543
- mkdirs(f'{output_path}/log',True)
544
- run(f'''rm -rf {install_path}/sd_main_dir/log''')
545
- run(f'''ln -s -r {output_path}/log {install_path}/sd_main_dir/''')
546
- # 链接训练输出目录 文件夹链接会导致功能不能用
547
- run(f'''rm -rf {install_path}/sd_main_dir/textual_inversion''')
548
- mkdirs(f'{output_path}/textual_inversion/',True)
549
- run(f'''ln -s -r {output_path}/textual_inversion {install_path}/sd_main_dir/''')
550
- print('链接输出目录 完成')
551
-
552
- def install_optimizing():
553
- run('sudo apt install nginx -y')
554
- run('env TF_CPP_MIN_LOG_LEVEL=1')
555
- run('sudo apt -y update -qq')
556
- run('wget http://launchpadlibrarian.net/367274644/libgoogle-perftools-dev_2.5-2.2ubuntu3_amd64.deb')
557
- run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/google-perftools_2.5-2.2ubuntu3_all.deb')
558
- run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libtcmalloc-minimal4_2.5-2.2ubuntu3_amd64.deb')
559
- run('wget https://launchpad.net/ubuntu/+source/google-perftools/2.5-2.2ubuntu3/+build/14795286/+files/libgoogle-perftools4_2.5-2.2ubuntu3_amd64.deb')
560
- run('sudo apt -y install -qq libunwind8-dev')
561
- run('dpkg -i *.deb')
562
- run('env LD_P_reLoad=libtcmalloc.so')
563
- run('rm *.deb')
564
-
565
- #安装依赖
566
- def install_dependencies():
567
- print('安装需要的python环境')
568
- global envInstalled
569
- global venvPath
570
- run(f'''rm -rf {install_path}/sd_main_dir/venv''')
571
- mkdirs(f'{install_path}/sd_main_dir/venv',True)
572
- if str(sys.version).startswith('3.10'):
573
- try:
574
- run('python3 -m venv venv' ,cwd=f'{install_path}/sd_main_dir',try_error=False)
575
- except:
576
- run('sudo apt install python3.10-venv -y')
577
- run('python3 -m venv venv' ,cwd=f'{install_path}/sd_main_dir')
578
- else:
579
- run('add-apt-repository ppa:deadsnakes/ppa -y')
580
- run('sudo apt update')
581
- run('sudo apt install python3.10 -y')
582
- run('python3.10 -m venv venv',cwd=f'{install_path}/sd_main_dir')
583
-
584
- if quickStart:
585
- if not Path(venvPath).exists():
586
- mkdirs(f'{install_path}/venv_cache',True)
587
- if not Path(f'{install_path}/venv_cache/venv.tar.bak').exists():
588
- download_file('https://huggingface.co/viyi/sdwui/resolve/main/venv.zip','venv.zip',f'{install_path}/venv_cache')
589
- run(f'''unzip {install_path}/venv_cache/venv.zip -d {install_path}/venv_cache''')
590
- venvPath = f'{install_path}/venv_cache/venv.tar.bak'
591
- run(f'''rm -rf {install_path}/venv_cache/venv.zip''')
592
- elif venvPath.endswith('.zip'):
593
- mkdirs(f'{install_path}/venv_cache',True)
594
- run(f'''unzip {venvPath} -d {install_path}/venv_cache''')
595
- venvPath = f'{install_path}/venv_cache/venv.tar.bak'
596
- print('解压环境')
597
- run(f'tar -xf {venvPath} -C ./venv',cwd=f'{install_path}/sd_main_dir')
598
- run(f'rm -rf {install_path}/sd_main_dir/venv.lib')
599
- if not Path(f'{install_path}/sd_main_dir/venv/bin/pip').exists():
600
- run('curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py')
601
- run(f'{install_path}/sd_main_dir/venv/bin/python3 get-pip.py')
602
-
603
- os.system(f'''{install_path}/sd_main_dir/venv/bin/python3 -V''')
604
- os.system(f'''{install_path}/sd_main_dir/venv/bin/python3 -m pip -V''')
605
-
606
- envInstalled = True
607
- print('安装需要的python环境 完成')
608
-
609
- # 个性化配置
610
- def use_config():
611
- print('使用自定义配置 包括tag翻译 \n')
612
- mkdirs(f'{install_path}/temp',True)
613
- run(f'git clone {config.git_proxy}{_sd_config_git_repu} sd-configs',cwd=f'{install_path}/temp')
614
- run(f'cp -r -f -n {install_path}/temp/sd-configs/dist/* {install_path}/sd_main_dir')
615
- if not Path(_ui_config_file).exists(): # ui配置文件
616
- mkdirs(f"{_ui_config_file[:_ui_config_file.rfind('/')]}",True)
617
- run(f'cp -f -n {install_path}/sd_main_dir/ui-config.json {_ui_config_file}')
618
- if not Path(_setting_file).exists(): # 设置配置文件
619
- mkdirs(f"{_setting_file[:_setting_file.rfind('/')]}",True)
620
- run(f'cp -f -n {install_path}/sd_main_dir/config.json {_setting_file}')
621
-
622
- def copy_last_log_to_images():
623
- print('复制编号最大的一张收藏图到输出目录,用于保持编号,否则会出现收藏的图片被覆盖的情况')
624
- img_list = os.listdir(f'{install_path}/sd_main_dir/log/images')
625
- last_img_path = ''
626
- last_img_num = 0
627
- for img in img_list:
628
- if re.findall(r'^\d+-',str(img)):
629
- num = int(re.findall(r'^\d+-',str(img))[0][:-1])
630
- if num > last_img_num:
631
- last_img_path = img
632
- last_img_num = num
633
- print(f'{install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/txt2img-images')
634
- mkdirs(f"{install_path}/sd_main_dir/outputs/txt2img-images",True)
635
- run(f'''cp -f {install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/txt2img-images/''')
636
-
637
- print(f'{install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/img2img-images')
638
- mkdirs(f"{install_path}/sd_main_dir/outputs/img2img-images",True)
639
- run(f'''cp -f {install_path}/sd_main_dir/log/images/{last_img_path} {install_path}/sd_main_dir/outputs/img2img-images/''')
640
-
641
- def start_webui(i):
642
- # 只要不爆内存,其他方式关闭后会再次重启 访问地址会发生变化
643
- print(i,'--port',str(_server_port+1+i))
644
- if i>0:
645
- print(f'使用第{i+1}张显卡启动第{i+1}个服务,通过frpc或nrgok地址后加/{i}/进行访问(不能使用同一个浏览器)')
646
- if _useFrpc:
647
- restart_times = 0
648
- last_restart_time = time.time()
649
- while True:
650
- os.system(f'''{install_path}/sd_main_dir/venv/bin/python3 launch.py --device-id={i} --port {str(_server_port+1+i)} {'' if i ==0 else '--nowebui'}''')
651
- print('5秒后重启服务')
652
- if time.time() - last_restart_time < 30:
653
- restart_times = restart_times + 1
654
- else:
655
- restart_times = 0
656
- last_restart_time = time.time()
657
- if restart_times >3 :
658
- # 如果90秒内重启了3此,将不再自动重启
659
- break
660
- time.sleep(5)
661
- else:
662
- os.system(f'''{install_path}/sd_main_dir/venv/bin/python3 launch.py --device-id={i} --port {str(_server_port+1+i)} {'' if i ==0 else '--nowebui'}''')
663
-
664
- # 启动
665
- def start():
666
- print('启动')
667
- os.chdir(f'''{install_path}/sd_main_dir''')
668
- args = ''
669
- if _ui_config_file is not None and _ui_config_file != '' and Path(_ui_config_file).exists(): # ui配置文件
670
- args += ' --ui-config-file=' + _ui_config_file
671
- if _setting_file is not None and _setting_file != '' and Path(_setting_file).exists(): # 设置配置文件
672
- args += ' --ui-settings-file=' + _setting_file
673
- args += ' ' + otherArgs
674
- os.environ['COMMANDLINE_ARGS']=args
675
- run(f'''echo COMMANDLINE_ARGS=$COMMANDLINE_ARGS''')
676
- os.environ['REQS_FILE']='requirements.txt'
677
- start_webui(0)
678
-
679
-
680
- # 启动非webui相关的的内容,加快启动速度
681
- def main():
682
- global envInstalled
683
- global huggingface_is_init
684
- startTicks = time.time()
685
- stop_solo_threads()
686
- isInstall = True if os.getenv('IsInstall','False') == 'True' else False
687
- if Path(f'{install_path}/sd_main_dir').exists():
688
- isInstall = True
689
- if isInstall is False or _reLoad:
690
- print('启动 安装和运行环境')
691
- install()
692
- link_dir()
693
- threading.Thread(target = install_dependencies,daemon=True,name='solo_install_dependencies').start()
694
- threading.Thread(target = install_optimizing,daemon=True,name='solo_install_optimizing').start()
695
- threading.Thread(target = installProxyExe,daemon=True).start()
696
- link_or_download_flie(replace_path(_async_downloading), _link_instead_of_copy=_link_instead_of_copy,
697
- base_path=f'{install_path}/sd_main_dir')
698
-
699
- link_or_download_flie(replace_path(_before_downloading), _link_instead_of_copy=_link_instead_of_copy,
700
- base_path=f'{install_path}/sd_main_dir',is_await=True)
701
- t = 0
702
- while not envInstalled:
703
- if t%10==0:
704
- print('等待python环境安装...')
705
- t = t+1
706
- time.sleep(1)
707
- use_config()
708
- localProxy()
709
- os.environ['IsInstall'] = 'True'
710
- else:
711
- envInstalled = True
712
- link_or_download_flie(replace_path(_before_start_sync_downloading), _link_instead_of_copy=_link_instead_of_copy,
713
- base_path=f'{install_path}/sd_main_dir',sync=True)
714
- threading.Thread(target = startProxy, daemon=True, name='solo_startProxy').start()
715
- ticks = time.time()
716
- print("安装耗时:",(ticks - startTicks),"秒")
717
- start()
718
-
719
-
720
- if _skip_start:
721
- print('已跳过自动启动,可手动执行 main() 进行启动。')
722
- print('''推荐的启动代码:
723
- try:
724
- check_gpu() # 检查是否存在gpu
725
- main()
726
- except KeyboardInterrupt:
727
- stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)
728
- ''')
729
- else:
730
- try:
731
- main()
732
- except KeyboardInterrupt:
733
- stop_solo_threads()
734
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stable-diffusion-webui-novelai-sdxl.ipynb DELETED
@@ -1 +0,0 @@
1
- {"cells":[{"cell_type":"markdown","metadata":{},"source":["# NovelAi stable-diffusion-webui+api+sdxl\n","---\n","**version: 1.6.0  •  python: 3.10.6  •  torch: 2.0.1+cu118  •  xformers: 0.0.21  •  gradio: 3.41.2**\n","- 发布地址 [kaggle stable-diffusion-webui-novelai](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)\n","- 这是一个用于快速体验ai绘画项目 [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 的笔记本,你可以直接启动就能在线体验ai绘图的乐趣。 \n","- kaggle和colab都是AI学习平台,请勿浪费计算资源,如果有需求,可以考虑AutoDL这类租用显卡的平台或者colab付费使用。\n","- 在保持可以免配置直接启动的情况下也提供了很多可自定义的配置,在下方的配置项里,请自行查看。 \n","- 同时也为新人提供了一份基础的帮助文档,包含了一些使用中可能遇到的问题,如果使用过程中有什么疑问,不妨先看看帮助文档。\n","- 如果你需要在此脚本上修改再发布,请随意,但请遵守相关法律法规,文明使用。\n","- 使用时如果遇到问题,尽可能通过帮助文档或者参考已有内容尝试自己解决。\n","- Q群 [816545732](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=OGQydingTPku9M_myV_cscWv6MVaCSde&authKey=RFadQ18FgReFkx7CRs8SNk4vHpxHz%2FD2ojHL3433MehuQOBlnG0hhWFIo8AX%2BFRU&noverify=0&group_code=816545732) ,这是我建的新群,如果有需要,可以进群,其实这个笔记已经非常简洁了,进群大概也不会有啥帮助。\n","- 使用前可以看一下最后的更新日志,可能有功能更新需要注意"]},{"cell_type":"markdown","metadata":{},"source":["## 重要文件列表\n","\n","- **这个列表仅加载一次 且会等待加载完成再开始安装sd**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["before_downloading = '''# 这个列表仅加载一次 且会等待加载完成再开始安装sd\n","[extensions] # 插件 如果你需要增加插件,把插件地址写到这来就行,支持git仓库和文件夹路径\n","https://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\n","https://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\n","https://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\n","https://github.com/Mikubill/sd-webui-controlnet.git\n","https://github.com/ilian6806/stable-diffusion-webui-state.git\n","https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\n","https://github.com/Bing-su/adetailer.git\n","https://github.com/zanllp/sd-webui-infinite-image-browsing.git\n","https://github.com/viyiviyi/stable-diffusion-webui-zoomimage.git\n","https://github.com/viyiviyi/sd-encrypt-image.git # 图片加密插件,解决涩图封号问题,需要在参数里设置你的密码开启\n","\n","# 如果你有模型文件需要在启动前加载,可以写在这个下面对应位置\n","\n","[models/Stable-diffusion] # 大模型列表\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","\n","[models/VAE] # VAE文件列表\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","\n","'''"]},{"cell_type":"markdown","metadata":{},"source":["## 普通文件列表\n","\n","- **这个列表仅加载一次 且不会等待加载完成**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["async_downloading='''# 这个列表仅加载一次 且不会等待加载完成\n","[extensions] # 插件 如果你没有使用ngrok或者frpc,请不要把插件放在这里加载,因为这里的文件可能在webui启动后才加载完成\n","\n","[models/Stable-diffusion] # 大模型列表\n","https://huggingface.co/viyi/testing_models/resolve/main/mg-LBG.safetensors\n","容华_国风_SDXL.safetensors:https://civitai.com/api/download/models/151978\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","Genshin_Impact_all-in-one.safetensors:https://civitai.com/api/download/models/116970\n","https://civitai.com/api/download/models/117151 # Clothing +/- Adjuster 衣物增/减 LoRA\n","https://civitai.com/api/download/models/62833 # Detail Tweaker LoRA (细节调整LoRA)\n","\n","[models/VAE] # VAE文件列表\n","{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-ema-560000-ema-pruned.safetensors\n","{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-mse-840000-ema-pruned.safetensors\n","https://huggingface.co/stabilityai/sd-vae-ft-ema-original/resolve/main/vae-ft-ema-560000-ema-pruned.safetensors\n","https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\n","sdxl_vae.safetensors:https://civitai.com/api/download/models/130720?type=VAE # sdxl模型需要sdxl的vae\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors\n","https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors\n","'''\n"]},{"cell_type":"markdown","metadata":{},"source":["## 按顺序加载的重要文件列表\n","\n","- **这个列表每次 run all 启动都会加载一次,且一定按照顺序加载后才启动webui**\n","- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n","- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n","- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n","- 如果需要下载到其他目录,可以使用同样的格式写其他目录"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["before_start_sync_downloading = ''' # 这个列表每次 run all 启动都会加载一次,且一定按照顺序加载\n","\n","# 如果你需要每次启动都加载一下文件,可以写在这。(比如测试路径是否正确的时候)\n","\n","[models/Stable-diffusion] # 大模型列表\n","\n","[models/hypernetworks] # hypernetworks文件列表\n","\n","[models/embeddings] # embeddings文件列表\n","\n","[models/Lora] # Lora文件列表\n","\n","[models/VAE] # VAE文件列表\n","\n","[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n","\n","'''"]},{"cell_type":"markdown","metadata":{},"source":["## webui 启动参数\n","- 所有的参数都会在启动时传入\n","- 可以在前面加```#```来屏蔽某个参数\n","- 端口参数需要在下一个代码块的```webuiPort```处修改"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["sd_start_args='''\n","# --ckpt=mg-Tender.safetensors # 默认模型名称,路径不能包含空格\n","--disable-safe-unpickle \n","--deepdanbooru \n","--no-hashing \n","--no-download-sd-model \n","--administrator\n","--skip-torch-cuda-test \n","--skip-version-check \n","--disable-nan-check\n","# --opt-sdp-attention \n","--opt-sdp-no-mem-attention \n","--xformers-flash-attention\n","--xformers\n","--api \n","--listen\n","--lowram\n","#--no-gradio-queue\n","#--encrypt-pass=123qwe # 图片加密插件的密码,如果要启用图片加密插件,删除这一行前面的#和将123qwe改成你的密码,也可以不改\n","# --share # 默认的内网穿透在kaggle和colab都已经不可用,请考虑其他方案\n","--disable-console-progressbars\n","--no-half-vae \n","# --no-half #关闭半精度\n","# --enable-console-prompts\n","# --nowebui # 如果只需要api服务,可以开启这个\n","# --api-auth=2333:6666 # api密码\n","# --gradio-auth=2333:6666 # webui密码\n","'''"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才会生效\n","#Ngrok\n","useNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n","#Frpc\n","useFrpc=True # 开启frp将不能启动\n","\n","#可以填写文件路径 或 直接填 token 内容\n","ngrok_config_or_file = '''\n","{input_path}/configs/ngrok_token.txt\n","'''\n","frp_config_or_file = '''\n","{input_path}/configs/frpc_litechat.ini\n","'''\n","frp_ssl_dir = '''\n","{input_path}/configs/litechat_nginx\n","'''\n","\n","# 配置启动参数\n","server_port=7860 # webui 默认端口\n","\n","# 仓库地址 这是修改过界面布局顺序的webui,不定期同步到官方版本\n","# 如果要使用官方版本,改成这个: https://github.com/AUTOMATIC1111/stable-diffusion-webui\n","sd_git_repo='https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n","# 配置文件,包括webui的设置和UI默认值,如果要自定义,fork这个仓库后修改并把地址替换这个地址\n","sd_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git'\n","# 设置文件保存路径 当使用谷歌云盘时非常有用\n","setting_file = '{output_path}/configs/config.json'\n","ui_config_file = '{output_path}/configs/ui-config.json'\n","\n","# 这是配置文件夹同步的相关配置\n","# 需要在huggingface创建一个数据集(datasets) 然后把数据集的名称(在页面上有复制的按钮)填到 huggingface_repo \n","# 需要获取 token 填到 huggingface_token 获取的地址是: https://huggingface.co/settings/tokens\n","huggingface_token = '{input_path}/configs/huggingface_token_file.txt'\n","huggingface_repo = 'viyi/sdwui-imgs'\n"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["link_instead_of_copy = True # 下载或加载Input的文件时是使用链接还是复制的方式加载到目标目录\n","hidden_console_info = True # 是否隐藏大部分的控制台内容"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 保存当前目录和启动时cd到之前保存的目录,可以减少sdwui-start-new.ipynb文件下载次数\n","import os\n","INIT_WORK_PATH = os.environ['HOME']\n","if os.getenv('INIT_WORK_PATH',''):\n"," INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\n","else:\n"," os.environ['INIT_WORK_PATH'] = os.getcwd()\n","%cd {INIT_WORK_PATH}"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["reLoad = True\n","# 如果需要重新安装,请注释下面这一行\n","reLoad = False"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["if not os.path.exists('sdwui-start-util.ipynb'):\n"," !wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start-util.ipynb -o log.log\n","%run sdwui-start-util.ipynb"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["try:\n"," check_gpu() # 检查是否存在gpu\n"," main()\n","except KeyboardInterrupt:\n"," stop_solo_threads() # 中断后自动停止后台线程 (有部分功能在后台线程中运行)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# 打包收藏文件夹 如果需要可以取消下面两行的注释\n","# zipPath('$install_path/sd_main_dir/log','log')\n","# !mv {output_path}/log.tar {output_path}/log.tar.bak\n","# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n","\n","# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n","# zipPath('$install_path/sd_main_dir/textual_inversion','训练输出') \n","# zipPath('$install_path/sd_main_dir/outputs','outputs')\n","\n","# 打包venv并上传到数据集\n","# zipPath('$install_path/sd_main_dir/venv','venv')\n","# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n","# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n","\n","# 打包命令参考,--exclude 可以排除不需要打包的目录\n","# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /sd_main_dir/ ."]},{"cell_type":"markdown","metadata":{},"source":["# 使用帮助\n","---\n","**代码块不能删除也不能调换顺序,如果出现变量未定义,请检查是否按顺序执行了代码块**\n","\n","---\n","\n","## kaggle账号\n","- 注册账号需要手机号,国内手机号也行,如果点击注册后没反应,估计是需要梯子,用于人机验证\n","- 注册后点此笔记的 **Copy & Edit** 按钮就进到编辑界面\n","\n","## 准备工作\n","1. 右侧面板 **Notebook options/ACCELERATOR** 需要选择GPU **T4x2**出图更快\n","2. 右侧面板 **Notebook options/LANGUAGE** 需要选择Python\n","2. 右侧面板 **Notebook options/PERSISTENCE** 建议选择 Files only **作用是保存Outpot目录内的文件,当前这个功能并没有任何作用**\n","3. 右侧面板 **Notebook options/ENVIRONMENT** 建议不改这个配置,使用当前默认值就行\n","4. 右侧面板 **Notebook options/INTERNET** 需要打开 用于联网\n","\n","## 启动\n","#### 启动方式一 **直接点击页面上边的 RunAll**\n","- 手机端可能会出现页面上边的工具栏不显示的情况,左侧菜单按钮里也有相关的操作\n","- 长时间不操作页面会导致脚本停止 (应该是40分钟吧)\n","\n","#### 启动方式二 **使用页面上边的 Save Version 后台运行**\n","- 后台运行不用担心长时间不操作脚本停止\n","- Version Type 选择 **Save & Run All**\n","- 在Save Version弹窗里需要选择使用**GPU**环境 (Advanced Settings 里最后一个选项)\n","\n","## 访问\n","- 如果你使用了ngrok或者frpc,可以访问你这两对应的地址\n","- 如果你不知道你的ngrok或者frpc的地址可以在控制台(页面最下方Console)的输出里面查看\n","- 使用Run All方式启动,控制台在启动完成后会输出访问网址,网址内容包含**gradio.live**,可以在页面中搜索快速找到\n","- 如果使用Save Verson的方式启动,点击左下角的**View Active Events**点击刚刚启动的脚步,在**Log**里找访问网址\n","- 一般情况下第一次启动此脚本需要等待kaggle下载模型文件,进度在页面上方\n","- 第二次及以后(不增加新的文件)需要3到5分钟\n","\n","## 增加模型\n","- 可以直接写模型的下载链接,省去下面这些步骤\n","1. 先创建数据集,也就是dataset\n","2. 创建时需要添加文件,选择自己的模型文件就行\n","3. 同类型文件放相同的数据集里面,一个数据集也不要太大\n","4. 可以在dataset搜索其他人上传的模型\n","5. 通过右侧的 **Add Data** 按钮选择已经上传的模型文件或者别人上传的模型文件\n"," - input 下面的列表就是模型文件,可以点击名称后面的复制按钮复制路径\n","6. 将模型路径放在配置里的对应配置里即可,支持文件夹和文件路径,参考 **modelDirs**\n"," - 如果目录里还有子目录也是需要加载的,可以用*表示子目录 例子:比如Loras目录下还有角色、画风、涩涩的文件夹,那路径里写成 '/kaggle/input/Loras/*'就可以加载子目录里面的文件了\n"," - 模型加载使用的文件链接方式,如果你融模型的时候新模型名字和原有模型名字一样,会出现不能修改只读文件的错误\n"," - 同理,直接对模型做编辑的工具可能也会出现相同的错误\n"," \n"," \n","- **受到kaggle内存大小的影响,切换多个模型后大概率爆内存导致停止运行**\n"," \n","**下边的配置项都写了对应配置的作用和使用说明,不理解的话也不用改,用默认的就好**\n","\n","## 下载文件\n","#### 方式一\n","- 在浏览器直接下 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n"," - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n"," - 你的访问地址是 https://123123123.gradio.live\n"," - 则可以在浏览器输入 https://123123123.gradio.live/file=/kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors 下载你的文件\n"," \n","#### 方式二\n","- 复制到Output目录下载 仅支持使用Run All方式运行的\n"," - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n"," - 先停止笔记本(不是关机,是停止)\n"," - 然后新建一个代码块,在里面输入 !cp -f /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n"," - 或者 新建一个代码块,在里面输入 !cp -f \\$install_path/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n"," - 你可能需要拼接路径 如果是在webui里面看到的路径,且路径里面没有带**stable-diffusion-webui**\n"," - 拼接方式是 **\\$install_path/stable-diffusion-webui** + **文件路径** 拼成类似前一条的样子\n"," - 就可以在右侧列表的Output目录看见复制出来的文件,点击下载即可\n","\n","## **一些可能没用的说明**\n","- 配置说明 **True或者False**表示布尔值 **True**表示“**是**” **False**表示“**否**” 只有这两个值\n","- 配置说明 **[]** 表示数组,里面可以存放内容,每个内容需要用**英语(半角)逗号**隔开\n","- 配置说明 **''或者\"\"** 英语(半角)的双引号或者单引号包裹的内容是**字符串**,比如放在数组里面的路径就需要是一个字符串\n","- 配置说明 **#** **#** 后面的内容是**注释**,是帮助性内容,对整个代码的执行不会有影响\n"]},{"cell_type":"markdown","metadata":{},"source":["# 更新记录\n","#### 231011 v180\n","- 增加了图片加密插件,默认不启用,请查看启动参数部分设置密码启动,批量解密图片可以查看插件的发布地址\n","\n","#### 230920 v177\n","- 默认不再开启gradio这个内网穿透\n","- 更新了一些文档和说明\n","\n","#### 230910 v175\n","- 增加了默认的sdxl模型\n","- 修改了不合适的使用说明\n","\n","#### 230901 v173\n","- 更新了依赖版本,可以加载sdxl模型了\n","- 增加代码块内容说明,希望有用\n","\n","#### 230812 v171\n","- 把关闭半精度的参数注释了,这是之前写错的,注释后不容易爆内存\n","- 增加默认模型的参数,用于指定模型启动时默认的模型\n","\n","#### 230726 v170\n","- 更新了整个配置,可以更加自由的下载和加载文件\n","- 删除了大部分参数\n","\n","#### 230726 v169\n","- 增加了一个文件加载配置,可以自定义把文件或下载地址加载到指定目录,配置方式见 [ 其他文件列表 ]\n","- 增加了一个配置,可以隐藏部分控制台输出,但隐藏不完全,没啥用\n","\n","#### 230719 v168\n","- 增加了同步收藏文件夹到 huggingface 数据集的功能,仅同步收藏文件夹,如果同步所有图片也太浪费资源了\n","\n","#### 230716 v167\n","- 账号解封了\n","- 已经更新为精简自动更新版,主要逻辑分离存放到 [huggingface](https://huggingface.co/viyi/sdwui),这边基本上不再需要更新\n","- 如果增加了新功能需要新的配置,可以在输出内容的最前面查看到(暂定)\n","\n","#### 230302 v165\n","- 可以修改disableShared=True来使用pm2启动,做到爆内存自动重启(需要使用frpc或者ngrok代理,否则无法访问界面)\n","\n","#### 230228 v156\n","- 移除了koishi的相关功能 如需使用,可查看 [sd-webui-koishi](https://www.kaggle.com/code/yiyiooo/sd-webui-koishi)\n","\n","#### 230227 v147\n","- 增加了nginx做反向代理,现在可以使用一个ngrok地址访问多个服务了 功能在版本156移除\n","\n","#### 230225 v139\n","- 可以加载ssl证书,启动https的隧道了\n","\n","#### 230224 v134\n","- 可以自动修改frp的本地端口\n","\n","#### 230224 v128\n","- 修复默认模型文件不存在时不能启动的问题\n","- 修复了多线程导致依赖等内容安装位置错乱的问题\n","- 修复了第一次启动会更新koishi数据对应的数据集问题\n","- 增加了配置检查功能,对一些配置项做了提示\n","- 增加了可配置webui端口功能,现在可以配置webui、froc、ngrok的端口了\n","\n","#### 230223 v126\n","- 修复了仅适用koishi数据目录无法启动koishi的问题\n","- 修改了部分文档\n","\n","#### 230223 v124\n","- 修复使用多线程后出现的文件安装下载目录失败的问题\n","- 修复使用多线程后文件目录错乱问题\n","\n","#### 230222 v123\n","- 使用多线程进行安装,节省安装时间\n","\n","#### 230222 v122\n","- 更改了默认配置,现在训练的输出可以在Output下面查看了\n","\n","#### 230222 v118\n","- 增加了自动上传koishi的数据到数据集且能自动下载的功能\n"," - 自动上传的数据集优先级高于手动上传的\n"," - 上一个版本的数据集与当前版本的目录结构有差异,如果更新后需要修改配置\n"," \n","#### 230121 v111\n","- 增加了koishi的部署相关功能 功能在版本156移除\n","\n","#### 230220 v110\n","- 增加了ControlNet插件的一些说明\n","\n","#### 230220 v109\n","- 修复第二次Run all时不能切换到新的frpc配置问题\n","- 增加更新记录,用于记录每次更新 "]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.4"}},"nbformat":4,"nbformat_minor":4}
 
 
stable-diffusion-webui-novelai.ipynb DELETED
@@ -1 +0,0 @@
1
- {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# NovelAi stable-diffusion-webui+api+sdxl\n---\n**version: 1.6.0  •  python: 3.10.6  •  torch: 2.0.1+cu118  •  xformers: 0.0.21  •  gradio: 3.41.2**\n- 发布地址 [kaggle stable-diffusion-webui-novelai](https://www.kaggle.com/code/yiyiooo/stable-diffusion-webui-novelai)\n- 这是一个用于快速体验ai绘画项目 [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 的笔记本,你可以直接启动就能在线体验ai绘图的乐趣。 \n- 在保持可以免配置直接启动的情况下也提供了很多可自定义的配置,在下方的配置项里,请自行查看。 \n- 同时也为新人提供了一份基础的帮助文档,包含了一些使用中可能遇到的问题,如果使用过程中有什么疑问,不妨先看看帮助文档。\n- 如果你需要在此脚本上修改再发布,请随意,但请遵守相关法律法规,文明使用。\n- 交流群632428790 这是 [qq2575044704](https://www.kaggle.com/qq2575044704) 的群,感谢他为这个笔记做了一些宣传。\n","metadata":{}},{"cell_type":"markdown","source":"## 重要文件列表\n\n- **这个列表仅加载一次 且会等待加载完成**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"重要文件列表 = '''# 这个列表仅加载一次 且会等待加载完成\n[extensions] # 插件\nhttps://github.com/dtlnor/stable-diffusion-webui-localization-zh_CN.git\nhttps://github.com/AlUlkesh/stable-diffusion-webui-images-browser.git\nhttps://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git\nhttps://github.com/Mikubill/sd-webui-controlnet.git\nhttps://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris.git\nhttps://github.com/LianZiZhou/sd-webui-pixink-console.git\nhttps://github.com/ilian6806/stable-diffusion-webui-state.git\nhttps://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111.git\nhttps://github.com/Bing-su/adetailer.git\nhttps://github.com/civitai/sd_civitai_extension.git\nhttps://github.com/zanllp/sd-webui-infinite-image-browsing.git\nhttps://github.com/viyiviyi/stable-diffusion-webui-zoomimage.git\n\n# 如果你有模型文件需要在启动前加载,可以写在这个下面对应位置\n\n[models/Stable-diffusion] # 大模型列表\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\n\n[models/LyCORIS] # LyCORIS文件列表\n\n[models/VAE] # VAE文件列表\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 普通文件列表\n\n- **这个列表仅加载一次 且不会等待加载完成**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"普通文件列表='''# 这个列表仅加载一次 且不会等待加载完成\n[extensions] # 插件 如果你没有使用ngrok或者frpc,请不要把插件放在这里加载,因为这里的文件可能在webui启动后才加载完成\n\n[models/Stable-diffusion] # 大模型列表\nmg-Tender.safetensors:https://civitai.com/api/download/models/75587\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\nGenshin_Impact_all-in-one.safetensors:https://civitai.com/api/download/models/116970\n\n[models/LyCORIS] # LyCORIS文件列表\n\n\n[models/VAE] # VAE文件列表\n{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-ema-560000-ema-pruned.safetensors\n{input_path}/vae-ft-ema-prunedsafetensors/vae-ft-mse-840000-ema-pruned.safetensors\nhttps://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors\nhttps://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors\n'''\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 按顺序加载的重要文件列表\n\n- **这个列表每次 run all 启动都会加载一次,且一定按照顺序加载后才启动webui**\n- ```[]```内的是下载文件的目标目录,可以是相对目录也可以是觉得路径\n- ```[]```的下一行就是文件列表,可以是下载地址、git仓库、文件路径、文件夹路径,且支持通配符\n- 如果需要对下载的文件重命名,可以在下载链接前面写上文件名后加一个```:```分开文件名和下载地址\n- 如果需要下载到其他目录,可以使用同样的格式写其他目录","metadata":{}},{"cell_type":"code","source":"按顺序加载的重要文件列表 = ''' # 这个列表每次 run all 启动都会加载一次,且一定按照顺序加载\n\n# 如果你需要每次启动都加载一下文件,可以写在这。(比如测试路径是否正确的时候)\n\n[models/Stable-diffusion] # 大模型列表\n\n[models/hypernetworks] # hypernetworks文件列表\n\n[models/embeddings] # embeddings文件列表\n\n[models/Lora] # Lora文件列表\n\n[models/LyCORIS] # LyCORIS文件列表\n\n[models/VAE] # VAE文件列表\n\n[extensions/sd-webui-controlnet/models] # controlnet插件的模型列表\n\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## webui 启动参数\n- 所有的参数都会在启动时传入\n- 可以在前面加```#```来屏蔽某个参数\n- 端口参数需要在下一个代码块的```webuiPort```处修改","metadata":{}},{"cell_type":"code","source":"参数列表='''\n--ckpt=mg-Tender.safetensors # 默认模型名称,路径不能包含空格\n--disable-safe-unpickle \n--deepdanbooru \n--no-hashing \n--no-download-sd-model \n--administrator\n--skip-torch-cuda-test \n--skip-version-check \n--disable-nan-check\n# --opt-sdp-attention \n--opt-sdp-no-mem-attention \n--xformers-flash-attention\n--xformers\n--api \n--listen\n--lowram\n--no-gradio-queue\n--share\n--disable-console-progressbars\n--no-half-vae \n# --no-half #关闭半精度\n# --enable-console-prompts\n# --nowebui\n# --api-auth=2333:6666 # api密码\n# --gradio-auth=2333:6666 # webui密码\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"useGooglrDrive = True # 连接到谷歌云盘 在google colab环境才会生效\n#Ngrok\nuseNgrok=True # 非必填 是否使用ngrok作为公网访问地址\n#Frpc\nuseFrpc=True # 开启frp将不能启动\n\n#文件或直接填配置\nngrok配置或文件地址='''\n{input_path}/configs/ngrok_token.txt\n'''\nfrp配置文件或配置='''\n{input_path}/configs/frpc_litechat.ini\n'''\nfrpSSL文件='''\n{input_path}/configs/litechat_nginx\n'''\n\n# 配置启动参数\nwebuiPort=7860 # webui默认端口\n\n# 仓库地址 这是修改过界面布局顺序的webui,不定期同步到官方版本\n# 如果要使用官方版本,改成这个: https://github.com/AUTOMATIC1111/stable-diffusion-webui\nwebui_git_repo='https://github.com/viyiviyi/stable-diffusion-webui.git -b local' \n# 配置文件,包括webui的设置和UI默认值,如果要自定义,fork这个仓库后修改并把地址替换这个地址\nwebui_config_git_repu = 'https://github.com/viyiviyi/sd-configs.git'\n# 设置文件保存路径 当使用谷歌云盘时非常有用\nsetting_file = '{output_path}/configs/config.json'\nui_config_file = '{output_path}/configs/ui-config.json'\n\n# 这是配置文件夹同步的相关配置\n# 需要在huggingface创建一个数据集(datasets) 然后把数据集的名称(在页面上有复制的按钮)填到 huggingface_repo \n# 需要获取 token 填到 huggingface_token 获取的地址是: https://huggingface.co/settings/tokens\nhuggingface_token = '{input_path}/configs/huggingface_token.txt'\nhuggingface_repo = 'viyi/sdwui-log'\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"link_instead_of_copy = True # 下载或加载Input的文件时是使用链接还是复制的方式加载到目标目录\nhidden_console_info = True # 是否隐藏大部分的控制台内容","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 保存当前目录和启动时cd到之前保存的目录,可以减少sdwui-start-new.ipynb文件下载次数\nimport os\nINIT_WORK_PATH = os.environ['HOME']\nif os.getenv('INIT_WORK_PATH',''):\n INIT_WORK_PATH = os.getenv('INIT_WORK_PATH','')\nelse:\n os.environ['INIT_WORK_PATH'] = os.getcwd()\n%cd {INIT_WORK_PATH}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reLoad = True\n# 如果需要重新安装,请注释下面这一行\nreLoad = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not os.path.exists('sdwui-start-new.ipynb'):\n !wget https://huggingface.co/viyi/sdwui/resolve/main/sdwui-start-new.ipynb -o log.log\n%run sdwui-start-new.ipynb","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 打包收藏文件夹 如果需要可以取消下面两行的注释\n# zipPath('$install_path/stable-diffusion-webui/log','log')\n# !mv {output_path}/log.tar {output_path}/log.tar.bak\n# createOrUpdateDataSet(f'{output_path}/log.tar.bak','sd-webui-log-bak')\n\n# 打包 这一行的结果是 压缩一个目录,并放在 output_path: /kaggle/working/ 目录下 名字是训练输出.tar\n# zipPath('$install_path/stable-diffusion-webui/textual_inversion','训练输出') \n# zipPath('$install_path/stable-diffusion-webui/outputs','outputs')\n\n# 打包venv并上传到数据集\n# zipPath('$install_path/stable-diffusion-webui/venv','venv')\n# !mv {output_path}/venv.tar /kaggle/working/venv.tar.bak\n# createOrUpdateDataSet('/kaggle/working/venv.tar.bak','sd-webui-venv')\n\n# 打包命令参考,--exclude 可以排除不需要打包的目录\n# !tar -cf $output_path/webui.tar.bak --exclude=venv --exclude=extensions -C /kaggle/stable-diffusion-webui/ .","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 使用帮助\n---\n**代码块不能删除也不能调换顺序,如果出现变量未定义,请检查是否按顺序执行了代码块**\n\n---\n\n## kaggle账号\n- 注册账号需要手机号,国内手机号也行,如果点击注册后没反应,估计是需要梯子,用于人机验证\n- 注册后点此笔记的 **Copy & Edit** 按钮就进到编辑界面\n\n## 准备工作\n1. 右侧面板 **Settings/ACCELERATOR** 需要选择GPU **T4x2**出图更快,且会自动开启两个webui\n2. 右侧面板 **Settings/LANGUAGE** 需要选择Python\n2. 右侧面板 **Settings/PERSISTENCE** 建议选择 Files only **作用是保存Outpot目录内的文件**\n3. 右侧面板 **Settings/ENVIRONMENT** 建议不改这个配置,使用当前默认值就行\n4. 右侧面板 **Settings/INTERNET** 需要打开 用于联网,没网跑不起来的啊\n\n## 启动\n#### 启动方式一 **直接点击页面上边的 RunAll**\n- 在没有关闭电源的情况下,后几次点击RunAll的输出在页面上端 (其实没有必要了,之前不知道代码块可以收起,很烦滚动到页面底端才能看见输出)\n- 手机端可能会出现页面上边的工具栏不显示的情况,左侧菜单按钮里也有相关的操作\n- 长时间不操作页面会导致脚本停止 (应该是40分钟吧)\n\n#### 启动方式二 **使用页面上边的 Save Version 后台运行**\n- 后台运行不用担心长时间不操作脚本停止\n- Version Type 选择 **Save & Run All**\n- 在Save Version弹窗里需要选择使用**GPU**环境 (Advanced Settings 里最后一个选项)\n- 后台运行的输出的图片可以在运行结束后下载(但是保存时间有限制,我就经常下不到,不够问题���大,喜欢的图在生成后就下载了)\n- 如果你需要下载运行后的图片,请不要把安装目录修改到 /kaggle/working 这个目录下,因为没有写打包功能,下载只能下载整个输出目录,也就是 /kaggle/working 目录\n\n## 访问\n- 如果你使用了ngrok或者frpc,可以访问你这两对应的地址\n- 如果你不知道你的ngrok或者frpc的地址可以在控制台(页面最下方Console)的输出里面查看\n- 使用Run All方式启动,控制台在启动完成后会输出访问网址,网址内容包含**gradio.live**,可以在页面中搜索快速找到\n- 如果使用Save Verson的方式启动,点击左下角的**View Active Events**点击刚刚启动的脚步,在**Log**里找访问网址\n- 一般情况下第一次启动此脚本需要等待kaggle下载模型文件,进度在页面上方\n- 第二次及以后(不增加新的文件)需要3到5分钟\n\n## 增加模型\n1. 先创建数据集,也就是dataset\n2. 创建时需要添加文件,选择自己的模型文件就行\n3. 同类型文件放相同的数据集里面,一个数据集也不要太大\n4. 可以在dataset搜索其他人上传的模型\n5. 通过右侧的 **Add Data** 按钮选择已经上传的模型文件或者别人上传的模型文件\n - input 下面的列表就是模型文件,可以点击名称后面的复制按钮复制路径\n6. 将模型路径放在配置里的对应配置里即可,支持文件夹和文件路径,参考 **modelDirs**\n - 如果目录里还有子目录也是需要加载的,可以用*表示子目录 例子:比如Loras目录下还有角色、画风、涩涩的文件夹,那路径里写成 '/kaggle/input/Loras/*'就可以加载子目录里面的文件了\n - 模型加载使用的文件链接方式,如果你融模型的时候新模型名字和原有模型名字一样,会出现不能修改只读文件的错误\n - 同理,直接对模型做编辑的工具可能也会出现相同的错误\n \n \n- **为了提高启动速度,导致切换模型过程较慢,点击切换模型后进度条大概率会一直存在,但模型在1分半左右基本能加载完。** \n- **受到kaggle内存大小的影响,切换多个模型后大概率爆内存导致停止运行**\n \n**下边的配置项都写了对应配置的作用和使用说明,不理解的话也不用改,用默认的就好**\n\n## 下载文件\n#### 方式一\n- 在浏览器直接下 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 你的访问地址是 https://123123123.gradio.live\n - 则可以在浏览器输入 https://123123123.gradio.live/file=/kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors 下载你的文件\n \n#### 方式二\n- 复制到Output目录下载 仅支持使用Run All方式运行的\n - 比如你需要下载的文件路径在 /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors\n - 先停止笔记本(不是关机,是停止)\n - 然后新建一个代码块,在里面输入 !cp -f /kaggle/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 或者 新建一个代码块,在里面输入 !cp -f \\$install_path/stable-diffusion-webui/models/Lora/dow_a.safetensors /kaggle/working/\n - 你可能需要拼接路径 如果是在webui里面看到的路径,且路径里面没有带**stable-diffusion-webui**\n - 拼接方式是 **\\$install_path/stable-diffusion-webui** + **文件路径** 拼成类似前一条的样子\n - 就可以在右侧列表的Output目录看见复制出来的文件,点击下载即可\n \n#### 方式三\n- 开启链接输出目录的配置 (配置在第二个代码块,通过搜索**配置文件链接**快速查找)\n - 此方法会把已知的三个训练输出目录链接到Output目录下,直接去下载即可(两种启动方式都可以用)\n - 如果有新的目录需要链接,可以参考着自己写或者联系我\n \n#### 方式四\n- 将安装目录改到输出目录(配置在第二个代码块,通过搜索**安装目录**快速查找)\n - 此方式会把所有文件都放在安装目录,找到并下载即可\n - 如果使用这个方式,右侧的设置里**PERSISTENCE**这个设置项建议选No pensistence。如果选其他项,可能会出现关机特别慢的情况,因为需要上传输出目录的文件。\n\n## **一些可能没用的说明**\n- 配置说明 **True或者False**表示布尔值 **True**表示“**是**” **False**表示“**否**” 只有这两个值\n- 配置说明 **[]** 表示数组,里面可以存放内容,每个内容需要用**英语(半角)逗号**隔开\n- 配置说明 **''或者\"\"** 英语(半角)的双引号或者单引号包裹的内容是**字符串**,比如放在数组里面的路径就需要是一个字符串\n- 配置说明 **#** **#** 后面的内容是**注释**,是帮助性内容,对整个代���的执行不会有影响\n","metadata":{}},{"cell_type":"markdown","source":"# 更新记录\n#### 230901 v173\n- 更新了依赖版本,可以加载sdxl模型了\n- 增加代码块内容说明,希望有用\n\n#### 230812 v171\n- 把关闭半精度的参数注释了,这是之前写错的,注释后不容易爆内存\n- 增加默认模型的参数,用于指定模型启动时默认的模型\n\n#### 230726 v170\n- 更新了整个配置,可以更加自由的下载和加载文件\n- 删除了大部分参数\n\n#### 230726 v169\n- 增加了一个文件加载配置,可以自定义把文件或下载地址加载到指定目录,配置方式见 [ 其他文件列表 ]\n- 增加了一个配置,可以隐藏部分控制台输出,但隐藏不完全,没啥用\n\n#### 230719 v168\n- 增加了同步收藏文件夹到 huggingface 数据集的功能,仅同步收藏文件夹,如果同步所有图片也太浪费资源了\n\n#### 230716 v167\n- 账号解封了\n- 已经更新为精简自动更新版,主要逻辑分离存放到 [huggingface](https://huggingface.co/viyi/sdwui),这边基本上不再需要更新\n- 如果增加了新功能需要新的配置,可以在输出内容的最前面查看到(暂定)\n\n#### 230302 v165\n- 可以修改disableShared=True来使用pm2启动,做到爆内存自动重启(需要使用frpc或者ngrok代理,否则无法访问界面)\n\n#### 230228 v156\n- 移除了koishi的相关功能 如需使用,可查看 [sd-webui-koishi](https://www.kaggle.com/code/yiyiooo/sd-webui-koishi)\n\n#### 230227 v147\n- 增加了nginx做反向代理,现在可以使用一个ngrok地址访问多个服务了 功能在版本156移除\n\n#### 230225 v139\n- 可以加载ssl证书,启动https的隧道了\n\n#### 230224 v134\n- 可以自动修改frp的本地端口\n\n#### 230224 v128\n- 修复默认模型文件不存在时不能启动的问题\n- 修复了多线程导致依赖等内容安装位置错乱的问题\n- 修复了第一次启动会更新koishi数据对应的数据集问题\n- 增加了配置检查功能,对一些配置项做了提示\n- 增加了可配置webui端口功能,现在可以配置webui、froc、ngrok的端口了\n\n#### 230223 v126\n- 修复了仅适用koishi数据目录无法启动koishi的问题\n- 修改了部分文档\n\n#### 230223 v124\n- 修复使用多线程后出现的文件安装下载目录失败的问题\n- 修复使用多线程后文件目录错乱问题\n\n#### 230222 v123\n- 使用多线程进行安装,节省安装时间\n\n#### 230222 v122\n- 更改了默认配置,现在训练的输出可以在Output下面查看了\n\n#### 230222 v118\n- 增加了自动上传koishi的数据到数据集且能自动下载的功能\n - 自动上传的数据集优先级高于手动上传的\n - 上一个版本的数据集与当前版本的目录结构有差异,如果更新后需要修改配置\n \n#### 230121 v111\n- 增加了koishi的部署相关功能 功能在版本156移除\n\n#### 230220 v110\n- 增加了ControlNet插件的一些说明\n\n#### 230220 v109\n- 修复第二次Run all时不能切换到新的frpc配置问题\n- 增加更新记录,用于记录每次更新 ","metadata":{}}]}
 
 
venv.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:449336282c7aa4142cdc5a4f2f653027018ce3396bd22e9b39ae461330c9b18a
3
+ size 2505464937