Как работают Марковские Цепные Чатботы? - PullRequest
70 голосов
/ 15 марта 2011

Я думал о создании чат-бота с использованием чего-то вроде цепей Маркова, но я не совсем уверен, как заставить его работать. Из того, что я понимаю, вы создаете таблицу из данных с данным словом, а затем слова, которые следуют. Можно ли прикрепить какую-либо вероятность или счетчик во время тренировки бота? Это даже хорошая идея?

Вторая часть проблемы связана с ключевыми словами. Предполагая, что я уже могу определить ключевые слова из пользовательского ввода, как мне создать предложение, которое использует это ключевое слово? Я не всегда хочу начинать предложение с ключевого слова, так как мне начать цепочку markov?

Ответы [ 3 ]

136 голосов
/ 15 марта 2011

Несколько лет назад я создал цепочку чата Маркова для IRC в Python и могу пролить свет на то, как я это сделал. Сгенерированный текст не обязательно имеет какой-либо смысл, но его может быть действительно интересно читать. Давайте разберем его по шагам. Предполагая, что у вас есть фиксированный ввод, текстовый файл (вы можете использовать ввод текста чата или текста или просто использовать свое воображение)

Переберите текст и создайте словарь, означающий контейнер ключ-значение. И поместите все пары слов в качестве ключей, а слово, следующее за ним, в качестве значения. Например: если у вас есть текст «abcabk», вы начинаете с «ab» в качестве ключа и «c» в качестве значения, затем «bc» и «a» в качестве значения ... значение должно быть списком или любой коллекцией, содержащей 0 .. многих «предметов», так как вы можете иметь более одного значения для данной пары слов. В приведенном выше примере у вас будет «a b» два раза, за которыми следует кулак «c», затем в конце «k». Таким образом, в итоге у вас будет словарь / хэш, похожий на этот: {'a b': ['c','k'], 'b c': ['a'], 'c a': ['b']}

Теперь у вас есть необходимая структура для создания вашего забавного текста. Вы можете начать со случайного ключа или фиксированного места! Таким образом, учитывая структуру, которую мы имеем, мы можем начать с сохранения «ab», а затем случайным образом взять следующее слово из значения, c или k, поэтому первое сохранение в цикле, «abk» (если «k» было выбрано случайное значение) затем вы продолжаете, перемещаясь на один шаг вправо, который в нашем случае равен «bk», и сохраняете случайное значение для этой пары, если у вас есть, в нашем случае нет, поэтому вы выходите из цикла (или вы можете решить другие вещи, такие как начать заново). Когда цикл завершен, вы печатаете сохраненную текстовую строку.

Чем больше ввод, тем больше у вас будет значений клавиш (пары слов), и тогда у вас будет «умнее бота», чтобы вы могли «обучить» своего бота, добавив больше текста (возможно, чата?). Если у вас есть книга в качестве входных данных, вы можете создать несколько хороших случайных предложений. Обратите внимание, что вам не нужно брать в качестве значения только одно слово, которое следует за парой, вы можете взять 2 или 10. Разница в том, что ваш текст будет выглядеть более точным, если вы будете использовать «более длинные» строительные блоки. Начните с пары в качестве ключа и следующего слова в качестве значения.

Итак, вы видите, что в принципе вы можете сделать два шага: сначала создать структуру, в которой вы случайным образом выбираете ключ для начала, затем возьмите этот ключ и напечатайте случайное значение этого ключа и продолжайте, пока у вас не будет значения или некоторого другое условие. Если вы хотите, вы можете «начать» пару слов из чата из вашей структуры ключ-значение, чтобы начать. Это зависит от вашего воображения, как начать цепочку.

Пример с реальными словами:

"hi my name is Al and i live in a box that i like very much and i can live in there as long as i want"

"hi my" -> ["name"]

"my name" -> ["is"]

"name is" -> ["Al"]

"is Al" -> ["and"]

........

"and i" -> ["live", "can"]

........

"i can" -> ["live"]

......

Теперь создайте цикл:

