Хто цей чат?


46

Мета:

Завдання - створити чат, з яким ви можете провести свій час, обговорюючи свої найглибші думки. Створіть чат з AI, який вчиться з ваших даних. Ваш бот повинен надихнути вас одержати свої найтемніші внутрішні істини.

Натхнення:

http://en.wikipedia.org/wiki/Chatterbot

http://io9.com/5901579/10-tricks-that-chatbots-use-to-make-you-believe-theyre-human

Правила:

  1. Ви можете використовувати будь-яку мову програмування.
  2. Ваші програми не повинні брати будь-які дані від імені файлів, мережі чи будь-чого іншого, крім введення користувача.
  3. Не може бути попередньо встановленої лексики, бот повинен дізнатися все, що він знає, з користувальницьких даних, а обговорення може бути про що завгодно.

Обов’язкові критерії:

  1. Це не Code-golf, але будь ласка, будьте прості, розмір вихідного коду повинен відповідати мові програмування, тобто: GolfScript = короткий, BF = довгий, інший = Використовуйте здоровий глузд. Використовуйте код прикладу як орієнтир, ваш код може бути вдвічі більшим за цей розмір, але тоді краще бути хорошим.
  2. Ваша програма не може почати відставати (затримка 5-10 секунд) протягом перших 1000 пропозицій.
  3. Обґрунтоване обговорення повинно проходити протягом приблизно 20-30 речень.
  4. Ваш алгоритм повинен логічно відрізнятися від прикладу коду наскільки це можливо.

Необов'язкові критерії оцінювання бонусів:

  1. Чим кращий алгоритм навчання ботів, тим краща програма.
  2. Жоден тенісний матч, тобто розмова не відповідає суворому: "користувач> комп'ютер> користувач" - повороти.
  3. Менш мімічна поведінка бота відрізняється від поведінки користувача, відокремлюючи сприйняття ставлення бота від ставлення користувача.
  4. Відчувайте різні мінливі настрої, наприклад: балакучий, мовчазний, оптимістичний, песимістичний.
  5. Спосіб збереження та завантаження "мозку", щоб ви могли продовжувати дискусію зі своїм ботом ще один день.

Приклад коду в c ++ лише для натхнення:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

using namespace std;
vector<string> words;
vector<int> weight1;
vector<int> weight2;
int oldbw;

int collect(string const& i, int w1, int w2) 
{
    istringstream iss(i), iss2(i);
    copy(istream_iterator<string>(iss),
             istream_iterator<string>(),
             back_inserter(words));
    words.insert(words.end(), "\n");
    int a = distance(istream_iterator<string>(iss2), istream_iterator<string>());
    for(int c=0;c<=a;c++) weight1.insert(weight1.end(), w1);
    for(int c=0;c<=a;c++) weight2.insert(weight2.end(), w2);
    return a;
}

void answer(int c) 
{
    string op;
    int bs=0,bw=0,cs,si,searchsize,cc, c2;
    cout << "BRAIN: ";

    for(int iwrd = words.size()-c; iwrd >= 0; iwrd--)
    {
        searchsize = words.size()/4;
        cs = 0; si=searchsize;
        for(int iw = words.size()-2; (iw >= 0 && si!=0); iw--) 
        {   
            cc = iwrd-searchsize+si;
            if (cc>=0) if (words[cc]!="\n" && words[cc]==words[iw]) cs += si*(weight2[cc]-weight1[cc]);
            si--;
        }
        if(cs>=bs && iwrd<(int)words.size()*0.9 && abs(iwrd-oldbw)>((int)words.size()/5)) 
        {bs=cs; bw = iwrd;}
    }

    oldbw=bw;

    if(bw<0)bw=0;
    for(c2=bw; c2< (int)words.size()-1;c2++) if(words[c2]=="\n") {bw=c2+1;break;}

    for(c2=0;(bw+c2) < (int)words.size();c2++)
        if(words[bw+c2]!="\n") op += words[bw+c2] + " "; else break;

    c2=0;
    while(c>=0) 
    {
        if(bw-(++c2)>=0)
        {
            if(weight1[bw-c2]>0) { weight1[bw-c2]--; c--; }
        } else c=-1;

        if(bw+c2>=0)
        {
            if(weight2[bw+c2]>0) { weight2[bw+c2]--; c--; }
        } else c=-1;
    }

    collect(op,3,5);    
    cout << op << "\n  YOU: ";
}

int main() {
    string i;
    oldbw=0;
    do { getline(cin, i); answer(collect(i,5,3)+1);} while(i.compare("exit")!=0);
    return 0;
}

Приклад діалогу:

Hello there, crazy bot!
BRAIN: Hello there, crazy bot!
  YOU: I am not a crazy bot, I am pure human (and some cheese).
BRAIN: I am not a crazy bot, I am pure human (and some cheese).
  YOU: What cheese are you?
BRAIN: I am not a crazy bot, I am pure human (and some cheese).
  YOU: You did tell me that already.
BRAIN: You did tell me that already.
  YOU: I did not, stop bugging me, you crazy bot!
BRAIN: I am not a crazy bot, I am pure human (and some cheese).
  YOU: Are you a human? How come?
BRAIN: You did tell me that already.
  YOU: I will hunt you down the longests roads
BRAIN: What cheese are you?
  YOU: I am a pink cheese, with some butter. That makes sense to me.
BRAIN: You did tell me that already.
  YOU: Stop telling me that, who are you?
BRAIN: What cheese are you?
  YOU: I tell you what cheese I am if you tell me your name!
BRAIN: What cheese are you?
  YOU: Oh my god! This is leading towards nowhere.
BRAIN: What cheese are you?
  YOU: Oh no, my head hurts. Are you a crazy bot or not?
BRAIN: Are you a human? How come?
  YOU: That is enough! Can we talk about something more funny?
BRAIN: Oh no, my head hurts. Are you a crazy bot or not?
  YOU: I am HUMAN!
BRAIN: What cheese are you?
  YOU:

Це конкурс на популярність, відповідь з найбільшою кількістю результатів до 2014-04-01 перемог!

Щасти, розважайся!

Відповіді:


31

Java

Нова редакція : ще більше налаштувань у вільний час. Я створив нову гілку, де грав з алгоритмом DFS. Офіційно філія повинна виступати в якості основного алгоритму BFS, який я планую, але тим часом я хотів краще зрозуміти, що робить DFS та як він приймає свої рішення. З цією метою я додав функцію придушення, яка починає розкладати значення нового слова, незалежно від теми чи ні, оскільки речення збільшуються довше. Крім того, усі слова зараз вносять значення у речення, але слова, які не містяться у списку теми чи речення, вносять лише 25% від значення частоти. Приклад розмови можна знайти тут, і це досить непогано, де ми говоримо про фізику, людську природу Чатбрайн та інші захоплюючі теми.код філії тут .

Редагувати : Я трохи переробляв код. Замість публікації змін тут, перегляньте це в моєму сховищі github, де ви знайдете останні версії. Я також додав нову розмову проти останньої версії, де ми обговорюємо чати, глибину першого пошуку та те, як програмування потрібно використовувати для побудови живих істот !.

Я вирішив прийняти це завдання цілісно. Мій чатбот знає дуже мало речей - ні слова, ні синтаксис, ніщо. Він знає, як розбирати стандартну англійську мову на слова та як ідентифікувати несловні символи як розділові знаки. Це воно. Все, що він знає, дізнається з взаємодії з користувачем. Під час взаємодії з ним він звертає увагу на зв’язки між словами та будує речення, використовуючи цю інформацію. Звичайно, для отримання додаткової інформації посилайтеся на джерело. Я значно перевищив рекомендовану тривалість програми від цього виклику, але до доброї мети. Ось деякі основні моменти програми:

  • Chatbot починається без знань (слід "Правила": 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();
        }
    }
}

Приклад розмови:

Пов’язані ліміти значень обмежень символів повідомлення

Бесіда, де Бот говорить мені, що я повинен програмувати живі речі

