- Add extract_trigger_words() method supporting Civitai, Kohya, AI Toolkit, SimpleTuner, OneTrainer - Add auto_trigger toggle to inject trigger words at LoRA tag positions - Add trigger_words output socket with all extracted triggers - Enhanced lora_info output to show trigger words per LoRA - Fix duplicate LoRA tags causing rendering issues (v1.4.1) - Update README with new examples and documentation - Update CHANGELOG with v1.4.1 and v1.5.0 entries
128 lines
3.7 KiB
Python
128 lines
3.7 KiB
Python
"""
|
|
Simple test script for the LoRA Tag Power Loader parser
|
|
Run this to verify tag parsing logic works correctly
|
|
"""
|
|
|
|
import re
|
|
|
|
|
|
def parse_lora_tag(tag_content, default_weight=1.0):
|
|
"""
|
|
Parse LoRA tag with hybrid format.
|
|
"""
|
|
parts = [p.strip() for p in tag_content.split(':')]
|
|
|
|
if len(parts) < 1 or not parts[0]:
|
|
return None
|
|
|
|
result = {
|
|
'name': parts[0],
|
|
'high_noise': default_weight,
|
|
'low_noise': default_weight,
|
|
'clip': default_weight
|
|
}
|
|
|
|
try:
|
|
if len(parts) == 2:
|
|
# Single weight: use everywhere
|
|
weight = float(parts[1])
|
|
result['high_noise'] = weight
|
|
result['low_noise'] = weight
|
|
result['clip'] = weight
|
|
|
|
elif len(parts) == 3:
|
|
# Dual noise: different high/low, clip follows high
|
|
result['high_noise'] = float(parts[1])
|
|
result['low_noise'] = float(parts[2])
|
|
result['clip'] = result['high_noise']
|
|
|
|
elif len(parts) >= 4:
|
|
# Full control: high, low, clip all separate
|
|
result['high_noise'] = float(parts[1])
|
|
result['low_noise'] = float(parts[2])
|
|
result['clip'] = float(parts[3])
|
|
|
|
except (ValueError, IndexError) as e:
|
|
print(f"Error parsing tag '{tag_content}': {e}")
|
|
return None
|
|
|
|
return result
|
|
|
|
|
|
def test_tag_parsing():
|
|
"""Test various tag formats"""
|
|
|
|
test_cases = [
|
|
# (input, description)
|
|
("style_lora:0.8", "Single weight"),
|
|
("detail:1.2:0.3", "Dual noise"),
|
|
("character:1.0:0.8:0.6", "Full control"),
|
|
("background:0.7", "Name only with weight"),
|
|
("lighting:1.5:0.5", "High/low different"),
|
|
("texture", "Name only (should use defaults)"),
|
|
("complex_name:0.9:0.9:0.7", "Same high/low, different clip"),
|
|
]
|
|
|
|
print("=" * 70)
|
|
print("LoRA Tag Parser Test")
|
|
print("=" * 70)
|
|
|
|
for tag, description in test_cases:
|
|
result = parse_lora_tag(tag)
|
|
print(f"\nTest: {description}")
|
|
print(f"Input: <lora:{tag}>")
|
|
if result:
|
|
print(f"Result:")
|
|
print(f" Name: {result['name']}")
|
|
print(f" High Noise: {result['high_noise']:.2f}")
|
|
print(f" Low Noise: {result['low_noise']:.2f}")
|
|
print(f" Clip: {result['clip']:.2f}")
|
|
else:
|
|
print("Result: FAILED TO PARSE")
|
|
|
|
print("\n" + "=" * 70)
|
|
|
|
|
|
def test_text_extraction():
|
|
"""Test extracting tags from full text"""
|
|
|
|
test_texts = [
|
|
"A beautiful portrait <lora:style:0.8> with lighting",
|
|
"Epic <lora:cinematic:1.2:0.4> landscape with <lora:detail:0.9:0.5>",
|
|
"Simple text without any loras",
|
|
"<lora:test1:0.5> <lora:test2:1.0:0.3> <lora:test3:0.8:0.6:0.5>",
|
|
]
|
|
|
|
tag_pattern = r"<lora:([^>]+)>"
|
|
|
|
print("\n" + "=" * 70)
|
|
print("Text Extraction Test")
|
|
print("=" * 70)
|
|
|
|
for text in test_texts:
|
|
print(f"\nInput text: {text}")
|
|
matches = re.finditer(tag_pattern, text)
|
|
lora_tags = [match.group(1) for match in matches]
|
|
|
|
if lora_tags:
|
|
print(f"Found {len(lora_tags)} tag(s):")
|
|
for i, tag in enumerate(lora_tags, 1):
|
|
parsed = parse_lora_tag(tag)
|
|
if parsed:
|
|
print(f" {i}. {parsed['name']} - H:{parsed['high_noise']:.2f} L:{parsed['low_noise']:.2f} C:{parsed['clip']:.2f}")
|
|
else:
|
|
print("No tags found")
|
|
|
|
# Show cleaned text
|
|
cleaned = re.sub(tag_pattern, "", text)
|
|
cleaned = re.sub(r'\s+', ' ', cleaned).strip()
|
|
print(f"Cleaned text: {cleaned}")
|
|
|
|
print("\n" + "=" * 70)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_tag_parsing()
|
|
test_text_extraction()
|
|
print("\n✓ All tests completed!")
|