def __init__(self, agent, task_data): super().__init__(agent) self.schematic = task_data["schematic"] # a list of xyz tuples self.block_idm = task_data.get("block_idm", (2, 0)) # default 2: grass self.build_task = None self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def task_stack_find_lowest_instance( self, cls_names: Union[str, Sequence[str]]) -> Optional["TaskNode"]: """Find and return the lowest item in the stack of the given class(es) Args: cls_names (Sequence): Class names of tasks Returns: TaskNode: A TaskNode object Examples :: >>> cls_names = 'Move' >>> task_stack_find_lowest_instance(cls_names) """ names = [cls_names] if type(cls_names) == str else cls_names (memid, ) = self._db_read_one( "SELECT uuid FROM Tasks WHERE {} ORDER BY created LIMIT 1".format( " OR ".join(["action_name=?" for _ in names])), *names, ) if memid is not None: return TaskNode(self, memid) else: return None
def __init__(self, agent, task_data): super().__init__(agent) self.schematic = task_data["schematic"] # list[(xyz, idm)] self.dig_message = True if "dig_message" in task_data else False self.submitted_build_task = False self.DIG_REACH = task_data.get("DIG_REACH", 3) self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent) self.object_idm = task_data["object_idm"] self.mobtype = MOBS_BY_ID[self.object_idm[1]] self.pos = task_data["pos"] self.PLACE_REACH = task_data.get("PLACE_REACH", 3) self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data={}): task_data["blocking"] = True super().__init__(agent, task_data=task_data) self.init_time = self.agent.memory.get_time() self.wait_time = task_data.get("wait_time", 800) self.awaiting_response = True self.asker_memid = task_data.get("asker_memid") TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data={}): task_data["blocking"] = True super().__init__(agent, task_data=task_data) self.question = task_data.get( "question") # chat text that will be sent to user self.task_memids = task_data.get( "task_memids") # list of Task objects, will be pushed in order self.asked = False TaskNode(agent.memory, self.memid).update_task(task=self)
def modified_step(self): if self.remove_condition.check(): self.finished = True if self.finished: TaskNode(self.agent.memory, self.memid).get_update_status({ "prio": -2, "finished": True }) return query = "SELECT MEMORY FROM Task WHERE ((prio>=1) AND (_has_parent_task=#={}))".format( self.memid) _, child_task_mems = self.agent.memory.basic_search(query) if child_task_mems: # this task has active children, step them return r = stepfn(self) TaskNode(self.agent.memory, self.memid).update_task(task=self) return
def __init__(self, agent, task_data): super().__init__(agent) self.origin = task_data["origin"] self.schematic = task_data["blocks_list"] self.destroy_task = None self.last_stepped_time = agent.memory.get_time() self.submitted_destroy = False TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent, task_data) if self.finished: return self.target = to_block_pos(np.array(task_data["target"])) self.approx = task_data.get("approx", 1) self.path = None self.replace = set() self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data={}, subcontrol="equal"): super().__init__(agent, task_data) # movement should be a Movement object from dance.py assert hasattr(self.agent, "swarm_workers") self.num_agents = self.agent.num_agents self.last_stepped_time = agent.memory.get_time() # self.swarm_worker_tasks = [] self.distribute(task_data) TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent, task_data={}) response_options = task_data.get("response_options") if not response_options: raise ValueError("Cannot init a Say with no response options") if type(response_options) is str: self.response_options = [response_options] else: self.response_options = response_options TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent) self.idm = task_data["idm"] self.pos = task_data["pos"] self.eid = task_data["eid"] self.obj_memid = task_data["obj_memid"] self.approx = 1 self.attempts = 10 self.item_count_before_get = agent.get_inventory_item_count( self.idm[0], self.idm[1]) TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super(DanceMove, self).__init__(agent) self.relative_yaw = task_data.get("relative_yaw") self.relative_pitch = task_data.get("relative_pitch") # look_turn is (yaw, pitch). pitch = 0 is head flat self.head_yaw_pitch = task_data.get("head_yaw_pitch") self.head_xyz = task_data.get("head_xyz") self.translate = task_data.get("translate") self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def come_to_player(agent): """Go to where the player is.""" op = agent.get_other_players() if len(op) == 0: return p = random.choice(agent.get_other_players()) TaskNode( agent.memory, tasks.Move(agent, { "target": pos_to_np(p.pos), "approx": 3 }).memid)
def __init__(self, agent, task_data={}): task_data["blocking"] = True super().__init__(agent, task_data=task_data) r = task_data.get("reference_object") if hasattr(r, "get_point_at_target"): self.bounds = r.get_point_at_target() else: # this should be an error self.bounds = tuple(np.min(r, axis=0)) + tuple(np.max(r, axis=0)) self.pointed = False self.asked = False TaskNode(agent.memory, self.memid).update_task(task=self)
def append(self, task): if self.prev is not None: prev_finished = TaskStatusCondition(self.agent.memory, self.prev.memid, status="finished") cdict = { "init_condition": AndCondition(self.agent.memory, [task.init_condition, prev_finished]) } TaskNode(self.agent.memory, task.memid).update_condition(cdict) else: self.fuse = SwitchCondition(self.agent.memory) cdict = { "init_condition": AndCondition(self.agent.memory, [task.init_condition, self.fuse]) } TaskNode(self.agent.memory, task.memid).update_condition(cdict) self.fuse.set_status(False) self.prev = task self.task_list.append(task)
def step(self): """Ask a confirmation question and wait for response.""" # Step 1: ask the question if not self.asked: task_list = [ Say(self.agent, {"response_options": self.question}), AwaitResponse(self.agent, {"asker_memid": self.memid}), ] self.add_child_task( maybe_task_list_to_control_block(task_list, self.agent)) self.asked = True return # Step 2: check the response and add the task if necessary self.finished = True # FIXME: change this to sqly when syntax for obj searches is settled: # search for a response to the confirmation question, which will be a triple # (self.memid, "dialogue_task_reponse", chat_memid) t = self.agent.memory.get_triples(subj=self.memid, pred_text="dialogue_task_response") if not t: return chat_mems = [ self.agent.memory.get_mem_by_id(triples[2]) for triples in t ] if any([c.chat_text in MAP_YES for c in chat_mems]): for m in self.task_memids: # activate TaskNode(self.agent.memory, m).get_update_status({ "prio": 1, "paused": 0 }) else: for m in self.task_memids: # mark tasks as finished TaskNode(self.agent.memory, m).get_update_status({"prio": -2}) return
def task_stack_push(self, task, parent_memid: str = None, chat_effect: bool = False) -> "TaskNode": """Create a task object in memory, add triples and add to task stack Args: task (Task): The task to be pushed parent_memid (string): Memory ID of the task's parent chat_effect (bool): If the task was a result of a chat, add the triple. Returns: TaskNode: A TaskNode object Examples :: >>> task = Move(agent, {"target": pos_to_np([0, 0 , 0]), "approx" : 3}) >>> parent_memid = '10517cc584844659907ccfa6161e9d32' >>> task_stack_push(task, parent_memid) """ memid = TaskNode.create(self, task) # Relations if parent_memid: self.add_triple(subj=memid, pred_text="_has_parent_task", obj=parent_memid) if chat_effect: chat = self.get_most_recent_incoming_chat() assert chat is not None, "chat_effect=True with no incoming chats" self.add_triple(subj=chat.memid, pred_text="chat_effect_", obj=memid) # Return newly created object return TaskNode(self, memid)
def build_random_shape(agent, shape_util_dict, rand_range=(10, 0, 10), no_chat=False): """Pick a random shape from shapes.py and build that""" target_loc = agent.pos for i in range(3): target_loc[i] += np.random.randint(-rand_range[i], rand_range[i] + 1) shape = random.choice(shape_util_dict["shape_names"]) opts = shape_util_dict["shape_option_fn_map"][shape]() opts["bid"] = shape_util_dict["bid"] schematic = shape_util_dict["shape_fns"][shape](**opts) relations = [ { "pred": "has_name", "obj": shape.lower() }, { "pred": "has_tag", "obj": shape.lower() }, ] task_data = { "blocks_list": schematic, "origin": target_loc, "verbose": False, "schematic_tags": relations, "default_behavior": "build_random_shape", # must == function name. Hacky and I hate it. } logging.debug("Default behavior: building {}".format(shape)) TaskNode(agent.memory, tasks.Build(agent, task_data).memid) if not no_chat: shape_name = prepend_a_an(shape.lower()) # FIXME agent , also don't push directly to stack, ask the manager? Say( agent, task_data={ "response_options": "I am building {} while you decide what you want me to do!". format(shape_name) }, ) return schematic
def handle_triple(self, agent) -> Tuple[Optional[str], Any]: """Writes a triple of type : (subject, predicate_text, object_text) to the memory and returns a confirmation. Returns: output_chat: An optional string for when the agent wants to send a chat step_data: Any other data that this step would like to send to the task """ ref_obj_d = {"filters": self.logical_form["filters"]} r = self.subinterpret["reference_objects"]( self, self.speaker, ref_obj_d, extra_tags=["_physical_object"] ) if len(r) == 0: raise ErrorWithResponse("I don't know what you're referring to") mem = r[0] name = "it" triples = self.memory.get_triples(subj=mem.memid, pred_text="has_tag") if len(triples) > 0: name = triples[0][2].strip("_") schematic_memid = ( self.memory.convert_block_object_to_schematic(mem.memid).memid if isinstance(mem, VoxelObjectNode) and len(mem.blocks) > 0 else None ) for t in self.logical_form["upsert"]["memory_data"].get("triples", []): if t.get("pred_text") and t.get("obj_text"): logging.debug("Tagging {} {} {}".format(mem.memid, t["pred_text"], t["obj_text"])) self.memory.add_triple( subj=mem.memid, pred_text=t["pred_text"], obj_text=t["obj_text"] ) if schematic_memid: self.memory.add_triple( subj=schematic_memid, pred_text=t["pred_text"], obj_text=t["obj_text"] ) point_at_target = mem.get_point_at_target() # FIXME agent : This is the only place in file using the agent from the .step() task = self.task_objects["point"](agent, {"target": point_at_target}) # FIXME? higher pri, make sure this runs now...? TaskNode(self.memory, task.memid) r = "OK I'm tagging this %r as %r %r " % (name, t["pred_text"], t["obj_text"]) Say(agent, task_data={"response_options": r}) return
def do_answer(self, agent, mems: Sequence[Any], vals: Sequence[Any]) -> Tuple[Optional[str], Any]: """This function uses the action dictionary and memory state to return an answer. Args: mems: Sequence of memories vals: Sequence of values Returns: output_chat: An optional string for when the agent wants to send a chat step_data: Any other data that this step would like to send to the task """ self.finished = True # noqa output_type = self.output_type try: if type(output_type) is str and output_type.lower() == "count": # FIXME will multiple count if getting tags if not any(vals): Say(agent, task_data={"response_options": "none"}) Say(agent, task_data={"response_options": str(vals[0])}) elif type(output_type) is dict and output_type.get("attribute"): attrib = output_type["attribute"] if type(attrib) is str and attrib.lower() == "location": # add a Point task if attribute is a location if self.subinterpret.get( "point_target") and self.task_objects.get("point"): target = self.subinterpret[ "point_target"].point_to_region(vals[0]) # FIXME agent : This is the only place in file using the agent from the .step() t = self.task_objects["point"](agent, { "target": target }) # FIXME? higher pri, make sure this runs now...? TaskNode(self.memory, t.memid) Say(agent, task_data={"response_options": str(vals)}) elif type(output_type) is str and output_type.lower() == "memory": self.handle_exists(mems) else: raise ValueError("Bad answer_type={}".format(output_type)) except IndexError: # index error indicates no answer available logging.error("No answer available from do_answer") raise ErrorWithResponse("I don't understand what you're asking") except Exception as e: logging.exception(e)
def task_stack_peek(self) -> Optional["TaskNode"]: """Return the top of task stack Returns: TaskNode: TaskNode object or None Examples :: >>> task_stack_peek() """ r = self._db_read_one(""" SELECT uuid FROM Tasks WHERE finished < 0 AND paused = 0 AND prio > 0 ORDER BY created DESC LIMIT 1 """) if r: return TaskNode(self, r[0]) else: return None
def get_last_finished_root_task(self, action_name: str = None, recency: int = None): """Get last task that was marked as finished Args: action_name (string): Name of action associated with task recency (int): How recent should the task be Returns: TaskNode: A TaskNode object Examples :: >>> action_name = "BUILD" >>> get_last_finished_root_task (action_name=action_name) """ q = """ SELECT uuid FROM Tasks WHERE finished >= ? {} ORDER BY created DESC """.format(" AND action_name=?" if action_name else "") if recency is None: recency = self.time.round_time(300) args: List = [max(self.get_time() - recency, 0)] if action_name: args.append(action_name) memids = [r[0] for r in self._db_read(q, *args)] for memid in memids: if self._db_read_one( "SELECT uuid FROM Triples WHERE pred_text='_has_parent_task' AND subj=?", memid): # not a root task continue return TaskNode(self, memid)
def __init__(self, agent, task_data={}, memid=None): self.agent = agent self.run_count = 0 self.interrupted = False self.finished = False self.name = None self.undone = False self.last_stepped_time = None if memid: self.memid = memid N = TaskNode(agent.memory, self.memid).update_task(task=self) # this is an egg, hatch it if N.prio == -3: N.get_update_status({"prio": -1}) else: TaskNode.create(self.agent.memory, self) # remember to get children of blocking tasks (and delete this comment) if task_data.get("blocking"): TripleNode.create(self.agent.memory, subj=self.memid, pred_text="has_tag", obj_text="blocking_task") # TODO put these in memory in a new table? # TODO methods for safely changing these i, s, ru, re = self.get_default_conditions(task_data, agent) self.init_condition = i self.stop_condition = s self.run_condition = ru self.remove_condition = re TripleNode.create( self.agent.memory, subj=self.memid, pred_text="has_name", obj_text=self.__class__.__name__.lower(), ) TaskNode(agent.memory, self.memid).update_task(task=self)
def step(self, agent) -> Tuple[Optional[str], Any]: start_time = datetime.datetime.now() assert self.logical_form["dialogue_type"] == "HUMAN_GIVE_COMMAND" try: actions = [] if "action" in self.logical_form: actions.append(self.logical_form["action"]) elif "action_sequence" in self.logical_form: actions = self.logical_form["action_sequence"] if len(actions) == 0: # The action dict is in an unexpected state raise ErrorWithResponse( "I thought you wanted me to do something, but now I don't know what" ) tasks_to_push = [] for action_def in actions: action_type = action_def["action_type"] # FIXME!: THIS IS A HACK to be removed by dec2021: # special case to push loops into the handlers if # there is only one action in the sequence but # there is a control structure around the sequence: if len(actions) == 1 and self.logical_form.get( "remove_condition") is not None: action_def = deepcopy(action_def) action_def["remove_condition"] = deepcopy( self.logical_form.get("remove_condition")) r = self.action_handlers[action_type](agent, self.speaker, action_def) if len(r) == 3: task, response, dialogue_data = r else: # FIXME don't use this branch, uniformize the signatures task = None response, dialogue_data = r if task: tasks_to_push.append(task) task_mem = None if tasks_to_push: T = maybe_task_list_to_control_block(tasks_to_push, agent) # task_mem = TaskNode(self.memory, tasks_to_push[0].memid) task_mem = TaskNode(self.memory, T.memid) if task_mem: chat = self.memory.get_most_recent_incoming_chat() TripleNode.create(self.memory, subj=chat.memid, pred_text="chat_effect_", obj=task_mem.memid) self.finished = True end_time = datetime.datetime.now() hook_data = { "name": "interpreter", "start_time": start_time, "end_time": end_time, "elapsed_time": (end_time - start_time).total_seconds(), "agent_time": self.memory.get_time(), "tasks_to_push": tasks_to_push, "task_mem": task_mem, } dispatch.send("interpreter", data=hook_data) except NextDialogueStep: return except ErrorWithResponse as err: Say(agent, task_data={"response_options": err.chat}) self.finished = True return
def __init__(self, agent, task_data): super().__init__(agent) self.eid = task_data["eid"] self.idm = task_data["idm"] self.obj_memid = task_data["obj_memid"] TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super(Point, self).__init__(agent) self.target = task_data.get("target") self.start_time = agent.memory.get_time() self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent) self.task_data = task_data self.embed = task_data.get("embed", False) self.schematic, _ = blocks_list_to_npy(task_data["blocks_list"]) self.origin = task_data["origin"] self.verbose = task_data.get("verbose", True) self.relations = task_data.get("relations", []) self.default_behavior = task_data.get("default_behavior") self.force = task_data.get("force", False) self.attempts = 3 * np.ones(self.schematic.shape[:3], dtype=np.uint8) self.fill_message = task_data.get("fill_message", False) self.schematic_memid = task_data.get("schematic_memid", None) self.schematic_tags = task_data.get("schematic_tags", []) self.giving_up_message_sent = False self.wait = False self.old_blocks_list = None self.old_origin = None self.PLACE_REACH = task_data.get("PLACE_REACH", 3) # negative schematic related self.is_destroy_schm = task_data.get("is_destroy_schm", False) self.dig_message = task_data.get("dig_message", False) self.blockobj_memid = None self.DIG_REACH = task_data.get("DIG_REACH", 3) self.last_stepped_time = agent.memory.get_time() if self.is_destroy_schm: # is it destroying a whole block object? if so, save its tags self.destroyed_block_object_triples = [] xyzs = set(strip_idmeta(task_data["blocks_list"])) mem = agent.memory.get_block_object_by_xyz(next(iter(xyzs))) # TODO what if there are several objects being destroyed? if mem and all(xyz in xyzs for xyz in mem.blocks.keys()): for pred in ["has_tag", "has_name", "has_colour"]: self.destroyed_block_object_triples.extend( agent.memory.get_triples(subj=mem.memid, pred_text=pred)) logging.debug("Destroying block object {} tags={}".format( mem.memid, self.destroyed_block_object_triples)) # modify the schematic to avoid placing certain blocks for bad, good in BUILD_BLOCK_REPLACE_MAP.items(): self.schematic[self.schematic[:, :, :, 0] == bad] = good self.new_blocks = [] # a list of (xyz, idm) of newly placed blocks # snap origin to ground if bottom level has dirt blocks # NOTE(kavyasrinet): except for when we are rebuilding the old dirt blocks, we # don't want to change the origin then, hence the self.force check. if not self.force and not self.embed and np.isin( self.schematic[:, :, :, 0], (2, 3)).any(): h = ground_height(agent, self.origin, 0) self.origin[1] = h[0, 0] # get blocks occupying build area and save state for undo() ox, oy, oz = self.origin sy, sz, sx, _ = self.schematic.shape current = agent.get_blocks(ox, ox + sx - 1, oy, oy + sy - 1, oz, oz + sz - 1) self.old_blocks_list = npy_to_blocks_list(current, self.origin) if len(self.old_blocks_list) > 0: self.old_origin = np.min(strip_idmeta(self.old_blocks_list), axis=0) TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent) # movement should be a Movement object from dance.py self.movement = task_data.get("movement") self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)
def __init__(self, agent, task_data): super().__init__(agent) self.to_undo_memid = task_data["memid"] self.last_stepped_time = agent.memory.get_time() TaskNode(agent.memory, self.memid).update_task(task=self)