コード例 #1
0
    def step(self, agent) -> Tuple[Optional[str], Any]:
        """Take immediate actions based on action dictionary and
        mark the dialogueObject as finished.

        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
        """
        try:
            # FIXME this will fail at clarifications
            self.finished = True
            memory_type = self.logical_form["upsert"]["memory_data"]["memory_type"]
            if memory_type == "REWARD":
                self.handle_reward(agent)
            elif memory_type == "SET":
                self.handle_set(agent)
            elif memory_type == "TRIPLE":
                self.handle_triple(agent)
            else:
                logging.debug(
                    "unknown memory type {} encountered in PutMemory handler".format(
                        self.logical_form
                    )
                )
        except ErrorWithResponse as err:
            self.finished = True
            Say(agent, task_data={"response_options": err.chat})
        return
コード例 #2
0
    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)
コード例 #3
0
 def handle_action(self, agent) -> Tuple[Optional[str], Any]:
     """This function handles questions about the attributes and status of
     the current action.
     """
     # no clarifications etc?  FIXME:
     self.finished = True  # noqa
     f = self.logical_form["filters"]
     F = self.subinterpret["filters"](self, self.speaker, f, get_all=True)
     mems, vals = F()
     Say(agent, task_data={"response_options": str(vals)})
コード例 #4
0
    def handle_exists(self,
                      mems: Sequence[MemoryNode]) -> Tuple[Optional[str], Any]:
        """Check if a memory exists.

        Args:
            mems: Sequence of memories

        """
        # we check the clarification because if it exists, there was a confirmation,
        # and the interpret reference object failed to find the object
        # so it does not have the proper tag.  this is an unused opportunity to learn...
        # also note if the answer is going to be no, bot will always ask.  maybe should fix this.
        clarification_query = (
            "SELECT MEMORY FROM Task WHERE reference_object_confirmation=#={}".
            format(self.memid))
        _, clarification_task_mems = self.memory.basic_search(
            clarification_query)
        if len(mems) > 0 and len(clarification_task_mems) == 0:
            Say(agent, task_data={"response_options": "yes"})
        else:
            Say(agent, task_data={"response_options": "no"})
コード例 #5
0
    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
コード例 #6
0
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
コード例 #7
0
    def handle_set(self, agent) -> Tuple[Optional[str], Any]:
        """creates a set of memories

        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"]}
        ref_objs = self.subinterpret["reference_objects"](
            self, self.speaker, ref_obj_d, extra_tags=["_physical_object"]
        )
        if len(ref_objs) == 0:
            raise ErrorWithResponse("I don't know what you're referring to")

        triples_d = self.logical_form["upsert"]["memory_data"].get("triples")
        if len(triples_d) == 1 and triples_d[0]["pred_text"] == "has_name":
            # the set has a name; check to see if one with that name exists,
            # if so add to it, else create one with that name
            name = triples_d[0]["obj_text"]
            set_memids, _ = self.memory.basic_search(
                "SELECT MEMORY FROM Set WHERE (has_name={} OR name={})".format(name, name)
            )
            if not set_memids:
                # make a new set, and name it
                set_memid = SetNode.create(self.memory)
                self.memory.add_triple(subj=set_memid, pred_text="has_name", obj_text=name)
            else:
                # FIXME, which one
                set_memid = set_memids[0]
        else:
            # an anonymous set, assuming its new, and defined to hold the triple(s)
            set_memid = SetNode.create(self.memory)
            for t in triples_d:
                self.memory.add_triple(
                    subj=set_memid, pred_text=t["pred_text"], obj_text=t["obj_text"]
                )
        for r in ref_objs:
            self.memory.add_triple(subj=r.memid, pred_text="member_of", obj=set_memid)

        # FIXME point to the objects put in the set, otherwise explain this better
        Say(agent, task_data={"response_options": "OK made those objects into a set "})
        return
コード例 #8
0
    def handle_reward(self, agent) -> Tuple[Optional[str], Any]:
        """Creates a new node of memory type : RewardNode and
        returns a confirmation.

        """
        self.finished = True
        try:
            reward_value = self.logical_form["upsert"]["memory_data"]["reward_value"]
            assert reward_value in ("POSITIVE", "NEGATIVE")
        except:
            # no subinterpreters called, etc; just fail silently if somehow this came from user...
            logging.debug(
                "unknown reward type {} encountered in PutMemory handler".format(self.logical_form)
            )
            return
        RewardNode.create(self.memory, reward_value)
        if reward_value == "POSITIVE":
            r = "Thank you!"
        else:
            r = "I'll try to do better in the future."
        Say(agent, task_data={"response_options": r})
コード例 #9
0
    def handle_fill(self, agent, speaker, d) -> Tuple[Any, Optional[str], Any]:
        """This function reads the dictionary, resolves the missing details using memory
        and perception and handles a 'fill' command by either pushing a dialogue object
        or pushing a Fill task to the task stack.

        Args:
            speaker: speaker_id or name.
            d: the complete action dictionary
        """
        tasks = []
        r = d.get("reference_object")
        if not r.get("filters"):
            r["filters"] = {"location", SPEAKERLOOK}

        # Get the reference location
        location_d = r["filters"].get("location", SPEAKERLOOK)
        mems = self.subinterpret["reference_locations"](self, speaker,
                                                        location_d)
        steps, reldir = interpret_relative_direction(self, location_d)
        location, _ = self.subinterpret["specify_locations"](self, speaker,
                                                             mems, steps,
                                                             reldir)
        """
        FIXME: We need to fix this and perhaps put this in reasoning. Agent should run perception
        and put into memory. Interpreter shouldn't be perceiving, but should be able to
        ask the agent to do it when needed.
        """
        # Get nearby holes
        perception_holes = self.get_all_holes_fn(
            agent, location, self.block_data,
            agent.low_level_data["fill_idmeta"])
        perception_output = CraftAssistPerceptionData(holes=perception_holes)
        output = self.memory.update(perception_output=perception_output)
        holes = output.get("holes", [])
        # Choose the best ones to fill
        holes = filter_by_sublocation(self, speaker, holes, r, loose=True)

        if holes is None:
            # FIXME: in stage III, replace agent with the lowlevel interface to sending chats
            raise ErrorWithResponse(
                "I don't understand what holes you want me to fill.")
        tasks = []
        for hole in holes:
            poss = list(hole.blocks.keys())
            try:
                fill_memid = agent.memory.get_triples(
                    subj=hole.memid, pred_text="has_fill_type")[0][2]
                fill_block_mem = self.memory.get_mem_by_id(fill_memid)
                fill_idm = (fill_block_mem.b, fill_block_mem.m)
            except:
                # FIXME use a constant name
                fill_idm = (3, 0)
            schematic, tags = interpret_fill_schematic(
                self,
                speaker,
                d.get("schematic", {}),
                poss,
                fill_idm,
                self.block_data,
                self.color_bid_map,
            )
            origin = np.min([xyz for (xyz, bid) in schematic], axis=0)
            task_data = {
                "blocks_list": schematic,
                "force": True,
                "origin": origin,
                "verbose": False,
                "embed": True,
                "fill_message": True,
                "schematic_tags": tags,
            }

            tasks.append(self.task_objects["build"](agent, task_data))

        if len(holes) > 1:
            Say(agent,
                task_data={"response_options": "Ok. I'll fill up the holes."})
        else:
            Say(agent,
                task_data={"response_options": "Ok. I'll fill that hole up."})

        return maybe_task_list_to_control_block(tasks, agent), None, None
コード例 #10
0
    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