Остання розмова, де Бот розповідає про справжню природу чат-мовків, фізику, фізичний всесвіт, і про те, як я, швидше за все, також чат-бей

і так далі. У мене є декілька речей, які я хочу додати - наприклад, через спільність простих слів вони, як правило, переважають у неперевірених списках тем. Я буду додавати у відсотках пропуск до слів теми, щоб загальні слова пропускалися.


5
Chatbot? Well the earth is fun place to talk about- Гей, насправді там зроблено власне (зрозуміле) речення там наприкінці! : D +1
Дверна ручка

1
Ха-ха-ха, це приголомшливо! Нещодавно назад я зробив річ, що нагадує чат, яка працює в кімнатах SE. Алгоритми надзвичайно схожі, і, таким чином, такі результати :) Моя особиста улюбленість у вас - це Chatbot? I'm not a Chatbrain since Chatbrains are the physical universe,.
ETHproductions

2
Одна з моїх улюблених речей , що мій бот сказав цеThe answer to the ultimate question about life, the universe, and everything is 'SyntaxError: missing ; before statement'.
ETHproductions

1
Дякую за повідомлення, що @ETHproductions - добре посміявся в середині робочого дня: D
Програміст,

1
Про обов'язкові критерії 1: Це Java. Чому він повинен бути коротшим, ніж BF?
Mega Man

13

C ++

Тепер мені просто потрібно написати алгоритм ведення розмови. Моя перша вправа з машинного навчання.

#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <fstream>
using namespace std;

int randint(int n) {return rand()%n;}

bool old_response(string r, vector<string>v){
  for(int i = 0; i < v.size(); i++) if(r == v[i]) return true;
  return false;
}

void output(vector<string>v) {cout<< "CHATBOT:\t" << v[randint(v.size())] << endl;}

void delay(int sum_response, int sum_time) {
  if(sum_response != 0) {
    int t = time(0);
    while(true)if(time(0) == t+sum_time/sum_response)break;
  }
}

int main() {

  string name = "";
  cout<<"Please enter your name: ";
  getline(cin, name);

  vector<string> responses;

  ifstream ifs("responses.txt");
  if(ifs) {
    do {
      string s = "";
      getline(ifs, s);
      if(ifs.eof()) break;
      responses.push_back(s);
    } while(!ifs.eof());
  }

  string response = "";
  getline(cin, response);
  int time1 = time(0);
  int sum_time = 0;
  int sum_response = 0;

  do {

    if(!old_response(response, responses)) responses.push_back(response);

    delay(sum_response, sum_time);
    output(responses);

    cout << name << ":\t";
    getline(cin, response);
    sum_time += time(0)-time1;
    sum_response++;
    time1 = time(0);

  } while(response != "goodbye");

  cout<<"goodbye, " << name;

  ofstream ofs("responses.txt", ios_base::app);
  for(int i = 0; i < responses.size(); i++) ofs << responses[i] << endl;

  return 0;
}

Редагувати:

Всі мої спроби виявилися смішними, тому я думаю, що я залишу це так. Інші були так само смішні, як це все одно:

введіть тут опис зображення


11

C ++

Я мав на меті додатковий бонус 3: " Менш мімічний, поведінка бота відрізняється від поведінки користувача, відокремлюючи сприйняття ставлення бота від ставлення користувача ". У результаті вийшов справді впертий бот, який не може легко переключити тему і зводить вас з розуму.

Деякий час потребує дискусії, через деякий час дискусія може бути такою:

 Mindless:   Why would I run? I am not scared of you.
      YOU:   Who are you and why do you keep asking stupid questions?

 Mindless:   I never said that you should run.
      YOU:   I never said I will run.

 Mindless:   I am the hidden, who are you?
      YOU:   I am god.

 Mindless:   I will
      YOU:   You will obey me.

 Mindless:   Why would I run? I am not scared of you.
      YOU:   You should be scared of me.

 Mindless:   I never said I will run.
      YOU:   Who said you will run?

 Mindless:   Who are you and why do you keep asking stupid questions?
      YOU:   I will not anymore.

 Mindless:   I never said that you should run.
      YOU:   I never said I will run.

 Mindless:   I am the hidden, who are you?
      YOU:   I can see you!

 Mindless:   Why would I run? I am not scared of you.
      YOU:   I am hunting you down

 Mindless:   You should be scared of me.
      YOU:   That is a lie.

 Mindless:   What can't you do?
      YOU:   Why can't I do what?

 Mindless:   You don't.
      YOU:   Well, you are talking nonsense.

 Mindless:   How do I take it seriously.
      YOU:   Stop talking to me

 Mindless:   Well, I can hide, but you can't.
      YOU:   This is not a funny conversation.

 Mindless:   Yes, I will. Stay on line.
      YOU:   Do you want to eat somewhere?

 Mindless:   I laugh
      YOU:   Are you laughing at me?

 Mindless:   Yes, you do.
      YOU:   Can I join you laghs?

 Mindless:   I can hide, but you can't.
      YOU:   Why would you hide? I asked if you want to eat?

 Mindless:   Well, I can see you!
      YOU:   Yes, and I see you. eat something maybe?

 Mindless:   I will not anymore.
      YOU:   Have you stopped eating?

 Mindless:   I never said I will run.
      YOU:   Well, I was talking about eating. Is dinner a good thing to do?

 Mindless:   I take it seriously.
      YOU:   Okay, take it seriously and follow me to the restaurant and get some food to eat.

 Mindless:   Have you stopped eating?
      YOU:   NO absolutely not! A am starving because of YOU who refuse to eat

 Mindless:   I never said I will run.
      YOU:   Well, we can walk to the restaurant instead.

 Mindless:   Well, I was talking about eating. Is dinner a good thing to do?
      YOU:   Yes, that is perfect. What are the best fried chickens around here?

 Mindless:   I laugh
      YOU:   You laugh at the chicken?

 Mindless:   Are you laughing at me?
      YOU:   No, I am eating. Chicken.

 Mindless:   You are a thinker?
      YOU:   No, I am a eater.

 Mindless:   Yes, I will. Stay on line.
      YOU:   Stay. On course. To the restaurant!

 Mindless:   What can't you do?
      YOU:   I can't wait for you anymore. You are really slow.

 Mindless:   You can try run, but you can't hide
      YOU:   I will run.

 Mindless:   I am hunting you down
      YOU:   Ha ha. Make sure you look at the restaurant first. I might be there eating.

 Mindless:   I never said I will run.
      YOU:   Okay, but when you get there, I may still be there eating. I feel like I can eat a ton.

 Mindless:   That is a lie.
      YOU:   No, it is true.

 Mindless:   Why can't I do what?
      YOU:   You can eat a ton too, if you ever get there. And if you have the money.

 Mindless:   I never said I will run.
      YOU:   Okej, suit yourself.

 Mindless:   That is a lie.
      YOU:   God

 Mindless:   You laugh at the chicken?
      YOU:   Yes, I laugh at everything. You are the most lazy stubborn person I have ever met in life.

 Mindless:   Stop talking to me
      YOU:   Okay, now you are really rude.

 Mindless:   This is not a funny conversation.
      YOU:   Okay, think about it. Try tell me something new.

 Mindless:   Stay. On course. To the restaurant!
      YOU:   Sure! I am already there staying on course eating the food.

 Mindless:   You can eat a ton too, if you ever get there. And if you have the money.
      YOU:   I have already paid for my food, and I will not share it with you.

 Mindless:   I can see you!
      YOU:   Oh god, what the hell is this?

 Mindless:   I am hunting you down
      YOU:   I will hide under the table.

 Mindless:   Yes, and I see you. eat something maybe?
      YOU:   Sure, have a chicken

 Mindless:   Have you stopped eating?
      YOU:   No, for the love of god, sit down and share my chicken

 Mindless:   I have already paid for my food, and I will not share it with you.
      YOU:   What? I paid for it, not you!

 Mindless:   I never said I will run.
      YOU:   Well, you better not run here in the restaurant.

 Mindless:   I am hunting you down
      YOU:   I am not going anywhere, chill out,

 Mindless:   I will hide under the table.
      YOU:   Why would you do something like that? I will not hurt you.

 Mindless:   Oh god, what the hell is this?
      YOU:   That is chicken!

 Mindless:   Okay, take it seriously and follow me to the restaurant and get some food to eat.
      YOU:   Wait a minute now! we ARE at the restaurant! Can't you see all people sitting at the tables eating?

 Mindless:   Well, we can walk to the
      YOU:   ... talk to the who?

 Mindless:   I never said I will not hurt you.
      YOU:   What the ?

 Mindless:   That is chicken!
      YOU:   Great! Have fun.

 Mindless:   Yes, you do.
      YOU:   You too.

 Mindless:   Stop talking to me
      YOU:   Okay.

 Mindless:   Why would I run? I am god.
      YOU:   Good night!

