Compare commits
3 Commits
1cf0364268
...
419994ee32
Author | SHA1 | Date | |
---|---|---|---|
419994ee32 | |||
e27087a86b | |||
8b3caabb57 |
18
ircbot/migrations/0019_ircchannel_discord_bridge.py
Normal file
18
ircbot/migrations/0019_ircchannel_discord_bridge.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.2.18 on 2023-02-16 22:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ircbot', '0018_ircserver_replace_irc_control_with_markdown'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ircchannel',
|
||||||
|
name='discord_bridge',
|
||||||
|
field=models.CharField(blank=True, default='', max_length=32),
|
||||||
|
),
|
||||||
|
]
|
@ -104,6 +104,8 @@ class IrcChannel(models.Model):
|
|||||||
|
|
||||||
markov_learn_from_channel = models.BooleanField(default=True)
|
markov_learn_from_channel = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
discord_bridge = models.CharField(default='', max_length=32, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Settings for the model."""
|
"""Settings for the model."""
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
|
"""Provide methods for manipulating markov chain processing."""
|
||||||
import logging
|
import logging
|
||||||
import random
|
from random import SystemRandom as sysrand
|
||||||
|
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
|
|
||||||
from markov.models import MarkovContext, MarkovState, MarkovTarget
|
from markov.models import MarkovContext, MarkovState, MarkovTarget
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
log = logging.getLogger('markov.lib')
|
|
||||||
|
|
||||||
|
|
||||||
def generate_line(context, topics=None, min_words=15, max_words=30, sentence_bias=2, max_tries=5):
|
def generate_line(context, topics=None, min_words=15, max_words=30, sentence_bias=2, max_tries=5):
|
||||||
"""String multiple sentences together into a coherent sentence."""
|
"""Combine multiple sentences together into a coherent sentence."""
|
||||||
|
|
||||||
tries = 0
|
tries = 0
|
||||||
line = []
|
line = []
|
||||||
min_words_per_sentence = min_words / sentence_bias
|
min_words_per_sentence = min_words / sentence_bias
|
||||||
@ -23,7 +22,7 @@ def generate_line(context, topics=None, min_words=15, max_words=30, sentence_bia
|
|||||||
else:
|
else:
|
||||||
if len(line) > 0:
|
if len(line) > 0:
|
||||||
if line[-1][-1] not in [',', '.', '!', '?', ':']:
|
if line[-1][-1] not in [',', '.', '!', '?', ':']:
|
||||||
line[-1] += random.choice(['?', '.', '!'])
|
line[-1] += sysrand.choice(['?', '.', '!'])
|
||||||
|
|
||||||
tries += 1
|
tries += 1
|
||||||
|
|
||||||
@ -33,7 +32,6 @@ def generate_line(context, topics=None, min_words=15, max_words=30, sentence_bia
|
|||||||
|
|
||||||
def generate_longish_sentence(context, topics=None, min_words=15, max_words=30, max_tries=100):
|
def generate_longish_sentence(context, topics=None, min_words=15, max_words=30, max_tries=100):
|
||||||
"""Generate a Markov chain, but throw away the short ones unless we get desperate."""
|
"""Generate a Markov chain, but throw away the short ones unless we get desperate."""
|
||||||
|
|
||||||
sent = ""
|
sent = ""
|
||||||
tries = 0
|
tries = 0
|
||||||
while tries < max_tries:
|
while tries < max_tries:
|
||||||
@ -52,20 +50,19 @@ def generate_longish_sentence(context, topics=None, min_words=15, max_words=30,
|
|||||||
|
|
||||||
def generate_sentence(context, topics=None, min_words=15, max_words=30):
|
def generate_sentence(context, topics=None, min_words=15, max_words=30):
|
||||||
"""Generate a Markov chain."""
|
"""Generate a Markov chain."""
|
||||||
|
|
||||||
words = []
|
words = []
|
||||||
# if we have topics, try to work from it and work backwards
|
# if we have topics, try to work from it and work backwards
|
||||||
if topics:
|
if topics:
|
||||||
topic_word = random.choice(topics)
|
topic_word = sysrand.choice(topics)
|
||||||
topics.remove(topic_word)
|
topics.remove(topic_word)
|
||||||
log.debug("looking for topic '{0:s}'".format(topic_word))
|
log.debug("looking for topic '%s'", topic_word)
|
||||||
new_states = MarkovState.objects.filter(context=context, v=topic_word)
|
new_states = MarkovState.objects.filter(context=context, v=topic_word)
|
||||||
|
|
||||||
if len(new_states) > 0:
|
if len(new_states) > 0:
|
||||||
log.debug("found '{0:s}', starting backwards".format(topic_word))
|
log.debug("found '%s', starting backwards", topic_word)
|
||||||
words.insert(0, topic_word)
|
words.insert(0, topic_word)
|
||||||
while len(words) <= max_words and words[0] != MarkovState._start2:
|
while len(words) <= max_words and words[0] != MarkovState._start2:
|
||||||
log.debug("looking backwards for '{0:s}'".format(words[0]))
|
log.debug("looking backwards for '%s'", words[0])
|
||||||
new_states = MarkovState.objects.filter(context=context, v=words[0])
|
new_states = MarkovState.objects.filter(context=context, v=words[0])
|
||||||
# if we find a start, use it
|
# if we find a start, use it
|
||||||
if MarkovState._start2 in new_states:
|
if MarkovState._start2 in new_states:
|
||||||
@ -87,7 +84,7 @@ def generate_sentence(context, topics=None, min_words=15, max_words=30):
|
|||||||
|
|
||||||
i = len(words)
|
i = len(words)
|
||||||
while words[-1] != MarkovState._stop:
|
while words[-1] != MarkovState._stop:
|
||||||
log.debug("looking for '{0:s}','{1:s}'".format(words[i-2], words[i-1]))
|
log.debug("looking for '%s','%s'", words[i-2], words[i-1])
|
||||||
new_states = MarkovState.objects.filter(context=context, k1=words[i-2], k2=words[i-1])
|
new_states = MarkovState.objects.filter(context=context, k1=words[i-2], k2=words[i-1])
|
||||||
log.debug("states retrieved")
|
log.debug("states retrieved")
|
||||||
|
|
||||||
@ -103,7 +100,7 @@ def generate_sentence(context, topics=None, min_words=15, max_words=30):
|
|||||||
words.append(MarkovState._stop)
|
words.append(MarkovState._stop)
|
||||||
elif len(target_hits) > 0:
|
elif len(target_hits) > 0:
|
||||||
# if there's a target word in the states, pick it
|
# if there's a target word in the states, pick it
|
||||||
target_hit = random.choice(target_hits)
|
target_hit = sysrand.choice(target_hits)
|
||||||
log.debug("found a topic hit %s, using it", target_hit)
|
log.debug("found a topic hit %s, using it", target_hit)
|
||||||
topics.remove(target_hit)
|
topics.remove(target_hit)
|
||||||
words.append(target_hit)
|
words.append(target_hit)
|
||||||
@ -129,7 +126,6 @@ def generate_sentence(context, topics=None, min_words=15, max_words=30):
|
|||||||
|
|
||||||
def get_or_create_target_context(target_name):
|
def get_or_create_target_context(target_name):
|
||||||
"""Return the context for a provided nick/channel, creating missing ones."""
|
"""Return the context for a provided nick/channel, creating missing ones."""
|
||||||
|
|
||||||
target_name = target_name.lower()
|
target_name = target_name.lower()
|
||||||
|
|
||||||
# find the stuff, or create it
|
# find the stuff, or create it
|
||||||
@ -156,7 +152,6 @@ def get_or_create_target_context(target_name):
|
|||||||
|
|
||||||
def get_word_out_of_states(states, backwards=False):
|
def get_word_out_of_states(states, backwards=False):
|
||||||
"""Pick one random word out of the given states."""
|
"""Pick one random word out of the given states."""
|
||||||
|
|
||||||
# work around possible broken data, where a k1,k2 should have a value but doesn't
|
# work around possible broken data, where a k1,k2 should have a value but doesn't
|
||||||
if len(states) == 0:
|
if len(states) == 0:
|
||||||
states = MarkovState.objects.filter(v=MarkovState._stop)
|
states = MarkovState.objects.filter(v=MarkovState._stop)
|
||||||
@ -168,9 +163,9 @@ def get_word_out_of_states(states, backwards=False):
|
|||||||
# this being None probably means there's no data for this context
|
# this being None probably means there's no data for this context
|
||||||
raise ValueError("no markov states to generate from")
|
raise ValueError("no markov states to generate from")
|
||||||
|
|
||||||
hit = random.randint(0, count_sum)
|
hit = sysrand.randint(0, count_sum)
|
||||||
|
|
||||||
log.debug("sum: {0:d} hit: {1:d}".format(count_sum, hit))
|
log.debug("sum: %s hit: %s", count_sum, hit)
|
||||||
|
|
||||||
states_itr = states.iterator()
|
states_itr = states.iterator()
|
||||||
for state in states_itr:
|
for state in states_itr:
|
||||||
@ -183,13 +178,12 @@ def get_word_out_of_states(states, backwards=False):
|
|||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
log.debug("found '{0:s}'".format(new_word))
|
log.debug("found '%s'", new_word)
|
||||||
return new_word
|
return new_word
|
||||||
|
|
||||||
|
|
||||||
def learn_line(line, context):
|
def learn_line(line, context):
|
||||||
"""Create a bunch of MarkovStates for a given line of text."""
|
"""Create a bunch of MarkovStates for a given line of text."""
|
||||||
|
|
||||||
log.debug("learning %s...", line[:40])
|
log.debug("learning %s...", line[:40])
|
||||||
|
|
||||||
words = line.split()
|
words = line.split()
|
||||||
@ -200,7 +194,7 @@ def learn_line(line, context):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for i, word in enumerate(words):
|
for i, word in enumerate(words):
|
||||||
log.debug("'{0:s}','{1:s}' -> '{2:s}'".format(words[i], words[i+1], words[i+2]))
|
log.debug("'%s','%s' -> '%s'", words[i], words[i+1], words[i+2])
|
||||||
state, created = MarkovState.objects.get_or_create(context=context,
|
state, created = MarkovState.objects.get_or_create(context=context,
|
||||||
k1=words[i],
|
k1=words[i],
|
||||||
k2=words[i+1],
|
k2=words[i+1],
|
||||||
|
@ -1,30 +1,22 @@
|
|||||||
"""
|
"""Save brain pieces as markov chains for chaining."""
|
||||||
markov/models.py --- save brain pieces for chaining
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
log = logging.getLogger('markov.models')
|
|
||||||
|
|
||||||
|
|
||||||
class MarkovContext(models.Model):
|
class MarkovContext(models.Model):
|
||||||
|
|
||||||
"""Define contexts for Markov chains."""
|
"""Define contexts for Markov chains."""
|
||||||
|
|
||||||
name = models.CharField(max_length=200, unique=True)
|
name = models.CharField(max_length=200, unique=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String representation."""
|
"""Provide string representation."""
|
||||||
|
|
||||||
return "{0:s}".format(self.name)
|
return "{0:s}".format(self.name)
|
||||||
|
|
||||||
|
|
||||||
class MarkovTarget(models.Model):
|
class MarkovTarget(models.Model):
|
||||||
|
|
||||||
"""Define IRC targets that relate to a context, and can occasionally be talked to."""
|
"""Define IRC targets that relate to a context, and can occasionally be talked to."""
|
||||||
|
|
||||||
name = models.CharField(max_length=200, unique=True)
|
name = models.CharField(max_length=200, unique=True)
|
||||||
@ -33,13 +25,11 @@ class MarkovTarget(models.Model):
|
|||||||
chatter_chance = models.IntegerField(default=0)
|
chatter_chance = models.IntegerField(default=0)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String representation."""
|
"""Provide string representation."""
|
||||||
|
|
||||||
return "{0:s} -> {1:s}".format(self.name, self.context.name)
|
return "{0:s} -> {1:s}".format(self.name, self.context.name)
|
||||||
|
|
||||||
|
|
||||||
class MarkovState(models.Model):
|
class MarkovState(models.Model):
|
||||||
|
|
||||||
"""One element in a Markov chain, some text or something."""
|
"""One element in a Markov chain, some text or something."""
|
||||||
|
|
||||||
_start1 = '__start1'
|
_start1 = '__start1'
|
||||||
@ -54,6 +44,8 @@ class MarkovState(models.Model):
|
|||||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""Options for the model itself."""
|
||||||
|
|
||||||
index_together = [
|
index_together = [
|
||||||
['context', 'k1', 'k2'],
|
['context', 'k1', 'k2'],
|
||||||
['context', 'v'],
|
['context', 'v'],
|
||||||
@ -65,6 +57,5 @@ class MarkovState(models.Model):
|
|||||||
unique_together = ('context', 'k1', 'k2', 'v')
|
unique_together = ('context', 'k1', 'k2', 'v')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String representation."""
|
"""Provide string representation."""
|
||||||
|
|
||||||
return "{0:s},{1:s} -> {2:s} (count: {3:d})".format(self.k1, self.k2, self.v, self.count)
|
return "{0:s},{1:s} -> {2:s} (count: {3:d})".format(self.k1, self.k2, self.v, self.count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user