def decode(self, obj: bytes) -> Message: """ Decode the message. :param obj: the bytes object :return: the message """ json_msg = json.loads(obj.decode("utf-8")) performative = GymMessage.Performative(json_msg["performative"]) new_body = copy.copy(json_msg) new_body["performative"] = performative if performative == GymMessage.Performative.ACT: action_bytes = base64.b64decode(json_msg["action"]) action = pickle.loads(action_bytes) # nosec new_body["action"] = action new_body["step_id"] = json_msg["step_id"] elif performative == GymMessage.Performative.PERCEPT: # observation, reward and info are gym implementation specific, done is boolean observation_bytes = base64.b64decode(json_msg["observation"]) observation = pickle.loads(observation_bytes) # nosec new_body["observation"] = observation reward_bytes = base64.b64decode(json_msg["reward"]) reward = pickle.loads(reward_bytes) # nosec new_body["reward"] = reward info_bytes = base64.b64decode(json_msg["info"]) info = pickle.loads(info_bytes) # nosec new_body["info"] = info new_body["step_id"] = json_msg["step_id"] gym_message = GymMessage(performative=performative, body=new_body) return gym_message
def _decode_percept(self, envelope: Envelope, expected_step_id: int) -> Message: """ Receive the response from the gym environment in the form of an envelope and decode it. The response is a PERCEPT message containing the usual 'observation', 'reward', 'done', 'info' parameters. :param expected_step_id: the expected step id :return: a message received as a response to the action performed in apply_action. """ if envelope is not None: if envelope.protocol_id == PublicId.from_str("fetchai/gym:0.1.0"): gym_msg = GymSerializer().decode(envelope.message) gym_msg_performative = GymMessage.Performative( gym_msg.get("performative")) gym_msg_step_id = gym_msg.get("step_id") if (gym_msg_performative == GymMessage.Performative.PERCEPT and gym_msg_step_id == expected_step_id): return gym_msg else: raise ValueError( "Unexpected performative or no step_id: {}".format( gym_msg_performative)) else: raise ValueError("Unknown protocol_id: {}".format( envelope.protocol_id)) else: raise ValueError("Missing envelope.")
def decode(obj: bytes) -> Message: """ Decode bytes into a 'Gym' message. :param obj: the bytes object. :return: the 'Gym' message. """ message_pb = ProtobufMessage() gym_pb = gym_pb2.GymMessage() message_pb.ParseFromString(obj) message_id = message_pb.dialogue_message.message_id dialogue_reference = ( message_pb.dialogue_message.dialogue_starter_reference, message_pb.dialogue_message.dialogue_responder_reference, ) target = message_pb.dialogue_message.target gym_pb.ParseFromString(message_pb.dialogue_message.content) performative = gym_pb.WhichOneof("performative") performative_id = GymMessage.Performative(str(performative)) performative_content = dict() # type: Dict[str, Any] if performative_id == GymMessage.Performative.ACT: pb2_action = gym_pb.act.action action = AnyObject.decode(pb2_action) performative_content["action"] = action step_id = gym_pb.act.step_id performative_content["step_id"] = step_id elif performative_id == GymMessage.Performative.PERCEPT: step_id = gym_pb.percept.step_id performative_content["step_id"] = step_id pb2_observation = gym_pb.percept.observation observation = AnyObject.decode(pb2_observation) performative_content["observation"] = observation reward = gym_pb.percept.reward performative_content["reward"] = reward done = gym_pb.percept.done performative_content["done"] = done pb2_info = gym_pb.percept.info info = AnyObject.decode(pb2_info) performative_content["info"] = info elif performative_id == GymMessage.Performative.STATUS: content = gym_pb.status.content content_dict = dict(content) performative_content["content"] = content_dict elif performative_id == GymMessage.Performative.RESET: pass elif performative_id == GymMessage.Performative.CLOSE: pass else: raise ValueError( "Performative not valid: {}.".format(performative_id)) return GymMessage(message_id=message_id, dialogue_reference=dialogue_reference, target=target, performative=performative, **performative_content)
def handle_gym_message(self, envelope: Envelope) -> None: """ Forward a message to gym. :param envelope: the envelope :return: None """ gym_message = GymSerializer().decode(envelope.message) performative = gym_message.get("performative") if GymMessage.Performative( performative) == GymMessage.Performative.ACT: action = gym_message.get("action") step_id = gym_message.get("step_id") observation, reward, done, info = self.gym_env.step( action) # type: ignore msg = GymMessage( performative=GymMessage.Performative.PERCEPT, observation=observation, reward=reward, done=done, info=info, step_id=step_id, ) msg_bytes = GymSerializer().encode(msg) envelope = Envelope( to=envelope.sender, sender=DEFAULT_GYM, protocol_id=GymMessage.protocol_id, message=msg_bytes, ) self._send(envelope) elif GymMessage.Performative( performative) == GymMessage.Performative.RESET: self.gym_env.reset() # type: ignore elif GymMessage.Performative( performative) == GymMessage.Performative.CLOSE: self.gym_env.close() # type: ignore