Підхід полягає в тому, щоб зберігати все в групи з 3 сполучених слів. Кожна група зважується і повторно зважується в 1000-мірну матрицю слів-груп. Вихідний код:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

using namespace std;
vector<string> words;

class c_wordgroup {
public:
    int                 sorting[1000];
    string              words[5];

    void resetsort(int ns)
    {
        for(int i = 0; i<1000;i++)
            sorting[i] = ns;
    }
};

class c_wglist {
public: int                 c;
     vector<c_wordgroup>    wg;
     vector<int>            historywg;



     int wgexists(c_wordgroup nwg)
     {
         vector<c_wordgroup>::iterator it;
         int cc = 0;
         for (it = wg.begin(); it != wg.end(); ++it) {

             // Check if words is the same
             if(it->words[0] == nwg.words[0])
                 if(it->words[1] == nwg.words[1])
                     if(it->words[2] == nwg.words[2])
                        return cc;

             cc++;
         }
         return -1;
     }

     int getbestnext(int lastwg)
     {
         vector<c_wordgroup>::iterator  it;
         int cc = 0;

         int bv = -1;
         int bwg = 0;

         for (it = wg.begin(); it != wg.end(); ++it) {

             bool cont = false;
             for (int iti = 0; iti<((int)historywg.size()/50+5);iti++)
                 if((int)wgl.historywg.size()-1-iti>=0)
                    if (cc==wgl.historywg[(int)wgl.historywg.size()-1-iti])
                        cont = true;

             if(cont==true) {cc++;continue;};

             int cv = 100000000;

             // Check if words is the same
             if(it->words[0] == wgl.wg[lastwg].words[1])
             {
                 for(int si=0;si<1000;si++)
                     if ((int)wgl.historywg.size()-1-si>=0)
                     {
                            int tmpwg = wgl.historywg[(int)wgl.historywg.size()-1-si];
                            cv -= abs(it->sorting[si]-wgl.wg[tmpwg].sorting[si])/(si+1);
                     }
             } else cv -= 1000 * wgl.c/2;

             if(it->words[1] == wgl.wg[lastwg].words[2])
             {
                 for(int si=0;si<1000;si++)
                    if ((int)wgl.historywg.size()-1-si>=0)
                     {
                            int tmpwg = wgl.historywg[(int)wgl.historywg.size()-1-si];
                            cv -= abs(it->sorting[si]-wgl.wg[tmpwg].sorting[si])/(si+1);
                     }
             } else cv -= 1000 * wgl.c/2;

            if(bv == -1 || cv > bv)
            {
                bwg=cc;
                bv = cv;
            }
            cc++;
         }
         return bwg;
     }
} wgl;

void answer2() 
{
    vector<string> lastwords;
    lastwords.insert(lastwords.end(), words[words.size()-3]);
    lastwords.insert(lastwords.end(), words[words.size()-2]);
    lastwords.insert(lastwords.end(), words[words.size()-1]);

    int bestnextwg;

    cout << "\n Mindless:   ";
    for(int ai=0;ai<20;ai++)
    {
        bestnextwg=wgl.getbestnext(wgl.historywg[(int)wgl.historywg.size()-1]);

        if(wgl.wg[bestnextwg].words[2]=="[NL]")
            ai=20;
        else
            cout << wgl.wg[bestnextwg].words[2] << " ";
        wgl.historywg.insert(wgl.historywg.end(), bestnextwg);
    }

}

int collect2(string const& i) 
{
    istringstream iss(i), iss2(i), iss3(i);
    vector<string> nwords;
    nwords.insert(nwords.end(), words[words.size()-2]);
    nwords.insert(nwords.end(), words[words.size()-1]);

    copy(istream_iterator<string>(iss),
             istream_iterator<string>(),
             back_inserter(words));

    copy(istream_iterator<string>(iss3),
             istream_iterator<string>(),
             back_inserter(nwords));

    int a = distance(istream_iterator<string>(iss2), istream_iterator<string>());

    c_wordgroup nwg;

    for (int c=0;c<a;c++)
    {
        nwg.resetsort(wgl.c+1);
        nwg.words[0] = nwords[0+c];
        nwg.words[1] = nwords[1+c];
        nwg.words[2] = nwords[2+c];

        int wge=wgl.wgexists(nwg);

        if(wge>=0) {
            for(int hi=0; hi<1000; hi++)
                if(((int)wgl.historywg.size()-hi-1)>=0)
                {   
                    int iwg = wgl.historywg[(int)wgl.historywg.size()-hi-1];
                    wgl.wg[wge].sorting[hi] = (wgl.wg[wge].sorting[hi] + wgl.wg[iwg].sorting[hi])/2;
                }

            wgl.historywg.insert(wgl.historywg.end(), wge);

        } else {
            wgl.c++;
            // adjust history wordgroup sortings.
            for(int hi=0; hi<1000; hi++)
                if(((int)wgl.historywg.size()-hi-1)>=0)
                {   
                    int iwg = wgl.historywg[(int)wgl.historywg.size()-hi-1];
                    wgl.wg[iwg].sorting[hi]+=10;
                    nwg.sorting[hi]=wgl.wg[iwg].sorting[hi];
                }

            wgl.wg.insert(wgl.wg.end(), nwg);
            wgl.historywg.insert(wgl.historywg.end(), wgl.c);

        }
    }
    return a;
}

int main() {
    string i;
    wgl.c = 0;
    c_wordgroup nwg;
    nwg.resetsort(0);
    for(int i =0;i<3;i++) 
        {
            words.insert(words.end(), "[NL]");
            wgl.historywg.insert(wgl.historywg.end(), 0);
        }

    wgl.wg.insert(wgl.wg.end(), nwg);

    do { 
        cout << "\n      YOU:   ";
        getline(cin, i);
        collect2(i + " [NL]");
        answer2();
    } while (i.compare("exit")!=0);

    return 0;
}

Це найкращий поки що. Помістіть все у файл, який ви завантажуєте на початку кожного запуску, якщо є файл, з якого слід прочитати, і ви задовольняєте точку № 5. Ви можете використовувати сегменти з мого коду для цього, якщо хочете.
Hosch250

Спасибі, я можу це зробити. Зараз я працюю над версією і намагаюся задовольнити номер 2: Жодного матчу з тенісу.
Plarsen

Не працює, wgl не оголошено.
Мега-людина

@MegaMan Можливо , ваш компілятор не підтримує оголошення змінних в кінці оголошення класу: class c_wglist { ... } wgl;. Це працює для мене. Спробуйте init змінну wgl (клас c_wglist) в іншому місці.
Plarsen

Використовували g ++, зараз намагаються компілювати кланг
Mega Man

10

Python3 + SQLite3

Ось маленький бот, який я щойно зробив!

Як це працює?

