예제 #1
0
파일: agent.py 프로젝트: zhiyuxzh/rasa
    async def handle_text(
        self,
        text_message: Union[Text, Dict[Text, Any]],
        message_preprocessor: Optional[Callable[[Text], Text]] = None,
        output_channel: Optional[OutputChannel] = None,
        sender_id: Optional[Text] = UserMessage.DEFAULT_SENDER_ID,
    ) -> Optional[List[Dict[Text, Any]]]:
        """Handle a single message.

        If a message preprocessor is passed, the message will be passed to that
        function first and the return value is then used as the
        input for the dialogue engine.

        The return value of this function depends on the ``output_channel``. If
        the output channel is not set, set to ``None``, or set
        to ``CollectingOutputChannel`` this function will return the messages
        the bot wants to respond.

        :Example:

            >>> from rasa.core.agent import Agent
            >>> from rasa.core.interpreter import RasaNLUInterpreter
            >>> agent = Agent.load("examples/restaurantbot/models/current")
            >>> await agent.handle_text("hello")
            [u'how can I help you?']

        """

        if isinstance(text_message, str):
            text_message = {"text": text_message}

        msg = UserMessage(text_message.get("text"), output_channel, sender_id)

        return await self.handle_message(msg, message_preprocessor)
예제 #2
0
def handle_whatsapp_messages():
    if request.method == "GET":
        pass
    else:
        try:
            msg = request.values.get('Body')
            sender_id = request.values.get('From')
            numMedia = int(request.values.get('NumMedia'))
            resp = MessagingResponse()
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            if msg is not None or msg != " " or msg != "":
                msgRasa = UserMessage(text=msg, sender_id=sender_id)
                responses = loop.run_until_complete(
                    agent_en.handle_message(msgRasa))
                for response in responses:
                    if numMedia > 0:
                        resp.message(response['text'])
                        # Insert media link into the media function
                        resp.message().media("thank-you-lettering.jpg")
                    else:
                        resp.message(response['text'])
                return str(resp)
            else:
                resp.message("Please Type Something")
        except Exception as e:
            logger.exception('Whatsapp API Handler error')
        return "success"
예제 #3
0
    async def handle_text(
        self,
        nlu_info: Optional[Dict],
        message_preprocessor: Optional[Callable[[Text], Text]] = None,
        output_channel: Optional[OutputChannel] = None,
        sender_id: Optional[Text] = UserMessage.DEFAULT_SENDER_ID
    ) -> Optional[List[Dict[Text, Any]]]:
        """Handle a single message.

        If a message preprocessor is passed, the message will be passed to that
        function first and the return value is then used as the
        input for the dialogue engine.

        The return value of this function depends on the ``output_channel``. If
        the output channel is not set, set to ``None``, or set
        to ``CollectingOutputChannel`` this function will return the messages
        the bot wants to respond.

        这个地方的输入是经过NLU提取之后的意图和实体Json(dict)."""

        # 进行输入数据的整合
        if isinstance(nlu_info, dict):
            msg = UserMessage(output_channel=output_channel,
                              sender_id=sender_id,
                              parse_data=nlu_info)
        else:
            # 如果nlu_info不是dict类型直接抛出异常
            raise TypeError("The nlu input data type must be a dictionary.")

        return await self.handle_message(msg, message_preprocessor)
        async def action(request):
            print("/action called - form: " + str(request.form))
            result = request.form.get("SpeechResult")
            call_sid = request.form.get("CallSid", None)

            print("Result: " + str(result))

            if result:
                out = CollectingOutputChannel()

                # sends message to Rasa, wait for the response
                await on_new_message(
                    UserMessage(
                        result, out, call_sid, input_channel="twilio_voice"
                    )
                )

                # extract the text from Rasa's response
                last_response = py_.nth(out.messages, -1)

                # Some times on restarts, the server is in a weird state and their may be no session for an action
                if last_response:
                    print("last message: " + last_response["text"])
                    return self.prompt(last_response["text"])
                else:
                    return self.prompt('How can I help you today?')
            else:
                # If we did not get a user response, just reprompt
                return self.prompt("sorry, I did not get that - please repeat")
