Exemple #1
0
    def setup_socket(self):
        """
        Set up socket to start communicating to workers.
        """
        if self.bypass_server_setup:
            return

        log_utils.print_and_log(logging.INFO,
                                'Local: Setting up WebSocket...',
                                should_print=True)

        self.app_token = self.get_app_token()

        # Set up receive
        socket_use_url = self.server_url
        if self.opt['local']:  # skip some hops for local stuff
            socket_use_url = 'https://localhost'
        # socket_use_url = 'https://localhost:8399/api/ws'
        socket_use_url = 'https://michinai.cf/api/ws'
        # socket_use_url = 'https://d4008293ad0.ngrok.io/api/ws'
        # socket_use_url = 'https://jig7357-parlai-messenger-chatb.herokuapp.com/webhook'
        self.port = 8399

        self.socket = ChatServiceMessageSocket(socket_use_url, self.port,
                                               self._handle_webhook_event)
        self.sender = MessageSender(self.app_token, self.socket)
        log_utils.print_and_log(logging.INFO,
                                'done with websocket',
                                should_print=True)
 def send_fb_message(
     self, receiver_id, message, is_response, quick_replies=None, persona_id=None
 ):
     """
     Sends a message directly to messenger.
     """
     api_address = f'https://graph.facebook.com/{API_VERSION}/me/messages'
     if quick_replies is not None:
         quick_replies = [create_reply_option(x, x) for x in quick_replies]
     ms = create_text_message(message, quick_replies)
     results = []
     for m in ms:
         if m['text'] == '':
             continue  # Skip blank messages
         payload = {
             "messaging_type": 'RESPONSE' if is_response else 'UPDATE',
             "recipient": {"id": receiver_id},
             "message": m,
         }
         if persona_id is not None:
             payload['persona_id'] = persona_id
         response = requests.post(api_address, params=self.auth_args, json=payload)
         result = response.json()
         if 'error' in result:
             if result['error']['code'] == 1200:
                 # temporary error please retry
                 response = requests.post(
                     api_address, params=self.auth_args, json=payload
                 )
                 result = response.json()
         log_utils.print_and_log(
             logging.INFO, '"Facebook response from message send: {}"'.format(result)
         )
         results.append(result)
     return results
Exemple #3
0
        def _world_function():
            world_generator = utils.get_world_fn_attr(self._world_module,
                                                      overworld_name,
                                                      "generate_world")
            overworld = world_generator(self.opt, [overworld_agent])
            while not overworld.episode_done() and not self.system_done:
                world_type = overworld.parley()
                if world_type is None:
                    time.sleep(0.5)
                    continue

                if world_type == self.manager.EXIT_STR:
                    self.manager._remove_agent(overworld_agent.id)
                    return world_type

                # perform onboarding
                onboard_type = onboard_map.get(world_type)
                if onboard_type:
                    onboard_id = 'onboard-{}-{}'.format(
                        overworld_agent.id, time.time())
                    agent = self.manager._create_agent(onboard_id,
                                                       overworld_agent.id)
                    agent.data = overworld_agent.data
                    agent_state.set_active_agent(agent)
                    agent_state.assign_agent_to_task(agent, onboard_id)
                    _, onboard_data = self._run_world(task, onboard_type,
                                                      [agent])
                    agent_state.onboard_data = onboard_data
                    agent_state.data = agent.data
                self.manager.add_agent_to_pool(agent_state, world_type)
                log_utils.print_and_log(logging.INFO,
                                        'onboarding/overworld complete')

            return world_type
Exemple #4
0
 def on_disconnect(*args):
     """
     Disconnect event is a no-op for us, as the server reconnects automatically
     on a retry.
     """
     log_utils.print_and_log(
         logging.INFO, 'World server disconnected: {}'.format(args))
     self.alive = False
     self._ensure_closed()
Exemple #5
0
 def _log_missing_agent(self, agent_id, assignment_id):
     """
     Log the occurence of a missing agent.
     """
     log_utils.print_and_log(
         logging.WARN,
         'Expected to have an agent for {}_{}, yet none was found'.format(
             agent_id, assignment_id),
     )
