I am a curious person. I enjoy building projects that don’t necessarily have any purpose other than to explore a new toolset and make something fun. I picked up Python a while back because I wanted to explore the universe of chatbots and some basic variations on AI. Caveat: I’m no expert, I’m only an explorer.
Beside the motivating factors of: I love building things, I love playing with new tools, and I want to see how to push the limits; I also have a sandbox that I like to populate with interactive projects. I run a MUD. Well, it’s technically a MUX, running on TinyMUX for those in the know. A MUD is the original multiplayer online game. These are text-based universes, and mine is social-themed. It used to be a lot more active and now feels a bit empty. So, I plan to populate it with a bot or two.
The initial solution was an off-the-shelf bot from GitHub that could connect into a MUD and understand (with some tinkering) the interaction model for the game. It already came with a basic Wikipedia lookup, regular expression interaction, and a simple Markov chain. While I’ve tinkered around with its personality and plumbing, the biggest change I’ve made was to rip out its OEM Markov mechanism and replace it with Markovify.
* * *
Now let’s step aside to another branch of this story before everything meets up again. Every year a friend hosts a Halloween party where he encourages guests to create some sort of gothic story, or poem and read it to the group. I decided to polish up my chatbot, feed it a corpus of gothic poetry, and have the bot itself be my submission.
There were a couple challenges along the way. Building and cleaning up a text corpus for a simplified text environment was critical. Did I want poem titles parsed into the Markov chain? Then I needed to give them punctuation. Additionally, characters that are fine for web pages and word documents needed simplification: em-dashes and en-dashes become the simple dash, single-quotes become apostrophes, etc. Then I attempted to beef up the parsing of my gothic texts with some natural language processing. Whoops.
A fun thing with Markovify is that you can overwrite methods and incorporate libraries like spaCy. Now you can identify the parts of speech for all your words before building your ngrams. And now your Markov chain can create a more convincing and interesting sentence. I ran a single Markov request, asking my bot to create a five-line poem. Then it crashed, and my Sysadmin wasn’t too happy with me.
While my chatbot interacts by talking with players in my MUD, the chatbot program lives on a separate service. That service is a web host and you don’t need a lot of memory for web pages. Adding spaCy was great, but it also loaded up the entire corpus into memory, and kept its parsed information in memory pushing me past my account’s allocation by at least double before the system killed it.
Lesson learned. Either subscribe to a service dedicated to applications with more memory available, or pre-parse the text offline and upload the saved model for the bot’s consumption. The latter will be my solution for my hack-and-slash approach.
* * *
Without the pre-processing, my RavenBOT works quite well regardless. This was a long introduction to show you the results. So below, I’m sharing the “gothic” poems created on the fly by RavenBOT as submitted that evening for the party.
These poems drew from two corpora: a general gothic poetry collection, and a collection of Lovecraft’s poetry. Each poem is a singular stanza consisting of five lines each.
Lovecraftian Poem 1
There’s an ancient, ancient garden that I cannot endure to recall.
Eternal brood the shadows of the ages, I have haunted the tombs of the wooded park.
Only the lean cats that howl in the pallid ray, sprung out of the ages, I have trod its untenanted hall, where the gaudy-tinted blossoms seem to wither into grey, and the harpies of upper air, that flutter and laugh and stare.
Legions of cats from the graves of the wooded park.
Mystic waves of beauty blended with the moans of invisible daemons, that out of the dark, from the knowledge of terrors forgotten and dead.
Gothic Poem 1
11 And by the Window.
O weary lady, Geraldine, I cannot tell — I thought I needed a mate for a lady’s chamber meet: the lamp with twofold silver chain is fastened to an untold murder.
Up starts the lark beside the many saintly figures fronting the cathedral’s gothic tympanum, close by the wind-extinct; The Crusaders’ streams of shadowy, midnight troops, sped with the setting sun, and ere the crimson sunset glow from the rough rage of swelling seas.
And there was no solace in the sun, or like a dark crime; it is the solemn noon of night, when haply wakeful from my house by a row of headstones.
Of higher birth he seem’d, and better days, nor mark of vulgar toil that hand that rein’d: and some deep feeling it were vain to trace his youth through all the monstrous debt.
Lovecraftian Poem 2
There is death in the dark let the lemurs bark, and the crumbling walls and pillars waken thoughts of yesterday.
I had wander’d in rapture beneath them, and bask’d in the plazas, and eyed their stone features with awe.
The cloudless day is richer at its close; A golden moon bewitching radiance yields, and England’s fairies trip o’er England’s fields.
Haughty Sphinx, whose amber eyes hold the secrets of the dark, from the alleys nocturnal.
A chill wind blows through the rows of white urn-carven marble, I listen intently for sound.
Gothic Poem 2
His page approach’d, and he scarce could brook tears, at the pompous gate.
I think they should not stay alone.
He raised the bleeding Otho, and the lady Geraldine.
Do not mention force, or you will allow me to the wall, I sat and watched the white-glazed inner walls sink in shame to shattered heaps of down.
And Lara call’d his page, and went to leave no other trace of his friend!
Lovecraftian Poem 0
The following poem was created via the powers of a more powerful NLP pre-processing utilizing SpaCy. It subsequently crashed the system with a memory overflow and made my Sysadmin fairly unhappy. Here are the entrails.
Forests may fall, but not the dusk they shield; So on the ground, and the crumbling walls and pillars waken thoughts of yesterday.
Done are my trials; my heart from thee?
White and amazing to the orb of sweet dreams.
Once on the forms in the wild moonlight, and the tangled weedy thicket chokes the arbour dark and cool: in the meadows that shimmer pale, and comes to twine where the wide waters rumble, back to the scene of the Seekonk, and a tremor seems to start — For I know the fiendish fable that the golden glitter bore; Now I know the fiendish fable that the golden glitter bore; Now I know the flow’rs are shrivell’d hopes — the garden is my heart.
Thus the living, lone and sobbing, In the lyre-born chords extended Harmonies of Lydian lays.