Skip to content

Commit

Permalink
Merger for Fooocus v2.1.820
Browse files Browse the repository at this point in the history
Parameter format for `loras` has changed as JSON.
  • Loading branch information
konieshadow committed Nov 17, 2023
1 parent 3257152 commit a1623c2
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 74 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

FastAPI powered API for [Fooocus](https://github.com/lllyasviel/Fooocus)

Currently loaded Fooocus version: 2.1.806
Currently loaded Fooocus version: 2.1.820

### Run with Replicate
Now you can use Fooocus-API by Replicate, the model is in [konieshadow/fooocus-api](https://replicate.com/konieshadow/fooocus-api).
Expand Down Expand Up @@ -76,6 +76,9 @@ All the generation api support for response in PNG bytes directly when request's

All the generation api support async process by pass parameter `async_process` to true. And then use query job api to retrieve progress and generation results.

Break change from v0.3.16:
* Parameter format for `loras` has changed for the img2img apis (the multipart/form-data requests). Now it requires JSON string.

Break change from v0.3.0:
* The generation apis won't return `base64` field expect request parameters set `require_base64` to true.
* The generation apis return a `url` field where the generated image can be requested via a static file url.
Expand Down
2 changes: 1 addition & 1 deletion fooocus_api_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = '0.3.15'
version = '0.3.16'
2 changes: 1 addition & 1 deletion fooocusapi/api_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def req_to_params(req: Text2ImgRequest) -> ImageGenerationParams:
print(f"[Warning] Wrong inpaint_engine input: {adp.inpaint_engine}, using default")
adp.inpaint_engine = flags.default_inpaint_engine_version

advanced_params = [adp.adm_scaler_positive, adp.adm_scaler_negative, adp.adm_scaler_end, adp.adaptive_cfg, adp.sampler_name,
advanced_params = [adp.disable_preview, adp.adm_scaler_positive, adp.adm_scaler_negative, adp.adm_scaler_end, adp.adaptive_cfg, adp.sampler_name,
adp.scheduler_name, False, adp.overwrite_step, adp.overwrite_switch, adp.overwrite_width, adp.overwrite_height,
adp.overwrite_vary_strength, adp.overwrite_upscale_strength,
adp.mixing_image_prompt_and_vary_upscale, adp.mixing_image_prompt_and_inpaint,
Expand Down
100 changes: 41 additions & 59 deletions fooocusapi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
from fastapi import Form, UploadFile
from fastapi.params import File
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel, ConfigDict, Field, ValidationError, parse_obj_as
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, ValidationError, parse_obj_as
from typing import List
from enum import Enum

from pydantic_core import InitErrorDetails
from fooocusapi.parameters import GenerationFinishReason, defualt_styles, default_base_model_name, default_refiner_model_name, default_refiner_switch, default_lora_name, default_lora_weight, default_cfg_scale, default_prompt_negative, default_aspect_ratio, default_sampler, default_scheduler
from fooocusapi.parameters import GenerationFinishReason, defualt_styles, default_base_model_name, default_refiner_model_name, default_refiner_switch, default_loras, default_cfg_scale, default_prompt_negative, default_aspect_ratio, default_sampler, default_scheduler
from fooocusapi.task_queue import TaskType
import modules.flags as flags



class Lora(BaseModel):
model_name: str
weight: float = Field(default=0.5, ge=-2, le=2)
Expand All @@ -21,6 +22,11 @@ class Lora(BaseModel):
)


LoraList = TypeAdapter(List[Lora])
default_loras_model = [Lora(model_name=l[0], weight=l[1]) for l in default_loras if l[0] != 'None']
default_loras_json = LoraList.dump_json(default_loras_model)


class PerfomanceSelection(str, Enum):
speed = 'Speed'
quality = 'Quality'
Expand Down Expand Up @@ -58,6 +64,7 @@ class ImagePrompt(BaseModel):


class AdvancedParams(BaseModel):
disable_preview: bool = Field(False, description="Disable preview during generation")
adm_scaler_positive: float = Field(1.5, description="Positive ADM Guidance Scaler", ge=0.1, le=3.0)
adm_scaler_negative: float = Field(0.8, description="Negative ADM Guidance Scaler", ge=0.1, le=3.0)
adm_scaler_end: float = Field(0.3, description="ADM Guidance End At Step", ge=0.0, le=1.0)
Expand Down Expand Up @@ -100,8 +107,7 @@ class Text2ImgRequest(BaseModel):
base_model_name: str = default_base_model_name
refiner_model_name: str = default_refiner_model_name
refiner_switch: float = Field(default=default_refiner_switch, description="Refiner Switch At", ge=0.1, le=1.0)
loras: List[Lora] = Field(default=[
Lora(model_name=default_lora_name, weight=default_lora_weight)])
loras: List[Lora] = Field(default=default_loras_model)
advanced_params: AdvancedParams | None = Field(deafult=None, description="Advanced parameters")
require_base64: bool = Field(default=False, description="Return base64 data of generated image")
async_process: bool = Field(default=False, description="Set to true will run async and return job info for retrieve generataion result later")
Expand All @@ -128,17 +134,8 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for upsa
base_model_name: str = Form(default_base_model_name),
refiner_model_name: str = Form(default_refiner_model_name),
refiner_switch: float = Form(default=default_refiner_switch, description="Refiner Switch At", ge=0.1, le=1.0),
l1: str | None = Form(default_lora_name),
w1: float = Form(default=default_lora_weight, ge=-2, le=2),
l2: str | None = Form(None),
w2: float = Form(default=default_lora_weight, ge=-2, le=2),
l3: str | None = Form(None),
w3: float = Form(default=default_lora_weight, ge=-2, le=2),
l4: str | None = Form(None),
w4: float = Form(default=default_lora_weight, ge=-2, le=2),
l5: str | None = Form(None),
w5: float = Form(default=default_lora_weight, ge=-2, le=2),
advanced_params: str| None = Form(default=None, description="Advanced parameters in JSON"),
loras: str | None = Form(default=default_loras_json, description='Lora config in JSON. Format as [{"model_name": "sd_xl_offset_example-lora_1.0.safetensors", "weight": 0.5}]'),
advanced_params: str | None = Form(default=None, description="Advanced parameters in JSON"),
require_base64: bool = Form(default=False, description="Return base64 data of generated image"),
async_process: bool = Form(default=False, description="Set to true will run async and return job info for retrieve generataion result later"),
):
Expand All @@ -149,15 +146,16 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for upsa
style = s.strip()
style_selection_arr.append(style)

loras: List[Lora] = []
lora_config = [(l1, w1), (l2, w2), (l3, w3), (l4, w4), (l5, w5)]
for config in lora_config:
lora_model, lora_weight = config
if lora_model is not None and len(lora_model) > 0:
loras.append(Lora(model_name=lora_model, weight=lora_weight))
loras_model: List[Lora] = []
if loras is not None and len(loras) > 0:
try:
loras_model = LoraList.validate_json(loras)
except ValidationError as ve:
errs = ve.errors()
raise RequestValidationError(errors=[errs])

advanced_params_obj = None
if advanced_params != None and len(advanced_params) > 0:
if advanced_params is not None and len(advanced_params) > 0:
try:
advanced_params_obj = AdvancedParams.__pydantic_validator__.validate_json(advanced_params)
except ValidationError as ve:
Expand All @@ -168,7 +166,7 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for upsa
performance_selection=performance_selection, aspect_ratios_selection=aspect_ratios_selection,
image_number=image_number, image_seed=image_seed, sharpness=sharpness, guidance_scale=guidance_scale,
base_model_name=base_model_name, refiner_model_name=refiner_model_name, refiner_switch=refiner_switch,
loras=loras, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)
loras=loras_model, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)