Exemple #6
0
 def upload_fb_attachment(self, payload):
     """
     Uploads an attachment using the Attachment Upload API and returns an attachment
     ID.
     """
     api_address = f'https://graph.facebook.com/{API_VERSION}/me/message_attachments'
     assert payload['type'] in [
         'image',
         'video',
         'file',
         'audio',
     ], 'unsupported attachment type'
     if 'url' in payload:
         message = {
             "message": {
                 "attachment": {
                     "type": payload['type'],
                     "payload": {
                         "is_reusable": "true",
                         "url": payload['url']
                     },
                 }
             }
         }
         response = requests.post(api_address,
                                  params=self.auth_args,
                                  json=message)
     elif 'filename' in payload:
         message = {
             "attachment": {
                 "type": payload['type'],
                 "payload": {
                     "is_reusable": "true"
                 },
             }
         }
         with open(payload['filename'], 'rb') as f:
             filedata = {
                 "filedata": (
                     payload['filename'],
                     f,
                     payload['type'] + '/' + payload['format'],
                 )
             }
             response = requests.post(
                 api_address,
                 params=self.auth_args,
                 data={"message": json.dumps(message)},
                 files=filedata,
             )
     result = response.json()
     log_utils.print_and_log(
         logging.INFO,
         '"Facebook response from attachment upload: {}"'.format(result),
     )
     return result
 def _done_callback(fut):
     e = fut.exception()
     if e is not None:
         log_utils.print_and_log(
             logging.ERROR,
             'World {} had error {}'.format(task_id, repr(e)),
             should_print=True,
         )
         traceback.print_exc(file=sys.stdout)
         if self.debug:
             raise e
Exemple #8
0
 def delete_persona(self, persona_id):
     """
     Deletes the persona.
     """
     api_address = 'https://graph.facebook.com/' + persona_id
     response = requests.delete(api_address, params=self.auth_args)
     result = response.json()
     log_utils.print_and_log(
         logging.INFO,
         '"Facebook response from delete persona: {}"'.format(result))
     return result
Exemple #9
0
 def create_persona(self, name, image_url):
     """
     Creates a new persona and returns persona_id.
     """
     api_address = 'https://graph.facebook.com/me/personas'
     message = {'name': name, "profile_picture_url": image_url}
     response = requests.post(api_address, params=self.auth_args, json=message)
     result = response.json()
     log_utils.print_and_log(
         logging.INFO, '"Facebook response from create persona: {}"'.format(result)
     )
     return result
Exemple #10
0
 def wrapper(self, *args, **kwargs):
     response = function(self, *args, **kwargs).json()
     if response['ok']:
         if 'description' in response:
             log_utils.print_and_log(
                 logging.INFO,
                 f"Telegram API response: {response['description']}",
                 should_print=True
             )
         return response['result']
     else:
         raise Exception(response['description'])
Exemple #11
0
    def send_fb_message(self,
                        receiver_id,
                        message,
                        is_response,
                        quick_replies=None,
                        persona_id=None):
        """
        Sends a message directly to messenger.
        """
        # api_address = f'https://graph.facebook.com/{API_VERSION}/me/messages'
        # if quick_replies is not None:
        #     quick_replies = [create_reply_option(x, x) for x in quick_replies]
        # ms = create_text_message(message, quick_replies)

        results = []

        if message == '':
            return
        payload = {
            "message_type": 'RESPONSE' if is_response else 'UPDATE',
            "recipient": receiver_id,
            "text": message,
        }
        # if persona_id is not None:
        #     payload['persona_id'] = persona_id
        # response = requests.post(api_address, params=self.auth_args, json=payload)
        # self.socket._safe_send(json.dumps(payload))
        # print(requests.post("http://localhost:8399/api/test", json=payload).text)
        print(requests.post("https://michinai.cf/api/test", json=payload).text)
        # print(requests.post("http://d4008293ad0.ngrok.io/api/ws", json=payload).text)

        print('sended ressult : ', payload)
        # result = response.json()
        import random
        result = {
            'recipient_id': receiver_id,
            'message_id': str(random.random())
        }
        # if 'error' in result:
        #     if result['error']['code'] == 1200:
        #         # temporary error please retry
        #         response = requests.post(
        #             api_address, params=self.auth_args, json=payload
        #         )
        #         result = response.json()
        log_utils.print_and_log(
            logging.INFO,
            '"Facebook response from message send: {}"'.format(result))
        results.append(result)

        return results