예제 #5
0
파일: test.py 프로젝트: spawn08/rasa
async def _get_e2e_entity_evaluation_result(
    processor: "MessageProcessor",
    tracker: DialogueStateTracker,
    prediction: PolicyPrediction,
) -> Optional[EntityEvaluationResult]:
    previous_event = tracker.events[-1]

    if isinstance(previous_event, SlotSet):
        # UserUttered events with entities can be followed by SlotSet events
        # if slots are defined in the domain
        previous_event = tracker.get_last_event_for(
            (UserUttered, ActionExecuted))

    if isinstance(previous_event, UserUttered):
        entities_predicted_by_policies = [
            entity for prediction_event in prediction.events
            if isinstance(prediction_event, EntitiesAdded)
            for entity in prediction_event.entities
        ]
        entity_targets = previous_event.entities
        if entity_targets or entities_predicted_by_policies:
            text = previous_event.text
            if text:
                parsed_message = await processor.parse_message(
                    UserMessage(text=text))
                if parsed_message:
                    tokens = [
                        Token(text[start:end], start, end)
                        for start, end in parsed_message.get(
                            TOKENS_NAMES[TEXT], [])
                    ]
                    return EntityEvaluationResult(
                        entity_targets, entities_predicted_by_policies, tokens,
                        text)
    return None
예제 #6
0
    async def log_message(request: Request, sender_id: Text):
        request_params = request.json
        try:
            message = request_params["message"]
        except KeyError:
            message = request_params.get("text")

        sender = request_params.get("sender")
        parse_data = request_params.get("parse_data")
        verbosity = event_verbosity_parameter(request,
                                              EventVerbosity.AFTER_RESTART)

        # TODO: implement properly for agent / bot
        if sender != "user":
            raise ErrorResponse(
                500,
                "NotSupported",
                "Currently, only user messages can be passed "
                "to this endpoint. Messages of sender '{}' "
                "cannot be handled.".format(sender),
                {
                    "parameter": "sender",
                    "in": "body"
                },
            )

        try:
            usermsg = UserMessage(message, None, sender_id, parse_data)
            tracker = await app.agent.log_message(usermsg)
            return response.json(tracker.current_state(verbosity))

        except Exception as e:
            logger.exception("Caught an exception while logging message.")
            raise ErrorResponse(500, "MessageException",
                                "Server failure. Error: {}".format(e))
예제 #7
0
async def test_lock_error(default_agent: Agent):
    lock_lifetime = 0.01
    wait_time_in_seconds = 0.01
    holdup = 0.5

    # Mock message handler again to add a wait time holding up the lock
    # after it's been acquired
    async def mocked_handle_message(self, message: UserMessage) -> None:
        async with self.lock_store.lock(
                message.sender_id,
                wait_time_in_seconds=wait_time_in_seconds,
                lock_lifetime=lock_lifetime,
        ):
            # hold up the message processing after the lock has been acquired
            await asyncio.sleep(holdup)

        return None

    with patch.object(Agent, "handle_message", mocked_handle_message):
        # first message blocks the lock for `holdup`,
        # meaning the second message will not be able to acquire a lock
        tasks = [
            default_agent.handle_message(
                UserMessage(f"sender {i}", sender_id="some id"))
            for i in range(2)
        ]

        with pytest.raises(LockError):
            await asyncio.gather(*(asyncio.ensure_future(t) for t in tasks))
예제 #8
0
파일: processor.py 프로젝트: yurilq/rasa01
    async def handle_reminder(
        self,
        reminder_event: ReminderScheduled,
        sender_id: Text,
        output_channel: OutputChannel,
        nlg: NaturalLanguageGenerator,
    ) -> None:
        """Handle a reminder that is triggered asynchronously."""

        tracker = self._get_tracker(sender_id)

        if not tracker:
            logger.warning("Failed to retrieve or create tracker for sender "
                           "'{}'.".format(sender_id))
            return None

        if (reminder_event.kill_on_user_message
                and self._has_message_after_reminder(tracker, reminder_event)
                or not self._is_reminder_still_valid(tracker, reminder_event)):
            logger.debug("Canceled reminder because it is outdated. "
                         "(event: {} id: {})".format(
                             reminder_event.action_name, reminder_event.name))
        else:
            # necessary for proper featurization, otherwise the previous
            # unrelated message would influence featurization
            tracker.update(UserUttered.empty())
            action = self._get_action(reminder_event.action_name)
            should_continue = await self._run_action(action, tracker,
                                                     output_channel, nlg)
            if should_continue:
                user_msg = UserMessage(None, output_channel, sender_id)
                await self._predict_and_execute_next_action(user_msg, tracker)
            # save tracker state to continue conversation from this state
            self._save_tracker(tracker)
