Get Fooocus Gradio API Working

The interesting AI image generation have probably been playing with for quite a while. I’ve been using it too, and one of the best tools I’ve found is Fooocus. It’s easy to use even for someone like me who has zero knowledge of large language models. However, when I wanted to batch process image-to-image generation using fooocus, I ran into a problem: the official version doesn’t plan to support batch processing, so we have to do it ourselves. In this post, we’ll complete the first step: getting the Fooocus API to work.

中文版

如果你可以读中文,那么看这里更方便。

Environment

I should preface this by saying I’m no python expert, so my approach might be rather simple and straight-forward. Bear with it, sorry, my abilities are limited.

Python

First, we need to prepare the python environment. Since the latest version of python has issues installing the Gradio client via pip, Python 3.11.5 was installed:

Next, Install the Gradio client without specifying a version:

Fooocus

Fooocus automatically checks for updates each time it runs. My current version is 2.3.0:

I’m running fooocus directly using run.bat. Note that after each update, or even when using different presets, the Fooocus interface might be changed. So if your current Fooocus version differs from mine at the time of writing, the code I provide might not work directly, and you’ll need to update it following the steps described below.

Getting the Fooocus API to Work

At the bottom of the Fooocus local website page, there’s a link called “Use via API”. It looks like explanation for how to use the API, right? Don’t get too excited - when you click it, you’ll find that the page content seems to be automatically generated and doesn’t contain useful information to get the API to work:

What’s worse, there’s no official documentation for this, otherwise this article wouldn’t be necessary. Although it isn’t that usable, the key details are there. First, we need to find the interface with the most parameters:

It should be mentioned that the fn_index and the number and order of parameters might vary depending on the Fooocus version and preset. Our first step is to copy this code into a Python file and get it running without errors.

Here’s the translation of the continued text:

I’ll say it again, the fn_index and the number and order of parameters may vary depending on the Fooocus version and preset. Our first step is to copy this code into a Python file and get it running without errors.

Readers who are familiar with Python, probably don’t need me to explain much, but for those who aren’t, let me explain more: The copied code won’t run directly; A few following issues would be encountered:

  1. "704×1408 <span style="color: grey;"> ∣ 1:2</span>" isn’t actually a standard string because there are quotes within quotes. A simple fix is to change it to "704×1408 <span style='color: grey;'> ∣ 1:2</span>". I haven’t verified if this works, but it at least stops throwing errors.

  2. The grey text in the image above is actually comment, but for some reason, they’re broken into multiple lines. We need to manually remove these line breaks.

  3. The random seed is actually a string format of a number. I simply filled it with "0".

  4. The image reference in the code is given as a URL (https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png). This link is valid, but in this article, I’ve left it empty.

After solving these four issues, executing this file with Python should not produce any errors. However, we’ll notice that the Fooocus application hasn’t actually started generating images. In other words, it’s possible that the Gradio client hasn’t sent the image-gen config to Fooocus yet, and has only recorded it locally.

So we need another API to make Fooocus to start working. This one is probably the interface we are looking for:

It looks like this API returns the completed image and preview, so it’s very likely to be the one we need. Let’s add the call to our Python file above:

from gradio_client import Client
client = Client("http://127.0.0.1:7865/")

result = client.predict(
  ...
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)

Running this file again, you’ll see Fooocus working, but the Gradio client will produce a long string of errors:

I could not figure out what these errors mean due to my limited relative knowledge, but the image has been generated. It’s in the Fooocus output directory:

It’s a very abstract image; I can’t even tell what it’s supposed to be. Strangely, even if we repeatedly modify the parameters that look like prompts, it doesn’t change significantly. However, I quickly realized that this is because the default values of the parameters are not actually Fooocus’s default values. So we need to go to the Fooocus interface and match the settings on the interface with the function parameters. This is a tedious process, but let’s summarize it briefly.

The function parameters correspond to the following types of settings:

  1. Textbox: String, usually for prompts
  2. Checkbox: Boolean, indicates yes or no
  3. Radio: String, represents the value of a single choice option
  4. Dropdown: String, similar to radio buttons
  5. Slider: Number, represents a value within a range
  6. Checkbox Group: List of strings, an obvious example is selecting multiple styles
  7. Image: String, the path or URL of an image

Basically, all parameters can be found corresponding to settings in the interface. We won’t go into the tedious process, but here are two sets of settings for version 2.3.0, with the corresponding parameter meanings written in the comment:

the default run config

from gradio_client import Client