Exemple #12
0
 def on_message(*args):
     """
     Incoming message handler for messages from the FB user.
     """
     packet_dict = json.loads(args[1])
     if packet_dict['type'] == 'conn_success':
         self.alive = True
         return  # No action for successful connection
     if packet_dict['type'] == 'pong':
         self.last_pong = time.time()
         return  # No further action for pongs
     message_data = packet_dict['content']
     log_utils.print_and_log(logging.DEBUG,
                             f'Message data received: {message_data}')
     self.message_callback(message_data)
    def setup_server(self):
        """
        Prepare the Messenger server for handling messages.
        """
        if self.bypass_server_setup:
            return

        log_utils.print_and_log(
            logging.INFO,
            '\nYou are going to allow people on Facebook to be agents in '
            'ParlAI.\nDuring this process, Internet connection is required, '
            'and you should turn off your computer\'s auto-sleep '
            'feature.\n',
            should_print=True,
        )
        input('Please press Enter to continue... ')
        log_utils.print_and_log(logging.NOTSET, '', True)

        if self.opt['local'] is True:
            log_utils.print_and_log(
                logging.INFO,
                'In order to run the server locally, you will need '
                'to have a public HTTPS endpoint (SSL signed) running on '
                'the server you are currently excecuting ParlAI on. Enter '
                'that public URL hostname when prompted and ensure that the '
                'port being used by ParlAI (usually 3000) has external '
                'traffic routed to it.',
                should_print=True,
            )
            input('Please press Enter to continue... ')

        log_utils.print_and_log(
            logging.INFO, 'Setting up Messenger webhook...', should_print=True
        )

        # Setup the server with a task name related to the current task
        task_name = '{}-{}'.format('ParlAI-Messenger', self.opt['task'])
        self.server_task_name = ''.join(
            e for e in task_name.lower() if e.isalnum() or e == '-'
        )
        self.server_url = server_utils.setup_server(
            self.server_task_name, local=self.opt['local']
        )
        log_utils.print_and_log(
            logging.INFO,
            'Webhook address: {}/webhook'.format(self.server_url),
            should_print=True,
        )
    def shutdown(self):
        """
        Handle any client shutdown cleanup.
        """
        try:
            self.is_running = False
            self.world_runner.shutdown()
            if not self.bypass_server_setup:
                self.socket.keep_running = False
            self._expire_all_conversations()
        except BaseException as e:
            log_utils.print_and_log(logging.ERROR, f'world ended in error: {e}')

        finally:
            if not self.bypass_server_setup:
                server_utils.delete_server(self.server_task_name, self.opt['local'])
Exemple #15
0
    def send_fb_payload(self,
                        receiver_id,
                        payload,
                        quick_replies=None,
                        persona_id=None):
        """
        Sends a payload to messenger, processes it if we can.
        """
        api_address = f'https://graph.facebook.com/{API_VERSION}/me/messages'
        if payload['type'] == 'list':
            data = create_compact_list_message(payload['data'])
        elif payload['type'] in ['image', 'video', 'file', 'audio']:
            data = create_attachment(payload)
        else:
            data = payload['data']

        message = {
            "messaging_type": 'RESPONSE',
            "recipient": {
                "id": receiver_id
            },
            "message": {
                "attachment": data
            },
        }
        if quick_replies is not None:
            quick_replies = [create_reply_option(x, x) for x in quick_replies]
            message['message']['quick_replies'] = quick_replies
        if persona_id is not None:
            payload['persona_id'] = persona_id
        response = requests.post(api_address,
                                 params=self.auth_args,
                                 json=message)
        result = response.json()
        if 'error' in result:
            if result['error']['code'] == 1200:
                # temporary error please retry
                response = requests.post(api_address,
                                         params=self.auth_args,
                                         json=message)
                result = response.json()
        log_utils.print_and_log(
            logging.INFO,
            '"Facebook response from message send: {}"'.format(result))
        return result
