初始化项目,由ModelHub XC社区提供模型

Model: Kezmark/Mordant-3B-Think
Source: Original Platform
This commit is contained in:
ModelHub XC
2026-06-22 18:07:31 +08:00
commit 826c3261ad
14 changed files with 503746 additions and 0 deletions

View File

@@ -0,0 +1,350 @@
import os
import gc
import threading
from typing import Optional
import torch
from llama_cpp import Llama
from comfy import model_management
import folder_paths
# -------------------------------------------------------------------
# 1. Helpers for GGUF file listing & resolution (unchanged)
# -------------------------------------------------------------------
_CACHE = {}
_CACHE_LOCK = threading.Lock()
def _list_gguf_files():
candidates = []
base_dirs = []
try:
base_dirs.extend(folder_paths.get_folder_paths("text_encoders"))
except Exception:
pass
for base in base_dirs:
if not base or not os.path.isdir(base):
continue
for root, _, files in os.walk(base):
for name in files:
if name.lower().endswith(".gguf"):
full = os.path.join(root, name)
try:
rel = os.path.relpath(full, base)
if rel not in candidates:
candidates.append(rel)
except Exception:
if full not in candidates:
candidates.append(full)
if "<manual_path>" not in candidates:
candidates.append("<manual_path>")
return candidates
def _resolve_model_path(model_name: str, manual_model_path: str = "") -> str:
if os.path.isabs(model_name) and os.path.isfile(model_name):
return model_name
if model_name == "<manual_path>":
p = (manual_model_path or "").strip()
if not p:
raise ValueError("model is <manual_path> but manual_model_path is empty")
if not os.path.isfile(p):
raise FileNotFoundError(f"GGUF model not found: {p}")
return p
full = folder_paths.get_full_path("text_encoders", model_name)
if full and os.path.isfile(full):
return full
try:
for base in folder_paths.get_folder_paths("text_encoders"):
probe = os.path.join(base, model_name)
if os.path.isfile(probe):
return probe
except Exception:
pass
raise FileNotFoundError(f"Could not resolve GGUF model path for: {model_name}")
def _build_messages(system_prompt: str, user_prompt: str):
messages = []
if system_prompt.strip():
messages.append({"role": "system", "content": system_prompt.strip()})
messages.append({"role": "user", "content": user_prompt.strip()})
return messages
def _assemble_prompt(messages: list, model_family: str) -> str:
prompt = ""
if model_family == "granite":
for msg in messages:
prompt += f"<|start_of_role|>{msg['role']}<|end_of_role|>{msg['content']}<|end_of_text|>\n"
prompt += "<|start_of_role|>assistant<|end_of_role|><think>\n"
else:
for msg in messages:
prompt += f"<|im_start|>{msg['role']}\n{msg['content']}<|im_end|>\n"
prompt += "<|im_start|>assistant\n<think>"
return prompt
# -------------------------------------------------------------------
# 2. Lookup table for Mordant models (unchanged)
# -------------------------------------------------------------------
MORDANT_INFO = {
"mordant-1.2b": {
"layers": 16,
"bf16_total_gb": 2.35,
"per_layer": {
"bf16": 2.35 / 16,
"q8_0": 1.27 / 16,
"q6_k_m": 1.01682 / 16,
"q5_k_m": None,
"q4_k_m": None,
}
},
"mordant-3b": {
"layers": 40,
"bf16_total_gb": 6.99,
"per_layer": {
"bf16": 6.99 / 40,
"q8_0": 3.86 / 40,
"q6_k_m": 3.05 / 40,
"q5_k_m": 2.70 / 40,
"q4_k_m": None,
}
},
"mordant-7b": {
"layers": 32,
"bf16_total_gb": 16.29,
"per_layer": {
"bf16": 16.29 / 32,
"q8_0": 9.58 / 32,
"q6_k_m": 7.85 / 32,
"q5_k_m": 7.08 / 32,
"q4_k_m": None,
}
},
"mordant-12b": {
"layers": 40,
"bf16_total_gb": 24.81,
"per_layer": {
"bf16": 24.81 / 40,
"q8_0": 13.55 / 40,
"q6_k_m": 10.64 / 40,
"q5_k_m": 9.33 / 40,
"q4_k_m": 8.11 / 40,
}
},
}
def _detect_model_info(model_path: str):
try:
llm_meta = Llama(model_path=model_path, vocab_only=True, n_gpu_layers=0, verbose=False)
meta = llm_meta.metadata
arch = meta.get("general.architecture", "unknown")
total_layers = int(meta.get(f"{arch}.block_count", 0))
quant_version = meta.get("general.quantization_version", "unknown").lower()
if quant_version == "unknown":
quant_version = meta.get("tokenizer.ggml.quantization_version", "unknown").lower()
del llm_meta
except Exception:
fname = os.path.basename(model_path).lower()
for name in MORDANT_INFO:
if name in fname:
info = MORDANT_INFO[name]
total_layers = info["layers"]
quant_version = "bf16"
for q in ["q8_0", "q6_k_m", "q5_k_m", "q4_k_m", "q3_k_m", "q2_k_m"]:
if q in fname:
quant_version = q
break
break
else:
total_layers = 32
quant_version = "bf16"
model_name = None
fname_lower = os.path.basename(model_path).lower()
for name in MORDANT_INFO:
if name in fname_lower:
model_name = name
break
if model_name is None:
file_size_gb = os.path.getsize(model_path) / (1024**3)
per_layer_vram = file_size_gb / total_layers if total_layers > 0 else 0.5
return (model_name or "unknown", total_layers, per_layer_vram, quant_version)
info = MORDANT_INFO[model_name]
layers = info["layers"]
per_layer_dict = info.get("per_layer", {})
per_layer_vram = None
quant_clean = quant_version.replace("_0", "").replace("_1", "").lower()
if quant_version in per_layer_dict and per_layer_dict[quant_version] is not None:
per_layer_vram = per_layer_dict[quant_version]
elif quant_clean in per_layer_dict and per_layer_dict[quant_clean] is not None:
per_layer_vram = per_layer_dict[quant_clean]
else:
bf16_per_layer = per_layer_dict.get("bf16")
if bf16_per_layer is None:
bf16_total = info["bf16_total_gb"]
bf16_per_layer = bf16_total / layers
actual_file_size_gb = os.path.getsize(model_path) / (1024**3)
per_layer_vram = actual_file_size_gb / layers
return model_name, layers, per_layer_vram, quant_version
def _auto_n_gpu_layers(model_path: str, verbose: bool = False) -> int:
if not torch.cuda.is_available():
return 0
total_vram_gb = torch.cuda.get_device_properties(0).total_memory / (1024**3)
usable_vram_gb = max(0, total_vram_gb - 2.0)
model_name, max_layers, per_layer_vram, quant = _detect_model_info(model_path)
if per_layer_vram <= 0:
return 0
n_layers = int(usable_vram_gb / per_layer_vram)
n_layers = max(0, min(max_layers, n_layers))
if verbose:
print(f"[Mordant Enhancer] GPU VRAM: {total_vram_gb:.2f} GB, "
f"Reserved: 2.00 GB, Usable: {usable_vram_gb:.2f} GB")
print(f"[Mordant Enhancer] Model: {model_name}, Layers: {max_layers}, "
f"Quant: {quant}, Perlayer VRAM: {per_layer_vram:.4f} GB")
print(f"[Mordant Enhancer] Autoselected GPU layers: {n_layers}")
return n_layers
# -------------------------------------------------------------------
# 3. Main node class Mordant Prompt Enhancer
# -------------------------------------------------------------------
class MordantPromptEnhancer:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"model": (_list_gguf_files(),),
"text": ("STRING", {"multiline": True, "default": "Rewrite this image prompt conservatively."}),
"mode": (["enhancer", "general"], {"default": "enhancer"}),
"enable_enhancement": ("BOOLEAN", {"default": True}),
"sampling_mode": ("BOOLEAN", {"default": True}),
"max_new_tokens": ("INT", {"default": 8192, "min": 1, "max": 8192}),
"seed": ("INT", {"default": 0, "min": -1, "max": 2147483647}),
"temperature": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 5.0, "step": 0.05}),
"top_p": ("FLOAT", {"default": 0.95, "min": 0.0, "max": 1.0, "step": 0.01}),
"top_k": ("INT", {"default": 50, "min": 0, "max": 1000}),
"repeat_penalty": ("FLOAT", {"default": 1.0, "min": 1.0, "max": 2.0, "step": 0.01}),
"n_batch": ("INT", {"default": 2048, "min": 32, "max": 4096, "step": 32}),
"keep_loaded": ("BOOLEAN", {"default": False}),
"offload_kqv": ("BOOLEAN", {"default": True}),
"flash_attn": ("BOOLEAN", {"default": True}),
"verbose": ("BOOLEAN", {"default": False}),
},
"optional": {
"manual_model_path": ("STRING", {"default": "", "multiline": False}),
"custom_system_prompt": ("STRING", {"default": "", "multiline": True}),
},
}
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("composition", "thinking")
FUNCTION = "generate"
CATEGORY = "text/llm"
def generate(self, model, text, mode, enable_enhancement,
sampling_mode, max_new_tokens, seed, temperature, top_p, top_k,
repeat_penalty, n_batch, keep_loaded, offload_kqv, flash_attn,
verbose, manual_model_path="", custom_system_prompt=""):
if not enable_enhancement:
return (text, "")
model_path = _resolve_model_path(model, manual_model_path)
system_prompt = (custom_system_prompt or "").strip()
n_ctx = 8192
n_threads = os.cpu_count() or 4
n_gpu_layers = _auto_n_gpu_layers(model_path, verbose=verbose)
if not sampling_mode:
eff_temp, eff_top_p, eff_top_k, eff_repeat_penalty = 0.2, 0.9, 20, max(repeat_penalty, 1.05)
else:
eff_temp, eff_top_p, eff_top_k, eff_repeat_penalty = temperature, top_p, top_k, repeat_penalty
try:
from llama_cpp import Llama
except ImportError:
raise RuntimeError("llama-cpp-python not installed.")
def _create_model():
kwargs = dict(
model_path=model_path,
n_ctx=n_ctx,
n_gpu_layers=n_gpu_layers,
n_batch=n_batch,
verbose=verbose,
cuda_graphs=False,
use_mmap=False,
use_mlock=False,
)
if n_threads is not None:
kwargs["n_threads"] = n_threads
try:
kwargs["offload_kqv"] = offload_kqv
kwargs["flash_attn"] = flash_attn
return Llama(**kwargs)
except TypeError:
kwargs.pop("offload_kqv", None)
kwargs.pop("flash_attn", None)
return Llama(**kwargs)
if keep_loaded:
key = (model_path, n_ctx, n_gpu_layers, n_threads, n_batch, offload_kqv, flash_attn)
with _CACHE_LOCK:
llm = _CACHE.get(key)
if llm is None:
llm = _create_model()
_CACHE[key] = llm
else:
llm = _create_model()
actual_family = "chatml"
if hasattr(llm, 'metadata'):
chat_template = llm.metadata.get('tokenizer.chat_template', '').lower()
if 'granite' in chat_template or 'start_of_role' in chat_template:
actual_family = "granite"
messages = _build_messages(system_prompt, text)
prompt = _assemble_prompt(messages, actual_family)
out = llm.create_completion(
prompt=prompt,
max_tokens=max_new_tokens,
temperature=eff_temp,
top_p=eff_top_p,
top_k=eff_top_k,
repeat_penalty=eff_repeat_penalty,
seed=None if seed < 0 else seed,
)
result_text = out["choices"][0]["text"]
if "</think>" in (result_text or ""):
parts = (result_text or "").rsplit("</think>", 1)
analysis_text, final_text = parts[0].strip(), parts[1].strip()
else:
analysis_text, final_text = "", (result_text or "").strip()
return (final_text, analysis_text)
# -------------------------------------------------------------------
# 4. Node registration
# -------------------------------------------------------------------
NODE_CLASS_MAPPINGS = {
"MordantPromptEnhancer": MordantPromptEnhancer,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"MordantPromptEnhancer": "Mordant Prompt Enhancer",
}

