ComfyUI icon indicating copy to clipboard operation
ComfyUI copied to clipboard

[Feature request]: Programmatic use and API

Open ebceu4 opened this issue 1 year ago • 7 comments

I would like to request a feature that allows for the saving and loading of pipelines as JSON. This will enable users to create complex and advanced pipelines using the graph/nodes/flowchart based interface and then leverage the visually built pipelines programmatically or via API through a runner

ebceu4 avatar Mar 14 '23 02:03 ebceu4

See: https://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/basic_api_example.py

comfyanonymous avatar Mar 14 '23 02:03 comfyanonymous

Is there a guide on how the API works

IcelandicIcecream avatar Mar 15 '23 08:03 IcelandicIcecream

I also want to use workflow struct my special API,because I can't process batch images now.It will make the workflow more powerful.

lunaticer avatar Mar 19 '23 09:03 lunaticer

That's a good question, and I'd like to implement this functionality by calling the ComfyUI workflow directly from an external application, which eliminates the hassle of using the stable diffusion api.

icelandno1 avatar Jul 12 '23 13:07 icelandno1

I would also love to have an API. If possible also an OpenApi/Swagger definition would be awesome, so you could generate a client in different languages.

Razorbob avatar Jul 12 '23 18:07 Razorbob

+1

misza222 avatar Jul 14 '23 12:07 misza222

if you update to the latest you can "enable dev mode options" in the settings (gear beside the "Queue Size: ") this will enable a button on the UI to save workflows in api format.

You can then use these api jsons in these script examples: https://github.com/comfyanonymous/ComfyUI/tree/master/script_examples

comfyanonymous avatar Jul 15 '23 04:07 comfyanonymous

Hi, Thanks for adding the "API Format" option it is super helpful !

tomermesser avatar Aug 09 '23 08:08 tomermesser

I took a look at how the websocket service works, and created a simple class to use the already existing API. It facilitated my workflow a lot and maybe some of you can find it useful.

https://github.com/fidecastro/ComfyUI-serverless/

fidecastro avatar Aug 14 '23 08:08 fidecastro

I'm Stucking in here! https://github.com/comfyanonymous/ComfyUI/issues/1083#issuecomment-1699082974

Can you give me a tought?

p0mad avatar Aug 30 '23 13:08 p0mad

/I could not find an api documentation, so here's what I gleamed from the source code and everyone's comments :

GET

/history Last queued renders, including all nodes used in the prompt, and all output images.

/history/{UID} A specific history entry by uid. When calling prompt, the result will contain this uid.

/view?filename={FILENAME} Access the images from history via this.

/extensions paths to the javascript files for each extension.

/embeddings Presumably a list of all embeddings. These aren't available as inputs in any Node, unlike models (see OTHERS).

/object_info List of all types of nodes that are available. (Not the actual node instances, just the node types.)
This exposes a lot of important enumerable values in the form of input types.

/queue What's happening or queued at the moment. Surprisingly comprehensive.

/system_stats os, python version, torch devices (like gpus) and vram used.

POST

/prompt https://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/basic_api_example.py

The json data payload must be stored under the name "prompt". In JS, it would look like so :

const res = await axios.post('http://127.0.0.1:8188/prompt',{
	prompt:json_data_object	
});

You can get an example of the json_data_object by enabling Dev Mode in the ComfyUI settings, and then clicking the newly added export button.

/interrupt Interrupts the execution of the running prompt and starts the next one in the queue.

/queue /history In POST, these routes should accept the payloads clear:true and delete:number[] .

/upload/image /upload/mask This uploads an image and returns a short path under which the image can be referred to in comfyui. Takes payload 'image' in body.

SYNTAX

The following typescript definitions are incomplete and may be wrong entirely.
Please leave a comment if you spot errors or if you have improvements.

// This is what apis like "prompt" expect.
export type JSON_ComfyGraph = {
    [uid: string|number]: JSON_ComfyNode
}

// A node instance.
export type JSON_ComfyNode = {
    // The type of the node as found in 'GET /object_info' by key
    class_type: string;
    // All incoming connections
    inputs: {
        [input_name: string]: JSON_ValueRef;
    }
}

