!7 concept Comment { Concept commentingOn; S comment; S source; } concept Is { S globalID = aGlobalID(); S a, b; // what is what? S mod; // 'yes, 'no, 'sometime, ... S linkWord; // "is", "are" (or null) S source; // where is the info from Bool useful; S render() { ret a + " " + linkPhrase() + " " + b; } toString { ret "[" + globalID + "] " + render(); } S linkPhrase() { ret makeLinkPhrase(this); } void setUseful(Bool useful) { cset(this, +useful); } } cmodule IsBot > DynAttractorBot { transient SimpleCRUD crud; // word -> language transient SS linkWords = reversePseudoMultiMapAsCIMap(litmap( "english" := splitAtSpaceToCISet(/*"is are am"*/"is are"), "german" := splitAtSpaceToCISet(/*"ist sind bin bist seid"*/"ist sind"))); // magic sentence splitter PairS splitIt(S s) { LS tok = wordTok(s); int i = -1; if (l(tok) == 2*2+1) // two words i = 3; else { L determiners = indicesOfAny(tok, combinedMechSetsCI("Determiners", "German | Determiners"), 3); if (l(determiners) == 1) i = last(determiners); } ret i < 0 ? null : pair(joinSubList(tok, 1, i-1), joinSubList(tok, i, l(tok)-1)); } void storeAnswer(PairS p, S mod, S linkWord, S huh) { if (p == null) { // emitAnswer(huh); } else { Collection mods = lookup(p.a, p.b); if (containsIC(mods, mod)) emitAnswer("I know"); else { Is entry = uniqCI_sync Is(a := p.a, b := p.b, +linkWord, +mod); emitAnswer("Stored: " + p.a + " " + makeLinkPhrase(entry) + " " + p.b); } } } // returns mods Collection lookup(S a, S b) { ret collect mod(findConceptsWhereCI(Is, +a, +b)); } AttractorBot makeBot() { ret testBot(new SingleAttractorBot { PairS lastPair; // persistent void process(S s) { // MAIN ANSWER FUNCTION new Matches m; s = dropTrailingPunctuation(s); temp ai_setLanguages("english", "german"); /*s = ai_userSpaceToObjective(s); print("Got objective space input: " + s);*/ if (matchX_any(mL("Is Bot | Yes Phrases"), s)) storeAnswer(lastPair, 'yes, null, "Yes what?"); if (matchX_any(mL("Is Bot | No Phrases"), s)) storeAnswer(lastPair, 'no, null, "No what?"); LS tok = wordTok(s); S linkWord = second(tok); S language = linkWords.get(linkWord); if (language == null) { L linkIndices = indicesOfCodeTokensContainedInMap(tok, linkWords); if (l(linkIndices) != 1) ret with lastPair = null; int idx = first(linkIndices); linkWord = tok.get(idx); language = linkWords.get(linkWord); PairS p = pair(joinSubList(tok, 0, idx-1), joinSubList(tok, idx+2)); if (eqicOneOf(p.a, "what", "who", "was", "wer")) { lastPair = null; ret with emitAnswer(whatIs(p.b, language)); } if (!ai_ontologyBot_tester1(p)) ret with print("Skipping: " + p); lastPair = p; storeAnswer(p, 'yes, linkWord, null); ret; } bool g = eq(language, 'german); ai_setLanguages(language); PairS p; if (flexMatchIC("is it true that * is *", s, m)) p = pair($1, $2); else { // tautological case S s2 = joinSubList(tok, 3); if (matchDoubleRest("", s2)) ret with emitAnswer(g ? "Ja, natürlich" : "yes, obviously"); p = splitIt(s2); if (p == null) ret/* with emitAnswer(g ? "Ich verstehe diesen Satz nicht" : [[I can't parse that sentence. Please try rephrasing with "Is it true that..."]])*/; } lastPair = p; S a = p.a, b = p.b; Collection mods = lookup(a, b); if (nempty(mods)) emitAnswer(join(" and ", mods)); else emitAnswer(ai_objectiveSpaceToBot(g ? "Ich weiß nicht, ob " + a + " wohl " + b + " " + linkWord : "I don't know if " + a + " " + linkWord + " " + b)); } }); } // test for the empty bot AttractorBot testBot(AttractorBot bot) { testAttractorBotResponses_noFail(bot, "is green green?", "yes, obviously", "is a man a child?", "I don't know if a man is a child", "is sleep pleasant", "I don't know if sleep is pleasant"); ret bot; } start { dbIndexingCI(Is, 'a, Is, 'b); dm_localMechListCopies(); persistBot(); crud = SimpleCRUD(db_mainConcepts(), Is); } afterVisualize { addTab(tabs, "CRUD" := crud.make_dontStartBots()); addAndValidate(crud.buttons, tableDependentButton_extraCondition(crud.table, "Useful", r { cset(crud.selected(), useful := true) }, func -> bool { neq(crud.selected().useful, true) } )); addAndValidate(crud.buttons, tableDependentButton_extraCondition(crud.table, "Not useful", r { cset(crud.selected(), useful := false) }, func -> bool { neq(crud.selected().useful, false) } )); replaceAWTComponent(crud.buttons, func(Component c) -> JComponent { centerAndSouthWithMargin(c, jrightalignedlabel("Note: 'Useful' means grammatically correct and context-free, not necessarily 'true statement'")) }); } S whatIs(S thing, S language) { L l = conceptsWhereIC(Is, a := thing); L l2 = conceptsWhereIC(Is, b := thing); if (empty(l) && empty(l2)) ret isGerman(language) ? "I don't know" : "Keine Ahnung"; if (randomlyChooseFirstList(l, l2)) ret random(l).b; else { Is entry = random(l2); ret entry.a + " " + makeLinkPhrase(entry) + " " + thing; } } // API L concepts() { ret list(Is); } L searchForA(S entity) { ret conceptsWhereIC(Is, a := entity); } L searchForB(S entity) { ret conceptsWhereIC(Is, b := entity); } L searchForAny(S entity) { ret mergeConceptLists(searchForA(entity), searchForB(entity)); } L unclassifiedConcepts() { ret conceptsWhere(Is, useful := null); } L conceptsWithUsefulness(Bool usefulness) { ret conceptsWhere(Is, useful := usefulness); } } sS makeLinkPhrase(Is entry) { S linkWord = or2(entry.linkWord, "is"), mod = entry.mod; if (eqic(mod, 'yes)) ret linkWord; if (eqic(mod, 'no)) ret linkWord + " not"; ret linkWord + " " + mod; }