krystv's picture
Add interactive generation script
c9e1658 verified
Raw
History Blame Contribute Delete
9.41 kB
"""
NeuroLex v4 โ€” Interactive Name Generator
=========================================
Generate creative names from a trained model.
Usage:
python generate.py --checkpoint checkpoints/neurolex_v4_best.pt
python generate.py --checkpoint checkpoints/neurolex_v4_best.pt --domain tech --style sharp --lang english --n 50
python generate.py --checkpoint checkpoints/neurolex_v4_best.pt --interactive
Or without a checkpoint (uses random untrained model for testing structure):
python generate.py --test
"""
import torch
import argparse
import sys
import os
from neurolex_v4_model import (
NeuroLexV4, NeuroLexConfig, CharTokenizer, create_model,
DOMAINS, STYLES, LANGUAGES, DOMAIN_TO_ID, STYLE_TO_ID, LANG_TO_ID
)
def load_model(checkpoint_path: str, device: str = 'auto'):
"""Load a trained model from checkpoint."""
if device == 'auto':
device = 'cuda' if torch.cuda.is_available() else 'cpu'
checkpoint = torch.load(checkpoint_path, map_location=device)
config = NeuroLexConfig(**checkpoint['config'])
model = NeuroLexV4(config)
model.load_state_dict(checkpoint['state_dict'])
model.eval()
model.to(device)
print(f"Model loaded from {checkpoint_path}")
print(f" Parameters: {model.count_parameters():,}")
print(f" Device: {device}")
return model, config, device
def generate_names(model, device, domain='tech', style='sharp', lang='english',
length=8, n=20, cfg_scale=2.5, temperature=0.9,
n_steps=80, odd_alpha=8.0):
"""Generate names with given parameters."""
domain_id = DOMAIN_TO_ID.get(domain, 0)
style_id = STYLE_TO_ID.get(style, 0)
lang_id = LANG_TO_ID.get(lang, 0)
names = model.generate(
domain_id=domain_id,
style_id=style_id,
lang_id=lang_id,
target_length=length,
batch_size=n,
cfg_scale=cfg_scale,
temperature=temperature,
n_steps=n_steps,
odd_alpha=odd_alpha,
device=str(device)
)
return names
def interactive_mode(model, device):
"""Interactive generation mode."""
print("\n" + "=" * 60)
print(" NEUROLEX v4 โ€” INTERACTIVE NAME GENERATOR")
print("=" * 60)
print(f"\n Available domains: {', '.join(DOMAINS)}")
print(f" Available styles: {', '.join(STYLES)}")
print(f" Available languages: {', '.join(LANGUAGES[:12])}...")
print(f"\n Type 'quit' to exit, 'help' for commands")
print("=" * 60)
while True:
try:
print("\n")
domain = input(" Domain [tech]: ").strip() or 'tech'
if domain == 'quit':
break
if domain == 'help':
print(f"\n Domains: {', '.join(DOMAINS)}")
print(f" Styles: {', '.join(STYLES)}")
print(f" Languages: {', '.join(LANGUAGES)}")
continue
style = input(" Style [sharp]: ").strip() or 'sharp'
lang = input(" Language [english]: ").strip() or 'english'
length = int(input(" Target length [8]: ").strip() or '8')
n = int(input(" How many [20]: ").strip() or '20')
temp = float(input(" Temperature [0.9]: ").strip() or '0.9')
cfg = float(input(" CFG scale [2.5]: ").strip() or '2.5')
print(f"\n Generating {n} names...")
print(f" [{domain} / {style} / {lang} / len={length} / temp={temp} / cfg={cfg}]")
print()
names = generate_names(
model, device, domain=domain, style=style, lang=lang,
length=length, n=n, cfg_scale=cfg, temperature=temp
)
unique = set(n.lower() for n in names)
for i, name in enumerate(names, 1):
print(f" {i:3d}. {name}")
print(f"\n Generated: {len(names)} | Unique: {len(unique)} ({len(unique)/max(len(names),1)*100:.0f}%)")
except KeyboardInterrupt:
break
except Exception as e:
print(f" Error: {e}")
print("\n Goodbye! ๐Ÿ‘‹")
def showcase_mode(model, device):
"""Generate a showcase across all categories."""
print("\n" + "=" * 70)
print(" NEUROLEX v4 โ€” FULL SHOWCASE")
print("=" * 70)
showcases = [
("๐Ÿ–ฅ๏ธ Tech Startup", 'tech', 'sharp', 'english', 8),
("๐Ÿ–ฅ๏ธ Tech (Futuristic)", 'tech', 'futuristic', 'japanese', 7),
("๐Ÿœ Food Brand", 'food', 'warm', 'french', 7),
("๐ŸŽฎ Gaming Channel", 'gaming', 'bold', 'english', 9),
("๐Ÿ’Ž Luxury Brand", 'luxury', 'elegant', 'italian', 8),
("๐Ÿค– AI Company", 'ai', 'sharp', 'latin', 7),
("๐ŸŒฟ Health/Wellness", 'health', 'organic', 'hawaiian', 7),
("๐Ÿช™ Crypto Project", 'crypto', 'futuristic', 'greek', 8),
("๐ŸŽต Music Platform", 'music', 'playful', 'spanish', 7),
("โ™ป๏ธ Eco Brand", 'eco', 'warm', 'swedish', 7),
("๐Ÿ’ช Fitness App", 'fitness', 'bold', 'german', 8),
("๐ŸŒ Social Platform", 'social', 'playful', 'korean', 6),
("โœจ Beauty Brand", 'beauty', 'elegant', 'french', 8),
("๐ŸŽ๏ธ Automotive", 'automotive', 'bold', 'italian', 8),
("๐Ÿ“š Education", 'education', 'professional', 'latin', 8),
("๐ŸŒ Travel", 'travel', 'warm', 'hawaiian', 7),
]
all_names = []
for label, domain, style, lang, length in showcases:
names = generate_names(
model, device, domain=domain, style=style, lang=lang,
length=length, n=12, n_steps=80
)
all_names.extend(names)
print(f"\n {label} ({style}, {lang}):")
for name in names[:8]:
print(f" โ†’ {name}")
# Summary
unique = set(n.lower() for n in all_names)
print(f"\n{'โ”€' * 70}")
print(f" ๐Ÿ“Š TOTAL: {len(all_names)} names generated")
print(f" ๐ŸŽฏ UNIQUE: {len(unique)} ({len(unique)/len(all_names)*100:.1f}%)")
print(f" ๐Ÿ“ AVG LENGTH: {sum(len(n) for n in all_names)/len(all_names):.1f} chars")
print(f"{'โ”€' * 70}")
def main():
parser = argparse.ArgumentParser(description='Generate names with NeuroLex v4')
parser.add_argument('--checkpoint', type=str, help='Path to model checkpoint')
parser.add_argument('--test', action='store_true', help='Test with untrained model')
parser.add_argument('--interactive', action='store_true', help='Interactive mode')
parser.add_argument('--showcase', action='store_true', help='Generate showcase across all categories')
parser.add_argument('--domain', type=str, default='tech')
parser.add_argument('--style', type=str, default='sharp')
parser.add_argument('--lang', type=str, default='english')
parser.add_argument('--length', type=int, default=8)
parser.add_argument('--n', type=int, default=20)
parser.add_argument('--cfg_scale', type=float, default=2.5)
parser.add_argument('--temperature', type=float, default=0.9)
parser.add_argument('--n_steps', type=int, default=80)
parser.add_argument('--odd_alpha', type=float, default=8.0)
parser.add_argument('--device', type=str, default='auto')
parser.add_argument('--size', type=str, default='base', choices=['tiny', 'small', 'base', 'large'])
args = parser.parse_args()
# Load or create model
if args.checkpoint and os.path.exists(args.checkpoint):
model, config, device = load_model(args.checkpoint, args.device)
elif args.test:
print("Creating untrained model for testing...")
model, config = create_model(args.size)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if args.device == 'auto' else torch.device(args.device)
model.to(device)
model.eval()
else:
# Try default path
default_paths = [
'checkpoints/neurolex_v4_best.pt',
'checkpoints/neurolex_v4_final.pt',
'neurolex_v4_trained.pt',
]
loaded = False
for path in default_paths:
if os.path.exists(path):
model, config, device = load_model(path, args.device)
loaded = True
break
if not loaded:
print("No checkpoint found. Use --test for untrained model or --checkpoint <path>")
print(f"Searched: {default_paths}")
sys.exit(1)
# Run mode
if args.interactive:
interactive_mode(model, device)
elif args.showcase:
showcase_mode(model, device)
else:
# Single generation
names = generate_names(
model, device,
domain=args.domain, style=args.style, lang=args.lang,
length=args.length, n=args.n,
cfg_scale=args.cfg_scale, temperature=args.temperature,
n_steps=args.n_steps, odd_alpha=args.odd_alpha
)
print(f"\n Generated {len(names)} names [{args.domain}/{args.style}/{args.lang}]:")
for i, name in enumerate(names, 1):
print(f" {i:3d}. {name}")
unique = set(n.lower() for n in names)
print(f"\n Unique: {len(unique)}/{len(names)} ({len(unique)/max(len(names),1)*100:.0f}%)")
if __name__ == '__main__':
main()