Java
Nueva edición : aún más ajustes en el tiempo libre. Comencé una nueva rama, donde he estado jugando con el algoritmo DFS. Oficialmente, la sucursal debe actuar como núcleo de un nuevo algoritmo BFS que estoy planeando, pero mientras tanto quería tener una mejor idea de lo que está haciendo el DFS y cómo está tomando sus decisiones. Con ese fin, agregué una función de supresión que comienza a deteriorar el valor de una nueva palabra, independientemente del tema o no, a medida que las oraciones crecen. Además, todas las palabras aportan valor a la oración ahora, pero las palabras que no están en el tema o en la lista de temas de oración contribuyen solo con el 25% de su valor de frecuencia. Aquí se puede encontrar una conversación de ejemplo y es bastante buena, donde hablamos sobre física, la naturaleza humana de Chatbrains y otros temas fascinantes. código de rama de aquí .
Editar : He estado modificando un poco el código. En lugar de publicar las revisiones aquí, échale un vistazo en mi repositorio de github donde encontrarás las últimas revisiones. ¡También agregué una nueva conversación contra la versión más reciente, donde discutimos los chatbots, la búsqueda profunda en primer lugar y cómo se debe usar la programación para construir seres vivos!
Decidí aceptar este desafío de manera integral. Mi chatbot sabe muy pocas cosas al principio: sin palabras, sin sintaxis, sin nada. Sabe cómo analizar el inglés estándar en palabras y cómo identificar los caracteres que no son palabras como puntuación. Eso es. Todo lo que sabe lo aprende de la interacción con el usuario. A medida que interactúa con él, presta atención a las conexiones entre las palabras y construye oraciones utilizando esa información. Por supuesto, consulte la fuente para obtener más información. He excedido en gran medida las expectativas recomendadas de duración del programa de este desafío, pero con un buen propósito. Estos son algunos aspectos destacados del programa:
- Chatbot comienza sin conocimiento (sigue las "Reglas": 3 )
- Se realiza un seguimiento de la frecuencia de aparición de palabras
- Las frecuencias de palabras están "decaídas" para que la conversación pueda moverse de un tema a otro (sigue "Bonus": 3 y 4 )
- Se registra la disposición de las palabras en las oraciones observadas, por lo que se hace un seguimiento implícito de las "frases" (por ejemplo, si usa muchas frases preposicionales al chatear con el bot, ¡el bot también usará muchas de ellas!)
- Las oraciones se construyen al preferir seguir las conexiones más frecuentes observadas entre palabras, con factores aleatorios para inyectar variación
- El algoritmo de construcción de oraciones es una Búsqueda de profundidad primero, que intenta maximizar la aparición de palabras de tema en la oración de salida, con una pequeña preferencia por las oraciones finales (esto sigue a "Bonus": 1 - Utilizo un algoritmo de aprendizaje muy bueno, que cambia con el tiempo y retiene el conocimiento de las conexiones de palabras cosechadas)
- editar: las palabras de tema ahora se extraen del conocimiento global de las palabras recurrentes y de la oración más reciente
- editar: las ponderaciones de las palabras ahora se calculan utilizando la base de registro 4 de la longitud de la palabra, por lo que las palabras más largas se ponderan más fuertemente y las palabras más cortas, más débilmente, esto es para compensar la falta de un corpus verdadero para usar tanto en la ponderación como en la ponderación eliminando palabras de alta frecuencia y bajo valor como se puede hacer fácilmente con un corpus.
- editar: a medida que la longitud de la oración aumenta durante la construcción, una función de supresión comienza a disminuir el valor de palabras adicionales.
- editar: El "final" de la oración es menos valioso ahora, ya que estaba causando una preponderancia de oraciones cortas y tontas.
- editar: Todas las palabras ahora aportan valor, aunque las palabras fuera del tema solo contribuyen al 25% del valor de frecuencia global.
- Hay un máximo de profundidad incorporado para evitar demasiados bucles y demasiado tiempo debido a mi uso del precedente de palabras para construir una oración.
- Los bucles se detectan directamente mientras se construye una oración, y aunque técnicamente están permitidos, existe una alta probabilidad de que se eviten los bucles.
- El tiempo de espera optimizable se utiliza para alentar tanto la poda de sucursales como la finalización de la declaración, y también para evitar pasar el "retraso aceptable" de 5 a 10 segundos en las reglas
Para resumir mi conexión con las reglas:
- Para "Reglas": 1 , elegí Java, que es detallado, así que sé gentil.
- Para "Reglas": 2 , solo se aprovecha la entrada del usuario, aunque tengo algo de código auxiliar para agregar la función de guardar / cargar el cerebro en el futuro
- Para "Reglas": 3 , no hay absolutamente ningún vocabulario preestablecido. ChatBot sabe cómo analizar el inglés, pero eso es todo. Comenzando, no sabe absolutamente nada.
- Para "Criterios obligatorios": 1 , mi programa es más largo, pero tiene muchos paquetes increíbles. Espero que pases por alto.
- Para "Criterios obligatorios": 2 , tengo un tiempo de espera en el algoritmo de construcción de mi oración para evitar explícitamente más de 5-6 segundos de tiempo de búsqueda. La mejor oración hasta ahora se devuelve en el tiempo de espera.
- Para "Criterios obligatorios": 3 , los temas generalmente se solidifican en aproximadamente 10 oraciones, por lo que el Bot estará en el tema para entonces, y en 20 oraciones responderá a las declaraciones con algunas construcciones aleatorias fascinantes que realmente tienen un poco de sentido.
- Para "Criterios obligatorios": 4 , no tomé prestado nada del código de referencia. Esta es una construcción completamente única.
- Para "Bonus": 1 , me gusta pensar que este bot es bastante excepcional. No será tan convincente como los bots con script, pero no tiene absolutamente ninguna limitación en los temas y se moverá con gracia (con persistencia) de un tema de conversación a otro.
- Para "Bonus": 2 , esto es estrictamente round-robin, por lo que no hay bonificación aquí. Todavía. No hay ningún requisito dentro de mi algoritmo para la respuesta, por lo que estoy planeando una versión Threaded que aborde esta bonificación.
- Para "Bonus": 3 , inicialmente este bot imitará, pero a medida que la conversación avance más allá de las primeras oraciones, la imitación terminará claramente.
- Para "Bonus": 4 , los "estados de ánimo" no se procesan de manera significativa, pero a medida que el tema de preferencias de bot sigue, cambiará los estados de ánimo.
- Para "Bonus": 5 , guardar y cargar cerebro no está actualmente en su lugar.
Por lo tanto, he cumplido todas las reglas básicas, todas las reglas obligatorias y las reglas de bonificación provisional 1, 3 y 4.
Como otra ventaja, he comentado todo el código, así que siéntase libre de pedir prestado o hacer recomendaciones para mejoras. Claramente, como no tengo diálogo incorporado ni conocimiento "estructural", las conversaciones serán extrañas por más tiempo que otros robots, pero creo que cumplo con las reglas bastante bien.
Ahora, en el código (Algunos comentarios redactados para ajustarse al límite del cuerpo) o sígalo en GitHub, a medida que continúo mejorando :
import java.util.*;
import java.util.regex.*;
public class LearningChatbot {
/**
* Static definition of final word in a statement. It never has
* any descendents, and concludes all statements. This is the only
* "starting knowledge" granted the bot.
*/
public static final ChatWord ENDWORD = new ChatWord("\n");
/**
* The Brain of this operation.
*/
private ChatbotBrain brain;
/**
* Starts LearningChatbot with a new brain
*/
public LearningChatbot() {
brain = new ChatbotBrain();
}
/**
* Starts LearningChatbot with restored brain.
*/
public LearningChatbot(String filename) {
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Invocation method.
*/
public void beginConversation() {
ChatbotBrain cb = new ChatbotBrain();
Scanner dialog = new Scanner(System.in);
boolean more = true;
while (more) {
System.out.print(" You? ");
String input = dialog.nextLine();
if (input.equals("++done")) {
System.exit(0);
} else if (input.equals("++save")) {
System.out.println("Saving not yet implemented, sorry!");
System.exit(0);
} else if (input.equals("++help")) {
getHelp();
}else {
cb.decay();
cb.digestSentence(input);
}
System.out.print("Chatbot? ");
System.out.println(cb.buildSentence());
}
}
/**
* Help display
*/
public static void getHelp() {
System.out.println("At any time during the conversation, type");
System.out.println(" ++done");
System.out.println("to exit without saving.");
System.out.println("Or type");
System.out.println(" ++save");
System.out.println("to exit and save the brain.");
System.out.println();
}
/**
* Get things started.
*/
public static void main(String[] args) {
System.out.println("Welcome to the Learning Chatbot");
System.out.println();
getHelp();
LearningChatbot lc = null;
if (args.length > 0) {
System.out.printf("Using %s as brain file, if possible.", args[0]);
lc = new LearningChatbot(args[0]);
} else {
lc = new LearningChatbot();
}
lc.beginConversation();
}
/**
* The ChatbotBrain holds references to all ChatWords and has various
* methods to decompose and reconstruct sentences.
*/
static class ChatbotBrain {
/**
* A tracking of all observed words. Keyed by the String version of
* the ChatWord, to allow uniqueness across all ChatWords
*/
private Map<String,ChatWord> observedWords;
/**
* This brain is going to be able to keep track of "topics" by way of
* a word frequency map. That way, it can generate sentences based
* on topic-appropriateness.
*/
private Map<ChatWord, Double> wordFrequencyLookup;
/**
* This holds the actual word frequencies, for quick isolation of
* highest frequency words.
*/
private NavigableMap<Double, Collection<ChatWord>> wordFrequency;
/**
* This holds the count of words observed total.
*/
private int wordCount;
/**
* This holds the current "values" of all words.
*/
private double wordValues;
/**
* A "word" that is arbitrarily the start of every sentence
*/
private ChatWord startWord;
/**
* Rate of decay of "topics".
*/
private double decayRate;
// These values configure various features of the recursive
// sentence construction algorithm.
/** Nominal (target) length of sentences */
public static final int NOMINAL_LENGTH = 10;
/** Max length of sentences */
public static final int MAX_LENGTH = 25;
/** Sentence creation timeout */
public static final long TIMEOUT = 5000;
/** Topic words to match against */
public static final int TOPICS = 3;
/** Minimum branches to consider for each word */
public static final int MIN_BRANCHES = 3;
/** Maximum branches to consider for each word */
public static final int MAX_BRANCHES = 5;
/** % chance as integer out of 100 to skip a word */
public static final int SKIP_CHANCE = 20;
/** % chance as integer to skip a word that would cause a loop */
public static final int LOOP_CHANCE = 5;
/** % chance that punctuation will happen at all */
public static final int PUNCTUATION_CHANCE = 25;
/** % chance that a particular punctuation will be skipped */
public static final int PUNCTUATION_SKIP_CHANCE = 40;
/**
* Convenience parameter to use a common random source
* throughout the brain.
*/
private Random random;
/**
* Gets the Chatbot started, sets up data structures necessary
*/
public ChatbotBrain() {
observedWords = new HashMap<String,ChatWord>();
observedWords.put("\n",ENDWORD);
startWord = new ChatWord("");
observedWords.put("",startWord);
wordFrequencyLookup = new HashMap<ChatWord, Double>();
wordFrequency = new TreeMap<Double, Collection<ChatWord>>();
decayRate = 0.05;
wordCount = 0;
wordValues = 0.0;
random = new Random();
}
/**
* More complex digest method (second edition) that takes a sentence,
* cuts it pu, and links up the words based on ordering.
*/
public void digestSentence(String sentence) {
Scanner scan = new Scanner(sentence);
ChatWord prior = null;
ChatWord current = null;
String currentStr = null;
String currentPnc = null;
while (scan.hasNext()) {
currentStr = scan.next();
Pattern wordAndPunctuation =
Pattern.compile("([a-zA-Z\\-_'0-9]+)([^a-zA-Z\\-_'0-9]?)[^a-zA-Z\\-_'0-9]*?");
Matcher findWords = wordAndPunctuation.matcher(currentStr);
// Basically this lets us find words-in-word typos like this:
// So,bob left his clothes with me again.
// where "So,bob" becomes "So," "bob"
while (findWords.find()) {
currentStr = findWords.group(1);
currentPnc = findWords.group(2);
if (currentStr != null) {
if (observedWords.containsKey(currentStr)) {
current = observedWords.get(currentStr);
} else {
current = new ChatWord(currentStr);
observedWords.put(currentStr, current);
}
incrementWord(current);
if (currentPnc != null && !currentPnc.equals("")) {
current.addPunctuation(currentPnc.charAt(0));
}
if (prior != null) {
prior.addDescendent(current);
}
if (prior == null) {
startWord.addDescendent(current);
}
prior = current;
}
}
}
if (prior != null) { // finalize.
prior.addDescendent(ENDWORD);
}
}
/**
* Increments the value of a word (catalogues a new sighting).
*/
public void incrementWord(ChatWord word) {
Double curValue;
Double nextValue;
Collection<ChatWord> freqMap;
if (wordFrequencyLookup.containsKey(word)) {
curValue = wordFrequencyLookup.get(word);
freqMap = wordFrequency.get(curValue);
freqMap.remove(word);
} else {
curValue = 0.0;
}
nextValue=curValue+1.0;
wordFrequencyLookup.put(word, nextValue);
freqMap = wordFrequency.get(nextValue);
if (freqMap == null) {
freqMap = new HashSet<ChatWord>();
wordFrequency.put(nextValue, freqMap);
}
freqMap.add(word);
wordCount++;
wordValues++;
}
/**
* Decays a particular word by decay rate.
*/
public void decayWord(ChatWord word) {
Double curValue;
Double nextValue;
Collection<ChatWord> freqMap;
if (wordFrequencyLookup.containsKey(word)) {
curValue = wordFrequencyLookup.get(word);
freqMap = wordFrequency.get(curValue);
freqMap.remove(word);
} else {
return;
}
wordValues-=curValue; // remove old decay value
nextValue=curValue-(curValue*decayRate);
wordValues+=nextValue; // add new decay value
wordFrequencyLookup.put(word, nextValue);
freqMap = wordFrequency.get(nextValue);
if (freqMap == null) {
freqMap = new HashSet<ChatWord>();
wordFrequency.put(nextValue, freqMap);
}
freqMap.add(word);
}
/**
* Decay all word's frequency values.
*/
public void decay() {
for (ChatWord cw : wordFrequencyLookup.keySet()) {
decayWord(cw);
}
}
/**
* Gets a set of words that appear to be "top" of the frequency
* list.
*/
public Set<ChatWord> topicWords(int maxTopics) {
Set<ChatWord> topics = new HashSet<ChatWord>();
int nTopics = 0;
for (Double weight: wordFrequency.descendingKeySet()) {
for (ChatWord word: wordFrequency.get(weight)) {
topics.add(word);
nTopics++;
if (nTopics == maxTopics) {
return topics;
}
}
}
return topics;
}
/**
* Uses word frequency records to prefer to build on-topic
* sentences.
*/
public String buildSentence() {
int maxDepth = NOMINAL_LENGTH+
random.nextInt(MAX_LENGTH - NOMINAL_LENGTH);
ChatSentence cs = new ChatSentence(startWord);
// We don't want to take too long to "think of an answer"
long timeout = System.currentTimeMillis() + TIMEOUT;
double bestValue = buildSentence(cs, topicWords(TOPICS), 0.0, 0, maxDepth, timeout);
return cs.toString();
}
public double buildSentence(ChatSentence sentence,
Set<ChatWord> topics, double curValue,
int curDepth, int maxDepth, long timeout){
if (curDepth==maxDepth || System.currentTimeMillis() > timeout) {
return curValue;
}
// Determine how many branches to enter from this node
int maxBranches = MIN_BRANCHES + random.nextInt(MAX_BRANCHES - MIN_BRANCHES);
// try a few "best" words from ChatWord's descendent list.
ChatWord word = sentence.getLastWord();
NavigableMap<Integer, Collection<ChatWord>> roots =
word.getDescendents();
// Going to keep track of current best encountered sentence
double bestSentenceValue = curValue;
ChatSentence bestSentence = null;
int curBranches = 0;
for (Integer freq : roots.descendingKeySet()) {
for (ChatWord curWord : roots.get(freq)) {
if (curWord.equals(ENDWORD)) {
// let's weigh the endword cleverly
double endValue = random.nextDouble() * wordFrequency.lastKey();
if (curValue+endValue > bestSentenceValue) {
bestSentenceValue = curValue+endValue;
bestSentence = new ChatSentence(sentence);
bestSentence.addWord(curWord);
}
curBranches++;
} else {
int chance = random.nextInt(100);
boolean loop = sentence.hasWord(curWord);
/* Include a little bit of chance in the inclusion of
* any given word, whether a loop or not.*/
if ( (!loop&&chance>=SKIP_CHANCE) ||
(loop&&chance<LOOP_CHANCE)) {
double wordValue = topics.contains(curWord)?
wordFrequencyLookup.get(curWord):0.0;
ChatSentence branchSentence = new ChatSentence(sentence);
branchSentence.addWord(curWord);
addPunctuation(branchSentence);
double branchValue = buildSentence(branchSentence,
topics, curValue+wordValue, curDepth+1,
maxDepth, timeout);
if (branchValue > bestSentenceValue) {
bestSentenceValue = branchValue;
bestSentence = branchSentence;
}
curBranches++;
}
}
if (curBranches == maxBranches) break;
}
if (curBranches == maxBranches) break;
}
if (bestSentence != null) {
sentence.replaceSentence(bestSentence);
}
return bestSentenceValue;
}
/**
* Adds punctuation to a sentence, potentially.
*/
public void addPunctuation(ChatSentence sentence) {
ChatWord word = sentence.getLastWord();
NavigableMap<Integer, Collection<Character>> punc = word.getPunctuation();
if (punc.size()>0 && random.nextInt(100)<PUNCTUATION_CHANCE){
Integer puncMax = punc.lastKey();
Collection<Character> bestPunc = punc.get(puncMax);
Character puncPick = null;
for (Integer freq : punc.descendingKeySet()) {
for (Character curPunc : punc.get(freq)) {
if (random.nextInt(100)>=PUNCTUATION_SKIP_CHANCE) {
puncPick = curPunc;
break;
}
}
if (puncPick != null) break;
}
if (puncPick != null) {
sentence.addCharacter(puncPick);
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChatBrain[");
sb.append(observedWords.size());
sb.append("]:");
for (Map.Entry<String,ChatWord> cw : observedWords.entrySet()) {
sb.append("\n\t");
sb.append(wordFrequencyLookup.get(cw.getValue()));
sb.append("\t");
sb.append(cw.getValue());
}
return sb.toString();
}
}
/**
* Useful helper class to construct sentences.
*/
static class ChatSentence implements Cloneable {
/**
* List of words.
*/
private List<Object> words;
/**
* Quick search construct to have O(ln) lookup times.
*/
private Set<Object> contains;
/**
* Starts to build a sentence with a single word as anchor
*/
public ChatSentence(ChatWord anchor) {
if (anchor == null) {
throw new IllegalArgumentException("Anchor must not be null");
}
words = new ArrayList<Object>();
contains = new HashSet<Object>();
words.add(anchor);
contains.add(anchor);
}
/**
* Starts a sentence using an existing ChatSentence. Also used for
* cloning.
*/
public ChatSentence(ChatSentence src) {
words = new ArrayList<Object>();
contains = new HashSet<Object>();
appendSentence(src);
}
/**
* Adds a word to a sentence
*/
public ChatSentence addWord(ChatWord word) {
if (word == null) {
throw new IllegalArgumentException("Can't add null word");
}
words.add(word);
contains.add(word);
return this;
}
/**
* Adds a character to a sentence.
*/
public ChatSentence addCharacter(Character punc) {
if (punc == null) {
throw new IllegalArgumentException("Can't add null punctuation");
}
words.add(punc);
contains.add(punc);
return this;
}
/**
* Replace a sentence with some other sentence.
* Useful to preserve references.
*/
public ChatSentence replaceSentence(ChatSentence src) {
words.clear();
contains.clear();
appendSentence(src);
return this;
}
public ChatSentence appendSentence(ChatSentence src) {
words.addAll(src.getWords());
contains.addAll(src.getWords());
return this;
}
/**
* Get last word of the sentence.
*/
public ChatWord getLastWord() {
for (int i=words.size()-1; i>=0; i--) {
if (words.get(i) instanceof ChatWord) {
return (ChatWord) words.get(i);
}
}
throw new IllegalStateException("No ChatWords found!");
}
/**
* Checks if the sentence has a word
*/
public boolean hasWord(ChatWord word) {
return contains.contains(word);
}
/**
* Counts the number of words in a sentence.
*/
public int countWords() {
int cnt = 0;
for (Object o : words) {
if (o instanceof ChatWord) {
cnt++;
}
}
return cnt;
}
/**
* Gets all the words of the sentence
*/
private List<Object> getWords() {
return words;
}
/**
* Returns the sentence as a string.
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
for (Object o : words) {
if (o instanceof ChatWord) {
ChatWord cw = (ChatWord) o;
sb.append(" ");
sb.append( cw.getWord() );
} else {
sb.append(o);
}
}
return sb.toString().trim();
}
/**
* Clones this sentence.
*/
@Override
public Object clone() {
return new ChatSentence(this);
}
}
/**
* ChatWord allows the creation of words that track how they are
* connected to other words in a forward fashion.
*/
static class ChatWord {
/** The word. */
private String word;
/** Collection of punctuation observed after this word */
private NavigableMap<Integer, Collection<Character>> punctuation;
/** Lookup linking observed punctuation to where they are in ordering */
private Map<Character, Integer> punctuationLookup;
/** Punctionation observation count */
private Integer punctuationCount;
/** Collection of ChatWords observed after this word */
private NavigableMap<Integer, Collection<ChatWord>> firstOrder;
/** Lookup linking observed words to where they are in ordering */
private Map<ChatWord, Integer> firstOrderLookup;
/** First order antecedent word count */
private Integer firstOrderCount;
/**
* Creates a new ChatWord that is aware of punctuation that
* follows it, and also ChatWords that follow it.
*/
public ChatWord(String word){
this.word = word;
this.firstOrder = new TreeMap<Integer, Collection<ChatWord>>();
this.firstOrderLookup = new HashMap<ChatWord, Integer>();
this.firstOrderCount = 0;
this.punctuation = new TreeMap<Integer, Collection<Character>>();
this.punctuationLookup = new HashMap<Character, Integer>();
this.punctuationCount = 0;
}
protected NavigableMap<Integer, Collection<ChatWord>> getDescendents() {
return firstOrder;
}
/**
* Returns how many descendents this word has seen.
*/
protected int getDescendentCount() {
return firstOrderCount;
}
/**
* Gets the lookup map for descendents
*/
protected Map<ChatWord, Integer> getDescendentsLookup() {
return firstOrderLookup;
}
/** As conversation progresses, word orderings will be encountered.
* The descendent style of "learning" basically weights how often
* words are encountered together, and is strongly biased towards
* encountered ordering.
*/
public void addDescendent(ChatWord next) {
if(next != null){
firstOrderCount++;
int nextCount = 1;
Collection<ChatWord> obs = null;
// If we've already seen this word, clean up prior membership.
if(firstOrderLookup.containsKey(next)){
nextCount = firstOrderLookup.remove(next);
obs = firstOrder.get(nextCount);
// Remove from prior obs count order
obs.remove(next);
nextCount++;
}
obs = firstOrder.get(nextCount);
if (obs == null) { // we don't have this order yet
obs = new HashSet<ChatWord>();
firstOrder.put(nextCount, obs);
}
firstOrderLookup.put(next, nextCount);
obs.add(next);
}
}
/**
* Some words have punctuation after them more often than not.
* This allows the ChatBrain to record occurrences of punctuation
* after a word.
*/
public void addPunctuation(Character punc) {
if(punc != null){
punctuationCount++;
int puncCount = 1;
Collection<Character> obs = null;
// If we've already seen this punc, clean up prior membership.
if(punctuationLookup.containsKey(punc)){
puncCount = punctuationLookup.remove(punc);
obs = punctuation.get(puncCount);
// Remove from prior obs count order
obs.remove(punc);
puncCount++;
}
obs = punctuation.get(puncCount);
if (obs == null) { // we don't have this order yet
obs = new HashSet<Character>();
punctuation.put(puncCount, obs);
}
punctuationLookup.put(punc, puncCount);
obs.add(punc);
}
}
/**
* Including this for now, but I don't like it -- it returns all
* punctuation wholesale. I think what would be better is some
* function that returns punctuation based on some characteristic.
*/
protected NavigableMap<Integer, Collection<Character>> getPunctuation() {
return punctuation;
}
/**
* Gets count of punctuation encountered.
*/
protected int getPunctuationCount() {
return punctuationCount;
}
/**
* Gets lookup of punctuations encountered.
*/
protected Map<Character, Integer> getPunctuationLookup() {
return punctuationLookup;
}
/**
* Gets the String backing this ChatWord.
*/
public String getWord() {
return word;
}
/**
* ChatWords are equivalent with the String they wrap.
*/
@Override
public int hashCode() {
return word.hashCode();
}
/**
* ChatWord equality is that ChatWords that wrap the same String
* are equal, and a ChatWord is equal to the String that it contains.
*/
@Override
public boolean equals(Object o){
if (o == this) {
return true;
}
if (o instanceof ChatWord) {
return ((ChatWord)o).getWord().equals(this.getWord());
}
if (o instanceof String) {
return ((String)o).equals(this.getWord());
}
return false;
}
/**
* Returns this ChatWord as a String.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChatWord[");
sb.append(word);
sb.append("]desc{");
for (Integer key : firstOrder.keySet() ) {
Collection<ChatWord> value = firstOrder.get(key);
sb.append(key);
sb.append(":[");
for (ChatWord cw : value) {
sb.append(cw.getWord());
sb.append(",");
}
sb.append("],");
}
sb.append("}punc{");
for (Integer key : punctuation.keySet() ) {
Collection<Character> value = punctuation.get(key);
sb.append(key);
sb.append(":[");
for (Character c : value) {
sb.append("\"");
sb.append(c);
sb.append("\",");
}
sb.append("],");
}
sb.append("}");
return sb.toString();
}
}
}
Conversación de muestra:
B / c vinculado de los límites de caracteres posteriores
Conversación donde el Bot me dice que debería programar seres vivos
Última conversación en la que el Bot habla sobre la verdadera naturaleza de Chatbrains, la física, el universo físico y cómo es muy probable que también sea Chatbrain
y así. Tengo algunas cosas que voy a agregar, por ejemplo, debido a la similitud de las palabras simples, tienden a dominar las listas de temas no curados. Voy a agregar un porcentaje de omisión a las palabras del tema para que se omitan las palabras comunes.
Chatbot? Well the earth is fun place to talk about
- ¡Hey, en realidad hizo su propia oración (comprensible) al final! : D +1Chatbot? I'm not a Chatbrain since Chatbrains are the physical universe,
.The answer to the ultimate question about life, the universe, and everything is 'SyntaxError: missing ; before statement'.
C ++
Ahora solo necesito escribir el algoritmo para mantener una conversación. Mi primer ejercicio de aprendizaje automático.
Editar:
Todos mis intentos resultaron ridículos, así que creo que lo dejaré así. Los demás eran tan ridículos como esto de todos modos:
fuente
C ++
Apunté a la bonificación opcional 3: " Menos imitación, el comportamiento del bot es diferente del comportamiento del usuario, separando la percepción de la actitud del bot de la actitud del usuario ". El resultado fue un bot realmente terco que no puede cambiar de tema fácilmente y te vuelve loco.
Se necesita algo de tiempo para iniciar una discusión, después de un tiempo una discusión puede ser así:
El enfoque es almacenar todo en grupos de 3 palabras conectadas. Cada grupo se pesa y se vuelve a pesar en una matriz de grupos de palabras de 1000 dimensiones. Código fuente:
fuente
class c_wglist { ... } wgl;
. Esto funciona para mi. Intente iniciar la variable wgl (clase c_wglist) en otro lugar.Python3 + SQLite3
¡Aquí hay un pequeño bot que acabo de hacer!
¿Como funciona?
Se utilizan tres tablas SQL: una para las palabras, una para las oraciones, una para asociar las palabras escritas por el usuario, con la siguiente oración que debe mostrar el bot.
¿Cuáles son las características especiales?
Ver código a continuación:
Aquí están las tres primeras "conversaciones" que tuve con el bot, comenzando en una base de datos vacía:
Puedes echar un vistazo aquí para obtener más explicaciones.
fuente
Aquí hay uno que escribí en Liberty BASIC hace un tiempo. No aprende, pero responde las diferentes respuestas de sus preguntas.
conversación de ejemplo:
fuente
HTML5
fuente
Fortran 95
Inspirado por la respuesta anterior del usuario TheDoctor, decidí crear un chatbot divertido de manera similar. Este código tampoco se aprende, y lo estoy compartiendo aquí solo por diversión.
Reconoce los siguientes términos y declaraciones: "sí" y "sí", "no" y "no", falta de puntuación o tipos de puntuación (frases que terminan en "!", "?", "...") , frases que comienzan con "por qué", "cómo" o "qué", FRASES EN MAYÚSCULAS, risas (como "jajaja", "jajaja" y "kkk"), respuestas muy cortas y muy largas, frases que contienen la palabra F, frase que contiene las palabras "te amo" (pruébalo al menos 3 veces). Cuando pregunte sobre el significado de la vida, intente responder "42". Si le pregunta si es más inteligente que HAL 9000, responda algo que contenga las palabras "verdadero", "verdad", "correcto", "mentira", "falso" o "falso". Si él pregunta si conoces un chiste en particular, responde "no" y deja que te lo diga. Si él "llama a la puerta", responde "¿quién está allí?", También ayúdalo con la fuente de una cita. Para salir, simplemente escriba "salir".
Ejemplo de conversación:
PD: perdona mi
goto
abuso, sé que todo este código es un desastre ... :)fuente