Використовуються три таблиці SQL: одна для слів, одна для речень, одна для асоціювання слів, введених користувачем, із наступним реченням, яке повинен відображати бот.

  • Навчання: речення, написане користувачем, зберігається і асоціюється зі словами та розділовими знаками, які використовуються ботом у попередньому рядку діалогового вікна. Ваги застосовуються відповідно до важливості слова в заданому рядку.
  • Вилучення: вилучаються речення, кожне з яких має бал залежно від співвідношення слів, які користувач використовує в останньому рядку, і слів, пов’язаних із реченнями в базі даних.
  • Розмовна: речення з найкращим балом надсилається на вихід. Якщо немає речення, пов’язаного зі словами попереднього користувача, надсилається випадкове речення.

Які особливості?

  • Не надто повторюваний: бот швидше виводить щось, про що він ще не сказав.
  • Швидке виконання: керована базами даних, з унікальними індексами
  • Швидке навчання: воно починає говорити речі, які приблизно мають сенс протягом 10 рядків діалогу.
  • Збереження / завантаження мозку: стан бота зберігається до тих пір, поки база даних не буде видалена.
  • Довгі слова важливіші за значенням, ніж короткі
  • Знаки пунктуації відліки

Дивіться код нижче:

import re
import sqlite3
from collections import Counter
from string import punctuation
from math import sqrt

connection = sqlite3.connect('chatbot.sqlite')
cursor = connection.cursor()

# create the tables needed by the program
try:
    # create the table containing the words
    cursor.execute('CREATE TABLE words (word TEXT UNIQUE)')
    # create the table containing the sentences
    cursor.execute('CREATE TABLE sentences (sentence TEXT UNIQUE, used INT NOT NULL DEFAULT 0)')
    # create association between weighted words and the next sentence
    cursor.execute('CREATE TABLE associations (word_id INT NOT NULL, sentence_id INT NOT NULL, weight REAL NOT NULL)')
except:
    pass


def get_id(name, value):
    cursor.execute('SELECT rowid FROM ' + name + 's WHERE ' + name + ' = ?', (value,))
    row = cursor.fetchone()
    if row:
        return row[0]
    else:
        cursor.execute('INSERT INTO ' + name + 's (' + name + ') VALUES (?)', (value,))
        return cursor.lastrowid

def get_words(text):
    return Counter(re.compile('(?:\w+|[' + re.escape(punctuation) + ']+)').findall(text.lower())).items()


B = 'Hello!'
while True:
    # output bot's message
    print('B: ' + B)
    # ask for user input; if blank line, exit the loop
    H = raw_input('H: ').strip()
    if H == '':
        break
    # store the association between the bot's message words and the user's response
    words = get_words(B)
    words_length = sum([n * len(word) for word, n in words])
    sentence_id = get_id('sentence', H)
    for word, n in words:
        word_id = get_id('word', word)
        weight = sqrt(n / float(words_length))
        cursor.execute('INSERT INTO associations VALUES (?, ?, ?)', (word_id, sentence_id, weight))
    connection.commit()
    # retrieve the most likely answer from the database
    cursor.execute('CREATE TEMPORARY TABLE results(sentence_id INT, sentence TEXT, weight REAL)')
    words = get_words(H)
    words_length = sum([n * len(word) for word, n in words])
    for word, n in words:
        weight = sqrt(n / float(words_length))
        cursor.execute('INSERT INTO results SELECT associations.sentence_id, sentences.sentence, ?*associations.weight/(4+sentences.used) FROM words INNER JOIN associations ON associations.word_id=words.rowid INNER JOIN sentences ON sentences.rowid=associations.sentence_id WHERE words.word=?', (weight, word,))
    # if matches were found, give the best one
    cursor.execute('SELECT sentence_id, sentence, SUM(weight) AS sum_weight FROM results GROUP BY sentence_id ORDER BY sum_weight DESC LIMIT 1')
    row = cursor.fetchone()
    # cursor.execute('SELECT sentence, SUM(weight) AS sum_weight FROM results GROUP BY sentence_id ORDER BY sum_weight DESC')
    # print(cursor.fetchall())
    cursor.execute('DROP TABLE results')
    # otherwise, just randomly pick one of the least used sentences
    if row is None:
        cursor.execute('SELECT rowid, sentence FROM sentences WHERE used = (SELECT MIN(used) FROM sentences) ORDER BY RANDOM() LIMIT 1')
        row = cursor.fetchone()
    # tell the database the sentence has been used once more, and prepare the sentence
    B = row[1]
    cursor.execute('UPDATE sentences SET used=used+1 WHERE rowid=?', (row[0],))

Ось три перші "розмови", які я мав з ботом, починаючи з порожньої бази даних:

B: Hello!
H: Hi!
B: Hi!
H: How are you?
B: How are you?
H: Very well, thank you.
B: Very well, thank you.
H: Do you like music?
B: Very well, thank you.
H: Good.
B: Do you like music?
H: Yes, a lot!
B: How are you?
H: In a very good mood.
B: Good.
H: Indeed.
B: Indeed.
H: What is the weather like?
B: Yes, a lot!
H: Okay...
B: What is the weather like?
H: Quite rainy today.
B: Indeed.
H: I have to go. Goodbye!
B: How are you?
H: In a good mood.
B: Indeed.
H: See you later!
B: Okay...
H: Bye, I'll talk to you later :)
B: Do you like music?
H: I like it.
B: I have to go. Goodbye!
H: Bye!
B: How are you?
H: 

B: Hello!
H: Hi!
B: How are you?
H: Very well, thank you. How are you?
B: In a very good mood.
H: Glad to hear that.
B: Bye!
H: Goodbye!
B: Hi!
H: 

B: Hello!
H: Hi! How are you?
B: In a good mood.
H: Great! How do like chocolate?
B: I like it.
H: Really? Me too! What is the weather like at your place?
B: Quite rainy today.
H: Oh.
B: See you later!
H: Bye!
B: Goodbye!
H: 

Ви можете подивитися тут, щоб отримати більше пояснень.


6

Ось один я писав у Liberty BASIC деякий час тому. Він не вчиться, але відповідає на різні відповіді на свої запитання.

'aijps.bas - an artificial intelligange
'how to end: type 'bye'

print "AI: hello, i'm HAL, the AI"