class ImgInpaintOrOutpaintRequest(Text2ImgRequest):
Expand Down Expand Up @@ -196,16 +194,7 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for inpa
base_model_name: str = Form(default_base_model_name),
refiner_model_name: str = Form(default_refiner_model_name),
refiner_switch: float = Form(default=default_refiner_switch, description="Refiner Switch At", ge=0.1, le=1.0),
l1: str | None = Form(default_lora_name),
w1: float = Form(default=default_lora_weight, ge=-2, le=2),
l2: str | None = Form(None),
w2: float = Form(default=default_lora_weight, ge=-2, le=2),
l3: str | None = Form(None),
w3: float = Form(default=default_lora_weight, ge=-2, le=2),
l4: str | None = Form(None),
w4: float = Form(default=default_lora_weight, ge=-2, le=2),
l5: str | None = Form(None),
w5: float = Form(default=default_lora_weight, ge=-2, le=2),
loras: str | None = Form(default=default_loras_json, description='Lora config in JSON. Format as [{"model_name": "sd_xl_offset_example-lora_1.0.safetensors", "weight": 0.5}]'),
advanced_params: str| None = Form(default=None, description="Advanced parameters in JSON"),
require_base64: bool = Form(default=False, description="Return base64 data of generated image"),
async_process: bool = Form(default=False, description="Set to true will run async and return job info for retrieve generataion result later"),
Expand Down Expand Up @@ -233,15 +222,16 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for inpa
style = s.strip()
style_selection_arr.append(style)