예제 #9
0
def test_int_sender_id_in_user_message():
    from rasa.core.channels import UserMessage

    # noinspection PyTypeChecker
    message = UserMessage("A text", sender_id=1234567890)

    assert message.sender_id == "1234567890"
예제 #10
0
파일: twilio.py 프로젝트: yurilq/rasa01
        async def message(request: Request):
            sender = request.form.get("From", None)
            text = request.form.get("Body", None)

            out_channel = TwilioOutput(self.account_sid, self.auth_token,
                                       self.twilio_number)

            if sender is not None and message is not None:
                try:
                    # @ signs get corrupted in SMSes by some carriers
                    text = text.replace("¡", "@")
                    await on_new_message(
                        UserMessage(text,
                                    out_channel,
                                    sender,
                                    input_channel=self.name()))
                except Exception as e:
                    logger.error(
                        "Exception when trying to handle message.{0}".format(
                            e))
                    logger.debug(e, exc_info=True)
                    if self.debug_mode:
                        raise
                    pass
            else:
                logger.debug("Invalid message")

            return response.text("success")
예제 #11
0
def test_int_message_id_in_user_message():
    from rasa.core.channels import UserMessage

    # noinspection PyTypeChecker
    message = UserMessage("B text", message_id=987654321)

    assert message.message_id == "987654321"
예제 #12
0
 async def receive(request: Request) -> HTTPResponse:
     sender_id = await self._extract_sender(request)
     text = self._extract_message(request)
     input_channel = self._extract_input_channel(request)
     metadata = self.get_metadata(request)
     collector = CollectingOutputChannel()
     # noinspection PyBroadException
     try:
         message = UserMessage(
             text,
             collector,
             sender_id,
             input_channel=input_channel,
             metadata=metadata,
         )
         await on_new_message(message)
     except CancelledError:
         logger.error("Message handling timed out for "
                      "user message '{}'.".format(text))
     except Exception:
         logger.exception("An exception occured while handling "
                          "user message '{}'.".format(text))
     return response.json(
         self.__filter_confidence_below_threshold(
             request=request,
             message=collector.messages,
             sender_id=sender_id))
예제 #13
0
        async def receive(request: Request) -> HTTPResponse:
            """
            Transform Zipwhip request into Rasa expected format

            :param request: Zipwhip message receive request
            {
                "body": "Hello from mobile device",
                "bodySize": 24,
                "address": "ptn:/+12063996756",
                "finalSource": "+12063996756",
                "finalDestination": "+12068163958",
                "fingerprint": "1514465037",
                "id": 1195453017123205120,
                "contactId": 14543967707,
                "deviceId": 377265507,
                "messageType": "MO",
                "cc": null,
                "bcc": null,
                "visible": true,
                "read": false,
                "scheduledDate": null,
                "dateDeleted": null,
                "messageTransport": 5,
                "dateDelivered": null,
                "hasAttachment": false,
                "dateCreated": "2019-11-15T21:26:24+00:00",
                "deleted": false,
                "dateRead": null,
                "statusCode": 4
            }
            :return: HTTP response to return to Zipwhip
            """
            sender_id = await self._extract_sender(request)
            text = self._extract_message(request)
            print(text)

            input_channel = self._extract_input_channel(request)
            metadata = self.get_metadata(request)

            collector = CollectingOutputChannel()
            # noinspection PyBroadException
            try:
                await on_new_message(
                    UserMessage(
                        text,
                        collector,
                        sender_id,
                        input_channel=input_channel,
                        metadata=metadata,
                    ))
            except CancelledError:
                logger.error("Message handling timed out for "
                             "user message '{}'.".format(text))
            except Exception:
                logger.exception("An exception occured while handling "
                                 "user message '{}'.".format(text))

            self.send_all(sender_id, collector.messages)
            return response.json("Success.")
예제 #14
0
        async def webhook(request):
            sender_id = self._extract_sender(request)
            text = self._extract_message(request)

            collector = CallbackOutput(self.callback_endpoint)
            await on_new_message(UserMessage(text, collector, sender_id,
                                             input_channel=self.name()))
            return response.text("success")
예제 #15
0
async def test_message_processor(default_processor):
    out = CollectingOutputChannel()
    await default_processor.handle_message(
        UserMessage('/greet{"name":"Core"}', out))
    assert {
        'recipient_id': 'default',
        'text': 'hey there Core!'
    } == out.latest_output()
예제 #16
0
async def test_message_processor(default_channel: CollectingOutputChannel,
                                 default_processor: MessageProcessor):
    await default_processor.handle_message(
        UserMessage('/greet{"name":"Core"}', default_channel))
    assert {
        "recipient_id": "default",
        "text": "hey there Core!",
    } == default_channel.latest_output()
예제 #17
0
def handle_websocket(websocket, path):
    path_split = path.split('/')
    lang = path_split[len(path_split) - 1]
    agent = agent_all.get(lang, None)
    session_message = None
    if agent is not None:
        if websocket is not None:
            try:
                while True:
                    msg = websocket.receive()
                    try:
                        message = json.loads(msg)
                    except:
                        break
                    session_message = message['user']
                    store_user(session_message, websocket)
                    text_message = message['text']
                    msgRasa = UserMessage(sender_id=session_message,
                                          text=text_message)
                    if text_message == "/restart" or text_message == "restart":
                        pause_user(session_message, pause=False)

                    loop = asyncio.new_event_loop()
                    asyncio.set_event_loop(loop)
                    t = loop.run_until_complete(agent.log_message(msgRasa))
                    slots = t.current_slot_values()
                    update_lang(session_message, lang)

                    if not isPause(session_message):
                        responses = loop.run_until_complete(
                            agent.handle_message(msgRasa))
                        for response in responses:
                            log_message = ""
                            if 'text' in response.keys():
                                log_message = response['text']
                            else:
                                log_message = json.dumps(
                                    response['attachment'], indent=3)
                            dashlog.log("outgoing", response,
                                        response['recipient_id'])
                            time.sleep(1)
                            websocket.send(
                                json.dumps(message_exec.send_typing()))
                            time.sleep(1.5)
                            parsed_message = message_exec.parse(response)
                            websocket.send(json.dumps(parsed_message))
                    else:
                        dashlog.log("incoming",
                                    None,
                                    session_message,
                                    queryText=text_message,
                                    intent_name='Human In The Loop')
            except KeyboardInterrupt:
                sys.exit()
            except WebSocketError as ex:
                logger.exception("Websocket Error")
    else:
        raise Exception(f"Agent not found, agent: {agent}")
예제 #18
0
async def test_message_id_logging(default_processor):
    from rasa.core.trackers import DialogueStateTracker

    message = UserMessage("If Meg was an egg would she still have a leg?")
    tracker = DialogueStateTracker('1', [])
    await default_processor._handle_message_with_tracker(message, tracker)
    logged_event = tracker.events[-1]

    assert logged_event.message_id == message.message_id
    assert logged_event.message_id is not None
        async def message(request):
            print(request.form)  # The payload is form-encoded body
            call_sid = request.form.get("CallSid", None)
            out = CollectingOutputChannel()
            await on_new_message(
                UserMessage(
                    "Hello there", out, call_sid, input_channel="twilio_voice"
                )
            )

            return self.prompt(out.messages[0]["text"])
예제 #20
0
def test_nlu_message_converter_converts_message_with_metadata(
        default_model_storage: ModelStorage,
        default_execution_context: ExecutionContext):
    component = NLUMessageConverter.create({}, default_model_storage,
                                           Resource("with_metadata"),
                                           default_execution_context)

    message = UserMessage(text="Hello", metadata={"test_key": "test_value"})
    nlu_message = component.convert_user_message([message])
    assert len(nlu_message) == 1
    assert isinstance(nlu_message[0], Message)

    assert nlu_message[0].get("text") == "Hello"
    assert nlu_message[0].get("metadata") == {"test_key": "test_value"}
예제 #21
0
파일: processor.py 프로젝트: yurilq/rasa01
    async def log_message(
            self, message: UserMessage) -> Optional[DialogueStateTracker]:

        # preprocess message if necessary
        if self.message_preprocessor is not None:
            message.text = self.message_preprocessor(message.text)
        # we have a Tracker instance for each user
        # which maintains conversation state
        tracker = self._get_tracker(message.sender_id)
        if tracker:
            await self._handle_message_with_tracker(message, tracker)
            # save tracker state to continue conversation from this state
            self._save_tracker(tracker)
        else:
            logger.warning("Failed to retrieve or create tracker for sender "
                           "'{}'.".format(message.sender_id))
        return tracker
예제 #22
0
async def test_http_parsing():
    message = UserMessage('lunch?')

    endpoint = EndpointConfig('https://interpreter.com')
    with aioresponses() as mocked:
        mocked.post('https://interpreter.com/parse', repeat=True, status=200)

        inter = RasaNLUHttpInterpreter(endpoint=endpoint)
        try:
            await MessageProcessor(inter, None, None, None,
                                   None)._parse_message(message)
        except KeyError:
            pass  # logger looks for intent and entities, so we except

        r = latest_request(mocked, 'POST', "https://interpreter.com/parse")

        assert r
        assert json_of_latest_request(r)['message_id'] == message.message_id
예제 #23
0
    async def on_message_wrapper(
        on_new_message: Callable[[UserMessage], Awaitable[Any]],
        text: Text,
        queue: Queue,
        sender_id: Text,
        input_channel: Text,
        metadata: Optional[Dict[Text, Any]],
    ) -> None:
        collector = QueueOutputChannel(queue)

        message = UserMessage(text,
                              collector,
                              sender_id,
                              input_channel=input_channel,
                              metadata=metadata)
        await on_new_message(message)

        await queue.put("DONE")  # pytype: disable=bad-return-type
예제 #24
0
def test_nlu_message_converter_converts_message(
        default_model_storage: ModelStorage,
        default_execution_context: ExecutionContext):
    component = NLUMessageConverter.create(
        {**NLUMessageConverter.get_default_config()},
        default_model_storage,
        Resource("test"),
        default_execution_context,
    )

    message = UserMessage(text="Hello", metadata=None)
    nlu_message = component.convert_user_message([message])
    assert len(nlu_message) == 1
    assert isinstance(nlu_message[0], Message)

    assert nlu_message[0].get("text") == "Hello"
    assert nlu_message[0].get("metadata") is None
    assert nlu_message[0].output_properties == {TEXT_TOKENS, TEXT}
예제 #25
0
async def test_http_interpreter(endpoint_url, joined_url):
    with aioresponses() as mocked:
        mocked.post(joined_url)

        endpoint = EndpointConfig(endpoint_url)
        interpreter = RasaNLUHttpInterpreter(endpoint_config=endpoint)
        message = UserMessage(text="message_text", sender_id="message_id")
        await interpreter.parse(message)

        r = latest_request(mocked, "POST", joined_url)

        query = json_of_latest_request(r)
        response = {
            "text": "message_text",
            "token": None,
            "message_id": "message_id"
        }

        assert query == response
예제 #26
0
async def test_http_parsing():
    message = UserMessage("lunch?")

    endpoint = EndpointConfig("https://interpreter.com")
    with aioresponses() as mocked:
        mocked.post("https://interpreter.com/model/parse",
                    repeat=True,
                    status=200)

        inter = RasaNLUHttpInterpreter(endpoint=endpoint)
        try:
            await MessageProcessor(inter, None, None, None,
                                   None)._parse_message(message)
        except KeyError:
            pass  # logger looks for intent and entities, so we except

        r = latest_request(mocked, "POST",
                           "https://interpreter.com/model/parse")

        assert r
예제 #27
0
파일: server.py 프로젝트: jayceyxc/rasa
    async def add_message(request: Request, conversation_id: Text):
        validate_request_body(
            request,
            "No message defined in request body. Add a message to the request body in "
            "order to add it to the tracker.",
        )

        request_params = request.json

        message = request_params.get("text")
        sender = request_params.get("sender")
        parse_data = request_params.get("parse_data")

        verbosity = event_verbosity_parameter(request,
                                              EventVerbosity.AFTER_RESTART)

        # TODO: implement for agent / bot
        if sender != "user":
            raise ErrorResponse(
                400,
                "BadRequest",
                "Currently, only user messages can be passed to this endpoint. "
                "Messages of sender '{}' cannot be handled.".format(sender),
                {
                    "parameter": "sender",
                    "in": "body"
                },
            )

        try:
            user_message = UserMessage(message, None, conversation_id,
                                       parse_data)
            tracker = await app.agent.log_message(user_message)
            return response.json(tracker.current_state(verbosity))
        except Exception as e:
            logger.debug(traceback.format_exc())
            raise ErrorResponse(
                500,
                "ConversationError",
                "An unexpected error occurred. Error: {}".format(e),
            )
