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