diff --git a/README.md b/README.md index 02bb812..a16c814 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ system dependencies: ``` # create and edit config from template -cp skynet.ini.example skynet.ini +cp skynet.toml.example skynet.toml # install poetry package manager curl -sSL https://install.python-poetry.org | python3 - @@ -41,6 +41,9 @@ system dependencies: - `docker` with gpu enabled ``` +# create and edit config from template +cp skynet.toml.example skynet.toml + # pull runtime container docker pull guilledk/skynet:runtime-cuda @@ -50,14 +53,27 @@ docker pull guilledk/skynet:runtime-cuda # launch simple ipfs node ./launch_ipfs.sh -# run worker +# run worker with all gpus docker run \ -it \ --rm \ + --env HF_HOME=hf_home \ --gpus all \ --network host \ --name skynet-worker \ --mount type=bind,source="$(pwd)",target=/root/target \ guilledk/skynet:runtime-cuda \ skynet run dgpu + +# run worker with specific gpu +docker run \ + -it \ + --rm \ + --env HF_HOME=hf_home \ + --gpus '"device=1"' \ + --network host \ + --name skynet-worker-1 \ + --mount type=bind,source="$(pwd)",target=/root/target \ + guilledk/skynet:runtime-cuda \ + skynet run dgpu ``` diff --git a/poetry.lock b/poetry.lock index f553c0b..3959dc5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3068,6 +3068,17 @@ dev = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -3632,4 +3643,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.12" -content-hash = "7a7556c8dd771303bd03afb008f678a175b97e1c07bba5ffaa7ae3cdad5b84f9" +content-hash = "787c1bb602457589bdfeb6252fbc725abb038234dd7576060b61dc10dc9c4035" diff --git a/pyproject.toml b/pyproject.toml index 1d5ba59..faa67e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ asks = '^3.0.0' Pillow = '^10.0.1' docker = '^6.1.3' py-leap = {git = 'https://github.com/guilledk/py-leap.git', rev = 'v0.1a14'} +toml = "^0.10.2" [tool.poetry.group.frontend] optional = true diff --git a/skynet.ini.example b/skynet.ini.example deleted file mode 100644 index 34e3d13..0000000 --- a/skynet.ini.example +++ /dev/null @@ -1,51 +0,0 @@ -# config sections are optional, depending on which services -# you wish to run - -[skynet.dgpu] -account = testworkerX -permission = active -key = 5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -node_url = https://testnet.skygpu.net -hyperion_url = https://testnet.skygpu.net -ipfs_gateway_url = /ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv -ipfs_url = http://127.0.0.1:5001 - -hf_home = hf_home -hf_token = hf_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx - -auto_withdraw = True - -[skynet.telegram] -account = telegram -permission = active -key = 5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -node_url = https://testnet.skygpu.net -hyperion_url = https://testnet.skygpu.net -ipfs_gateway_url = /ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv -ipfs_url = http://127.0.0.1:5001 - -token = XXXXXXXXXX:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -[skynet.discord] -account = discord -permission = active -key = 5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -node_url = https://testnet.skygpu.net -hyperion_url = https://testnet.skygpu.net -ipfs_gateway_url = /ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv -ipfs_url = http://127.0.0.1:5001 - -token = XXXXXXXXXX:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -[skynet.pinner] -hyperion_url = https://testnet.skygpu.net -ipfs_url = http://127.0.0.1:5001 - -[skynet.user] -account = testuser -permission = active -key = 5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -node_url = https://testnet.skygpu.net diff --git a/skynet.toml.example b/skynet.toml.example new file mode 100644 index 0000000..fa86fb0 --- /dev/null +++ b/skynet.toml.example @@ -0,0 +1,46 @@ +# config sections are optional, depending on which services +# you wish to run + +[skynet.dgpu] +account = 'testworkerX' +permission = 'active' +key = '5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +node_url = 'https://testnet.skygpu.net' +hyperion_url = 'https://testnet.skygpu.net' +ipfs_gateway_url = '/ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv' +ipfs_url = 'http://127.0.0.1:5001' +hf_home = 'hf_home' +hf_token = 'hf_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx' +auto_withdraw = true +non_compete = [] + +[skynet.telegram] +account = 'telegram' +permission = 'active' +key = '5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +node_url = 'https://testnet.skygpu.net' +hyperion_url = 'https://testnet.skygpu.net' +ipfs_gateway_url = '/ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv' +ipfs_url = 'http://127.0.0.1:5001' +token = 'XXXXXXXXXX:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + +[skynet.discord] +account = 'discord' +permission = 'active' +key = '5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +node_url = 'https://testnet.skygpu.net' +hyperion_url = 'https://testnet.skygpu.net' +ipfs_gateway_url = '/ip4/169.197.140.154/tcp/4001/p2p/12D3KooWKWogLFNEcNNMKnzU7Snrnuj84RZdMBg3sLiQSQc51oEv' +ipfs_url = 'http://127.0.0.1:5001' +token = 'XXXXXXXXXX:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + +[skynet.pinner] +hyperion_url = 'https://testnet.skygpu.net' +ipfs_url = 'http://127.0.0.1:5001' + +[skynet.user] +account = 'testuser' +permission = 'active' +key = '5Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +node_url = 'https://testnet.skygpu.net' + diff --git a/skynet/cli.py b/skynet/cli.py index 55e1922..ae56adb 100755 --- a/skynet/cli.py +++ b/skynet/cli.py @@ -32,7 +32,7 @@ def skynet(*args, **kwargs): def txt2img(*args, **kwargs): from . import utils - config, _ = load_skynet_ini() + config = load_skynet_toml() hf_token = load_key(config, 'skynet.dgpu', 'hf_token') hf_home = load_key(config, 'skynet.dgpu', 'hf_home') set_hf_vars(hf_token, hf_home) @@ -50,7 +50,7 @@ def txt2img(*args, **kwargs): @click.option('--seed', '-S', default=None) def img2img(model, prompt, input, output, strength, guidance, steps, seed): from . import utils - config, _ = load_skynet_ini() + config = load_skynet_toml() hf_token = load_key(config, 'skynet.dgpu', 'hf_token') hf_home = load_key(config, 'skynet.dgpu', 'hf_home') set_hf_vars(hf_token, hf_home) @@ -81,7 +81,7 @@ def upscale(input, output, model): @skynet.command() def download(): from . import utils - config, _ = load_skynet_ini() + config = load_skynet_toml() hf_token = load_key(config, 'skynet.dgpu', 'hf_token') hf_home = load_key(config, 'skynet.dgpu', 'hf_home') set_hf_vars(hf_token, hf_home) @@ -110,7 +110,7 @@ def enqueue( import trio from leap.cleos import CLEOS - config, _ = load_skynet_ini() + config = load_skynet_toml() key = load_key(config, 'skynet.user', 'key') account = load_key(config, 'skynet.user', 'account') @@ -155,7 +155,7 @@ def clean( import trio from leap.cleos import CLEOS - config, _ = load_skynet_ini() + config = load_skynet_toml() key = load_key(config, 'skynet.user', 'key') account = load_key(config, 'skynet.user', 'account') permission = load_key(config, 'skynet.user', 'permission') @@ -176,7 +176,7 @@ def clean( @skynet.command() def queue(): import requests - config, _ = load_skynet_ini() + config = load_skynet_toml() node_url = load_key(config, 'skynet.user', 'node_url') resp = requests.post( f'{node_url}/v1/chain/get_table_rows', @@ -193,7 +193,7 @@ def queue(): @click.argument('request-id') def status(request_id: int): import requests - config, _ = load_skynet_ini() + config = load_skynet_toml() node_url = load_key(config, 'skynet.user', 'node_url') resp = requests.post( f'{node_url}/v1/chain/get_table_rows', @@ -212,7 +212,7 @@ def dequeue(request_id: int): import trio from leap.cleos import CLEOS - config, _ = load_skynet_ini() + config = load_skynet_toml() key = load_key(config, 'skynet.user', 'key') account = load_key(config, 'skynet.user', 'account') permission = load_key(config, 'skynet.user', 'permission') @@ -246,7 +246,7 @@ def config( import trio from leap.cleos import CLEOS - config, _ = load_skynet_ini() + config = load_skynet_toml() key = load_key(config, 'skynet.user', 'key') account = load_key(config, 'skynet.user', 'account') @@ -275,7 +275,7 @@ def deposit(quantity: str): import trio from leap.cleos import CLEOS - config, _ = load_skynet_ini() + config = load_skynet_toml() key = load_key(config, 'skynet.user', 'key') account = load_key(config, 'skynet.user', 'account') @@ -324,7 +324,7 @@ def nodeos(): @run.command() @click.option('--loglevel', '-l', default='INFO', help='Logging level') @click.option( - '--config-path', '-c', default='skynet.ini') + '--config-path', '-c', default=DEFAULT_CONFIG_PATH) def dgpu( loglevel: str, config_path: str @@ -334,17 +334,15 @@ def dgpu( logging.basicConfig(level=loglevel) - config, non_compete = load_skynet_ini(file_path=config_path) - hf_token = load_key(config, 'skynet.dgpu', 'hf_token') - hf_home = load_key(config, 'skynet.dgpu', 'hf_home') + config = load_skynet_toml(file_path=config_path) + hf_token = load_key(config, 'skynet.dgpu.hf_token') + hf_home = load_key(config, 'skynet.dgpu.hf_home') set_hf_vars(hf_token, hf_home) - assert 'skynet.dgpu' in config + assert 'skynet' in config + assert 'dgpu' in config['skynet'] - config = dict(config['skynet.dgpu']) - config['non_compete'] = non_compete - - trio.run(open_dgpu_node, config) + trio.run(open_dgpu_node, config['skynet']['dgpu']) @run.command() @@ -366,7 +364,7 @@ def telegram( logging.basicConfig(level=loglevel) - config, _ = load_skynet_ini() + config = load_skynet_toml() tg_token = load_key(config, 'skynet.telegram', 'tg_token') key = load_key(config, 'skynet.telegram', 'key') @@ -422,7 +420,7 @@ def discord( logging.basicConfig(level=loglevel) - config, _ = load_skynet_ini() + config = load_skynet_toml() dc_token = load_key(config, 'skynet.discord', 'dc_token') key = load_key(config, 'skynet.discord', 'key') @@ -472,7 +470,7 @@ def pinner(loglevel): from .ipfs import AsyncIPFSHTTP from .ipfs.pinner import SkynetPinner - config, _ = load_skynet_ini() + config = load_skynet_toml() hyperion_url = load_key(config, 'skynet.pinner', 'hyperion_url') ipfs_url = load_key(config, 'skynet.pinner', 'ipfs_url') diff --git a/skynet/config.py b/skynet/config.py index ad5a7e7..73ee8c3 100755 --- a/skynet/config.py +++ b/skynet/config.py @@ -1,9 +1,9 @@ #!/usr/bin/python import os +import toml from pathlib import Path -from configparser import ConfigParser from .constants import DEFAULT_CONFIG_PATH @@ -12,34 +12,23 @@ class ConfigParsingError(BaseException): ... -def load_skynet_ini( - file_path=DEFAULT_CONFIG_PATH -) -> ConfigParser: - config = ConfigParser() - config.read(file_path) - - non_compete = [] - if Path('.non-compete').is_file(): - with open('.non-compete', 'r') as non_compete_file: - for line in non_compete_file.readlines(): - line = line.rstrip() - if line: - non_compete.append(line) - - return config, non_compete +def load_skynet_toml(file_path=DEFAULT_CONFIG_PATH) -> dict: + config = toml.load(file_path) + return config -def load_key(config: ConfigParser, section: str, key: str) -> str: - if section not in config: - conf_sections = [s for s in config] - raise ConfigParsingError(f'section \"{section}\" not in {conf_sections}') +def load_key(config: dict, key: str) -> str: + for skey in key.split('.'): + if skey not in config: + conf_keys = [k for k in config] + raise ConfigParsingError(f'key \"{skey}\" not in {conf_keys}') - if key not in config[section]: - conf_keys = [k for k in config[section]] - raise ConfigParsingError(f'key \"{key}\" not in {conf_keys}') + config = config[skey] + + return config - return str(config[section][key]) def set_hf_vars(hf_token: str, hf_home: str): os.environ['HF_TOKEN'] = hf_token os.environ['HF_HOME'] = hf_home + os.environ['HUGGINGFACE_HUB_CACHE'] = hf_home diff --git a/skynet/constants.py b/skynet/constants.py index d2413cb..2c89ca0 100755 --- a/skynet/constants.py +++ b/skynet/constants.py @@ -162,7 +162,7 @@ DEFAULT_MODEL = list(MODELS.keys())[4] DEFAULT_ROLE = 'pleb' DEFAULT_UPSCALER = None -DEFAULT_CONFIG_PATH = 'skynet.ini' +DEFAULT_CONFIG_PATH = 'skynet.toml' DEFAULT_INITAL_MODELS = [ 'stabilityai/stable-diffusion-xl-base-1.0' diff --git a/skynet/dgpu/compute.py b/skynet/dgpu/compute.py index a62fa27..c343ae7 100644 --- a/skynet/dgpu/compute.py +++ b/skynet/dgpu/compute.py @@ -54,6 +54,10 @@ class SkynetMM: if 'initial_models' in config else DEFAULT_INITAL_MODELS ) + self.cache_dir = None + if 'hf_home' in config: + self.cache_dir = config['hf_home'] + self._models = {} for model in self.initial_models: self.load_model(model, False, force=True) @@ -78,7 +82,9 @@ class SkynetMM: ): logging.info(f'loading model {model_name}...') if force or len(self._models.keys()) == 0: - pipe = pipeline_for(model_name, image=image) + pipe = pipeline_for( + model_name, image=image, cache_dir=self.cache_dir) + self._models[model_name] = { 'pipe': pipe, 'generated': 0, @@ -100,7 +106,8 @@ class SkynetMM: gc.collect() torch.cuda.empty_cache() - pipe = pipeline_for(model_name, image=image) + pipe = pipeline_for( + model_name, image=image, cache_dir=self.cache_dir) self._models[model_name] = { 'pipe': pipe, diff --git a/skynet/utils.py b/skynet/utils.py index 4de2b78..7c19a82 100755 --- a/skynet/utils.py +++ b/skynet/utils.py @@ -64,7 +64,13 @@ def convert_from_bytes_and_crop(raw: bytes, max_w: int, max_h: int) -> Image: return image.convert('RGB') -def pipeline_for(model: str, mem_fraction: float = 1.0, image=False) -> DiffusionPipeline: +def pipeline_for( + model: str, + mem_fraction: float = 1.0, + image: bool = False, + cache_dir: str | None = None +) -> DiffusionPipeline: + assert torch.cuda.is_available() torch.cuda.empty_cache() torch.cuda.set_per_process_memory_fraction(mem_fraction) @@ -90,7 +96,8 @@ def pipeline_for(model: str, mem_fraction: float = 1.0, image=False) -> Diffusio params = { 'torch_dtype': torch.float16, - 'safety_checker': None + 'safety_checker': None, + 'cache_dir': cache_dir } if shortname == 'stable': @@ -107,6 +114,7 @@ def pipeline_for(model: str, mem_fraction: float = 1.0, image=False) -> Diffusio else: pipe_class = StableDiffusionPipeline + breakpoint() pipe = pipe_class.from_pretrained( model, **params)