// Any value that can is passed into a ComfyNode
// This can be either an atomic value, like a string or a number, or a reference to another node's output.
export type JSON_ValueRef = [target_node_uid: string, output_socket_index: number] | string | number | boolean


// All possible input/output types. This type is incomplete.
// string[] represents an enum dropdown.
export type JSON_ComfyPrimitive = "MODEL" | "CLIP" | "STYLE_MODEL" | "CLIP_VISION_OUTPUT" | "CONTROL_NET" | "UPSCALE_MODEL" | "CLIP_VISION" | "VAE" | "LATENT" | "INT" | "FLOAT" | "IMAGE" | "TEXT" | "CONDITIONING" | "EXTRA_PNGINFO" | "MASK" | string[];

// Some types accept options like restrictions or special ui operations. So they are wrapped in an array of type + options
export type JSON_ComfyPrimitiveDeclaration = 
// An empty array means the name of the output/input is the same as the type. Case insensitive. Eg an output named 'latent' defaults to type "LATENT".
[] 
| [JSON_ComfyPrimitive]
| [
    "INT" | "FLOAT",
    {
        default?: number,
        min?: number,
        max?: number,
        step?: number,
        round?: number
    }
]
| [
    "TEXT"|string[],
    {
        multiline?:boolean,
        default?:string
    }
]
| [
    "IMAGE"|string[],
    {
        image_upload?:boolean,
        default?:string
    }
]

// This is what apis like "object_info" return.
export type JSON_ComfyNodeTypes = {
    [key: string]: {
        // This is what creates the submenus in the context menu.
        category: string,
        // Verbal description of the node for use in the ui.
        description: string,
        // The name which should be displayed in the editor.
        display_name: string,
        input: {
            // List of all input types
            required: {
                [name: string]: JSON_ComfyPrimitiveDeclaration
            },
            hidden: {
                [name: string]: JSON_ComfyPrimitiveDeclaration
            }
        },
        // Unique name
        name: string,
        // Unique names of all the outputs
        output: string[],
        // Is the output a list?
        output_is_list: boolean[],
        // Labels of all the outputs
        output_name: string[],
        // Is this node an output? Useful for evaluating if a graph is valid.
        output_node: boolean;
    }
}

// This is what apis like "history" return.
export type JSON_History = {
    [uid: string]: JSON_HistoryEntry;
}

export type JSON_HistoryEntry = {
    prompt: [id_maybe: number, uid:string, list_of_used_nodes:JSON_ComfyGraph, no_idea:any, no_idea2:[string]];
    outputs: {
        images: JSON_ImageReference[];
    }[];
}

export type JSON_ImageReference = {
    filename: string;
    subfolder: string;
    type: "output";
}

OTHER

You can retrieve the list of all available models from the CheckpointLoader object. GET /object_info Then CheckpointLoader->input->required->ckpt_name->0 .

kiriri avatar Sep 26 '23 15:09 kiriri

I took a look at how the websocket service works, and created a simple class to use the already existing API. It facilitated my workflow a lot and maybe some of you can find it useful.

https://github.com/fidecastro/ComfyUI-serverless/

It's a great work

darkcurrent avatar Oct 19 '23 12:10 darkcurrent

Could anyone give me any functional example of the use of the API? What is complete and that has an example embedded as those of the Save in Api Format? I can't run the Basic Example:/

zephirusgit avatar Dec 04 '23 09:12 zephirusgit

si actualizas a lo último puedes "solar las opciones de modo dev" en la configuración (envejecer junto al "Queue Size: ") esto permitirá un botón en la interfaz de usuario para guardar flujos de trabajo en formato api.

A continuación puede utilizar estos api jsons en estos ejemplos de script: https://github.com/comfyanonymous/ComfyU/tree/master/script-examples

Could anyone give me any functional example of the use of the API? What is complete and that has an example embedded as those of the Save in Api Format? I can't run the Basic Example:/

zephirusgit avatar Dec 04 '23 09:12 zephirusgit

For sample usage you may check this small project I've created. https://github.com/rsandagon/comfyui-batch-image-generation

For websocket handling, check here

For API endpoint, check here

You need to have the same client_id for both API and websocket to get proper websocket updates on the workflow.