Выберите случайный ключ, скажите «привет мой» и случайным образом выберите значение, только одно здесь, поэтому его «имя» (СОХРАНЕНИЕ "привет, меня зовут") .
Теперь переместитесь на один шаг вправо, взяв «мое имя» в качестве следующего ключа, и выберите случайное значение ... «есть» (СОХРАНЕНИЕ "привет, меня зовут") .
Теперь двигайся и возьми "зовут" ... "Ал" (СОХРАНЕНИЕ "привет, меня зовут AL") .
Теперь возьмите "Ал" ... "и" (СОХРАНЯЯ "привет, меня зовут Ал и") .

...

Когда вы приходите к «и я», вы случайным образом выбираете значение, скажем «можно», затем появляется слово «я могу» и т. Д. ... когда вы приходите в состояние остановки или у вас нет значений выведите построенную строку в нашем случае:

«Привет, меня зовут Ал, и я могу жить там столько, сколько захочу»

Если у вас есть больше значений, вы можете перейти к любой клавише. Чем больше значений, тем больше у вас комбинаций и тем более случайным и забавным будет текст.

7 голосов
/ 28 мая 2014

Бот выбирает случайное слово из вашего ввода и генерирует ответ, выбирая другое случайное слово, которое считается преемником своего удерживаемого слова.Затем он повторяет этот процесс, находя преемника к этому слову по очереди и итеративно, пока не решит, что слова достаточно.Он приходит к такому заключению, останавливаясь на слове, которое было до знака препинания в учебном тексте.Затем он снова возвращается в режим ввода, чтобы вы могли ответить, и т. Д.

Это не очень реалистично, но я тем самым призываю любого сделать лучше в 71 строке кода !!Это большой вызов для любого начинающего Pythonists, и я просто хотел бы открыть этот вызов для более широкой аудитории, чем небольшое количество посетителей этого блога.Чтобы кодировать бота, который всегда гарантированно должен быть грамматическим, наверняка должен быть ближе к нескольким сотням строк, я упростил задачу, просто пытаясь придумать простейшее правило, позволяющее компьютеру просто сказать, что сказать.

Его ответы довольно импрессионистские, если не сказать больше!Также вы должны поместить то, что вы говорите, в одинарные кавычки.

Я использовал «Войну и мир» для своего «корпуса», который занял пару часов на тренировочном заезде, используйте более короткий файл, если вы нетерпеливы…

вот тренер

#lukebot-trainer.py
import pickle
b=open('war&peace.txt')
text=[]
for line in b:
    for word in line.split():
        text.append (word)
b.close()
textset=list(set(text))
follow={}
for l in range(len(textset)):
    working=[]
    check=textset[l]
    for w in range(len(text)-1):
        if check==text[w] and text[w][-1] not in '(),.?!':
            working.append(str(text[w+1]))
    follow[check]=working
a=open('lexicon-luke','wb')
pickle.dump(follow,a,2)
a.close()

Вот бот:

#lukebot.py
import pickle,random
a=open('lexicon-luke','rb')
successorlist=pickle.load(a)
a.close()
def nextword(a):
    if a in successorlist:
        return random.choice(successorlist[a])
    else:
        return 'the'
speech=''
while speech!='quit':
    speech=raw_input('>')
    s=random.choice(speech.split())
    response=''
    while True:
        neword=nextword(s)
        response+=' '+neword
        s=neword
        if neword[-1] in ',?!.':
            break
    print response

Вы склонны испытывать странное чувство, когда оно говорит что-то, что, кажется, частично имеет смысл.

0 голосов
/ 02 мая 2014

Вы могли бы сделать так: Сделайте заказ на 1 цепочку генераторов Маркова, используя слова, а не буквы.Каждый раз, когда кто-то что-то публикует, то, что он писал, добавляется в базу данных ботов.Кроме того, бот сохранял бы, когда он шел в чат и когда парень отправил первое сообщение (кратно 10 секундам), то он сохранял бы количество времени, которое этот же парень ожидал опубликовать снова (кратно 10 секундам) ...Эта вторая часть будет использоваться, чтобы увидеть, когда парень отправит сообщение, поэтому он присоединяется к чату и через некоторое время, основываясь на таблице «через сколько 10 секунд парень отправил сообщение после присоединения к чату», затем он продолжитписать с той же таблицей, думая: «сколько времени ушло на написание поста, который был опубликован после поста, который он использовал за X секунд, чтобы подумать и написать»

...