Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6cc907de2 | ||
|
|
f847dcccf4 | ||
|
|
ff3f8f52d0 | ||
|
|
d7d46682fc | ||
|
|
dfe720f3ec | ||
|
|
2c68662c22 | ||
|
|
bc1b998ba5 |
@@ -1,11 +1,20 @@
|
||||
##
|
||||
|
||||
v0.2.6 🚀🚗🚚🏃
|
||||
|
||||
- [Add getting camera video stream](./workflow/7-camera-workflow.json)
|
||||
- Add a slider to the floating window, which can be used as input for denoise
|
||||
- OSupport for calling multiple GPTs
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### ScreenShareNode & FloatingVideoNode
|
||||
> Now comfyui supports capturing screen pixel streams from any software and can be used for LCM-Lora integration. Let's get started with implementation and design! 💻🌐
|
||||
|
||||
>
|
||||
|
||||
https://github.com/shadowcz007/comfyui-mixlab-nodes/assets/12645064/e7e77f90-e43e-410a-ab3a-1952b7b4e7da
|
||||
|
||||
|
||||
@@ -16,7 +25,7 @@ https://github.com/shadowcz007/comfyui-mixlab-nodes/assets/12645064/e7e77f90-e43
|
||||
|
||||
|
||||
### LoadImagesFromLocal
|
||||
> Monitor changes to images in a local folder, and trigger real-time execution of workflows, supporting common image formats, especially PSD format, in conjunction with Photoshop. Q: Translate into English
|
||||
> Monitor changes to images in a local folder, and trigger real-time execution of workflows, supporting common image formats, especially PSD format, in conjunction with Photoshop.
|
||||
|
||||

|
||||
|
||||
@@ -24,7 +33,7 @@ https://github.com/shadowcz007/comfyui-mixlab-nodes/assets/12645064/e7e77f90-e43
|
||||
|
||||
|
||||
### GPT
|
||||
> ChatGPT、ChatGLM3 , Some code provided by rui.
|
||||
>Support for calling multiple GPTs.ChatGPT、ChatGLM3 , Some code provided by rui. If you are using OpenAI's service, fill in https://api.openai.com/v1 . If you are using a local LLM service, fill in http://127.0.0.1:xxxx/v1 . Azure OpenAI:https://xxxx.openai.azure.com
|
||||
|
||||
|
||||