예제 #28
0
파일: __init__.py 프로젝트: eternius/asm
    async def get_response(self, request):
        """Train the engine.
        """
        if self.config.get('domain') is None:
            self.config.setdefault(
                'domain',
                Domain.from_file("data/" + self.config['skill-id'] +
                                 "/core/model"))
            self.config.setdefault(
                'tracker_store',
                ArcusTrackerStore(self.config.get('domain'), self.asm))

        domain = self.config.get('domain')
        tracker_store = self.config.get('tracker_store')
        nlg = NaturalLanguageGenerator.create(None, domain)
        policy_ensemble = SimplePolicyEnsemble.load("data/" +
                                                    self.config['skill-id'] +
                                                    "/core")
        interpreter = LocalNLUInterpreter(request)

        url = 'http://localhost:8080/api/v1/skill/generic_action'
        processor = MessageProcessor(interpreter,
                                     policy_ensemble,
                                     domain,
                                     tracker_store,
                                     nlg,
                                     action_endpoint=EndpointConfig(url),
                                     message_preprocessor=None)

        message_nlu = UserMessage(request['text'],
                                  None,
                                  request['user'],
                                  input_channel=request['channel'])

        result = await processor.handle_message(message_nlu)
        if result is not None and len(result) > 0:
            return {"text": result[0]['text']}
        else:
            _LOGGER.info(result)
            return {"text": "error"}
예제 #29
0
async def _predict_tracker_actions(
    tracker: DialogueStateTracker,
    agent: "Agent",
    fail_on_prediction_errors: bool = False,
    use_e2e: bool = False,
) -> Tuple[EvaluationStore, DialogueStateTracker, List[Dict[Text, Any]]]:

    processor = agent.create_processor()
    tracker_eval_store = EvaluationStore()

    events = list(tracker.events)

    partial_tracker = DialogueStateTracker.from_events(
        tracker.sender_id,
        events[:1],
        agent.domain.slots,
        sender_source=tracker.sender_source,
    )

    tracker_actions = []
    should_predict_another_action = True
    num_predicted_actions = 0

    for event in events[1:]:
        if isinstance(event, ActionExecuted):
            circuit_breaker_tripped = processor.is_action_limit_reached(
                num_predicted_actions, should_predict_another_action)
            (action_executed_result,
             prediction) = _collect_action_executed_predictions(
                 processor,
                 partial_tracker,
                 event,
                 fail_on_prediction_errors,
                 circuit_breaker_tripped,
             )
            tracker_eval_store.merge_store(action_executed_result)
            tracker_actions.append({
                "action":
                action_executed_result.action_targets[0],
                "predicted":
                action_executed_result.action_predictions[0],
                "policy":
                prediction.policy_name,
                "confidence":
                prediction.max_confidence,
            })
            should_predict_another_action = processor.should_predict_another_action(
                action_executed_result.action_predictions[0])
            num_predicted_actions += 1

        elif use_e2e and isinstance(event, UserUttered):
            # This means that user utterance didn't have a user message, only intent,
            # so we can skip the NLU part and take the parse data directly.
            # Indirectly that means that the test story was in YAML format.
            if not event.text:
                predicted = event.parse_data
            # Indirectly that means that the test story was in Markdown format.
            # Leaving that as it is because Markdown is in legacy mode.
            else:
                predicted = await processor.parse_message(
                    UserMessage(event.text))
            user_uttered_result = _collect_user_uttered_predictions(
                event, predicted, partial_tracker, fail_on_prediction_errors)

            tracker_eval_store.merge_store(user_uttered_result)
        else:
            partial_tracker.update(event)
        if isinstance(event, UserUttered):
            num_predicted_actions = 0

    return tracker_eval_store, partial_tracker, tracker_actions
예제 #30
0
async def test_parsing(default_processor):
    message = UserMessage('/greet{"name": "boy"}')
    parsed = await default_processor._parse_message(message)
    assert parsed["intent"]["name"] == 'greet'
    assert parsed["entities"][0]["entity"] == 'name'