Fooocus
Fooocus copied to clipboard
API very undocumented
I am trying to use the api by clicking "Use via API"
But the actual endpoints themself are barely documented? I wanna be able to just put in a prompt and be done with it..?
I am trying to do this:
import { client } from "@gradio/client";
import { createRequire } from "module";
const require = createRequire(import.meta.url);
global.EventSource = require('eventsource');
const app = await client("http://127.0.0.1:7865/");
const response_0 = await fetch("https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png");
const exampleImage = await response_0.blob();
const result = await app.predict(29, [
"realistic portrait photo of beautiful woman with blonde hair and her labrador dog, hair roots slightly faded, latina, influencer, light blue eyes, no makeup, instagram",
"unrealistic, saturated, high contrast, big nose, painting, drawing, sketch, cartoon, anime, manga, render, CG, 3d, watermark, signature, label",
["Fooocus V2", "Fooocus Photograph", "Fooocus Negative"],
"Speed",
"896x1152 <span style='color: grey;'> ∣ 7:9</span>",
1,
"8082836497533172128",
2,
3,
"realisticStockPhoto_v10.safetensors",
"None",
0.1,
"SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors",
0.25,
"None",
1,
"None",
1,
"None",
1,
false,
"Howdy!", // string in 'parameter_73' Textbox component
"Disabled", // string in 'Upscale or Variation:' Radio component
exampleImage, // blob in 'Drag above image to here' Image component
["Left"], // string[] (array of strings) in 'Outpaint Direction' Checkboxgroup component
exampleImage, // blob in 'Drag above image to here' Image component
"Howdy!", // string in 'Inpaint Additional Prompt' Textbox component
exampleImage, // blob in 'Image' Image component
0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component
0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component
"ImagePrompt", // string in 'Type' Radio component
exampleImage, // blob in 'Image' Image component
0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component
0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component
"ImagePrompt", // string in 'Type' Radio component
exampleImage, // blob in 'Image' Image component
0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component
0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component
"ImagePrompt", // string in 'Type' Radio component
exampleImage, // blob in 'Image' Image component
0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component
0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component
"ImagePrompt", // string in 'Type' Radio component
]);
console.log(result.data);
But it doesn't work.
I know this isn't the answer you're looking for but since the backend is basically comfyui you could probably use that instead. sending it to localhost:8188/prompt as the request
I know this isn't the answer you're looking for but since the backend is basically comfyui you could probably use that instead. sending it to localhost:8188/prompt as the request
How would the request look like?
ADDRESS = "127.0.0.1"
PORT = "8188"
def queue(prompt_workflow):
p = {"prompt": prompt_workflow}
data = json.dumps(p).encode("utf-8")
requests.post(f"http://{ADDRESS}:{PORT}/prompt", data=data)
Here's a snippet from one of my older projects, should probably work for your use-case also. The parameters in the function would be a variable of a json file that has the information for comfyui.
ADDRESS = "127.0.0.1" PORT = "8188" def queue(prompt_workflow): p = {"prompt": prompt_workflow} data = json.dumps(p).encode("utf-8") requests.post(f"http://{ADDRESS}:{PORT}/prompt", data=data)
Here's a snippet from one of my older projects, should probably work for your use-case also. The parameters in the function would be a variable of a json file that has the information for comfyui.
You sure the port is 8188 can't reach that port even in browser?
For me the main UI is at: http://127.0.0.1:7865/
Also, when doing post request for the main UI it returns:
{
"detail": "Not Found"
}
Well its for the comfy ui backend part, so the request would be sending to 127.0.0.1:8188/prompt dont forget the subdomain of "prompt". I'm not sure if fooocus handles backend the same way the API comfy does you're gonna have to do some experimenting. But for debugging purposes while foocus is running try see if you can send something to this url 127.0.0.1:7865/prompt (default) is accessible through the browser
Well its for the comfy ui backend part, so the request would be sending to 127.0.0.1:8188/prompt dont forget the subdomain of "prompt". I'm not sure if fooocus handles backend the same way the API comfy does you're gonna have to do some experimenting. But for debugging purposes while foocus is running try see if you can send something to this url 127.0.0.1:7865/prompt (default) is accessible through the browser
Yea that's when I get the json response
{"detail":"Not Found"}
Okay so it's most likely that you have to structure the file being sent to the back-end in a way that when its being parsed the "detail" parameter is being filled correctly
Okay so it's most likely that you have to structure the file being sent to the back-end in a way that when its being parsed the "detail" parameter is being filled correctly
Ok, how would I do that
Ah well, that's where documentation comes in. So basically we're at square one again.. Sorry I couldn't be of help
I am trying to use the api by clicking "Use via API"
But the actual endpoints themself are barely documented? I wanna be able to just put in a prompt and be done with it..?
I am trying to do this:
import { client } from "@gradio/client"; import { createRequire } from "module"; const require = createRequire(import.meta.url); global.EventSource = require('eventsource'); const app = await client("http://127.0.0.1:7865/"); const response_0 = await fetch("https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"); const exampleImage = await response_0.blob(); const result = await app.predict(29, [ "realistic portrait photo of beautiful woman with blonde hair and her labrador dog, hair roots slightly faded, latina, influencer, light blue eyes, no makeup, instagram", "unrealistic, saturated, high contrast, big nose, painting, drawing, sketch, cartoon, anime, manga, render, CG, 3d, watermark, signature, label", ["Fooocus V2", "Fooocus Photograph", "Fooocus Negative"], "Speed", "896x1152 <span style='color: grey;'> ∣ 7:9</span>", 1, "8082836497533172128", 2, 3, "realisticStockPhoto_v10.safetensors", "None", 0.1, "SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors", 0.25, "None", 1, "None", 1, "None", 1, false, "Howdy!", // string in 'parameter_73' Textbox component "Disabled", // string in 'Upscale or Variation:' Radio component exampleImage, // blob in 'Drag above image to here' Image component ["Left"], // string[] (array of strings) in 'Outpaint Direction' Checkboxgroup component exampleImage, // blob in 'Drag above image to here' Image component "Howdy!", // string in 'Inpaint Additional Prompt' Textbox component exampleImage, // blob in 'Image' Image component 0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component 0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component "ImagePrompt", // string in 'Type' Radio component exampleImage, // blob in 'Image' Image component 0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component 0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component "ImagePrompt", // string in 'Type' Radio component exampleImage, // blob in 'Image' Image component 0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component 0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component "ImagePrompt", // string in 'Type' Radio component exampleImage, // blob in 'Image' Image component 0, // number (numeric value between 0.0 and 1.0) in 'Stop At' Slider component 0, // number (numeric value between 0.0 and 2.0) in 'Weight' Slider component "ImagePrompt", // string in 'Type' Radio component ]); console.log(result.data);
But it doesn't work.
- Fooocus didn't receive enough input values (needed: 45, got: 43). Add:
"None",
1,
before false
- try "896×1152" instead of "896x1152 ∣ 7:9", gradio use '×' spilt the string. 😂
can anyone paste working complete code ?
from gradio_client import Client
client = Client("http://127.0.0.1:7865/", serialize=False)
result = client.predict(
"Howdy!", # str in 'parameter_10' Textbox component
"Howdy!", # str in 'Negative Prompt' Textbox component
["Fooocus V2"], # List[str] in 'Selected Styles' Checkboxgroup component
"Speed", # str in 'Performance' Radio component
"1152×896 <span style='color: grey;'> | 1:2</span>", # str in 'Aspect Ratios' Radio component
1, # int | float (numeric value between 1 and 32)in 'Image Number' Slider component
"123", # str in 'Seed' Textbox component
0, # int | float (numeric value between 0.0 and 30.0)in 'Image Sharpness' Slider component
1, # int | float (numeric value between 1.0 and 30.0)in 'Guidance Scale' Slider component
"juggernautXL_version6Rundiffusion.safetensors", # str (Option from: ['juggernautXL_version6Rundiffusion.safetensors', 'realisticStockPhoto_v10.safetensors', 'bluePencilXL_v050.safetensors', 'DreamShaper_8_pruned.safetensors'])in 'Base Model (SDXL only)' Dropdown component
"None", # str (Option from: ['None', 'juggernautXL_version6Rundiffusion.safetensors', 'realisticStockPhoto_v10.safetensors', 'bluePencilXL_v050.safetensors', 'DreamShaper_8_pruned.safetensors'])in 'Refiner (SDXL or SD 1.5)' Dropdown component
0.1, # int | float (numeric value between 0.1 and 1.0)in 'Refiner Switch At' Slider component
"None", # str (Option from: ['None', 'sd_xl_offset_example-lora_1.0.safetensors', 'SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors', 'sdxl_lcm_lora.safetensors'])in 'LoRA 1' Dropdown component
-2, # int | float (numeric value between -2 and 2)in 'Weight' Slider component
"None", # str (Option from: ['None', 'sd_xl_offset_example-lora_1.0.safetensors', 'SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors', 'sdxl_lcm_lora.safetensors'])in 'LoRA 2' Dropdown component
-2, # int | float (numeric value between -2 and 2)in 'Weight' Slider component
"None", # str (Option from: ['None', 'sd_xl_offset_example-lora_1.0.safetensors', 'SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors', 'sdxl_lcm_lora.safetensors'])in 'LoRA 3' Dropdown component
-2, # int | float (numeric value between -2 and 2)in 'Weight' Slider component
"None", # str (Option from: ['None', 'sd_xl_offset_example-lora_1.0.safetensors', 'SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors', 'sdxl_lcm_lora.safetensors'])in 'LoRA 4' Dropdown component
-2, # int | float (numeric value between -2 and 2)in 'Weight' Slider component
"None", # str (Option from: ['None', 'sd_xl_offset_example-lora_1.0.safetensors', 'SDXL_FILM_PHOTOGRAPHY_STYLE_BetaV0.4.safetensors', 'sdxl_lcm_lora.safetensors'])in 'LoRA 5' Dropdown component
-2, # int | float (numeric value between -2 and 2)in 'Weight' Slider component
True, # bool in 'Input Image' Checkbox component
"Howdy!", # str in 'parameter_73' Textbox component
"Disabled", # str in 'Upscale or Variation:' Radio component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Drag above image to here' Image component
["Left"], # List[str] in 'Outpaint Direction' Checkboxgroup component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Drag above image to here' Image component
"Howdy!", # str in 'Inpaint Additional Prompt' Textbox component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
0, # int | float (numeric value between 0.0 and 1.0)in 'Stop At' Slider component
0, # int | float (numeric value between 0.0 and 2.0)in 'Weight' Slider component
"ImagePrompt", # str in 'Type' Radio component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
0, # int | float (numeric value between 0.0 and 1.0)in 'Stop At' Slider component
0, # int | float (numeric value between 0.0 and 2.0)in 'Weight' Slider component
"ImagePrompt", # str in 'Type' Radio component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
0, # int | float (numeric value between 0.0 and 1.0)in 'Stop At' Slider component
0, # int | float (numeric value between 0.0 and 2.0)in 'Weight' Slider component
"ImagePrompt", # str in 'Type' Radio component
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
0, # int | float (numeric value between 0.0 and 1.0)in 'Stop At' Slider component
0, # int | float (numeric value between 0.0 and 2.0)in 'Weight' Slider component
"ImagePrompt", # str in 'Type' Radio component
fn_index=29
)
print(result)
What kind of image is this? "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
Cant I just say: False, # bool in 'Input Image' Checkbox component for a simplified example.
Do you also have a more simplified example, please?
What kind of image is this? "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==", # str (filepath or URL to image)in 'Image' Image component
Cant I just say: False, # bool in 'Input Image' Checkbox component for a simplified example.
Do you also have a more simplified example, please?
Base64 Image encoded (google it)
I still do not get it. Shouldnt it be something like image.jg instead of a weird long number?
This is how far I've got
- Open F12 > network panel in a browser
- Use whatever function you need in fooocus
- In the network panel check the last 2 join messages and right click on the messages sent to fooocus (green indicator) 4.After right click Copy the message and use it later in python
eg the 2nd last message is
{"data":[null,false,"__art___","",["Fooocus V2","Fooocus Enhance","Fooocus Sharp"],"Speed","1152×896 <span style=\"color: grey;\"> ∣ 9:7</span>",1,"png","2887978505541915116",false,2,4,"juggernautXL_v8Rundiffusion.safetensors","None",0.5,true,"sd_xl_offset_example-lora_1.0.safetensors",0.1,true,"None",1,true,"None",1,true,"None",1,true,"None",1,false,"uov","Disabled",null,[],null,"",null,false,false,false,1.5,0.8,0.3,7,"dpmpp_2m_sde_gpu","karras",-1,-1,-1,-1,-1,-1,false,false,false,false,64,128,"joint",0.25,false,1.01,1.02,0.99,0.95,false,false,"v2.6",1,0.618,false,false,0,true,"fooocus",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt"],"event_data":null,"fn_index":40,"session_hash":"cb6b2mjcea4"}
then the very last message is
{"data":[null],"event_data":null,"fn_index":41,"session_hash":"cb6b2mjcea4"}
somehow both are needed then invoke in python as
def convert_msg_to_api_call(msg={}, client=None):
if 'data' in msg:
if msg['data'][0] == None:
del msg['data'][0]
result = client.predict(
fn_index=msg['fn_index'],
*msg['data'],
)
return result
from gradio_client import Client
client = Client("http://localhost:7865/")
null = None
false = False
true = True
# the next line contains the 2nd last message copied from F12
msg = {"data":[null,false,"__fox___","",["Fooocus V2","Fooocus Enhance","Fooocus Sharp"],"Speed","1152×896 <span style=\"color: grey;\"> ∣ 9:7</span>",2,"png","6453127819374729619",false,2,4,"juggernautXL_v8Rundiffusion.safetensors","None",0.5,true,"sd_xl_offset_example-lora_1.0.safetensors",0.1,true,"None",1,true,"None",1,true,"None",1,true,"None",1,false,"uov","Disabled",null,[],null,"",null,false,false,false,1.5,0.8,0.3,7,"dpmpp_2m_sde_gpu","karras",-1,-1,-1,-1,-1,-1,false,false,false,false,64,128,"joint",0.25,false,1.01,1.02,0.99,0.95,false,false,"v2.6",1,0.618,false,false,0,true,"fooocus",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt",null,0.5,0.6,"ImagePrompt"],"event_data":null,"fn_index":40,"session_hash":"cb6b2mjcea4"}
r1= convert_msg_to_api_call(msg=msg, client=client)
print(r1)
#the next line contains the last message from network panel
msg = {"data":[null],"event_data":null,"fn_index":41,"session_hash":"cb6b2mjcea4"}
r2= convert_msg_to_api_call(msg=msg, client=client)
I still get an error after the 2nd invocation but the images are created in the output folder
(check your fooocus logs)
This is still accurate I would assume? I'm considering building an iOS native app that could hit the API endpoints of Fooocus, with some nice improvements over the mobile browser interface (persistent sessions for one).
But if the API's still have low documentation that may be a lot more effort than just building a SwiftUI app.