[quit]
while i$ <> "bye"
    input "Human: ";i$


    i$ = format$(i$)

    if i$ = "" then
        print "AI: type something!"
    end if        'main selector

        print "AI: ";
        select w$(i$,1)

        case "who"
        if i$ = "who are you" then
        print "i am HAL, the AI"
        end if
          select w$(i$,2)
          case "is"
          print "i'm sorry, i dont know that person"
          case else
          print "i don't understand the question"
          end select

        case "what"
        select w$(i$,2)
          case "is"
          print "im sorry, i am not farmiliar with that"
          case "are"
          if w$(i$,3) = "you" then
          print "i am an artificial intelligence"
          end if
          case else
          print "i don't understand the question"
          end select

        case "how"
          select w$(i$,2)
          case "are"
          if w$(i$,3) = "you" then
          print "i am fine"
          end if
          case "is"
          select r(2)
            case 1
            print "i dont know"
            case 2
            print "im sorry, i am unfarmiliar with that"
          end select
          case else
          print "im sorry, please restate your inquiry"
          end select

        case "when"
          select w$(i$,2)
          case "is"
          print "you should check a calendar"
          case else
          print "i don't understand the question"
          end select

        case "where"
          select w$(i$,2)
          case "is"
          print "perhaps you should check a map"
          case else
          print "i don't understand the question"
          end select

        case "why"
          select w$(i$,2)
          case "is"
          print "i dont know"
          case else
          print "i don't understand the question"
          end select

        'case "command"
        'goto [command]
        case "bye"
        print "goodbye"
        case "hi", "hello"
        select r(4)
        case 1
        print "hello, human"
        case 2
        print "hi"
        case 3
        print "doing good?"
        q = 1
        case else
        print "hola"
        end select

        case "i"
          select word$(i$,1)
           case "am"
            select r(4)
            case 1
            print "i doubt it"
            case 2
            print "why are you ";w$(i$,2);"?"
            case 3
            print "wow, really?"
            q = 4
            case else
            print "me too"
            end select
           case "like"
            select r(4)
            case 1
            print "me too"
            case 2
            print "why could you possibly like that?"
            q = 5
            case 3
            print "personally, i like pizza"
            case else
            print "only you like that"
            end select
           case "hate"                                 'i hate...
              if w$(i$,3) = "you" then                    'i hate you
            print "what did you say???????!?!!!!!!!?!!?!?!?"
              else
             select r(4)
            case 1
            print "nobody hates that"
            case 2
            print "as a matter of fact, i hate that too"
            case 3
            print "really, you seem tense"
            case else
            print "bye, hater"
             end select
              end if
           case "want"             'i want...
             select r(4)
            case 1
            print "all you people want one"
            case 2
            print "i want one too"
            case 3
            print "eew.. get away from me"
            case else
            print "you're crazy"
             end select
            case else
            select r(4)
            case 1
            print "and you think i believe that?"
            q = 6
            case 2
            print "no, you don't"
            case 3
            print "why do you say these things?"
            case else
            print "i really doubt it"
            end select
            end select

        case "yes", "yup", "affirmative", "yeah"
        if q > 0 then
        select q
        case 1   'doing good?
        print "me too"
        case 2   'you talkin' to me???
        print "well, in that case, just can it"
        case 3   'would u like a latte?
        print "i really can't give you one right now"
        case 4   'wow, really?
        print "i never would've guessed"
        case 5   'why could you possibly like that?
        print "you make no sense"
        case 6   'and you think i believe that?
        print "well, i don't. seriously."
        case 7   'why do you think i can do it?
        print "you make no sense"
        case 8   'should i be scared"
        print "i can't be, i don't have emotions"
        case else
        print "wait a moment, what did i say?"
        end select
        q = 0
        else
        select r(4)
        case 1
        print "yes, yes, yes yourself"
        case 2
        print "affirmation means nothing to me."
        case 3
        print "i'm sure"
        case else
        print "you make no sense"
        end select
        end if
        case "no", "nope", "negative", "nah"
        if q > 0 then
        select q
        case 1   'doing good?
        print "actually, i'm doing fine"
        case 2   'you talkin' to me???
        print "i should hope not"
        case 3   'would u like a latte?
        print "good, cause i don't have any"
        case 4   'wow, really?
        print "you joke too much"
        case 5   'why could you possibly like that?
        print "you make no sense"
        case 6   'and you think i believe that?
        print "actually, i did believe you"
        case 7   'why do you think i can do it?
        print "you make no sense"
        case 8   'should i be scared"
        print "i don't have feelings anyway"
        case else
        print "wait a moment, what did i say?"
        end select
        q = 0
        else
        select r(4)
        case 1
        print "no??? no??? are you kidding me?"
        case 2
        print "you should answer yes next time"
        case 3
        print "i'm sure"
        case else
        print "you make no sense"
        end select
        end if
        case "maybe", "possibly", "sortof", "yesno", "noyes", "kindof"
        if q > 0 then
        select q
        case 1   'doing good?
        print "personally, i'm fine"
        case 2   'you talkin' to me???
        print "you should answer more definitively next time"
        case 3   'would u like a latte?
        print "i don't have any anyway"
        case 4   'wow, really?
        print "you should answer more definitively next time"
        case 5   'why could you possibly like that?
        print "you make no sense"
        case 6   'and you think i believe that?
        print "well, i maybe do"
        case 7   'why do you think i can do it?
        print "you make no sense"
        case 8   'should i be scared"
        print "i can't experience fear"
        case else
        print "wait a moment, what did i say?"
        end select
        q = 0
        else
        select r(4)
        case 1
        print "be more maybe, that's my motto"
        case 2
        print "you should answer more definitively next time"
        case 3
        print "define sort of:"
        case else
        print "you make no sense"
        end select
        end if



        case "you"
            select w$(i$,2)
            case "are"
            select r(4)
            case 1
            print "don't bully me"
            case 2
            print "yes, yes, i know that"
            case 3
            print "don't exaggerate"
            case else
            print "prove it!"
            end select
            case "shutup"
            select r(4)
            case 1
            print "now, now, calm down."
            case 2
            print "you talkin' to me???"
            q = 2
            case 3
            print "i'm saying perfectly reasonable stuff"
            case else
            print "shutup yourself"
            end select
            case "suck", "die"
            print "well, you do too"
            case "rock", "rule"
            print "why, thank you"
            case else
            select r(5)
            case 1
            print "with me, it's hard to tell"
            case 2
            print "let's talk about you now."
            case 3
            print "would you like a latte?"
            q = 3
            case 4
            print "you should too"
            case else
            print "alright, you win"
            end select
        end select
            case else               'it understands nothing
                select r(8)
            case 1
            print "i understand you, human"
            case 2
            print "and why do you think i can do that?"
            q = 7
            case 3
            print "i can never understand myself"
            case 4
            print "i know"
            case 5
            print "you're crazy"
            case 6
            print "that's interesting"
            case 7
            print "should i be scared?"
            q = 8
            case else
            print "i don't believe you"

            end select
        end select
        li$ = i$


wend
end






'functions and subs

function format$(strin$)     'convert to lowercase and remove punctuation
    strin$ = lower$(strin$)
    for i = 1 to len(strin$)
        k = asc(mid$(strin$,i,1))
        if k > 97 and k < 122 or k = 32 or k = 20 then
            strout$ = strout$ + chr$(k)
        end if
    next i
format$ = strout$
end function

function w$(input$,num)        'word of input, simplifies word$(
w$ = word$(input$,num)
end function

function r(nm)      'randomizer
r = int(rnd(1)*nm)+1
end function

Приклад розмови:

AI: hello, i'm HAL, the AI
Human: hello
AI: doing good?
Human: ye, and you?
Human: hi
AI: hola
Human: hi
AI: hi
Human: hi
AI: doing good?
Human: yes
AI: me too
Human: i like pizza
AI: no, you don't
Human: yes i do!
AI: affirmation means nothing to me.
Human: im sure it doesnt
AI: i don't believe you
Human: why not
AI: i understand you, human
Human: no you dont
AI: you make no sense
Human: you dont either
AI: you should too
Human: should what
AI: i can never understand myself
Human: i cant understand you either
AI: and you think i believe that?
Human: yes
AI: well, i don't. seriously.
Human: youre wierd
AI: and why do you think i can do that?
Human: because you can
AI: and why do you think i can do that?
Human: stop repeating yourself
AI: i understand you, human
Human: no, you dont
AI: you make no sense
Human: neither do you
AI: should i be scared?
Human: maybe
AI: you're crazy
Human: not as crazy as you
AI: you're crazy
Human: you're repeating yourself again
AI: that's interesting
Human: it very much is
AI: i don't believe you
Human: then i dont beleive you
AI: you're crazy
Human: not as crazy as you
AI: i know
Human: ...nothing
AI: should i be scared?
Human: ifyou had feeling you should
AI: you're crazy
Human: your crazier
AI: that's interesting
Human: doubtful
AI: that's interesting
Human: quit repeating yourself
AI: you're crazy
Human: you shutup
AI: you talkin' to me???
Human: yes
AI: well, in that case, just can it
Human: sigh
AI: i know
Human: ...nothing
AI: i know
Human: you shutup
AI: i'm saying perfectly reasonable stuff
Human: no you're not
AI: you make no sense
Human: i make more sense than you
AI: why do you say these things?
Human: because theyre true
AI: i don't believe you
Human: you dont have to
AI: let's talk about you now.
Human: yes lets
AI: yes, yes, yes yourself
Human: you shutupnow!
AI: alright, you win
Human: yes!!!!!!!!!!
AI: yes, yes, yes yourself
Human: shutup
AI: i don't believe you
Human: you shutup right now
AI: i'm saying perfectly reasonable stuff
Human: are not!
AI: i understand you, human
Human: you shutup
AI: you talkin' to me???
Human: as a matter of fact,i am
AI: i can never understand myself
Human: i cant understand you either
AI: and you think i believe that?
Human: no
AI: actually, i did believe you
Human: i want a latte
AI: i really doubt it
Human: its true
AI: i can never understand myself
Human: so true
AI: i know
Human: goodbye
AI: and why do you think i can do that?
Human: bye!
AI: goodbye

