diff --git a/__init__.py b/__init__.py index dc81bf8..1ef33c2 100644 --- a/__init__.py +++ b/__init__.py @@ -1,10 +1,12 @@ from .node import * +from .gpt4 import * NODE_CLASS_MAPPINGS = { "Image Blending Mode Mask" : Image_Blending_Mode_Mask, "Load Image With Bool" : LoadImage_Bool, "IPAdapter Mad Scientist Weight_Type" : IPAdapter_Mad_Scientist_weight_type, - "IPAdapter FaceID With Bool" : IPAdapter_FaceID_Bool + "IPAdapter FaceID With Bool" : IPAdapter_FaceID_Bool, + "GPT4 WWL" : GPT4_WWL } diff --git a/gpt4.py b/gpt4.py new file mode 100644 index 0000000..3e76e05 --- /dev/null +++ b/gpt4.py @@ -0,0 +1,99 @@ +import yaml +import openai +from .settings import load_settings + +class GPT4_WWL: + + + @classmethod + def INPUT_TYPES(s): + all_settings = load_settings() + default_user_prompt = all_settings['example_user_prompt'] + available_apis = [a for a in all_settings['openai_compatible']] + default_model = all_settings['openai_compatible']['default']['model'] + + return { + "required": { + "api": (available_apis, { + "default": "default" + }), + "model": (default_model, + {"default": "gpt-4-1106-preview"}), + "system_prompt": ("STRING", + { + "default": ("act as prompt generator, I will give you text and you describe an image that matches that text in details, " + "answer with one response only.if I input in Chinese to communicate with you, but it is crucial that your response be in English."), + "multiline": True, "dynamicPrompts": False + }), + + "user_prompt": ("STRING", { + "multiline": True, + "default": default_user_prompt + }), + "temperature": ("FLOAT", { + "default": 0.7, "min": 0.0, "max": 2.0, "step": 0.01, + }), + }, + "optional": { + "top_p": ("FLOAT", { + "default": 1.0, "min": 0.001, "max": 1.0, "step": 0.01, + }), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("gpt_response",) + FUNCTION = "generate" + CATEGORY = "WWL" + + def generate(self, api, model: str, temperature: float | None = None, + top_p: float | None = None, user_prompt="", system_prompt=""): + try: + system_content = system_prompt + user_content = user_prompt + + messages = [ + {'role': 'user', 'content': user_content}, + {'role': 'system', 'content': system_content} + ] + + + response = self.gpt_openai( + messages=messages, + model=model, + temperature=temperature, + ) + return (response,) + except Exception as e: + print(f"Error occurred: {e}") + return (system_content,) + + def gpt_openai(self, messages, model, max_tokens=None, temperature=1, silent=False): + settings = load_settings() + api_settings = settings['openai_compatible']['default'] + + APP_ID = api_settings['app_id'] + APP_KEY = api_settings['api_key'] + END_POINT = api_settings['base_url'] + + + client = openai.OpenAI( + api_key=f'{APP_ID}.{APP_KEY}', + base_url=END_POINT, + ) + + data = { + "model": model, + "messages": messages, + "temperature": temperature, + } + if max_tokens: + data.update({"max_tokens": max_tokens}) + + if not silent: + print("gpt data: {}".format(data)) + + response = client.chat.completions.create(**data) + + return (f'{response.choices[0].message.content}',) + diff --git a/node.py b/node.py index 88c766e..e8cf816 100644 --- a/node.py +++ b/node.py @@ -198,7 +198,7 @@ class Image_Blending_Mode_Mask: RETURN_NAMES = ("image",) FUNCTION = "image_blending_mode_mask" - CATEGORY = "Image/Image" + CATEGORY = "WWL" def image_blending_mode_mask(self, image_a, image_b, mode='add', blend_percentage=1.0, mask=None): @@ -269,6 +269,7 @@ class LoadImage_Bool: RETURN_TYPES = ("IMAGE", "MASK", "BOOLEAN") FUNCTION = "load_image" + CATEGORY = "WWL" def load_image(self, image=DEFAULT_IMAGE_NAME): if not image or image == LoadImage_Bool.DEFAULT_IMAGE_NAME: @@ -378,7 +379,7 @@ class IPAdapter_Mad_Scientist_weight_type: RETURN_TYPES = ("STRING",) RETURN_NAMES = ("layer_weights",) FUNCTION = "generate_prompt" - CATEGORY = "ipadapter" + CATEGORY = "WWL" def generate_prompt(self, **kwargs): prompt_parts = {str(i): 0.0 for i in range(0, 12)} @@ -431,6 +432,7 @@ class IPAdapter_FaceID_Bool(): RETURN_TYPES = ("MODEL","IMAGE","BOOLEAN") RETURN_NAMES = ("MODEL", "face_image", "bool",) FUNCTION = "apply_ipadapter_bool" + CATEGORY = "WWL" def apply_ipadapter_bool(self, model, ipadapter, start_at=0.0, end_at=1.0, weight=1.0, weight_style=1.0, weight_composition=1.0, expand_style=False, weight_type="linear", combine_embeds="concat", weight_faceidv2=None, image=None, image_style=None, image_composition=None, image_negative=None, clip_vision=None, attn_mask=None, insightface=None, embeds_scaling='V only', layer_weights=None, ipadapter_params=None, encode_batch_size=0, style_boost=None, composition_boost=None, enhance_tiles=1, enhance_ratio=1.0): try: diff --git a/requirements.txt b/requirements.txt index c243da3..c01ca6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ numpy -pilgram \ No newline at end of file +pilgram +openai \ No newline at end of file diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..869f39c --- /dev/null +++ b/settings.py @@ -0,0 +1,45 @@ +import os +import pathlib + +import yaml + +DEFAULT_SETTINGS = { + "cyberdolphin": { + "openai": { + "app_id": "NO ID", + "api_key": "NO API KEY", + "model": "gpt-4-1106-preview" + }, + "openai_compatible": { + "app_id": "NO ID", + "api_key": "your_key", + "api_base": 'http://ip:3200' + }, + "prompts": { + "example_user_prompt": "{Camel|goldfish|glowing orb},{moss|tree|fern|balloon},{space station|garden shed|glowing laser sword|bowl of petunias|orange taxi|neon sign}", + "default_prompt": { + "system": "You are deeply artistic, understanding of concepts like composition, pallete and color theory, and image psychology.", + "prefix": "Do use objective language. Do not add narrative. Do describe objects visually and in context. \ + Do not describe the purpose of the objects, or any other explanations \"", + "suffix": '"' + } + } + } +} + + +def load_settings(): + path = os.path.join(os.path.dirname(__file__), "settings.yaml") + file_path = pathlib.Path(path) + if not file_path.exists(): + return DEFAULT_SETTINGS['cyberdolphin'] + + with open(path) as settings: + the_yaml = yaml.safe_load(settings) + # print(f'LOADED: {the_yaml["cyberdolphin"]}') + return the_yaml['cyberdolphin'] + + +def api_settings(section: str = "openai"): + openai_settings = load_settings()['openai_compatible'][section] + return openai_settings['api_base'], openai_settings['api_key'], openai_settings['organisation'] diff --git a/settings.yaml b/settings.yaml new file mode 100644 index 0000000..20b9f01 --- /dev/null +++ b/settings.yaml @@ -0,0 +1,45 @@ +cyberdolphin: + openai_compatible: + default: + organisation: "NONE" + app_id: "xxxxxxx" + api_key: "xxxxxxxx" + base_url: "https://xxxxxxx.com" + model: + - "gpt-4-1106-preview" + - "gpt-4-0125-preview" + - "gpt-4" + + + example_user_prompt: "your user prompt here" + prompt_templates: +# the user prompt is by default a list of objects, such as what might be returned from a resnet node + + default: + system: >- + act as prompt generator ,i will give you text and you describe an image that match that text in details, answer with one response only.I input in Chinese to communicate with you, but it is crucial that your response be in English. + prefix: >- + make a list of the things you see. do not explain why you see them. + do explain what the things you see are doing. do explain where they are. + do not explain their purpose, + do not say anything other than the list of things you see. + do use purely objective language: do not say "I see a..." but instead say "there is a..." + SO: + When I provide the list " + suffix: >- + ", + what is this scene - + do not simply repeat the list, do not say "when I provide the list" or similar just project the description. + describe what you see in your mind. + + + prompt_two_example: + system: >- + You are deeply artistic, understanding of concepts like composition, palette and color theory, and image psychology. + prefix: >- + describe a scene using the following list of objects: " + suffix: >- + " - there are many things + and you must list them using a maximum of 25 words. be clear and specific. + use present tense, objective language: do not say, "I see ..." rather say, "there is ..." +