!752 static boolean equipWithSigned = true; // add Stefan's signed theories to all AIs static new Map aiMap; static O prolog; static class AI { S theory; boolean enabled; S icon; long iconFetched; *() {} *(S *theory) {} } p { load("aiMap"); } static S createAI(S name, S theory) { if (getTheory(theory) == null) ret format("Theory * not found", theory); AI ai = new AI(theory); ai.enabled = true; aiMap.put(name, ai); logStructure("log", litlist("add", name, ai)); save("aiMap"); ret format("OK, AI * is created & enabled!", name); } synchronized answer { exceptionToUser { if "create ai * *" { S name = m.unq(0), theory = m.unq(1); ret createAI(name, theory); } if "create ai *" { S name = m.unq(0); ret createAI(name, name); } if "update ai * *" { S name = m.unq(0), theory = m.unq(1); if (getTheory(theory) == null) ret format("Theory * not found", theory); AI ai = lookupPossiblyIgnoreCase(aiMap, name); if (ai == null) ret format("AI * not found", name); ai.theory = theory; save("aiMap"); ret format("AI * updated to *", name, theory); } if "disable ai *" { S name = m.unq(0); AI ai = lookupPossiblyIgnoreCase(aiMap, name); if (ai == null) ret format("AI * not found", name); if (!ai.enabled) ret "AI not enabled anyway"; ai.enabled = false; save("aiMap"); ret "AI disabled."; } if "enable ai *" { S name = m.unq(0); AI ai = lookupPossiblyIgnoreCase(aiMap, name); if (ai == null) ret format("AI * not found", name); if (ai.enabled) ret "AI already enabled"; ai.enabled = true; save("aiMap"); ret "AI enabled."; } if "rename ai * to *" { S name = m.unq(0), newName = m.unq(1); AI ai = lookupPossiblyIgnoreCase(aiMap, name); if (ai == null) ret format("AI * not found", name); name = reverseLookup(aiMap, ai); AI ai2 = lookupPossiblyIgnoreCase(aiMap, newName); if (ai2 != null) ret format("Target name * exists!", newName); aiMap.remove(name); aiMap.put(newName, ai); save("aiMap"); ret format("AI * renamed to *", name, newName); } if "list ais" { ret slackSnippet(structureLines(aiMap)); } if "theory of *" { S name = m.unq(0); AI ai = lookupPossiblyIgnoreCase(aiMap, name); if (ai != null) { L names = getTheoryNames(name, ai); new StringBuilder buf; for (S theory : names) buf.append(getTheory(theory) + "\n"); ret reverseLookup(aiMap, ai) + " / " + quote(ai.theory) + "\n" + slackSnippet(buf); } } if "test ai * *" exceptionToUser { S name = m.unq(0), input = m.unq(1); AI ai = aiMap.get(name); if (ai == null) ret format("AI * not found", name); S answer = queryAI(name, input, nlParse(input), true); S x = answer + "\n" + slackSnippet((L) get(prolog, "log")); prolog = null; ret x; } if "time ai * *" exceptionToUser { S name = m.unq(0), input = m.unq(1); AI ai = aiMap.get(name); if (ai == null) ret format("AI * not found", name); S answer; time { answer = queryAI(name, input, nlParse(input), false); } S x = answer + "\n" + lastTiming() + " ms"; prolog = null; ret x; } if "ai program *" exceptionToUser { S name = m.unq(0); AI ai = aiMap.get(name); if (ai == null) ret format("AI * not found", name); makeProlog(name, ai, false); S x = cast call(prolog, "showProgram"); prolog = null; ret x; } // do the job Lisp input = null; for (S name : aiMap.keySet()) pcall { AI ai = aiMap.get(name); if (!ai.enabled) continue; if (input == null) input = nlParse(s); S answer = queryAI(name, s, input, false); prolog = null; // clean up prolog interpreter if (nempty(answer)) { callOpt(getMainBot(), "postAs", name); if ((ai.icon == null || ai.iconFetched < now()-(empty(ai.icon) ? 1 : 24)*60*60*1000) && canGetIcons()) { if (ai.icon == null) ai.icon = ""; // for safety if request fails ai.iconFetched = now(); pcall { makeIcon(name, ai); } save("aiMap"); } if (nempty(ai.icon)) callOpt(getMainBot(), "botIcon", ai.icon); ret answer; } } }} static boolean makeProlog(S name, AI ai, boolean logOn) { L theoryNames = getTheoryNames(name, ai); if (empty(theoryNames)) ret false; prolog = call(prologBot(), "newProlog", theoryNames, logOn); ret true; } // input = nlParse(s) static S queryAI(S name, S s, Lisp input, boolean logOn) { AI ai = aiMap.get(name); if (!makeProlog(name, ai, logOn)) ret null; set(prolog, "outTheory", name + ".data"); //S in = "user says " + nlUnparse(input, false); /*call(prolog, "addClause", in); S question = "say $x";*/ S question = "[think [user says " + nlUnparse(nlEscapeVariables(input), false) + "]] and [say $x]"; Map solution = cast quickImport(call(prolog, "solve", question)); if (solution != null) { print("SOLUTION: " + structure(solution)); Lisp x = solution.get("$x"); if (x != null) ret nlUnparse(x); } ret null; } static L getTheoryNames(S name, AI ai) { new L l; l.add(name + ".data"); if (equipWithSigned) l.add("signedstefan"); S theory = getTheory(ai.theory); if (theory == null) ret litlist(); // hack to make directly linked theories work L tok = codeTokens(snlTok(theory)); if (eq(get(tok, 0), "if") || eq(get(tok, 1), "if")) l.add(ai.theory); else { Lisp t = nlParse(theory); for (Lisp x : t.args) if (neq(x.head, ",")) l.add(unquote(x.head)); } ret l; } static O prologBot() { ret getBot("#1002841"); } static S getTheory(S name) { ret (S) callOpt(getBot("#1002762"), "getTheoryOpt", name); } static boolean canGetIcons() { ret getBot("#1002511") != null; } static void makeIcon(S name, AI ai) { print("Making icon for AI: " + name); S url = cast call(getBot("#1002511"), "findImageNoShorten", name); if (nempty(url)) ai.icon = url; }