Exemple #16
0
 def on_error(ws, error):
     try:
         if error.errno == errno.ECONNREFUSED:
             self._ensure_closed()
             self.use_socket = False
             raise Exception("Socket refused connection, cancelling")
         else:
             log_utils.print_and_log(
                 logging.WARN,
                 'Socket logged error: {}'.format(repr(error)))
     except BaseException:
         if type(error) is websocket.WebSocketConnectionClosedException:
             return  # Connection closed is noop
         log_utils.print_and_log(
             logging.WARN,
             'Socket logged error: {} Restarting'.format(repr(error)),
         )
         self._ensure_closed()
Exemple #17
0
 def run_socket(*args):
     url_base_name = self.server_url.split('https://')[1]
     while self.keep_running:
         try:
             sock_addr = "wss://{}/".format(url_base_name)
             self.ws = websocket.WebSocketApp(
                 sock_addr,
                 on_message=on_message,
                 on_error=on_error,
                 on_close=on_disconnect,
             )
             self.ws.on_open = on_socket_open
             self.ws.run_forever(ping_interval=1, ping_timeout=0.9)
         except Exception as e:
             log_utils.print_and_log(
                 logging.WARN,
                 'Socket error {}, attempting restart'.format(repr(e)),
             )
         time.sleep(0.2)
Exemple #18
0
    def setup_server(self):
        """
        Prepare the Telegram server for handling messages.
        """
        if self.bypass_server_setup:
            return

        log_utils.print_and_log(
            logging.INFO,
            '\nYou are going to allow people on Telegram to be agents in '
            'ParlAI.\nDuring this process, Internet connection is required, '
            'and you should turn off your computer\'s auto-sleep '
            'feature.\n',
            should_print=True,
        )
        input('Please press Enter to continue... ')

        log_utils.print_and_log(
            logging.INFO, 'Setting up Telegram webhook...', should_print=True
        )

        # Setup the server with a task name related to the current task
        task_name = f'ParlAI-Telegram-{self.opt["task"]}'
        self.server_task_name = ''.join(
            ch for ch in task_name.lower() if ch.isalnum() or ch == '-'
        )
        self.server_url = server_utils.setup_server(self.server_task_name, self.opt['local'])
        log_utils.print_and_log(
            logging.INFO,
            f'Webhook address: {self.server_url}/webhook',
            should_print=True,
        )
    def setup_socket(self):
        """
        Set up socket to start communicating to workers.
        """
        if self.bypass_server_setup:
            return

        log_utils.print_and_log(
            logging.INFO, 'Local: Setting up WebSocket...', should_print=True
        )

        self.app_token = self.get_app_token()
        self.sender = MessageSender(self.app_token)

        # Set up receive
        socket_use_url = self.server_url
        if self.opt['local']:  # skip some hops for local stuff
            socket_use_url = 'https://localhost'
        self.socket = ChatServiceMessageSocket(
            socket_use_url, self.port, self._handle_webhook_event
        )
        log_utils.print_and_log(logging.INFO, 'done with websocket', should_print=True)
