Improving the Name Generator using ChatGPT


I wasn't happy with the Markov chain name generator that ChatGPT provided, as it often produced names that were difficult to pronounce and sounded like gibberish. I knew that I had to improve it at some point, so I decided to do that today!

I wasn't sure how to improve it, so I turned to ChatGPT for advice and it suggested that the current implementation of the Markov chain only considers the next character after a pair of characters, which is not entirely accurate. The probability of the next character depends on more than one preceding character. For example, the probability of "ie" being followed by "n" is much higher than "i" being followed by "n". To make the names more realistic and pronounceable, ChatGPT suggested using higher-order n-grams (such as trigrams or quadgrams) instead of bigrams. It also suggested using syllables, phenomes, and constraints.

I decided to choose to use syllables extracted from the list of names I provided rather than use phenomes because it would require the least amount of changes. The BuildChain method was modified to split each name into syllables using a simple set of rules based on vowels and consonants. Whenever a vowel was encountered, a new syllable was created, and any subsequent consonants were added to the current syllable until the next vowel was found. This process was repeated until the end of the name was reached.

The resulting list of syllables was used to build the Markov chain, , rather than just pairs of characters in the previous implementation. In the GenerateName method, the last syllable of each generated name was used as the key for the chain.

After implementing the updated code, I tested it thoroughly to ensure that it was generating realistic and pronounceable names. The results were great! The names, if they could speak for themselves, would not sound like random noise anymore! :D

Here is the updated code:

using System; 
using System.Collections.Generic; 
using System.Linq;  
     class NameGenerator
     {
         private readonly Dictionary<string, list<string="">> _chain = new Dictionary<string, list<string="">>();
         private readonly List<string> _vowels = new List<string> { "a", "e", "i", "o", "u", "y" };
         public NameGenerator(List<string> names)
         {
             BuildChain(names);
         }
         private void BuildChain(List<string> names)
         {
             foreach (var name in names)
             {
                 var syllables = new List<string>();
                 var currentSyllable = "";
                 for (int i = 0; i < name.Length; i++)
                 {
                     var c = name[i];
                     if (_vowels.Contains(c.ToString()))
                     {
                         syllables.Add(currentSyllable);
                         currentSyllable = c.ToString();
                     }
                     else
                     {
                         currentSyllable += c.ToString();
                     }
                 }
                 syllables.Add(currentSyllable);
                 for (int i = 0; i < syllables.Count - 1; i++)
                 {
                     var key = syllables[i];
                     var nextSyllable = syllables[i + 1];
                     if (!_chain.ContainsKey(key))
                     {
                         _chain[key] = new List<string>();
                     }
                     _chain[key].Add(nextSyllable);
                 }
             }
         }
         public string GenerateName(Random random)
         {
             var currentKey = _chain.Keys.ElementAt(random.Next(_chain.Keys.Count));
             var name = currentKey;
             while (true)
             {
                 if (!_chain.TryGetValue(currentKey, out List<string> nextSyllables))
                 {
                     break;
                 }
                 var nextSyllable = nextSyllables[random.Next(nextSyllables.Count)];
                 name += nextSyllable;
                 if (name.Length >= 20)
                 {
                     break;
                 }
                 var lastSyllable = "";
                 for (int i = name.Length - 1; i >= 0; i--)
                 {
                     var c = name[i];
                     if (_vowels.Contains(c.ToString()))
                     {
                         lastSyllable = name.Substring(i);
                         break;
                     }
                 }
                 currentKey = lastSyllable;
             }
             return char.ToUpper(name[0]) + name.Substring(1);
         }
     }

Leave a comment

Log in with itch.io to leave a comment.