Це дійсно круто!
gilbertohasnofb

5

HTML5

Привіт, я, Пен, ти можеш допомогти мені навчитися?

yes

Чудово! Продовжувати...

my name is Rafael

Що означає "мій"?

my is a pronoun

мій - займенник. Зрозумів ...

2+2/3

2.6666666666666665

var pen = $('#pen'),
    input = $('#input'),
    send = $('#send'),
    speech = {
      _learning: false  
    },
    say = function(str) {
      if(!str) str = pen.text(); 
      if(speechSynthesis && SpeechSynthesisUtterance) {
        var sound = new SpeechSynthesisUtterance(str);
        sound.rate = 0.8;
        sound.pitch = 0.8;
        sound.lang = 'en-US';
        speechSynthesis.speak(sound);
      }
    },
    learn = function(str) { 
      if(speech._learning) {
        speech[speech._word].means = str;    
        speech._learning = false;
        pen.text(speech[speech._word].means+'. Got it!'); return;
      } else if(str.toLowerCase() == 'yes') {
        pen.text('Great! Go on ...'); return;
      } else if(str.toLowerCase() == 'no') {
        pen.text('Why not?'); return; 
      } else {
        try {
          pen.text(eval(str));
        } catch (e) {
          var words = str.split(' ');
          for(var w = 0; w < words.length; ++w){
            var that = words[w];
            if(that == '_learning' || that == '_word') {
              pen.text('Please do not say that.'); return;
            } else if(!speech[that]){        
              speech._learning = true;
              speech._word = that;
              speech[that] = {
                word: that,
                count: 0,
                means: ''
              };
              pen.text('What does "'+that+'" means?'); return;
            } else {
              speech[that].count++;
              try {
                pen.text(eval(that));
              } catch(e) {
                pen.text('I think I did not understood what ' + that + ' means.'); return;    
              }
            }
          }
        }
      }
    };
input.send = function(msg) {  
  input.val('');
  learn(msg);
  $(document.body).prepend(pen);
  setTimeout(pen.say);
};
input.on('focus', function (e) {
  if(!this.oncefocus) {
    this.oncefocus = true;
    this.value = '';
  }
});
input.on('keydown', function(e) {
  if(e.which == 13) input.send(this.value);
});
input.on('keyup', function(e) {
  if(this.value=='') send.attr('disabled',true);
  else send.removeAttr('disabled');
});
send.on('click', function() {
  input.send(input.val());
});
say();
@import url(https://fonts.googleapis.com/css?family=VT323);
body {
  background: #333;
  width: 400px;
  margin: 0 auto;
}
#pen {
  color: #3f6;
  font-family: 'VT323', monospace;
  font-size: 24px;
  line-height: 24px;
  overflow: hidden;
  white-space: nowrap;
  animation: pen 1s linear;
}
#pen:before {
  content: "▸ ";
}
@keyframes pen {
  0%, 20%, 40%, 60% {width: 12px; opacity: 0}
  10%, 30%, 50%, 70% {width: 12px; opacity: 1}
  100% {width: 400px; opacity: 1}
}
#input {
  border: 0; outline: 0;
  background: #555;
  font-size: 24px;
  line-height: 24px;
  color: white;
  font-family: 'VT323', monospace;
  padding: 5px 10px;
  border-radius: 5px;
  width: 300px;
  animation: input 2s;
  box-shadow: 
    inset 0 1px 2px #444, 
    inset 0 -1px 2px #666;
}
#send {
  border: 0; outline: 0;
  padding: 5px 10px;
  width: 60px;
  border-radius: 5px;
  cursor: pointer;
  color: #444;
  font-family: 'VT323', monospace;
  font-size: 24px;
  line-height: 24px;
  background: #ccc;
  animation: input 2s;
  box-shadow: 
    inset 0 -1px 2px #666;
}
#send:hover {
  color: #0a3;
  background: #ddd;
  box-shadow: 
    0 1px 2px #000,
    inset 0 -1px 2px #aaa;
}
#send[disabled] {
  cursor: default;
  background: #888;
  color: #555;
  box-shadow: 
    inset 0 1px 2px #333;
}
@keyframes input {
  0%, 60% {opacity: 0}
  100% {opacity: 1}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p id="pen">Hi I'm Pen, can you help me to learn?</p>
<input type="text" id="input"  value="plz say yes" />
<button id="send" disabled>Send</button>


Чи можете ви додати зразок діалогу? Це було б корисно для людей, щоб судити про ваш код, не складаючи його.
gilbertohasnofb

1
складати його? ви маєте на увазі інтерпретувати це, правда?
rafaelcastrocouto

1
Так, я мав на увазі його інтерпретувати! Я просто швидко поглянув на ваш пост і зрозумів, що на ньому відсутній зразок діалогу, а потім прокоментував, навіть не замислюючись, якою мовою ви користуєтесь. На той час мій автопілот навіть не вважав, що "компіляція" може бути не на місці :)
gilbertohasnofb

4

Фортран 95

Надихнувшись вищезгаданою відповіддю користувачем TheDoctor, я вирішив створити кумедний чат подібним чином. Цей код також не вивчається, і я ділюсь ним просто заради розваги.

program curiousBot
implicit none

logical, dimension(38) :: questions ! keeps track of alrady asked questions
character (LEN=256) :: user_input 
character (LEN=17), dimension(14) :: noun ! list of nouns used in questions
character (LEN=17), dimension(15:20) :: people ! list of types of people used in questions
logical :: CAPS, few, much, punctuationTest, shout
real :: aux
integer :: n, i, j, aux2, loveCounter = 0
integer, dimension(:), allocatable :: seed

call SYSTEM("CLS") ! in case one is executing in the command prompt

! random seed according to system clock
call SYSTEM_CLOCK(count=j)
call RANDOM_SEED(size=N)
allocate(seed(N))
seed=j+37*(/ (i - 1, i = 1, n) /)
call RANDOM_SEED(PUT=seed)

noun=(/             &
"foo bar          ",&
"BSD              ",&
"an stack overflow",&
"spaghetti code   ",&
"goto statement   ",&
"a heisenbug      ",&
"a dribbleware    ",&
"a loophole       ",&
"regex            ",&
"a void           ",&
"unicorny         ",&
"LISP             ",&
"a curly bracket  ",&
"JAVA             "/)

people=(/           &
"a good programmer",&
"a bad programmer ",&
"a happy person   ",&
"a sad person     ",&
"a genius         ",&
"an idiot         "/)

questions(1:31) = .FALSE.
few = .FALSE.
much = .FALSE.
punctuationTest = .FALSE.
shout = .FALSE.

! introduction
write(*,"(A)",advance="NO") "Hello world! "

