First implementation of questions management

This commit is contained in:
2020-08-14 08:16:33 +02:00
parent e84b394da2
commit 351c16f946
47 changed files with 1582 additions and 400 deletions
+75 -39
View File
@@ -4,6 +4,7 @@ import time
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import NO_MATCH
from core.sheerka.services.SheerkaShortTermMemory import SheerkaShortTermMemory
from core.sheerka_logger import get_logger
from sdp.sheerkaDataProvider import Event
@@ -11,11 +12,13 @@ DEBUG_TAB_SIZE = 4
PROPERTIES_TO_SERIALIZE = ("_id",
"_bag",
"_children",
"_start",
"_stop",
"who",
"action",
"action_context",
"desc",
"children",
"inputs",
"values",
"obj",
@@ -46,16 +49,20 @@ class ExecutionContext:
desc: str = None,
logger=None,
global_hints=None,
global_errors=None,
errors=None,
**kwargs):
self._parent = None
self._id = ExecutionContext.get_id(event.get_digest()) if event else None
self._parent = None
self._children = []
self._tab = ""
self._bag = {} # context variables
self._start = 0 # when the execution starts (to measure elapsed time)
self._stop = 0 # when the execution stops (to measure elapses time)
self._logger = logger
self._format_instructions = None # how to print the execution context
self._stat_log = get_logger("stats")
self._show_stats = False
self.who = who # who is asking
self.event = event # what was the (original) trigger
@@ -63,26 +70,24 @@ class ExecutionContext:
self.action = action
self.action_context = action_context
self.desc = desc # human description of what is going on
self.children = []
self.preprocess = None
self.logger = logger
self.local_hints = set()
self.stm = False # True if the context has short term memory entries
self.private_hints = set()
self.protected_hints = set()
self.global_hints = set() if global_hints is None else global_hints
self.global_errors = [] if global_errors is None else global_errors
self.errors = [] if errors is None else errors # error are global
self.inputs = {} # what was the parameters of the execution context
self.inputs = {} # what were the parameters of the execution context
self.values = {} # what was produced by the execution context
self.obj = kwargs.pop("obj", None) # current obj we are working on
self.concepts = kwargs.pop("concepts", {}) # known concepts specific to this context
# update the other elements
for k, v in kwargs.items():
self._bag[k] = v
self.stat_log = get_logger("stats")
self.show_stats = False
@property
def elapsed(self):
if self._start == 0:
@@ -96,10 +101,22 @@ class ExecutionContext:
dt = nano_sec / 1e6
return f"{dt} ms" if dt < 1000 else f"{dt / 1000} s"
@property
def logger(self):
return self._logger
@property
def id(self):
return self._id
@property
def achildren(self):
"""
I prefixed with an 'a' to make it appear on the top when debugging
:return:
"""
return self._children
def __getattr__(self, item):
if item in self._bag:
return self._bag[item]
@@ -112,9 +129,12 @@ class ExecutionContext:
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self.stm:
self.sheerka.services[SheerkaShortTermMemory.NAME].remove_context(self)
self._stop = time.time_ns()
if self.show_stats:
self.stat_log.debug(f"[{self._id:2}]" + self._tab + "Execution time: " + self.elapsed_str)
if self._show_stats:
self._stat_log.debug(f"[{self._id:2}]" + self._tab + "Execution time: " + self.elapsed_str)
def __repr__(self):
msg = f"ExecutionContext(who={self.who}, id={self._id}, action={self.action}, context={self.action_context}"
@@ -136,7 +156,7 @@ class ExecutionContext:
return False
for prop in PROPERTIES_TO_SERIALIZE:
if prop == "who":
if prop in ("who", "action", "action_context"):
value = str(getattr(self, prop))
other_value = str(getattr(other, prop))
else:
@@ -150,7 +170,7 @@ class ExecutionContext:
def push(self, action: BuiltinConcepts, action_context, who=None, desc=None, logger=None, **kwargs):
who = who or self.who
logger = logger or self.logger
logger = logger or self._logger
_kwargs = {"obj": self.obj, "concepts": self.concepts}
_kwargs.update(self._bag)
_kwargs.update(kwargs)
@@ -163,14 +183,14 @@ class ExecutionContext:
desc,
logger,
self.global_hints,
self.global_errors,
self.errors,
**_kwargs)
new._parent = self
new._tab = self._tab + " " * DEBUG_TAB_SIZE
new.preprocess = self.preprocess
new.local_hints.update(self.local_hints)
new.protected_hints.update(self.protected_hints)
self.children.append(new)
self._children.append(new)
return new
def add_preprocess(self, name, **kwargs):
@@ -194,6 +214,23 @@ class ExecutionContext:
self.values[k] = v
return self
def add_to_short_term_memory(self, key, concept):
"""
Add a concept to the short term memory (relative to the current execution context)
:param key:
:param concept:
:return:
"""
self.sheerka.add_to_short_term_memory(self, key, concept)
def get_from_short_term_memory(self, key):
"""
:param key:
:return:
"""
return self.sheerka.get_from_short_term_memory(self, key)
def get_concept(self, key):
# search in obj
if isinstance(self.obj, Concept):
@@ -234,44 +271,43 @@ class ExecutionContext:
return self.sheerka.new(key, **kwargs)
def log_new(self):
if self.logger and not self.logger.disabled:
self.logger.debug(f"[{self._id:2}]" + self._tab + str(self))
self.show_stats = True
if self._logger and not self._logger.disabled:
self._logger.debug(f"[{self._id:2}]" + self._tab + str(self))
self._show_stats = True
def log(self, message, who=None):
if self.logger and not self.logger.disabled:
self.logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
if self._logger and not self._logger.disabled:
self._logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
def log_error(self, message, who=None, exc=None):
self.global_errors.append(exc or message)
if self.logger and not self.logger.disabled:
self.logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
self.errors.append(exc or message)
if self._logger and not self._logger.disabled:
self._logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
def log_result(self, return_values):
if not self.logger or not self.logger.isEnabledFor(logging.DEBUG):
if not self._logger or not self._logger.isEnabledFor(logging.DEBUG):
return
if len(return_values) == 0:
self.logger.debug(self._tab + "No return value")
self._logger.debug(self._tab + "No return value")
for r in return_values:
to_str = self.return_value_to_str(r)
self.logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
self._logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
def get_parent(self):
return self._parent
def in_context(self, concept_key):
if concept_key in self.local_hints:
return True
if concept_key in self.global_hints:
return True
return False
return concept_key in self.protected_hints or \
concept_key in self.global_hints or \
concept_key in self.private_hints
def in_current_context(self, concept_key):
return concept_key in self.local_hints
return concept_key in self.protected_hints or concept_key in self.private_hints
def in_private_context(self, concept_key):
return concept_key in self.private_hints
@staticmethod
def _is_return_value(obj):
@@ -336,7 +372,7 @@ class ExecutionContext:
bag["bag." + k] = v
for prop in ("id", "who", "action", "desc", "obj", "inputs", "values", "concepts"):
bag[prop] = getattr(self, prop)
bag["action"] = self.action_context
bag["context"] = self.action_context
for prop in ("desc", "obj", "inputs", "values", "concepts"):
bag[prop] = getattr(self, prop)
bag["status"] = self.get_status()