Haiku
This commit is contained in:
+84
-1
@@ -4,6 +4,7 @@ from discord.ext import commands
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import random
|
import random
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
class Chatbot(object):
|
class Chatbot(object):
|
||||||
"""Een heuse chatbot. Under construction..."""
|
"""Een heuse chatbot. Under construction..."""
|
||||||
@@ -274,7 +275,7 @@ class Chatbot(object):
|
|||||||
responsePairDict = wordDict['responsePairs']
|
responsePairDict = wordDict['responsePairs']
|
||||||
#TODO store in global variable to minimise IO?
|
#TODO store in global variable to minimise IO?
|
||||||
|
|
||||||
#Wtart with <SOM>
|
#Start with <SOM>
|
||||||
chain = [self.START_OF_MESSAGE]
|
chain = [self.START_OF_MESSAGE]
|
||||||
|
|
||||||
#Go through the chain:
|
#Go through the chain:
|
||||||
@@ -328,3 +329,85 @@ class Chatbot(object):
|
|||||||
#yield from ctx.channel.send(' '.join(chain))
|
#yield from ctx.channel.send(' '.join(chain))
|
||||||
return ' '.join(chain)
|
return ' '.join(chain)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Try to count the number of syllables in a word
|
||||||
|
#Used to make Haikus
|
||||||
|
def countSyllables(self, word: str):
|
||||||
|
KNOWN_ACRONYMS = ["aub", "svp", "ivm", "nr", "zsm", "mbt", "tmi", "fyi", "afk", "omg", "idk", "coc"]
|
||||||
|
word = word.lower().strip()
|
||||||
|
|
||||||
|
#for acryonyms, just count the letters:
|
||||||
|
if word in KNOWN_ACRONYMS or re.match("^([a-z]{1}[.]{1}){2,}$", word) or re.match("^([bcdfghjklmnpqrstvwxz]){2,}$", word):
|
||||||
|
return len(word.replace(".", ""))
|
||||||
|
|
||||||
|
#count vowels surrounded by consonants
|
||||||
|
count = len(re.findall("[bcdfghjklmnpqrstvwxyz]{1}[aeiouyëäïöüéèáà]{1,2}[bcdfghjklmnpqrstvwxz]{0,1}|[aeiouyëäïöüéèáà]{1,2}[bcdfghjklmnpqrstvwxz]{1}", word))
|
||||||
|
count += len(re.findall("[ëäï]", word)) #ideeën etc
|
||||||
|
|
||||||
|
return max(1, count)
|
||||||
|
|
||||||
|
#Append a message change with a numer of syllables
|
||||||
|
#If it returns False, it couldn't find anything
|
||||||
|
#It's recursive, yo
|
||||||
|
def appendMessageWithNrOfSyllables(self, nrOfSyl: int, chain, wordPairDict):
|
||||||
|
#Find the possibilities:
|
||||||
|
if chain[-1] == "\n":
|
||||||
|
pairPossibilities = wordPairDict[chain[-2]].copy()
|
||||||
|
else:
|
||||||
|
pairPossibilities = wordPairDict[chain[-1]].copy()
|
||||||
|
|
||||||
|
for poss in list(pairPossibilities.keys()):
|
||||||
|
if self.countSyllables(poss) > nrOfSyl or poss == self.END_OF_MESSAGE: #TODO change to constant
|
||||||
|
del pairPossibilities[poss]
|
||||||
|
|
||||||
|
if len(pairPossibilities) == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
#Calculate probabilities and pick a next word:
|
||||||
|
possible_words = list(pairPossibilities.keys())
|
||||||
|
weights = np.array(list(pairPossibilities.values()))
|
||||||
|
probs = weights / weights.sum()
|
||||||
|
chain.append(np.random.choice(possible_words, p=probs))
|
||||||
|
#TODO this is duplicate code. reuse the stuff from getResponseForMessage()
|
||||||
|
|
||||||
|
if self.countSyllables(chain[-1]) == nrOfSyl:
|
||||||
|
return chain
|
||||||
|
#RECURSION!
|
||||||
|
return self.appendMessageWithNrOfSyllables( (nrOfSyl-self.countSyllables(chain[-1])) , chain, wordPairDict)
|
||||||
|
|
||||||
|
#Make a nice Haiku
|
||||||
|
def getHaiku(self):
|
||||||
|
MAX_N_TRIES = 50
|
||||||
|
|
||||||
|
#Get dictionary/Markov chain
|
||||||
|
wordDict = np.load('markov_dict.npy').item()
|
||||||
|
wordPairDict = wordDict['pairs']
|
||||||
|
|
||||||
|
#try:
|
||||||
|
for i in range(1, MAX_N_TRIES):
|
||||||
|
chain = [self.START_OF_MESSAGE]
|
||||||
|
|
||||||
|
chain = self.appendMessageWithNrOfSyllables(5, chain, wordPairDict)
|
||||||
|
if chain is not False:
|
||||||
|
chain.append("\n")
|
||||||
|
chain = self.appendMessageWithNrOfSyllables(7, chain, wordPairDict)
|
||||||
|
if chain is not False:
|
||||||
|
chain.append("\n")
|
||||||
|
chain = self.appendMessageWithNrOfSyllables(5, chain, wordPairDict)
|
||||||
|
if chain is not False:
|
||||||
|
break
|
||||||
|
|
||||||
|
chain = chain[1:] #remove <SOM>
|
||||||
|
return ' '.join(chain)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, hidden=False)
|
||||||
|
@asyncio.coroutine
|
||||||
|
def haiku(self, ctx):
|
||||||
|
"""Stroop is een poëet. Laat hem een Haiku maken.
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = self.getHaiku()
|
||||||
|
yield from ctx.channel.send(response)
|
||||||
|
|
||||||
Reference in New Issue
Block a user