View File

@@ -0,0 +1,54 @@
Just place the Mordant-Prompt-Enhancer file in your ComfyUI custom_nodes folder.
You can see in the example workflow how to connect everything. And the default settings should be good, and you can experiment after.
The node looks for the models in the /models/text_encoders forlders, so place the mordant gguf there.
What does the mode do?
Enhancer is your daily prompt enhancer mode, general is more of a llm.
enable_enhancement toggle, basically turns the node on and off, for when you want to just use your own un-altered prompt.
Everything else is fairly obvious, if not, you should just leave it as is. Keep_loaded is if you have enough vram to keep the model loaded after generation, otherwise, by default the node unloads it.
**Installation**
Place the node file in ComfyUI's `custom_nodes/` folder. The only additional dependency is `llama-cpp-python`.
**CPUonly** (no GPU offloading):
```bat
# Windows portable
python_embeded\python.exe -m pip install llama-cpp-python
```
```bash
# Linux / venv / Mac
pip install llama-cpp-python
```
**GPU / CUDA — recommended** (prebuilt wheels, no compiler required):
```bat
# Windows portable — replace cu121 with your CUDA version
python_embeded\python.exe -m pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu121
```
```bash
# Linux / venv — replace cu121 with your CUDA version
pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu121
```
> Supported versions: `cu121` · `cu122` · `cu124` · `cu125` — run `nvidia-smi` to check yours (topright of output).
<details>
<summary>Build from source (advanced — only if wheels fail)</summary>
Requires CUDA Toolkit, CMake, and C++ build tools (Visual Studio on Windows).
```bat
# Windows
set CMAKE_ARGS=-DGGML_CUDA=on
python_embeded\python.exe -m pip install llama-cpp-python --force-reinstall --no-cache-dir
```
```bash
# Linux
CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python --force-reinstall --no-cache-dir
```
</details>
After restarting ComfyUI, the node appears under `text/llm` as **Mordant Prompt Enhancer**. Just pick your model and start composing.