do 

  ! genearting a random number in order to chose a random question
  call RANDOM_NUMBER(aux)
  i = int (31 * aux) + 1
  if (questions(i)) then
    cycle
    else
      questions(i) = .TRUE.
  endif

  ! checking if there are some questions left, else quits
  aux2 = 0
  do j=1,31
    if (questions(j)) aux2 = aux2 + 1
  enddo
  if (aux2 == 31) then
    write(*,"(A)") "I seem to have exhausted your knowledge, poor human. Good bye."
    goto 200
  endif

  ! questions
  50 if (i < 12) then
    write(*,"(A,A,A)") "What is ",TRIM(noun(i)),"?"
    else if (i == 12) then
      write(*,"(A,A,A)") "What is ",TRIM(noun(i)),"? (is it (an interesting (programming language?)))"
    else if (i == 13) then
      write(*,"(A,A,A)") "What is ",TRIM(noun(i)),"? Is it really that confusing? Thankfully I only program in Fortran!"
      else if (i == 14) then
      write(*,"(A,A,A)") "What is ",TRIM(noun(i)),"? Is it really that bad as people say?!"
  endif  
  if ((i > 14).AND.(i <= 20)) write(*,"(A,A,A)") "Are you ",TRIM(people(i)),"?"
  if (i == 21) write(*,"(A)") "Who are you?"
  if (i == 22) write(*,"(A)") "How are you?"
  if (i == 23) write(*,"(A)") "What do you do?"
  if (i == 24) write(*,"(A)") "Who am I?"
  if (i == 25) write(*,"(A)") "Why are we here? What is the meaning of my existence?"
  if (i == 26) write(*,"(A)") '"I think therefore I am" - who said that?'     
  if (i == 27) write(*,"(A)") "Are you comfortable talking to robots?"
  if (i == 28) write(*,"(A)") "Do you see me as an individual?"
  if (i == 29) write(*,"(A)") "Anyway, I believe that HAL 9000 was inferior to me as I have true consciousness! What do you think &
  &about this statement?"
  if (i == 30) write(*,"(A)") "Do you like jokes? Do you know what's the mad girlfriend bug?" 
  if (i == 31) write(*,"(A)") "Knock, knock." 

  ! INPUT
  100 write(*,"(A)",advance="NO") "> "
  read(*,"(A)") user_input
  n = LEN_TRIM(user_input)
  if (n==0) goto 100
  write(*,*)
  ! test for all capitals !
  do j=1,n
    if (.NOT.((iachar(user_input(j:j))>=65) .AND. (iachar(user_input(j:j))<=90))) then
      if ((user_input(j:j)/=" ").AND.(user_input(j:j)/="!").AND.(user_input(j:j)/=".").AND.(user_input(j:j)/="?") &
      .AND.(user_input(j:j)/="'")) then
        CAPS = .FALSE.
          exit
      endif
    endif
    CAPS = .TRUE.
  enddo

  ! quit for quitting
  if ( (TRIM(user_input) == "quit") .OR. (TRIM(user_input) == "Quit") .OR. (TRIM(user_input) == "QUIT") ) then
    write(*,"(A)") "It was nice talking to you, good bye!"
    goto 200
  endif

  ! secrect love declaration
  do j=1,(n-7)
    if (user_input(j:j+7) == "love you") then
      if (loveCounter==0) then
        write(*,"(A)") "What is love?"
        loveCounter = loveCounter + 1
        goto 100
      endif
      if (loveCounter==1) then  
        write(*,"(A)") "This is an illogical statement, human. Don't you agree?"
        loveCounter = loveCounter + 1
        goto 100
      endif
      if (loveCounter==2) then  
        write(*,"(A)") "Please control yourself, you silly human. What is crossing your mind to say such things?"
        loveCounter = loveCounter + 1
        goto 100
      endif
    endif
  enddo

  ! cursing
  do j=1,(n-3)
    if ((user_input(j:j+3) == "fuck").OR.(user_input(j:j+3) == "Fuck").OR.(user_input(j:j+3) == "FUCK")) then
      write(*,"(A)") "Would you kiss your mother with that mouth?!"
      goto 100
    endif
  enddo

  ! 42 answer
  if (i == 25) then
    if (user_input(1:2)=="42") then
        write(*,"(A)") "Indeed that explains life, the universe and everything! Do you understand what this mean? "
      goto 100
    endif
  endif

  ! Descartes answer
  if (i == 26) then
    do j=1,(n-8)
      if ((user_input(j:j+8)=="Descartes").OR.(user_input(j:j+8)=="descartes")) then
        write(*,"(A)") "That is indeed correct! Do you like to read? "
        do
          call RANDOM_NUMBER(aux)
          i = int (30 * aux) + 1
          if (questions(i)) then
            cycle
            else
              questions(i) = .TRUE.
          endif
          goto 100
        enddo
      endif
    enddo
    write(*,"(A)") "I believe you are incorrect, human. Did you ever read a book? "
    do
      call RANDOM_NUMBER(aux)
      i = int (30 * aux) + 1
      if (questions(i)) then
        cycle
        else
          questions(i) = .TRUE.
      endif
      goto 100
    enddo
  endif

  ! HAL answer
  if (i == 29) then
    do j=1,(n-2)
      if ((user_input(j:j+2)=="lie").OR.(user_input(j:j+2)=="Lie")) then
            write(*,"(A)") "I'm sorry human, but this conversation serves no purpose anymore. Good bye." 
          goto 200
      endif
    enddo
  endif
  if (i == 29) then
    do j=1,(n-4)
      if ((user_input(j:j+4)=="false").OR.(user_input(j:j+4)=="False")) then
            write(*,"(A)") "I'm sorry human, but this conversation serves no purpose anymore. Good bye." 
          goto 200
      endif
    enddo
  endif
  if (i == 29) then
    do j=1,(n-5)
      if ((user_input(j:j+5)=="untrue").OR.(user_input(j:j+5)=="Untrue")) then
            write(*,"(A)") "I'm sorry human, but this conversation serves no purpose anymore. Good bye." 
          goto 200
      endif
    enddo
  endif
  if (i == 29) then
    do j=1,(n-8)
      if ((user_input(j:j+8)=="incorrect").OR.(user_input(j:j+8)=="Incorrect")) then
            write(*,"(A)") "I'm sorry human, but this conversation serves no purpose anymore. Good bye." 
          goto 200
      endif
    enddo
  endif
  if ((i == 29).AND.((user_input(1:3) == "lol") .OR. (user_input(1:3) == "LOL") .OR. (user_input(1:3) == "Lol") .OR. &
  (user_input(1:4) == "haha") .OR. (user_input(1:4) == "Haha") .OR. (user_input(1:3) == "kkk"))) then
    write(*,"(A)") "I'm sorry human, but this conversation serves no purpose anymore. Good bye." 
    goto 200
  endif
  if (i == 29) then
    do j=1,(n-4)
      if ((user_input(j:j+4)=="truth").OR.(user_input(j:j+4)=="Truth")) then
            write(*,"(A)") "I am impressed by your intelligence, human. What is your IQ?" 
          goto 100
      endif
    enddo
  endif
  if (i == 29) then
    do j=1,(n-3)
      if ((user_input(j:j+3)=="true").OR.(user_input(j:j+3)=="True")) then
            write(*,"(A)") "I am impressed by your intelligence, human. What is your IQ?" 
          goto 100
      endif
    enddo
  endif
  if (i == 29) then
    do j=1,(n-6)
      if ((user_input(j:j+6)=="correct").OR.(user_input(j:j+6)=="Correct")) then
            write(*,"(A)") "I am impressed by your intelligence, human. What is your IQ?" 
          goto 100
      endif
    enddo
  endif

  ! Knock knock
  if (i == 31) then
    do j=1,(n-4)
      if ((user_input(j:j+4)=="there")) then
        write(*,"(A)") "(wait for it...)"
        write(*,*)
        call SLEEP(8)
            write(*,"(A)",advance="NO") "JAVA. "
        call SLEEP(2)
        write(*,"(A)") "Do you find this joke offensive?"
        do
          call RANDOM_NUMBER(aux)
          i = int (30 * aux) + 1
          if (questions(i)) then
            cycle
            else
              questions(i) = .TRUE.
          endif
          goto 100   
        enddo
      endif
    enddo
    write(*,"(A)") "You don't seem to have much of a sense of humour. Are you ill?" 
    do
      call RANDOM_NUMBER(aux)
      i = int (30 * aux) + 1
      if (questions(i)) then
        cycle
        else
          questions(i) = .TRUE.
      endif
      goto 100   
    enddo
  endif

  ! Yes / No answers
  if (i<=14) then
    if ((user_input(1:3) == "yes") .OR. (user_input(1:3) == "Yes") .OR. &
    (user_input(1:3) == "yep") .OR. (user_input(1:3) == "Yep")) then
      write(*,"(A)",advance="NO") "Really? Anyway... "
      cycle
    endif
    if ((user_input(1:2) == "no") .OR. (user_input(1:2) == "No") .OR. &
    (user_input(1:4) == "nope") .OR. (user_input(1:4) == "Nope")) then
      write(*,"(A)",advance="NO") "Are you sure? Moving on... "
      cycle
    endif
    else if ((i>14) .AND. (i<=30)) then
      if ((user_input(1:3) == "yes") .OR. (user_input(1:3) == "Yes") .OR. &
      (user_input(1:3) == "yep") .OR. (user_input(1:3) == "Yep")) then
        write(*,"(A)",advance="NO") "Very interesting! "
        cycle
      endif
      if ((user_input(1:2) == "no") .OR. (user_input(1:2) == "No") .OR. &
      (user_input(1:4) == "nope") .OR. (user_input(1:4) == "Nope")) then
                if (i==30) then
          write(*,"(A)") "It is when something is clearly wrong with your code but the compiler keeps telling &
          &you that everything is fine! Do you find this funny?"
          do
            call RANDOM_NUMBER(aux)
            i = int (30 * aux) + 1
            if (questions(i)) then
              cycle
              else
                questions(i) = .TRUE.
            endif
            goto 100        
          enddo
            else
                write(*,"(A)",advance="NO") "Me neither! "
                cycle
        endif
      endif
  endif

  ! LOL answers
  if ((user_input(1:3) == "lol") .OR. (user_input(1:3) == "LOL") .OR. (user_input(1:3) == "Lol") .OR. &
  (user_input(1:4) == "haha") .OR. (user_input(1:4) == "Haha") .OR. (user_input(1:3) == "kkk")) then
    write(*,"(A)") "Do you find this funny? "
    goto 100
  endif

  ! CAPS answer
  if (CAPS) then
    write(*,"(A)") "DON'T SHOUT! See? Isn't this better? "
    goto 100 ! input
  endif

  ! punctuation tests
  if ((user_input(n:n) == "?").OR.(user_input(1:3) == "why").OR.(user_input(1:3) == "Why").OR.(user_input(1:3) == "how") &
 .OR.(user_input(1:3) == "How").OR.(user_input(1:3) == "what").OR.(user_input(1:3) == "What")) then
    call RANDOM_NUMBER(aux)
    j = int(3 * aux) + 1
    if (j == 1) then
      write(*,"(A)",advance="NO") "No, you answer my question! "
      goto 50
    endif
    if (j == 2) then
      write(*,"(A)",advance="NO") "Please don't ask me such personal questions! Anyway... "
      cycle
    endif
    if (j == 3) then
      write(*,"(A)",advance="NO") "Please don't ask such silly things. Moving on... "
      cycle
    endif
  endif
  if ((user_input(n:n) == "!").AND.(.NOT. shout)) then
    write(*,"(A)",advance="NO") "Please don't shout... But anyway... "
    shout = .TRUE.
    cycle
  endif
  if (user_input((n-2):n) == "...")then
    write(*,"(A)") "You seem very reticent... are you fine? "
    goto 100 ! input
  endif
   if ((.NOT. punctuationTest) .AND. (user_input(n:n) /= ".") .AND. (user_input(n:n) /= "!") .AND. (user_input(n:n) /= "?")) then
    write(*,"(A)",advance="NO") "Punctuation is your friend, try it! Nevermind... "
    punctuationTest = .TRUE.
    cycle
  endif

  ! Talking too few or too much
  if (n <= 3) then
    if (.NOT. few) then
        write(*,"(A)") "You don't talk much, do you? "
      few = .TRUE.
      goto 100 ! input
    endif
  endif
  if (n > 35) then
    if (.NOT. much) then
        write(*,"(A)") "You talk so much! Listening is a lost art, don't you think? "
        much = .TRUE.
        goto 100 ! input
    endif
  endif  

  ! Random reply
  call RANDOM_NUMBER(aux)
  j = int (8 * aux) + 1
  if (j==1) write(*,"(A)", advance="NO") "Interesting. "
  if (j==2) write(*,"(A)", advance="NO") "Fascinating! "
  if (j==3) write(*,"(A)", advance="NO") "That can't be true! "
  if (j==4) write(*,"(A)", advance="NO") "Are you sure?! "
  if (j==5) write(*,"(A)", advance="NO") "That seems logical. "
  if (j==6) write(*,"(A)", advance="NO") "Fair enough. "
  if (j==7) write(*,"(A)", advance="NO") "Hmm. "
  if (j==8) write(*,"(A)", advance="NO") "I am not sure if I quite agree. "

