""" 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 ") 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()