mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 01:04:32 +02:00
add ip_adapter to api and fix control
This commit is contained in:
@@ -105,34 +105,6 @@ class Api:
|
||||
shared.log.info(f'Browser session: user={user} client={req.client.host} agent={agent}')
|
||||
return {}
|
||||
|
||||
def prepare_img_gen_request(self, request):
|
||||
if hasattr(request, "face") and request.face and not request.script_name and (not request.alwayson_scripts or "face" not in request.alwayson_scripts.keys()):
|
||||
request.script_name = "face"
|
||||
request.script_args = [
|
||||
request.face.mode,
|
||||
request.face.source_images,
|
||||
request.face.ip_model,
|
||||
request.face.ip_override_sampler,
|
||||
request.face.ip_cache_model,
|
||||
request.face.ip_strength,
|
||||
request.face.ip_structure,
|
||||
request.face.id_strength,
|
||||
request.face.id_conditioning,
|
||||
request.face.id_cache,
|
||||
request.face.pm_trigger,
|
||||
request.face.pm_strength,
|
||||
request.face.pm_start,
|
||||
request.face.fs_cache
|
||||
]
|
||||
del request.face
|
||||
|
||||
if hasattr(request, "ip_adapter") and request.ip_adapter and request.script_name != "IP Adapter" and (not request.alwayson_scripts or "IP Adapter" not in request.alwayson_scripts.keys()):
|
||||
request.alwayson_scripts = {} if request.alwayson_scripts is None else request.alwayson_scripts
|
||||
request.alwayson_scripts["IP Adapter"] = {
|
||||
"args": [request.ip_adapter.adapter, request.ip_adapter.scale, request.ip_adapter.image]
|
||||
}
|
||||
del request.ip_adapter
|
||||
|
||||
def set_upscalers(self, req: dict):
|
||||
reqDict = vars(req)
|
||||
reqDict['extras_upscaler_1'] = reqDict.pop('upscaler_1', None)
|
||||
|
||||
+20
-4
@@ -28,7 +28,7 @@ ReqControl = models.create_model_from_signature(
|
||||
{"key": "send_images", "type": bool, "default": True},
|
||||
{"key": "save_images", "type": bool, "default": False},
|
||||
{"key": "alwayson_scripts", "type": dict, "default": {}},
|
||||
{"key": "ip_adapter", "type": Optional[models.ItemIPAdapter], "default": None, "exclude": True},
|
||||
{"key": "ip_adapter", "type": Optional[List[models.ItemIPAdapter]], "default": None, "exclude": True},
|
||||
{"key": "face", "type": Optional[models.ItemFace], "default": None, "exclude": True},
|
||||
{"key": "control", "type": Optional[List[ItemControl]], "default": [], "exclude": True},
|
||||
]
|
||||
@@ -93,9 +93,27 @@ class APIControl():
|
||||
]
|
||||
del req.face
|
||||
|
||||
def prepare_ip_adapter(self, request):
|
||||
if hasattr(request, "ip_adapter") and request.ip_adapter:
|
||||
args = { 'ip_adapter_names': [], 'ip_adapter_scales': [], 'ip_adapter_starts': [], 'ip_adapter_ends': [], 'ip_adapter_images': [] }
|
||||
for ipadapter in request.ip_adapter:
|
||||
if not ipadapter.images or len(ipadapter.images) == 0:
|
||||
continue
|
||||
args['ip_adapter_names'].append(ipadapter.adapter)
|
||||
args['ip_adapter_scales'].append(ipadapter.scale)
|
||||
args['ip_adapter_starts'].append(ipadapter.start)
|
||||
args['ip_adapter_ends'].append(ipadapter.end)
|
||||
args['ip_adapter_images'].append([helpers.decode_base64_to_image(x) for x in ipadapter.images])
|
||||
del request.ip_adapter
|
||||
return args
|
||||
else:
|
||||
return {}
|
||||
|
||||
def prepare_control(self, req):
|
||||
from modules.control.unit import Unit, unit_types
|
||||
req.units = []
|
||||
if req.unit_type is None:
|
||||
return req.control
|
||||
if req.unit_type not in unit_types:
|
||||
shared.log.error(f'Control uknown unit type: type={req.unit_type} available={unit_types}')
|
||||
return req.control
|
||||
@@ -122,7 +140,6 @@ class APIControl():
|
||||
# prepare args
|
||||
args = req.copy(update={ # Override __init__ params
|
||||
"sampler_index": processing_helpers.get_sampler_index(req.sampler_name),
|
||||
"no_save": not req.save_images,
|
||||
"is_generator": False,
|
||||
"inputs": [helpers.decode_base64_to_image(x) for x in req.inputs] if req.inputs else None,
|
||||
"inits": [helpers.decode_base64_to_image(x) for x in req.inits] if req.inits else None,
|
||||
@@ -134,10 +151,10 @@ class APIControl():
|
||||
# run
|
||||
with self.queue_lock:
|
||||
shared.state.begin('api-control', api=True)
|
||||
|
||||
output_images = []
|
||||
output_processed = []
|
||||
output_info = ''
|
||||
run.control_set({ 'do_not_save_grid': not req.save_images, 'do_not_save_samples': not req.save_images, **self.prepare_ip_adapter(req) })
|
||||
res = run.control_run(**args)
|
||||
for item in res:
|
||||
if len(item) > 0 and (isinstance(item[0], list) or item[0] is None): # output_images
|
||||
@@ -146,7 +163,6 @@ class APIControl():
|
||||
output_info += item[2] if len(item) > 2 and item[2] is not None else ''
|
||||
else:
|
||||
output_info += item
|
||||
|
||||
shared.state.end(api=False)
|
||||
|
||||
# return
|
||||
|
||||
+19
-1
@@ -22,7 +22,6 @@ class APIGenerate():
|
||||
args.pop('alwayson_scripts', None)
|
||||
args.pop('face', None)
|
||||
args.pop('face_id', None)
|
||||
args.pop('ip_adapter', None)
|
||||
args.pop('save_images', None)
|
||||
return args
|
||||
|
||||
@@ -61,6 +60,23 @@ class APIGenerate():
|
||||
]
|
||||
del request.face
|
||||
|
||||
def prepare_ip_adapter(self, request, p):
|
||||
if hasattr(request, "ip_adapter") and request.ip_adapter:
|
||||
p.ip_adapter_names = []
|
||||
p.ip_adapter_scales = []
|
||||
p.ip_adapter_starts = []
|
||||
p.ip_adapter_ends = []
|
||||
p.ip_adapter_images = []
|
||||
for ipadapter in request.ip_adapter:
|
||||
if not ipadapter.images or len(ipadapter.images) == 0:
|
||||
continue
|
||||
p.ip_adapter_names.append(ipadapter.adapter)
|
||||
p.ip_adapter_scales.append(ipadapter.scale)
|
||||
p.ip_adapter_starts.append(ipadapter.start)
|
||||
p.ip_adapter_ends.append(ipadapter.end)
|
||||
p.ip_adapter_images.append([helpers.decode_base64_to_image(x) for x in ipadapter.images])
|
||||
del request.ip_adapter
|
||||
|
||||
def post_text2img(self, txt2imgreq: models.ReqTxt2Img):
|
||||
self.prepare_face_module(txt2imgreq)
|
||||
script_runner = scripts.scripts_txt2img
|
||||
@@ -81,6 +97,7 @@ class APIGenerate():
|
||||
send_images = args.pop('send_images', True)
|
||||
with self.queue_lock:
|
||||
p = StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)
|
||||
self.prepare_ip_adapter(txt2imgreq, p)
|
||||
p.scripts = script_runner
|
||||
p.outpath_grids = shared.opts.outdir_grids or shared.opts.outdir_txt2img_grids
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples
|
||||
@@ -123,6 +140,7 @@ class APIGenerate():
|
||||
send_images = args.pop('send_images', True)
|
||||
with self.queue_lock:
|
||||
p = StableDiffusionProcessingImg2Img(sd_model=shared.sd_model, **args)
|
||||
self.prepare_ip_adapter(img2imgreq, p)
|
||||
p.init_images = [helpers.decode_base64_to_image(x) for x in init_images]
|
||||
p.scripts = script_runner
|
||||
p.outpath_grids = shared.opts.outdir_img2img_grids
|
||||
|
||||
@@ -43,7 +43,7 @@ def setup_middleware(app: FastAPI, cmd_opts):
|
||||
endpoint = req.scope.get('path', 'err')
|
||||
token = req.cookies.get("access-token") or req.cookies.get("access-token-unsecure")
|
||||
if (cmd_opts.api_log or cmd_opts.api_only) and endpoint.startswith('/sdapi'):
|
||||
if '/sdapi/v1/log' or '/sdapi/v1/browser' in endpoint:
|
||||
if '/sdapi/v1/log' in endpoint or '/sdapi/v1/browser' in endpoint:
|
||||
return res
|
||||
log.info('API {user} {code} {prot}/{ver} {method} {endpoint} {cli} {duration}'.format( # pylint: disable=consider-using-f-string, logging-format-interpolation
|
||||
user = app.tokens.get(token) if hasattr(app, 'tokens') else None,
|
||||
|
||||
@@ -149,9 +149,11 @@ class ItemEmbedding(BaseModel):
|
||||
vectors: int = Field(title="Vectors", description="The number of vectors in the embedding")
|
||||
|
||||
class ItemIPAdapter(BaseModel):
|
||||
adapter: str = Field(title="Adapter", default="Base", description="Adapter to use")
|
||||
image: str = Field(title="Image", default="", description="Adapter image, must be a base64 string containing the image's data.")
|
||||
scale: float = Field(title="Scale", default=0.5, gt=0, le=1, description="Scale of the adapter image, must be between 0 and 1.")
|
||||
adapter: str = Field(title="Adapter", default="Base", description="")
|
||||
images: List[str] = Field(title="Image", default=[], description="")
|
||||
scale: float = Field(title="Scale", default=0.5, gt=0, le=1, description="")
|
||||
start: float = Field(title="Start", default=0.0, gt=0, le=1, description="")
|
||||
end: float = Field(title="End", default=1.0, gt=0, le=1, description="")
|
||||
|
||||
class ItemFace(BaseModel):
|
||||
mode: str = Field(title="Mode", default="FaceID", description="The mode to use (available values: FaceID, FaceSwap, PhotoMaker, InstantID).")
|
||||
@@ -204,7 +206,7 @@ ReqTxt2Img = PydanticModelGenerator(
|
||||
{"key": "send_images", "type": bool, "default": True},
|
||||
{"key": "save_images", "type": bool, "default": False},
|
||||
{"key": "alwayson_scripts", "type": dict, "default": {}},
|
||||
{"key": "ip_adapter", "type": Optional[ItemIPAdapter], "default": None, "exclude": True},
|
||||
{"key": "ip_adapter", "type": Optional[List[ItemIPAdapter]], "default": None, "exclude": True},
|
||||
{"key": "face", "type": Optional[ItemFace], "default": None, "exclude": True},
|
||||
]
|
||||
).generate_model()
|
||||
@@ -229,7 +231,7 @@ ReqImg2Img = PydanticModelGenerator(
|
||||
{"key": "send_images", "type": bool, "default": True},
|
||||
{"key": "save_images", "type": bool, "default": False},
|
||||
{"key": "alwayson_scripts", "type": dict, "default": {}},
|
||||
{"key": "ip_adapter", "type": Optional[ItemIPAdapter], "default": None, "exclude": True},
|
||||
{"key": "ip_adapter", "type": Optional[List[ItemIPAdapter]], "default": None, "exclude": True},
|
||||
{"key": "face_id", "type": Optional[ItemFace], "default": None, "exclude": True},
|
||||
]
|
||||
).generate_model()
|
||||
|
||||
Reference in New Issue
Block a user