rsandagon avatar Jan 07 '24 12:01 rsandagon

you can also look at https://github.com/rvion/CushyStudio

It is probably the biggest custom frontend around.

I maintain the most comprehensive set of typings possible, along a higher level type-safe typescript ComfyUI SDK to build workflows with all possible goodies you can imagine.

CushyStudio also generates a whole type-safe SDK for your specific ComfyUI setup, with every custom node, and even model you have installed

  • https://gist.github.com/rvion/f68635427c7d5e9b0846121e4d9e87a7#file-global-d-ts-L6789
  • https://gist.github.com/rvion/f68635427c7d5e9b0846121e4d9e87a7#file-global-d-ts-L5324
  • https://gist.github.com/rvion/f68635427c7d5e9b0846121e4d9e87a7#file-global-d-ts-L5190

writing workflows and running them is super smooth.

Cushy also feature a scripting engine with hot reload, and a custom gradio-like framework (simpler and type-safe) to build custom apps with UI on top of the ComfyUI SDK.

Only reason it's not popular yet is that it's not released yet (so no one knows about it), and that it probably has a few quirks here and there. but maybe you'll have fun trying it out. feel free to reach out on discord if you need help:)

rvion avatar Jan 07 '24 19:01 rvion

Cushy also includes higher level API / typings for comfy manager, and host management too, (and other non-comfy things that works well with ComfyUI, like a full programmatic image building API to build masks, etc)

rvion avatar Jan 07 '24 19:01 rvion

Finally I found a page, which explained how to use it in Python and it worked for me https://medium.com/@yushantripleseven/comfyui-websockets-api-part-1-618175802d5a

https://medium.com/@yushantripleseven/comfyui-using-the-api-part-2-daac17fd2727

zephirusgit avatar Jan 09 '24 04:01 zephirusgit

/I could not find an api documentation, so here's what I gleamed from the source code and everyone's comments :

GET

/history Last queued renders, including all nodes used in the prompt, and all output images.

/history/{UID} A specific history entry by uid. When calling prompt, the result will contain this uid.

/view?filename={FILENAME} Access the images from history via this.

/extensions paths to the javascript files for each extension.

/embeddings Presumably a list of all embeddings. These aren't available as inputs in any Node, unlike models (see OTHERS).

/object_info List of all types of nodes that are available. (Not the actual node instances, just the node types.) This exposes a lot of important enumerable values in the form of input types.

/queue What's happening or queued at the moment. Surprisingly comprehensive.

/system_stats os, python version, torch devices (like gpus) and vram used.

POST

/prompt https://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/basic_api_example.py

The json data payload must be stored under the name "prompt". In JS, it would look like so :

const res = await axios.post('http://127.0.0.1:8188/prompt',{
	prompt:json_data_object	
});

You can get an example of the json_data_object by enabling Dev Mode in the ComfyUI settings, and then clicking the newly added export button.

/interrupt Interrupts the execution of the running prompt and starts the next one in the queue.

/queue /history In POST, these routes should accept the payloads clear:true and delete:number[] .

/upload/image /upload/mask This uploads an image and returns a short path under which the image can be referred to in comfyui. Takes payload 'image' in body.

SYNTAX

The following typescript definitions are incomplete and may be wrong entirely. Please leave a comment if you spot errors or if you have improvements.

// This is what apis like "prompt" expect.
export type JSON_ComfyGraph = {
    [uid: string|number]: JSON_ComfyNode
}

// A node instance.
export type JSON_ComfyNode = {
    // The type of the node as found in 'GET /object_info' by key
    class_type: string;
    // All incoming connections
    inputs: {
        [input_name: string]: JSON_ValueRef;
    }
}

// Any value that can is passed into a ComfyNode
// This can be either an atomic value, like a string or a number, or a reference to another node's output.
export type JSON_ValueRef = [target_node_uid: string, output_socket_index: number] | string | number | boolean


// All possible input/output types. This type is incomplete.
// string[] represents an enum dropdown.
export type JSON_ComfyPrimitive = "MODEL" | "CLIP" | "STYLE_MODEL" | "CLIP_VISION_OUTPUT" | "CONTROL_NET" | "UPSCALE_MODEL" | "CLIP_VISION" | "VAE" | "LATENT" | "INT" | "FLOAT" | "IMAGE" | "TEXT" | "CONDITIONING" | "EXTRA_PNGINFO" | "MASK" | string[];

