forked from forslund/fallback-aiml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
121 lines (106 loc) · 4.66 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Copyright 2022 Åke Forslund
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import aiml
import os
from os import listdir, remove as remove_file
from os.path import dirname, isfile
from ovos_workshop.skills.fallback import FallbackSkill
from ovos_workshop.decorators import intent_handler
from ovos_workshop.intents import IntentBuilder
class AimlFallback(FallbackSkill):
def initialize(self):
self.kernel = aiml.Kernel()
self.aiml_path = os.path.join(dirname(__file__), 'aiml')
self.brain_path = os.path.join(self.file_system.path, 'bot_brain.brn')
# reloading skills will also reset this 'timer', so ideally it should
# not be too high
self.line_count = 1
self.save_loop_threshold = int(self.settings.get('save_loop_threshold', 4))
self.brain_loaded = False
self.register_fallback(self.handle_fallback, 90)
def load_brain(self):
"""Set up the aiml engine using available device information."""
self.log.info('Loading Brain')
if isfile(self.brain_path):
self.kernel.bootstrap(brainFile=self.brain_path)
else:
aimls = listdir(self.aiml_path)
for aiml_file in aimls:
self.kernel.learn(os.path.join(self.aiml_path, aiml_file))
self.kernel.saveBrain(self.brain_path)
device = {
"name": "Mycroft",
"platform": "AI"
}
self.kernel.setBotPredicate("name", device["name"])
self.kernel.setBotPredicate("species", device["platform"])
self.kernel.setBotPredicate("genus", "Mycroft")
self.kernel.setBotPredicate("family", "virtual personal assistant")
self.kernel.setBotPredicate("order", "artificial intelligence")
self.kernel.setBotPredicate("class", "computer program")
self.kernel.setBotPredicate("kingdom", "machine")
self.kernel.setBotPredicate("hometown", "127.0.0.1")
self.kernel.setBotPredicate("botmaster", "master")
self.kernel.setBotPredicate("master", "the community")
# IDEA: extract age from
# https://api.github.com/repos/MycroftAI/mycroft-core created_at date
self.kernel.setBotPredicate("age", "2")
self.brain_loaded = True
@intent_handler(IntentBuilder("ResetMemoryIntent").require("Reset")
.require("Memory"))
def handle_reset_brain(self, message):
"""Delete the stored memory, effectively resetting the brain state."""
self.log.debug('Deleting brain file')
# delete the brain file and reset memory
self.speak_dialog("reset.memory")
remove_file(self.brain_path)
self.soft_reset_brain()
def ask_brain(self, utterance):
"""Send a query to the AIML brain.
Saves the state to disk once in a while.
"""
response = self.kernel.respond(utterance)
# make a security copy once in a while
if (self.line_count % self.save_loop_threshold) == 0:
self.kernel.saveBrain(self.brain_path)
self.line_count += 1
return response
def soft_reset_brain(self):
# Only reset the active kernel memory
self.kernel.resetBrain()
self.brain_loaded = False
def handle_fallback(self, message):
"""Mycroft fallback handler interfacing the AIML.
If enabled in home, this will parse a sentence and return answer from
the AIML engine.
"""
if self.settings.get("enabled"):
if not self.brain_loaded:
self.load_brain()
utterance = message.data.get("utterance")
answer = self.ask_brain(utterance)
if answer != "":
asked_question = False
if answer.endswith("?"):
asked_question = True
self.speak(answer, expect_response=asked_question)
return True
return False
def shutdown(self):
"""Shut down any loaded brain."""
if self.brain_loaded:
self.kernel.saveBrain(self.brain_path)
self.kernel.resetBrain() # Manual remove
self.remove_fallback(self.handle_fallback)
super().shutdown()