From 6aa40e3a33304cbef3c5e758582dff665aae3a35 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Tue, 2 Apr 2024 11:18:15 +0700 Subject: [PATCH 01/22] - add merge lora to checkpoint api --- api.py | 231 ++++++++++++++++++++++++++++++++++ api_models.py | 96 ++++++++++++++ scripts/mbwpresets.txt | 39 ++++++ scripts/mergers/model_util.py | 4 +- scripts/mergers/pluslora.py | 17 +++ scripts/supermerger.py | 4 + xyzpresets.json | 1 + 7 files changed, 390 insertions(+), 2 deletions(-) create mode 100644 api.py create mode 100644 api_models.py create mode 100644 scripts/mbwpresets.txt create mode 100644 xyzpresets.json diff --git a/api.py b/api.py new file mode 100644 index 0000000..b60eeb1 --- /dev/null +++ b/api.py @@ -0,0 +1,231 @@ +"""API module for FastAPI""" +from typing import Callable, Dict, Optional +from threading import Lock +from secrets import compare_digest +import asyncio +from collections import defaultdict +from hashlib import sha256 +import string +from random import choices + +from modules import shared # pylint: disable=import-error +from modules.api.api import decode_base64_to_image # pylint: disable=E0401 +from modules.call_queue import queue_lock # pylint: disable=import-error +from fastapi import FastAPI, Depends, HTTPException +from fastapi.security import HTTPBasic, HTTPBasicCredentials + +import api_models as models +from scripts.mergers import pluslora + + +class Api: + """Api class for FastAPI""" + + def __init__( + self, app: FastAPI, qlock: Lock, prefix: Optional[str] = None + ) -> None: + if shared.cmd_opts.api_auth: + self.credentials = {} + for auth in shared.cmd_opts.api_auth.split(","): + user, password = auth.split(":") + self.credentials[user] = password + + self.app = app + self.queue: Dict[str, asyncio.Queue] = {} + self.res: Dict[str, Dict[str, Dict[str, float]]] = \ + defaultdict(dict) + self.queue_lock = qlock + self.tasks: Dict[str, asyncio.Task] = {} + + self.runner: Optional[asyncio.Task] = None + self.prefix = prefix + self.running_batches: Dict[str, Dict[str, float]] = \ + defaultdict(lambda: defaultdict(int)) + + # self.add_api_route( + # 'interrogate', + # self.endpoint_interrogate, + # methods=['POST'], + # response_model=models.TaggerInterrogateResponse + # ) + + # self.add_api_route( + # 'interrogators', + # self.endpoint_interrogators, + # methods=['GET'], + # response_model=models.TaggerInterrogatorsResponse + # ) + + self.add_api_route( + 'unload-interrogators', + self.endpoint_unload_interrogators, + methods=['POST'], + response_model=str, + ) + + self.add_api_route( + 'merge-lora', + self.merge_lora, + methods=['POST'], + response_model=models.MergeLoraResponse, + ) + + async def add_to_queue(self, m, q, n='', i=None, t=0.0) -> Dict[ + str, Dict[str, float] + ]: + if m not in self.queue: + self.queue[m] = asyncio.Queue() + # loop = asyncio.get_running_loop() + # asyncio.run_coroutine_threadsafe( + task = asyncio.create_task(self.queue[m].put((q, n, i, t))) + # , loop) + + if self.runner is None: + loop = asyncio.get_running_loop() + asyncio.ensure_future(self.batch_process(), loop=loop) + await task + return await self.tasks[q+"\t"+n] + + async def do_queued_interrogation(self, m, q, n, i, t) -> Dict[ + str, Dict[str, float] + ]: + self.running_batches[m][q] += 1.0 + # queue and name empty to process, not queue + res = self.endpoint_interrogate( + models.TaggerInterrogateRequest( + image=i, + model=m, + threshold=t, + name_in_queue='', + queue='' + ) + ) + self.res[q][n] = res.caption["tag"] + for k, v in res.caption["rating"].items(): + self.res[q][n]["rating:"+k] = v + return self.running_batches + + async def finish_queue(self, m, q) -> Dict[str, Dict[str, float]]: + if q in self.running_batches[m]: + del self.running_batches[m][q] + if q in self.res: + return self.res.pop(q) + return self.running_batches + + async def batch_process(self) -> None: + # loop = asyncio.get_running_loop() + while len(self.queue) > 0: + for m in self.queue: + # if zero the queue might just be pending + while True: + try: + # q, n, i, t = asyncio.run_coroutine_threadsafe( + # self.queue[m].get_nowait(), loop).result() + q, n, i, t = self.queue[m].get_nowait() + except asyncio.QueueEmpty: + break + self.tasks[q+"\t"+n] = asyncio.create_task( + self.do_queued_interrogation(m, q, n, i, t) if n != "" + else self.finish_queue(m, q) + ) + + for model in self.running_batches: + if len(self.running_batches[model]) == 0: + del self.queue[model] + else: + await asyncio.sleep(0.1) + + self.running_batches.clear() + self.runner = None + + def auth(self, creds: Optional[HTTPBasicCredentials] = None): + if creds is None: + creds = Depends(HTTPBasic()) + if creds.username in self.credentials: + if compare_digest(creds.password, + self.credentials[creds.username]): + return True + + raise HTTPException( + status_code=401, + detail="Incorrect username or password", + headers={ + "WWW-Authenticate": "Basic" + }) + + def add_api_route(self, path: str, endpoint: Callable, **kwargs): + if self.prefix: + path = f'{self.prefix}/{path}' + + if shared.cmd_opts.api_auth: + return self.app.add_api_route(path, endpoint, dependencies=[ + Depends(self.auth)], **kwargs) + return self.app.add_api_route(path, endpoint, **kwargs) + + async def queue_interrogation(self, m, q, n='', i=None, t=0.0) -> Dict[ + str, Dict[str, float] + ]: + """ queue an interrogation, or add to batch """ + if n == '': + task = asyncio.create_task(self.add_to_queue(m, q)) + else: + if n == '': + n = sha256(i).hexdigest() + if n in self.res[q]: + return self.running_batches + elif n in self.res[q]: + # clobber name if it's already in the queue + j = 0 + while f'{n}#{j}' in self.res[q]: + j += 1 + n = f'{n}#{j}' + self.res[q][n] = {} + # add image to queue + task = asyncio.create_task(self.add_to_queue(m, q, n, i, t)) + return await task + + def endpoint_unload_interrogators(self): + unloaded_models = 0 + + return f"Successfully unload {unloaded_models} model(s)" + + def merge_lora(self, request: models.MergeLoraRequest): + """Merge Lora""" + try: + # comment: + + request.loraratios = "\ + NONE:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\ + ALL:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\n\ + INS:1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0\n\ + IND:1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0\n\ + INALL:1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0\n\ + MIDD:1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0\n\ + OUTD:1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0\n\ + OUTS:1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1\n\ + OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ + ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" + + data = request + + res = pluslora.pluslora( + loraratios=data.loraratios, + calc_precision=data.calc_precision, + device=data.device, + lnames=data.lnames, + metasets=data.metasets, + model=data.model, + output=data.output, + save_precision=data.save_precision, + settings=[] + ) + + return models.MergeLoraResponse(checkpoint_merged_path=res) + + except Exception as e: + raise e + # end try + + +def on_app_started(_, app: FastAPI): + Api(app, queue_lock, '/supermerger/v1') diff --git a/api_models.py b/api_models.py new file mode 100644 index 0000000..5cf7565 --- /dev/null +++ b/api_models.py @@ -0,0 +1,96 @@ +"""Purpose: Pydantic models for the API.""" +from typing import List, Dict + +from modules.api import models as sd_models # pylint: disable=E0401 +from pydantic import BaseModel, Field + + +class TaggerInterrogateRequest(sd_models.InterrogateRequest): + """Interrogate request model""" + model: str = Field( + title='Model', + description='The interrogate model used.', + ) + threshold: float = Field( + title='Threshold', + description='The threshold used for the interrogate model.', + default=0.0, + ) + queue: str = Field( + title='Queue', + description='name of queue; leave empty for single response', + default='', + ) + name_in_queue: str = Field( + title='Name', + description='name to queue image as or use . leave empty to ' + 'retrieve the final response', + default='', + ) + + +class TaggerInterrogateResponse(BaseModel): + """Interrogate response model""" + caption: Dict[str, Dict[str, float]] = Field( + title='Caption', + description='The generated captions for the image.' + ) + + +class TaggerInterrogatorsResponse(BaseModel): + """Interrogators response model""" + models: List[str] = Field( + title='Models', + description='' + ) + +class MergeLoraRequest(BaseModel): + """Interrogate request model""" + lnames: str = Field( + title='Lnames', + description='Lora name.', + default='NgocYen001:1', + ) + output: str = Field( + title='Output name', + description='Output name.', + default='lora_output', + ) + model: str = Field( + title='model', + description='Checkpoint model used for the generation.', + default='dreamshaper_8.safetensors', + ) + save_precision: str = Field( + title='Save precision', + description='Save precision.', + default='fp16', + ) + calc_precision: str = Field( + title='Calc precision', + description='Calc precision.', + default='float' + ) + metasets: str = Field( + title='Metasets', + description='Metasets.', + default='create new', + ) + device: str = Field( + title='Device', + description='Device.', + default='cuda', + ) + loraratios: str = Field( + title='Loraratios', + description='Loraratios.', + default='', + ) + +class MergeLoraResponse(BaseModel): + """Interrogate request model""" + checkpoint_merged_path: str = Field( + title='Merged Checkpoint Path', + description='Merged Checkpoin Path.', + default='', + ) \ No newline at end of file diff --git a/scripts/mbwpresets.txt b/scripts/mbwpresets.txt new file mode 100644 index 0000000..29a4de2 --- /dev/null +++ b/scripts/mbwpresets.txt @@ -0,0 +1,39 @@ +preset_name preset_weights +GRAD_V 0,1,0.9166666667,0.8333333333,0.75,0.6666666667,0.5833333333,0.5,0.4166666667,0.3333333333,0.25,0.1666666667,0.0833333333,0,0.0833333333,0.1666666667,0.25,0.3333333333,0.4166666667,0.5,0.5833333333,0.6666666667,0.75,0.8333333333,0.9166666667,1.0 +GRAD_A 0,0,0.0833333333,0.1666666667,0.25,0.3333333333,0.4166666667,0.5,0.5833333333,0.6666666667,0.75,0.8333333333,0.9166666667,1.0,0.9166666667,0.8333333333,0.75,0.6666666667,0.5833333333,0.5,0.4166666667,0.3333333333,0.25,0.1666666667,0.0833333333,0 +FLAT_25 0,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25 +FLAT_75 0,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75 +WRAP08 0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 +WRAP12 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 +WRAP14 0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1 +WRAP16 0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1 +MID12_50 0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0 +OUT07 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1 +OUT12 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1 +OUT12_5 0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,1,1,1,1,1,1,1,1,1,1,1,1 +RING08_SOFT 0,0,0,0,0,0,0.5,1,1,1,0.5,0,0,0,0,0,0.5,1,1,1,0.5,0,0,0,0,0 +RING08_5 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0 +RING10_5 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0 +RING10_3 0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0 +SMOOTHSTEP 0,0,0.00506365740740741,0.0196759259259259,0.04296875,0.0740740740740741,0.112123842592593,0.15625,0.205584490740741,0.259259259259259,0.31640625,0.376157407407407,0.437644675925926,0.5,0.562355324074074,0.623842592592592,0.68359375,0.740740740740741,0.794415509259259,0.84375,0.887876157407408,0.925925925925926,0.95703125,0.980324074074074,0.994936342592593,1 +REVERSE-SMOOTHSTEP 0,1,0.994936342592593,0.980324074074074,0.95703125,0.925925925925926,0.887876157407407,0.84375,0.794415509259259,0.740740740740741,0.68359375,0.623842592592593,0.562355324074074,0.5,0.437644675925926,0.376157407407408,0.31640625,0.259259259259259,0.205584490740741,0.15625,0.112123842592592,0.0740740740740742,0.0429687499999996,0.0196759259259258,0.00506365740740744,0 +SMOOTHSTEP*2 0,0,0.0101273148148148,0.0393518518518519,0.0859375,0.148148148148148,0.224247685185185,0.3125,0.411168981481482,0.518518518518519,0.6328125,0.752314814814815,0.875289351851852,1.,0.875289351851852,0.752314814814815,0.6328125,0.518518518518519,0.411168981481481,0.3125,0.224247685185184,0.148148148148148,0.0859375,0.0393518518518512,0.0101273148148153,0 +R_SMOOTHSTEP*2 0,1,0.989872685185185,0.960648148148148,0.9140625,0.851851851851852,0.775752314814815,0.6875,0.588831018518519,0.481481481481481,0.3671875,0.247685185185185,0.124710648148148,0.,0.124710648148148,0.247685185185185,0.3671875,0.481481481481481,0.588831018518519,0.6875,0.775752314814816,0.851851851851852,0.9140625,0.960648148148149,0.989872685185185,1 +SMOOTHSTEP*3 0,0,0.0151909722222222,0.0590277777777778,0.12890625,0.222222222222222,0.336371527777778,0.46875,0.616753472222222,0.777777777777778,0.94921875,0.871527777777778,0.687065972222222,0.5,0.312934027777778,0.128472222222222,0.0507812500000004,0.222222222222222,0.383246527777778,0.53125,0.663628472222223,0.777777777777778,0.87109375,0.940972222222222,0.984809027777777,1 +R_SMOOTHSTEP*3 0,1,0.984809027777778,0.940972222222222,0.87109375,0.777777777777778,0.663628472222222,0.53125,0.383246527777778,0.222222222222222,0.05078125,0.128472222222222,0.312934027777778,0.5,0.687065972222222,0.871527777777778,0.94921875,0.777777777777778,0.616753472222222,0.46875,0.336371527777777,0.222222222222222,0.12890625,0.0590277777777777,0.0151909722222232,0 +SMOOTHSTEP*4 0,0,0.0202546296296296,0.0787037037037037,0.171875,0.296296296296296,0.44849537037037,0.625,0.822337962962963,0.962962962962963,0.734375,0.49537037037037,0.249421296296296,0.,0.249421296296296,0.495370370370371,0.734375000000001,0.962962962962963,0.822337962962962,0.625,0.448495370370369,0.296296296296297,0.171875,0.0787037037037024,0.0202546296296307,0 +R_SMOOTHSTEP*4 0,1,0.97974537037037,0.921296296296296,0.828125,0.703703703703704,0.55150462962963,0.375,0.177662037037037,0.0370370370370372,0.265625,0.50462962962963,0.750578703703704,1.,0.750578703703704,0.504629629629629,0.265624999999999,0.0370370370370372,0.177662037037038,0.375,0.551504629629631,0.703703703703703,0.828125,0.921296296296298,0.979745370370369,1 +SMOOTHSTEP/2 0,0,0.0196759259259259,0.0740740740740741,0.15625,0.259259259259259,0.376157407407407,0.5,0.623842592592593,0.740740740740741,0.84375,0.925925925925926,0.980324074074074,1.,0.980324074074074,0.925925925925926,0.84375,0.740740740740741,0.623842592592593,0.5,0.376157407407407,0.259259259259259,0.15625,0.0740740740740741,0.0196759259259259,0 +R_SMOOTHSTEP/2 0,1,0.980324074074074,0.925925925925926,0.84375,0.740740740740741,0.623842592592593,0.5,0.376157407407407,0.259259259259259,0.15625,0.0740740740740742,0.0196759259259256,0.,0.0196759259259256,0.0740740740740742,0.15625,0.259259259259259,0.376157407407407,0.5,0.623842592592593,0.740740740740741,0.84375,0.925925925925926,0.980324074074074,1 +SMOOTHSTEP/3 0,0,0.04296875,0.15625,0.31640625,0.5,0.68359375,0.84375,0.95703125,1.,0.95703125,0.84375,0.68359375,0.5,0.31640625,0.15625,0.04296875,0.,0.04296875,0.15625,0.31640625,0.5,0.68359375,0.84375,0.95703125,1 +R_SMOOTHSTEP/3 0,1,0.95703125,0.84375,0.68359375,0.5,0.31640625,0.15625,0.04296875,0.,0.04296875,0.15625,0.31640625,0.5,0.68359375,0.84375,0.95703125,1.,0.95703125,0.84375,0.68359375,0.5,0.31640625,0.15625,0.04296875,0 +SMOOTHSTEP/4 0,0,0.0740740740740741,0.259259259259259,0.5,0.740740740740741,0.925925925925926,1.,0.925925925925926,0.740740740740741,0.5,0.259259259259259,0.0740740740740741,0.,0.0740740740740741,0.259259259259259,0.5,0.740740740740741,0.925925925925926,1.,0.925925925925926,0.740740740740741,0.5,0.259259259259259,0.0740740740740741,0 +R_SMOOTHSTEP/4 0,1,0.925925925925926,0.740740740740741,0.5,0.259259259259259,0.0740740740740742,0.,0.0740740740740742,0.259259259259259,0.5,0.740740740740741,0.925925925925926,1.,0.925925925925926,0.740740740740741,0.5,0.259259259259259,0.0740740740740742,0.,0.0740740740740742,0.259259259259259,0.5,0.740740740740741,0.925925925925926,1 +COSINE 0,1,0.995722430686905,0.982962913144534,0.961939766255643,0.933012701892219,0.896676670145617,0.853553390593274,0.80438071450436,0.75,0.691341716182545,0.62940952255126,0.565263096110026,0.5,0.434736903889974,0.37059047744874,0.308658283817455,0.25,0.195619285495639,0.146446609406726,0.103323329854382,0.0669872981077805,0.0380602337443566,0.0170370868554658,0.00427756931309475,0 +REVERSE_COSINE 0,0,0.00427756931309475,0.0170370868554659,0.0380602337443566,0.0669872981077808,0.103323329854383,0.146446609406726,0.19561928549564,0.25,0.308658283817455,0.37059047744874,0.434736903889974,0.5,0.565263096110026,0.62940952255126,0.691341716182545,0.75,0.804380714504361,0.853553390593274,0.896676670145618,0.933012701892219,0.961939766255643,0.982962913144534,0.995722430686905,1 +TRUE_CUBIC_HERMITE 0,0,0.199031876929012,0.325761959876543,0.424641927083333,0.498456790123457,0.549991560570988,0.58203125,0.597360869984568,0.598765432098765,0.589029947916667,0.570939429012346,0.547278886959876,0.520833333333333,0.49438777970679,0.470727237654321,0.45263671875,0.442901234567901,0.444305796682099,0.459635416666667,0.491675106095678,0.543209876543211,0.617024739583333,0.715904706790124,0.842634789737655,1 +TRUE_REVERSE_CUBIC_HERMITE 0,1,0.800968123070988,0.674238040123457,0.575358072916667,0.501543209876543,0.450008439429012,0.41796875,0.402639130015432,0.401234567901235,0.410970052083333,0.429060570987654,0.452721113040124,0.479166666666667,0.50561222029321,0.529272762345679,0.54736328125,0.557098765432099,0.555694203317901,0.540364583333333,0.508324893904322,0.456790123456789,0.382975260416667,0.284095293209876,0.157365210262345,0 +FAKE_CUBIC_HERMITE 0,0,0.157576195987654,0.28491512345679,0.384765625,0.459876543209877,0.512996720679012,0.546875,0.564260223765432,0.567901234567901,0.560546875,0.544945987654321,0.523847415123457,0.5,0.476152584876543,0.455054012345679,0.439453125,0.432098765432099,0.435739776234568,0.453125,0.487003279320987,0.540123456790124,0.615234375,0.71508487654321,0.842423804012347,1 +FAKE_REVERSE_CUBIC_HERMITE 0,1,0.842423804012346,0.71508487654321,0.615234375,0.540123456790123,0.487003279320988,0.453125,0.435739776234568,0.432098765432099,0.439453125,0.455054012345679,0.476152584876543,0.5,0.523847415123457,0.544945987654321,0.560546875,0.567901234567901,0.564260223765432,0.546875,0.512996720679013,0.459876543209876,0.384765625,0.28491512345679,0.157576195987653,0 +ALL_A 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +ALL_B 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 diff --git a/scripts/mergers/model_util.py b/scripts/mergers/model_util.py index 813bc91..85726e8 100644 --- a/scripts/mergers/model_util.py +++ b/scripts/mergers/model_util.py @@ -105,7 +105,7 @@ def savemodel(state_dict,currentmodel,fname,savesets,metadata={}): if os.path.isfile(fname) and not "overwrite" in savesets: _err_msg = f"Output file ({fname}) existed and was not saved]" print(_err_msg) - return _err_msg + raise Exception(_err_msg) print("Saving...") isxl = "conditioner.embedders.1.model.transformer.resblocks.9.mlp.c_proj.weight" in state_dict @@ -141,7 +141,7 @@ def savemodel(state_dict,currentmodel,fname,savesets,metadata={}): state_dict[key] = other_dict[key] del other_dict load_model(checkpoint_info, already_loaded_state_dict=state_dict) - return "Merged model saved in "+fname + return f"{fname}" def filenamecutter(name,model_a = False): if name =="" or name ==[]: return diff --git a/scripts/mergers/pluslora.py b/scripts/mergers/pluslora.py index 7c0b660..7763985 100644 --- a/scripts/mergers/pluslora.py +++ b/scripts/mergers/pluslora.py @@ -664,6 +664,21 @@ def lycomerge(filename,ratios,calc_precision): ############################################################## ####### merge to checkpoint def pluslora(lnames,loraratios,settings,output,model,save_precision,calc_precision,metasets,device): + + request_input = { + "lnames": lnames, + "loraratios": loraratios, + "output": output, + "model": model, + "save_precision": save_precision, + "calc_precision": calc_precision, + "metasets": metasets, + "device": device, + "settings": settings + } + print("Merge To Checkpoint Request: ",request_input) + + if model == []: return "ERROR: No model Selected" if lnames == "":return "ERROR: No LoRA Selected" @@ -802,6 +817,8 @@ def pluslora(lnames,loraratios,settings,output,model,save_precision,calc_precisi result = savemodel(theta_0,dname,output,settings) del theta_0 gc.collect() + + print("Plus LoRA end: ",result) return result + add def newpluslora(theta_0,filenames,lweis,names, isxl,isv2, keychanger): diff --git a/scripts/supermerger.py b/scripts/supermerger.py index 30770ac..82b087b 100644 --- a/scripts/supermerger.py +++ b/scripts/supermerger.py @@ -1303,5 +1303,9 @@ def has_alphanumeric(text): pattern = re.compile(r'[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;"\'<>,.?/\|\\]') return bool(pattern.search(text.replace("",""))) +from api import on_app_started + if __package__ == "supermerger": + script_callbacks.on_app_started(on_app_started) script_callbacks.on_ui_tabs(on_ui_tabs) + diff --git a/xyzpresets.json b/xyzpresets.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/xyzpresets.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 46408a055cfcf42b715bee50b15c6ae21b4ee4a5 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Tue, 2 Apr 2024 14:39:38 +0700 Subject: [PATCH 02/22] - add upload lora file and merge to checkpoint api --- api.py | 82 +++++++++++++++++++++++++++++++++++++++++-- api_models.py | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 174 insertions(+), 4 deletions(-) diff --git a/api.py b/api.py index b60eeb1..edec46d 100644 --- a/api.py +++ b/api.py @@ -17,6 +17,10 @@ import api_models as models from scripts.mergers import pluslora +from fastapi import File, UploadFile, Form +from typing import Annotated +import shutil + class Api: """Api class for FastAPI""" @@ -65,11 +69,25 @@ def __init__( self.add_api_route( 'merge-lora', - self.merge_lora, + self.merge_lora_api, methods=['POST'], response_model=models.MergeLoraResponse, ) + self.add_api_route( + 'upload-lora', + self.upload_lora_api, + methods=['POST'], + response_model=models.UploadLoraResponse, + ) + + self.add_api_route( + 'upload-lora-merge-checkpoint', + self.upload_lora_and_merge_lora_to_checkpoint, + methods=['POST'], + response_model=models.UploadLoraMergeLoraResponse, + ) + async def add_to_queue(self, m, q, n='', i=None, t=0.0) -> Dict[ str, Dict[str, float] ]: @@ -189,7 +207,7 @@ def endpoint_unload_interrogators(self): return f"Successfully unload {unloaded_models} model(s)" - def merge_lora(self, request: models.MergeLoraRequest): + def merge_lora(self, request: models.MergeLoraRequest) -> str: """Merge Lora""" try: # comment: @@ -220,12 +238,72 @@ def merge_lora(self, request: models.MergeLoraRequest): settings=[] ) + return res + + except Exception as e: + raise e + # end try + + def merge_lora_api(self, request: models.MergeLoraRequest): + """Merge Lora""" + try: + # comment: + + res = self.merge_lora(request) + return models.MergeLoraResponse(checkpoint_merged_path=res) except Exception as e: raise e # end try + def upload_file(self, file: UploadFile): + try: + # save lora file to disk + file_location = f"models/Lora/{file.filename}" + with open(file_location, "wb+") as file_object: + shutil.copyfileobj(file.file, file_object) + message = f'{file.filename} saved at {file_location}' + + return message + except Exception as e: + raise e + # end try + + def upload_lora_api(self, lora_file: UploadFile): + """Upload Lora""" + try: + # comment: + message = self.upload_file(lora_file) + + return models.UploadLoraResponse(message=message) + except Exception as e: + raise e + # end try + + def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_request: models.UploadLoraMergeLoraRequest = Depends()): + """Upload Lora and merge Lora to checkpoint""" + try: + # comment: + print("Merge Request: ", merge_request) + lora_file_name = lora_file.filename.split(".")[0] + + upload_res = self.upload_file(lora_file) + + # merge lora + merge_request.lnames = f"{lora_file_name}:{merge_request.rate}" + + merged_res = self.merge_lora(merge_request) + + message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' + + checkpoint_merged_name = merged_res.split("/")[-1] + + return models.UploadLoraMergeLoraResponse(message=message, checkpoint_merged_name=checkpoint_merged_name) + except Exception as e: + raise e + # end try + def on_app_started(_, app: FastAPI): Api(app, queue_lock, '/supermerger/v1') diff --git a/api_models.py b/api_models.py index 5cf7565..d283b1c 100644 --- a/api_models.py +++ b/api_models.py @@ -4,6 +4,9 @@ from modules.api import models as sd_models # pylint: disable=E0401 from pydantic import BaseModel, Field +from fastapi import File, UploadFile, Form +from typing import Annotated + class TaggerInterrogateRequest(sd_models.InterrogateRequest): """Interrogate request model""" @@ -44,6 +47,7 @@ class TaggerInterrogatorsResponse(BaseModel): description='' ) + class MergeLoraRequest(BaseModel): """Interrogate request model""" lnames: str = Field( @@ -86,11 +90,99 @@ class MergeLoraRequest(BaseModel): description='Loraratios.', default='', ) - + + class MergeLoraResponse(BaseModel): """Interrogate request model""" checkpoint_merged_path: str = Field( title='Merged Checkpoint Path', description='Merged Checkpoin Path.', default='', - ) \ No newline at end of file + ) + + +class UploadLoraRequest(BaseModel): + """Interrogate request model""" + lora_file: UploadFile + + +class UploadLoraResponse(BaseModel): + """Interrogate request model""" + message: str = Field( + title='Message', + description='Message.', + default='', + ) + + +class ErrorResponse(BaseModel): + """Error response model""" + message: str = Field( + title='Message', + description='Error message.', + default='', + ) + + +class UploadLoraMergeLoraRequest(BaseModel): + """Interrogate request model""" + lnames: str = Field( + title='Lnames', + description='Lora name.', + default='NgocYen001:1', + ) + output: str = Field( + title='Output name', + description='Output name.', + default='lora_output', + ) + model: str = Field( + title='model', + description='Checkpoint model used for the generation.', + default='dreamshaper_8.safetensors', + ) + save_precision: str = Field( + title='Save precision', + description='Save precision.', + default='fp16', + ) + calc_precision: str = Field( + title='Calc precision', + description='Calc precision.', + default='float' + ) + metasets: str = Field( + title='Metasets', + description='Metasets.', + default='create new', + ) + device: str = Field( + title='Device', + description='Device.', + default='cuda', + ) + loraratios: str = Field( + title='Loraratios', + description='Loraratios.', + default='', + ) + rate: float = Field( + title='Rate', + description='Rate.', + default=0.7, + ) + + +class UploadLoraMergeLoraResponse(BaseModel): + + message = Field( + title='Message', + description='Message.', + default='', + ) + + checkpoint_merged_name: str = Field( + title='Checkpoint Merged Name', + description='Checkpoint Merged Name.', + default='', + ) From 01269959c9518d1510a673ddd42e2d64404cbd40 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 3 Apr 2024 09:44:01 +0700 Subject: [PATCH 03/22] - add logs --- api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api.py b/api.py index edec46d..915b31d 100644 --- a/api.py +++ b/api.py @@ -289,10 +289,12 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ lora_file_name = lora_file.filename.split(".")[0] upload_res = self.upload_file(lora_file) + print("Uploaded file successfully: ", upload_res) # merge lora merge_request.lnames = f"{lora_file_name}:{merge_request.rate}" - + + print("Started to merge lora") merged_res = self.merge_lora(merge_request) message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' From fc4ea5ed5f5011a654c8120721e77d59d40b78b4 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 3 Apr 2024 11:13:31 +0700 Subject: [PATCH 04/22] - add refresh lora after upload to sd --- api.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/api.py b/api.py index 915b31d..aea5a65 100644 --- a/api.py +++ b/api.py @@ -1,4 +1,5 @@ """API module for FastAPI""" +import requests from typing import Callable, Dict, Optional from threading import Lock from secrets import compare_digest @@ -244,6 +245,19 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: raise e # end try + def referesh_loras_request(self): + """Refresh Loras""" + try: + # comment: + + res = requests.post("http://localhost:7860/sdapi/v1/refresh-loras") + + return res + + except Exception as e: + raise e + # end try + def merge_lora_api(self, request: models.MergeLoraRequest): """Merge Lora""" try: @@ -275,6 +289,7 @@ def upload_lora_api(self, lora_file: UploadFile): try: # comment: message = self.upload_file(lora_file) + self.referesh_loras_request() return models.UploadLoraResponse(message=message) except Exception as e: From aa52b1b2ddf44abcb6719cfa0490746f77542dbb Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 3 Apr 2024 11:33:10 +0700 Subject: [PATCH 05/22] - add refresh after upload file --- api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api.py b/api.py index aea5a65..1d3d7f0 100644 --- a/api.py +++ b/api.py @@ -290,7 +290,7 @@ def upload_lora_api(self, lora_file: UploadFile): # comment: message = self.upload_file(lora_file) self.referesh_loras_request() - + return models.UploadLoraResponse(message=message) except Exception as e: raise e @@ -305,6 +305,7 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ upload_res = self.upload_file(lora_file) print("Uploaded file successfully: ", upload_res) + self.referesh_loras_request() # merge lora merge_request.lnames = f"{lora_file_name}:{merge_request.rate}" From bea9cb1c126229d7b833351c476dba7840cf123c Mon Sep 17 00:00:00 2001 From: flydino linux Date: Thu, 4 Apr 2024 11:30:17 +0700 Subject: [PATCH 06/22] - add LCM lora auto --- api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api.py b/api.py index 1d3d7f0..d108444 100644 --- a/api.py +++ b/api.py @@ -225,6 +225,7 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" + request.lnames = f"{request.lnames},pytorch_lora_weights:1" data = request res = pluslora.pluslora( From 0730a4a69b219e3452ab25f968c47f5d7fb389bc Mon Sep 17 00:00:00 2001 From: hako-mikan <122196982+hako-mikan@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:59:38 +0900 Subject: [PATCH 07/22] #345 --- scripts/mergers/pluslora.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/mergers/pluslora.py b/scripts/mergers/pluslora.py index 3960009..6b723de 100644 --- a/scripts/mergers/pluslora.py +++ b/scripts/mergers/pluslora.py @@ -177,6 +177,7 @@ def on_ui_tabs(): def toselect(input): out = [] for name, vals in input.items(): + if (not isinstance(vals, list)) or len(vals) != 3: continue dim, ltype, sdver = vals add = [] if dim == "LyCORIS" else [str(dim)] if ltype != "LoRA": add +=[ltype] @@ -694,8 +695,14 @@ def pluslora(lnames,loraratios,settings,output,model,save_precision,calc_precisi import lora lnames = lnames.split(",") - for i, n in enumerate(lnames): - lnames[i] = n.split(":") + temp = [] + for n in lnames: + if ":" in n: + temp.append(n.split(":")) + else: + temp[-1].append(n) + + lnames = temp loraratios=loraratios.splitlines() ldict ={} @@ -707,11 +714,16 @@ def pluslora(lnames,loraratios,settings,output,model,save_precision,calc_precisi names, filenames, loratypes, lweis = [], [], [], [] for n in lnames: - if len(n) ==3: + if len(n) ==2: + ratio = [float(n[1])]*26 + elif len(n) ==3: if n[2].strip() in ldict: ratio = [float(r)*float(n[1]) for r in ldict[n[2]].split(",")] ratio = to26(ratio) else:ratio = [float(n[1])]*26 + elif len(n[2:]) in BLOCKNUMS: + ratio = [float(x) for x in n[2:]] + ratio = to26(ratio) else:ratio = [float(n[1])]*26 c_lora = lora.available_loras.get(n[0], None) names.append(n[0]) From 97030c89bc94ada7f56e5adcd784e90887a8db6f Mon Sep 17 00:00:00 2001 From: hako-mikan <122196982+hako-mikan@users.noreply.github.com> Date: Sat, 6 Apr 2024 00:33:45 +0900 Subject: [PATCH 08/22] #345 --- scripts/mergers/pluslora.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/mergers/pluslora.py b/scripts/mergers/pluslora.py index 6b723de..97ce224 100644 --- a/scripts/mergers/pluslora.py +++ b/scripts/mergers/pluslora.py @@ -182,15 +182,16 @@ def toselect(input): add = [] if dim == "LyCORIS" else [str(dim)] if ltype != "LoRA": add +=[ltype] if sdver != "1.X/2.X": add += [sdver] - out.append(f"{name}[{','.join(add)}]") + out.append(f"{name}[{','.join(add)}]" if add != ["","",""] else f"{name}") return out def updateloras(): lora.list_available_loras() names = [] for n in lora.available_loras.items(): - if n[0] not in ldict:ldict[n[0]] = "" + if n[0] not in ldict:ldict[n[0]] = ["","",""] names.append(n[0]) + for l in list(ldict.keys()): if l not in names:ldict.pop(l) @@ -225,7 +226,7 @@ def calculatedim(calcsets): print("listing dimensions...") for n in tqdm(lora.available_loras.items()): name = n[0] - if name in ldict and ldict[n[0]] != "": + if name in ldict and ldict[n[0]] != ["","",""]: continue c_lora = lora.available_loras.get(n[0], None) d, t, s = dimgetter(c_lora.filename) From 6f191f36baf36b17065d49baa551f7308f1b9d4e Mon Sep 17 00:00:00 2001 From: hako-mikan <122196982+hako-mikan@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:31:13 +0900 Subject: [PATCH 09/22] fix 2nd text encoder for XL --- scripts/mergers/pluslora.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/mergers/pluslora.py b/scripts/mergers/pluslora.py index 97ce224..8c4e579 100644 --- a/scripts/mergers/pluslora.py +++ b/scripts/mergers/pluslora.py @@ -935,7 +935,7 @@ def lbw(lora,lwei,isv2): for i,block in enumerate(blocks): if block in key: - if i == 26: i=0 + if i == 26 or i == 27: i=0 ratio = lwei[i] picked = True @@ -1194,7 +1194,8 @@ def makeloraname(model_a,model_b): "diffusion_model_output_blocks_9_", "diffusion_model_output_blocks_10_", "diffusion_model_output_blocks_11_", -"embedders"] +"embedders", +"transformer_resblocks"] ########################################################### ##### metadata From fb1791896d551a918dfb703dd5347db29407a58e Mon Sep 17 00:00:00 2001 From: flydino linux Date: Mon, 8 Apr 2024 16:40:33 +0700 Subject: [PATCH 10/22] - add merge lora to queue --- api.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/api.py b/api.py index d108444..60dd1a2 100644 --- a/api.py +++ b/api.py @@ -21,7 +21,8 @@ from fastapi import File, UploadFile, Form from typing import Annotated import shutil - +from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task +from time import sleep class Api: """Api class for FastAPI""" @@ -225,7 +226,7 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" - request.lnames = f"{request.lnames},pytorch_lora_weights:1" + request.lnames = f"{request.lnames},pytorch_lora_weights:0.7" data = request res = pluslora.pluslora( @@ -291,7 +292,7 @@ def upload_lora_api(self, lora_file: UploadFile): # comment: message = self.upload_file(lora_file) self.referesh_loras_request() - + return models.UploadLoraResponse(message=message) except Exception as e: raise e @@ -300,8 +301,16 @@ def upload_lora_api(self, lora_file: UploadFile): def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_request: models.UploadLoraMergeLoraRequest = Depends()): """Upload Lora and merge Lora to checkpoint""" try: + + task_id = create_task_id( + "upload_lora_and_merge_lora_to_checkpoint") + print("Task ID: ", task_id) + add_task_to_queue(task_id) # comment: + + start_task(task_id) print("Merge Request: ", merge_request) + # sleep(30) lora_file_name = lora_file.filename.split(".")[0] upload_res = self.upload_file(lora_file) @@ -309,8 +318,8 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ self.referesh_loras_request() # merge lora - merge_request.lnames = f"{lora_file_name}:{merge_request.rate}" - + merge_request.lnames = f"{lora_file_name}:0.8" + print("Started to merge lora") merged_res = self.merge_lora(merge_request) @@ -321,8 +330,12 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ return models.UploadLoraMergeLoraResponse(message=message, checkpoint_merged_name=checkpoint_merged_name) except Exception as e: raise e + finally: + print("Finish task") + finish_task(task_id) # end try def on_app_started(_, app: FastAPI): + Api(app, queue_lock, '/supermerger/v1') From 7479609a26727aba138efba7c76de55e3a54a749 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Tue, 9 Apr 2024 14:13:17 +0700 Subject: [PATCH 11/22] - add api to queue lock --- api.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/api.py b/api.py index 60dd1a2..40851d9 100644 --- a/api.py +++ b/api.py @@ -24,6 +24,7 @@ from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task from time import sleep + class Api: """Api class for FastAPI""" @@ -302,30 +303,41 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ """Upload Lora and merge Lora to checkpoint""" try: - task_id = create_task_id( - "upload_lora_and_merge_lora_to_checkpoint") - print("Task ID: ", task_id) + task_id = create_task_id("txt2img") + print("Task merge ID: ", task_id) add_task_to_queue(task_id) # comment: - start_task(task_id) print("Merge Request: ", merge_request) - # sleep(30) lora_file_name = lora_file.filename.split(".")[0] - upload_res = self.upload_file(lora_file) - print("Uploaded file successfully: ", upload_res) - self.referesh_loras_request() + with self.queue_lock: + + try: + shared.state.begin(job="scripts_txt2img") + start_task(task_id) + sleep(30) - # merge lora - merge_request.lnames = f"{lora_file_name}:0.8" + upload_res = self.upload_file(lora_file) + print("Uploaded file successfully: ", upload_res) + self.referesh_loras_request() - print("Started to merge lora") - merged_res = self.merge_lora(merge_request) + # merge lora + merge_request.lnames = f"{lora_file_name}:0.8" - message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' + print("Started to merge lora") + merged_res = self.merge_lora(merge_request) - checkpoint_merged_name = merged_res.split("/")[-1] + message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' + + checkpoint_merged_name = merged_res.split("/")[-1] + finally: + shared.state.end() + shared.total_tqdm.clear() + finish_task(task_id) + + + return models.UploadLoraMergeLoraResponse(message=message, checkpoint_merged_name=checkpoint_merged_name) except Exception as e: @@ -337,5 +349,4 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ def on_app_started(_, app: FastAPI): - Api(app, queue_lock, '/supermerger/v1') From fa12bd4295012110735314fc674cdc976ded3422 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Tue, 9 Apr 2024 14:18:53 +0700 Subject: [PATCH 12/22] - add api to queue lock --- api.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/api.py b/api.py index 40851d9..79c00f5 100644 --- a/api.py +++ b/api.py @@ -24,7 +24,6 @@ from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task from time import sleep - class Api: """Api class for FastAPI""" @@ -316,7 +315,6 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ try: shared.state.begin(job="scripts_txt2img") start_task(task_id) - sleep(30) upload_res = self.upload_file(lora_file) print("Uploaded file successfully: ", upload_res) From 64c19541117b9874dc5e02c030daf0fe4b49c1be Mon Sep 17 00:00:00 2001 From: hako-mikan <122196982+hako-mikan@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:11:37 +0900 Subject: [PATCH 13/22] #364 --- scripts/GenParamGetter.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/GenParamGetter.py b/scripts/GenParamGetter.py index d46a689..3c511b0 100644 --- a/scripts/GenParamGetter.py +++ b/scripts/GenParamGetter.py @@ -103,6 +103,25 @@ def get_params_components(demo: gr.Blocks, app): outputs=[*components.imagegal], ) + components.merge2.click( + fn=smergegen, + inputs=[*components.msettings,components.esettings1,*components.genparams,*components.hiresfix,*components.lucks,components.currentmodel,components.dfalse,*components.txt2img_params], + outputs=[components.submit_result,components.currentmodel] + ) + + components.mergeandgen2.click( + fn=smergegen, + inputs=[*components.msettings,components.esettings1,*components.genparams,*components.hiresfix,*components.lucks,components.currentmodel,components.dtrue,*components.txt2img_params], + outputs=[components.submit_result,components.currentmodel,*components.imagegal] + ) + + components.gen2.click( + fn=simggen, + inputs=[*components.genparams,*components.hiresfix,components.currentmodel,components.id_sets,gr.Textbox(value="No id",visible=False),*components.txt2img_params], + outputs=[*components.imagegal], + ) + + components.s_reserve.click( fn=numanager, inputs=[gr.Textbox(value="reserve",visible=False),*components.xysettings,*components.msettings,*components.genparams,*components.hiresfix,*components.lucks,*components.txt2img_params], From 843ca282948dbd3fac1246fcb1b66544a371778b Mon Sep 17 00:00:00 2001 From: hako-mikan <122196982+hako-mikan@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:12:05 +0900 Subject: [PATCH 14/22] #364 --- scripts/supermerger.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/supermerger.py b/scripts/supermerger.py index 77f7bd4..0ca9dad 100644 --- a/scripts/supermerger.py +++ b/scripts/supermerger.py @@ -410,6 +410,12 @@ def on_ui_tabs(): mgeninfo = output_panel[1] if isinstance(output_panel, tuple) else output_panel.generation_info mhtmlinfo = output_panel[2] if isinstance(output_panel, tuple) else output_panel.infotext mhtmllog = output_panel[3] if isinstance(output_panel, tuple) else output_panel.html_log + + with gr.Row(): + components.merge2 = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Merge!",variant='primary') + components.mergeandgen2 = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Merge&Gen",variant='primary') + components.gen2 = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Gen",variant='primary') + stopmerge2 = gr.Button(elem_id="stopmerge", elem_classes=["compact_button"], value="Stop") # main ui end @@ -539,6 +545,7 @@ def unload(): stopgrid.click(fn=freezetime) stopmerge.click(fn=freezemtime) + stopmerge2.click(fn=freezemtime) checkpoints.change(fn=lambda x:",".join(x),inputs=[checkpoints],outputs=[inputer]) blockids.change(fn=lambda x:" ".join(x),inputs=[blockids],outputs=[inputer]) From 7c005e26405b9ad6b473efd068b668ae5ebf2cc9 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Mon, 22 Apr 2024 09:52:22 +0700 Subject: [PATCH 15/22] - unload api --- api.py | 2 +- scripts/supermerger.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api.py b/api.py index 79c00f5..1947179 100644 --- a/api.py +++ b/api.py @@ -226,7 +226,7 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" - request.lnames = f"{request.lnames},pytorch_lora_weights:0.7" + request.lnames = f"{request.lnames}" data = request res = pluslora.pluslora( diff --git a/scripts/supermerger.py b/scripts/supermerger.py index 82b087b..9b5bfdf 100644 --- a/scripts/supermerger.py +++ b/scripts/supermerger.py @@ -1303,9 +1303,9 @@ def has_alphanumeric(text): pattern = re.compile(r'[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;"\'<>,.?/\|\\]') return bool(pattern.search(text.replace("",""))) -from api import on_app_started +# from api import on_app_started if __package__ == "supermerger": - script_callbacks.on_app_started(on_app_started) + # script_callbacks.on_app_started(on_app_started) script_callbacks.on_ui_tabs(on_ui_tabs) From f47cb2219a5199aba616c54ce28f1a0184c4f02e Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 24 Apr 2024 11:50:32 +0700 Subject: [PATCH 16/22] - update for python 39 --- api.py | 3 +-- api_models.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/api.py b/api.py index d108444..fa55a64 100644 --- a/api.py +++ b/api.py @@ -19,7 +19,6 @@ from scripts.mergers import pluslora from fastapi import File, UploadFile, Form -from typing import Annotated import shutil @@ -225,7 +224,7 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" - request.lnames = f"{request.lnames},pytorch_lora_weights:1" + request.lnames = f"{request.lnames}" data = request res = pluslora.pluslora( diff --git a/api_models.py b/api_models.py index d283b1c..4da739e 100644 --- a/api_models.py +++ b/api_models.py @@ -5,7 +5,6 @@ from pydantic import BaseModel, Field from fastapi import File, UploadFile, Form -from typing import Annotated class TaggerInterrogateRequest(sd_models.InterrogateRequest): From 3399498be29feb67d27b17b901352600cf233469 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 24 Apr 2024 11:54:40 +0700 Subject: [PATCH 17/22] Update merge lora without lcm --- api.py | 47 ++++++++++++++++++++++++++++++++++++++---- api_models.py | 6 ++++++ scripts/supermerger.py | 4 ++-- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/api.py b/api.py index bcb2493..dc085e8 100644 --- a/api.py +++ b/api.py @@ -23,6 +23,7 @@ from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task from time import sleep + class Api: """Api class for FastAPI""" @@ -246,6 +247,44 @@ def merge_lora(self, request: models.MergeLoraRequest) -> str: raise e # end try + def merge_lora_with_lcm(self, request: models.MergeLoraRequest) -> str: + """Merge Lora""" + try: + # comment: + + request.loraratios = "\ + NONE:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\ + ALL:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1\n\ + INS:1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0\n\ + IND:1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0\n\ + INALL:1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0\n\ + MIDD:1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0\n\ + OUTD:1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0\n\ + OUTS:1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1\n\ + OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1\n\ + ALL0.5:0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5" + + request.lnames = f"{request.lnames}, pytorch_lora_weights:0.8" + data = request + + res = pluslora.pluslora( + loraratios=data.loraratios, + calc_precision=data.calc_precision, + device=data.device, + lnames=data.lnames, + metasets=data.metasets, + model=data.model, + output=data.output, + save_precision=data.save_precision, + settings=[] + ) + + return res + + except Exception as e: + raise e + # end try + def referesh_loras_request(self): """Refresh Loras""" try: @@ -323,7 +362,10 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ merge_request.lnames = f"{lora_file_name}:0.8" print("Started to merge lora") - merged_res = self.merge_lora(merge_request) + if merge_request.is_with_lcm == True: + merged_res = self.merge_lora_with_lcm(merge_request) + else: + merged_res = self.merge_lora(merge_request) message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' @@ -333,9 +375,6 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ shared.total_tqdm.clear() finish_task(task_id) - - - return models.UploadLoraMergeLoraResponse(message=message, checkpoint_merged_name=checkpoint_merged_name) except Exception as e: raise e diff --git a/api_models.py b/api_models.py index 4da739e..7b36efe 100644 --- a/api_models.py +++ b/api_models.py @@ -170,6 +170,12 @@ class UploadLoraMergeLoraRequest(BaseModel): description='Rate.', default=0.7, ) + + is_with_lcm: bool = Field( + title='Is with LCM', + description='Is with LCM.', + default=False, + ) class UploadLoraMergeLoraResponse(BaseModel): diff --git a/scripts/supermerger.py b/scripts/supermerger.py index c1081db..9f04ebe 100644 --- a/scripts/supermerger.py +++ b/scripts/supermerger.py @@ -1310,9 +1310,9 @@ def has_alphanumeric(text): pattern = re.compile(r'[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;"\'<>,.?/\|\\]') return bool(pattern.search(text.replace("",""))) -# from api import on_app_started +from api import on_app_started if __package__ == "supermerger": - # script_callbacks.on_app_started(on_app_started) + script_callbacks.on_app_started(on_app_started) script_callbacks.on_ui_tabs(on_ui_tabs) From ad77114c1384ea4827d5e00961ae46db2dcceda4 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Wed, 24 Apr 2024 13:48:32 +0700 Subject: [PATCH 18/22] - fix for queue --- api.py | 6 +++--- scripts/GenParamGetter.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api.py b/api.py index dc085e8..2685e90 100644 --- a/api.py +++ b/api.py @@ -351,7 +351,7 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ with self.queue_lock: try: - shared.state.begin(job="scripts_txt2img") + # shared.state.begin(job="scripts_txt2img") start_task(task_id) upload_res = self.upload_file(lora_file) @@ -371,8 +371,8 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ checkpoint_merged_name = merged_res.split("/")[-1] finally: - shared.state.end() - shared.total_tqdm.clear() + # shared.state.end() + # shared.total_tqdm.clear() finish_task(task_id) return models.UploadLoraMergeLoraResponse(message=message, checkpoint_merged_name=checkpoint_merged_name) diff --git a/scripts/GenParamGetter.py b/scripts/GenParamGetter.py index 3c511b0..82f8345 100644 --- a/scripts/GenParamGetter.py +++ b/scripts/GenParamGetter.py @@ -36,8 +36,8 @@ def after_component(self, component: gr.components.Component, **_kwargs): elif component.elem_id == "img2img_generate": GenParamGetter.img2img_gen_button = component - def get_components_by_ids(root: gr.Blocks, ids: list[int]): - components: list[gr.Blocks] = [] + def get_components_by_ids(root: gr.Blocks, ids: 'list[int]'): + components: 'list[gr.Blocks]' = [] if root._id in ids: components.append(root) @@ -48,7 +48,7 @@ def get_components_by_ids(root: gr.Blocks, ids: list[int]): components.extend(GenParamGetter.get_components_by_ids(block, ids)) return components - def compare_components_with_ids(components: list[gr.Blocks], ids: list[int]): + def compare_components_with_ids(components: 'list[gr.Blocks]', ids: 'list[int]'): return len(components) == len(ids) and all(component._id == _id for component, _id in zip(components, ids)) def get_params_components(demo: gr.Blocks, app): From b263fadbcc4e306f4dd04db337945749338d9bc0 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Thu, 25 Apr 2024 10:17:25 +0700 Subject: [PATCH 19/22] - add merge without LCM for stable diffusion v1.3.0 --- api_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_models.py b/api_models.py index 7b36efe..de4f788 100644 --- a/api_models.py +++ b/api_models.py @@ -173,7 +173,7 @@ class UploadLoraMergeLoraRequest(BaseModel): is_with_lcm: bool = Field( title='Is with LCM', - description='Is with LCM.', + description='Default false for Stable Diffusion v1.3 is not compatible with LCM.', default=False, ) From 26713d5ccc8edfb8731150769e5e682ff8099399 Mon Sep 17 00:00:00 2001 From: flydino linux Date: Thu, 25 Apr 2024 10:25:06 +0700 Subject: [PATCH 20/22] - add merge without LCM for stable diffusion v1.3.0 --- api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.py b/api.py index 2685e90..0c293aa 100644 --- a/api.py +++ b/api.py @@ -359,7 +359,7 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ self.referesh_loras_request() # merge lora - merge_request.lnames = f"{lora_file_name}:0.8" + merge_request.lnames = f"{lora_file_name}:{merge_request.rate}" print("Started to merge lora") if merge_request.is_with_lcm == True: From 28e4987f129f2680912babf978fd9921b8ca146f Mon Sep 17 00:00:00 2001 From: "nhutl@flydinotech.com" Date: Thu, 9 May 2024 10:08:36 +0700 Subject: [PATCH 21/22] copy checkpoint --- .env.example | 3 +++ api.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b7138ce --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +PEM_PATH= +SERVER_ADDRESS= +DESTINATION_FILE= \ No newline at end of file diff --git a/api.py b/api.py index 0c293aa..28e1d2c 100644 --- a/api.py +++ b/api.py @@ -22,6 +22,11 @@ import shutil from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task from time import sleep +import subprocess +import os +from dotenv import load_dotenv + +load_dotenv() class Api: @@ -367,6 +372,8 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ else: merged_res = self.merge_lora(merge_request) + self.copy_checkpoint(merged_res) + message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' checkpoint_merged_name = merged_res.split("/")[-1] @@ -382,7 +389,21 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ print("Finish task") finish_task(task_id) # end try + + def copy_checkpoint(source_file): + print(source_file) + pem_file = os.environ['PEM_PATH'] + server_address = os.environ['SERVER_ADDRESS'] + destination_file = os.environ['DESTINATION_FILE'] + + command = ["sudo", "scp", "-i", pem_file, source_file, server_address + ":" + destination_file] + try: + subprocess.run(command, check=True) + print("File copied successfully!") + except subprocess.CalledProcessError as e: + print("Error copying file:", e.output) + raise e def on_app_started(_, app: FastAPI): Api(app, queue_lock, '/supermerger/v1') From 165f9d5dff51ac4560bcfde83dffe293e5477219 Mon Sep 17 00:00:00 2001 From: "nhutl@flydinotech.com" Date: Mon, 13 May 2024 14:17:47 +0700 Subject: [PATCH 22/22] add print for scp --- api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api.py b/api.py index 28e1d2c..a493071 100644 --- a/api.py +++ b/api.py @@ -372,6 +372,7 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ else: merged_res = self.merge_lora(merge_request) + print('Merge checkpoint response:: ', merged_res) self.copy_checkpoint(merged_res) message = f'Upload and merge lora <{lora_file.filename}> to checkpoint <{merge_request.model}> successfully.' @@ -391,7 +392,7 @@ def upload_lora_and_merge_lora_to_checkpoint(self, lora_file: UploadFile, merge_ # end try def copy_checkpoint(source_file): - print(source_file) + print('Source file:: ', source_file) pem_file = os.environ['PEM_PATH'] server_address = os.environ['SERVER_ADDRESS'] destination_file = os.environ['DESTINATION_FILE']