// Some types accept options like restrictions or special ui operations. So they are wrapped in an array of type + options
export type JSON_ComfyPrimitiveDeclaration = 
// An empty array means the name of the output/input is the same as the type. Case insensitive. Eg an output named 'latent' defaults to type "LATENT".
[] 
| [JSON_ComfyPrimitive]
| [
    "INT" | "FLOAT",
    {
        default?: number,
        min?: number,
        max?: number,
        step?: number,
        round?: number
    }
]
| [
    "TEXT"|string[],
    {
        multiline?:boolean,
        default?:string
    }
]
| [
    "IMAGE"|string[],
    {
        image_upload?:boolean,
        default?:string
    }
]

// This is what apis like "object_info" return.
export type JSON_ComfyNodeTypes = {
    [key: string]: {
        // This is what creates the submenus in the context menu.
        category: string,
        // Verbal description of the node for use in the ui.
        description: string,
        // The name which should be displayed in the editor.
        display_name: string,
        input: {
            // List of all input types
            required: {
                [name: string]: JSON_ComfyPrimitiveDeclaration
            },
            hidden: {
                [name: string]: JSON_ComfyPrimitiveDeclaration
            }
        },
        // Unique name
        name: string,
        // Unique names of all the outputs
        output: string[],
        // Is the output a list?
        output_is_list: boolean[],
        // Labels of all the outputs
        output_name: string[],
        // Is this node an output? Useful for evaluating if a graph is valid.
        output_node: boolean;
    }
}

// This is what apis like "history" return.
export type JSON_History = {
    [uid: string]: JSON_HistoryEntry;
}

export type JSON_HistoryEntry = {
    prompt: [id_maybe: number, uid:string, list_of_used_nodes:JSON_ComfyGraph, no_idea:any, no_idea2:[string]];
    outputs: {
        images: JSON_ImageReference[];
    }[];
}

export type JSON_ImageReference = {
    filename: string;
    subfolder: string;
    type: "output";
}

OTHER

You can retrieve the list of all available models from the CheckpointLoader object. GET /object_info Then CheckpointLoader->input->required->ckpt_name->0 .

Thanks, this should be added to wiki)

hippogamesunity avatar Jan 16 '24 20:01 hippogamesunity

Is there any way to clear the output folder with API?

hippogamesunity avatar Jan 16 '24 20:01 hippogamesunity

@comfyanonymous is there a way to turn off nodes other than setting strength it doesn't seem like the api version of a workflow allows mode modification

CrossPr0duct avatar Jan 30 '24 04:01 CrossPr0duct

@comfyanonymous is there a way to turn off nodes other than setting strength it doesn't seem like the api version of a workflow allows mode modification

You can create xml workflows on fly and pass them to /promp with POST. Also I've found a 3rd article with API description based on code analysis.

image

hippogamesunity avatar Jan 30 '24 06:01 hippogamesunity

Closing after a week of inactivity.

robinjhuang avatar Jul 01 '24 23:07 robinjhuang

Hi there,

is there a way to read via API the front UI parameters like width, height, cfg, etc. before doing anything?

Cheers Theo

teodor-krastev avatar Jul 06 '24 14:07 teodor-krastev

Hi there,

is there a way to read via API the front UI parameters like width, height, cfg, etc. before doing anything?

Cheers Theo

The question is incorrect. You need to create the front data (i.e., prompt) and send it via API. The backend doesn't have the front end's data.

ltdrdata avatar Jul 06 '24 14:07 ltdrdata

Thank you ltdrdata for your prompt reply. I don't think my question is incorrect, simply the answer is NO. The backend acts as a server to the front end and towards API as clients. Have a lovely weekend! Theo

teodor-krastev avatar Jul 06 '24 16:07 teodor-krastev

For anyone interested, I have found a "dirty" way to read the user web interface. If you execute an image generation from web UI and then get "http://127.0.0.1:8188/history" (without promptId) you will have the parameters from web UI in json format.

teodor-krastev avatar Jul 07 '24 13:07 teodor-krastev