Rasa issue on twilio voice

Hi I have am issue integrating rasa bot with twilio voice. I have followed Programmable Voice on twilio tutorial and i get this error. SMS is working fine on Programmable SMS. Raised a ticket with them, they seem to be clueless. Funny enough if I do follow their tutorial content is working just fine but they do not use rasa on tutorial. Please help I have spent lot of time with this and I need to make it work.

os win server 2016 rasa ver 1.4.3

2020-01-29 00:17:12 DEBUG rasa.cli.utils - Parameter ‘endpoints’ not set. Using default location ‘endpoints.yml’ instead. 2020-01-29 00:17:12 DEBUG rasa.cli.utils - Parameter ‘credentials’ not set. Using default location ‘credentials.yml’ instead. 2020-01-29 00:17:12 DEBUG rasa.model - Extracted model to ‘C:\Users\ADMINI~1\AppData\Local\Temp\tmp8cmqippf’. 2020-01-29 00:17:14 DEBUG sanic.root - CORS: Configuring CORS with resources: {’/’: {‘origins’: [’’], ‘methods’: ‘DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT’, ‘allow_head ers’: [’.’], ‘expose_headers’: None, ‘supports_credentials’: True, ‘max_age’: None, ‘send_wildcard’: False, ‘automatic_options’: True, ‘vary_header’: True, ‘resources’: {’/*’: {‘origins’: ‘’}}, ‘intercept_exceptions’: True, ‘always_send’: True}} 2020-01-29 00:17:14 DEBUG rasa.core.utils - Available web server routes: /webhooks/rasa GET custom_webhook_RasaChatInput.health /webhooks/rasa/webhook POST custom_webhook_RasaChatInput.receive /webhooks/rest GET custom_webhook_RestInput.health /webhooks/rest/webhook POST custom_webhook_RestInput.receive / GET hello /webhooks/twilio GET twilio_webhook.health /webhooks/twilio/webhook POST twilio_webhook.message 2020-01-29 00:17:14 INFO root - Starting Rasa server on http://localhost:5005 2020-01-29 00:17:14 DEBUG rasa.core.utils - Using the default number of Sanic workers (1). 2020-01-29 00:17:14 INFO root - Enabling coroutine debugging. Loop id 2231186310704. 2020-01-29 00:17:14 DEBUG rasa.model - Extracted model to ‘C:\Users\ADMINI~1\AppData\Local\Temp\tmpfmeokqyw’. 2020-01-29 00:17:20 INFO absl - Entry Point [tensor2tensor.envs.tic_tac_toe_env:TicTacToeEnv] registered with id [T2TEnv-TicTacToeEnv-v0] 2020-01-29 00:17:23 DEBUG rasa.core.tracker_store - Connected to InMemoryTrackerStore. 2020-01-29 00:17:23 DEBUG rasa.core.lock_store - Connected to lock store ‘InMemoryLockStore’. 2020-01-29 00:17:24 DEBUG rasa.model - Extracted model to ‘C:\Users\ADMINI~1\AppData\Local\Temp\tmp_dij6nsr’. 2020-01-29 00:17:24 DEBUG pykwalify.compat - Using yaml library: c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\ruamel\yaml_init_.py 2020-01-29 00:18:02 ERROR rasa.core.channels.twilio - Exception when trying to handle message.‘NoneType’ object has no attribute ‘replace’ 2020-01-29 00:18:02 DEBUG rasa.core.channels.twilio - ‘NoneType’ object has no attribute ‘replace’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 126, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’ Exception occurred while handling uri: ‘http://489eb39a.ngrok.io/webhooks/twilio/webhook’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\app.py”, line 942, in handle_request response = await response File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\asyncio\coroutines.py”, line 110, in next return self.gen.send(None) File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 126, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’

What message is being sent when this happens? Can you see its value and type?

Hi there is no message sent is just at the beginning of the conversation. I call Twilio number , as it is a trial I have to press a key and app is launched. Next I can hear the line ringing and a message from twilio stating that an error has occurred and the line shut down . Rasa server is successfully launched ngrok is working fine is just this mixture of rasa with twilio that does not work well. The link form debug is sending me to twilio.py line126

-- coding: utf-8 --

import logging from sanic import Blueprint, response from sanic.request import Request from sanic.response import HTTPResponse from twilio.base.exceptions import TwilioRestException from twilio.rest import Client from typing import Dict, Text, Any, Callable, Awaitable, Optional

from rasa.core.channels.channel import InputChannel from rasa.core.channels.channel import UserMessage, OutputChannel

logger = logging.getLogger(name)

class TwilioOutput(Client, OutputChannel): “”“Output channel for Twilio”""

@classmethod
def name(cls) -> Text:
    return "twilio"

def __init__(
    self,
    account_sid: Optional[Text],
    auth_token: Optional[Text],
    twilio_number: Optional[Text],
) -> None:
    super(TwilioOutput, self).__init__(account_sid, auth_token)
    self.twilio_number = twilio_number
    self.send_retry = 0
    self.max_retry = 5

async def _send_message(self, message_data: Dict[Text, Any]):
    message = None
    try:
        while not message and self.send_retry < self.max_retry:
            message = self.messages.create(**message_data)
            self.send_retry += 1
    except TwilioRestException as e:
        logger.error("Something went wrong " + repr(e.msg))
    finally:
        self.send_retry = 0

    if not message and self.send_retry == self.max_retry:
        logger.error("Failed to send message. Max number of retires exceeded.")

    return message

async def send_text_message(
    self, recipient_id: Text, text: Text, **kwargs: Any
) -> None:
    """Sends text message"""

    message_data = {"to": recipient_id, "from_": self.twilio_number}
    for message_part in text.split("\n\n"):
        message_data.update({"body": message_part})
        await self._send_message(message_data)

async def send_custom_json(
    self, recipient_id: Text, json_message: Dict[Text, Any], **kwargs: Any
) -> None:
    """Send custom json dict"""

    json_message.setdefault("to", recipient_id)
    if not json_message.get("media_url"):
        json_message.setdefault("body", "")
    if not json_message.get("messaging_service_sid"):
        json_message.setdefault("from", self.twilio_number)

    await self._send_message(json_message)

class TwilioInput(InputChannel): “”“Twilio input channel”""

@classmethod
def name(cls) -> Text:
    return "twilio"

@classmethod
def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> InputChannel:
    if not credentials:
        cls.raise_missing_credentials_exception()

    # pytype: disable=attribute-error
    return cls(
        credentials.get("account_sid"),
        credentials.get("auth_token"),
        credentials.get("twilio_number"),
    )
    # pytype: enable=attribute-error

def __init__(
    self,
    account_sid: Optional[Text],
    auth_token: Optional[Text],
    twilio_number: Optional[Text],
    debug_mode: bool = True,
) -> None:
    self.account_sid = account_sid
    self.auth_token = auth_token
    self.twilio_number = twilio_number
    self.debug_mode = debug_mode

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

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

    @twilio_webhook.route("/webhook", methods=["POST"])
    async def message(request: Request) -> HTTPResponse:
        sender = request.form.get("From", None)
        text = request.form.get("Body", None)

        out_channel = self.get_output_channel()

        if sender is not None and message is not None:
            metadata = self.get_metadata(request)
            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(),
                        metadata=metadata,
                    )
                )
            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("", status=204)

    return twilio_webhook

def get_output_channel(self) -> OutputChannel:
    return TwilioOutput(self.account_sid, self.auth_token, self.twilio_number)

line 126 start where is : if sender is not None and message is not None

Although you’re not sending a text message, the contents of the message variable could still give a clue to what is going on - can you print out it’s value?

how can I do that ? just print(message) ?

You could add it to the logger - add request as well, since that’s where the value of text comes from e.g.:

async def message(request: Request) -> HTTPResponse:
    sender = request.form.get("From", None)
    text = request.form.get("Body", None)

    out_channel = self.get_output_channel()

    if sender is not None and message is not None:
        metadata = self.get_metadata(request)
        try:
            logger.debug(request)
            logger.debug(message)
            .....

I am eager to hear how you’re implementing Rasa to Twilio Voice. I’ve been trying to figure out the way to do this through Twilio SIP <> Asterisk <> Google Cloud Speech <> Rasa.

At the moment I am a bit stuck but will get there . In essence should work as simple as adding credentials and configure webhook.

Could you share this information with me, sir? I mean seems pointless to do the GCS and Asterisk hassle if it is doable with straight integration to Twilio Voice.

read documentation on twilip voice programming

I came with a bit new stuff . This is the original error :

Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\app.py”, line 918, in handle_request handler, args, kwargs, uri = self.router.get(request) File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\router.py”, line 407, in get return self._get(request.path, request.method, “”) File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\router.py”, line 470, in _get raise NotFound(“Requested URL {} not found”.format(url)) sanic.exceptions.NotFound: Requested URL /favicon.ico not found <function TwilioInput.blueprint..message at 0x00000162734320D0> 2020-02-04 11:52:00 ERROR rasa.core.channels.twilio - Exception when trying to handle message.‘NoneType’ object has no attribute ‘replace’ 2020-02-04 11:52:00 DEBUG rasa.core.channels.twilio - ‘NoneType’ object has no attribute ‘replace’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 127, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’ Exception occurred while handling uri: ‘http://cf772c6b.ngrok.io/webhooks/twilio/webhook’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\app.py”, line 942, in handle_request response = await response File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\asyncio\coroutines.py”, line 110, in next return self.gen.send(None) File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 127, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’

How things are happening - After setting up everything , credentials etc etc to Programmable voice in Twilio, I place a call. first because it is a trial account I do receive a voice message stating so and is asking to press any button to run my code then it is a ring and an error voice message (with no delay allowing me to speak) saying that it was an error and it hung up straight away.

from twilio support I have this message :

Hi Cristian,

Thanks for sharing your code.

It looks like the problem is because the variable text is coming from a Body parameter, however this Body parameter is only included by Twilio for incoming SMS messages. It is not included for incoming voice calls.

This code is a bit buggy. If you would like to fix it yourself, I’ve highlighted the suggested lines to change message to text, in bold. But if you prefer you can also contact the developer or vendor first. @twilio_webhook.route("/webhook", methods=[“POST”]) async def message(request: Request) -> HTTPResponse: sender = request.form.get(“From”, None) text = request.form.get(“Body”, None)

        out_channel = self.get_output_channel()

        if sender is not None and text is not None:
            metadata = self.get_metadata(request)
            print(text)
            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(),
                        metadata=metadata,
                    )
                )
            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("", status=204)

However please be aware that an empty response will not work with incoming voice calls. It would only work with incoming messages.

The error changes to 2020-02-04 12:07:16 DEBUG rasa.core.channels.twilio - Invalid message so the ‘fix’ is not working.

I have made changes as per your suggestion and the result looks pretty much the same as initial error

2020-02-04 12:11:33 DEBUG rasa.core.channels.twilio - <Request: POST /webhooks/twilio/webhook> 2020-02-04 12:11:33 DEBUG rasa.core.channels.twilio - <function TwilioInput.blueprint..message at 0x0000014145E320D0> <function TwilioInput.blueprint..message at 0x0000014145E320D0> 2020-02-04 12:11:33 ERROR rasa.core.channels.twilio - Exception when trying to handle message.‘NoneType’ object has no attribute ‘replace’ 2020-02-04 12:11:33 DEBUG rasa.core.channels.twilio - ‘NoneType’ object has no attribute ‘replace’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 129, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’ Exception occurred while handling uri: ‘http://cf772c6b.ngrok.io/webhooks/twilio/webhook’ Traceback (most recent call last): File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\sanic\app.py”, line 942, in handle_request response = await response File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\asyncio\coroutines.py”, line 110, in next return self.gen.send(None) File “c:\users\administrator\anaconda3\envs\tensorflowtest\lib\site-packages\rasa\core\channels\twilio.py”, line 129, in message text = text.replace("¡", “@”) AttributeError: ‘NoneType’ object has no attribute ‘replace’

Debugging from Twilio: error after replacing ‘message’ with ‘text’

Error - 11770

Empty response body

Twilio received a HTTP response with Transfer-encoding: chunked but an empty body.

Possible Causes

  • Server misconfiguration
  • Network disruptions

Possible Solutions

  • Verify that the server is serving a non-empty HTTP response
  • Verify that the network connection is stable

Request Inspector

  • Expand All

2020-02-04 12:07:16 UTC

Request

URL

Parameters

Message TextShow Raw

Msg “”
sourceComponent “12000”
ErrorCode “11770”
LogLevel “ERROR”
url https://cf772c6b.ngrok.io/webhooks/twilio/webhook

Response

Headers

Body

No body.

====================

Original error:

502 Bad Gateway errors

If your debugger is reporting a 502 Bad Gateway error, this may mean that Twilio’s internal server had trouble retrieving content from your website. Your request must contain a Content-Type that is valid. Twilio may also have had problems resolving your DNS name to an IP address, or issues with the network connection. Check that your web server is started, and is available over the public Internet.

Request Inspector

  • Expand All

POST

https://cf772c6b.ngrok.io/webhooks/twilio/webhook

2020-02-04 12:11:33 UTC

500

Request

URL

ParametersShow Raw

Message TextShow Raw

Msg “An attempt to retrieve content from https://cf772c6b.ngrok.io/webhooks/twilio/webhook returned the HTTP status code 500”
msg “An attempt to retrieve content from https://cf772c6b.ngrok.io/webhooks/twilio/webhook returned the HTTP status code 500”
sourceComponent “12000”
ErrorCode “11200”
httpResponse “500”
LogLevel “ERROR”
url https://cf772c6b.ngrok.io/webhooks/twilio/webhook

Response

Headers

X-Cache MISS from Twilio-Cache X-Cache-Lookup MISS from Twilio-Cache:3128 Access-Control-Allow-Credentials true X-Twilio-WebhookAttempt 1 X-Twilio-WebhookRetriable false Content-Length 144 Date Tue, 04 Feb 2020 12:11:33 GMT Content-Type text/html; charset=utf-8

BodyShow Raw

Internal Server Error

The server encountered an internal error and cannot complete your request.

no help

I realize this is a pretty old thread, but if you’re still interested in connecting your bot to Twilio, I just completed a tutorial you may want to check out. I cover every little step because I just implemented it for a prototype for work, and took careful notes.

Hope this helps

1 Like