web-dev-qa-db-fra.com

Comment fonctionnent les chatbots Markov Chain?

Je pensais créer un chatbot en utilisant quelque chose comme des chaînes de Markov, mais je ne sais pas trop comment le faire fonctionner. D'après ce que je comprends, vous créez un tableau à partir de données avec un mot donné, puis des mots qui suivent. Est-il possible d'attacher n'importe quelle sorte de probabilité ou de compteur pendant l'entraînement du bot? Est-ce même une bonne idée?

La deuxième partie du problème concerne les mots clés. En supposant que je puisse déjà identifier les mots clés à partir des entrées de l'utilisateur, comment générer une phrase qui utilise ce mot clé? Je ne veux pas toujours commencer la phrase avec le mot-clé, alors comment amorcer la chaîne markov?

70
Jordan

J'ai créé un chatbot de chaîne Markov pour IRC in Python il y a quelques années et je peux faire la lumière sur la façon dont je l'ai fait. Le texte généré ne fait pas nécessairement de sens, mais il peut être très amusant à lire. Permet de le décomposer en étapes. En supposant que vous avez une entrée fixe, un fichier texte, (vous pouvez utiliser la saisie à partir du texte de chat ou des paroles ou simplement utiliser votre imagination)

Parcourez le texte et créez un dictionnaire, c'est-à-dire un conteneur de valeur-clé. Et mettez toutes les paires de mots comme clés et le mot suivant comme valeur. Par exemple: si vous avez un texte "abcabk", vous commencez par "ab" comme clé et "c" comme valeur, puis "bc" et "a" comme valeur ... la valeur doit être une liste ou toute collection contenant 0 ..many 'items' car vous pouvez avoir plusieurs valeurs pour une paire de mots donnée. Dans l'exemple ci-dessus, vous aurez "a b" deux fois suivi du poing par "c" puis à la fin par "k". Donc, à la fin, vous aurez un dictionnaire/hachage ressemblant à ceci: {'a b': ['c','k'], 'b c': ['a'], 'c a': ['b']}

Vous avez maintenant la structure nécessaire pour créer votre texte funky. Vous pouvez choisir de commencer avec une clé aléatoire ou un endroit fixe! Donc, étant donné la structure que nous avons, nous pouvons commencer par enregistrer "ab" puis prendre au hasard un mot suivant de la valeur, c ou k, donc le premier enregistrement dans la boucle, "abk" (si "k" était la valeur aléatoire choisie) puis vous continuez en déplaçant une étape vers la droite qui dans notre cas est "bk" et enregistrez une valeur aléatoire pour cette paire si vous l'avez, dans notre cas non, donc vous sortez de la boucle (ou vous pouvez décider d'autres choses comme recommencer à nouveau). Lorsque la boucle est terminée, vous imprimez votre chaîne de texte enregistrée.

Plus l'entrée est grande, plus vous aurez de valeurs pour vos clés (paire de mots) et vous aurez alors un "bot plus intelligent" afin que vous puissiez "entraîner" votre bot en ajoutant plus de texte (peut-être une entrée de chat?). Si vous avez un livre en entrée, vous pouvez construire de belles phrases aléatoires. Veuillez noter que vous n'avez pas à prendre un seul mot qui suit une paire comme valeur, vous pouvez en prendre 2 ou 10. La différence est que votre texte apparaîtra plus précis si vous utilisez des blocs de construction "plus longs". Commencez avec une paire comme clé et le mot suivant comme valeur.

Donc, vous voyez que vous pouvez essentiellement avoir deux étapes, commencez par créer une structure où vous choisissez au hasard une clé pour commencer, puis prenez cette clé et imprimez une valeur aléatoire de cette clé et continuez jusqu'à ce que vous n'ayez pas de valeur ou une autre condition. Si vous le souhaitez, vous pouvez "amorcer" une paire de mots à partir d'une entrée de discussion à partir de votre structure de valeurs-clés pour commencer. C'est à votre imagination comment démarrer votre chaîne.

Exemple avec de vrais mots:

"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"]

......

Construisons maintenant une boucle:

Choisissez une clé aléatoire, dites "salut mon" et choisissez une valeur au hasard, une seule ici donc son "nom" (SAUVEGARDE "salut mon nom").
Maintenant, déplacez-vous d'un pas vers la droite en prenant "mon nom" comme clé suivante et choisissez une valeur aléatoire ... "est" (ENREGISTRER "salut mon nom est").
Maintenant, déplacez-vous et prenez "nom est" ... "Al" (SAUVEGARDE "salut mon nom est AL").
Maintenant, prenez "est Al" ... "et" (ENREGISTREMENT "salut mon nom est Al et").

...

Lorsque vous arrivez à "et je", vous choisirez au hasard une valeur, disons "peut", puis le mot "je peux" est fait etc ... lorsque vous arrivez à votre condition d'arrêt ou que vous n'avez aucune valeur, imprimez le construit chaîne dans notre cas:

"salut je m'appelle Al et je peux y vivre aussi longtemps que je veux"

Si vous avez plus de valeurs, vous pouvez passer à n'importe quelle touche. Plus vous aurez de valeurs, plus vous aurez de combinaisons et plus le texte sera aléatoire et amusant.

137
Nocker

Le bot choisit un mot aléatoire dans votre entrée et génère une réponse en choisissant un autre mot aléatoire qui a été vu comme étant un successeur de son mot détenu. Il répète ensuite le processus en trouvant à son tour un successeur à cette Parole et en continuant de manière itérative jusqu'à ce qu'il pense qu'il en dit assez. Il arrive à cette conclusion en s'arrêtant à un mot qui était avant un signe de ponctuation dans le texte de formation. Il revient ensuite en mode de saisie pour vous permettre de répondre, etc.

Ce n'est pas très réaliste, mais je mets au défi quiconque de faire mieux avec 71 lignes de code !! C'est un grand défi pour tous les pythonistes en herbe, et je souhaite juste pouvoir ouvrir le défi à un public plus large que le petit nombre de visiteurs que j'obtiens sur ce blog. Pour coder un bot qui est toujours garanti grammatical, il doit sûrement être plus proche de plusieurs centaines de lignes, j'ai simplifié énormément en essayant simplement de penser à la règle la plus simple pour donner à l'ordinateur un simple coup de poignard pour avoir quelque chose à dire.

Ses réponses sont pour le moins plutôt impressionnistes! Vous devez également mettre ce que vous dites entre guillemets simples.

J'ai utilisé Guerre et Paix pour mon "corpus" qui a pris quelques heures pour l'entraînement, utilisez un fichier plus court si vous êtes impatient…

voici l'entraîneur

#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()

Voici le bot:

#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

Vous avez tendance à ressentir un sentiment étrange quand il dit quelque chose qui semble partiellement logique.

7
user3513316

Vous pourriez faire comme ceci: Créez un générateur de chaîne de Markov d'ordre 1, en utilisant des mots et non des lettres. Chaque fois que quelqu'un publie quelque chose, ce qu'il a publié est ajouté à la base de données du bot. De plus, le bot économiserait quand il allait discuter et quand un gars avait posté le premier message (en multiples de 10 secondes), puis il économisait le temps que ce même gars avait attendu pour publier à nouveau (en multiples de 10 secondes) ... Cette deuxième partie serait utilisée pour voir quand le gars postera, donc il rejoint le chat et après un certain temps basé sur une table avec "après combien de 10 secondes le gars a posté après avoir rejoint le chat", alors il continuerait de poster avec le même tableau en pensant "combien de temps a été utilisé pour écrire le post qui a été posté après un post qu'il a utilisé X secondes pour réfléchir et écrire"

0
guestrt