chore: rename drawing node to GPT Image

This commit is contained in:
Marigold1122
2026-05-20 04:02:47 +08:00
parent 51be6596db
commit aedb281628
2 changed files with 30 additions and 30 deletions
+9 -9
View File
@@ -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
View File
@@ -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",
}