1 | bool debug; |
2 | bool imagineMode; |
3 | bool collectCheckingLog = true; |
4 | new LinkedHashSet<S> imaginedFacts; |
5 | LS checkingLog; |
6 | long processingTime; |
7 | new L<IfThen> activeTempRules; |
8 | int evalTimeout = 20000; |
9 | bool useIterate; // full iterate mode for normal rule checking |
10 | O standardGrouper; // grouping function for all input |
11 | S ruleFired, lastRuleFired; |
12 | |
13 | *() { |
14 | please include function parse3_cachedPattern. |
15 | please include function parse3_cachedInput. |
16 | setMaxSizeOfMRUCache(parse3_cachedPattern_cache, 10000); |
17 | setMaxSizeOfMRUCache(parse3_cachedInput_cache, 10000); |
18 | } |
19 | |
20 | void thinkAbout(S s) { |
21 | time "Processing Time For Message"{ |
22 | thinkAbout_impl(s); |
23 | } |
24 | processingTime = lastTiming(); |
25 | } |
26 | |
27 | void thinkAbout_impl(fS input) { |
28 | final new Thinking t; |
29 | final Map<S, O> tl = getMCThreadLocals(ai_staticVars()); |
30 | /*Thread thread = startThread("Think!", r { |
31 | setMCThreadLocals(tl);*/ |
32 | t.thinkAbout(input); |
33 | /*});*/ |
34 | int n = 0; |
35 | do { |
36 | while (l(t.output) > n) |
37 | postMessage(t.output.get(n++)); |
38 | //joinThread(thread, 50); |
39 | } while (!t.done); |
40 | |
41 | activeTempRules.clear(); |
42 | lastRuleFired = ruleFired; |
43 | //print("lastRuleFired := " + lastRuleFired); |
44 | /*if (lastRuleFired != null) { |
45 | lastRuleFired = null; |
46 | print("lastRuleFired := null"); |
47 | }*/ |
48 | } |
49 | |
50 | void _postMessage(S s) { postMessage(s); } |
51 | |
52 | class Thinking { |
53 | long cancelTime = now()+20000; |
54 | new Map<S, Int> ruleScores; |
55 | new LinkedHashSet<S> rewrittenInputs; |
56 | new LinkedHashSet<S> newRewrittenInputs; |
57 | volatile bool posted, done; |
58 | new L<IfThen> rules; |
59 | replace Plan with PlanInMotion. |
60 | new Plan<Runnable> plan; |
61 | new HashSet<S> outputSet; |
62 | LS output = synchroList(); |
63 | |
64 | void postMessage(S s) { |
65 | //_postMessage(s); |
66 | if (outputSet.add(s)) |
67 | output.add(s); |
68 | posted = true; |
69 | } |
70 | |
71 | void done() { done = true; } |
72 | |
73 | void thinkAbout(S input) { |
74 | try { |
75 | thinkAbout_impl(input); |
76 | } finally { |
77 | done(); |
78 | } |
79 | } |
80 | |
81 | void thinkAbout_impl(fS input0) { |
82 | if (ruleFired != null) { |
83 | ruleFired = null; |
84 | //print("ruleFired := null"); |
85 | } |
86 | fS input1 = unixLineBreaks(input0); |
87 | plan.add(r "!initiative" { |
88 | if (!eq(input1, "!initiative")) ret; |
89 | L<IfThen> rules = mL_parsedNLRulesWithoutIDs("Initiative rules"); |
90 | for (IfThen rule : shuffledIterator(rules)) { |
91 | Pair<Exp> p = nlLogic_extractFirstCondition(rule.in); |
92 | if (p == null) continue; |
93 | if (nlLogic_isFunc(p.a, 'initiative)) { |
94 | postMessage(nlLogic_text(((Func) p.a).arg)); |
95 | IfThen temp = IfThen(p.b, rule.out); |
96 | temp.globalID = aGlobalID(); |
97 | print("Have temp rule: " + sfu(temp)); |
98 | activeTempRules.add(temp); |
99 | ret with done(); |
100 | } |
101 | } |
102 | ret with done(); |
103 | }); |
104 | |
105 | plan.add(r "!step" { |
106 | new Matches mm; |
107 | if (!startsWith_trim(input1, "!step ", mm)) ret; |
108 | // TODO |
109 | }); |
110 | |
111 | runPlanWithCheck(plan, func -> bool { !done }); |
112 | if (done) ret; |
113 | |
114 | stdCommands(input1); |
115 | |
116 | S input2 = input1; |
117 | final new LS options; |
118 | if (startsWith(input2, "[")) { |
119 | addAll(options, leadingSquareBracketOptions(input2)); |
120 | input2 = dropLeadingSquareBracketStuff(input2); |
121 | } |
122 | |
123 | fS input = callFOrKeep(standardGrouper, input2); |
124 | ai_tg_collectRuleFeedback(ruleScores, null); |
125 | |
126 | newRewrittenInputs.add(input); |
127 | final Map msg = telegram_msg(); |
128 | |
129 | final NLLogicChecker_v3 c = new NLLogicChecker_v3 { |
130 | bool checkExpression_impl(Exp e, Matching m) { |
131 | if (e instanceof Literal) { |
132 | // TEXT CONDITIONS |
133 | |
134 | S text = nlLogic_text(e); |
135 | if (eq(text, "authorized")) |
136 | ret telegram_amIAuthorized(); |
137 | else if(eq(text, "imagineMode")) |
138 | ret imagineMode; |
139 | } |
140 | |
141 | ret super.checkExpression_impl(e, m); |
142 | } |
143 | }; |
144 | c.followingUpOn = lastRuleFired; |
145 | |
146 | if (collectCheckingLog) { |
147 | checkingLog = new L; |
148 | nlLogic_collectCheckingLog(c, checkingLog); |
149 | } |
150 | |
151 | Pair<L<IfThen>, LS> rulesAndFacts = getRulesAndFacts(); |
152 | c.facts = reversed(rulesAndFacts.b); |
153 | rules = concatLists_conservative(activeTempRules, reversed(rulesAndFacts.a)); // latest rules first! |
154 | final Set<S> toDrop = asHashSet(matchAll_first("$x is not a general chat rule", c.facts)); |
155 | rules = [IfThen r : rules | !toDrop.contains(r.globalID) |
156 | && ai_ruleAccessesInput(r)]; |
157 | c.rules = rules; |
158 | |
159 | while (!posted && now() < cancelTime && nempty(newRewrittenInputs)) { |
160 | fS s = first(newRewrittenInputs); |
161 | rewrittenInputs.add(s); |
162 | newRewrittenInputs.remove(s); |
163 | |
164 | c.input = s; |
165 | c.recentHistory = recentHistory; |
166 | c.useIterate = useIterate; |
167 | |
168 | final new L<RuleWithParams> battleSpace; |
169 | |
170 | nlLogic_fillBattleSpace(c, battleSpace, debug); |
171 | |
172 | print("Have " + n2(battleSpace, "possible rule") |
173 | + (empty(battleSpace) ? "" : ": " + joinWithComma(map(func(RuleWithParams r) -> S { r.ruleID() + "/" + toInt(ruleScores.get(r.ruleID())) }, battleSpace)))); |
174 | |
175 | bool all = options.contains("all"); |
176 | if (!all) nlLogic_battleItOut(battleSpace, c.facts); |
177 | |
178 | L<RuleWithParams> winners = all ? battleSpace : nlLogic_highestScore(battleSpace, ruleScores); |
179 | |
180 | fS msgGlobalID = getString(msg, 'globalID); |
181 | //print("msgGlobalID=" + msgGlobalID); |
182 | for (RuleWithParams r : winners) { |
183 | print("Firing rule " + r.rule.globalID); |
184 | |
185 | // Save rule fire |
186 | ruleFired = r.rule.globalID; |
187 | if (nempty(msgGlobalID) && nempty(r.rule.globalID)) { |
188 | S fact = format("Rule * fired on message * at *", r.rule.globalID, msgGlobalID, localDateWithMilliseconds()); |
189 | if (nempty(r.matches)) |
190 | fact += " with vars " + dropPrefix("lhm", struct(r.matches)); |
191 | print("Saving rule fire. Mech mode: " + mechMode()); |
192 | print(addToMechList("Telegram Rule Fires", print(fact))); |
193 | } |
194 | |
195 | executeRule(c, r, this); |
196 | } |
197 | |
198 | if (collectCheckingLog) |
199 | print("Checking log length: " + l(checkingLog)); |
200 | } |
201 | } |
202 | } // end class Thinking |
203 | |
204 | void executeRule(NLLogicChecker_v3 c, RuleWithParams r, Thinking t) { |
205 | // Execute rule |
206 | for (Exp e : nlLogic_unrollAnd(r.rule.out)) { |
207 | e = c.apply(e, r.matches); |
208 | if (e cast Func) { |
209 | S name = e.name, arg = nlLogic_text(e.arg); |
210 | if (eqOneOf(name, 'output, 'say)) |
211 | t.postMessage(arg); |
212 | else if (eq(name, 'fact)) { |
213 | S fact = arg; |
214 | if (imagineMode) { |
215 | if (!containsNL(imaginedFacts, fact)) { |
216 | imaginedFacts.add(fact); |
217 | t.postMessage("Storing imaginary fact: " + fact); |
218 | } |
219 | } else if (!ai_isQuestion_2(fact) && ai_storeActualFact(fact)) |
220 | t.postMessage("Storing fact: " + fact); |
221 | } else if (eq(name, 'storeRule)) { |
222 | S rule = arg; |
223 | if (!telegram_authorizedToStoreRule(rule)) continue; |
224 | rule = nlLogic_addGlobalID(rule); |
225 | if (mech_changed(appendToMechList_noUniq("NL Logic Examples", "\n" + rule))) |
226 | t.postMessage("Rule stored"); |
227 | } else if (eq(name, 'imagineMode)) { |
228 | imagineMode = match("true", arg); |
229 | if (!imagineMode) imaginedFacts.clear(); |
230 | } else if (eq(name, 'input)) { |
231 | S x = arg; |
232 | if (!t.rewrittenInputs.contains(x) && t.newRewrittenInputs.add(x)) |
233 | print("New rewritten input: " + x); |
234 | } else if (c.checkHelper(e, ai_matchingWrapping(r.matches))) { |
235 | } else |
236 | ret with print("Skipping rule with unknown RHS func: " + e.name); |
237 | } else |
238 | ret with print("Skipping rule with unknown RHS element: " + e); |
239 | } |
240 | } |
241 | |
242 | Pair<L<IfThen>, LS> getRulesAndFacts() { |
243 | Pair<L<IfThen>, LS> p = ai_activeRulesAndFacts(imagineMode ? asList(imaginedFacts) : null); |
244 | if (debug) |
245 | print("getRulesAndFacts: " + n2(p.a, "rule")); |
246 | ret p; |
247 | } |
248 | |
249 | void stdCommands(S s) { |
250 | s = trim(s); |
251 | |
252 | final new Matches m; |
253 | S procedure = nlLookup(mechMap("Telegram Procedures"), s, m); |
254 | if (procedure != null) { |
255 | procedure = expandDollarRefsToMatches(procedure, m, true); |
256 | print(">> " + procedure); |
257 | postMessage(strOrNull(javaEvalOrInterpret(procedure))); |
258 | } |
259 | |
260 | print("s=" + s); |
261 | S language = 'english; |
262 | if (swic_trim(s, "!german ", m)) { |
263 | language = 'german; |
264 | s = m.rest(); |
265 | print("s=" + s); |
266 | } |
267 | ai_setLanguage(language); |
268 | |
269 | if (swic_trim(s, "!say ", m)) |
270 | postMessage(m.rest()); |
271 | |
272 | if (eq(s, "!gac")) |
273 | postMessage(random_gac36k()); |
274 | |
275 | if (swic_trim(s, "!parse ", m)) |
276 | postMessage(ai_renderCulledParseTree(ai_parseToTreeWithGuessing(m.rest()))); |
277 | |
278 | if (swic_trim(s, "!simplify ", m)) |
279 | postMessage(lines(ai_parseTree_simplifiedTexts(ai_parseToTreeWithGuessing(m.rest())))); |
280 | |
281 | if (swicOneOf_trim(s, m, "!factsFrom ", "!factsFrom\n")) { |
282 | S x = m.rest(); |
283 | ai_deriveFacts_debug = leadingSquareBracketOptions(x).contains("debug"); |
284 | temp tempSet(NLLogicChecker_v2, staticVerbose := ai_deriveFacts_debug); |
285 | fS _x = dropActuallyLeadingSquareBracketStuff(x); |
286 | postMessage(or2(evalWithTimeout_text(evalTimeout, func { |
287 | lines(ai_factsFromNewFacts(tlft(_x))) |
288 | }), "No new facts found")); |
289 | } |
290 | |
291 | if (swic_trim(s, "!askBack ", m)) { |
292 | NLLogicChecker_v2 c = nlLogicCheckerWithRulesAndFacts(getRulesAndFacts()); |
293 | c.input = m.rest(); |
294 | askBack(c); |
295 | } |
296 | |
297 | if (swic_trim(s, "!askBackAboutFact ", m)) { |
298 | NLLogicChecker_v2 c = nlLogicCheckerWithRulesAndFacts(getRulesAndFacts()); |
299 | c.facts = listPlus_inFront(c.facts, m.rest()); |
300 | askBack(c); |
301 | } |
302 | |
303 | /*if (telegram_amIAuthorized())*/ { |
304 | if (telegram_amIFullyAuthorized()) { |
305 | if (eq(s, "!reload")) { |
306 | if (!hasFunctionNamed(mc(), 'dm_reloadMe)) |
307 | postMessage("Not a module"); |
308 | else { |
309 | postMessage("OK, reloading."); |
310 | doAfter(1000, 'dm_reloadMe); |
311 | ret; |
312 | } |
313 | } |
314 | |
315 | bool freshMe = swic_trim(s, "!fresh ", m); |
316 | if (freshMe || eq(s, "!fresh")) { dm_refreshTranspiler(); if (!freshMe) postMessage("OK"); } |
317 | |
318 | if (swic_trim(s, "!eval ", m)) |
319 | postMessage(pcallOrExceptionText(func { strOrNull(javaEvalOrInterpret(m.rest())) })); |
320 | |
321 | if (freshMe || swic_trim(s, "!real-eval ", m)) |
322 | postMessage(evalWithTimeout_text(evalTimeout, func { |
323 | javaEval(m.rest()) |
324 | })); |
325 | } |
326 | |
327 | if (swic_trim(s, "!rule ", m)) { |
328 | S rule = m.rest(); |
329 | if (!telegram_authorizedToStoreRule(rule)) ret; |
330 | LS rules = trimAll(ai_unparsedTalkRules()); |
331 | if (!contains(rules, rule)) { // TODO: ignore global IDs |
332 | rule = nlLogic_addGlobalID(rule); |
333 | appendToMechList_noUniq("NL Logic Examples", "\n" + rule); |
334 | postMessage("Rule saved as " + leadingSquareBracketOptions_id(rule) + ". Have " + n2(l(rules)+1, "rule") + "."); |
335 | } |
336 | } |
337 | |
338 | if (swic_trim(s, "!fact ", m)) { |
339 | S fact = m.rest(); |
340 | LS facts = mL("Random facts"); |
341 | if (!contains(facts, fact)) { |
342 | appendToMechList_noUniq("Random facts", fact); |
343 | postMessage("Fact saved. Have " + n2(l(facts)+1, "fact") + "."); |
344 | } |
345 | } |
346 | |
347 | if (eqic(s, "!deriveFacts")) |
348 | postMessage("Got " + n2(ai_applyFactToFactRules(), "fact") + ". Total: " + l(mL("Derived facts"))); |
349 | |
350 | if (eqic(s, "!groupFacts")) |
351 | if (standardGrouper != null) { |
352 | appendToMechList("Derived facts", map(standardGrouper, ai_facts())); |
353 | postMessage("OK"); |
354 | } |
355 | |
356 | if (eqic(s, "!imaginaryFacts")) { |
357 | Pair<L<IfThen>, LS> rulesAndFacts = getRulesAndFacts(); |
358 | LS facts = reversed(rulesAndFacts.b); |
359 | L<IfThen> rules = concatLists_conservative(activeTempRules, reversed(rulesAndFacts.a)); // latest rules first! |
360 | final Set<S> toDrop = asHashSet(matchAll_first("$x is not a general chat rule", facts)); |
361 | rules = [IfThen r : rules | !toDrop.contains(r.globalID) |
362 | && !ai_ruleAccessesInput(r)]; |
363 | print("Deriving from " + n2(rules, "rule") + " and " + n2(facts, "fact")); |
364 | set ai_deriveFacts_debug; |
365 | Set<S> newFacts = ai_deriveFacts(rules, facts); |
366 | newFacts = setMinusSet(newFacts, facts); |
367 | imaginedFacts.addAll(newFacts); |
368 | postMessage("Got " + n2(newFacts, "imaginary fact") + ". Total: " + l(imaginedFacts)); |
369 | } |
370 | |
371 | // end of authorized functions |
372 | } |
373 | } |
374 | |
375 | void askBack(NLLogicChecker_v2 c) { |
376 | L<RuleFailInfo> fails = nlLogic_sortedRuleFails(nlLogic_ruleFails(c, c.rules)); |
377 | print("Have " + n2(fails, "fail")); |
378 | //pnl(fails); |
379 | postMessage(lines(nlLogic_unresolvedFactsToQuestions(fails))); |
380 | } |
381 | |
382 | int numRules() { ret l(first(getRulesAndFacts())); } |
Began life as a copy of #1017946
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1018038 |
Snippet name: | Telegram Facts Bot [Include v2] |
Eternal ID of this version: | #1018038/63 |
Text MD5: | a9fea91f459236e4f299c92088c577ec |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-10-05 18:07:43 |
Source code size: | 13633 bytes / 382 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 549 / 1255 |
Version history: | 62 change(s) |
Referenced in: | [show references] |