diff --git a/js/ChildWorkflowNodes.js b/js/ChildWorkflowNodes.js index 0803773..b682ce1 100644 --- a/js/ChildWorkflowNodes.js +++ b/js/ChildWorkflowNodes.js @@ -40,12 +40,12 @@ app.registerExtension({ this.setProperty("paramList", []) this.setProperty("workflow", {}) let thisNode = this - const widget = this.widgets.find(w => w.name === "workflowFile"); this.addDOMWidget('childJson',"list",$el('span.hidden',{style:{"word-wrap": "break-word"}}),{ getValue(){ return JSON.stringify(thisNode.properties['workflow']) } }); + const widget = this.widgets.find(w => w.name === "workflowFile"); widget.callback = async (value) => { if (value) { let props = await getWorkflow(value); diff --git a/js/ChildWorkflowParameters.js b/js/ChildWorkflowParameters.js index a13072b..a83c3c2 100644 --- a/js/ChildWorkflowParameters.js +++ b/js/ChildWorkflowParameters.js @@ -79,8 +79,8 @@ function get_position_style(ctx, widget_width, y, node_height) { return { transformOrigin: '0 0', transform: transform, - left: `50px`, - top: `35px`, + left: `0px`, + top: `0px`, position: "absolute", maxWidth: `${widget_width - MARGIN*2}px`, maxHeight: `${node_height - MARGIN*2}px`, // we're assuming we have the whole height of the node diff --git a/py/OpenAiPrompt.py b/py/OpenAiPrompt.py index a9c2fa6..0cde8bc 100644 --- a/py/OpenAiPrompt.py +++ b/py/OpenAiPrompt.py @@ -1,5 +1,15 @@ import json from openai import OpenAI +import base64 +from PIL import Image +import io +import numpy as np +from lam_tools import tensor2pil,pil2tensor + +def encode_image(image_path: str) -> str: + """将图像编码为 base64 字符串""" + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') class OpenAiPrompt: """ @@ -19,12 +29,13 @@ class OpenAiPrompt: "text": ("STRING", {"multiline": True}), }, "optional": { - "messages":("LIST",) + "messages":("LIST",), + "images": ("IMAGE,STRING", ) } } - RETURN_TYPES = ("STRING",) - RETURN_NAMES = ("结果",) + RETURN_TYPES = ("STRING","LIST",) + RETURN_NAMES = ("结果","messages",) FUNCTION = "translate" @@ -32,15 +43,30 @@ class OpenAiPrompt: CATEGORY = "lam" - def translate(self, server_url,api_key,model_name,system_prompt,text,messages=None): + def translate(self, server_url,api_key,model_name,system_prompt,text,messages=None,images=None): client = OpenAI(api_key=api_key,base_url=server_url) if messages is None: messages = [] + if system_prompt and len(system_prompt.strip())>0: messages.append({"role": "system", "content": system_prompt}) - messages.append({"role": "user", "content": text}) - completion = client.chat.completions.create(model=model_name,messages=messages, - top_p=0.8, - temperature=0.7) + if images!=None: + content=[] + content.append({"type": "text", "text": text}) + if isinstance(images, str): + # 图像理解示例 + image_base64 = encode_image(images) + content.append({"type": "image_url", "image_url": {"url":f"data:image/jpeg;base64,{image_base64}"}}) + else: + img = tensor2pil(images) + output = io.BytesIO() + img.save(output, format="JPEG") + image_base64 = base64.b64encode(output.getvalue()).decode('utf-8') + content.append({"type": "image_url", "image_url": {"url":f"data:image/jpeg;base64,{image_base64}"}}) + messages.append({"role": "user", "content": content}) + else: + messages.append({"role": "user", "content": text}) + + completion = client.chat.completions.create(model=model_name,messages=messages,top_p=0.8,temperature=0.7) messages.append({"role": "assistant", "content": completion.choices[0].message.content}) return (completion.choices[0].message.content,messages,)