loras: List[Lora] = []
lora_config = [(l1, w1), (l2, w2), (l3, w3), (l4, w4), (l5, w5)]
for config in lora_config:
lora_model, lora_weight = config
if lora_model is not None and len(lora_model) > 0:
loras.append(Lora(model_name=lora_model, weight=lora_weight))
loras_model: List[Lora] = []
if loras is not None and len(loras) > 0:
try:
loras_model = LoraList.validate_json(loras)
except ValidationError as ve:
errs = ve.errors()
raise RequestValidationError(errors=[errs])

advanced_params_obj = None
if advanced_params != None and len(advanced_params) > 0:
if advanced_params is not None and len(advanced_params) > 0:
try:
advanced_params_obj = AdvancedParams.__pydantic_validator__.validate_json(advanced_params)
except ValidationError as ve:
Expand All @@ -252,7 +242,7 @@ def as_form(cls, input_image: UploadFile = Form(description="Init image for inpa
performance_selection=performance_selection, aspect_ratios_selection=aspect_ratios_selection,
image_number=image_number, image_seed=image_seed, sharpness=sharpness, guidance_scale=guidance_scale,
base_model_name=base_model_name, refiner_model_name=refiner_model_name, refiner_switch=refiner_switch,
loras=loras, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)
loras=loras_model, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)


