Making a WhatsApp Crypto Chatbot with AWS Lex, CDK, CoinMarketCap, and Twilio
Tags: aws, python, todayilearned, tutorial
Published: 2022-05-21 14:51:37

## What is a Chatbot?

A chatbot is a software or computer program that simulates human conversation or "chatter" through text or voice interactions.

Amazon Lex is a fully managed artificial intelligence (AI) service with advanced natural language models to design, build, test, and deploy conversational interfaces in applications.

This article aims to create an automated agent that will retrieve information about the current prices and trends of the crypto market.

**Requirements**

- AWS account
- NPM / CDK / Python 
- Coinmarketcap API key
- Twilio account (optional)

## Walkthrough
Let's create an account in CoinMarketCap to get our API Key. Feel free to choose the plan that adjusts to your use case, but the basic plan is good enough for this example.
![Key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew862kpqsshx37t9hzn4.png)
With our API Key, create a Parameter Store to store this value.
```
/dev/crypto-bot/COIN_MARKETCAP_API_KEY : <<your-api-key>>
```
For this example, I will use a clear string for the API Key value, but it is recommended to secure the string with an encrypted  AWS KMS key.
![Parameter store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kc4799bfz7j5acoiv28.png)
Now lets begin creating our project with cdk, after we configure our aws credentials, run:

```
cdk init sample-app --language python
```
In our `requirements.txt` file lets add the following dependencies:

```
#requirements.txt
aws-cdk-lib==2.23.0
constructs>=10.0.0,<11.0.0
python-coinmarketcap==0.3
requests==2.27.1
boto3>=1.15.0
```

**python-coinmarketcap** is a dependency that wraps Coinmarketcap API very nicely; feel free to use this dependency or to use a direct implementation which you can find [here](https://coinmarketcap.com/api/documentation/v1/#section/Quick-Start-Guide).
**boto3** is a dependency that acts as the [AWS SDK for Python](https://aws.amazon.com/sdk-for-python/?nc1=h_ls); this will be used to access the Parameter Store previously created.

In our `app.py` file you can change the name of the project and the name of the stack, for this example I will name it cbot.

```python
#app.py
import aws_cdk as cdk

from cbot.cbot_stack import CbotStack


app = cdk.App()
CbotStack(app, "cbot")

app.synth()
```
Create a folder with the name of your project (`cbot`), and create or rename the name of the stack file (`cbot_stack.py`). In this stack, we will create a lambda, give that lambda access to our Parameter Store, and create a layer to add our dependencies.

{% gist https://gist.github.com/bdllerena/6ff375f96a51898e270a6d5c207d379b %}

Create a folder named lambda, and create a cbot_handler.py. In this lambda, we will use the CoinMarketCap API, which will interact with our slot intent.

```python
#cbot_handler.py
def search_crypto(intent_request):
    session_attributes = get_session_attributes(intent_request)
    slots = get_slots(intent_request)
    crypto = get_slot(intent_request, "crypto")
    api_key = ssm.get_parameter(Name="/dev/crypto-bot/COIN_MARKETCAP_API_KEY")
    cmc = coinmarketcapapi.CoinMarketCapAPI(api_key["Parameter"]["Value"])
    r = cmc.cryptocurrency_info(symbol=crypto.upper())
    text = repr(r.data[crypto]["description"])
    message = {"contentType": "PlainText", "content": text}
    fulfillment_state = "Fulfilled"
    return close(intent_request, session_attributes, fulfillment_state, message)
```
{% gist https://gist.github.com/bdllerena/88281c4626e2a78451ec0da960c43a3e %}
Our project should look a bit like this:
![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5phjwhul322dgcfsemwe.png)

Run the cdk bootstrap command to prepare our account to handle cdk deployments.
 
```
cdk bootstrap
```
Now we are ready to deploy our lambda into our account
```
cdk deploy
```
Let's start with the final step, create a bot using the AWS Lex service

- Creation method > Create a blank bot
- Bot configuration > Name your bot
- IAM permissions > Create a role with basic Amazon Lex permissions
- Children’s Online Privacy Protection Act (COPPA) > No
- Language > English (US)

Create a Welcome Intent; let's add some examples that our bot will learn and detect our intent

![Sample Utterance 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vu55ceq4hl8rek5fyz7u.png)
Add our bot response to the fulfillment section
![Fulfilment 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxfnh7sf7kfcb32c6fdo.png)
Test our bot, if we configure our intents properly it should response with our fulfillment text
![Test Bot 1 ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upce8k59vlyrmcw4yhhf.png)
Configure the text of the fallback intent, if something goes wrong this intent should catch this error and show a generic error message
![Fallback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy9g8hzjolijyxzvqd3v.png)
Save the intent, build and test. If you write something that we didn't add to the utterance examples, it should trigger our fallback intent.
![Test Fallback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5fnmy1h8hzpcojz3eog.png)
Create another intent named CryptoSearch; let's add some utterance examples to detect if a user wants to search about crypto
![Crypto Intent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19a3kpx6fcmty10aamyv.png)
Add a slot. In this slot, we will capture the crypto symbol we would like to search with our CoinMarketCap API; you can define a specific type of data, but for simplicity, I will use the integrated type AMAZON.FirstName to capture the value inputed by the user. (Be sure to name it identical to our code in our lambda.)
![Slot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5kp058arl6quvspka4g.png)
Under Deployment in Aliases, let's add our lambda, be sure to create a production alias when you move your bot to production. For this example, we will use the default alias

![Aliases](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eufjqvf0r76zd38sitg1.png)

![Language](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s7frlye07bzyh6wvz7uf.png)
![Lambda Function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idqjj4oc7uhl5pwu22u6.png)
In the fulfillment section of our CryptoSearch intent, be sure to use our lambda function 
![Codehook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7ds1ctncvwug6lxpi8i.png)
Save the intent, build and test our bot. Now we can retrieve information about any crypto that CoinMarketCap supports! We can even try fancy things like plotting, creating trends, or showing candle graphs.
![CryptoBot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59ho9cax1p7ri19d8kmc.png)
Now let's integrate our bot into social media. In this example, I will use Twillio to publish our bot into WhatsApp, create an account in Twilio and copy the SID and Authentication values.
In AWS, lex select Channels, select Twilio and create the channel integration.
![Twillio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b5mmupcbzuuyt9by8r9.png)
Copy the callback URL generated in our integration.
![Callback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zasuqlthez0ijh4m3339.png)
In the Twilio, dashboard, select message and set up a Twilio Sandbox for Whatsapp; here, we will copy our callback URL, which will connect the messages sent from WhatsApp to our bot in AWS Lex.
![Twilio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/auk96glfd11cbxnu1uqs.png)
And.. that's it! Now our bot works with WhatsApp and Lex.
![WhatsApp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwdyjc0jl9hqu8d79zku.png)

You can find the complete code [here](https://github.com/bdllerena/aws-lex-cypto-bot)
## References:

- [CoinMarketCap API](https://coinmarketcap.com/api/documentation/v1/)
- [Twilio Lex Integration](https://docs.aws.amazon.com/es_es/lex/latest/dg/twilio-bot-association.html)