2008-09-10 15 views
32

Quiero crear un bot que le pregunte a alguien algunas preguntas simples y ramas basadas en la respuesta. Me doy cuenta de que analizar el significado de las respuestas humanas será un desafío, pero ¿cómo configuras el programa para lidiar con el "estado" de la conversación?¿Cómo puedo programar un chat simple bot AI?

Será una conversación uno-a-uno entre un humano y el bot.

+4

No estoy del todo convencido de que los bots de chat existentes tengan algo así como 'estado'. Sus respuestas parecen depender solo de la última pregunta que hizo. Es solo una coincidencia que los humanos haremos una serie de preguntas relacionadas. –

+0

http://search.cpan.org/search?query=bot&mode=all –

+5

Hay bots con estado, trabajé en uno yo mismo. Era un bot de análisis contra una base de conocimiento que usa una red neuronal. –

Respuesta

22

Es probable que desee ver en Markov Chains como los elementos básicos para el bot AI. Escribí algo hace mucho tiempo (el código del que no estoy orgulloso y necesita algunas modificaciones para ejecutar en Python> 1.5) que puede ser un lugar de inicio útil para usted: http://sourceforge.net/projects/benzo/

EDITAR: Aquí hay un ejemplo mínimo en Python de una Cadena de Markov que acepta la entrada de stdin y emite texto en función de las probabilidades de que las palabras sucedan entre sí en la entrada. Está optimizado para los registros de chat de estilo de IRC, pero el funcionamiento de cualquier texto de tamaño decente a través de él debe demostrar los conceptos:

import random, sys 

NONWORD = "\n" 
STARTKEY = NONWORD, NONWORD 
MAXGEN=1000 

class MarkovChainer(object): 
    def __init__(self): 
     self.state = dict() 

    def input(self, input): 
     word1, word2 = STARTKEY 
     for word3 in input.split(): 
      self.state.setdefault((word1, word2), list()).append(word3) 
      word1, word2 = word2, word3 
     self.state.setdefault((word1, word2), list()).append(NONWORD) 

    def output(self): 
     output = list() 
     word1, word2 = STARTKEY 
     for i in range(MAXGEN): 
      word3 = random.choice(self.state[(word1,word2)]) 
      if word3 == NONWORD: break 
      output.append(word3) 
      word1, word2 = word2, word3 
     return " ".join(output) 

if __name__ == "__main__": 
    c = MarkovChainer() 
    c.input(sys.stdin.read()) 
    print c.output() 

Es bastante fácil de aquí para enchufar persistencia y una biblioteca de IRC y tienen la función de la tipología de bot de lo que estás hablando.

0

Sugeriría mirar las probabilidades bayesianas. Luego simplemente supervise la sala de chat por un período de tiempo para crear su árbol de probabilidades.

3

Creo que puede ver el código de Kooky, y IIRC también utiliza las Cadenas de Markov.

También echa un vistazo a kooky quotes, fueron presentados en Coding Horror no hace mucho tiempo y algunos son divertidísimos.

2

Creo que para comenzar este proyecto, sería bueno tener una base de datos con preguntas (organizada como un árbol. En cada nodo, una o más preguntas). Estas preguntas se pueden responder con "sí" o "no".

Si el robot comienza a cuestionarse, puede comenzar con cualquier pregunta de su base de datos de preguntas marcadas como una pregunta de inicio. La respuesta es el camino al siguiente nodo en el árbol.

Editar: Aquí está una somple uno escrito en Ruby puede empezar con: rubyBOT

0

No estoy seguro de que esto es lo que está buscando, pero hay un viejo programa llamado ELIZA que podría mantener una conversación tomando lo que dijiste y escupiéndote después de realizar algunas transformaciones textuales simples.

Si no recuerdo mal, muchas personas estaban convencidas de que estaban "hablando" con una persona real y tenían conversaciones largas y elaboradas con ella.

14

La gente ha mencionado ya que statefulness no es un gran componente de chatbots típicos:

  • un puro implementaciones de Markov puede expresar una especie muy suelto de estado si está creciendo su léxico y mesa en tiempo real — declaraciones anteriores por el interlocutor humano pueden ser regurgitadas por casualidad más adelante en la conversación — pero el modelo de Markov no tiene ningún mecanismo inherente para seleccionar o producir tales respuestas.

  • un bot basado en análisis (p. Ej.ELIZA) generalmente intenta responder a (algunos de) el contenido semántico de la información más reciente del usuario sin tener en cuenta los intercambios previos.

