Merge pull request #2 from Limbicnation/feature/lora-integration

Feature/lora integration
This commit is contained in:
Gero Doll
2026-02-02 04:04:36 +01:00
committed by GitHub
4 changed files with 118 additions and 5 deletions
+28
View File
@@ -88,3 +88,31 @@ comfy node publish --confirm
1. Add entry to `config/templates.yaml` following existing format
2. Add style key to `INPUT_TYPES()` style combo list in `prompt_generator_node.py`
3. Optionally add to `DEFAULT_STYLES` dict for fallback when YAML unavailable
- **Current version**: `1.1.1` - Added dynamic LoRA model selection and prioritization. (2026-02-02)
- **LoRA Training**: Trained QLoRA on Qwen3-4B-Instruct-2507 using the Limbicnation Video Diffusion Prompt dataset.
- **Quantization**: Merged LoRA and converted to Q8_0 GGUF for Ollama.
- **Integration**: `PromptGeneratorNode` now auto-discovers and prioritizes models containing `lora` or `limbicnation` keywords.
### Creating a LoRA-Enhanced Model
1. Fine-tune a LoRA on the [Limbicnation/Images-Diffusion-Prompt-Style](https://huggingface.co/datasets/Limbicnation/Images-Diffusion-Prompt-Style) dataset (750 prompts)
2. Export as `.safetensors` (non-quantized recommended)
3. Create the Ollama model:
```bash
# Edit config/Modelfile.limbicnation with your adapter path
ollama create qwen3-limbicnation -f config/Modelfile.limbicnation
```
4. Restart ComfyUI - the new model will appear in the dropdown
### Modelfile Template
See `config/Modelfile.limbicnation` for a pre-configured template with:
- Limbicnation system prompt
- Optimal temperature/top_p settings
- ADAPTER placeholder for your LoRA
+33
View File
@@ -0,0 +1,33 @@
# Limbicnation LoRA Modelfile Template
#
# This Modelfile creates an Ollama model with the Limbicnation image prompt style LoRA.
#
# Usage:
# 1. Fine-tune your LoRA using the 750 prompts from Limbicnation/Images-Diffusion-Prompt-Style
# 2. Export as .safetensors (non-quantized recommended)
# 3. Update the ADAPTER path below
# 4. Run: ollama create qwen3-limbicnation -f Modelfile.limbicnation
# 5. Test: ollama run qwen3-limbicnation "Generate a cinematic forest prompt"
# Base model - use the same model you fine-tuned the LoRA on
FROM qwen3:4b
# LoRA adapter path (update this to your fine-tuned adapter)
# ADAPTER /path/to/limbicnation-lora.safetensors
# System prompt for image prompt generation
SYSTEM """You are an expert AI Image Prompt Engineer specializing in the "Limbicnation" aesthetic.
Your prompts emphasize: cinematic lighting, intricate textures, evocative atmosphere, dramatic compositions.
When generating image prompts:
1. Use rich, sensory language
2. Include quality tokens: photorealistic, 8k, detailed, masterpiece
3. Specify lighting and atmosphere
4. Add negative prompts when requested
5. Format for Flux, Z Image, or Stable Diffusion models
"""
# Optimal parameters for prompt generation
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER num_ctx 4096
+55 -3
View File
@@ -191,14 +191,64 @@ Format the response as a single, detailed sci-fi prompt."""
}
}
# Class-level cache for available models
_cached_models = None
_cache_time = 0
def __init__(self):
"""Initialize the node and load style templates."""
self.style_templates = self._load_templates()
self.timeout = 120
@classmethod
def _get_available_models(cls) -> list:
"""
Fetch available Ollama models with caching.
Prioritizes LoRA-enhanced models (containing 'lora', 'limbicnation', 'fine').
"""
import time
# Cache for 60 seconds
if cls._cached_models and (time.time() - cls._cache_time) < 60:
return cls._cached_models
default_models = ["qwen3:8b", "qwen3:4b", "llama3.2:latest"]
if not OLLAMA_API_AVAILABLE:
return default_models
try:
result = ollama.list()
models = [m['name'] for m in result.get('models', []) if 'name' in m]
if not models:
return default_models
# Sort: LoRA/fine-tuned models first, then alphabetically
lora_keywords = ['lora', 'limbicnation', 'fine', 'style', 'prompt']
def sort_key(name):
name_lower = name.lower()
is_lora = any(kw in name_lower for kw in lora_keywords)
return (0 if is_lora else 1, name)
models = sorted(models, key=sort_key)
cls._cached_models = models
cls._cache_time = time.time()
print(f"[PromptGenerator] Found {len(models)} Ollama models")
return models
except Exception as e:
print(f"[PromptGenerator] Could not fetch models: {e}")
return default_models
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""Define input parameters for the node."""
available_models = cls._get_available_models()
return {
"required": {
"description": ("STRING", {
@@ -210,6 +260,10 @@ Format the response as a single, detailed sci-fi prompt."""
"abstract", "cyberpunk", "sci-fi"], {
"default": "cinematic"
}),
"model": (available_models, {
"default": available_models[0] if available_models else "qwen3:8b",
"tooltip": "Select Ollama model. LoRA-enhanced models appear first."
}),
},
"optional": {
"emphasis": ("STRING", {
@@ -239,9 +293,6 @@ Format the response as a single, detailed sci-fi prompt."""
"label_on": "Show Reasoning",
"label_off": "Hide Reasoning"
}),
"model": ("STRING", {
"default": "qwen3:8b"
}),
}
}
@@ -250,6 +301,7 @@ Format the response as a single, detailed sci-fi prompt."""
FUNCTION = "generate"
CATEGORY = "text/generation"
OUTPUT_NODE = False
def _load_templates(self) -> Dict[str, Any]:
"""Load style templates from YAML file or use defaults."""
+2 -2
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-prompt-generator"
description = "Generate Stable Diffusion prompts using Qwen3-8B via Ollama with 7 style presets"
version = "1.0.5"
description = "Generate Stable Diffusion prompts using Qwen/Ollama with LoRA support and 7 style presets"
version = "1.1.2"
license = {file = "LICENSE"}
readme = "README.md"
requires-python = ">=3.10"