client = Client("http://127.0.0.1:7865/")

# Textbox: string
# Checkbox: bool
# Radio: string
# Dropdown: string
# Slider: float | int
# Checkboxgroup: list[string]
# Image: filepath or URL to image

result = client.predict(
	False,	# 'Generate Image Grid for Each Batch' Checkbox
	"a girl sitting in chair",	# 'Prompt' Textbox
	"",	# 'Negative Prompt' Textbox
    # 'Selected Styles' Checkboxgroup
	["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp", "Fooocus Negative"],
	"Speed",	# 'Performance' Radio
	"704×1408 <span style='color: grey;'> ∣ 1:2</span>",	# 'Aspect Ratios' Radio
	1,		# 'Image Number' Slider [1,32]
	"png",	# 'Output Format' Radio
	"0",	# 'Seed' Textbox
    False,	# 'Read wildcards in order' Checkbox
	2,		# 'Image Sharpness' Slider [0.0,30.0]
	4,		#  'Guidance Scale' Slider [1.0,30.0]
	"juggernautXL_v8Rundiffusion.safetensors",	# 'Base Model (SDXL only)' Dropdown
	"None",	# 'Refiner (SDXL or SD 1.5)' Dropdown
	0.1,	# 'Refiner Switch At' Slider [0.1,1.0]
	True,	# 'LoRA 1 Enable' Checkbox
	"sd_xl_offset_example-lora_1.0.safetensors",	# 'LoRA 1' Dropdown
	0.1,	# 'LoRA 1 Weight' Slider [-2,2]
	True,	# 'LoRA 2 Enable' Checkbox
	"None",	# 'LoRA 2' Dropdown
	1,		# 'LoRA 2 Weight' Slider [-2,2]
	True,	# 'LoRA 3 Enable' Checkbox
	"None",	# 'LoRA 3' Dropdown
	1,		# 'LoRA 3 Weight' Slider [-2,2]
	True,	# 'LoRA 4 Enable' Checkbox
	"None",	# 'LoRA 4' Dropdown
	1,		# 'LoRA 4 Weight' Slider [-2,2]
	True,	# 'LoRA 5 Enable' Checkbox
	"None",	# 'LoRA 5' Dropdown component
	1,		# 'LoRA 5 Weight' Slider [-2,2]
	False,	#'Input Image' Checkbox
	"",		# 'parameter_91' Textbox? maybe: Upscale or Variation Prompt
	"Disabled",	# 'Upscale or Variation:' Radio
	"",			# 'Upscale or Variation' Image
	["Left"],	# 'Outpaint Direction' Checkboxgroup
	"",		# 'Inpaint or Outpaint' Image
	"",		# 'Inpaint Additional Prompt' Textbox
	"",		# 'Inpaint or Outpaint Mask Upload' Image
	True,	# 'Developer Debug Mode: Disable Preview' Checkbox
	True,	# 'Developer Debug Mode: Disable Intermediate Results' Checkbox
	True,	# 'Developer Debug Mode: Disable seed increment' Checkbox
	1.5,	# 'Developer Debug Mode: Positive ADM Guidance Scaler' Slider [0.1,3.0]
	0.8,	# 'Developer Debug Mode: Negative ADM Guidance Scaler' Slider [0.1,3.0]
	0.3,	# 'Developer Debug Mode: ADM Guidance End At Step' Slider [0.0,1.0]
	7,		# 'Developer Debug Mode: CFG Mimicking from TSNR' Slider [1.0,30.0]
	"dpmpp_2m_sde_gpu",	# 'Developer Debug Mode: Sampler' Dropdown
	"karras",	# 'Developer Debug Mode: Scheduler' Dropdown
	-1,	# 'Developer Debug Mode: Forced Overwrite of Sampling Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Refiner Switch Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Width' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Height' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Vary"' Slider [-1,1.0]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Upscale"' Slider [-1,1.0]
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Vary/Upscale' Checkbox
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Inpaint' Checkbox
	False,	# 'Developer Debug Mode: Debug Preprocessors' Checkbox
	False,	# 'Developer Debug Mode: Skip Preprocessors' Checkbox
	64,		# 'Developer Debug Mode: Canny Low Threshold' Slider [1,255]
	128,	# 'Developer Debug Mode: Canny High Threshold' Slider [1,255]
	"joint",	# 'Developer Debug Mode: Refiner swap method' Dropdown
	0.25,	# 'Developer Debug Mode: Softness of ControlNet' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: FreeU Enabled' Checkbox
	1.01,	# 'Developer Debug Mode: FreeU B1' Slider [0,2]
	1.02,	# 'Developer Debug Mode: FreeU B2' Slider [0,2]
	0.99,	# 'Developer Debug Mode: FreeU S1' Slider [0,4]
	0.95,	# 'Developer Debug Mode: FreeU S2' Slider [0,4]
	False,	# 'Developer Debug Mode: Debug Inpaint Preprocessing' Checkbox
	False,	# 'Developer Debug Mode: Disable initial latent in inpaint' Checkbox
	"v2.6",	# 'Developer Debug Mode: Inpaint Engine' Dropdown
	1,		# 'Developer Debug Mode: Inpaint Denoising Strength' Slider [0.0,1.0]
	0.618,	# 'Developer Debug Mode: Inpaint Respective Field' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: Enable Mask Upload' Checkbox
	False,	# 'Developer Debug Mode: Invert Mask' Checkbox
	0,		# 'Developer Debug Mode: Mask Erode or Dilate' Slider [-64,64]
	False,	# 'Developer Debug Mode: Save Metadata to Images' Checkbox
	"fooocus",	# 'Metadata Scheme' Radio
	"",				# 'Image Prompt Image 1' Image component
	0,				# 'Image Prompt Image 1 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 1 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 1 Type' Radio
	"",				# 'Image Prompt Image 2' Image component
	0,				# 'Image Prompt Image 2 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 2 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 2 Type' Radio
	"",				# 'Image Prompt Image 3' Image component
	0,				# 'Image Prompt Image 3 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 3 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 3 Type' Radio
	"",				# 'Image Prompt Image 4' Image component
	0,				# 'Image Prompt Image 4 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 4 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 4 Type' Radio
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)
# print(result)