class ImgPromptRequest(Text2ImgRequest):
Expand Down Expand Up @@ -304,16 +294,7 @@ def as_form(cls, cn_img1: UploadFile = Form(File(None), description="Input image
base_model_name: str = Form(default_base_model_name),
refiner_model_name: str = Form(default_refiner_model_name),
refiner_switch: float = Form(default=default_refiner_switch, description="Refiner Switch At", ge=0.1, le=1.0),
l1: str | None = Form(default_lora_name),
w1: float = Form(default=default_lora_weight, ge=-2, le=2),
l2: str | None = Form(None),
w2: float = Form(default=default_lora_weight, ge=-2, le=2),
l3: str | None = Form(None),
w3: float = Form(default=default_lora_weight, ge=-2, le=2),
l4: str | None = Form(None),
w4: float = Form(default=default_lora_weight, ge=-2, le=2),
l5: str | None = Form(None),
w5: float = Form(default=default_lora_weight, ge=-2, le=2),
loras: str | None = Form(default=default_loras_json, description='Lora config in JSON. Format as [{"model_name": "sd_xl_offset_example-lora_1.0.safetensors", "weight": 0.5}]'),
advanced_params: str| None = Form(default=None, description="Advanced parameters in JSON"),
require_base64: bool = Form(default=False, description="Return base64 data of generated image"),
async_process: bool = Form(default=False, description="Set to true will run async and return job info for retrieve generataion result later"),
Expand Down Expand Up @@ -346,15 +327,16 @@ def as_form(cls, cn_img1: UploadFile = Form(File(None), description="Input image
style = s.strip()
style_selection_arr.append(style)

loras: List[Lora] = []
lora_config = [(l1, w1), (l2, w2), (l3, w3), (l4, w4), (l5, w5)]
for config in lora_config:
lora_model, lora_weight = config
if lora_model is not None and len(lora_model) > 0:
loras.append(Lora(model_name=lora_model, weight=lora_weight))
loras_model: List[Lora] = []
if loras is not None and len(loras) > 0:
try:
loras_model = LoraList.validate_json(loras)
except ValidationError as ve:
errs = ve.errors()
raise RequestValidationError(errors=[errs])

advanced_params_obj = None
if advanced_params != None and len(advanced_params) > 0:
if advanced_params is not None and len(advanced_params) > 0:
try:
advanced_params_obj = AdvancedParams.__pydantic_validator__.validate_json(advanced_params)
except ValidationError as ve:
Expand All @@ -365,7 +347,7 @@ def as_form(cls, cn_img1: UploadFile = Form(File(None), description="Input image
performance_selection=performance_selection, aspect_ratios_selection=aspect_ratios_selection,
image_number=image_number, image_seed=image_seed, sharpness=sharpness, guidance_scale=guidance_scale,
base_model_name=base_model_name, refiner_model_name=refiner_model_name, refiner_switch=refiner_switch,
loras=loras, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)
loras=loras_model, advanced_params=advanced_params_obj, require_base64=require_base64, async_process=async_process)


class GeneratedImageResult(BaseModel):
Expand Down
8 changes: 7 additions & 1 deletion fooocusapi/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
default_base_model_name = 'juggernautXL_version6Rundiffusion.safetensors'
default_refiner_model_name = 'None'
default_refiner_switch = 0.5
default_loras = [['sd_xl_offset_example-lora_1.0.safetensors', 0.1]]
default_lora_name = 'sd_xl_offset_example-lora_1.0.safetensors'
default_lora_weight = 0.1
default_cfg_scale = 4.0
Expand Down Expand Up @@ -60,6 +61,10 @@
]


def get_aspect_ratio_value(label: str) -> str:
return label.split(' ')[0].replace('*', '×')


class GenerationFinishReason(str, Enum):
success = 'SUCCESS'
queue_is_full = 'QUEUE_IS_FULL'
Expand Down Expand Up @@ -113,6 +118,7 @@ def __init__(self, prompt: str,
self.inpaint_input_image = inpaint_input_image
self.image_prompts = image_prompts
if advanced_params is None:
disable_preview = False
adm_scaler_positive = 1.5
adm_scaler_negative = 0.8
adm_scaler_end = 0.3
Expand All @@ -137,7 +143,7 @@ def __init__(self, prompt: str,
refiner_swap_method = 'joint'
freeu_enabled = False
freeu_b1, freeu_b2, freeu_s1, freeu_s2 = [None] * 4
self.advanced_params = [adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adaptive_cfg, sampler_name,
self.advanced_params = [disable_preview, adm_scaler_positive, adm_scaler_negative, adm_scaler_end, adaptive_cfg, sampler_name,
scheduler_name, generate_image_grid, overwrite_step, overwrite_switch, overwrite_width, overwrite_height,
overwrite_vary_strength, overwrite_upscale_strength,
mixing_image_prompt_and_vary_upscale, mixing_image_prompt_and_inpaint,
Expand Down
4 changes: 2 additions & 2 deletions fooocusapi/repositories_versions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os

fooocus_version = '2.1.806'
fooocus_version = '2.1.820'
fooocus_commit_hash = os.environ.get(
'FOOOCUS_COMMIT_HASH', "c9a5e729d91ba3772d421a5db7bf79497011e59f")
'FOOOCUS_COMMIT_HASH', "3b97e49dd814a43fc75a26b2495603e38b8b2f62")
2 changes: 1 addition & 1 deletion fooocusapi/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def yield_result(imgs, tasks):

for i, t in enumerate(tasks):
if abs(float(cfg_scale) - 1.0) < 1e-4:
progressbar(10, f'Skipped negative #{i + 1} ...')
# progressbar(10, f'Skipped negative #{i + 1} ...')
t['uc'] = pipeline.clone_cond(t['c'])
else:
progressbar(10, f'Encoding negative #{i + 1} ...')
Expand Down
11 changes: 5 additions & 6 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,17 +284,16 @@ def prepare_environments(args) -> bool:
import modules.config as config
import modules.flags as flags
import fooocusapi.parameters as parameters
parameters.default_inpaint_engine_version = flags.default_inpaint_engine_version
parameters.default_inpaint_engine_version = config.default_inpaint_engine_version
parameters.defualt_styles = config.default_styles
parameters.default_base_model_name = config.default_base_model_name
parameters.default_refiner_model_name = config.default_refiner_model_name
parameters.default_refiner_switch = config.default_refiner_switch
parameters.default_lora_name = config.default_lora_name
parameters.default_lora_weight = config.default_lora_weight
parameters.default_loras = config.default_loras
parameters.default_cfg_scale = config.default_cfg_scale
parameters.default_prompt_negative = config.default_prompt_negative
parameters.default_aspect_ratio = config.default_aspect_ratio.replace('*', '×')
parameters.available_aspect_ratios = [a.replace('*', '×') for a in config.available_aspect_ratios]
parameters.default_aspect_ratio = parameters.get_aspect_ratio_value(config.default_aspect_ratio)
parameters.available_aspect_ratios = [parameters.get_aspect_ratio_value(a) for a in config.available_aspect_ratios]

ini_cbh_args()

Expand Down Expand Up @@ -364,7 +363,7 @@ def preplaod_pipeline():
default='info', help="Log info for Uvicorn, default: info")
parser.add_argument("--sync-repo", default=None,
help="Sync dependent git repositories to local, 'skip' for skip sync action, 'only' for only do the sync action and not launch app")
parser.add_argument("--disable-private-log", default=False, action="store_true", help="Disable Fooocus private log, won't save output files (include generated image files)")
parser.add_argument("--disable-private-log", default=False, action="store_true", help="Disable Fooocus image log, won't save output files (include generated image files)")
parser.add_argument("--skip-pip", default=False, action="store_true", help="Skip automatic pip install when setup")
parser.add_argument("--preload-pipeline", default=False, action="store_true", help="Preload pipeline before start http server")
parser.add_argument("--queue-size", type=int, default=3, help="Working queue size, default: 3, generation requests exceeding working queue size will return failure")
Expand Down
Loading

0 comments on commit a1623c2

Please sign in to comment.