Merge branch 'comfyanonymous:master' into feat/is_change_object_storage

This commit is contained in:
Dr.Lt.Data 2023-07-15 03:40:08 +09:00 committed by GitHub
commit 57a696643c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 82 additions and 44 deletions

View File

@ -479,8 +479,8 @@ class CLIP:
def load_from_state_dict(self, sd): def load_from_state_dict(self, sd):
self.cond_stage_model.load_sd(sd) self.cond_stage_model.load_sd(sd)
def add_patches(self, patches, strength=1.0): def add_patches(self, patches, strength_patch=1.0, strength_model=1.0):
return self.patcher.add_patches(patches, strength) return self.patcher.add_patches(patches, strength_patch, strength_model)
def clip_layer(self, layer_idx): def clip_layer(self, layer_idx):
self.layer_idx = layer_idx self.layer_idx = layer_idx
@ -514,6 +514,9 @@ class CLIP:
def unpatch_model(self): def unpatch_model(self):
self.patcher.unpatch_model() self.patcher.unpatch_model()
def get_key_patches(self):
return self.patcher.get_key_patches()
class VAE: class VAE:
def __init__(self, ckpt_path=None, device=None, config=None): def __init__(self, ckpt_path=None, device=None, config=None):
if config is None: if config is None:

View File

@ -23,6 +23,27 @@ class ModelMergeSimple:
m.add_patches({k: kp[k]}, 1.0 - ratio, ratio) m.add_patches({k: kp[k]}, 1.0 - ratio, ratio)
return (m, ) return (m, )
class CLIPMergeSimple:
@classmethod
def INPUT_TYPES(s):
return {"required": { "clip1": ("CLIP",),
"clip2": ("CLIP",),
"ratio": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
}}
RETURN_TYPES = ("CLIP",)
FUNCTION = "merge"
CATEGORY = "advanced/model_merging"
def merge(self, clip1, clip2, ratio):
m = clip1.clone()
kp = clip2.get_key_patches()
for k in kp:
if k.endswith(".position_ids") or k.endswith(".logit_scale"):
continue
m.add_patches({k: kp[k]}, 1.0 - ratio, ratio)
return (m, )
class ModelMergeBlocks: class ModelMergeBlocks:
@classmethod @classmethod
def INPUT_TYPES(s): def INPUT_TYPES(s):
@ -94,4 +115,5 @@ NODE_CLASS_MAPPINGS = {
"ModelMergeSimple": ModelMergeSimple, "ModelMergeSimple": ModelMergeSimple,
"ModelMergeBlocks": ModelMergeBlocks, "ModelMergeBlocks": ModelMergeBlocks,
"CheckpointSave": CheckpointSave, "CheckpointSave": CheckpointSave,
"CLIPMergeSimple": CLIPMergeSimple,
} }

View File