run_anime config

from gradio_client import Client

client = Client("http://127.0.0.1:7865/")

# Textbox: string
# Checkbox: bool
# Radio: string
# Dropdown: string
# Slider: float | int
# Checkboxgroup: list[string]
# Image: filepath or URL to image

result = client.predict(
	False,	# 'Generate Image Grid for Each Batch' Checkbox
	"a girl sitting in chair",	# 'Prompt' Textbox
	"",	# 'Negative Prompt' Textbox
    # 'Selected Styles' Checkboxgroup
	["Fooocus V2", "Fooocus Semi Realistic", "Fooocus Masterpiece"],
	"Speed",	# 'Performance' Radio
	"704×1408 <span style='color: grey;'> ∣ 1:2</span>",	# 'Aspect Ratios' Radio
	1,		# 'Image Number' Slider [1,32]
	"png",	# 'Output Format' Radio
	"0",	# 'Seed' Textbox
    False,	# 'Read wildcards in order' Checkbox
	2,		# 'Image Sharpness' Slider [0.0,30.0]
	7,		#  'Guidance Scale' Slider [1.0,30.0]
	"animaPencilXL_v100.safetensors",	# 'Base Model (SDXL only)' Dropdown
	"None",	# 'Refiner (SDXL or SD 1.5)' Dropdown
	0.1,	# 'Refiner Switch At' Slider [0.1,1.0]
	True,	# 'LoRA 1 Enable' Checkbox
	"None",	# 'LoRA 1' Dropdown
	1,	# 'LoRA 1 Weight' Slider [-2,2]
	True,	# 'LoRA 2 Enable' Checkbox
	"None",	# 'LoRA 2' Dropdown
	1,		# 'LoRA 2 Weight' Slider [-2,2]
	True,	# 'LoRA 3 Enable' Checkbox
	"None",	# 'LoRA 3' Dropdown
	1,		# 'LoRA 3 Weight' Slider [-2,2]
	True,	# 'LoRA 4 Enable' Checkbox
	"None",	# 'LoRA 4' Dropdown
	1,		# 'LoRA 4 Weight' Slider [-2,2]
	True,	# 'LoRA 5 Enable' Checkbox
	"None",	# 'LoRA 5' Dropdown component
	1,		# 'LoRA 5 Weight' Slider [-2,2]
	False,	#'Input Image' Checkbox
	"",		# 'parameter_91' Textbox? maybe: Upscale or Variation Prompt
	"Disabled",	# 'Upscale or Variation:' Radio
	"",			# 'Upscale or Variation' Image
	["Left"],	# 'Outpaint Direction' Checkboxgroup
	"",		# 'Inpaint or Outpaint' Image
	"",		# 'Inpaint Additional Prompt' Textbox
	"",		# 'Inpaint or Outpaint Mask Upload' Image
	True,	# 'Developer Debug Mode: Disable Preview' Checkbox
	True,	# 'Developer Debug Mode: Disable Intermediate Results' Checkbox
	True,	# 'Developer Debug Mode: Disable seed increment' Checkbox
	1.5,	# 'Developer Debug Mode: Positive ADM Guidance Scaler' Slider [0.1,3.0]
	0.8,	# 'Developer Debug Mode: Negative ADM Guidance Scaler' Slider [0.1,3.0]
	0.3,	# 'Developer Debug Mode: ADM Guidance End At Step' Slider [0.0,1.0]
	7,		# 'Developer Debug Mode: CFG Mimicking from TSNR' Slider [1.0,30.0]
	"dpmpp_2m_sde_gpu",	# 'Developer Debug Mode: Sampler' Dropdown
	"karras",	# 'Developer Debug Mode: Scheduler' Dropdown
	-1,	# 'Developer Debug Mode: Forced Overwrite of Sampling Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Refiner Switch Step' Slider [-1,200]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Width' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Generating Height' Slider [-1,2048]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Vary"' Slider [-1,1.0]
	-1,	# 'Developer Debug Mode: Forced Overwrite of Denoising Strength of "Upscale"' Slider [-1,1.0]
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Vary/Upscale' Checkbox
	False,	# 'Developer Debug Mode: Mixing Image Prompt and Inpaint' Checkbox
	False,	# 'Developer Debug Mode: Debug Preprocessors' Checkbox
	False,	# 'Developer Debug Mode: Skip Preprocessors' Checkbox
	64,		# 'Developer Debug Mode: Canny Low Threshold' Slider [1,255]
	128,	# 'Developer Debug Mode: Canny High Threshold' Slider [1,255]
	"joint",	# 'Developer Debug Mode: Refiner swap method' Dropdown
	0.25,	# 'Developer Debug Mode: Softness of ControlNet' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: FreeU Enabled' Checkbox
	1.01,	# 'Developer Debug Mode: FreeU B1' Slider [0,2]
	1.02,	# 'Developer Debug Mode: FreeU B2' Slider [0,2]
	0.99,	# 'Developer Debug Mode: FreeU S1' Slider [0,4]
	0.95,	# 'Developer Debug Mode: FreeU S2' Slider [0,4]
	False,	# 'Developer Debug Mode: Debug Inpaint Preprocessing' Checkbox
	False,	# 'Developer Debug Mode: Disable initial latent in inpaint' Checkbox
	"v2.6",	# 'Developer Debug Mode: Inpaint Engine' Dropdown
	1,		# 'Developer Debug Mode: Inpaint Denoising Strength' Slider [0.0,1.0]
	0.618,	# 'Developer Debug Mode: Inpaint Respective Field' Slider [0.0,1.0]
	False,	# 'Developer Debug Mode: Enable Mask Upload' Checkbox
	False,	# 'Developer Debug Mode: Invert Mask' Checkbox
	0,		# 'Developer Debug Mode: Mask Erode or Dilate' Slider [-64,64]
	False,	# 'Developer Debug Mode: Save Metadata to Images' Checkbox
	"fooocus",	# 'Metadata Scheme' Radio
	"",				# 'Image Prompt Image 1' Image component
	0,				# 'Image Prompt Image 1 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 1 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 1 Type' Radio
	"",				# 'Image Prompt Image 2' Image component
	0,				# 'Image Prompt Image 2 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 2 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 2 Type' Radio
	"",				# 'Image Prompt Image 3' Image component
	0,				# 'Image Prompt Image 3 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 3 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 3 Type' Radio
	"",				# 'Image Prompt Image 4' Image component
	0,				# 'Image Prompt Image 4 Stop At' Slider [0.0-1.0]
	0,				# 'Image Prompt Image 4 Weight' Slider [0.0-2.0]
	"ImagePrompt",	# 'Image Prompt Image 4 Type' Radio
	fn_index=40
)
print(result)
result= client.predict(fn_index=41)
# print(result)

With the config above, we can now generate images using prompts.

Again: since the API is not stabilized, if the version changes, we’ll need to match the parameters with the interface one more time.

Summary

At this point, we’ve managed to command Fooocus to generate images using an API. It looks like we’re one step closer to our goal of batch image generation. Next, we’ll look at how to use the API to perform image-to-image operations.