|
||||
|
||||
+21
-8
@@ -64,6 +64,18 @@ except ImportError:
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
def install_openai():
|
||||
# Helper function to install the OpenAI module if not already installed
|
||||
try:
|
||||
importlib.import_module('openai')
|
||||
except ImportError:
|
||||
import pip
|
||||
pip.main(['install', 'openai'])
|
||||
|
||||
install_openai()
|
||||
|
||||
|
||||
current_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
@@ -260,7 +272,7 @@ from .nodes.ImageNode import TransparentImage,LoadImagesFromPath,AreaToMask,Smoo
|
||||
from .nodes.Vae import VAELoader,VAEDecode
|
||||
from .nodes.ScreenShareNode import ScreenShareNode,FloatingVideo
|
||||
from .nodes.Clipseg import CLIPSeg,CombineMasks
|
||||
from .nodes.ChatGPT import ChatGPTNode,SessionHistory
|
||||
from .nodes.ChatGPT import ChatGPTNode,ShowTextForGPT,CharacterInText
|
||||
|
||||
# 要导出的所有节点及其名称的字典
|
||||
# 注意:名称应全局唯一
|
||||
@@ -281,20 +293,21 @@ NODE_CLASS_MAPPINGS = {
|
||||
"FloatingVideo":FloatingVideo,
|
||||
"CLIPSeg_":CLIPSeg,
|
||||
"CombineMasks_":CombineMasks,
|
||||
"ChatGPT":ChatGPTNode,
|
||||
"SessionHistory":SessionHistory
|
||||
"ChatGPTOpenAI":ChatGPTNode,
|
||||
"ShowTextForGPT":ShowTextForGPT,
|
||||
"CharacterInText":CharacterInText
|
||||
}
|
||||
|
||||
# 一个包含节点友好/可读的标题的字典
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RandomPrompt": "Random Prompt #Mixlab",
|
||||
"RandomPrompt": "Random Prompt ♾️Mixlab",
|
||||
"SplitLongMask":"Splitting a long image into sections",
|
||||
"VAELoaderConsistencyDecoder":"Consistency Decoder Loader",
|
||||
"VAEDecodeConsistencyDecoder":"Consistency Decoder Decode",
|
||||
"ScreenShare":"ScreenShare #Mixlab",
|
||||
"FloatingVideo":"FloatingVideo #Mixlab",
|
||||
"ChatGPT":"ChatGPT #Mixlab",
|
||||
"SessionHistory":"SessionHistory #Mixlab"
|
||||
"ScreenShare":"ScreenShare ♾️Mixlab",
|
||||
"FloatingVideo":"FloatingVideo ♾️Mixlab",
|
||||
"ChatGPTOpenAI":"ChatGPT ♾️Mixlab",
|
||||
"ShowTextForGPT":"ShowTextForGPT ♾️Mixlab"
|
||||
}
|
||||
|
||||
# web ui的节点功能
|
||||
|
||||
+81
-24
@@ -66,7 +66,7 @@ class ChatGPTNode:
|
||||
def __init__(self):
|
||||
# self.__client = OpenAI()
|
||||
self.session_history = [] # 用于存储会话历史的列表
|
||||
self.seed=0
|
||||
# self.seed=0
|
||||
self.system_content="You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible."
|
||||
|
||||
@classmethod
|
||||
@@ -75,24 +75,29 @@ class ChatGPTNode:
|
||||
"required": {
|
||||
"api_key":("KEY", {"default": "", "multiline": True}),
|
||||
"api_url":("URL", {"default": "", "multiline": True}),
|
||||
"prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"system_content": ("STRING",
|
||||
{
|
||||
"default": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.",
|
||||
"multiline": True
|
||||
}),
|
||||
"model": (["gpt-3.5-turbo", "gpt-3.5-turbo-16k-0613", "gpt-4-0613","gpt-4-1106-preview"],
|
||||
"model": (["gpt-3.5-turbo","gpt-35-turbo","gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-4-0613","gpt-4-1106-preview"],
|
||||
{"default": "gpt-3.5-turbo"}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1}),
|
||||
"context_size":("INT", {"default": 1, "min": 0, "max":30, "step": 1}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING",)
|
||||
RETURN_NAMES = ("STRING","session_history",)
|
||||
RETURN_TYPES = ("STRING","STRING","STRING",)
|
||||
RETURN_NAMES = ("text","messages","session_history",)
|
||||
FUNCTION = "generate_contextual_text"
|
||||
CATEGORY = "Mixlab/GPT"
|
||||
CATEGORY = "♾️Mixlab/GPT"
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,False,)
|
||||
OUTPUT_IS_LIST = (False,False,False,)
|
||||
|
||||
|
||||
def generate_contextual_text(self,
|
||||
@@ -101,18 +106,13 @@ class ChatGPTNode:
|
||||
prompt,
|
||||
system_content,
|
||||
model,
|
||||
seed):
|
||||
print(api_key,
|
||||
api_url,
|
||||
prompt,
|
||||
system_content,
|
||||
model,
|
||||
seed)
|
||||
seed,context_size,unique_id = None, extra_pnginfo=None):
|
||||
# print(api_key!='',api_url,prompt,system_content,model,seed)
|
||||
# 可以选择保留会话历史以维持上下文记忆
|
||||
# 或者在此处清除会话历史 self.session_history.clear()
|
||||
if seed!=self.seed:
|
||||
self.seed=seed
|
||||
self.session_history=[]
|
||||
# if seed!=self.seed:
|
||||
# self.seed=seed
|
||||
# self.session_history=[]
|
||||
|
||||
# 把系统信息和初始信息添加到会话历史中
|
||||
if system_content:
|
||||
@@ -129,21 +129,45 @@ class ChatGPTNode:
|
||||
|
||||
# 把用户的提示添加到会话历史中
|
||||
# 调用API时传递整个会话历史
|
||||
messages=[{"role": "system", "content": self.system_content}]+self.session_history+[{"role": "user", "content": prompt}]
|
||||
|
||||
def crop_list_tail(lst, size):
|
||||
if size >= len(lst):
|
||||
return lst
|
||||
elif size==0:
|
||||
return []
|
||||
else:
|
||||
return lst[-size:]
|
||||
|
||||
session_history=crop_list_tail(self.session_history,context_size)
|
||||
|
||||
messages=[{"role": "system", "content": self.system_content}]+session_history+[{"role": "user", "content": prompt}]
|
||||
response_content = chat(client,model,messages)
|
||||
|
||||
self.session_history=self.session_history+[{"role": "user", "content": prompt}]+[{'role':'assistant',"content":response_content}]
|
||||
|
||||
|
||||
# if unique_id and extra_pnginfo and "workflow" in extra_pnginfo[0]:
|
||||
# workflow = extra_pnginfo[0]["workflow"]
|
||||
# node = next((x for x in workflow["nodes"] if str(x["id"]) == unique_id[0]), None)
|
||||
# if node:
|
||||
# node["widgets_values"] = ["",
|
||||
# api_url,
|
||||
# prompt,
|
||||
# system_content,
|
||||
# model,
|
||||
# seed,
|
||||
# context_size]
|
||||
|
||||
return (response_content,json.dumps(self.session_history, indent=4),)
|
||||
return (response_content,json.dumps(messages, indent=4),json.dumps(self.session_history, indent=4),)
|
||||
|
||||
|
||||
|
||||
class SessionHistory:
|
||||
class ShowTextForGPT:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"session_history": ("STRING", {"forceInput": True}),
|
||||
"text": ("STRING", {"forceInput": True}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +177,41 @@ class SessionHistory:
|
||||
OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
CATEGORY = "Mixlab/GPT"
|
||||
CATEGORY = "♾️Mixlab/GPT"
|
||||
|
||||
def run(self, session_history):
|
||||
def run(self, text):
|
||||
# print(session_history)
|
||||
return {"ui": {"text": session_history}, "result": (session_history,)}
|
||||
return {"ui": {"text": text}, "result": (text,)}
|
||||
|
||||
|
||||
class CharacterInText:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"multiline": True}),
|
||||
"character": ("STRING", {"multiline": True}),
|
||||
"start_index": ("INT", {
|
||||
"default": 1,
|
||||
"min": 0, #Minimum value
|
||||
"max": 1024, #Maximum value
|
||||
"step": 1, #Slider's step
|
||||
"display": "number" # Cosmetic only: display as "number" or "slider"
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
RETURN_TYPES = ("INT",)
|
||||
FUNCTION = "run"
|
||||
# OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
CATEGORY = "♾️Mixlab/GPT"
|
||||
|
||||
def run(self, text,character,start_index):
|
||||
# print(text,character,start_index)
|
||||
b=1 if character in text else 0
|
||||
|
||||
return (b+start_index,)
|
||||
|
||||
|
||||
+2
-2
@@ -99,7 +99,7 @@ class CLIPSeg:
|
||||
}
|
||||
}
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
RETURN_TYPES = ("MASK", "IMAGE", "IMAGE",)
|
||||
RETURN_NAMES = ("Mask","Heatmap Mask", "BW Mask")
|
||||
|
||||
@@ -204,7 +204,7 @@ class CombineMasks:
|
||||
},
|
||||
}
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
RETURN_TYPES = ("MASK", "IMAGE", "IMAGE",)
|
||||
RETURN_NAMES = ("Combined Mask","Heatmap Mask", "BW Mask")
|
||||
|
||||
|
||||
+9
-9
@@ -341,7 +341,7 @@ class SmoothMask:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
|
||||
@@ -389,7 +389,7 @@ class FeatheredMask:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
@@ -456,7 +456,7 @@ class SplitLongMask:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@@ -499,7 +499,7 @@ class TransparentImage:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
# INPUT_IS_LIST = True, 一个batch传进来
|
||||
OUTPUT_IS_LIST = (True,True,True,)
|
||||
@@ -568,7 +568,7 @@ class EnhanceImage:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
|
||||
@@ -627,7 +627,7 @@ class LoadImagesFromPath:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
# INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,True,False,)
|
||||
@@ -688,7 +688,7 @@ class ImageCropByAlpha:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
@@ -719,7 +719,7 @@ class AreaToMask:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
@@ -754,7 +754,7 @@ class FaceToMask:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/mask"
|
||||
CATEGORY = "♾️Mixlab/mask"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
+2
-2
@@ -79,7 +79,7 @@ class RandomPrompt:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/prompt"
|
||||
CATEGORY = "♾️Mixlab/prompt"
|
||||
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
OUTPUT_NODE = True
|
||||
@@ -158,7 +158,7 @@ class RunWorkflow:
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/workflow"
|
||||
CATEGORY = "♾️Mixlab/workflow"
|
||||
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
OUTPUT_NODE = True
|
||||
|
||||
@@ -82,23 +82,24 @@ class ScreenShareNode:
|
||||
},
|
||||
"optional":{
|
||||
"prompt": ("PROMPT",),
|
||||
"slide": ("SLIDE",),
|
||||
# "seed": ("INT", {"default": 1, "min": 0, "max": 0xffffffffffffffff}),
|
||||
} }
|
||||
|
||||
RETURN_TYPES = ('IMAGE','STRING')
|
||||
|
||||
RETURN_TYPES = ('IMAGE','STRING','FLOAT')
|
||||
RETURN_NAMES = ("IMAGE","PROMPT","FLOAT",)
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
# INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (False,False,False)
|
||||
OUTPUT_IS_LIST = (False,False,False,False)
|
||||
|
||||
# 运行的函数
|
||||
def run(self,image_base64,prompt):
|
||||
def run(self,image_base64,prompt,slide):
|
||||
im,mask=base64_save(image_base64)
|
||||
# print('##########prompt',prompt)
|
||||
return (im,prompt)
|
||||
return (im,prompt,slide)
|
||||
|
||||
|
||||
class FloatingVideo:
|
||||
@@ -114,7 +115,7 @@ class FloatingVideo:
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "Mixlab/image"
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
# INPUT_IS_LIST = True
|
||||
# OUTPUT_IS_LIST = (False,False,)
|
||||
@@ -137,3 +138,15 @@ class FloatingVideo:
|
||||
|
||||
return { "ui": { "images_": results } }
|
||||
|
||||
|
||||
|
||||
# class SildeNode:
|
||||
# CATEGORY = "quicknodes"
|
||||
# @classmethod
|
||||
# def INPUT_TYPES(s):
|
||||
# return { "required":{} }
|
||||
# RETURN_TYPES = ()
|
||||
# RETURN_NAMES = ()
|
||||
# FUNCTION = "func"
|
||||
# def func(self):
|
||||
# return ()
|
||||
+2
-2
@@ -145,7 +145,7 @@ class VAELoader:
|
||||
RETURN_TYPES = ("VAE",)
|
||||
FUNCTION = "load_vae"
|
||||
|
||||
CATEGORY = "Mixlab/ConsistencyDecoder"
|
||||
CATEGORY = "♾️Mixlab/ConsistencyDecoder"
|
||||
|
||||
#TODO: scale factor?
|
||||
def load_vae(self, vae_name):
|
||||
@@ -165,7 +165,7 @@ class VAEDecode:
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "decode"
|
||||
|
||||
CATEGORY = "Mixlab/ConsistencyDecoder"
|
||||
CATEGORY = "♾️Mixlab/ConsistencyDecoder"
|
||||
|
||||
def decode(self, vae, samples):
|
||||
image = vae.decode(samples["samples"].to("cuda:0"))
|
||||
|
||||
@@ -3,20 +3,24 @@ import { app } from '../../../scripts/app.js'
|
||||
const repoOwner = 'shadowcz007' // 替换为仓库的所有者
|
||||
const repoName = 'comfyui-mixlab-nodes' // 替换为仓库的名称
|
||||
|
||||
const version = 'v0.2.5'
|
||||
const version = 'v0.2.6'
|
||||
|
||||
fetch(`https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const latestVersion = data.tag_name
|
||||
console.log('Latest release version:', latestVersion)
|
||||
// if (latestVersion === localStorage.getItem('_mixlab_nodes_vesion')) return
|
||||
if (latestVersion != version) {
|
||||
// localStorage.setItem('_mixlab_nodes_vesion', latestVersion)
|
||||
if (
|
||||
latestVersion &&
|
||||
latestVersion === localStorage.getItem('_mixlab_nodes_vesion')
|
||||
)
|
||||
return
|
||||
if (latestVersion && latestVersion != version) {
|
||||
localStorage.setItem('_mixlab_nodes_vesion', latestVersion)
|
||||
app.ui.dialog.show(`<h4 style="font-size: 18px;">${repoName} <br>
|
||||
Latest release version: ${latestVersion}</h4>
|
||||
<p>Please proceed to the official repository to download the latest version.</p>
|
||||
<a style=" color: #2196F3;
|
||||
<a style="color: #2196F3;
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 2px;
|
||||
@@ -46,12 +46,22 @@ function get_position_style (ctx, widget_width, y, node_height) {
|
||||
}
|
||||
}
|
||||
|
||||
const getLocalData = key => {
|
||||
let data = {}
|
||||
try {
|
||||
data = JSON.parse(localStorage.getItem(key)) || {}
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Mixlab.GPT.ChatGPT',
|
||||
name: 'Mixlab.GPT.ChatGPTOpenAI',
|
||||
async getCustomWidgets (app) {
|
||||
return {
|
||||
KEY (node, inputName, inputData, app) {
|
||||
// console.log('node', inputName, inputData[0])
|
||||
// console.log('##node', node)
|
||||
const widget = {
|
||||
type: inputData[0], // the type, CHEESE
|
||||
name: inputName, // the name, slice
|
||||
@@ -61,7 +71,8 @@ app.registerExtension({
|
||||
return [128, 24] // a method to compute the current size of the widget
|
||||
},
|
||||
async serializeValue (nodeId, widgetIndex) {
|
||||
return localStorage.getItem('_mixlab_api_key') || ''
|
||||
let data = getLocalData('_mixlab_api_key')
|
||||
return data[node.id] || 'by Mixlab'
|
||||
}
|
||||
}
|
||||
// widget.something = something; // maybe adds stuff to it
|
||||
@@ -81,7 +92,8 @@ app.registerExtension({
|
||||
return [128, 24] // a method to compute the current size of the widget
|
||||
},
|
||||
async serializeValue (nodeId, widgetIndex) {
|
||||
return localStorage.getItem('_mixlab_api_url') || ''
|
||||
let data = getLocalData('_mixlab_api_url')
|
||||
return data[node.id] || 'https://api.openai.com/v1'
|
||||
}
|
||||
}
|
||||
// widget.something = something; // maybe adds stuff to it
|
||||
@@ -90,22 +102,21 @@ app.registerExtension({
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
||||
// console.log(nodeType.comfyClass)
|
||||
if (nodeType.comfyClass == 'ChatGPT') {
|
||||
if (nodeType.comfyClass == 'ChatGPTOpenAI') {
|
||||
const orig_nodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
orig_nodeCreated?.apply(this, arguments)
|
||||
|
||||
console.log('ChatGPT widtget', this.widgets)
|
||||
|
||||
const api_key = this.widgets.filter(w => w.name == 'api_key')[0]
|
||||
const api_url = this.widgets.filter(w => w.name == 'api_url')[0]
|
||||
console.log('api_key', api_key, api_url)
|
||||
|
||||
console.log('ChatGPTOpenAI nodeData', this.widgets)
|
||||
|
||||
const widget = {
|
||||
type: 'div',
|
||||
name: 'chatgpt div',
|
||||
name: 'chatgptdiv',
|
||||
draw (ctx, node, widget_width, y, widget_height) {
|
||||
Object.assign(
|
||||
this.div.style,
|
||||
@@ -118,87 +129,101 @@ app.registerExtension({
|
||||
|
||||
document.body.appendChild(widget.div)
|
||||
|
||||
const inputKey = document.createElement('input'),
|
||||
inputUrl = document.createElement('input')
|
||||
inputKey.type = 'text'
|
||||
inputUrl.type = 'text'
|
||||
const inputDiv = (key, placeholder) => {
|
||||
let div = document.createElement('div')
|
||||
const ip = document.createElement('input')
|
||||
ip.type = placeholder === 'Key' ? 'password' : 'text'
|
||||
ip.className = `${'comfy-multiline-input'} ${placeholder}`
|
||||
div.style = `display: flex;
|
||||
align-items: center;
|
||||
margin: 6px 8px;
|
||||
margin-top: 0;`
|
||||
ip.placeholder = placeholder
|
||||
ip.value = placeholder
|
||||
|
||||
inputKey.placeholder = 'Key'
|
||||
inputUrl.placeholder = 'URL'
|
||||
ip.style = `margin-left: 24px;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 4px;width: 100%;`
|
||||
const label = document.createElement('label')
|
||||
label.style = 'font-size: 10px;min-width:32px'
|
||||
label.innerText = placeholder
|
||||
div.appendChild(label)
|
||||
div.appendChild(ip)
|
||||
|
||||
inputKey.style = `margin:4px 48px;`
|
||||
inputUrl.style = `margin:4px 48px`
|
||||
ip.addEventListener('change', () => {
|
||||
let data = getLocalData(key)
|
||||
data[this.id] = ip.value.trim()
|
||||
localStorage.setItem(key, JSON.stringify(data))
|
||||
console.log(this.id, key)
|
||||
})
|
||||
return div
|
||||
}
|
||||
|
||||
inputUrl.value = localStorage.getItem('_mixlab_api_url') || ''
|
||||
inputKey.value = localStorage.getItem('_mixlab_api_key') || ''
|
||||
let inputKey = inputDiv('_mixlab_api_key', 'Key')
|
||||
let inputUrl = inputDiv('_mixlab_api_url', 'URL')
|
||||
|
||||
widget.div.appendChild(inputKey)
|
||||
widget.div.appendChild(inputUrl)
|
||||
|
||||
inputKey.addEventListener('change', () => {
|
||||
api_key.serializeValue = () => inputKey.value || ''
|
||||
localStorage.setItem('_mixlab_api_key', inputKey.value)
|
||||
})
|
||||
|
||||
inputUrl.addEventListener('change', () => {
|
||||
api_url.serializeValue = () => inputUrl.value || ''
|
||||
localStorage.setItem('_mixlab_api_url', inputUrl.value)
|
||||
})
|
||||
|
||||
/*
|
||||
Add the widget, make sure we clean up nicely, and we do not want to be serialized!
|
||||
*/
|
||||
this.addCustomWidget(widget)
|
||||
this.onRemoved = function () {
|
||||
|
||||
const onRemoved = this.onRemoved
|
||||
this.onRemoved = () => {
|
||||
inputUrl.remove()
|
||||
inputKey.remove()
|
||||
widget.div.remove()
|
||||
return onRemoved?.()
|
||||
}
|
||||
this.serialize_widgets = false
|
||||
|
||||
this.serialize_widgets = true //需要保存参数
|
||||
}
|
||||
}
|
||||
},
|
||||
async loadedGraphNode (node, app) {
|
||||
// Fires every time a node is constructed
|
||||
// You can modify widgets/add handlers/etc here
|
||||
|
||||
if (node.type === 'ChatGPTOpenAI') {
|
||||
let widget = node.widgets.filter(w => w.div)[0]
|
||||
|
||||
let apiKey = getLocalData('_mixlab_api_key'),
|
||||
url = getLocalData('_mixlab_api_url')
|
||||
|
||||
let id = node.id
|
||||
|
||||
console.log('ChatGPTOpenAI serialize_widgets', this)
|
||||
|
||||
widget.div.querySelector('.Key').value = apiKey[id] || 'by Mixlab'
|
||||
widget.div.querySelector('.URL').value =
|
||||
url[id] || 'https://api.openai.com/v1'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
app.registerExtension({
|
||||
name: "Mixlab.GPT.SessionHistory",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "SessionHistory") {
|
||||
name: 'Mixlab.GPT.ShowTextForGPT',
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "ShowTextForGPT") {
|
||||
function populate(text) {
|
||||
if (this.widgets) {
|
||||
|
||||
// const pos = this.widgets.findIndex((w) => w.name === "text");
|
||||
// if (pos !== -1) {
|
||||
// for (let i = pos; i < this.widgets.length; i++) {
|
||||
// this.widgets[i].onRemove?.();
|
||||
// }
|
||||
// this.widgets.length = pos;
|
||||
// }
|
||||
|
||||
for (let i = 0; i < this.widgets.length; i++) {
|
||||
this.widgets[i].onRemove?.();
|
||||
}
|
||||
this.widgets.length = 0;
|
||||
|
||||
const pos = this.widgets.findIndex((w) => w.name === "text");
|
||||
if (pos !== -1) {
|
||||
for (let i = pos; i < this.widgets.length; i++) {
|
||||
this.widgets[i].onRemove?.();
|
||||
}
|
||||
this.widgets.length = pos;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('SessionHistory',this.widgets,text)
|
||||
|
||||
// console.log('ShowTextForGPT',this.widgets.length)
|
||||
for (const list of text) {
|
||||
const w = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget;
|
||||
w.inputEl.readOnly = true;
|
||||
w.inputEl.style.opacity = 0.6;
|
||||
|
||||
let res=list;
|
||||
|
||||
try {
|
||||
res=JSON.stringify(JSON.parse(list),null,2)
|
||||
} catch (error) {
|
||||
// console.log(list)
|
||||
}
|
||||
|
||||
w.value = res;
|
||||
w.value = list;
|
||||
}
|
||||
|
||||
// console.log('ShowTextForGPT',this.widgets.length)
|
||||
requestAnimationFrame(() => {
|
||||
const sz = this.computeSize();
|
||||
if (sz[0] < this.size[0]) {
|
||||
@@ -223,9 +248,15 @@ app.registerExtension({
|
||||
nodeType.prototype.onConfigure = function () {
|
||||
onConfigure?.apply(this, arguments);
|
||||
if (this.widgets_values?.length) {
|
||||
|
||||
populate.call(this, this.widgets_values);
|
||||
}
|
||||
};
|
||||
|
||||
this.serialize_widgets = true //需要保存参数
|
||||
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
})
|
||||
@@ -106,24 +106,65 @@ async function uploadFile (file) {
|
||||
|
||||
// alert(navigator.mediaDevices)
|
||||
|
||||
async function shareScreen (webcamVideo, shareBtn, liveBtn, previewArea) {
|
||||
async function shareScreen (
|
||||
isCamera = false,
|
||||
webcamVideo,
|
||||
shareBtn,
|
||||
liveBtn,
|
||||
previewArea
|
||||
) {
|
||||
try {
|
||||
// let webcamVideo = document.createElement('video')
|
||||
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: true
|
||||
})
|
||||
let mediaStream
|
||||
|
||||
if (!isCamera) {
|
||||
mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: true
|
||||
})
|
||||
} else {
|
||||
if (!localStorage.getItem('_mixlab_webcamera_select')) return
|
||||
let constraints =
|
||||
JSON.parse(localStorage.getItem('_mixlab_webcamera_select')) || {}
|
||||
mediaStream = await navigator.mediaDevices.getUserMedia(constraints)
|
||||
}
|
||||
|
||||
webcamVideo.removeEventListener('timeupdate', videoTimeUpdateHandler)
|
||||
webcamVideo.srcObject = mediaStream
|
||||
webcamVideo.onloadedmetadata = () => {
|
||||
let x = 0,
|
||||
y = 0,
|
||||
width = webcamVideo.videoWidth,
|
||||
height = webcamVideo.videoHeight,
|
||||
imgWidth = webcamVideo.videoWidth,
|
||||
imgHeight = webcamVideo.videoHeight
|
||||
|
||||
let d = getSetAreaData()
|
||||
if (
|
||||
d &&
|
||||
d.x >= 0 &&
|
||||
d.imgWidth === imgWidth &&
|
||||
d.imgHeight === imgHeight
|
||||
) {
|
||||
x = d.x
|
||||
y = d.y
|
||||
width = d.width
|
||||
height = d.height
|
||||
imgWidth = d.imgWidth
|
||||
imgHeight = d.imgHeight
|
||||
console.log('#screen_share::使用上一次选区')
|
||||
}
|
||||
updateSetAreaData(x, y, width, height, imgWidth, imgHeight)
|
||||
|
||||
webcamVideo.play()
|
||||
|
||||
createBlobFromVideo(webcamVideo, true)
|
||||
|
||||
webcamVideo.addEventListener('timeupdate', videoTimeUpdateHandler)
|
||||
|
||||
window._mixlab_screen_x = 0
|
||||
window._mixlab_screen_y = 0
|
||||
// console.log(webcamVideo)
|
||||
window._mixlab_screen_width = webcamVideo.videoWidth
|
||||
window._mixlab_screen_height = webcamVideo.videoHeight
|
||||
// window._mixlab_screen_x = 0
|
||||
// window._mixlab_screen_y = 0
|
||||
// // console.log(webcamVideo)
|
||||
// window._mixlab_screen_width = webcamVideo.videoWidth
|
||||
// window._mixlab_screen_height = webcamVideo.videoHeight
|
||||
}
|
||||
|
||||
mediaStream.addEventListener('inactive', handleStopSharing)
|
||||
@@ -278,7 +319,7 @@ async function startLive (btn) {
|
||||
previousImage,
|
||||
currentImage
|
||||
)
|
||||
// console.log('#图片是否有变化:', imageChanged)
|
||||
console.log('#图片是否有变化:', imageChanged)
|
||||
|
||||
if (imageChanged) {
|
||||
window._mixlab_screen_imagePath = currentImage
|
||||
@@ -328,26 +369,17 @@ async function createBlobFromVideoForArea (webcamVideo) {
|
||||
return blob
|
||||
}
|
||||
|
||||
async function createBlobFromVideo (webcamVideo) {
|
||||
async function createBlobFromVideo (webcamVideo, updateImageBase64 = false) {
|
||||
const videoW = webcamVideo.videoWidth
|
||||
const videoH = webcamVideo.videoHeight
|
||||
const aspectRatio = videoW / videoH
|
||||
const WIDTH = window._mixlab_screen_width,
|
||||
HEIGHT = window._mixlab_screen_height
|
||||
const canvas = new OffscreenCanvas(WIDTH, HEIGHT)
|
||||
|
||||
const { x, y, width, height } = window._mixlab_share_screen
|
||||
|
||||
const canvas = new OffscreenCanvas(width, height)
|
||||
const ctx = canvas.getContext('2d')
|
||||
// console.log('#createBlobFromVideo', WIDTH, HEIGHT)
|
||||
ctx.drawImage(
|
||||
webcamVideo,
|
||||
window._mixlab_screen_x,
|
||||
window._mixlab_screen_y,
|
||||
WIDTH,
|
||||
HEIGHT,
|
||||
0,
|
||||
0,
|
||||
WIDTH,
|
||||
HEIGHT
|
||||
)
|
||||
|
||||
ctx.drawImage(webcamVideo, x, y, width, height, 0, 0, width, height)
|
||||
|
||||
const blob = await canvas.convertToBlob({
|
||||
type: 'image/jpeg',
|
||||
@@ -356,12 +388,17 @@ async function createBlobFromVideo (webcamVideo) {
|
||||
// imgElement.src = await blobToBase64(blob)
|
||||
window._mixlab_screen_blob = blob
|
||||
|
||||
console.log('########')
|
||||
// let currentImage = await blobToBase64(blob)
|
||||
// // console.log(window._mixlab_screen_imagePath)
|
||||
// if (!window._mixlab_screen_imagePath) {
|
||||
// window._mixlab_screen_imagePath = currentImage
|
||||
// }
|
||||
console.log(
|
||||
'########updateImageBase64 ',
|
||||
updateImageBase64,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
)
|
||||
if (updateImageBase64) {
|
||||
window._mixlab_screen_imagePath = await blobToBase64(blob)
|
||||
}
|
||||
}
|
||||
|
||||
async function blobToBase64 (blob) {
|
||||
@@ -391,6 +428,36 @@ function base64ToBlob (base64) {
|
||||
|
||||
return blob
|
||||
}
|
||||
|
||||
async function requestCamera () {
|
||||
// 请求授权
|
||||
try {
|
||||
let stream = await navigator.mediaDevices.getUserMedia({ video: true })
|
||||
console.log('摄像头授权成功')
|
||||
// 获取视频轨道
|
||||
var videoTrack = stream.getVideoTracks()[0]
|
||||
|
||||
// 停止视频轨道
|
||||
videoTrack.stop()
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
// 用户拒绝授权或发生其他错误
|
||||
console.error('摄像头授权失败:', error)
|
||||
|
||||
// 提示用户授权摄像头访问权限
|
||||
if (error.name === 'NotAllowedError') {
|
||||
alert('请授权摄像头访问权限 chrome://settings/content/camera')
|
||||
} else {
|
||||
alert('摄像头访问权限请求失败,请重试 chrome://settings/content/camera')
|
||||
}
|
||||
|
||||
// // 跳转到浏览器的授权设置页面
|
||||
// window.location.href = 'chrome://settings/content/camera'
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
A method that returns the required style for the html
|
||||
*/
|
||||
@@ -432,7 +499,7 @@ const base64Df =
|
||||
app.registerExtension({
|
||||
name: 'Mixlab.image.ScreenShareNode',
|
||||
async getCustomWidgets (app) {
|
||||
console.log('#Mixlab.image.ScreenShareNode', app)
|
||||
// console.log('#Mixlab.image.ScreenShareNode', app)
|
||||
return {
|
||||
CHEESE (node, inputName, inputData, app) {
|
||||
// We return an object containing a field CHEESE which has a function (taking node, name, data, app)
|
||||
@@ -473,6 +540,26 @@ app.registerExtension({
|
||||
// console.log('###widget', widget)
|
||||
node.addCustomWidget(widget) // adds it to the node
|
||||
return widget // and returns it.
|
||||
},
|
||||
SLIDE (node, inputName, inputData, app) {
|
||||
// We return an object containing a field CHEESE which has a function (taking node, name, data, app)
|
||||
const widget = {
|
||||
type: inputData[0], // the type, CHEESE
|
||||
name: inputName, // the name, slice
|
||||
size: [128, 12], // a default size
|
||||
draw (ctx, node, width, y) {
|
||||
// a method to draw the widget (ctx is a CanvasRenderingContext2D)
|
||||
},
|
||||
computeSize (...args) {
|
||||
return [128, 12] // a method to compute the current size of the widget
|
||||
},
|
||||
async serializeValue (nodeId, widgetIndex) {
|
||||
return window._mixlab_screen_slide_input || 0.5
|
||||
}
|
||||
}
|
||||
// console.log('###widget', widget)
|
||||
node.addCustomWidget(widget) // adds it to the node
|
||||
return widget // and returns it.
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -510,8 +597,15 @@ app.registerExtension({
|
||||
})
|
||||
|
||||
widget.previewArea = $el('div', {
|
||||
style: {}
|
||||
})
|
||||
|
||||
widget.shareDiv = $el('div', {
|
||||
// innerText: 'Share Screen',
|
||||
style: {
|
||||
// position:'ab'
|
||||
cursor: 'pointer',
|
||||
fontWeight: '300',
|
||||
display: 'flex'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -521,7 +615,19 @@ app.registerExtension({
|
||||
cursor: 'pointer',
|
||||
padding: '8px 0',
|
||||
fontWeight: '300',
|
||||
margin: '2px'
|
||||
margin: '2px',
|
||||
width: '100%'
|
||||
}
|
||||
})
|
||||
|
||||
widget.shareOfWebCamBtn = $el('button', {
|
||||
innerText: 'Camera',
|
||||
style: {
|
||||
cursor: 'pointer',
|
||||
padding: '8px 0',
|
||||
fontWeight: '300',
|
||||
margin: '2px',
|
||||
width: '100%'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -563,20 +669,30 @@ app.registerExtension({
|
||||
widget.previewCard.appendChild(widget.preview)
|
||||
widget.previewCard.appendChild(widget.previewArea)
|
||||
|
||||
widget.card.appendChild(widget.shareBtn)
|
||||
widget.card.appendChild(widget.shareDiv)
|
||||
widget.shareDiv.appendChild(widget.shareBtn)
|
||||
widget.shareDiv.appendChild(widget.shareOfWebCamBtn)
|
||||
widget.card.appendChild(widget.openFloatingWinBtn)
|
||||
widget.card.appendChild(widget.refreshInput)
|
||||
widget.card.appendChild(widget.liveBtn)
|
||||
|
||||
widget.shareBtn.addEventListener('click', async () => {
|
||||
const toggleShare = async (isCamera = false) => {
|
||||
if (widget.preview.paused) {
|
||||
window._mixlab_stopVideo = await shareScreen(
|
||||
isCamera,
|
||||
widget.preview,
|
||||
widget.shareBtn,
|
||||
widget.liveBtn,
|
||||
widget.previewArea
|
||||
)
|
||||
widget.shareBtn.innerText = 'Stop Share'
|
||||
|
||||
if (isCamera) {
|
||||
widget.shareOfWebCamBtn.innerText = 'Stop Share'
|
||||
widget.shareBtn.innerText = 'Stop'
|
||||
} else {
|
||||
widget.shareOfWebCamBtn.innerText = 'Stop'
|
||||
widget.shareBtn.innerText = 'Stop Share'
|
||||
}
|
||||
|
||||
console.log('视频已暂停')
|
||||
if (window._mixlab_stopLive) {
|
||||
@@ -584,12 +700,15 @@ app.registerExtension({
|
||||
window._mixlab_stopLive = null
|
||||
widget.liveBtn.innerText = 'Live Run'
|
||||
}
|
||||
|
||||
setTimeout(() => updateSetAreaDisplay(), 2000)
|
||||
} else {
|
||||
console.log('视频正在播放')
|
||||
if (window._mixlab_stopVideo) {
|
||||
window._mixlab_stopVideo()
|
||||
window._mixlab_stopVideo = null
|
||||
widget.shareBtn.innerText = 'Share Screen'
|
||||
widget.shareOfWebCamBtn.innerText = 'Camera'
|
||||
}
|
||||
if (window._mixlab_stopLive) {
|
||||
window._mixlab_stopLive()
|
||||
@@ -597,6 +716,121 @@ app.registerExtension({
|
||||
widget.liveBtn.innerText = 'Live Run'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateSetAreaDisplay(widget.previewArea, 200, 200)
|
||||
widget.shareOfWebCamBtn.addEventListener('click', async () => {
|
||||
if (!widget.preview.paused) {
|
||||
if (window._mixlab_stopVideo) {
|
||||
window._mixlab_stopVideo()
|
||||
window._mixlab_stopVideo = null
|
||||
widget.shareBtn.innerText = 'Share Screen'
|
||||
widget.shareOfWebCamBtn.innerText = 'Camera'
|
||||
}
|
||||
if (window._mixlab_stopLive) {
|
||||
window._mixlab_stopLive()
|
||||
window._mixlab_stopLive = null
|
||||
widget.liveBtn.innerText = 'Live Run'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let r = await requestCamera()
|
||||
if (r === false) return
|
||||
const devices = await navigator.mediaDevices.enumerateDevices()
|
||||
|
||||
// 查找摄像头设备
|
||||
var cameras = devices.filter(function (device) {
|
||||
// console.log(device)
|
||||
return device.kind === 'videoinput'
|
||||
})
|
||||
|
||||
// 创建 <select> 元素
|
||||
var select = document.createElement('select')
|
||||
|
||||
// 创建默认选项
|
||||
// var defaultOption = document.createElement('option')
|
||||
// defaultOption.text = '请选择摄像头'
|
||||
// defaultOption.disabled = true
|
||||
// defaultOption.selected = true
|
||||
// select.appendChild(defaultOption)
|
||||
|
||||
// 创建每个摄像头设备的选项
|
||||
Array.from(cameras, (camera, i) => {
|
||||
var option = document.createElement('option')
|
||||
option.value = camera.deviceId
|
||||
option.text = camera.label || 'Camera ' + (select.length - 1)
|
||||
if (i === 0) option.selected = true
|
||||
select.appendChild(option)
|
||||
})
|
||||
|
||||
let modal = document.createElement('div')
|
||||
modal.className = 'comfy-modal'
|
||||
modal.style.display = 'flex'
|
||||
|
||||
let modalContent = document.createElement('div')
|
||||
modalContent.className = 'comfy-modal-content'
|
||||
|
||||
let title = document.createElement('p')
|
||||
title.innerText = 'Please select a camera'
|
||||
|
||||
modalContent.appendChild(title)
|
||||
modalContent.appendChild(select)
|
||||
|
||||
let btns = document.createElement('div')
|
||||
btns.style = `display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 24px 0;`
|
||||
|
||||
let btn = document.createElement('button')
|
||||
btn.innerText = 'OK'
|
||||
btn.style = `width: 112px;`
|
||||
|
||||
let closeBtn = document.createElement('button')
|
||||
closeBtn.innerText = 'Cancel'
|
||||
closeBtn.style = `width: 112px;`
|
||||
|
||||
modalContent.appendChild(btns)
|
||||
btns.appendChild(btn)
|
||||
btns.appendChild(closeBtn)
|
||||
|
||||
modal.appendChild(modalContent)
|
||||
document.body.appendChild(modal)
|
||||
|
||||
btn.addEventListener('click', () => {
|
||||
// 获取所选择的选项的索引
|
||||
var selectedIndex = select.selectedIndex
|
||||
|
||||
// 获取所选择的选项的值
|
||||
var selectedValue = select.options[selectedIndex].value
|
||||
if (selectedValue) {
|
||||
const constraints = {
|
||||
audio: false,
|
||||
video: {
|
||||
width: { ideal: 1920, max: 1920 },
|
||||
height: { ideal: 1080, max: 1080 },
|
||||
deviceId: selectedValue
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem(
|
||||
'_mixlab_webcamera_select',
|
||||
JSON.stringify(constraints)
|
||||
)
|
||||
|
||||
toggleShare(true)
|
||||
}
|
||||
|
||||
modal.remove()
|
||||
})
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
modal.remove()
|
||||
})
|
||||
})
|
||||
|
||||
widget.shareBtn.addEventListener('click', async () => {
|
||||
toggleShare()
|
||||
})
|
||||
|
||||
widget.refreshInput.addEventListener('change', async () => {
|
||||
@@ -636,6 +870,8 @@ app.registerExtension({
|
||||
this.addCustomWidget(widget)
|
||||
this.onRemoved = function () {
|
||||
widget.preview.remove()
|
||||
widget.shareDiv.remove()
|
||||
widget.shareOfWebCamBtn.remove()
|
||||
widget.shareBtn.remove()
|
||||
widget.liveBtn.remove()
|
||||
widget.card.remove()
|
||||
@@ -643,22 +879,114 @@ app.registerExtension({
|
||||
widget.previewArea.remove()
|
||||
widget.previewCard.remove()
|
||||
}
|
||||
this.serialize_widgets = false
|
||||
this.serialize_widgets = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function setArea (src) {
|
||||
function updateSetAreaDisplay () {
|
||||
try {
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.width = window._mixlab_screen_webcamVideo.videoWidth
|
||||
canvas.height = window._mixlab_screen_webcamVideo.videoHeight
|
||||
let ctx = canvas.getContext('2d')
|
||||
const lineWidth = 2 // Width of the stroke line
|
||||
const strokeColor = 'red' // Color of the stroke
|
||||
|
||||
// Draw the rectangle
|
||||
ctx.strokeStyle = strokeColor // Set the stroke color
|
||||
ctx.lineWidth = lineWidth // Set the stroke line width
|
||||
|
||||
ctx.fillStyle = 'rgba(255,0,0,0.35)'
|
||||
|
||||
let x = 0,
|
||||
y = 0,
|
||||
width = canvas.width,
|
||||
height = canvas.height
|
||||
|
||||
if (!window._mixlab_share_screen) {
|
||||
let d = getSetAreaData()
|
||||
if (d) {
|
||||
window._mixlab_share_screen = d
|
||||
}
|
||||
}
|
||||
|
||||
if (window._mixlab_share_screen) {
|
||||
x = window._mixlab_share_screen.x
|
||||
y = window._mixlab_share_screen.y
|
||||
width = window._mixlab_share_screen.width
|
||||
height = window._mixlab_share_screen.height
|
||||
}
|
||||
|
||||
ctx.strokeRect(x, y, width, height) // Draw the stroked rectangle
|
||||
ctx.fillRect(x, y, width, height)
|
||||
|
||||
canvas.style.width = '100%'
|
||||
|
||||
let area = graph._nodes
|
||||
.filter(n => n.type === 'ScreenShare')[0]
|
||||
.widgets.filter(w => w.name == 'sreen_share')[0].previewArea
|
||||
|
||||
area.innerHTML = ''
|
||||
area.appendChild(canvas)
|
||||
area.style = `
|
||||
position: absolute;
|
||||
width:100%%;
|
||||
left:0;
|
||||
top:0;
|
||||
`
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
function updateSetAreaData (left, top, width, height, imgWidth, imgHeight) {
|
||||
window._mixlab_share_screen = {
|
||||
x: left,
|
||||
y: top,
|
||||
width,
|
||||
height,
|
||||
imgWidth,
|
||||
imgHeight
|
||||
}
|
||||
localStorage.setItem(
|
||||
'_mixlab_share_screen',
|
||||
JSON.stringify(window._mixlab_share_screen)
|
||||
)
|
||||
}
|
||||
|
||||
function getSetAreaData () {
|
||||
try {
|
||||
let data = JSON.parse(localStorage.getItem('_mixlab_share_screen')) || {}
|
||||
if (data.width === 0 || data.height === 0 || data.width === undefined)
|
||||
return
|
||||
return data
|
||||
} catch (error) {}
|
||||
return
|
||||
}
|
||||
|
||||
async function setArea (src) {
|
||||
let displayHeight = Math.round(window.screen.availHeight * 0.6)
|
||||
let div = document.createElement('div')
|
||||
div.innerHTML = `
|
||||
<div id='ml_overlay' style='position: absolute;top:0'>
|
||||
<img id='ml_video' style='position: absolute; width: 500px; user-select: none; -webkit-user-drag: none;' />
|
||||
<div id='ml_selection' style='position: absolute; border: 2px dashed red; pointer-events: none;'></div>
|
||||
<div id='ml_overlay' style='position: absolute;top:0;background: #251f1fc4;
|
||||
height: 100vh;
|
||||
width: 100%;'>
|
||||
<img id='ml_video' style='position: absolute;
|
||||
height: ${displayHeight}px;user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
outline: 2px solid #eaeaea;
|
||||
box-shadow: 8px 9px 17px #575757;' />
|
||||
<div id='ml_selection' style='position: absolute;
|
||||
border: 2px dashed red;
|
||||
pointer-events: none;'></div>
|
||||
</div>`
|
||||
// document.body.querySelector('#ml_overlay')
|
||||
document.body.appendChild(div)
|
||||
|
||||
let im = await createImage(src)
|
||||
|
||||
let img = div.querySelector('#ml_video')
|
||||
let overlay = div.querySelector('#ml_overlay')
|
||||
let selection = div.querySelector('#ml_selection')
|
||||
@@ -667,10 +995,56 @@ function setArea (src) {
|
||||
// Set video source
|
||||
img.src = src
|
||||
|
||||
// init area
|
||||
const data = getSetAreaData()
|
||||
let x = 0,
|
||||
y = 0,
|
||||
width = (im.naturalWidth * displayHeight) / im.naturalHeight,
|
||||
height = displayHeight
|
||||
let imgWidth = im.naturalWidth
|
||||
let imgHeight = im.naturalHeight
|
||||
// console.log(
|
||||
// '#screen_share::使用上一次选区 selection',
|
||||
// data,
|
||||
// imgWidth,
|
||||
// img.width
|
||||
// )
|
||||
if (
|
||||
data &&
|
||||
data.width > 0 &&
|
||||
data.height > 0 &&
|
||||
data.imgWidth === imgWidth &&
|
||||
data.imgHeight === imgHeight &&
|
||||
data.imgHeight > 0
|
||||
) {
|
||||
// 相同尺寸窗口,恢复选区
|
||||
x = (img.width * data.x) / data.imgWidth
|
||||
y = (img.height * data.y) / data.imgHeight
|
||||
width = (img.width * data.width) / data.imgWidth
|
||||
height = (img.height * data.height) / data.imgHeight
|
||||
// imgWidth = data.imgWidth
|
||||
// imgHeight = data.imgHeight;
|
||||
// console.log('#screen_share::使用上一次选区 selection', x, y, width, height)
|
||||
}
|
||||
|
||||
selection.style.left = x + 'px'
|
||||
selection.style.top = y + 'px'
|
||||
selection.style.width = width + 'px'
|
||||
selection.style.height = height + 'px'
|
||||
|
||||
// Add mouse events
|
||||
img.addEventListener('mousedown', startSelection)
|
||||
img.addEventListener('mousemove', updateSelection)
|
||||
img.addEventListener('mouseup', endSelection)
|
||||
overlay.addEventListener('click', remove)
|
||||
|
||||
function remove () {
|
||||
overlay.removeEventListener('click', remove)
|
||||
img.removeEventListener('mousedown', startSelection)
|
||||
img.removeEventListener('mousemove', updateSelection)
|
||||
img.removeEventListener('mouseup', endSelection)
|
||||
div.remove()
|
||||
}
|
||||
|
||||
function startSelection (event) {
|
||||
if (start == false) {
|
||||
@@ -732,49 +1106,27 @@ function setArea (src) {
|
||||
// console.log('宽度: ' + width)
|
||||
// console.log('高度: ' + height)
|
||||
|
||||
img.removeEventListener('mousedown', startSelection)
|
||||
img.removeEventListener('mousemove', updateSelection)
|
||||
img.removeEventListener('mouseup', endSelection)
|
||||
// img.removeEventListener('mousedown', startSelection)
|
||||
// img.removeEventListener('mousemove', updateSelection)
|
||||
// img.removeEventListener('mouseup', endSelection)
|
||||
|
||||
window._mixlab_screen_x = left
|
||||
window._mixlab_screen_y = top
|
||||
window._mixlab_screen_width = width
|
||||
window._mixlab_screen_height = height
|
||||
// window._mixlab_screen_x = left
|
||||
// window._mixlab_screen_y = top
|
||||
// window._mixlab_screen_width = width
|
||||
// window._mixlab_screen_height = height
|
||||
|
||||
try {
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.width = _mixlab_screen_webcamVideo.videoWidth
|
||||
canvas.height = _mixlab_screen_webcamVideo.videoHeight
|
||||
let ctx = canvas.getContext('2d')
|
||||
const lineWidth = 1 // Width of the stroke line
|
||||
const strokeColor = 'red' // Color of the stroke
|
||||
if (width <= 0 && height <= 0) return remove()
|
||||
|
||||
// Draw the rectangle
|
||||
ctx.strokeStyle = strokeColor // Set the stroke color
|
||||
ctx.lineWidth = lineWidth // Set the stroke line width
|
||||
ctx.strokeRect(
|
||||
_mixlab_screen_x,
|
||||
_mixlab_screen_y,
|
||||
_mixlab_screen_width,
|
||||
_mixlab_screen_height
|
||||
) // Draw the stroked rectangle
|
||||
updateSetAreaData(left, top, width, height, imgWidth, imgHeight)
|
||||
|
||||
canvas.style.width = '100%'
|
||||
updateSetAreaDisplay()
|
||||
|
||||
let area = graph._nodes
|
||||
.filter(n => n.type === 'ScreenShare')[0]
|
||||
.widgets.filter(w => w.name == 'sreen_share')[0].previewArea
|
||||
area.innerHTML = ''
|
||||
area.appendChild(canvas)
|
||||
area.style = `
|
||||
position: absolute;
|
||||
width:100%%;
|
||||
left:0;
|
||||
top:0;
|
||||
`
|
||||
} catch (error) {}
|
||||
createBlobFromVideo(
|
||||
window._mixlab_screen_webcamVideo,
|
||||
!window._mixlab_screen_live
|
||||
)
|
||||
|
||||
div.remove()
|
||||
remove()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,7 +1293,7 @@ app.registerExtension({
|
||||
outline: none;background: black;`
|
||||
|
||||
let div = document.createElement('div')
|
||||
div.style = `display:flex;position: fixed;
|
||||
div.style = `display:flex;position: fixed;flex-direction: column;
|
||||
bottom: 0px;
|
||||
z-index: 9999;
|
||||
left: 0px;
|
||||
@@ -949,6 +1301,8 @@ app.registerExtension({
|
||||
margin: 12px;`
|
||||
|
||||
let inputDiv = document.createElement('div')
|
||||
inputDiv.style = `width: 100%;`
|
||||
|
||||
// inputDiv.style = ``
|
||||
let infoDiv = document.createElement('div')
|
||||
infoDiv.style = ` width: 100%;
|
||||
@@ -1007,10 +1361,10 @@ app.registerExtension({
|
||||
btn.style = `cursor: pointer;height: 24px;margin:4px;
|
||||
color: red;`
|
||||
btn.addEventListener('click', () => {
|
||||
if (input.style.display == 'none') {
|
||||
input.style.display = 'block'
|
||||
if (inputDiv.style.display == 'none') {
|
||||
inputDiv.style.display = 'block'
|
||||
} else {
|
||||
input.style.display = 'none'
|
||||
inputDiv.style.display = 'none'
|
||||
}
|
||||
try {
|
||||
pipWindow.document.querySelector('#info').innerText = ''
|
||||
@@ -1119,16 +1473,48 @@ app.registerExtension({
|
||||
|
||||
pipWindow.document.body.append(widget.preview)
|
||||
pipWindow.document.body.append(div)
|
||||
|
||||
// 滑动条
|
||||
const createSlide = () => {
|
||||
let d = document.createElement('div')
|
||||
d.style = `width: 100%;margin-bottom: 12px;`
|
||||
let range = document.createElement('input')
|
||||
range.type = 'range'
|
||||
d.appendChild(range)
|
||||
return range
|
||||
}
|
||||
|
||||
let slideInp = createSlide()
|
||||
slideInp.addEventListener('change', () => {
|
||||
console.log(~~slideInp.value / 100)
|
||||
window._mixlab_screen_slide_input = ~~slideInp.value / 100
|
||||
try {
|
||||
pipWindow.document.querySelector('#info').innerText =
|
||||
window._mixlab_screen_slide_input;
|
||||
document.querySelector('#queue-button').click()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
})
|
||||
|
||||
// console.log(pipWindow)
|
||||
|
||||
div.appendChild(btnDiv)
|
||||
let fnDiv = document.createElement('div')
|
||||
fnDiv.style = `display: flex;`
|
||||
|
||||
div.appendChild(infoDiv)
|
||||
div.appendChild(fnDiv)
|
||||
|
||||
fnDiv.appendChild(btnDiv)
|
||||
|
||||
btnDiv.appendChild(btn)
|
||||
btnDiv.appendChild(pauseBtn)
|
||||
btnDiv.appendChild(promptFinishBtn)
|
||||
|
||||
// 输入框
|
||||
div.appendChild(inputDiv)
|
||||
inputDiv.appendChild(infoDiv)
|
||||
fnDiv.appendChild(inputDiv)
|
||||
inputDiv.appendChild(slideInp)
|
||||
|
||||
inputDiv.appendChild(input)
|
||||
|
||||
input.addEventListener('input', () => {
|
||||
@@ -1179,7 +1565,7 @@ app.registerExtension({
|
||||
widget.card.remove()
|
||||
widget.PictureInPicture.remove()
|
||||
}
|
||||
this.serialize_widgets = false
|
||||
this.serialize_widgets = true
|
||||
}
|
||||
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
@@ -1628,7 +2014,7 @@ const node = {
|
||||
},
|
||||
async setup (a) {
|
||||
for (const node of app.graph._nodes) {
|
||||
console.log('#setup', node)
|
||||
// console.log('#setup', node)
|
||||
if (node.type === 'RandomPrompt') {
|
||||
updateUI(node)
|
||||
}
|
||||
@@ -169,7 +169,7 @@ app.registerExtension({
|
||||
this.onRemoved = function () {
|
||||
// widget.card.remove()
|
||||
}
|
||||
this.serialize_widgets = false
|
||||
this.serialize_widgets = true
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
-99
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"last_node_id": 34,
|
||||
"last_link_id": 35,
|
||||
"last_node_id": 47,
|
||||
"last_link_id": 46,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 27,
|
||||
@@ -14,7 +14,7 @@
|
||||
"1": 164.31304931640625
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 35,
|
||||
"link": 46,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
@@ -136,7 +136,7 @@
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
264070254513477,
|
||||
971428736321335,
|
||||
"randomize",
|
||||
15,
|
||||
8,
|
||||
@@ -294,26 +294,26 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"type": "SessionHistory",
|
||||
"id": 44,
|
||||
"type": "ShowTextForGPT",
|
||||
"pos": [
|
||||
1300,
|
||||
430
|
||||
],
|
||||
"size": [
|
||||
580.1640810546876,
|
||||
223.1105875244142
|
||||
1171,
|
||||
425
|
||||
],
|
||||
"size": {
|
||||
"0": 432.46002197265625,
|
||||
"1": 264.40771484375
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "session_history",
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 33,
|
||||
"link": 44,
|
||||
"widget": {
|
||||
"name": "session_history"
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -322,38 +322,37 @@
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 6,
|
||||
"slot_index": 0
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SessionHistory"
|
||||
"Node name for S&R": "ShowTextForGPT"
|
||||
},
|
||||
"widgets_values": [
|
||||
"[\n {\n \"role\": \"user\",\n \"content\": \"黑客与画家\"\n },\n {\n \"role\": \"assistant\",\n \"content\": \"\\\"Hacker and Painter\\\" is a popular Chinese comic series written and illustrated by Cheng先辈, which has gained a large following worldwide.\\n\\nThe series revolves around the lives of two main characters, a young hacker and an artist, who embark on a journey of self-discovery and personal growth. Set in a futuristic, dystopian world, the story combines elements of science fiction, technology, and action with a touch of humor and satire.\\n\\nThe art style in \\\"Hacker and Painter\\\" is a mix of sci-fi and traditional Chinese ink painting, with bold lines, vibrant colors, and intricate details. Cheng先辈 employs a unique painting technique, using watercolor washes and ink to create a dynamic, expressive, and visually striking visual style.\\n\\nThe artist's use of photography and various camera angles adds an extra layer of depth to the storytelling, allowing the viewer to experience the world from different perspectives and gain a deeper understanding of the characters' emotions and motivations.\\n\\nLighting plays a significant role in the series, with the use of dramatic, contrasting light sources adding to the intensity and emotion of various scenes. Cheng先辈 expertly utilizes lighting to enhance the mood and setting, drawing the audience into the world of \\\"Hacker and Painter\\\" and making them feel like they are part of the action.\\n\\nOverall, \\\"Hacker and Painter\\\" is a visually stunning and thought-provoking series that combines the best of science fiction, action, and art, making it a must-read for fans of all ages.\"\n }\n]"
|
||||
"[\n {\n \"role\": \"system\",\n \"content\": \"You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"\"\n }\n]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"type": "SessionHistory",
|
||||
"id": 43,
|
||||
"type": "ShowTextForGPT",
|
||||
"pos": [
|
||||
1300,
|
||||
230
|
||||
],
|
||||
"size": [
|
||||
562.8610810546875,
|
||||
125.32558752441412
|
||||
1166,
|
||||
740
|
||||
],
|
||||
"size": {
|
||||
"0": 424.0079650878906,
|
||||
"1": 430.6391296386719
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "session_history",
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 34,
|
||||
"link": 45,
|
||||
"widget": {
|
||||
"name": "session_history"
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -361,100 +360,114 @@
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
35
|
||||
],
|
||||
"shape": 6,
|
||||
"slot_index": 0
|
||||
"links": null,
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SessionHistory"
|
||||
"Node name for S&R": "ShowTextForGPT"
|
||||
},
|
||||
"widgets_values": [
|
||||
"\"Hacker and Painter\" is a popular Chinese comic series written and illustrated by Cheng先辈, which has gained a large following worldwide.\n\nThe series revolves around the lives of two main characters, a young hacker and an artist, who embark on a journey of self-discovery and personal growth. Set in a futuristic, dystopian world, the story combines elements of science fiction, technology, and action with a touch of humor and satire.\n\nThe art style in \"Hacker and Painter\" is a mix of sci-fi and traditional Chinese ink painting, with bold lines, vibrant colors, and intricate details. Cheng先辈 employs a unique painting technique, using watercolor washes and ink to create a dynamic, expressive, and visually striking visual style.\n\nThe artist's use of photography and various camera angles adds an extra layer of depth to the storytelling, allowing the viewer to experience the world from different perspectives and gain a deeper understanding of the characters' emotions and motivations.\n\nLighting plays a significant role in the series, with the use of dramatic, contrasting light sources adding to the intensity and emotion of various scenes. Cheng先辈 expertly utilizes lighting to enhance the mood and setting, drawing the audience into the world of \"Hacker and Painter\" and making them feel like they are part of the action.\n\nOverall, \"Hacker and Painter\" is a visually stunning and thought-provoking series that combines the best of science fiction, action, and art, making it a must-read for fans of all ages."
|
||||
"[\n {\n \"role\": \"user\",\n \"content\": \"\"\n },\n {\n \"role\": \"assistant\",\n \"content\": \"I'm sorry, I'm ChatGLM3-6B, not ChatGPT. I am a language model jointly trained by Tsinghua University KEG Lab and Zhipu AI Company.\"\n }\n]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"type": "PrimitiveNode",
|
||||
"id": 45,
|
||||
"type": "ShowTextForGPT",
|
||||
"pos": [
|
||||
1314,
|
||||
1075
|
||||
1092,
|
||||
262
|
||||
],
|
||||
"size": {
|
||||
"0": 571.9803466796875,
|
||||
"1": 100.6700210571289
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
32
|
||||
],
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"title": "prompt",
|
||||
"properties": {},
|
||||
"widgets_values": [
|
||||
"黑客与画家"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "ChatGPT",
|
||||
"pos": [
|
||||
1300,
|
||||
720
|
||||
],
|
||||
"size": {
|
||||
"0": 586.7649536132812,
|
||||
"1": 301.5857849121094
|
||||
"0": 635.8358154296875,
|
||||
"1": 101.46092224121094
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 32,
|
||||
"link": 43,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
},
|
||||
"slot_index": 0
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ShowTextForGPT"
|
||||
},
|
||||
"widgets_values": [
|
||||
"I'm sorry, I'm ChatGLM3-6B, not ChatGPT. I am a language model jointly trained by Tsinghua University KEG Lab and Zhipu AI Company."
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"type": "ChatGPTOpenAI",
|
||||
"pos": [
|
||||
585,
|
||||
306
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 342
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
34
|
||||
43,
|
||||
46
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "JSON",
|
||||
"name": "messages",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
33
|
||||
44
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "session_history",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
45
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ChatGPT"
|
||||
}
|
||||
"Node name for S&R": "ChatGPTOpenAI"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.",
|
||||
"gpt-3.5-turbo-16k",
|
||||
2220,
|
||||
"randomize",
|
||||
1,
|
||||
null
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
@@ -579,32 +592,32 @@
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
32,
|
||||
32,
|
||||
43,
|
||||
47,
|
||||
0,
|
||||
10,
|
||||
45,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
33,
|
||||
10,
|
||||
44,
|
||||
47,
|
||||
1,
|
||||
33,
|
||||
44,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
34,
|
||||
10,
|
||||
0,
|
||||
34,
|
||||
45,
|
||||
47,
|
||||
2,
|
||||
43,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
35,
|
||||
34,
|
||||
46,
|
||||
47,
|
||||
0,
|
||||
27,
|
||||
1,
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
{
|
||||
"last_node_id": 5,
|
||||
"last_link_id": 4,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 4,
|
||||
"type": "ChatGPTOpenAI",
|
||||
"pos": [
|
||||
-512,
|
||||
-236
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 342
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "session_history",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ChatGPTOpenAI"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
"描述一个科幻的场景",
|
||||
"You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.",
|
||||
"gpt-35-turbo",
|
||||
6933,
|
||||
"randomize",
|
||||
1,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "ChatGPTOpenAI",
|
||||
"pos": [
|
||||
-36,
|
||||
-234
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 342
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 2,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "session_history",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ChatGPTOpenAI"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"增加丰富的细节和光影,摄影技巧,镜头语言,材质肌理",
|
||||
"gpt-3.5-turbo",
|
||||
2836,
|
||||
"randomize",
|
||||
1,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "ChatGPTOpenAI",
|
||||
"pos": [
|
||||
-30,
|
||||
183
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 342
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 3,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
4
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "session_history",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ChatGPTOpenAI"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"翻译成英文,并按照格式输出: 画面、主题、细节、灯光、氛围、艺术家、其他",
|
||||
"gpt-3.5-turbo",
|
||||
1085,
|
||||
"randomize",
|
||||
1,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "ShowTextForGPT",
|
||||
"pos": [
|
||||
447,
|
||||
-229
|
||||
],
|
||||
"size": [
|
||||
503.79851499517997,
|
||||
356.0560985581077
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 4,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ShowTextForGPT"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Picture: The picture is composed of carefully chosen elements, capturing the subject matter in a visually striking way.\n\nTheme: The theme of the photograph could vary, from capturing nature's beauty to showcasing urban landscapes, human emotions, or abstract concepts.\n\nDetails: The photograph captures intricate details, bringing attention to the subject's textures, colors, shapes, and patterns.\n\nLighting: The photographer manipulates lighting, using techniques like natural light, dramatic shadows, or artificial lighting to enhance the mood and atmosphere of the photograph.\n\nAmbiance: The photograph evokes a specific ambiance or mood, whether it's serene, mysterious, joyful, melancholic, or any other emotional response.\n\nArtist: The photographer skillfully crafts the image, demonstrating their artistic vision, technical skills, and creative expression through the composition, framing, and post-processing choices.\n\nOthers: Apart from the elements mentioned above, the photograph may also incorporate other creative techniques like long exposure, multiple exposures, color grading, or unconventional perspectives to create a unique and captivating image.\n\nIn the future, as technology and imagination continue to advance, photography will likely continue to evolve and innovate, offering even more realistic and awe-inspiring visual experiences for humans."
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
2,
|
||||
4,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
4,
|
||||
5,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,724 @@
|
||||
{
|
||||
"last_node_id": 23,
|
||||
"last_link_id": 54,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 7,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
495,
|
||||
307
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 33
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
29
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
504,
|
||||
33
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 32
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 48,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
51
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "LoraLoader",
|
||||
"pos": [
|
||||
112,
|
||||
5
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 126
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 31
|
||||
},
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 45
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
44
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoraLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"lcm-lora-sdv1-5.safetensors",
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "VAEEncode",
|
||||
"pos": [
|
||||
563,
|
||||
663
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pixels",
|
||||
"type": "IMAGE",
|
||||
"link": 52
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 53
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
54
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEEncode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
1085,
|
||||
49
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 44
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 51
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 29
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 54
|
||||
},
|
||||
{
|
||||
"name": "denoise",
|
||||
"type": "FLOAT",
|
||||
"link": 49,
|
||||
"widget": {
|
||||
"name": "denoise"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
35
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
758428944049342,
|
||||
"fixed",
|
||||
4,
|
||||
1.6,
|
||||
"lcm",
|
||||
"karras",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "VAEDecode",
|
||||
"pos": [
|
||||
1451,
|
||||
59
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 35
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 34
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
41
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEDecode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"type": "FloatingVideo",
|
||||
"pos": [
|
||||
1464,
|
||||
243
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 41
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "FloatingVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "CheckpointLoaderSimple",
|
||||
"pos": [
|
||||
80,
|
||||
238
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 98
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
31
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": [
|
||||
32,
|
||||
33,
|
||||
45
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"links": [
|
||||
34,
|
||||
53
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CheckpointLoaderSimple"
|
||||
},
|
||||
"widgets_values": [
|
||||
"deliberate_v2.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"type": "ScreenShare",
|
||||
"pos": [
|
||||
103,
|
||||
412
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 146
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
46,
|
||||
52
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
48
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "FLOAT",
|
||||
"type": "FLOAT",
|
||||
"links": [
|
||||
49
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ScreenShare"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
-501,
|
||||
918
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 46
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
3,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
5,
|
||||
8,
|
||||
0,
|
||||
5,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
6,
|
||||
9,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
7,
|
||||
10,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
8,
|
||||
10,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
9,
|
||||
5,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
10,
|
||||
10,
|
||||
2,
|
||||
11,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
11,
|
||||
6,
|
||||
1,
|
||||
7,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
12,
|
||||
6,
|
||||
1,
|
||||
8,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
14,
|
||||
11,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
17,
|
||||
1,
|
||||
2,
|
||||
7,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
18,
|
||||
7,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
19,
|
||||
15,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
20,
|
||||
16,
|
||||
0,
|
||||
15,
|
||||
1,
|
||||
"CONTROL_NET"
|
||||
],
|
||||
[
|
||||
24,
|
||||
1,
|
||||
0,
|
||||
18,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
25,
|
||||
18,
|
||||
0,
|
||||
15,
|
||||
2,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
29,
|
||||
7,
|
||||
0,
|
||||
5,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
31,
|
||||
10,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
32,
|
||||
10,
|
||||
1,
|
||||
8,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
33,
|
||||
10,
|
||||
1,
|
||||
7,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
34,
|
||||
10,
|
||||
2,
|
||||
11,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
35,
|
||||
5,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
41,
|
||||
11,
|
||||
0,
|
||||
20,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
44,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
45,
|
||||
10,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
46,
|
||||
22,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
48,
|
||||
22,
|
||||
1,
|
||||
8,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
49,
|
||||
22,
|
||||
2,
|
||||
5,
|
||||
4,
|
||||
"FLOAT"
|
||||
],
|
||||
[
|
||||
51,
|
||||
8,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
52,
|
||||
22,
|
||||
0,
|
||||
23,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
53,
|
||||
10,
|
||||
2,
|
||||
23,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
54,
|
||||
23,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
"LATENT"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user