Files
fallback-aiml/__init__.py
2019-06-20 09:35:02 +02:00

135 lines
4.9 KiB
Python

# Fallback AIML
# Copyright (C) 2019 Mycroft Community
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import aiml
import os
from os import listdir, remove as remove_file
from os.path import dirname, isfile, getsize
from mycroft.api import DeviceApi
from mycroft.skills.core import FallbackSkill, intent_handler
from adapt.intent import IntentBuilder
from mycroft.util.log import LOG
class AimlFallback(FallbackSkill):
def __init__(self):
super(AimlFallback, self).__init__(name='AimlFallback')
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
def initialize(self):
self.register_fallback(self.handle_fallback, 90)
return
def load_brain(self):
LOG.info('Loading Brain')
if (isfile(self.brain_path) and
getsize(self.brain_path) > (1024 * 1024)):
self.kernel.bootstrap(brainFile=self.brain_path)
else:
aimls = listdir(self.aiml_path)
for aiml in aimls:
self.kernel.learn(os.path.join(self.aiml_path, aiml))
self.kernel.saveBrain(self.brain_path)
try:
device = DeviceApi().get()
except Exception:
device = {
"name": "Mycroft",
"type": "AI"
}
self.kernel.setBotPredicate("name", device.get("name", 'Mycroft'))
self.kernel.setBotPredicate("species", device.get("platform",
"unknown"))
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
return
@intent_handler(IntentBuilder("ResetMemoryIntent").require("Reset")
.require("Memory"))
def handle_reset_brain(self, message):
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()
return
def ask_brain(self, utterance):
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
return
def handle_fallback(self, message):
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):
if self.brain_loaded:
self.kernel.saveBrain(self.brain_path)
self.kernel.resetBrain() # Manual remove
self.remove_fallback(self.handle_fallback)
super(AimlFallback, self).shutdown()
def stop(self):
pass
def create_skill():
return AimlFallback()