View File

@@ -0,0 +1,757 @@
{
"id": "8e195d44-7179-4dfd-b08d-635cff8984d8",
"revision": 0,
"last_node_id": 37,
"last_link_id": 51,
"nodes": [
{
"id": 2,
"type": "LoaderGGUFAdvanced",
"pos": [
22242.338811590744,
11999.450597519388
],
"size": [
270.8125,
203.96875
],
"flags": {
"pinned": true
},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
37
]
}
],
"properties": {
"Node name for S&R": "LoaderGGUFAdvanced"
},
"widgets_values": [
"QwenImg\\flux2-dev-Q5_K_M.gguf",
"float32",
"float32",
false
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 4,
"type": "CLIPLoader",
"pos": [
22242.338811590744,
12239.450597519388
],
"size": [
270.4375,
187.03125
],
"flags": {
"collapsed": false,
"pinned": true
},
"order": 1,
"mode": 0,
"showAdvanced": true,
"inputs": [],
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"links": [
34,
42
]
}
],
"properties": {
"Node name for S&R": "CLIPLoader"
},
"widgets_values": [
"mistral_3_small_flux2_fp8.safetensors",
"flux2",
"default"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 5,
"type": "VAELoaderKJ",
"pos": [
22242.338811590744,
12459.450597519388
],
"size": [
270,
175.96875
],
"flags": {
"pinned": true
},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
22,
24,
47
]
}
],
"properties": {
"Node name for S&R": "VAELoaderKJ"
},
"widgets_values": [
"flux2-vae.safetensors",
"main_device",
"fp32"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 7,
"type": "TextEncodeQwenImageEdit",
"pos": [
22560,
13050
],
"size": [
287.875,
184.40625
],
"flags": {
"collapsed": false,
"pinned": true
},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 42
},
{
"name": "vae",
"shape": 7,
"type": "VAE",
"link": 47
},
{
"name": "image",
"shape": 7,
"type": "IMAGE",
"link": null
},
{
"name": "prompt",
"type": "STRING",
"widget": {
"name": "prompt"
},
"link": 51
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
41
]
}
],
"title": "Positive",
"properties": {
"Node name for S&R": "TextEncodeQwenImageEdit"
},
"widgets_values": [
"A painterly strong graphic novel illustration of a dynamic combat scene set within the catacombs of an abandoned cathedral during the Warhammer 40k universe. The composition is rendered with expressive brushwork that emphasizes the gritty texture of the environment against the warm glow of the setting sun.\n\n**Foreground Action:**\nThe lower section of the frame is dominated by the massive, red sash of a leviathan-clad warrior, its fabric rippling in the wind. He leans forward with aggressive momentum, his body angled slightly toward the viewer but his gaze fixed on the enemy ahead. His heavy, gold-trimmed leather armor is detailed with heavy pauldrons featuring intricate black and red sigils that catch the light. On his back, a large, segmented leviathan head—black bone and skin with glowing red eyes—recedes into the frame, its mouth open in a roar or claw strike. The texture of his leather is rough-hewn, with visible brushstrokes that emphasize the weight of his armor.\n\n**Mid-Ground Action:**\nTo the left, a towering figure in heavy, black leather armor with glowing red sigils on his chest stands in a dynamic pose. His massive, horned headpiece with jagged edges and a glowing red sigil on the forehead is a focal point of the scene. He holds a massive, glowing green weapon (the Leviathan's staff) diagonally across his body, the energy of the weapon rendered as distinct, pulsating lines that contrast sharply with the cool tones of his armor. The light from the weapon casts sharp, defined shadows on his face and chest, while the dust particles in the air catch the light, adding depth to the scene.\n\n**Background and Atmosphere:**\nThe upper portion of the image is defined by the cathedral's towering, gothic architecture with massive, arched windows that reveal a bright, hazy sky. The sun's rays, captured as distinct, glowing beams, slice through the dust and smoke, illuminating the dust motes floating in the air. The light creates a strong contrast between the warm, golden tones of the sunlit areas and the cool, purple shadows of the catacombs. The architecture is detailed with stone arches and windows that frame the action, their edges catching the light in sharp, defined points.\n\n**Lighting and Atmosphere:**\nThe lighting is high-contrast, with a golden sunbeam (god rays) cutting through the dust, creating a dramatic, almost theatrical illumination. The color palette is dominated by warm reds, golds, and deep purples, with the red sash and weapon providing a sharp visual anchor. The atmosphere is thick with dust and smoke, giving the scene a gritty, cinematic quality. The texture of the air is palpable, with the light beams creating a sense of volume and movement, while the stone walls of the cathedral are rendered with rough, detailed brushwork that emphasizes their ancient, crumbling nature."
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 9,
"type": "TextEncodeQwenImageEdit",
"pos": [
22871.35154241452,
13052.572534054745
],
"size": [
280.9375,
178.25
],
"flags": {
"collapsed": false,
"pinned": true
},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 34
},
{
"name": "vae",
"shape": 7,
"type": "VAE",
"link": 22
},
{
"name": "image",
"shape": 7,
"type": "IMAGE",
"link": null
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
8
]
}
],
"title": "Negative",
"properties": {
"Node name for S&R": "TextEncodeQwenImageEdit"
},
"widgets_values": [
"低分辨率低画质肢体畸形手指畸形画面过饱和蜡像感人脸无细节过度光滑画面具有AI感。构图混乱。文字模糊扭曲\n"
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 10,
"type": "KSampler",
"pos": [
23187.038623038603,
13019.460469625074
],
"size": [
338.5625,
316.65625
],
"flags": {
"collapsed": false,
"pinned": true
},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 37
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 41
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 8
},
{
"name": "latent_image",
"type": "LATENT",
"link": 12
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
9
]
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
906386284359144,
"fixed",
16,
6,
"euler",
"simple",
1
]
},
{
"id": 13,
"type": "VAEDecode",
"pos": [
23570.694240662328,
13334.885792891377
],
"size": [
225,
7.328125
],
"flags": {
"collapsed": true,
"pinned": true
},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 9
},
{
"name": "vae",
"type": "VAE",
"link": 24
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
11
]
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 14,
"type": "SaveImage",
"pos": [
23545.778409193183,
13017.942215410685
],
"size": [
264.78125,
315.328125
],
"flags": {
"pinned": true
},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 11
}
],
"outputs": [],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 15,
"type": "EmptySD3LatentImage",
"pos": [
22242.338811590744,
12669.450597519388
],
"size": [
264.34375,
143.328125
],
"flags": {
"collapsed": false,
"pinned": true
},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
12
]
}
],
"properties": {
"Node name for S&R": "EmptySD3LatentImage"
},
"widgets_values": [
1680,
720,
1
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 35,
"type": "PreviewAny",
"pos": [
22980,
11990
],
"size": [
746.09375,
310.625
],
"flags": {
"pinned": true
},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "source",
"type": "*",
"link": 49
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": []
}
],
"title": "Thinking",
"properties": {
"Node name for S&R": "PreviewAny",
"cnr_id": "comfy-core",
"ver": "0.19.0",
"enableTabs": false,
"tabWidth": 65,
"tabXOffset": 10,
"hasSecondTab": false,
"secondTabText": "Send Back",
"secondTabOffset": 80,
"secondTabWidth": 65,
"ue_properties": {
"widget_ue_connectable": {},
"version": "7.7",
"input_ue_unconnectable": {}
}
},
"widgets_values": [
null,
null,
null
],
"color": "#223",
"bgcolor": "#335"
},
{
"id": 36,
"type": "PreviewAny",
"pos": [
22980,
12360
],
"size": [
759.1875,
600.34375
],
"flags": {
"pinned": true
},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "source",
"type": "*",
"link": 48
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": []
}
],
"title": "Composition",
"properties": {
"Node name for S&R": "PreviewAny",
"cnr_id": "comfy-core",
"ver": "0.19.0",
"enableTabs": false,
"tabWidth": 65,
"tabXOffset": 10,
"hasSecondTab": false,
"secondTabText": "Send Back",
"secondTabOffset": 80,
"secondTabWidth": 65,
"ue_properties": {
"widget_ue_connectable": {},
"version": "7.7",
"input_ue_unconnectable": {}
}
},
"widgets_values": [
null,
null,
null
],
"color": "#223",
"bgcolor": "#335"
},
{
"id": 37,
"type": "MordantPromptEnhancer",
"pos": [
22587.859813643525,
12162.405451552098
],
"size": [
353.96875,
728.65625
],
"flags": {
"pinned": true
},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "composition",
"type": "STRING",
"links": [
48,
51
]
},
{
"name": "thinking",
"type": "STRING",
"links": [
49
]
}
],
"properties": {
"Node name for S&R": "MordantPromptEnhancer"
},
"widgets_values": [
"models\\Kezmark\\Mordant-1.2B-BF16\\Mordant-1.2B-BF16.gguf",
"",
"enhancer",
true,
true,
8192,
325853571,
"randomize",
0.7,
0.95,
50,
1,
2048,
false,
true,
true,
false,
"",
""
],
"color": "#223",
"bgcolor": "#335"
}
],
"links": [
[
8,
9,
0,
10,
2,
"CONDITIONING"
],
[
9,
10,
0,
13,
0,
"LATENT"
],
[
11,
13,
0,
14,
0,
"IMAGE"
],
[
12,
15,
0,
10,
3,
"LATENT"
],
[
22,
5,
0,
9,
1,
"VAE"
],
[
24,
5,
0,
13,
1,
"VAE"
],
[
34,
4,
0,
9,
0,
"CLIP"
],
[
37,
2,
0,
10,
0,
"MODEL"
],
[
41,
7,
0,
10,
1,
"CONDITIONING"
],
[
42,
4,
0,
7,
0,
"CLIP"
],
[
47,
5,
0,
7,
1,
"VAE"
],
[
48,
37,
0,
36,
0,
"STRING"
],
[
49,
37,
1,
35,
0,
"STRING"
],
[
51,
37,
0,
7,
3,
"STRING"
]
],
"groups": [
{
"id": 1,
"title": "Loaders",
"bounding": [
22232.338811590744,
11929.450597519388,
290.8125,
893.328125
],
"color": "#3f789e",
"flags": {}
},
{
"id": 2,
"title": "Prompt",
"bounding": [
22550,
12980,
612.2890424145189,
264.421875
],
"color": "#3f789e",
"flags": {}
},
{
"id": 3,
"title": "Prompt Enhancer",
"bounding": [
22570,
11920,
1187.4399139007546,
1055.7277089007566
],
"color": "#3f789e",
"flags": {}
}
],
"config": {},
"extra": {
"ds": {
"scale": 0.31863081771035934,
"offset": [
-21670.282977170747,
-11392.588403980808
]
},
"frontendVersion": "1.44.19",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}