Markov: allow for auto-context insertion
this should result in no chains having a null context --- if no pre-existing context is created, one is created for the channel/nick and used. this makes, for example, arbitrary queries "private" to that nick (again unless that has been overridden). shouldn't affect much of anything, but adding this made the context-less learning code obsolete, which is fine since it was never used anyway
This commit is contained in:
parent
ce93480e9b
commit
7d41564d02
@ -54,11 +54,9 @@ class Markov(Module):
|
|||||||
self.stop = '__stop'
|
self.stop = '__stop'
|
||||||
|
|
||||||
# set up regexes, for replying to specific stuff
|
# set up regexes, for replying to specific stuff
|
||||||
trainpattern = '^!markov\s+train\s+(.*)$'
|
|
||||||
learnpattern = '^!markov\s+learn\s+(.*)$'
|
learnpattern = '^!markov\s+learn\s+(.*)$'
|
||||||
replypattern = '^!markov\s+reply(\s+min=(\d+))?(\s+max=(\d+))?(\s+(.*)$|$)'
|
replypattern = '^!markov\s+reply(\s+min=(\d+))?(\s+max=(\d+))?(\s+(.*)$|$)'
|
||||||
|
|
||||||
self.trainre = re.compile(trainpattern)
|
|
||||||
self.learnre = re.compile(learnpattern)
|
self.learnre = re.compile(learnpattern)
|
||||||
self.replyre = re.compile(replypattern)
|
self.replyre = re.compile(replypattern)
|
||||||
|
|
||||||
@ -163,11 +161,14 @@ class Markov(Module):
|
|||||||
target = event.target()
|
target = event.target()
|
||||||
nick = irclib.nm_to_n(event.source())
|
nick = irclib.nm_to_n(event.source())
|
||||||
|
|
||||||
|
if not irclib.is_channel(target):
|
||||||
|
target = nick
|
||||||
|
|
||||||
self.lines_seen.append((nick, datetime.now()))
|
self.lines_seen.append((nick, datetime.now()))
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
|
|
||||||
# don't learn from commands
|
# don't learn from commands
|
||||||
if self.trainre.search(what) or self.learnre.search(what) or self.replyre.search(what):
|
if self.learnre.search(what) or self.replyre.search(what):
|
||||||
return
|
return
|
||||||
|
|
||||||
self._learn_line(what, target)
|
self._learn_line(what, target)
|
||||||
@ -177,10 +178,7 @@ class Markov(Module):
|
|||||||
|
|
||||||
target = event.target()
|
target = event.target()
|
||||||
|
|
||||||
if self.trainre.search(what):
|
if self.learnre.search(what):
|
||||||
return self.reply(connection, event, self.markov_train(connection, event, nick,
|
|
||||||
userhost, what, admin_unlocked))
|
|
||||||
elif self.learnre.search(what):
|
|
||||||
return self.reply(connection, event, self.markov_learn(connection, event, nick,
|
return self.reply(connection, event, self.markov_learn(connection, event, nick,
|
||||||
userhost, what, admin_unlocked))
|
userhost, what, admin_unlocked))
|
||||||
elif self.replyre.search(what) and not self.shut_up:
|
elif self.replyre.search(what) and not self.shut_up:
|
||||||
@ -202,21 +200,6 @@ class Markov(Module):
|
|||||||
self.lines_seen.append(('.self.said.', datetime.now()))
|
self.lines_seen.append(('.self.said.', datetime.now()))
|
||||||
return self.reply(connection, event, '{0:s}'.format(self._generate_line(target, line=what)))
|
return self.reply(connection, event, '{0:s}'.format(self._generate_line(target, line=what)))
|
||||||
|
|
||||||
def markov_train(self, connection, event, nick, userhost, what, admin_unlocked):
|
|
||||||
"""Learn lines from a file. Good for initializing a brain."""
|
|
||||||
|
|
||||||
match = self.trainre.search(what)
|
|
||||||
if match and admin_unlocked:
|
|
||||||
filename = match.group(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
for line in open(filename, 'r'):
|
|
||||||
self._learn_line(line)
|
|
||||||
|
|
||||||
return 'Learned from \'{0:s}\'.'.format(filename)
|
|
||||||
except IOError:
|
|
||||||
return 'No such file \'{0:s}\'.'.format(filename)
|
|
||||||
|
|
||||||
def markov_learn(self, connection, event, nick, userhost, what, admin_unlocked):
|
def markov_learn(self, connection, event, nick, userhost, what, admin_unlocked):
|
||||||
"""Learn one line, as provided to the command."""
|
"""Learn one line, as provided to the command."""
|
||||||
|
|
||||||
@ -431,10 +414,10 @@ class Markov(Module):
|
|||||||
max_id = self._get_max_chain_id()
|
max_id = self._get_max_chain_id()
|
||||||
rand_id = random.randint(1,max_id)
|
rand_id = random.randint(1,max_id)
|
||||||
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
|
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
|
||||||
'(context_id = ? OR context_id IS NULL) AND id >= {0:d} LIMIT 1'.format(rand_id))
|
'(context_id = ?) AND id >= {0:d} LIMIT 1'.format(rand_id))
|
||||||
else:
|
else:
|
||||||
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
|
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
|
||||||
'(context_id = ? OR context_id IS NULL)')
|
'(context_id = ?)')
|
||||||
cursor = db.execute(query, (k1,k2,context_id))
|
cursor = db.execute(query, (k1,k2,context_id))
|
||||||
results = cursor.fetchall()
|
results = cursor.fetchall()
|
||||||
|
|
||||||
@ -454,7 +437,7 @@ class Markov(Module):
|
|||||||
values = []
|
values = []
|
||||||
try:
|
try:
|
||||||
db = self.get_db()
|
db = self.get_db()
|
||||||
query = 'SELECT k2 FROM markov_chain WHERE v = ? AND (context_id = ? OR context_id IS NULL)'
|
query = 'SELECT k2 FROM markov_chain WHERE v = ? AND (context_id = ?)'
|
||||||
cursor = db.execute(query, (v,context_id))
|
cursor = db.execute(query, (v,context_id))
|
||||||
results = cursor.fetchall()
|
results = cursor.fetchall()
|
||||||
|
|
||||||
@ -529,7 +512,52 @@ class Markov(Module):
|
|||||||
if result:
|
if result:
|
||||||
return result['id']
|
return result['id']
|
||||||
else:
|
else:
|
||||||
return None
|
# auto-generate a context to keep things private
|
||||||
|
self._add_context_for_target(target)
|
||||||
|
return self._get_context_id_for_target(target)
|
||||||
|
except sqlite3.Error as e:
|
||||||
|
db.close()
|
||||||
|
print('sqlite error in Markov._get_context_id_for_target: ' + str(e))
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _add_context_for_target(self, target):
|
||||||
|
|
||||||
|
"""Create a new context for the desired/input target."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
db = self.get_db()
|
||||||
|
cur = db.cursor()
|
||||||
|
statement = 'INSERT INTO markov_context (context) VALUES (?)'
|
||||||
|
cur.execute(statement, (target,))
|
||||||
|
statement = '''
|
||||||
|
INSERT INTO markov_target_to_context_map (target, context_id)
|
||||||
|
VALUES (?, (SELECT id FROM markov_context WHERE context = ?))
|
||||||
|
'''
|
||||||
|
cur.execute(statement, (target,target))
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
except sqlite3.Error as e:
|
||||||
|
db.rollback()
|
||||||
|
db.close()
|
||||||
|
print("sqlite error in Markov._add_context_for_target: " + str(e))
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
db = self.get_db()
|
||||||
|
query = '''
|
||||||
|
SELECT mc.id FROM markov_context mc
|
||||||
|
INNER JOIN markov_target_to_context_map mt
|
||||||
|
ON mt.context_id = mc.id
|
||||||
|
WHERE mt.target = ?
|
||||||
|
'''
|
||||||
|
cursor = db.execute(query, (target,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
db.close()
|
||||||
|
if result:
|
||||||
|
return result['id']
|
||||||
|
else:
|
||||||
|
# auto-generate a context to keep things private
|
||||||
|
self._add_context_for_target(target)
|
||||||
|
return self._get_context_id_for_target(target)
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
db.close()
|
db.close()
|
||||||
print('sqlite error in Markov._get_context_id_for_target: ' + str(e))
|
print('sqlite error in Markov._get_context_id_for_target: ' + str(e))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user