2021-07-30 14:10:35 +02:00
|
|
|
import json
|
|
|
|
|
2021-07-27 23:10:01 +02:00
|
|
|
from adapt.engine import DomainIntentDeterminationEngine
|
2021-07-29 20:16:22 +02:00
|
|
|
from padatious import IntentContainer
|
2021-07-27 23:10:01 +02:00
|
|
|
|
2021-09-14 10:49:09 +02:00
|
|
|
from jarvis.utils import utils, client_utils
|
|
|
|
from jarvis.utils.fallbacks.wolframalpha import wa_client
|
2021-07-30 12:31:59 +02:00
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
adapt_engine = DomainIntentDeterminationEngine()
|
|
|
|
padatious_intents_container = IntentContainer('intent_cache')
|
2021-07-27 23:10:01 +02:00
|
|
|
|
2021-07-29 14:57:55 +02:00
|
|
|
intents_handlers_adapt = dict()
|
|
|
|
intents_handlers_padatious = dict()
|
2021-07-28 19:31:47 +02:00
|
|
|
|
2021-07-27 23:10:01 +02:00
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
def register_entity_adapt(entity_value, entity_type, domain):
|
|
|
|
adapt_engine.register_entity(entity_value=entity_value, entity_type=entity_type, domain=domain)
|
2021-07-28 19:31:47 +02:00
|
|
|
# print("[Adapt]: Added entity with type " + entity_type + " for " + domain)
|
2021-07-27 23:10:01 +02:00
|
|
|
|
|
|
|
|
2021-08-02 20:04:28 +02:00
|
|
|
def register_entity_padatious(entity_name, file_lines_list):
|
|
|
|
padatious_intents_container.add_entity(entity_name, file_lines_list)
|
2021-08-02 11:57:16 +02:00
|
|
|
# print("[Padatious]: Added entity with name " + entity_name + " with " str(len(list)) + "examples.")
|
|
|
|
|
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
def register_regex_adapt(regex, domain):
|
|
|
|
adapt_engine.register_regex_entity(regex, domain)
|
2021-07-28 19:31:47 +02:00
|
|
|
# print("[Adapt]: Added new regex for " + domain)
|
2021-07-27 23:10:01 +02:00
|
|
|
|
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
def register_intent_adapt(intent, domain):
|
|
|
|
adapt_engine.register_intent_parser(intent, domain=domain)
|
|
|
|
print("[Adapt]: Registered new intent " + intent.name + " for skill " + domain + ".")
|
|
|
|
|
|
|
|
|
|
|
|
def register_intent_padatious(intent_name, list_of_intent_examples):
|
|
|
|
padatious_intents_container.add_intent(intent_name, list_of_intent_examples)
|
|
|
|
print("[Padatious]: Registered new intent " + intent_name + " with " + str(
|
|
|
|
len(list_of_intent_examples)) + " examples.")
|
|
|
|
|
|
|
|
|
|
|
|
def train_padatious():
|
|
|
|
padatious_intents_container.train()
|
2021-07-27 23:10:01 +02:00
|
|
|
|
|
|
|
|
2021-07-30 14:10:35 +02:00
|
|
|
def load_all_skills():
|
2021-07-29 14:57:55 +02:00
|
|
|
for handler in intents_handlers_adapt:
|
|
|
|
function_handler = intents_handlers_adapt.get(handler)
|
2021-07-29 20:16:22 +02:00
|
|
|
intent_builder = getattr(function_handler[0], "_data", [])[0]
|
2021-07-28 19:31:47 +02:00
|
|
|
skill_name = function_handler[1]
|
2021-07-29 20:16:22 +02:00
|
|
|
register_intent_adapt(intent_builder.build(), domain=skill_name)
|
2021-07-28 19:31:47 +02:00
|
|
|
|
2021-07-29 14:57:55 +02:00
|
|
|
for handler in intents_handlers_padatious:
|
2021-07-29 20:16:22 +02:00
|
|
|
function_handler = intents_handlers_padatious.get(handler)
|
|
|
|
intent_data_examples = function_handler[1]
|
|
|
|
register_intent_padatious(handler, intent_data_examples)
|
2021-07-29 14:57:55 +02:00
|
|
|
|
2021-07-28 19:31:47 +02:00
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
def handle(intent_name, data):
|
2021-07-30 12:31:59 +02:00
|
|
|
module_path_str = None
|
|
|
|
handler_method_name = None
|
|
|
|
|
2021-07-29 14:57:55 +02:00
|
|
|
if intent_name in intents_handlers_adapt:
|
2021-07-30 12:31:59 +02:00
|
|
|
# something like handler_play_song_spotify (used to call the handler method from the skill imported below)
|
|
|
|
handler_method_name = intents_handlers_adapt.get(intent_name)[2]
|
2021-07-29 20:16:22 +02:00
|
|
|
|
2021-07-30 12:31:59 +02:00
|
|
|
# something like jarvis.skill.entertainment.spotify (used to import the create_skill method to create a new object)
|
|
|
|
module_path_str = intents_handlers_adapt.get(intent_name)[3]
|
2021-08-02 19:07:59 +02:00
|
|
|
|
2021-07-29 20:16:22 +02:00
|
|
|
if intent_name in intents_handlers_padatious:
|
2021-07-30 12:31:59 +02:00
|
|
|
handler_method_name = intents_handlers_padatious.get(intent_name)[0]
|
|
|
|
module_path_str = intents_handlers_padatious.get(intent_name)[2]
|
|
|
|
|
|
|
|
if module_path_str is not None and handler_method_name is not None:
|
|
|
|
# import the create_skill method from the skill using the skill module path
|
|
|
|
create_skill_method = utils.import_method_from_string(module_path_str, "create_skill")
|
|
|
|
|
2021-08-01 11:56:38 +02:00
|
|
|
skill_init_data = {'client_ip': data['client_ip'], 'client_port': data['client_port']}
|
2021-08-01 11:47:16 +02:00
|
|
|
|
2021-07-30 12:31:59 +02:00
|
|
|
# create a new object of the right skill for the utterance
|
2021-08-01 11:56:38 +02:00
|
|
|
skill = create_skill_method(skill_init_data)
|
2021-07-30 12:31:59 +02:00
|
|
|
|
|
|
|
# import and call the handler method from the skill
|
|
|
|
getattr(skill, handler_method_name)(data=data)
|
2021-07-28 19:31:47 +02:00
|
|
|
|
|
|
|
|
2021-08-03 19:05:07 +02:00
|
|
|
def train_padatious():
|
|
|
|
print("Training PADATIOUS intents models, can take a few minutes (first time) or a few seconds (startup)")
|
|
|
|
padatious_intents_container.train(timeout=120)
|
|
|
|
|
|
|
|
|
2021-08-01 11:47:16 +02:00
|
|
|
def recognise(sentence, client_ip=None, client_port=None):
|
2021-07-29 12:35:07 +02:00
|
|
|
sentence = sentence.lower()
|
|
|
|
print(sentence)
|
2021-07-28 19:31:47 +02:00
|
|
|
|
2021-08-02 11:08:19 +02:00
|
|
|
data = dict()
|
|
|
|
data['client_ip'] = client_ip
|
|
|
|
data['client_port'] = client_port
|
2021-08-02 19:07:59 +02:00
|
|
|
data['utterance'] = sentence
|
|
|
|
|
|
|
|
best_intent_adapt = get_best_intent_adapt(sentence)
|
|
|
|
best_intent_padatious = get_best_intent_padatious(sentence)
|
|
|
|
|
|
|
|
confidence_adapt = get_confidence(best_intent_adapt)
|
|
|
|
confidence_padatious = get_confidence(best_intent_padatious)
|
|
|
|
|
|
|
|
if confidence_adapt < 0.2 and confidence_padatious < 0.2:
|
2021-09-14 10:49:09 +02:00
|
|
|
|
|
|
|
# Wolfram-Alpha Fallback
|
|
|
|
wolfram_response = wa_client.ask(data['utterance'])
|
|
|
|
if wolfram_response is not None:
|
|
|
|
client_utils.speak(wolfram_response, client_ip, client_port)
|
|
|
|
return wolfram_response
|
|
|
|
else:
|
|
|
|
# Nothing found at all
|
|
|
|
return "I didn't understand..."
|
2021-08-02 19:07:59 +02:00
|
|
|
else:
|
|
|
|
return handle_intent(data,
|
|
|
|
best_intent_adapt if confidence_adapt > confidence_padatious else best_intent_padatious)
|
|
|
|
|
|
|
|
|
|
|
|
def get_confidence(intent):
|
|
|
|
if intent is None:
|
|
|
|
return 0
|
2021-08-02 11:08:19 +02:00
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
if 'confidence' in intent:
|
|
|
|
return intent['confidence']
|
|
|
|
elif hasattr(intent, 'conf'):
|
|
|
|
return intent.conf
|
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def get_best_intent_adapt(sentence):
|
2021-07-29 20:16:22 +02:00
|
|
|
if len(intents_handlers_adapt) > 0:
|
|
|
|
try:
|
|
|
|
best_intents = adapt_engine.determine_intent(sentence, 100)
|
|
|
|
best_intent = next(best_intents)
|
|
|
|
|
2021-07-30 14:10:35 +02:00
|
|
|
return best_intent
|
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
except StopIteration:
|
2021-07-30 12:31:59 +02:00
|
|
|
pass
|
2021-07-29 12:35:07 +02:00
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
return None # No match (Adapt)
|
|
|
|
|
|
|
|
|
|
|
|
def get_best_intent_padatious(sentence):
|
2021-07-29 20:16:22 +02:00
|
|
|
if len(intents_handlers_padatious) > 0:
|
|
|
|
result = padatious_intents_container.calc_intent(sentence)
|
2021-08-02 19:07:59 +02:00
|
|
|
return result
|
|
|
|
else:
|
|
|
|
return None # No match (Padatious)
|
2021-07-29 14:08:36 +02:00
|
|
|
|
2021-08-01 11:47:16 +02:00
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
def handle_intent(data, intent):
|
|
|
|
if 'intent_type' in intent:
|
|
|
|
return handle_adapt_intent(data, intent)
|
|
|
|
elif hasattr(intent, 'name'):
|
|
|
|
return handle_padatious_intent(data, intent)
|
2021-07-30 14:10:35 +02:00
|
|
|
|
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
def handle_adapt_intent(data, best_intent):
|
|
|
|
for key, val in best_intent.items():
|
|
|
|
if key != 'intent_type' and key != 'target' and key != 'confidence':
|
|
|
|
data[key] = val
|
|
|
|
handle(best_intent['intent_type'], data=data)
|
|
|
|
return best_intent
|
|
|
|
|
2021-08-01 18:26:11 +02:00
|
|
|
|
2021-08-02 19:07:59 +02:00
|
|
|
def handle_padatious_intent(data, result):
|
|
|
|
data.update(result.matches) # adding the matches from padatious to the data
|
|
|
|
handle(result.name, data)
|
|
|
|
return json.dumps(str(result))
|