Ява
Новое редактирование : еще больше настроек в свободное время. Я начал новую ветку, где я играл с алгоритмом DFS. Официально ветка должна выступать в качестве ядра для нового алгоритма BFS, который я планирую, но в то же время я хотел лучше понять, что делает DFS и как она принимает решения. Для этого я добавил функцию подавления, которая начинает затухать значение нового слова, независимо от тематики или нет, по мере того, как предложения растут длиннее. Кроме того, все слова теперь вносят ценность в предложение, но слова, которых нет в теме или списке тем предложения, вносят только 25% их значения частоты. Пример разговора можно найти здесь, и это очень хорошо, когда мы говорим о физике, человеческой природе Chatbrains и других захватывающих темах.код филиала здесь .
Изменить : я немного подправил код. Вместо того, чтобы публиковать ревизии здесь, проверьте это в моем репозитории github, где вы найдете последние ревизии. Я также добавил новую беседу против самой последней версии, где мы обсуждаем чат-ботов, глубинный поиск и то, как программирование должно использоваться для создания живых существ!
Я решил принять этот вызов целостно. Мой чат-бот знает очень мало вещей: ни слов, ни синтаксиса, ни ничего. Он умеет разбирать стандартный английский на слова и распознавать несловарные символы как знаки препинания. Вот и все. Все, что он знает, он узнает из взаимодействия с пользователем. Когда вы взаимодействуете с ним, он обращает внимание на связи между словами и строит предложения, используя эту информацию. Конечно, обратитесь к источнику за дополнительной информацией. Я значительно превзошел рекомендованную продолжительность программы, но с хорошей целью. Вот некоторые основные моменты программы:
- Чатбот начинается без ведома (следует «Правилам»: 3 )
- Частота появления слова отслеживается
- Частоты слов «затухают», поэтому разговор может переходить от темы к теме (следует «Бонус»: 3 и 4 )
- Расположение слов в наблюдаемых предложениях записывается, поэтому «фразы» неявно отслеживаются (например, если вы используете много предложных фраз в чате с ботом, бот тоже будет использовать их много!)
- Приговоры строятся на основе предпочтения следовать наиболее часто наблюдаемым связям между словами со случайными факторами, которые привносят вариации
- Алгоритм построения предложения - это поиск в глубину, который пытается максимизировать вхождение тематических слов в выходное предложение с небольшим предпочтением к конечным предложениям (это следует за «Бонусом»: 1 - я использую довольно чертовски крутой алгоритм обучения, который меняется со временем и сохраняет знания о собранных словесных связях)
- редактировать: тематические слова теперь взяты как из глобального знания повторяющихся слов, так и из самого последнего предложения
- редактировать: веса слов теперь вычисляются с использованием логической базы 4 длины слова, поэтому более длинные слова взвешиваются более сильно, а более короткие слова - более слабо - это восполняет недостаток истинного корпуса, который можно использовать как для взвешивания, так и для устранение высокочастотных, малоценных слов, как это легко сделать с помощью корпуса.
- редактирование: по мере того, как длина предложения увеличивается во время построения, функция подавления начинает уменьшать значение дополнительных слов.
- редактирование: «окончание» предложения теперь менее ценно, так как оно вызывало перевес коротких глупых предложений.
- редактировать: все слова теперь дают значение, хотя не по теме слова вносят вклад только в 25% от общего значения частоты.
- Существует встроенный максимум глубины, чтобы предотвратить слишком много циклов и слишком много времени, затрачиваемого на использование моего прецедента слова для построения предложения.
- Циклы обнаруживаются непосредственно при построении предложения, и, хотя они технически допустимы, существует высокая вероятность того, что циклов избежать
- Настраиваемое время ожидания используется, чтобы стимулировать как сокращение веток, так и завершение операторов, а также предотвращение прохождения 5-10 секундной «приемлемой задержки» в правилах.
Подводя итог моей связи с правилами:
- Для «Правил»: 1 я выбрал Java, которая является многословной, поэтому будьте осторожны.
- Для «Правил»: 2 используется только пользовательский ввод, хотя у меня есть некоторый код заглушки, чтобы добавить сохранение / загрузку мозга на будущее
- Для «Правил»: 3 предустановленного словаря нет. ChatBot знает, как разбирать английский, но это все. Начиная, он абсолютно ничего не знает.
- Для «Обязательных критериев»: 1 , моя программа длиннее, но в ней много классного. Я надеюсь, вы пропустите.
- Для «Обязательных критериев»: 2 у меня есть тайм-аут в алгоритме построения моего предложения, чтобы явно предотвратить поиск продолжительностью более 5-6 секунд. Лучшее предложение до сих пор возвращается по таймауту.
- Для «Обязательных критериев»: 3 Темы обычно объединяются примерно в 10 предложений, поэтому к тому времени Бот будет по теме, а к 20 предложениям будет отвечать на утверждения с некоторыми захватывающими случайными конструкциями, которые действительно имеют некоторый смысл.
- Для «Обязательных критериев»: 4 я ничего не позаимствовал из ссылочного кода. Это совершенно уникальная конструкция.
- Для «Бонуса»: 1 , мне нравится думать, что этот бот довольно исключительный. Это не будет так убедительно, как скриптовые боты, но не имеет абсолютно никаких ограничений по темам и будет изящно (с постоянством) переходить от темы разговора к теме.
- Для «Бонуса»: 2 , это строго круговая игра, поэтому здесь нет бонуса. Все же. В моем алгоритме ответа нет требований, поэтому я планирую версию с резьбой, которая будет учитывать этот бонус.
- Для «Бонуса»: 3 , изначально этот бот будет имитировать, но по мере того, как разговор переходит за пределы первых нескольких предложений, имитация явно закончится.
- Для «Бонуса»: 4 «настроения» не обрабатываются каким-либо осмысленным образом, но, как следует из темы с настройками бота, это изменит настроение.
- Для «Бонуса»: 5 , сохранение и загрузка мозга в настоящее время не осуществляются.
Итак, я выполнил все базовые правила, все обязательные правила и временные правила бонусов 1, 3 и 4.
В качестве еще одного бонуса я прокомментировал весь код, поэтому не стесняйтесь заимствовать или давать рекомендации по улучшению. Ясно, что, поскольку у меня нет встроенного диалога и нет «структурных» знаний, разговоры будут странными дольше, чем другие боты, но я думаю, что я довольно хорошо соблюдаю правила.
Теперь перейдите к коду (некоторые комментарии отредактированы, чтобы соответствовать ограничению тела) или следуйте ему на GitHub, так как я продолжаю улучшать его :
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();
}
}
}
Пример разговора:
Связанные ч / б ограничений по количеству символов
Разговор, где Бот говорит мне, что я должен программировать живые существа
Последний разговор, в котором Бот рассказывает об истинной природе чат-мозгов, физике, физической вселенной и о том, как я, скорее всего, тоже чат-мозг
и так далее. У меня есть несколько вещей, которые я собираюсь добавить - например, из-за общности простых слов, они, как правило, доминируют в списках неучтенных тем. Я собираюсь добавить процент пропуска к теме слов, чтобы пропустить общие слова.
Chatbot? Well the earth is fun place to talk about
- Эй, на самом деле он сделал свое (понятное) предложение там в конце! : 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 ++
Теперь мне просто нужно написать алгоритм ведения разговора. Мое первое упражнение по машинному обучению.
Редактировать:
Все мои попытки оказались нелепыми, поэтому я думаю, что оставлю это так. Другие были так же смешны, как и все это:
источник
C ++
Я стремился к дополнительному бонусу 3: « Менее подражая, поведение бота отличается от поведения пользователя, отделяя восприятие отношения бота от отношения пользователя ». В результате получился действительно упрямый бот, который не может легко переключить тему и сводит вас с ума.
Обсуждение может занять некоторое время, через некоторое время обсуждение может быть таким:
Подход состоит в том, чтобы хранить все в группы из 3 связанных слов. Каждая группа взвешивается и повторно взвешивается в 1000-мерной матрице словогрупп. Исходный код:
источник
class c_wglist { ... } wgl;
. Меня устраивает. Попробуйте инициализировать переменную wgl (class c_wglist) в другом месте.Python3 + SQLite3
Вот маленький бот, который я только что сделал!
Как это работает?
Используются три таблицы SQL: одна для слов, одна для предложений, одна для связи слов, набранных пользователем, со следующим предложением, которое должен отобразить бот.
Каковы особенности?
Смотрите код ниже:
Вот три первых «разговора», которые у меня были с ботом, начиная с пустой базы данных:
Вы можете посмотреть здесь для более подробного объяснения.
источник
Вот один из тех, что я написал в Liberty BASIC некоторое время назад. Он не учится, но отвечает на разные ответы на свои вопросы.
пример разговора:
источник
HTML5
источник
Фортран 95
Вдохновленный ответом пользователя TheDoctor выше, я решил создать забавного чат-бота аналогичным образом. Этот код также не изучается, и я делюсь им здесь просто для удовольствия.
Он распознает следующие термины и утверждения: «да» и «да», «нет» и «нет», отсутствие пунктуации или типы знаков препинания (фразы заканчивающиеся на «!», «?», «...») фразы, начинающиеся с «почему», «как» или «что», фразы в шапках, смех (такие как «хахаха», «lol» и «kkk»), очень короткие и очень длинные ответы, фразы, содержащие слово «F», фразу содержащие слова «люблю тебя» (попробуйте не менее 3 раз). Когда он спросит о смысле жизни, попробуйте ответить «42». Если он спросит, умнее ли он, чем HAL 9000, ответьте на что-нибудь, содержащее слова «правда», «правда», «правильно», «ложь», «ложь» или «неправда». Если он спросит, знаете ли вы конкретную шутку, ответьте «нет» и пусть он скажет это вам. Если он «тук-тук», ответьте «кто там?», Также помогите ему с источником цитаты. Чтобы выйти, просто введите «выйти».
Пример разговора:
PS: пожалуйста, прости мое
goto
оскорбление, я знаю, что весь этот код - своего рода беспорядок ... :)источник