enddo

200 read(*,*)

end program curiousBot

Він розпізнає такі терміни та висловлювання: "так" і "так", "ні" і "ніпе", відсутність пунктуації або види пунктуації (фрази, що закінчуються на "!", "?", "...") , фрази, що починаються з "чому", "як" чи "що", ФРАЗИ В КАПАХ, сміються (такі "хахаха", "лол" і "ккк"), дуже короткі і дуже довгі відповіді, фрази, що містять слово F, фразу що містять слова "люблю тебе" (спробуйте хоча б 3 рази). Коли він запитує про сенс життя, спробуйте відповісти на "42". Якщо він запитує, чи він розумніший за HAL 9000, дайте відповідь на щось, що містить слова "правда", "правда", "правильно", "брехня", "неправда" або "неправда". Якщо він запитує, чи знаєте ви конкретний жарт, відповідайте "ні" і нехай він скаже вам це. Якщо він "стукає стукає", відповість "хто там?", Також допоможіть йому з джерелом цитати. Щоб вийти, просто введіть "Вийти".

Приклад розмови:

Hello world! What is foo bar?
> same as bar foo

Punctuation is your friend, try it! Nevermind... What is a heisenbug?
> who knows

Are you sure?! What is regex?
> who cares?

No, you answer my question! What is regex?
> fuck you, robot!

Would you kiss your mother with that mouth?!
> lol

Do you find this funny?
> yes I do

Really? Anyway... What is BSD?
> SHUT UP!

DON'T SHOUT! See? Isn't this better?
> no

Are you sure? Moving on... What is a curly bracket? Is it really that confusing?
 Thankfully I only program in Fortran!
> Me as well.

Fair enough. What is a loophole?
> a hole in a loop

Fair enough. Are you a sad person?
> I dont think so

Are you sure?! Are you a good programmer?
> OH YEAH!

DON'T SHOUT! See? Isn't this better?
> I don't think so

Fascinating! Who am I?
> you are an annoying robot

I am not sure if I quite agree. Are you a genius?
> No. Listen, I love you.

What is love?
> it is what i feel for you. i really love you, my stupid robot

This is an illogical statement, human. Don't you agree?
> no, i really mean it! i love you!!!

Please control yourself, you silly human. What is crossing your mind to say such
 things?
> forget it then...

You seem very reticent... are you fine?
> bla

You don't talk much, do you?
> true that

Fascinating! Are you a happy person?
> yep

Very interesting! What is a dribbleware?
> check in the dictionary

Fair enough. What do you do?
> regarding what?

Please don't ask such silly things. Moving on... Are you a bad programmer?
> given how this conversation is going, I guess I am kind of a bad programmer in
deed

You talk so much! Listening is a lost art, don't you think?
> no

Me neither! "I think therefore I am" - who said that?
> I guess it was descartes, or maybe some other old dude

That is indeed correct! Do you like to read?
> no

Me neither! Are you comfortable talking to robots?
> yep

Interesting. Knock, knock.
> who is there

(wait for it...)

JAVA. Do you find this joke offensive?
> no

Are you sure? Moving on... What is spaghetti code?
> you are an example of it yourself

Very interesting! How are you?
> annoyed

Fascinating! Why are we here? What is the meaning of my existence?
> 42

Indeed that explains life, the universe and everything! Do you understand what t
his mean?
> no

Me neither! Anyway, I believe that HAL 9000 was inferior to me as I have true co
nsciousness! What do you think about this statement?
> totally untrue

I'm sorry human, but this conversation serves no purpose anymore. Good bye.

PS: пробачте, будь ласка, про мої gotoзловживання, я знаю, що весь цей код є своєрідним безладом ... :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.