Exemple #20
0
        def _done_callback(fut):
            """
            Log and raise exception of task world, if there is one.

            Additionally, set active agent to overworld agent.
            """
            e = fut.exception()
            if e is not None:
                log_utils.print_and_log(
                    logging.ERROR,
                    'World {} had error {}'.format(world_type, repr(e)),
                    should_print=True,
                )
                traceback.print_exc(file=sys.stdout)
                for agent in agents:
                    self.observe_message(
                        agent.id,
                        'Sorry, this world closed. Returning to overworld.')
            else:
                log_utils.print_and_log(
                    logging.INFO,
                    'World {} had no error'.format(world_type),
                    should_print=True,
                )
            self.active_worlds[task_id] = None
            for agent in agents:
                self.after_agent_removed(agent.id)
                agent_state = self.get_agent_state(agent.id)
                agent_state.data = agent.data
                next_task = agent.data.get("next_task")
                log_utils.print_and_log(logging.INFO,
                                        "Next task: {}".format(next_task))
                if next_task is None:
                    self._launch_overworld(agent.id)
                    overworld_agent = agent_state.get_overworld_agent()
                    overworld_agent.data = agent_state.data
                    agent_state.set_active_agent(overworld_agent)
                elif next_task == self.EXIT_STR:
                    self._remove_agent(agent.id)
                else:
                    self.add_agent_to_pool(agent_state, next_task)
Exemple #21
0
    def _manager_loop_fn(self):
        """
        An iteration of the manager's main loop to launch worlds.
        """

        with self.agent_pool_change_condition:
            valid_pools = self._get_unique_pool()
            for world_type, agent_pool in valid_pools.items():
                # check if agent has exceeded max time in pool
                world_config = self.task_configs[world_type]
                if world_config.max_time_in_pool is not None:
                    self.check_timeout_in_pool(
                        world_type,
                        agent_pool,
                        world_config.max_time_in_pool,
                        world_config.backup_task,
                    )

                needed_agents = self.max_agents_for[world_type]
                if len(agent_pool) >= needed_agents:
                    log_utils.print_and_log(logging.INFO,
                                            'starting pool',
                                            should_print=True)
                    # enough agents in pool to start new conversation
                    self.conversation_index += 1
                    task_id = 't_{}'.format(self.conversation_index)

                    # Add the required number of valid agents to the conv
                    agent_states = [w for w in agent_pool[:needed_agents]]
                    agents = []
                    for state in agent_states:
                        agent = self._create_agent(task_id, state.get_id())
                        agent.onboard_data = state.onboard_data
                        agent.data = state.data
                        state.assign_agent_to_task(agent, task_id)
                        state.set_active_agent(agent)
                        agents.append(agent)
                        # reset wait message state
                        state.stored_data['seen_wait_message'] = False
                    assign_role_function = utils.get_assign_roles_fn(
                        self.world_module, self.taskworld_map[world_type])
                    if assign_role_function is None:
                        assign_role_function = utils.default_assign_roles_fn
                    assign_role_function(agents)
                    # Allow task creator to filter out workers and run
                    # versions of the task that require fewer agents
                    for a in agents:
                        # Remove selected workers from the agent pool
                        self.remove_agent_from_pool(
                            self.get_agent_state(a.id),
                            world_type=world_type,
                            mark_removed=False,
                        )
                    for a in agents:
                        partner_list = agents.copy()
                        partner_list.remove(a)
                        a.message_partners = partner_list

                    done_callback = self._get_done_callback_for_agents(
                        task_id, world_type, agents)

                    # launch task world.
                    future = self.world_runner.launch_task_world(
                        task_id, self.taskworld_map[world_type], agents)
                    future.add_done_callback(done_callback)
                    self.active_worlds[task_id] = future
Exemple #22
0
 def _world_fn():
     log_utils.print_and_log(logging.INFO,
                             'Starting task {}...'.format(task_name))
     return self._run_world(task, world_name, agents)
 def _log_debug(self, text: str):
     time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
     log_utils.print_and_log(logging.DEBUG, f'{time}: {text}', should_print=True)
Exemple #24
0
 def on_socket_open(*args):
     log_utils.print_and_log(logging.DEBUG,
                             'Socket open: {}'.format(args))
     self._send_world_alive()
Exemple #25
0
 def on_socket_open(*args):
     log_utils.print_and_log(logging.DEBUG, f'Socket open: {args}')
     self._send_world_alive()