Added Support for Riverflow 2.5

This commit is contained in:
Sirshendu Ganguly
2026-06-08 09:27:56 +05:30
parent 85ec73715d
commit 46074fde9c
11 changed files with 468 additions and 22 deletions
+1 -1
View File
@@ -204,7 +204,7 @@ class txt2img:
"tooltip": "Connect Runware Safety Inputs node to configure safety and content moderation settings.",
}),
"settings": ("RUNWARESETTINGS", {
"tooltip": "Connect Runware Image Inference Settings for temperature, systemPrompt, topP, layers, quality, background, style, search, promptExtend, editRegions (JSON), thinking, thinkingLevel (high/medium/low), sequential, colorPalette (via Color Palette node), etc.",
"tooltip": "Connect Runware Image Inference Settings for temperature, systemPrompt, topP, layers, quality, backgroundMode, backgroundColor, enhancePrompt, scoringPrompt, background, style, search, promptExtend, editRegions (JSON), thinking, thinkingLevel (low/medium/high/xhigh), sequential, colorPalette (via Color Palette node), etc.",
}),
"ultralytics": ("RUNWAREULTRALYTICSINPUTS", {
"tooltip": "Connect Runware Image Inference Ultralytics node to configure Ultralytics parameters (maskBlur, maskPadding, confidence, prompts, steps, CFGScale, strength).",
+13 -1
View File
@@ -49,12 +49,20 @@ class imageInferenceInputs:
"tooltip": f"Specifies {ordinal.capitalize()} Super Resolution Reference Image for the inputs.",
})
optionalInputs["Fonts"] = ("RUNWAREIMAGEINFERENCEFONTS", {
"tooltip": "Connect Runware Image Inference Inputs Fonts for inputs.fonts (up to 2 font URL + text references).",
})
return {
"required": {},
"optional": optionalInputs
}
DESCRIPTION = "Configure custom inputs for Runware Image Inference, including image/mask, reference images (with optional tag, role, type e.g. 'sketch' for illustrative style models, and strength 0-1 for sketch), and super resolution references."
DESCRIPTION = (
"Configure custom inputs for Runware Image Inference, including image/mask, reference images "
"(with optional tag, role, type e.g. 'sketch' for illustrative style models, and strength 0-1 for sketch), "
"super resolution references, and font references (inputs.fonts)."
)
FUNCTION = "createInputs"
RETURN_TYPES = ("RUNWAREIMAGEINFERENCEINPUTS",)
RETURN_NAMES = ("Inference Inputs",)
@@ -80,6 +88,10 @@ class imageInferenceInputs:
if len(super_resolution_refs) > 0:
inputs["superResolutionReferenceImages"] = super_resolution_refs
fonts = kwargs.get("Fonts", None)
if fonts is not None and isinstance(fonts, list) and len(fonts) > 0:
inputs["fonts"] = fonts
return (inputs,)
def _collectReferences(self, kwargs):
+60
View File
@@ -0,0 +1,60 @@
"""
Runware Image Inference Inputs Fonts node.
Builds inputs.fonts for image inference (up to 2 font references with url and text).
"""
from typing import Any, Dict, List, Tuple
class RunwareImageInferenceInputsFonts:
"""Build inputs.fonts[] for image inference requests."""
MAX_FONTS = 2
@classmethod
def INPUT_TYPES(cls):
optional_inputs = {}
for i in range(1, cls.MAX_FONTS + 1):
optional_inputs[f"fontUrl{i}"] = ("STRING", {
"default": "",
"tooltip": (
f"Font file URL for reference {i}. Must be ttf, otf, woff, or woff2. "
"Included when both fontUrl and text are non-empty."
),
})
optional_inputs[f"text{i}"] = ("STRING", {
"multiline": True,
"default": "",
"tooltip": f"Text to render with font reference {i}. Included when both fontUrl and text are non-empty.",
})
return {
"required": {},
"optional": optional_inputs,
}
RETURN_TYPES = ("RUNWAREIMAGEINFERENCEFONTS",)
RETURN_NAMES = ("fonts",)
FUNCTION = "create_fonts"
CATEGORY = "Runware"
DESCRIPTION = (
"Configure inputs.fonts for Runware Image Inference (up to 2 entries). "
"Each entry: { \"url\": \"<font URL>\", \"text\": \"<text to render>\" }. "
"A slot is included only when both fontUrl and text are non-empty. "
"Connect to Runware Image Inference Inputs."
)
def create_fonts(self, **kwargs) -> Tuple[List[Dict[str, Any]]]:
fonts: List[Dict[str, Any]] = []
for i in range(1, self.MAX_FONTS + 1):
font_url = (kwargs.get(f"fontUrl{i}") or "").strip()
text = (kwargs.get(f"text{i}") or "").strip()
if len(font_url) > 0 and len(text) > 0:
fonts.append({
"url": font_url,
"text": text,
})
return (fonts,)
@@ -0,0 +1,171 @@
"""
Runware Image Inference Settings Scoring Rubric
Builds settings.scoringRubric[] for Riverflow 2.5 (1–8 dimensions).
"""
from typing import Any, Dict, List, Tuple
_MAX_SCORE_GUIDANCE = 5
_MAX_RUBRIC_COMBINE = 4
def _build_score_guidance(kwargs: Dict[str, Any]) -> List[Dict[str, Any]]:
guidance: List[Dict[str, Any]] = []
for i in range(1, _MAX_SCORE_GUIDANCE + 1):
if not kwargs.get(f"useScoreGuidance{i}", False):
continue
score = kwargs.get(f"score{i}")
description = (kwargs.get(f"guidanceDescription{i}") or "").strip()
if score is None or not description:
continue
guidance.append({
"score": float(score),
"description": description,
})
return guidance
def _build_rubric_entry(kwargs: Dict[str, Any]) -> Dict[str, Any]:
entry: Dict[str, Any] = {
"key": (kwargs.get("key") or "").strip(),
"label": (kwargs.get("label") or "").strip(),
"description": (kwargs.get("description") or "").strip(),
"weight": float(kwargs.get("weight", 1.0)),
}
if kwargs.get("usePassingScore", False):
entry["passingScore"] = float(kwargs.get("passingScore", 0.0))
guidance = _build_score_guidance(kwargs)
if guidance:
entry["scoreGuidance"] = guidance
return entry
class RunwareImageInferenceSettingsScoringRubric:
"""Build one scoringRubric dimension for settings.scoringRubric."""
@classmethod
def INPUT_TYPES(cls):
optional: Dict[str, tuple] = {
"usePassingScore": ("BOOLEAN", {
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
"tooltip": "Include passingScore for this scoring dimension.",
}),
"passingScore": ("FLOAT", {
"default": 0.5,
"min": 0.0,
"max": 1.0,
"step": 0.01,
"tooltip": "Optional dimension floor from 0 to 1. Only used when usePassingScore is enabled.",
}),
}
for i in range(1, _MAX_SCORE_GUIDANCE + 1):
optional[f"useScoreGuidance{i}"] = ("BOOLEAN", {
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
"tooltip": f"Include scoreGuidance anchor {i} (up to {_MAX_SCORE_GUIDANCE} per dimension).",
})
optional[f"score{i}"] = ("FLOAT", {
"default": 0.0,
"min": 0.0,
"max": 1.0,
"step": 0.01,
"tooltip": f"Normalized score anchor (0–1) for scoreGuidance entry {i}.",
})
optional[f"guidanceDescription{i}"] = ("STRING", {
"multiline": True,
"default": "",
"tooltip": f"What score anchor {i} means for the judge.",
})
return {
"required": {
"key": ("STRING", {
"default": "",
"tooltip": "Unique machine-readable dimension key (e.g. composition, lighting).",
}),
"label": ("STRING", {
"default": "",
"tooltip": "Short human-readable dimension label.",
}),
"description": ("STRING", {
"multiline": True,
"default": "",
"tooltip": "Judging criteria for this score dimension.",
}),
"weight": ("FLOAT", {
"default": 1.0,
"min": 0.01,
"max": 100.0,
"step": 0.01,
"tooltip": "Positive scoring weight. Weights are normalized internally.",
}),
},
"optional": optional,
}
RETURN_TYPES = ("RUNWAREIMAGEINFERENCESCORINGRUBRIC",)
RETURN_NAMES = ("scoringRubric",)
FUNCTION = "build_scoring_rubric"
CATEGORY = "Runware"
DESCRIPTION = (
"Define one settings.scoringRubric[] dimension for Riverflow 2.5 (key, label, description, weight, "
"optional passingScore and up to 5 scoreGuidance anchors). Connect to Runware Image Inference Settings, "
"or use Runware Image Inference Settings Scoring Rubric Combine for up to 4 dimensions."
)
def build_scoring_rubric(self, **kwargs) -> Tuple[List[Dict[str, Any]]]:
return ([_build_rubric_entry(kwargs)],)
class RunwareImageInferenceSettingsScoringRubricCombine:
"""Combine up to 4 Scoring Rubric node outputs into settings.scoringRubric."""
@classmethod
def INPUT_TYPES(cls):
optional: Dict[str, tuple] = {}
for i in range(2, _MAX_RUBRIC_COMBINE + 1):
optional[f"Scoring Rubric {i}"] = ("RUNWAREIMAGEINFERENCESCORINGRUBRIC", {
"tooltip": f"Optional scoring rubric dimension {i} (connect Runware Image Inference Settings Scoring Rubric).",
})
return {
"required": {
"Scoring Rubric 1": ("RUNWAREIMAGEINFERENCESCORINGRUBRIC", {
"tooltip": "First scoring rubric dimension (connect Runware Image Inference Settings Scoring Rubric).",
}),
},
"optional": optional,
}
RETURN_TYPES = ("RUNWAREIMAGEINFERENCESCORINGRUBRIC",)
RETURN_NAMES = ("scoringRubric",)
FUNCTION = "combine_scoring_rubric"
CATEGORY = "Runware"
DESCRIPTION = (
"Combine up to 4 Runware Image Inference Settings Scoring Rubric outputs into settings.scoringRubric. "
"Connect scoringRubric to Runware Image Inference Settings."
)
def combine_scoring_rubric(self, **kwargs) -> Tuple[List[Dict[str, Any]]]:
combined: List[Dict[str, Any]] = []
for i in range(1, _MAX_RUBRIC_COMBINE + 1):
chunk = kwargs.get(f"Scoring Rubric {i}")
if chunk is not None and isinstance(chunk, list):
combined.extend(
entry for entry in chunk
if isinstance(entry, dict) and len(entry) > 0
)
return (combined,)
+105 -7
View File
@@ -2,7 +2,8 @@
Runware Image Inference Settings (registered as Runware Settings for workflow compatibility).
Provides settings for image generation including temperature, systemPrompt, topP, layers,
quality, background, style, search, promptExtend, editRegions, thinking (boolean),
thinkingLevel (high/medium/low), sequential, renderingSpeed (TURBO/DEFAULT/QUALITY),
thinkingLevel (low/medium/high/xhigh), backgroundMode (original/transparent/solid), backgroundColor,
enhancePrompt, scoringPrompt, sequential, renderingSpeed (TURBO/DEFAULT/QUALITY),
magicPrompt (AUTO/ON/OFF), autoCrop, dilatePixels, creativity (raw/low/medium/high), colorPalette,
moodboards (from Runware Image Inference Settings Moodboards),
structuredPrompt (from Runware Image Inference Settings Structured Prompt; Ideogram 4.0),
@@ -127,9 +128,12 @@ class RunwareSettings:
"tooltip": "Enable to include thinkingLevel (string) in settings.",
"default": False,
}),
"thinkingLevel": (["high", "medium", "low"], {
"thinkingLevel": (["high", "medium", "low", "xhigh"], {
"default": "high",
"tooltip": "Reasoning level for visual understanding. Only used when 'Use Thinking Level' is enabled.",
"tooltip": (
"Reasoning level for visual understanding. Riverflow 2.5 also supports xhigh (Pro only). "
"Only used when 'Use Thinking Level' is enabled."
),
}),
"useBackground": ("BOOLEAN", {
"tooltip": "Enable to include background style in API request",
@@ -212,6 +216,60 @@ class RunwareSettings:
"promptEnhance": ("RUNWAREIMAGEINFERENCEPROMPTENHANCE", {
"tooltip": "Connect Runware Image Inference Settings Prompt Enhance. Merged into settings.promptEnhance (temperature, topP). Omit from API when not connected or empty.",
}),
"useBackgroundMode": ("BOOLEAN", {
"tooltip": "Enable to include backgroundMode in settings (Riverflow 2.5 output background handling).",
"default": False,
}),
"backgroundMode": (["original", "transparent", "solid"], {
"default": "original",
"tooltip": (
"settings.backgroundMode: original, transparent, or solid. "
"Only used when 'Use Background Mode' is enabled."
),
}),
"useBackgroundColor": ("BOOLEAN", {
"tooltip": "Enable to include backgroundColor in settings (required when backgroundMode is solid).",
"default": False,
}),
"backgroundColor": ("STRING", {
"default": "#FFFFFF",
"tooltip": (
"Hex color (#RRGGBB) composited when backgroundMode is solid. "
"Only used when 'Use Background Color' is enabled."
),
}),
"useEnhancePrompt": ("BOOLEAN", {
"tooltip": "Enable to include enhancePrompt (boolean) in settings.",
"default": False,
}),
"enhancePrompt": ("BOOLEAN", {
"default": False,
"label_on": "true",
"label_off": "false",
"tooltip": (
"Enhance the prompt with use-case context before generation (Riverflow 2.5). "
"Distinct from settings.promptEnhance (nested object). "
"Only used when 'Use Enhance Prompt' is enabled."
),
}),
"useScoringPrompt": ("BOOLEAN", {
"tooltip": "Enable to include scoringPrompt in settings.",
"default": False,
}),
"scoringPrompt": ("STRING", {
"multiline": True,
"default": "",
"tooltip": (
"Optional quality rubric used when RF 2.5 scores candidate outputs. "
"Only used when 'Use Scoring Prompt' is enabled."
),
}),
"scoringRubric": ("RUNWAREIMAGEINFERENCESCORINGRUBRIC", {
"tooltip": (
"Connect Runware Image Inference Settings Scoring Rubric or Scoring Rubric Combine "
"for settings.scoringRubric (up to 4 dimensions via Combine)."
),
}),
}
}
@@ -220,10 +278,12 @@ class RunwareSettings:
FUNCTION = "createSettings"
CATEGORY = "Runware"
DESCRIPTION = (
"Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, background, style, search, "
"promptExtend, editRegions (JSON), thinking (boolean), thinkingLevel (high/medium/low), sequential, "
"Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, "
"backgroundMode (original/transparent/solid), backgroundColor, enhancePrompt, scoringPrompt, background, style, search, "
"promptExtend, editRegions (JSON), thinking (boolean), thinkingLevel (low/medium/high/xhigh), sequential, "
"renderingSpeed (TURBO/DEFAULT/QUALITY), magicPrompt (AUTO/ON/OFF), autoCrop, dilatePixels, "
"creativity (raw/low/medium/high), and optional colorPalette, moodboards, structuredPrompt, and promptEnhance from dedicated settings nodes."
"creativity (raw/low/medium/high), and optional colorPalette, moodboards, structuredPrompt, promptEnhance, "
"and scoringRubric from dedicated settings nodes."
)
def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]:
@@ -244,6 +304,10 @@ class RunwareSettings:
useEditRegions = kwargs.get("useEditRegions", False)
useThinking = kwargs.get("useThinking", False)
useThinkingLevel = kwargs.get("useThinkingLevel", False)
useBackgroundMode = kwargs.get("useBackgroundMode", False)
useBackgroundColor = kwargs.get("useBackgroundColor", False)
useEnhancePrompt = kwargs.get("useEnhancePrompt", False)
useScoringPrompt = kwargs.get("useScoringPrompt", False)
useSequential = kwargs.get("useSequential", False)
useRenderingSpeed = kwargs.get("useRenderingSpeed", False)
useMagicPrompt = kwargs.get("useMagicPrompt", False)
@@ -304,7 +368,37 @@ class RunwareSettings:
settings["thinking"] = bool(kwargs.get("thinking", False))
if useThinkingLevel:
settings["thinkingLevel"] = str(kwargs.get("thinkingLevel", "high"))
thinking_level = str(kwargs.get("thinkingLevel", "high"))
if thinking_level not in ("low", "medium", "high", "xhigh"):
raise ValueError(
"thinkingLevel must be low, medium, high, or xhigh when useThinkingLevel is enabled."
)
settings["thinkingLevel"] = thinking_level
if useBackgroundMode:
background_mode = str(kwargs.get("backgroundMode", "original"))
if background_mode not in ("original", "transparent", "solid"):
raise ValueError(
"backgroundMode must be original, transparent, or solid when useBackgroundMode is enabled."
)
settings["backgroundMode"] = background_mode
if useBackgroundColor:
background_color = (kwargs.get("backgroundColor") or "").strip()
if background_color:
if not background_color.startswith("#") or len(background_color) != 7:
raise ValueError(
"backgroundColor must be a hex color in #RRGGBB format when useBackgroundColor is enabled."
)
settings["backgroundColor"] = background_color
if useEnhancePrompt:
settings["enhancePrompt"] = bool(kwargs.get("enhancePrompt", False))
if useScoringPrompt:
scoring_prompt = (kwargs.get("scoringPrompt") or "").strip()
if scoring_prompt:
settings["scoringPrompt"] = scoring_prompt
if useSequential:
settings["sequential"] = bool(kwargs.get("sequential", False))
@@ -332,6 +426,10 @@ class RunwareSettings:
):
settings["promptEnhance"] = prompt_enhance
scoring_rubric: Optional[List[Dict[str, Any]]] = kwargs.get("scoringRubric")
if scoring_rubric is not None and isinstance(scoring_rubric, list) and len(scoring_rubric) > 0:
settings["scoringRubric"] = scoring_rubric
if useRenderingSpeed:
settings["renderingSpeed"] = str(renderingSpeed)
if useMagicPrompt: