Exemple #1
0
    def __init__(self, model_config: Union[str, Path], service_name: str,
                 agent_namespace: str, batch_size: int,
                 utterance_lifetime_sec: int, rabbit_host: str,
                 rabbit_port: int, rabbit_login: str, rabbit_password: str,
                 rabbit_virtualhost: str,
                 loop: asyncio.AbstractEventLoop) -> None:
        self._add_to_buffer_lock = asyncio.Lock()
        self._infer_lock = asyncio.Lock()
        server_params = get_server_params(model_config)
        self._model_args_names = server_params['model_args_names']
        self._model = build_model(model_config)
        self._in_queue = None
        self._utterance_lifetime_sec = utterance_lifetime_sec
        self._batch_size = batch_size
        self._incoming_messages_buffer = []

        loop.run_until_complete(
            self._connect(loop=loop,
                          host=rabbit_host,
                          port=rabbit_port,
                          login=rabbit_login,
                          password=rabbit_password,
                          virtualhost=rabbit_virtualhost,
                          agent_namespace=agent_namespace))
        loop.run_until_complete(
            self._setup_queues(service_name, agent_namespace))
        loop.run_until_complete(
            self._in_queue.consume(callback=self._on_message_callback))

        log.info(f'Service in queue started consuming')
Exemple #2
0
def start_ms_bf_server(model_config: Path,
                       app_id: Optional[str],
                       app_secret: Optional[str],
                       port: Optional[int] = None,
                       https: Optional[bool] = None,
                       ssl_key: Optional[str] = None,
                       ssl_cert: Optional[str] = None) -> None:

    server_params = get_server_params(model_config)

    host = server_params['host']
    port = port or server_params['port']

    ssl_config = get_ssl_params(server_params, https, ssl_key=ssl_key, ssl_cert=ssl_cert)

    input_q = Queue()
    bot = MSBot(model_config, input_q, app_id, app_secret)
    bot.start()

    endpoint = '/v3/conversations'
    redirect_root_to_docs(app, 'answer', endpoint, 'post')

    @app.post(endpoint)
    async def answer(activity: dict) -> dict:
        bot.input_queue.put(activity)
        return {}

    uvicorn.run(app, host=host, port=port, logger=uvicorn_log, ssl_version=ssl_config.version,
                ssl_keyfile=ssl_config.keyfile, ssl_certfile=ssl_config.certfile)
    bot.join()
    def interact_api(config_path):
        server_params = get_server_params(config_path)

        url_base = 'http://{}:{}'.format(server_params['host'], api_port
                                         or server_params['port'])
        url = urljoin(url_base.replace('http://0.0.0.0:', 'http://127.0.0.1:'),
                      server_params['model_endpoint'])

        post_headers = {'Accept': 'application/json'}

        logfile = io.BytesIO(b'')
        args = [
            sys.executable, "-m", "deeppavlov", "riseapi",
            str(config_path)
        ]
        if api_port:
            args += ['-p', str(api_port)]
        p = pexpect.popen_spawn.PopenSpawn(' '.join(args),
                                           timeout=None,
                                           logfile=logfile)
        try:
            p.expect(url_base)

            get_url = urljoin(
                url_base.replace('http://0.0.0.0:', 'http://127.0.0.1:'),
                '/api')
            get_response = requests.get(get_url)
            response_code = get_response.status_code
            assert response_code == 200, f"GET /api request returned error code {response_code} with {config_path}"

            model_args_names = get_response.json()
            post_payload = dict()
            for arg_name in model_args_names:
                arg_value = ' '.join(['qwerty'] * 10)
                post_payload[arg_name] = [arg_value]

            post_response = requests.post(url,
                                          json=post_payload,
                                          headers=post_headers)
            response_code = post_response.status_code
            assert response_code == 200, f"POST request returned error code {response_code} with {config_path}"

        except pexpect.exceptions.EOF:
            raise RuntimeError('Got unexpected EOF: \n{}'.format(
                logfile.getvalue().decode()))

        finally:
            p.kill(signal.SIGTERM)
            p.wait()
Exemple #4
0
def start_alice_server(model_config: Union[str, Path],
                       host: Optional[str] = None,
                       port: Optional[int] = None,
                       endpoint: Optional[str] = None,
                       https: Optional[bool] = None,
                       ssl_key: Optional[str] = None,
                       ssl_cert: Optional[str] = None) -> None:
    server_params = get_server_params(model_config)

    host = host or server_params['host']
    port = port or server_params['port']
    endpoint = endpoint or server_params['model_endpoint']

    ssl_config = get_ssl_params(server_params,
                                https,
                                ssl_key=ssl_key,
                                ssl_cert=ssl_cert)

    input_q = Queue()
    output_q = Queue()

    bot = AliceBot(model_config, input_q, output_q)
    bot.start()

    redirect_root_to_docs(app, 'answer', endpoint, 'post')

    @app.post(endpoint,
              summary='A model endpoint',
              response_description='A model response')
    async def answer(data: dict = data_body) -> dict:
        loop = asyncio.get_event_loop()
        bot.input_queue.put(data)
        response: dict = await loop.run_in_executor(None, bot.output_queue.get)
        return response

    uvicorn.run(app,
                host=host,
                port=port,
                logger=uvicorn_log,
                ssl_version=ssl_config.version,
                ssl_keyfile=ssl_config.keyfile,
                ssl_certfile=ssl_config.certfile)
    bot.join()
Exemple #5
0
    def __init__(self,
                 model_config: Path,
                 socket_type: str,
                 port: Optional[int] = None,
                 socket_file: Optional[Union[str, Path]] = None) -> None:
        """Initializes socket server.

        Args:
            model_config: Path to the config file.
            socket_type: Socket family. "TCP" for the AF_INET socket server, "UNIX" for UNIX Domain Socket server.
            port: Port number for the AF_INET address family. If parameter is not defined, the port number from the
                utils/settings/server_config.json is used.
            socket_file: Path to the file to which UNIX Domain Socket server connects. If parameter is not defined,
                the path from the utils/settings/server_config.json is used.

        Raises:
            ValueError: If ``socket_type`` parameter is neither "TCP" nor "UNIX".

        """
        server_params = get_server_params(model_config)
        socket_type = socket_type or server_params['socket_type']
        self._loop = asyncio.get_event_loop()

        if socket_type == 'TCP':
            host = server_params['host']
            port = port or server_params['port']
            self._launch_msg = f'{server_params["socket_launch_message"]} http://{host}:{port}'
            self._loop.create_task(
                asyncio.start_server(self._handle_client, host, port))
        elif socket_type == 'UNIX':
            socket_file = socket_file or server_params['unix_socket_file']
            socket_path = Path(socket_file).resolve()
            if socket_path.exists():
                socket_path.unlink()
            self._launch_msg = f'{server_params["socket_launch_message"]} {socket_file}'
            self._loop.create_task(
                asyncio.start_unix_server(self._handle_client, socket_file))
        else:
            raise ValueError(f'socket type "{socket_type}" is not supported')

        self._model = build_model(model_config)
        self._model_args_names = server_params['model_args_names']
    def interact_socket(config_path, socket_type):
        socket_params = get_server_params(config_path)
        model_args_names = socket_params['model_args_names']

        host = socket_params['host']
        port = api_port or socket_params['port']

        socket_payload = {}
        for arg_name in model_args_names:
            arg_value = ' '.join(['qwerty'] * 10)
            socket_payload[arg_name] = [arg_value]

        logfile = io.BytesIO(b'')
        args = [
            sys.executable, "-m", "deeppavlov", "risesocket",
            str(config_path), '--socket-type', socket_type
        ]
        if socket_type == 'TCP':
            args += ['-p', str(port)]
            address_family = socket.AF_INET
            connect_arg = (host, port)
        else:
            address_family = socket.AF_UNIX
            connect_arg = socket_params['unix_socket_file']
        p = pexpect.popen_spawn.PopenSpawn(' '.join(args),
                                           timeout=None,
                                           logfile=logfile)
        try:
            p.expect(socket_params['socket_launch_message'])
            with socket.socket(address_family, socket.SOCK_STREAM) as s:
                try:
                    s.connect(connect_arg)
                except ConnectionRefusedError:
                    sleep(1)
                    s.connect(connect_arg)
                s.sendall(encode(socket_payload))
                s.settimeout(60)
                header = s.recv(4)
                body_len = unpack('<I', header)[0]
                data = bytearray()
                while len(data) < body_len:
                    chunk = s.recv(body_len - len(data))
                    if not chunk:
                        raise ValueError(
                            f'header does not match body\nheader: {body_len}\nbody length: {len(data)}'
                            f'data: {data}')
                    data.extend(chunk)
            try:
                resp = json.loads(data)
            except json.decoder.JSONDecodeError:
                raise ValueError(f"Can't decode model response {data}")
            assert resp['status'] == 'OK', f"{socket_type} socket request returned status: {resp['status']}" \
                                           f" with {config_path}\n{logfile.getvalue().decode()}"

        except pexpect.exceptions.EOF:
            raise RuntimeError(
                f'Got unexpected EOF: \n{logfile.getvalue().decode()}')

        except json.JSONDecodeError:
            raise ValueError(
                f'Got JSON not serializable response from model: "{data}"\n{logfile.getvalue().decode()}'
            )

        finally:
            p.kill(signal.SIGTERM)
            p.wait()
Exemple #7
0
def start_alexa_server(model_config: Union[str, Path, dict],
                       port: Optional[int] = None,
                       https: Optional[bool] = None,
                       ssl_key: Optional[str] = None,
                       ssl_cert: Optional[str] = None) -> None:
    """Initiates FastAPI web service with Alexa skill.

    Allows raise Alexa web service with DeepPavlov config in backend.

    Args:
        model_config: DeepPavlov config path.
        port: FastAPI web service port.
        https: Flag for running Alexa skill service in https mode.
        ssl_key: SSL key file path.
        ssl_cert: SSL certificate file path.

    """
    server_params = get_server_params(model_config)

    host = server_params['host']
    port = port or server_params['port']

    ssl_config = get_ssl_params(server_params,
                                https,
                                ssl_key=ssl_key,
                                ssl_cert=ssl_cert)

    input_q = Queue()
    output_q = Queue()

    bot = AlexaBot(model_config, input_q, output_q)
    bot.start()

    endpoint = '/interact'
    redirect_root_to_docs(app, 'interact', endpoint, 'post')

    @app.post(endpoint,
              summary='Amazon Alexa custom service endpoint',
              response_description='A model response')
    async def interact(
            data: dict = data_body,
            signature: str = signature_header,
            signature_chain_url: str = cert_chain_url_header) -> JSONResponse:
        # It is necessary for correct data validation to serialize data to a JSON formatted string with separators.
        request_dict = {
            'request_body': json.dumps(data,
                                       separators=(',', ':')).encode('utf-8'),
            'signature_chain_url': signature_chain_url,
            'signature': signature,
            'alexa_request': data
        }

        bot.input_queue.put(request_dict)
        loop = asyncio.get_event_loop()
        response: dict = await loop.run_in_executor(None, bot.output_queue.get)
        response_code = 400 if 'error' in response.keys() else 200
        return JSONResponse(response, status_code=response_code)

    uvicorn.run(app,
                host=host,
                port=port,
                logger=uvicorn_log,
                ssl_version=ssl_config.version,
                ssl_keyfile=ssl_config.keyfile,
                ssl_certfile=ssl_config.certfile)
    bot.join()