@ -1,6 +1,6 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
import { ComfyDialog, $el } from "/scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
import { ComfyApp } from "/scripts/app.js"; import { ComfyApp } from "../../scripts/app.js";
export class ClipspaceDialog extends ComfyDialog { export class ClipspaceDialog extends ComfyDialog {
static items = []; static items = [];

View File

@ -1,5 +1,5 @@
import {app} from "/scripts/app.js"; import {app} from "../../scripts/app.js";
import {$el} from "/scripts/ui.js"; import {$el} from "../../scripts/ui.js";
// Manage color palettes // Manage color palettes

View File

@ -1,4 +1,4 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
// Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys // Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys

View File

@ -1,4 +1,4 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
// Inverts the scrolling of context menus // Inverts the scrolling of context menus

View File

@ -1,4 +1,4 @@
import {app} from "/scripts/app.js"; import {app} from "../../scripts/app.js";
app.registerExtension({ app.registerExtension({
name: "Comfy.Keybinds", name: "Comfy.Keybinds",

View File

@ -1,7 +1,8 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
import { ComfyDialog, $el } from "/scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
import { ComfyApp } from "/scripts/app.js"; import { ComfyApp } from "../../scripts/app.js";
import { ClipspaceDialog } from "/extensions/core/clipspace.js"; import { api } from "../../scripts/api.js"
import { ClipspaceDialog } from "./clipspace.js";
// Helper function to convert a data URL to a Blob object // Helper function to convert a data URL to a Blob object
function dataURLToBlob(dataURL) { function dataURLToBlob(dataURL) {
@ -33,7 +34,7 @@ function loadedImageToBlob(image) {
} }
async function uploadMask(filepath, formData) { async function uploadMask(filepath, formData) {
await fetch('/upload/mask', { await api.fetchApi('/upload/mask', {
method: 'POST', method: 'POST',
body: formData body: formData
}).then(response => {}).catch(error => { }).then(response => {}).catch(error => {
@ -41,7 +42,7 @@ async function uploadMask(filepath, formData) {
}); });
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image(); ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image();
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = "/view?" + new URLSearchParams(filepath).toString() + app.getPreviewFormatParam(); ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = api.apiURL("/view?" + new URLSearchParams(filepath).toString() + app.getPreviewFormatParam());
if(ComfyApp.clipspace.images) if(ComfyApp.clipspace.images)
ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']] = filepath; ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']] = filepath;

View File

@ -1,5 +1,5 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
import { ComfyDialog, $el } from "/scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
// Adds the ability to save and add multiple nodes as a template // Adds the ability to save and add multiple nodes as a template
// To save: // To save:

View File

@ -1,4 +1,4 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
// Use widget values and dates in output filenames // Use widget values and dates in output filenames

View File

@ -1,5 +1,5 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
import { ComfyWidgets } from "/scripts/widgets.js"; import { ComfyWidgets } from "../../scripts/widgets.js";
// Adds defaults for quickly adding nodes with middle click on the input/output // Adds defaults for quickly adding nodes with middle click on the input/output
app.registerExtension({ app.registerExtension({

View File

@ -1,4 +1,4 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
// Shift + drag/resize to snap to grid // Shift + drag/resize to snap to grid

View File

@ -1,4 +1,4 @@
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
// Adds an upload button to the nodes // Adds an upload button to the nodes

View File

@ -1,5 +1,5 @@
import { ComfyWidgets, addValueControlWidget } from "/scripts/widgets.js"; import { ComfyWidgets, addValueControlWidget } from "../../scripts/widgets.js";
import { app } from "/scripts/app.js"; import { app } from "../../scripts/app.js";
const CONVERTED_TYPE = "converted-widget"; const CONVERTED_TYPE = "converted-widget";
const VALID_TYPES = ["STRING", "combo", "number"]; const VALID_TYPES = ["STRING", "combo", "number"];

View File

@ -4,12 +4,12 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>ComfyUI</title> <title>ComfyUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="stylesheet" type="text/css" href="lib/litegraph.css" /> <link rel="stylesheet" type="text/css" href="./lib/litegraph.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="./style.css" />
<script type="text/javascript" src="lib/litegraph.core.js"></script> <script type="text/javascript" src="./lib/litegraph.core.js"></script>
<script type="text/javascript" src="lib/litegraph.extensions.js" defer></script> <script type="text/javascript" src="./lib/litegraph.extensions.js" defer></script>
<script type="module"> <script type="module">
import { app } from "/scripts/app.js"; import { app } from "./scripts/app.js";
await app.setup(); await app.setup();
window.app = app; window.app = app;
window.graph = app.graph; window.graph = app.graph;

View File

@ -3,6 +3,16 @@ class ComfyApi extends EventTarget {
constructor() { constructor() {
super(); super();
this.api_host = location.host;
this.api_base = location.pathname.split('/').slice(0, -1).join('/');
}
apiURL(route) {
return this.api_base + route;
}
fetchApi(route, options) {
return fetch(this.apiURL(route), options);
} }
addEventListener(type, callback, options) { addEventListener(type, callback, options) {
@ -16,7 +26,7 @@ class ComfyApi extends EventTarget {
#pollQueue() { #pollQueue() {
setInterval(async () => { setInterval(async () => {
try { try {
const resp = await fetch("/prompt"); const resp = await this.fetchApi("/prompt");
const status = await resp.json(); const status = await resp.json();
this.dispatchEvent(new CustomEvent("status", { detail: status })); this.dispatchEvent(new CustomEvent("status", { detail: status }));
} catch (error) { } catch (error) {
@ -40,7 +50,7 @@ class ComfyApi extends EventTarget {
existingSession = "?clientId=" + existingSession; existingSession = "?clientId=" + existingSession;
} }
this.socket = new WebSocket( this.socket = new WebSocket(
`ws${window.location.protocol === "https:" ? "s" : ""}://${location.host}/ws${existingSession}` `ws${window.location.protocol === "https:" ? "s" : ""}://${this.api_host}${this.api_base}/ws${existingSession}`
); );
this.socket.binaryType = "arraybuffer"; this.socket.binaryType = "arraybuffer";
@ -149,7 +159,7 @@ class ComfyApi extends EventTarget {
* @returns An array of script urls to import * @returns An array of script urls to import
*/ */
async getExtensions() { async getExtensions() {
const resp = await fetch("/extensions", { cache: "no-store" }); const resp = await this.fetchApi("/extensions", { cache: "no-store" });
return await resp.json(); return await resp.json();
} }
@ -158,7 +168,7 @@ class ComfyApi extends EventTarget {
* @returns An array of script urls to import * @returns An array of script urls to import
*/ */
async getEmbeddings() { async getEmbeddings() {
const resp = await fetch("/embeddings", { cache: "no-store" }); const resp = await this.fetchApi("/embeddings", { cache: "no-store" });
return await resp.json(); return await resp.json();
} }
@ -167,7 +177,7 @@ class ComfyApi extends EventTarget {
* @returns The node definitions * @returns The node definitions
*/ */
async getNodeDefs() { async getNodeDefs() {
const resp = await fetch("object_info", { cache: "no-store" }); const resp = await this.fetchApi("/object_info", { cache: "no-store" });
return await resp.json(); return await resp.json();
} }
@ -189,7 +199,7 @@ class ComfyApi extends EventTarget {
body.number = number; body.number = number;
} }
const res = await fetch("/prompt", { const res = await this.fetchApi("/prompt", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -224,7 +234,7 @@ class ComfyApi extends EventTarget {
*/ */
async getQueue() { async getQueue() {
try { try {
const res = await fetch("/queue"); const res = await this.fetchApi("/queue");
const data = await res.json(); const data = await res.json();
return { return {
// Running action uses a different endpoint for cancelling // Running action uses a different endpoint for cancelling
@ -246,7 +256,7 @@ class ComfyApi extends EventTarget {
*/ */
async getHistory() { async getHistory() {
try { try {
const res = await fetch("/history"); const res = await this.fetchApi("/history");
return { History: Object.values(await res.json()) }; return { History: Object.values(await res.json()) };
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -261,7 +271,7 @@ class ComfyApi extends EventTarget {
*/ */
async #postItem(type, body) { async #postItem(type, body) {
try { try {
await fetch("/" + type, { await this.fetchApi("/" + type, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -404,7 +404,7 @@ export class ComfyApp {
this.images = output.images; this.images = output.images;
imagesChanged = true; imagesChanged = true;
imgURLs = imgURLs.concat(output.images.map(params => { imgURLs = imgURLs.concat(output.images.map(params => {
return "/view?" + new URLSearchParams(params).toString() + app.getPreviewFormatParam(); return api.apiURL("/view?" + new URLSearchParams(params).toString() + app.getPreviewFormatParam());
})) }))
} }
} }
@ -1005,7 +1005,7 @@ export class ComfyApp {
const extensions = await api.getExtensions(); const extensions = await api.getExtensions();
for (const ext of extensions) { for (const ext of extensions) {
try { try {
await import(ext); await import(api.apiURL(ext));
} catch (error) { } catch (error) {
console.error("Error loading extension", ext, error); console.error("Error loading extension", ext, error);
} }

View File

@ -1,3 +1,5 @@
import { api } from "./api.js"
function getNumberDefaults(inputData, defaultStep) { function getNumberDefaults(inputData, defaultStep) {
let defaultVal = inputData[1]["default"]; let defaultVal = inputData[1]["default"];
let { min, max, step } = inputData[1]; let { min, max, step } = inputData[1];
@ -305,7 +307,7 @@ export const ComfyWidgets = {
subfolder = name.substring(0, folder_separator); subfolder = name.substring(0, folder_separator);
name = name.substring(folder_separator + 1); name = name.substring(folder_separator + 1);
} }
img.src = `/view?filename=${name}&type=input&subfolder=${subfolder}${app.getPreviewFormatParam()}`; img.src = api.apiURL(`/view?filename=${name}&type=input&subfolder=${subfolder}${app.getPreviewFormatParam()}`);
node.setSizeForImage?.(); node.setSizeForImage?.();
} }
@ -362,7 +364,7 @@ export const ComfyWidgets = {
// Wrap file in formdata so it includes filename // Wrap file in formdata so it includes filename
const body = new FormData(); const body = new FormData();
body.append("image", file); body.append("image", file);
const resp = await fetch("/upload/image", { const resp = await api.fetchApi("/upload/image", {
method: "POST", method: "POST",
body, body,
}); });

View File

@ -1,5 +1,5 @@
import { LGraphNode, IWidget } from "./litegraph"; import { LGraphNode, IWidget } from "./litegraph";
import { ComfyApp } from "/scripts/app"; import { ComfyApp } from "../../scripts/app";
export interface ComfyExtension { export interface ComfyExtension {
/** /**