Try to respond to the previous message
This commit is contained in:
+97
-19
@@ -16,7 +16,7 @@ class Chatbot(object):
|
||||
np.load('markov_dict.npy')
|
||||
except FileNotFoundError:
|
||||
#If there's no initial file, make a new one:
|
||||
initFile = {'pairs':{self.START_OF_MESSAGE:{'Hoi':1},'Hoi':{self.END_OF_MESSAGE:1}}, 'trairs':{}}
|
||||
initFile = {'pairs':{self.START_OF_MESSAGE:{'Hoi':1},'Hoi':{self.END_OF_MESSAGE:1}}, 'trairs':{}, 'responsePairs':{}}
|
||||
np.save("markov_dict.npy", initFile)
|
||||
except:
|
||||
print("ERROR! - Could not open or create Markov chat file")
|
||||
@@ -39,9 +39,9 @@ class Chatbot(object):
|
||||
|
||||
#Learn from a human message
|
||||
#Returns an updated dict
|
||||
def learnFrom(self, wordDict, message: str):
|
||||
newPairDict = wordDict['pairs']
|
||||
newTrairDict = wordDict['trairs']
|
||||
def learnFrom(self, wordDictPairs, wordDictTrairs, message: str):
|
||||
newPairDict = wordDictPairs
|
||||
newTrairDict = wordDictTrairs
|
||||
|
||||
message = self.START_OF_MESSAGE + " " + message + " " + self.END_OF_MESSAGE
|
||||
corpus = message.split()
|
||||
@@ -67,7 +67,42 @@ class Chatbot(object):
|
||||
else:
|
||||
newTrairDict[word_1] = {word_3 : 1}
|
||||
|
||||
return {'pairs':newPairDict, 'trairs':newTrairDict};
|
||||
return newPairDict, newTrairDict;
|
||||
|
||||
#Learn to respond to messages
|
||||
#Returns ???
|
||||
def learnResponse(self, wordDictResp, message1: str, message2: str):
|
||||
STOP_WORDS = ["aan", "achter", "al", "ben", "dan", "dat", "de", "die", "dit", "een", "en", "er", "gehad", "had", "heb",
|
||||
"hen", "het", "hun", "in", "is", "kon", "met", "na", "of", "om", "ook", "op", "tot", "van", "was", "wat", "zo",
|
||||
"a", "an", "the", "am", "was", "were", "be", "not", "at"]
|
||||
|
||||
newRespPairDict = wordDictResp
|
||||
|
||||
#Split messages into words and remove stopwords:
|
||||
message1List = []
|
||||
message2List = []
|
||||
for word in message1.split():
|
||||
if word not in STOP_WORDS:
|
||||
message1List.append(word)
|
||||
for word in message2.split():
|
||||
if word not in STOP_WORDS:
|
||||
message2List.append(word)
|
||||
|
||||
#link words of response to words of initial message
|
||||
for word_1 in message1List:
|
||||
for word_2 in message2List:
|
||||
if word_1 in newRespPairDict.keys():
|
||||
if word_2 in newRespPairDict[word_1].keys():
|
||||
newRespPairDict[word_1][word_2] += 1
|
||||
else:
|
||||
newRespPairDict[word_1][word_2] = 1
|
||||
else:
|
||||
newRespPairDict[word_1] = {word_2 : 1}
|
||||
|
||||
return newRespPairDict
|
||||
|
||||
|
||||
|
||||
|
||||
@commands.command(pass_context=True, hidden=True)
|
||||
@asyncio.coroutine
|
||||
@@ -82,30 +117,55 @@ class Chatbot(object):
|
||||
wordDict = np.load('markov_dict.npy').item()
|
||||
|
||||
#Iterate through the last x messages from the channel:
|
||||
iterator = channel.history(limit=nrOfMessages, before=None, after=None, reverse=False, around=None)
|
||||
messageIterator = channel.history(limit=nrOfMessages, before=None, after=None, reverse=False, around=None)
|
||||
allMessages = []
|
||||
for i in range(nrOfMessages):
|
||||
msg = yield from iterator.next()
|
||||
msg = yield from messageIterator.next()
|
||||
allMessages.append(msg)
|
||||
|
||||
i = 0
|
||||
nextMessageIndex = -10
|
||||
#Note: the loop goes from new to old
|
||||
for msg in allMessages:
|
||||
messageContent = msg.content.replace('(', '').replace(')', '').replace('"', '')
|
||||
messageContent = messageContent.strip()
|
||||
|
||||
if messageContent == "":
|
||||
pass #print("-- Bericht is leeg. Negeer.")
|
||||
pass # Bericht is leeg. Negeer.
|
||||
elif msg.author.bot:
|
||||
pass #print("-- Dit is een bot chat. Negeer.")
|
||||
pass # Dit is een bot chat. Negeer.
|
||||
elif messageContent[0] == "!":
|
||||
pass #print("-- Dit is een commando. Negeer.")
|
||||
pass # Dit is een commando. Negeer.
|
||||
elif "```" in messageContent:
|
||||
pass #print("-- Daar zit een codeblok in. Negeer.")
|
||||
pass # Daar zit een codeblok in. Negeer.
|
||||
elif messageContent[0:7] == "http://" or messageContent[0:8] == "https://":
|
||||
pass # Een link. Negeer. TODO: post af en toe een random link die geen repost is
|
||||
else:
|
||||
wordDict = self.learnFrom(wordDict, messageContent)
|
||||
# Usable message!
|
||||
wordDict['pairs'], wordDict['trairs'] = self.learnFrom(wordDict['pairs'], wordDict['trairs'], messageContent)
|
||||
|
||||
if (i-nextMessageIndex) == 1 and msg.author != nextMessage.author: #the previous usable messages was the one right after this one and was not from the same author
|
||||
timeDelta = nextMessage.created_at - msg.created_at
|
||||
#TODO check for different author
|
||||
if timeDelta.days == 0 and timeDelta.seconds < 3600: #less than an hour difference
|
||||
#this is counted as a response. learn from it
|
||||
wordDict['responsePairs'] = self.learnResponse(wordDict['responsePairs'], messageContent, nextMessageContent)
|
||||
|
||||
#save for next iteration:
|
||||
nextMessage = msg
|
||||
nextMessageContent = messageContent
|
||||
nextMessageIndex = i
|
||||
i += 1
|
||||
|
||||
np.save("markov_dict.npy", wordDict)
|
||||
|
||||
yield from ctx.channel.send("Ik heb weer wat nieuwe woordjes geleerd. :slight_smile:")
|
||||
|
||||
|
||||
@commands.command(pass_context=True, hidden=False)
|
||||
@asyncio.coroutine
|
||||
def reageer(self, ctx):
|
||||
"""UNDER CONSTRUCTION. Laat Stroop iets willekeurigs zeggen.
|
||||
"""UNDER CONSTRUCTION. Laat Stroop ergens op reageren.
|
||||
Stroop leert van onze gesprekken. Hij kan zich nu voordoen als een van ons. Soort van.
|
||||
"""
|
||||
|
||||
@@ -115,19 +175,30 @@ class Chatbot(object):
|
||||
wordDict = np.load('markov_dict.npy').item()
|
||||
wordPairDict = wordDict['pairs']
|
||||
wordTrairDict = wordDict['trairs']
|
||||
responsePairDict = wordDict['responsePairs']
|
||||
#TODO store in global variable to minimise IO?
|
||||
|
||||
#Get previous message to respond to
|
||||
messageIterator = ctx.channel.history(limit=3, before=None, after=None, reverse=False, around=None)
|
||||
messageToRespondTo = yield from messageIterator.next() #this will be the !reageer command. skip
|
||||
messageToRespondTo = yield from messageIterator.next()
|
||||
if messageToRespondTo.content.strip()[0] == '!' or messageToRespondTo.author.bot: #another chance
|
||||
messageToRespondTo = yield from messageIterator.next() #but it's not a huge problem if he responds to himself
|
||||
if messageToRespondTo.content.strip()[0] == '!':
|
||||
wordsToRespondTo = []
|
||||
else:
|
||||
wordsToRespondTo = messageToRespondTo.content.strip().split()
|
||||
#print("respond to: ", wordsToRespondTo)
|
||||
|
||||
#Delete command
|
||||
try:
|
||||
yield from ctx.message.delete()
|
||||
except:
|
||||
print("No permission to delete message")
|
||||
|
||||
#print(wordDict)
|
||||
pass
|
||||
|
||||
#Pick a random first word (Which is not an end-of-message)
|
||||
#Usually, we start with a regular <SOM>, but sometimes we don't
|
||||
a = random.randint(1,10)
|
||||
a = random.randint(1,15)
|
||||
if a == 1:
|
||||
first_word = np.random.choice(list(wordPairDict.keys()))
|
||||
while first_word == self.END_OF_MESSAGE:
|
||||
@@ -135,8 +206,6 @@ class Chatbot(object):
|
||||
else:
|
||||
first_word = self.START_OF_MESSAGE
|
||||
chain = [first_word]
|
||||
#TODO pick a word which responds to the previous message in the channel
|
||||
|
||||
|
||||
#Go through the chain:
|
||||
for i in range(1, MAX_N_WORDS):
|
||||
@@ -145,6 +214,14 @@ class Chatbot(object):
|
||||
|
||||
#Find the possibilities:
|
||||
pairPossibilities = wordPairDict[chain[-1]].copy()
|
||||
|
||||
#Increase score if it would be a good response:
|
||||
for userWord in wordsToRespondTo:
|
||||
if userWord in responsePairDict:
|
||||
for goodResponseWord in responsePairDict[userWord]:
|
||||
if goodResponseWord in pairPossibilities.keys():
|
||||
pairPossibilities[goodResponseWord] += responsePairDict[userWord][goodResponseWord]
|
||||
#Increase score for trairs:
|
||||
if i > 1: #we can only compare trairs if we have at least two words already
|
||||
if chain[-2] in wordTrairDict:
|
||||
trairPossibilities = wordTrairDict[chain[-2]].copy()
|
||||
@@ -152,6 +229,7 @@ class Chatbot(object):
|
||||
for word2 in pairPossibilities.keys():
|
||||
if word2 in trairPossibilities.keys():
|
||||
pairPossibilities[word2] += trairPossibilities[word2]
|
||||
|
||||
#Calculate probabilities and pick a next word:
|
||||
#https://stackoverflow.com/questions/835092/python-dictionary-are-keys-and-values-always-the-same-order
|
||||
possible_words = list(pairPossibilities.keys())
|
||||
|
||||
Reference in New Issue
Block a user