mirror of
https://github.com/house-of-vanity/conf_bot.git
synced 2025-07-06 14:24:08 +00:00
Add markov chain text generator.
This commit is contained in:
@ -162,7 +162,11 @@ class DataBase:
|
|||||||
|
|
||||||
def get_random_word(self, count=1, like="%"):
|
def get_random_word(self, count=1, like="%"):
|
||||||
sql = "SELECT word FROM word WHERE word LIKE '%s' ORDER BY random() LIMIT %s" % (like, count)
|
sql = "SELECT word FROM word WHERE word LIKE '%s' ORDER BY random() LIMIT %s" % (like, count)
|
||||||
print(sql)
|
result = self.execute(sql)
|
||||||
|
return(result)
|
||||||
|
|
||||||
|
def get_random_message(self):
|
||||||
|
sql = "SELECT text FROM xxx_message ORDER BY RANDOM() LIMIT 1"
|
||||||
result = self.execute(sql)
|
result = self.execute(sql)
|
||||||
return(result)
|
return(result)
|
||||||
|
|
||||||
|
7
markov/__init__.py
Normal file
7
markov/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""Markov chain text generator"""
|
||||||
|
|
||||||
|
from .gen import MarkovChain
|
||||||
|
from .simple import get
|
||||||
|
|
||||||
|
__all__ = ["MarkovChain", "get"]
|
||||||
|
|
74
markov/gen.py
Normal file
74
markov/gen.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
from .histograms import Dictogram
|
||||||
|
import random
|
||||||
|
from collections import deque
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class MarkovChain:
|
||||||
|
def __init__(self, text=str()):
|
||||||
|
self.length = 25
|
||||||
|
self.text = text
|
||||||
|
self.text_list = None
|
||||||
|
self._prepare_list()
|
||||||
|
self.model = self._gen_model()
|
||||||
|
|
||||||
|
def _prepare_list(self):
|
||||||
|
if isinstance(self.text, str):
|
||||||
|
self._clean_text()
|
||||||
|
self.text_list = self.text.split()
|
||||||
|
else:
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
def _clean_text(self):
|
||||||
|
text = self.text.replace('—','')
|
||||||
|
text = self.text.replace('«','')
|
||||||
|
text = self.text.replace('»','')
|
||||||
|
text = self.text.replace('(','')
|
||||||
|
text = self.text.replace(')','')
|
||||||
|
text = self.text.replace('.','')
|
||||||
|
text = self.text.replace(',','')
|
||||||
|
self.text = text
|
||||||
|
print(self.text)
|
||||||
|
|
||||||
|
def _gen_model(self):
|
||||||
|
data = self.text_list
|
||||||
|
if data is None:
|
||||||
|
raise TypeError
|
||||||
|
markov_model = dict()
|
||||||
|
for i in range(0, len(data)-1):
|
||||||
|
if data[i] in markov_model:
|
||||||
|
markov_model[data[i]].update([data[i+1]])
|
||||||
|
else:
|
||||||
|
markov_model[data[i]] = Dictogram([data[i+1]])
|
||||||
|
return markov_model
|
||||||
|
|
||||||
|
def _generate_random_start(self):
|
||||||
|
model = self.model
|
||||||
|
# Чтобы сгенерировать любое начальное слово, раскомментируйте строку:
|
||||||
|
return random.choice(list(model.keys()))
|
||||||
|
|
||||||
|
# Чтобы сгенерировать "правильное" начальное слово, используйте код ниже:
|
||||||
|
# Правильные начальные слова - это те, что являлись началом предложений в корпусе
|
||||||
|
if 'END' in model:
|
||||||
|
seed_word = 'END'
|
||||||
|
while seed_word == 'END':
|
||||||
|
seed_word = model['END'].return_weighted_random_word()
|
||||||
|
return seed_word
|
||||||
|
return random.choice(list(model.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_random_sentence(self):
|
||||||
|
markov_model = self.model
|
||||||
|
length = self.length if len(self.text_list) > self.length else len(self.text_list) - 1
|
||||||
|
current_word = self._generate_random_start()
|
||||||
|
sentence = [current_word]
|
||||||
|
for i in range(0, length):
|
||||||
|
try:
|
||||||
|
current_dictogram = markov_model[current_word]
|
||||||
|
random_weighted_word = current_dictogram.return_weighted_random_word()
|
||||||
|
current_word = random_weighted_word
|
||||||
|
sentence.append(current_word)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
sentence[0] = sentence[0].capitalize()
|
||||||
|
return ' '.join(sentence) + '.'
|
49
markov/histograms.py
Normal file
49
markov/histograms.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
class Dictogram(dict):
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
# Инициализируем наше распределение как новый объект класса,
|
||||||
|
# добавляем имеющиеся элементы
|
||||||
|
super(Dictogram, self).__init__()
|
||||||
|
self.types = 0 # число уникальных ключей в распределении
|
||||||
|
self.tokens = 0 # общее количество всех слов в распределении
|
||||||
|
if iterable:
|
||||||
|
self.update(iterable)
|
||||||
|
|
||||||
|
def update(self, iterable):
|
||||||
|
# Обновляем распределение элементами из имеющегося
|
||||||
|
# итерируемого набора данных
|
||||||
|
for item in iterable:
|
||||||
|
if item in self:
|
||||||
|
self[item] += 1
|
||||||
|
self.tokens += 1
|
||||||
|
else:
|
||||||
|
self[item] = 1
|
||||||
|
self.types += 1
|
||||||
|
self.tokens += 1
|
||||||
|
|
||||||
|
def count(self, item):
|
||||||
|
# Возвращаем значение счетчика элемента, или 0
|
||||||
|
if item in self:
|
||||||
|
return self[item]
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def return_random_word(self):
|
||||||
|
random_key = random.sample(self, 1)
|
||||||
|
# Другой способ:
|
||||||
|
# random.choice(histogram.keys())
|
||||||
|
return random_key[0]
|
||||||
|
|
||||||
|
def return_weighted_random_word(self):
|
||||||
|
# Сгенерировать псевдослучайное число между 0 и (n-1),
|
||||||
|
# где n - общее число слов
|
||||||
|
random_int = random.randint(0, self.tokens-1)
|
||||||
|
index = 0
|
||||||
|
list_of_keys = list(self.keys())
|
||||||
|
# вывести 'случайный индекс:', random_int
|
||||||
|
for i in range(0, self.types):
|
||||||
|
index += self[list_of_keys[i]]
|
||||||
|
# вывести индекс
|
||||||
|
if(index > random_int):
|
||||||
|
# вывести list_of_keys[i]
|
||||||
|
return list_of_keys[i]
|
95
markov/simple.py
Normal file
95
markov/simple.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import random
|
||||||
|
from collections import deque
|
||||||
|
import re
|
||||||
|
|
||||||
|
class Dictogram(dict):
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
super(Dictogram, self).__init__()
|
||||||
|
self.types = 0
|
||||||
|
self.tokens = 0
|
||||||
|
if iterable:
|
||||||
|
self.update(iterable)
|
||||||
|
|
||||||
|
def update(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
if item in self:
|
||||||
|
self[item] += 1
|
||||||
|
self.tokens += 1
|
||||||
|
else:
|
||||||
|
self[item] = 1
|
||||||
|
self.types += 1
|
||||||
|
self.tokens += 1
|
||||||
|
|
||||||
|
def count(self, item):
|
||||||
|
if item in self:
|
||||||
|
return self[item]
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def return_random_word(self):
|
||||||
|
random_key = random.sample(self, 1)
|
||||||
|
return random_key[0]
|
||||||
|
|
||||||
|
def return_weighted_random_word(self):
|
||||||
|
random_int = random.randint(0, self.tokens-1)
|
||||||
|
index = 0
|
||||||
|
list_of_keys = list(self.keys())
|
||||||
|
for i in range(0, self.types):
|
||||||
|
index += self[list_of_keys[i]]
|
||||||
|
if(index > random_int):
|
||||||
|
return list_of_keys[i]
|
||||||
|
|
||||||
|
def get():
|
||||||
|
def generate_random_start(model):
|
||||||
|
if 'END' in model:
|
||||||
|
seed_word = 'END'
|
||||||
|
while seed_word == 'END':
|
||||||
|
seed_word = model['END'].return_weighted_random_word()
|
||||||
|
return seed_word
|
||||||
|
return random.choice(list(model.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_random_sentence(length, markov_model):
|
||||||
|
current_word = generate_random_start(markov_model)
|
||||||
|
sentence = [current_word]
|
||||||
|
for i in range(0, length):
|
||||||
|
current_dictogram = markov_model[current_word]
|
||||||
|
random_weighted_word = current_dictogram.return_weighted_random_word()
|
||||||
|
current_word = random_weighted_word
|
||||||
|
sentence.append(current_word)
|
||||||
|
sentence[0] = sentence[0].capitalize()
|
||||||
|
return ' '.join(sentence) + '.'
|
||||||
|
return sentence
|
||||||
|
|
||||||
|
def make_markov_model(data):
|
||||||
|
markov_model = dict()
|
||||||
|
|
||||||
|
for i in range(0, len(data)-1):
|
||||||
|
if data[i] in markov_model:
|
||||||
|
markov_model[data[i]].update([data[i+1]])
|
||||||
|
else:
|
||||||
|
markov_model[data[i]] = Dictogram([data[i+1]])
|
||||||
|
return markov_model
|
||||||
|
|
||||||
|
text = """
|
||||||
|
Олег Соколов, преподававший в СПбГУ, в ноябре был задержан в Петербурге,
|
||||||
|
в его рюкзаке обнаружили две отпиленные женские руки. Соколов признался,
|
||||||
|
что убил и расчленил свою бывшую студентку Анастасию Ещенко, с которой
|
||||||
|
его связывали близкие отношения. Адвокат Соколова Александр Почуев заявлял,
|
||||||
|
что не исключает «и версию самооговора» его подзащитного и иные версии
|
||||||
|
преступления, «вплоть до мистических»."""
|
||||||
|
|
||||||
|
# simple cleanup
|
||||||
|
text = text.replace('—','')
|
||||||
|
text = text.replace('«','')
|
||||||
|
text = text.replace('»','')
|
||||||
|
text = text.replace('(','')
|
||||||
|
text = text.replace(')','')
|
||||||
|
text = "START " + text
|
||||||
|
text = text.replace('.', ' END')
|
||||||
|
|
||||||
|
text_list = text.split()
|
||||||
|
model = make_markov_model(text_list)
|
||||||
|
|
||||||
|
generated = generate_random_sentence(50, model)
|
||||||
|
generated = generated.replace(' END', '.')
|
||||||
|
print(generated)
|
87
simple.py
Normal file
87
simple.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import random
|
||||||
|
from collections import deque
|
||||||
|
import re
|
||||||
|
|
||||||
|
class Dictogram(dict):
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
super(Dictogram, self).__init__()
|
||||||
|
self.types = 0
|
||||||
|
self.tokens = 0
|
||||||
|
if iterable:
|
||||||
|
self.update(iterable)
|
||||||
|
|
||||||
|
def update(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
if item in self:
|
||||||
|
self[item] += 1
|
||||||
|
self.tokens += 1
|
||||||
|
else:
|
||||||
|
self[item] = 1
|
||||||
|
self.types += 1
|
||||||
|
self.tokens += 1
|
||||||
|
|
||||||
|
def count(self, item):
|
||||||
|
if item in self:
|
||||||
|
return self[item]
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def return_random_word(self):
|
||||||
|
random_key = random.sample(self, 1)
|
||||||
|
return random_key[0]
|
||||||
|
|
||||||
|
def return_weighted_random_word(self):
|
||||||
|
random_int = random.randint(0, self.tokens-1)
|
||||||
|
index = 0
|
||||||
|
list_of_keys = list(self.keys())
|
||||||
|
for i in range(0, self.types):
|
||||||
|
index += self[list_of_keys[i]]
|
||||||
|
if(index > random_int):
|
||||||
|
return list_of_keys[i]
|
||||||
|
|
||||||
|
def get(text):
|
||||||
|
def generate_random_start(model):
|
||||||
|
if 'END' in model:
|
||||||
|
seed_word = 'END'
|
||||||
|
while seed_word == 'END':
|
||||||
|
seed_word = model['END'].return_weighted_random_word()
|
||||||
|
return seed_word
|
||||||
|
return random.choice(list(model.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_random_sentence(length, markov_model):
|
||||||
|
current_word = generate_random_start(markov_model)
|
||||||
|
sentence = [current_word]
|
||||||
|
for i in range(0, length):
|
||||||
|
current_dictogram = markov_model[current_word]
|
||||||
|
random_weighted_word = current_dictogram.return_weighted_random_word()
|
||||||
|
current_word = random_weighted_word
|
||||||
|
sentence.append(current_word)
|
||||||
|
sentence[0] = sentence[0].capitalize()
|
||||||
|
return ' '.join(sentence) + '.'
|
||||||
|
return sentence
|
||||||
|
|
||||||
|
def make_markov_model(data):
|
||||||
|
markov_model = dict()
|
||||||
|
|
||||||
|
for i in range(0, len(data)-1):
|
||||||
|
if data[i] in markov_model:
|
||||||
|
markov_model[data[i]].update([data[i+1]])
|
||||||
|
else:
|
||||||
|
markov_model[data[i]] = Dictogram([data[i+1]])
|
||||||
|
return markov_model
|
||||||
|
|
||||||
|
# simple cleanup
|
||||||
|
text = text.replace('—','')
|
||||||
|
text = text.replace('«','')
|
||||||
|
text = text.replace('»','')
|
||||||
|
text = text.replace('(','')
|
||||||
|
text = text.replace(')','')
|
||||||
|
text = "START " + text
|
||||||
|
text = text.replace('.', ' END')
|
||||||
|
|
||||||
|
text_list = text.split()
|
||||||
|
model = make_markov_model(text_list)
|
||||||
|
|
||||||
|
generated = generate_random_sentence(50, model)
|
||||||
|
generated = generated.replace(' END', '.')
|
||||||
|
print(generated)
|
Reference in New Issue
Block a user