chore: rename drawing node to GPT Image
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# ComfyUI Chat Image Bridge
|
||||
|
||||
一个用于 ComfyUI 的第三方 API 生图节点集合,主要面向 OpenAI-compatible 聊天接口,也包含面向 Right Codes 绘图接口的专用节点。
|
||||
一个用于 ComfyUI 的第三方 API 生图节点集合,主要面向 OpenAI-compatible 聊天接口,也包含 GPT Image 专用请求节点。
|
||||
|
||||
仓库不会内置任何 API Key。通用节点不内置服务商地址;Right Codes 专用节点会预填官方 `base_url`,方便直接使用,也可以自行修改。
|
||||
仓库不会内置任何 API Key 或服务商地址。用户需要在节点里填写自己的 `base_url`、`api_key` 和模型名。
|
||||
|
||||
## 功能
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
- 支持 1K、2K、4K 分辨率和常见长宽比
|
||||
- 支持 1-2 张参考图输入
|
||||
- 支持解析 Markdown 图片、图片 URL、`b64_json`、Gemini `inlineData`
|
||||
- 提供 Right Codes GPT Image 专用节点,使用流式 `/v1/chat/completions`
|
||||
- 提供 GPT Image 专用节点,使用流式 `/v1/chat/completions`
|
||||
- 提供高级节点,可输出原始响应和图片引用,方便调试
|
||||
|
||||
## 安装
|
||||
@@ -74,15 +74,15 @@ api -> Chat Image Bridge -> Chat Image Bridge
|
||||
|
||||
可以直接接到 `Save Image` 或其他 ComfyUI 图像节点。
|
||||
|
||||
## Right Codes GPT Image 节点
|
||||
## GPT Image 节点
|
||||
|
||||
添加节点:
|
||||
|
||||
```text
|
||||
api -> Chat Image Bridge -> Right Codes GPT Image
|
||||
api -> Chat Image Bridge -> GPT Image
|
||||
```
|
||||
|
||||
这个节点面向 Right Codes 绘图接口,默认使用:
|
||||
这个节点面向 GPT Image / Nano Banana 这类绘图接口,使用流式 `/v1/chat/completions`。如果你的服务商使用 Right Codes draw 格式,`base_url` 可以填写:
|
||||
|
||||
```text
|
||||
https://www.right.codes/draw/v1/chat/completions
|
||||
@@ -120,7 +120,7 @@ https://example.com/v1/chat/completions
|
||||
|
||||
节点会自动整理为请求需要的接口地址。
|
||||
|
||||
Right Codes 专用节点默认填的是:
|
||||
如果使用 Right Codes draw 格式,可以填:
|
||||
|
||||
```text
|
||||
https://www.right.codes/draw
|
||||
@@ -174,7 +174,7 @@ gemini-3-pro-image-preview
|
||||
|
||||
这样 `4K` 和长宽比会作为真正的图片参数发送,而不是只写进 prompt。
|
||||
|
||||
Right Codes GPT Image 节点则会按接口文档传入 `size`,例如 `3840x2160`。
|
||||
GPT Image 节点则会按接口文档传入 `size`,例如 `3840x2160`。
|
||||
|
||||
## 高级节点
|
||||
|
||||
@@ -197,5 +197,5 @@ api -> Chat Image Bridge -> Chat Image Bridge Advanced
|
||||
|
||||
- API Key 只在节点 UI 里填写,本仓库不会硬编码任何 Key。
|
||||
- 不同中转站对 OpenAI-compatible 的兼容程度不同,字段支持可能不完全一致。
|
||||
- `gpt-image-2` 和 `nano-banana` 在 Right Codes 节点里只开放 1K,选择更高分辨率会直接报错,避免请求失败或产生无效消耗。
|
||||
- `gpt-image-2` 和 `nano-banana` 在 GPT Image 节点里只开放 1K,选择更高分辨率会直接报错,避免请求失败或产生无效消耗。
|
||||
- 旧版工作流如果使用过 `endpoint_url`,建议改成新版的 `base_url`。
|
||||
|
||||
+21
-21
@@ -23,18 +23,18 @@ GRSAI_PROXY_RE = re.compile(
|
||||
RESOLUTION_OPTIONS = ["auto", "1K", "2K", "4K"]
|
||||
ASPECT_RATIO_OPTIONS = ["auto", "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "4:5", "5:4", "21:9"]
|
||||
DEFAULT_MODEL = "gemini-3-pro-image-preview"
|
||||
RIGHT_CODES_DEFAULT_BASE_URL = "https://www.right.codes/draw"
|
||||
RIGHT_CODES_MODELS = ["gpt-image-2-vip", "gpt-image-2", "nano-banana", "nano-banana-2", "nano-banana-pro"]
|
||||
RIGHT_CODES_RESOLUTION_OPTIONS = ["1K", "2K", "4K"]
|
||||
RIGHT_CODES_ASPECT_RATIO_OPTIONS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "4:5", "5:4", "21:9"]
|
||||
RIGHT_CODES_MODEL_RESOLUTIONS = {
|
||||
GPT_IMAGE_DEFAULT_BASE_URL = ""
|
||||
GPT_IMAGE_MODELS = ["gpt-image-2-vip", "gpt-image-2", "nano-banana", "nano-banana-2", "nano-banana-pro"]
|
||||
GPT_IMAGE_RESOLUTION_OPTIONS = ["1K", "2K", "4K"]
|
||||
GPT_IMAGE_ASPECT_RATIO_OPTIONS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "4:5", "5:4", "21:9"]
|
||||
GPT_IMAGE_MODEL_RESOLUTIONS = {
|
||||
"gpt-image-2-vip": {"1K", "2K", "4K"},
|
||||
"gpt-image-2": {"1K"},
|
||||
"nano-banana": {"1K"},
|
||||
"nano-banana-2": {"1K", "2K", "4K"},
|
||||
"nano-banana-pro": {"1K", "2K", "4K"},
|
||||
}
|
||||
RIGHT_CODES_SIZE_TABLE = {
|
||||
GPT_IMAGE_SIZE_TABLE = {
|
||||
"1K": {
|
||||
"1:1": "1280x1280",
|
||||
"2:3": "848x1280",
|
||||
@@ -163,22 +163,22 @@ def normalize_generation_option(value):
|
||||
return value
|
||||
|
||||
|
||||
def right_codes_size_for(model, resolution, aspect_ratio):
|
||||
def gpt_image_size_for(model, resolution, aspect_ratio):
|
||||
model = (model or "").strip()
|
||||
resolution = (resolution or "").strip()
|
||||
aspect_ratio = (aspect_ratio or "").strip()
|
||||
|
||||
supported = RIGHT_CODES_MODEL_RESOLUTIONS.get(model)
|
||||
supported = GPT_IMAGE_MODEL_RESOLUTIONS.get(model)
|
||||
if not supported:
|
||||
raise ValueError(f"Unsupported Right Codes image model: {model}")
|
||||
raise ValueError(f"Unsupported GPT Image model: {model}")
|
||||
if resolution not in supported:
|
||||
allowed = ", ".join(sorted(supported))
|
||||
raise ValueError(f"{model} supports resolution {allowed}, but got {resolution}")
|
||||
|
||||
try:
|
||||
return RIGHT_CODES_SIZE_TABLE[resolution][aspect_ratio]
|
||||
return GPT_IMAGE_SIZE_TABLE[resolution][aspect_ratio]
|
||||
except KeyError as exc:
|
||||
raise ValueError(f"Unsupported Right Codes size option: {resolution} {aspect_ratio}") from exc
|
||||
raise ValueError(f"Unsupported GPT Image size option: {resolution} {aspect_ratio}") from exc
|
||||
|
||||
|
||||
def tensor_to_png_data_url(tensor):
|
||||
@@ -682,19 +682,19 @@ class ChatImageBridgeAdvanced(ChatImageBridgeBase):
|
||||
)
|
||||
|
||||
|
||||
class RightCodesGPTImage(ChatImageBridgeBase):
|
||||
"""Right Codes draw node using streaming chat/completions requests."""
|
||||
class GPTImage(ChatImageBridgeBase):
|
||||
"""GPT image node using streaming chat/completions requests."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"api_key": ("STRING", {"default": "", "multiline": False}),
|
||||
"base_url": ("STRING", {"default": RIGHT_CODES_DEFAULT_BASE_URL, "multiline": False}),
|
||||
"model": (RIGHT_CODES_MODELS, {"default": "gpt-image-2-vip"}),
|
||||
"base_url": ("STRING", {"default": GPT_IMAGE_DEFAULT_BASE_URL, "multiline": False}),
|
||||
"model": (GPT_IMAGE_MODELS, {"default": "gpt-image-2-vip"}),
|
||||
"prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"resolution": (RIGHT_CODES_RESOLUTION_OPTIONS, {"default": "1K"}),
|
||||
"aspect_ratio": (RIGHT_CODES_ASPECT_RATIO_OPTIONS, {"default": "1:1"}),
|
||||
"resolution": (GPT_IMAGE_RESOLUTION_OPTIONS, {"default": "1K"}),
|
||||
"aspect_ratio": (GPT_IMAGE_ASPECT_RATIO_OPTIONS, {"default": "1:1"}),
|
||||
"timeout_seconds": ("INT", {"default": 600, "min": 60, "max": 3600}),
|
||||
},
|
||||
"optional": {
|
||||
@@ -805,7 +805,7 @@ class RightCodesGPTImage(ChatImageBridgeBase):
|
||||
preview = json.dumps(redact_object(data), ensure_ascii=False)[:2000]
|
||||
if raw_preview and preview == '{"stream": true, "content": "", "chunks": []}':
|
||||
preview = "\n".join(raw_preview)[:2000]
|
||||
raise RuntimeError(f"Right Codes stream did not contain image data or image URLs: {preview}")
|
||||
raise RuntimeError(f"GPT Image stream did not contain image data or image URLs: {preview}")
|
||||
|
||||
return data, refs
|
||||
|
||||
@@ -818,7 +818,7 @@ class RightCodesGPTImage(ChatImageBridgeBase):
|
||||
raise ValueError("prompt is required")
|
||||
|
||||
model = (model or "").strip()
|
||||
size = right_codes_size_for(model, resolution, aspect_ratio)
|
||||
size = gpt_image_size_for(model, resolution, aspect_ratio)
|
||||
endpoint = normalize_endpoint(base_url)
|
||||
payload = self._build_payload(model, prompt, size, [image_1, image_2])
|
||||
_, refs = self._post_streaming_chat(endpoint, api_key, payload, int(timeout_seconds))
|
||||
@@ -829,11 +829,11 @@ class RightCodesGPTImage(ChatImageBridgeBase):
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ChatImageBridge": ChatImageBridge,
|
||||
"ChatImageBridgeAdvanced": ChatImageBridgeAdvanced,
|
||||
"RightCodesGPTImage": RightCodesGPTImage,
|
||||
"GPTImage": GPTImage,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ChatImageBridge": "Chat Image Bridge",
|
||||
"ChatImageBridgeAdvanced": "Chat Image Bridge Advanced",
|
||||
"RightCodesGPTImage": "Right Codes GPT Image",
|
||||
"GPTImage": "GPT Image",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user