mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-12-29 00:00:53 +08:00
Merge branch 'master' into v3-improvements
This commit is contained in:
commit
cd3790a7ed
@ -212,6 +212,8 @@ Python 3.14 works but you may encounter issues with the torch compile node. The
|
|||||||
|
|
||||||
Python 3.13 is very well supported. If you have trouble with some custom node dependencies on 3.13 you can try 3.12
|
Python 3.13 is very well supported. If you have trouble with some custom node dependencies on 3.13 you can try 3.12
|
||||||
|
|
||||||
|
torch 2.4 and above is supported but some features might only work on newer versions. We generally recommend using the latest major version of pytorch unless it is less than 2 weeks old.
|
||||||
|
|
||||||
### Instructions:
|
### Instructions:
|
||||||
|
|
||||||
Git clone this repo.
|
Git clone this repo.
|
||||||
|
|||||||
@ -133,6 +133,7 @@ class GeminiImageGenerateContentRequest(BaseModel):
|
|||||||
systemInstruction: GeminiSystemInstructionContent | None = Field(None)
|
systemInstruction: GeminiSystemInstructionContent | None = Field(None)
|
||||||
tools: list[GeminiTool] | None = Field(None)
|
tools: list[GeminiTool] | None = Field(None)
|
||||||
videoMetadata: GeminiVideoMetadata | None = Field(None)
|
videoMetadata: GeminiVideoMetadata | None = Field(None)
|
||||||
|
uploadImagesToStorage: bool = Field(True)
|
||||||
|
|
||||||
|
|
||||||
class GeminiGenerateContentRequest(BaseModel):
|
class GeminiGenerateContentRequest(BaseModel):
|
||||||
|
|||||||
@ -34,6 +34,7 @@ from comfy_api_nodes.util import (
|
|||||||
ApiEndpoint,
|
ApiEndpoint,
|
||||||
audio_to_base64_string,
|
audio_to_base64_string,
|
||||||
bytesio_to_image_tensor,
|
bytesio_to_image_tensor,
|
||||||
|
download_url_to_image_tensor,
|
||||||
get_number_of_images,
|
get_number_of_images,
|
||||||
sync_op,
|
sync_op,
|
||||||
tensor_to_base64_string,
|
tensor_to_base64_string,
|
||||||
@ -141,9 +142,11 @@ def get_parts_by_type(response: GeminiGenerateContentResponse, part_type: Litera
|
|||||||
)
|
)
|
||||||
parts = []
|
parts = []
|
||||||
for part in response.candidates[0].content.parts:
|
for part in response.candidates[0].content.parts:
|
||||||
if part_type == "text" and hasattr(part, "text") and part.text:
|
if part_type == "text" and part.text:
|
||||||
parts.append(part)
|
parts.append(part)
|
||||||
elif hasattr(part, "inlineData") and part.inlineData and part.inlineData.mimeType == part_type:
|
elif part.inlineData and part.inlineData.mimeType == part_type:
|
||||||
|
parts.append(part)
|
||||||
|
elif part.fileData and part.fileData.mimeType == part_type:
|
||||||
parts.append(part)
|
parts.append(part)
|
||||||
# Skip parts that don't match the requested type
|
# Skip parts that don't match the requested type
|
||||||
return parts
|
return parts
|
||||||
@ -163,12 +166,15 @@ def get_text_from_response(response: GeminiGenerateContentResponse) -> str:
|
|||||||
return "\n".join([part.text for part in parts])
|
return "\n".join([part.text for part in parts])
|
||||||
|
|
||||||
|
|
||||||
def get_image_from_response(response: GeminiGenerateContentResponse) -> Input.Image:
|
async def get_image_from_response(response: GeminiGenerateContentResponse) -> Input.Image:
|
||||||
image_tensors: list[Input.Image] = []
|
image_tensors: list[Input.Image] = []
|
||||||
parts = get_parts_by_type(response, "image/png")
|
parts = get_parts_by_type(response, "image/png")
|
||||||
for part in parts:
|
for part in parts:
|
||||||
image_data = base64.b64decode(part.inlineData.data)
|
if part.inlineData:
|
||||||
returned_image = bytesio_to_image_tensor(BytesIO(image_data))
|
image_data = base64.b64decode(part.inlineData.data)
|
||||||
|
returned_image = bytesio_to_image_tensor(BytesIO(image_data))
|
||||||
|
else:
|
||||||
|
returned_image = await download_url_to_image_tensor(part.fileData.fileUri)
|
||||||
image_tensors.append(returned_image)
|
image_tensors.append(returned_image)
|
||||||
if len(image_tensors) == 0:
|
if len(image_tensors) == 0:
|
||||||
return torch.zeros((1, 1024, 1024, 4))
|
return torch.zeros((1, 1024, 1024, 4))
|
||||||
@ -596,7 +602,7 @@ class GeminiImage(IO.ComfyNode):
|
|||||||
|
|
||||||
response = await sync_op(
|
response = await sync_op(
|
||||||
cls,
|
cls,
|
||||||
endpoint=ApiEndpoint(path=f"{GEMINI_BASE_ENDPOINT}/{model}", method="POST"),
|
ApiEndpoint(path=f"/proxy/vertexai/gemini/{model}", method="POST"),
|
||||||
data=GeminiImageGenerateContentRequest(
|
data=GeminiImageGenerateContentRequest(
|
||||||
contents=[
|
contents=[
|
||||||
GeminiContent(role=GeminiRole.user, parts=parts),
|
GeminiContent(role=GeminiRole.user, parts=parts),
|
||||||
@ -610,7 +616,7 @@ class GeminiImage(IO.ComfyNode):
|
|||||||
response_model=GeminiGenerateContentResponse,
|
response_model=GeminiGenerateContentResponse,
|
||||||
price_extractor=calculate_tokens_price,
|
price_extractor=calculate_tokens_price,
|
||||||
)
|
)
|
||||||
return IO.NodeOutput(get_image_from_response(response), get_text_from_response(response))
|
return IO.NodeOutput(await get_image_from_response(response), get_text_from_response(response))
|
||||||
|
|
||||||
|
|
||||||
class GeminiImage2(IO.ComfyNode):
|
class GeminiImage2(IO.ComfyNode):
|
||||||
@ -729,7 +735,7 @@ class GeminiImage2(IO.ComfyNode):
|
|||||||
|
|
||||||
response = await sync_op(
|
response = await sync_op(
|
||||||
cls,
|
cls,
|
||||||
ApiEndpoint(path=f"{GEMINI_BASE_ENDPOINT}/{model}", method="POST"),
|
ApiEndpoint(path=f"/proxy/vertexai/gemini/{model}", method="POST"),
|
||||||
data=GeminiImageGenerateContentRequest(
|
data=GeminiImageGenerateContentRequest(
|
||||||
contents=[
|
contents=[
|
||||||
GeminiContent(role=GeminiRole.user, parts=parts),
|
GeminiContent(role=GeminiRole.user, parts=parts),
|
||||||
@ -743,7 +749,7 @@ class GeminiImage2(IO.ComfyNode):
|
|||||||
response_model=GeminiGenerateContentResponse,
|
response_model=GeminiGenerateContentResponse,
|
||||||
price_extractor=calculate_tokens_price,
|
price_extractor=calculate_tokens_price,
|
||||||
)
|
)
|
||||||
return IO.NodeOutput(get_image_from_response(response), get_text_from_response(response))
|
return IO.NodeOutput(await get_image_from_response(response), get_text_from_response(response))
|
||||||
|
|
||||||
|
|
||||||
class GeminiExtension(ComfyExtension):
|
class GeminiExtension(ComfyExtension):
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import comfy.utils
|
|||||||
import node_helpers
|
import node_helpers
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
from comfy_api.latest import ComfyExtension, io
|
from comfy_api.latest import ComfyExtension, io
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
class BasicScheduler(io.ComfyNode):
|
class BasicScheduler(io.ComfyNode):
|
||||||
@ -1013,6 +1014,25 @@ class AddNoise(io.ComfyNode):
|
|||||||
|
|
||||||
add_noise = execute
|
add_noise = execute
|
||||||
|
|
||||||
|
class ManualSigmas(io.ComfyNode):
|
||||||
|
@classmethod
|
||||||
|
def define_schema(cls):
|
||||||
|
return io.Schema(
|
||||||
|
node_id="ManualSigmas",
|
||||||
|
category="_for_testing/custom_sampling",
|
||||||
|
is_experimental=True,
|
||||||
|
inputs=[
|
||||||
|
io.String.Input("sigmas", default="1, 0.5", multiline=False)
|
||||||
|
],
|
||||||
|
outputs=[io.Sigmas.Output()]
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def execute(cls, sigmas) -> io.NodeOutput:
|
||||||
|
sigmas = re.findall(r"[-+]?(?:\d*\.*\d+)", sigmas)
|
||||||
|
sigmas = [float(i) for i in sigmas]
|
||||||
|
sigmas = torch.FloatTensor(sigmas)
|
||||||
|
return io.NodeOutput(sigmas)
|
||||||
|
|
||||||
class CustomSamplersExtension(ComfyExtension):
|
class CustomSamplersExtension(ComfyExtension):
|
||||||
@override
|
@override
|
||||||
@ -1052,6 +1072,7 @@ class CustomSamplersExtension(ComfyExtension):
|
|||||||
DisableNoise,
|
DisableNoise,
|
||||||
AddNoise,
|
AddNoise,
|
||||||
SamplerCustomAdvanced,
|
SamplerCustomAdvanced,
|
||||||
|
ManualSigmas,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
# This file is automatically generated by the build process when version is
|
# This file is automatically generated by the build process when version is
|
||||||
# updated in pyproject.toml.
|
# updated in pyproject.toml.
|
||||||
__version__ = "0.5.1"
|
__version__ = "0.6.0"
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
comfyui_manager==4.0.3b7
|
comfyui_manager==4.0.4
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ComfyUI"
|
name = "ComfyUI"
|
||||||
version = "0.5.1"
|
version = "0.6.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { file = "LICENSE" }
|
license = { file = "LICENSE" }
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
comfyui-frontend-package==1.34.9
|
comfyui-frontend-package==1.35.9
|
||||||
comfyui-workflow-templates==0.7.62
|
comfyui-workflow-templates==0.7.64
|
||||||
comfyui-embedded-docs==0.3.1
|
comfyui-embedded-docs==0.3.1
|
||||||
torch
|
torch
|
||||||
torchsde
|
torchsde
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user