Dicho esto, que sin duda puede añadir una cierta cantidad de estado a un conversacional, independientemente del modelo de entrada-análisis y síntesis comunicado que está utilizando. Cómo hacer eso depende mucho de lo que quiere lograr con su estado, y eso no está claro en su pregunta. Un par de ideas generales, sin embargo:

  • Cree una pila de palabras clave. A medida que su ser humano ofrece información, analice las palabras clave de sus declaraciones/preguntas y las arroje a una pila de algún tipo. Cuando su chatbot no puede encontrar algo convincente para responder en la entrada más reciente — o, quizás, al azar, para mezclar las cosas — regrese a su pila, tome una palabra clave anterior, y use eso para sembrar su próximo síntesis. Para obtener puntos de bonificación, haz que el bot reconozca explícitamente que se está volviendo a un tema anterior, p. "Espera, HUMANO, antes mencionaste foo. [Sentencia sembrada por foo]".

  • Cree una lógica de diálogo tipo RPG en el bot. A medida que analice las entradas de datos, alternar indicadores para mensajes de conversación específicos o contenido del usuario y alterar de forma condicional lo que el chatbot puede hablar, o cómo se comunica. Por ejemplo, un chatbot erizado (o regaño o risa) en lenguaje grosero es bastante común; un chatbot que se pondrá de pie, y condicionalmente seguirá siéndolo hasta que se disculpe con, sería una interesante variación con respecto a esto. Cambiar la salida a MAYÚSCULAS, el tiro en la retórica de confrontación o demandas o llorando, etc.

¿Puede aclarar un poco lo que quiere el estado para ayudar a lograr?

5

Imagine una red neuronal con capacidades de análisis en cada nodo o neurona. Dependiendo de las reglas y los resultados del análisis, las neuronas disparan. Si se activan ciertas neuronas, obtendrá una buena idea sobre el tema y la semántica de la pregunta y, por lo tanto, puede dar una buena respuesta.

La memoria se realiza manteniendo los temas de los que se habla en una sesión, lo que aumenta la activación de la siguiente pregunta y, por lo tanto, guía el proceso de selección de posibles respuestas al final.

Mantenga sus reglas y patrones en una base de conocimiento, pero compílelos en la memoria al inicio, con una neurona por regla. Puede diseñar sinapsis usando algo así como oyentes o funciones de eventos.

+0

Hola Ralph, aprecio tu idea; Me acerco a un enfoque similar, más simplemente, cada "neurona" es una máquina de estados finitos con su coincidencia de patrón de dominio estrecho. Nombre de código: naif. Próximamente: https://twitter.com/solyarisoftware/status/792258290591858688 –

0

Si solo está incursionando, creo que Pidgin le permite guiar el comportamiento del estilo de chat. Parte del marco probablemente corrige el estado de quién envió el mensaje cuando, y desea mantener un registro del estado interno de su bot para cada uno de los últimos N mensajes. Las futuras decisiones estatales podrían codificarse en función de la inspección de los estados anteriores y el contenido de los mensajes más recientes. O podría hacer algo como las cadenas de Markov discutidas y usarlo tanto para analizar como para generar.

0

Si no necesita un robot de aprendizaje, es muy probable que el uso de AIML (http://www.aiml.net/) produzca el resultado que desea, al menos con respecto a la entrada de análisis de bot y la respuesta basada en él.

Reutilizará o creará "cerebros" hechos de XML (en formato AIML) y los analizará/ejecutará en un programa (analizador). Hay analizadores hechos en varios idiomas diferentes para elegir, y hasta donde puedo decir que el código parece ser de código abierto en la mayoría de los casos.

1

programa de chatbot naive. Sin análisis, sin inteligencia, solo un archivo de entrenamiento y salida.

Primero se entrena en un texto y luego usa los datos de esa capacitación para generar respuestas a la entrada del interlocutor. El proceso de capacitación crea un diccionario donde cada clave es una palabra y el valor es una lista de todas las palabras que siguen esa palabra secuencialmente en cualquier parte del texto de capacitación. Si una palabra aparece más de una vez en esta lista, entonces eso refleja y es más probable que sea elegido por el bot, no hay necesidad de cosas probabilísticas simplemente hazlo con una lista.

El bot elige una palabra aleatoria de su entrada y genera una respuesta eligiendo otra palabra aleatoria que se ha visto como sucesora de su palabra retenida. Luego repite el proceso encontrando un sucesor de esa palabra y continuando iterativamente hasta que crea que ya se dijo lo suficiente. Llega a esa conclusión deteniéndose en una palabra que era anterior a un signo de puntuación en el texto de entrenamiento. Luego vuelve al modo de entrada nuevamente para que pueda responder, y así sucesivamente.

No es muy realista, pero por el presente desafío a cualquiera a que lo haga mejor en 71 líneas de código. Este es un gran desafío para cualquier incipiente Pythonists, y solo desearía poder abrir el desafío a un público más amplio que la pequeña cantidad de visitantes que recibo en este blog. Para codificar un bot que siempre está garantizado que es gramatical seguramente debe estar más cerca de varios cientos de líneas, simplifiqué enormemente al tratar de pensar en la regla más simple para darle a la computadora una mera puñalada para tener algo que decir.

¡Sus respuestas son más bien impresionistas por decir lo menos! También debes poner lo que dices entre comillas simples.

Solía ​​Guerra y Paz para mi “corpus”, que tuvo un par de horas para el recorrido de entrenamiento, utilice un archivo más corto si está impaciente ...

aquí es el entrenador

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

aquí es el 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 

Tiendes a tener una sensación extraña cuando dice algo que parece parcialmente tener sentido.