Jawa
Sunting Baru : Masih ada lagi penyesuaian di waktu luang. Saya sudah memulai cabang baru, tempat saya bermain dengan algoritma DFS. Secara resmi cabang akan bertindak sebagai inti dari algoritma BFS baru yang saya rencanakan, tetapi sementara itu saya ingin mendapatkan penanganan yang lebih baik tentang apa yang dilakukan DFS, dan bagaimana ia membuat keputusannya. Untuk itu, saya telah menambahkan fungsi penindasan yang mulai mengurangi nilai kata baru, terlepas dari topik atau tidak, karena kalimat bertambah panjang. Selain itu, semua kata berkontribusi nilai untuk kalimat sekarang, tetapi kata-kata yang tidak ada dalam topik atau daftar topik kalimat berkontribusi hanya 25% dari nilai frekuensi mereka. Contoh percakapan di dapat ditemukan di sini dan itu cukup bagus, di mana kita berbicara tentang fisika, sifat manusia dari Chatbrains, dan topik menarik lainnya.kode cabang di sini .
Sunting : Saya telah sedikit mengubah kode. Alih-alih memposting revisi di sini, periksa di repositori github saya di mana Anda akan menemukan revisi terbaru. Saya juga menambahkan percakapan baru terhadap versi terbaru, di mana kami membahas chatbots, pencarian mendalam pertama, dan bagaimana pemrograman harus digunakan untuk membangun makhluk hidup !.
Saya memutuskan untuk menerima tantangan ini secara holistik. Chatbot saya tahu sangat sedikit hal mulai - tidak ada kata-kata, tidak ada sintaks, tidak ada apa-apa. Ia tahu bagaimana mem-parsing bahasa Inggris standar menjadi kata-kata, dan bagaimana mengidentifikasi karakter non-kata sebagai tanda baca. Itu dia. Segala sesuatu yang diketahuinya dipelajari dari interaksi dengan pengguna. Saat Anda berinteraksi dengannya, ia memperhatikan hubungan antara kata-kata, dan menyusun kalimat menggunakan informasi itu. Tentu saja, rujuk sumbernya untuk informasi lebih lanjut. Saya telah jauh melampaui harapan lama program yang disarankan untuk tantangan ini, tetapi untuk tujuan yang baik. Berikut adalah beberapa hal penting dari program ini:
- Chatbot dimulai tanpa pengetahuan (mengikuti "Aturan": 3 )
- Frekuensi kemunculan kata dilacak
- Frekuensi kata "membusuk" sehingga percakapan dapat berpindah dari satu topik ke topik lainnya (mengikuti "Bonus": 3 dan 4 )
- Susunan kata-kata dalam kalimat yang diamati direkam, jadi "frasa" secara implisit terus dilacak (misalnya jika Anda menggunakan banyak frasa preposisi ketika mengobrol dengan bot, bot akan menggunakan banyak juga!)
- Kalimat dibangun dengan memilih untuk mengikuti koneksi yang paling sering diamati antara kata-kata, dengan faktor acak untuk menyuntikkan variasi
- Algoritma konstruksi kalimat adalah Pencarian Kedalaman Pertama, yang mencoba untuk memaksimalkan kemunculan kata-kata topik dalam kalimat output, dengan preferensi kecil untuk mengakhiri kalimat (ini mengikuti "Bonus": 1 - Saya menggunakan algoritma pembelajaran yang sangat keren, yang bergeser dari waktu ke waktu dan mempertahankan pengetahuan tentang koneksi kata yang dipanen)
- sunting: Kata-kata topik sekarang diambil dari pengetahuan global tentang kata-kata berulang, dan dari kalimat terbaru
- sunting: Bobot kata sekarang dihitung menggunakan basis log 4 dari panjang kata, jadi kata yang lebih panjang diberi bobot lebih kuat, dan kata-kata lebih pendek, lebih lemah - ini adalah untuk menebus kurangnya corpus sejati untuk digunakan dalam pembobotan dan menghilangkan frekuensi tinggi, kata-kata bernilai rendah seperti yang dapat dengan mudah dilakukan dengan corpus.
- sunting: Ketika panjang kalimat tumbuh selama konstruksi, fungsi penindasan mulai mengurangi nilai kata-kata tambahan.
- sunting: Kalimat "ending" sekarang kurang bernilai, karena menyebabkan lebih banyak kalimat pendek yang konyol.
- sunting: Semua kata sekarang berkontribusi nilai, meskipun kata-kata di luar topik hanya berkontribusi sebesar 25% dari nilai frekuensi global.
- Ada kedalaman maksimum bawaan untuk mencegah terlalu banyak perulangan dan terlalu banyak waktu yang dihabiskan karena penggunaan kata preseden untuk membangun kalimat
- Loop terdeteksi secara langsung saat membuat kalimat, dan meskipun secara teknis diizinkan, ada kemungkinan besar loop akan dihindari
- Batas waktu yang dapat disetel digunakan untuk mendorong pemangkasan cabang dan finalisasi pernyataan, dan juga untuk mencegah melewati "keterlambatan yang dapat diterima" 5-10 detik dalam aturan
Untuk meringkas koneksi saya dengan aturan:
- Untuk "Aturan": 1 , saya memilih Java, yang verbose, jadi berhati-hatilah.
- Untuk "Aturan": 2 , input pengguna saja dimanfaatkan, meskipun saya memiliki beberapa kode rintisan untuk menambahkan penyimpanan / pemuatan otak untuk masa depan
- Untuk "Aturan": 3 , sama sekali tidak ada kosakata yang telah ditentukan sebelumnya. ChatBot tahu cara menguraikan bahasa Inggris, tetapi hanya itu. Sejak awal, ia sama sekali tidak tahu apa-apa.
- Untuk "Kriteria Wajib": 1 , program saya lebih panjang, tapi paketnya banyak sekali. Saya harap Anda mengabaikannya.
- Untuk "Kriteria Wajib": 2 , saya memiliki batas waktu pada algoritma konstruksi kalimat saya untuk secara eksplisit mencegah waktu pencarian lebih dari 5-6 detik. Kalimat terbaik sejauh ini dikembalikan pada batas waktu.
- Untuk "Kriteria Wajib": 3 , Topik umumnya dipadatkan dalam sekitar 10 kalimat, sehingga Bot akan menjadi topik saat itu, dan pada 20 kalimat akan menanggapi pernyataan dengan beberapa konstruksi acak yang menarik yang benar-benar masuk akal.
- Untuk "Kriteria Wajib": 4 , saya tidak meminjam apa pun dari kode referensi. Ini adalah konstruksi yang sepenuhnya unik.
- Untuk "Bonus": 1 , saya suka berpikir bot ini cukup luar biasa. Itu tidak akan meyakinkan seperti skrip bot, tetapi sama sekali tidak ada batasan pada topik, dan akan bergerak dengan anggun (dengan ketekunan) dari topik pembicaraan ke topik.
- Untuk "Bonus": 2 , ini sepenuhnya round-robin, jadi tidak ada bonus di sini. Namun. Tidak ada persyaratan dalam algoritme saya untuk tanggapan, jadi saya merencanakan versi Berurutan yang akan membahas bonus ini.
- Untuk "Bonus": 3 , awalnya bot ini akan meniru, tetapi saat percakapan berlanjut melampaui beberapa kalimat pertama, meniru akan berakhir dengan jelas.
- Untuk "Bonus": 4 , "suasana hati" tidak diproses dengan cara yang berarti, tetapi karena topik preferensi bot berikut, itu akan mengubah suasana hati.
- Untuk "Bonus": 5 , menabung dan memuat otak saat ini tidak ada.
Jadi, saya sudah memenuhi semua aturan dasar, semua aturan wajib, dan aturan bonus sementara 1, 3, dan 4.
Sebagai bonus lain, saya sudah berkomentar di seluruh kode, jadi silakan meminjam atau membuat rekomendasi untuk perbaikan. Jelas, karena saya tidak memiliki dialog bawaan dan tidak ada pengetahuan "struktural", percakapan akan terasa aneh lebih lama dari bot lainnya, tapi saya pikir saya memenuhi aturan dengan cukup baik.
Sekarang, lanjutkan ke kode (Beberapa komentar disunting agar sesuai dengan batas tubuh) atau ikuti di GitHub, karena saya terus meningkatkannya :
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();
}
}
}
Contoh percakapan:
Tertaut b / c dari batas karakter pos
Percakapan di mana Bot mengatakan padaku aku harus memprogram makhluk hidup
Percakapan terbaru di mana Bot berbicara tentang sifat sebenarnya dari otak Chat, fisika, alam semesta fisik, dan bagaimana saya kemungkinan besar juga seorang otak Chat.
dan seterusnya. Saya punya beberapa hal yang akan saya tambahkan - misalnya, karena kesamaan kata-kata sederhana, mereka cenderung mendominasi daftar topik yang tidak akurat. Saya akan menambahkan persentase lewati ke kata-kata topik sehingga kata-kata umum dilewati.
Chatbot? Well the earth is fun place to talk about
- Hei, itu benar-benar membuat kalimatnya sendiri (dapat dimengerti) di sana pada akhirnya! : D +1Chatbot? I'm not a Chatbrain since Chatbrains are the physical universe,
.The answer to the ultimate question about life, the universe, and everything is 'SyntaxError: missing ; before statement'.
C ++
Sekarang saya hanya perlu menulis algoritme untuk melanjutkan percakapan. Latihan pembelajaran mesin pertama saya.
Sunting:
Semua percobaan saya ternyata konyol, jadi saya pikir saya akan membiarkannya seperti ini. Yang lain sama konyolnya dengan ini:
sumber
C ++
Saya bertujuan untuk bonus opsional 3: " Kurang meniru, perilaku bot berbeda dari perilaku pengguna, memisahkan persepsi sikap bot dari sikap pengguna. ". Hasilnya adalah bot yang benar-benar keras kepala yang tidak bisa mengalihkan topik pembicaraan dengan mudah dan membuat Anda gila.
Butuh beberapa waktu untuk memulai diskusi, setelah beberapa saat diskusi dapat seperti ini:
Pendekatannya adalah untuk menyimpan semuanya menjadi 3 kelompok kata yang terhubung. Setiap kelompok ditimbang dan ditimbang kembali ke dalam matriks 1000 dimensi kelompok kata. Kode sumber:
sumber
class c_wglist { ... } wgl;
. Ini bekerja untuk saya. Coba init variabel wgl (class c_wglist) di tempat lain.Python3 + SQLite3
Ini bot kecil yang baru saja saya buat!
Bagaimana cara kerjanya?
Tiga tabel SQL digunakan: satu untuk kata-kata, satu untuk kalimat, satu untuk mengaitkan kata-kata yang diketik oleh pengguna, dengan kalimat berikutnya yang harus ditampilkan oleh bot.
Apa sajakah fitur khusus?
Lihat kode di bawah ini:
Inilah tiga "percakapan" pertama yang saya miliki dengan bot, dimulai dari database kosong:
Anda dapat melihat di sini untuk penjelasan lebih lanjut.
sumber
Ini adalah salah satu yang saya tulis di Liberty BASIC beberapa waktu lalu. Itu tidak belajar, tetapi menjawab jawaban yang berbeda dari pertanyaan itu.
contoh percakapan:
sumber
HTML5
sumber
Fortran 95
Terinspirasi oleh jawaban di atas oleh pengguna TheDoctor, saya memutuskan untuk membuat chatbot lucu dengan cara yang sama. Kode ini juga tidak belajar, dan saya membagikannya di sini hanya untuk bersenang-senang.
Ini mengakui istilah dan pernyataan berikut: "ya" dan "ya", "tidak" dan "tidak", kurangnya tanda baca, atau jenis tanda baca (frasa yang diakhiri dengan "!", "?", "...") , frasa yang dimulai dengan "mengapa", "bagaimana" atau "apa", PHRASES DI CAPS, tertawa (seperti "hahaha", "lol" dan "kkk"), jawaban yang sangat pendek dan sangat panjang, frasa yang mengandung kata F, frasa mengandung kata "love you" (coba minimal 3 kali). Ketika ditanya tentang arti hidup, coba jawab "42". Jika ditanya apakah dia lebih pintar daripada HAL 9000, jawablah sesuatu yang mengandung kata "benar", "kebenaran", "benar", "bohong", "salah" atau "tidak benar". Jika dia bertanya apakah Anda tahu lelucon tertentu, jawab "tidak" dan biarkan dia memberitahumu. Jika dia "mengetuk ketukan", jawab "siapa yang ada di sana?", Juga membantunya dengan sumber kutipan. Untuk berhenti, cukup ketik "berhenti".
Contoh percakapan:
PS: tolong maafkan
goto
penyalahgunaan saya , saya tahu seluruh kode ini berantakan ... :)sumber