blob: ed1cf315ef1dfddd6f65dc32c5823117a131e819 [file]
import itertools
import glob
import re
from base64 import b64decode
from importlib import import_module
from app.objects.secondclass.c_relationship import Relationship
from app.objects.secondclass.c_link import update_scores
from app.service.interfaces.i_learning_svc import LearningServiceInterface
from app.utility.base_service import BaseService
class LearningService(LearningServiceInterface, BaseService):
def __init__(self):
self.log = self.add_service('learning_svc', self)
self.model = set()
self.parsers = self.add_parsers('app/learning')
self.re_variable = re.compile(r'#{(.*?)}', flags=re.DOTALL)
self.log.debug('Loaded %d parsers' % len(self.parsers))
@staticmethod
def add_parsers(directory):
parsers = []
for filepath in glob.iglob('%s/**.py' % directory):
module = import_module(filepath.replace('/', '.').replace('\\', '.').replace('.py', ''))
parsers.append(module.Parser())
return parsers
async def build_model(self):
for ability in await self.get_service('data_svc').locate('abilities'):
for executor in ability.executors:
if executor.command:
variables = frozenset(re.findall(self.re_variable, executor.test))
if len(variables) > 1: # relationships require at least 2 variables
self.model.add(variables)
self.model = set(self.model)
async def learn(self, facts, link, blob, operation=None):
decoded_blob = b64decode(blob).decode('utf-8')
found_facts = []
for parser in self.parsers:
try:
for fact in parser.parse(decoded_blob):
found_facts.append(fact)
except Exception as e:
self.log.error(e)
await update_scores(operation=None, increment=len(found_facts), used=facts, facts=link.facts)
await self._store_results(link, found_facts, operation)
async def _store_results(self, link, facts, operation=None):
facts_covered = []
for relationship in self.model:
matches = []
for fact in facts:
if fact.trait in relationship:
matches.append(fact)
facts_covered.append(fact)
for pair in itertools.combinations(matches, r=2):
if pair[0].trait != pair[1].trait:
await link.create_relationships([Relationship(source=pair[0], edge='has', target=pair[1])],
operation=operation)
for f in [x for x in facts if x not in facts_covered]:
await link.save_fact(operation=operation, fact=f, score=1, relationship=[])