Skip to content

Commit

Permalink
Add job_step_preview field to Query Job api
Browse files Browse the repository at this point in the history
  • Loading branch information
konieshadow committed Nov 15, 2023
1 parent 0a1c4e7 commit 8aec8db
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 56 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ Alternative api for 'Image Prompt' tab of Fooocus Gradio interface.
Query async generation request results, return job progress and generation results.

You can get preview image of generation steps at current time by this api.

#### Query Job Queue Info
> GET /v1/generation/job-queue
Expand Down
48 changes: 37 additions & 11 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -738,14 +738,16 @@
"type": "string"
},
"type": "array",
"title": "Model Filenames"
"title": "Model Filenames",
"description": "All available model filenames"
},
"lora_filenames": {
"items": {
"type": "string"
},
"type": "array",
"title": "Lora Filenames"
"title": "Lora Filenames",
"description": "All available lora filenames"
}
},
"type": "object",
Expand All @@ -759,17 +761,29 @@
"properties": {
"job_id": {
"type": "integer",
"title": "Job Id"
"title": "Job Id",
"description": "Job ID"
},
"job_type": {
"$ref": "#/components/schemas/TaskType"
"allOf": [
{
"$ref": "#/components/schemas/TaskType"
}
],
"description": "Job type"
},
"job_stage": {
"$ref": "#/components/schemas/AsyncJobStage"
"allOf": [
{
"$ref": "#/components/schemas/AsyncJobStage"
}
],
"description": "Job running stage"
},
"job_progess": {
"type": "integer",
"title": "Job Progess"
"title": "Job Progess",
"description": "Job running progress, 100 is for finished."
},
"job_status": {
"anyOf": [
Expand All @@ -780,7 +794,20 @@
"type": "null"
}
],
"title": "Job Status"
"title": "Job Status",
"description": "Job status in text"
},
"job_step_preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Job Step Preview",
"description": "Preview result in each generation step, as base64 image"
},
"job_result": {
"anyOf": [
Expand All @@ -794,17 +821,16 @@
"type": "null"
}
],
"title": "Job Result"
"title": "Job Result",
"description": "Job generation result"
}
},
"type": "object",
"required": [
"job_id",
"job_type",
"job_stage",
"job_progess",
"job_status",
"job_result"
"job_progess"
],
"title": "AsyncJobResponse"
},
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.12'
version = '0.3.13'
38 changes: 3 additions & 35 deletions fooocusapi/api_utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import base64
import io
from io import BytesIO
from typing import List

import numpy as np
from fastapi import Response, UploadFile
from PIL import Image
from fastapi import Response
from fooocusapi.file_utils import get_file_serve_url, output_file_to_base64img, output_file_to_bytesimg
from fooocusapi.img_utils import read_input_image
from fooocusapi.models import AsyncJobResponse, AsyncJobStage, GeneratedImageResult, GenerationFinishReason, ImgInpaintOrOutpaintRequest, ImgPromptRequest, ImgUpscaleOrVaryRequest, Text2ImgRequest
from fooocusapi.parameters import ImageGenerationParams, ImageGenerationResult, available_aspect_ratios, default_aspect_ratio, default_inpaint_engine_version, default_sampler, default_scheduler, default_base_model_name, default_refiner_model_name
from fooocusapi.task_queue import QueueTask
Expand All @@ -15,36 +12,6 @@
from modules.sdxl_styles import legal_style_names


def narray_to_base64img(narray: np.ndarray) -> str:
if narray is None:
return None

img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
base64_str = base64.b64encode(byte_data)
return base64_str


def narray_to_bytesimg(narray) -> bytes:
if narray is None:
return None

img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
return byte_data


def read_input_image(input_image: UploadFile) -> np.ndarray:
input_image_bytes = input_image.file.read()
pil_image = Image.open(io.BytesIO(input_image_bytes))
image = np.array(pil_image)
return image


def req_to_params(req: Text2ImgRequest) -> ImageGenerationParams:
if req.base_model_name is not None:
if req.base_model_name not in config.model_filenames:
Expand Down Expand Up @@ -181,6 +148,7 @@ def generation_output(results: QueueTask | List[ImageGenerationResult], streamin
job_stage=job_stage,
job_progess=task.finish_progess,
job_status=task.task_status,
job_step_preview=task.task_step_preview,
job_result=job_result)

if streaming_output:
Expand Down
35 changes: 35 additions & 0 deletions fooocusapi/img_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import base64
from io import BytesIO
import numpy as np
from fastapi import Response, UploadFile
from PIL import Image


def narray_to_base64img(narray: np.ndarray) -> str:
if narray is None:
return None

img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
base64_str = base64.b64encode(byte_data)
return base64_str


def narray_to_bytesimg(narray) -> bytes:
if narray is None:
return None

img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
return byte_data


def read_input_image(input_image: UploadFile) -> np.ndarray:
input_image_bytes = input_image.file.read()
pil_image = Image.open(BytesIO(input_image_bytes))
image = np.array(pil_image)
return image
17 changes: 9 additions & 8 deletions fooocusapi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,13 @@ class AsyncJobStage(str, Enum):


class AsyncJobResponse(BaseModel):
job_id: int
job_type: TaskType
job_stage: AsyncJobStage
job_progess: int
job_status: str | None
job_result: List[GeneratedImageResult] | None
job_id: int = Field(description="Job ID")
job_type: TaskType = Field(description="Job type")
job_stage: AsyncJobStage = Field(description="Job running stage")
job_progess: int = Field(description="Job running progress, 100 is for finished.")
job_status: str | None = Field(None, description="Job running status in text")
job_step_preview: str | None = Field(None, description="Preview result in each generation step, as base64 image")
job_result: List[GeneratedImageResult] | None = Field(None, description="Job generation result")


class JobQueueInfo(BaseModel):
Expand All @@ -399,8 +400,8 @@ class JobQueueInfo(BaseModel):


class AllModelNamesResponse(BaseModel):
model_filenames: List[str]
lora_filenames: List[str]
model_filenames: List[str] = Field(description="All available model filenames")
lora_filenames: List[str] = Field(description="All available lora filenames")

model_config = ConfigDict(
protected_namespaces=('protect_me_', 'also_protect_')
Expand Down
12 changes: 11 additions & 1 deletion fooocusapi/task_queue.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from enum import Enum
import time
import numpy as np
from typing import List, Tuple

from fooocusapi.img_utils import narray_to_base64img


class TaskType(str, Enum):
text_2_img = 'Text to Image'
Expand All @@ -17,6 +20,7 @@ class QueueTask(object):
finish_millis: int = 0
finish_with_error: bool = False
task_status: str | None = None
task_step_preview: str | None = None
task_result: any = None
error_message: str | None = None

Expand All @@ -32,6 +36,9 @@ def set_progress(self, progress: int, status: str | None):
self.finish_progess = progress
self.task_status = status

def set_step_preview(self, task_step_preview: str | None):
self.task_step_preview = task_step_preview

def set_result(self, task_result: any, finish_with_error: bool, error_message: str | None = None):
if not finish_with_error:
self.finish_progess = 100
Expand Down Expand Up @@ -116,4 +123,7 @@ def append(self, args: List[any]):
if args[0] == 'preview' and isinstance(args[1], Tuple) and len(args[1]) >= 2:
number = args[1][0]
text = args[1][1]
self.task.set_progress(number, text)
self.task.set_progress(number, text)
if len(args[1]) >= 3 and isinstance(args[1][2], np.ndarray):
base64_preview_img = narray_to_base64img(args[1][2])
self.task.set_step_preview(base64_preview_img)

0 comments on commit 8aec8db

Please sign in to comment.