Process user text

Hello! Help me please. I need to process text message of user, when worked one of intents, and return processed message to tracker. And send this text to extractor. How I can do it? What event should I link this to? What my sequence of operations? RASA 2.8

Do you know how to intercept and change the incoming message before sending it to rasa nlu?

Hi! :smiley:

You have two ways to do it. Make the change in frontend, when the user click “send” and frontend make post to rasa or…

Build a custom channel to do it

Look my custom_channel.py i think it will help you :smiley:

This is how i get user message

text = request.json.get("text") 

references:

Edit-------

I replayed you in this topic But i think better we stay in this thread you has created :smiley:

@itsjhonny Thanks for the quick response. I need to process the message before extracting entities from it. After processing, it is necessary to extract entities from the processed message. I found a way to do this using a custom component in the pipeline in config.yml. The order is as follows: I add my component after classifier and process the message based on the presence of the entity. But my bot falls into error when you send him a message with the necessary entity. Can you help?

This is my Class of custom pipeline component:

class ProcessMessage(Component): “”“A new component”“”

supported_language_list = None
not_supported_language_list = None

def __init__(self, component_config: Optional[Dict[Text, Any]] = None) -> None:
    super().__init__(component_config)

def process(self, message: Message, **kwargs: Any) -> None:

    metadata = message.get("metadata")
    current_message = message.as_dict()
    if current_message["intent"]["name"] == "order":
        print(current_message["text"])

This is an error:

Your input → order
order None 2022-04-20 16:47:29 ERROR asyncio - Task exception was never retrieved future: <Task finished name=‘Task-2’ coro=<configure_app..run_cmdline_io() done, defined at /home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/rasa/core/run.py:131> exception=TimeoutError()> Traceback (most recent call last): File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/rasa/core/run.py”, line 135, in run_cmdline_io await console.record_messages( File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/rasa/core/channels/console.py”, line 184, in record_messages async for response in bot_responses: File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/rasa/core/channels/console.py”, line 139, in _send_message_receive_stream async for line in resp.content: File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/aiohttp/streams.py”, line 35, in anext rv = await self.read_func() File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/aiohttp/streams.py”, line 311, in readline return await self.readuntil() File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/aiohttp/streams.py”, line 343, in readuntil await self._wait(“readuntil”) File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/aiohttp/streams.py”, line 304, in _wait await waiter File “/home/faust/miniconda3/envs/rasa2/lib/python3.8/site-packages/aiohttp/helpers.py”, line 721, in exit raise asyncio.TimeoutError from None asyncio.exceptions.TimeoutError

Hi @faupotron it’s happen because rasa can’t wait much seconds (maybe 10s) to return the user.

exit raise asyncio.TimeoutError from None asyncio.exceptions.TimeoutError

Print func work fine in terminal ?

Maybe you need to put return

Can you check example of printer.py? I think this can help you :smiley:

@itsjhonny Thanks. I try component printer.py. It’s work and print any message. I want to change the user massage and it doesn’t work out. I can’t save to user text…

there are two ways to solve the problem. I want to share my experience:

  1. Using the custom connector: Using the POST method, we receive a message, process it and submit it to the tracker and it gets processed by the NLU Here is an example of my custom connector:

class FreeSwitchInput(InputChannel): @classmethod def name(cls) → Text: return “freeswitch”

def blueprint(self, on_new_message: Callable[[UserMessage], Awaitable[Any]]) -> Blueprint:

    freeswitch_webhook = Blueprint(
        "freeswitch_webhook_{}".format(type(self).__name__),
        inspect.getmodule(self).__name__,
    )

    @freeswitch_webhook.route("/", methods=["GET"])
    async def health(request: Request) -> HTTPResponse:
        return response.json({"status": "ok"})

    @freeswitch_webhook.route("/webhook", methods=["POST"])
    async def receive(request: Request) -> HTTPResponse:
        if not request.json:
            return response.text("")
        sender_id = request.json.get("sender")  # method to get sender_id
        text = request.json.get("message")  # method to fetch text
        input_channel = self.name()  # method to fetch input channel
        metadata = self.get_metadata(request)  # method to get metadata
        logger.debug(f"Output channel: {input_channel}")
        collector = FreeSwitchOutput()

        processing_str = ProcessingStrTime()
        work_str = processing_str.token_text(text)

        # check user text message for words related to time
        if (
            set(work_str) & set(YEARS)
            or set(work_str) & set(MONTHS)
            or set(work_str) & set(TIME_WORDS)
            or set(work_str) & set(EVENING_WORD)
            or set(work_str) & set(DAY_WORDS)
            or set(work_str) & set(TODAY_WORD)
            or set(work_str) & set(HALF_HOUR)
            or set(work_str) & set(MINUTE_WORD)
            or set(work_str) & set(BEFORE)
        ):
            extractor = NumberExtractor()
            date, time = processing_str.separate_date(text)

            numbers_in_date, _ = extractor.replace(date, apply_regrouping=True)
            numbers_in_time, _ = extractor.replace(time, apply_regrouping=False)

            text = processing_str.convert_str(numbers_in_date, numbers_in_time)
        else:
            text = text

        # include exception handling
        try:
            await on_new_message(
                UserMessage(
                    text,
                    collector,
                    sender_id,
                    input_channel=input_channel,
                    metadata=metadata,
                )
            )
        except Exception as e:
            logger.error(f"Exception when trying to handle message.{e}")
            logger.error(str(e), exc_info=True)

        return response.json(collector.messages)

    return freeswitch_webhook
  1. Using the custom component of NLU We insert our NLU component at the beginning of the pipeline for text preprocessing. Next, the preprocessed text is processed by the NLU and passes intents and entities to the tracker. In this case, the user’s original text in the tracker remains unchanged

Here is an example of my custom component:

class ProcessMessage(Component): supported_language_list = [“ru”] not_supported_language_list = None language_list = [“ru”]

@classmethod
def required_components(cls) -> List[Type[Component]]:
    """Specify which components need to be present in the pipeline."""
    return []

def __init__(self, component_config: Optional[Dict[Text, Any]] = None) -> None:
    super().__init__(component_config)

def process(self, message: Message, **kwargs: Any) -> None:
    if "text" in message.data:
        text = message.data["text"]
        processing_str = ProcessingStrTime()
        work_str = processing_str.token_text(text)

        # проверка текста на маркеры, говорящие о дате-времени
        if (
            set(work_str) & set(YEARS)
            or set(work_str) & set(MONTHS)
            or set(work_str) & set(TIME_WORDS)
            or set(work_str) & set(EVENING_WORD)
            or set(work_str) & set(DAY_WORDS)
            or set(work_str) & set(TODAY_WORD)
            or set(work_str) & set(HALF_HOUR)
            or set(work_str) & set(MINUTE_WORD)
            or set(work_str) & set(BEFORE)
        ):
            extractor = NumberExtractor()
            date, time = processing_str.separate_date(text)

            numbers_in_date, _ = extractor.replace(date, apply_regrouping=True)
            numbers_in_time, _ = extractor.replace(time, apply_regrouping=False)

            text = processing_str.convert_str(numbers_in_date, numbers_in_time)
        else:
            text = text

        message.data["text"] = text