The Research Nest
Published in

The Research Nest

How To Make Your Chatbot Tweet News For You

Building Yuki [Part 2]: Design And Implementation Of Twitter API Based Actions WIth Rasa 1.0 and Python

We are starting off right at where we left in part 1 of this series, Building Yuki, A Level 3 Conversational AI Using Rasa 1.0 And Python For Beginners. It’s a lengthy article but I would recommend you to give a quick read if you are new to Rasa before you read this one, but this can be considered as a stand-alone tutorial as well. We will be exploring different development approaches and features, which can be used for other kinds of software projects as well.

The main prerequisite to understanding this tutorial is your ability to read code. Make sure you are clear with the python syntax and read between the lines and you should be good to go.

(Note: Check the above article for the development setup I am using)

A Quick Recap: Features Implemented So Far

  • Fetch news from the internet using a keyword input by a user with the help of the NEWS API.
  • General chitchat responses, giving an introduction, thank you, and miscellaneous conversational flows.

In this tutorial, we are going to use Twitter API to give some interesting capabilities to Yuki, the name of the bot I am building.

Objectives

  1. Tweet the fetched news articles on Twitter.
  2. Delete the latest tweet if required.
  3. Make the project more structured for future implementations.

With that being said, let’s get started!

✔️ Checkpoint 1: Setting Up Your Twitter Developer Account

  • You need a twitter developer account to proceed further. Visit this URL- https://developer.twitter.com/en/docs/basics/getting-started. Follow the 6 instructions under the ‘How to get started with the Twitter API’. Most steps are self-explanatory.
  • After you get approval to your developer account, create an app in the developer portal, you should get your consumer API keys and Access Tokens required for authentication purposes and to access the Twitter API. This may take about 2–3 days. In the meantime, you can have the rest of the project ready.
  • Also, install the tweepy library using pip install tweepy in your virtual environment. This is a python wrapper for the Twitter API I will be using. It makes using Twitter API in python very easy.

✔️ Checkpoint 2: Create A File To Store All Your API Keys And Global Constants

  • Create a new python file to store all the global variables like API keys, tokens, and other sensitive information that must be confidential. It is a good practice to store such information elsewhere in some other folder and import it into our project. Never use passwords, tokens, etc directly in your code. I create a file called global_constants.pyin a separate folder.
# global_constants.pyNEWS_API_KEY = 'paste your news api key here'TWITTER_CONSUMER_KEY = 'paste your twitter consumer key here'TWITTER_CONSUMER_SECRET = 'paste your twitter consumer secret here'TWITTER_ACCESS_TOKEN = 'paste your access token here'TWITTER_ACCESS_TOKEN_SECRET = 'paste your token secret'
  • You can import all these variables by adding the following lines at the beginning of your actions.py file:
import sys
sys.path.append("C:/Users/adity/path to your file")
from global_constants import *

With this, you can use your variables names without exposing the actual values. You need not worry about removing the values while pushing your repository to GitHub or sharing your code. Also, I have moved my credentials.yml file outside my project directory for the same reason. While deploying online, you can pass on the path to that file to load the required information.

✔️ Checkpoint 3: Keep Your Project Well Organised

As we implement more and more features, the code can get quite ugly. To keep my project well structured, I made some changes as follows:

  • Created new python class files NewsEngine.py and TwitterEngine.pyin my project folder and removed the redundant code from actions.py
  • These python classes will contain all the methods I intend to implement related to those functionalities. I’ll be importing them into actions.py and then call the functions directly. The code is a bit cleaner this way.
# NewsEngine.py
import requests
class NewsEngine:
def __init__(self, topic, pageSize, NEWS_API_KEY):
self.topic = topic
self.pageSize = str(pageSize)
self.NEWS_API_KEY = NEWS_API_KEY
def fetchNews(self):
url = "https://newsapi.org/v2/everything?q=" + self.topic + "&apiKey=" + self.NEWS_API_KEY + "&pageSize=" + self.pageSize
r = requests.get(url=url)
data = r.json() # extracting data in json format
## data to be returned
data = data['articles']
return data
  • If you are new to python objects and classes, I recommend you read through the official documentation online to understand better before proceeding further. In short, these classes are like blueprints from which objects can be made. The NewsEngine I have here can instantiate (create) a News object with all the parameters we define.
  • In the TwitterEngine code, you can see that I used tweepy to make direct API calls. For now, I have used three APIs, one to update status (tweet), one to retrieve the latest tweet ID, using which I make another API call to delete that tweet.
  • In a similar manner, lessen the code cluttering in your own actions.py file. These classes can be in fact used in any other project as well. Just import them like done here and call the required method (function) that will return the required result.
# TwitterEngine.py
import tweepy
class TwitterEngine:
def __init__(self, tweet, TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET,TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET):
self.tweet = tweet
self.TWITTER_CONSUMER_KEY = TWITTER_CONSUMER_KEY
self.TWITTER_CONSUMER_SECRET = TWITTER_CONSUMER_SECRET
self.TWITTER_ACCESS_TOKEN = TWITTER_ACCESS_TOKEN
self.TWITTER_ACCESS_TOKEN_SECRET = TWITTER_ACCESS_TOKEN_SECRET
self.auth = tweepy.OAuthHandler(TWITTER_CONSUMER_KEY,TWITTER_CONSUMER_SECRET)
self.auth.set_access_token(TWITTER_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET)
self.api = tweepy.API(self.auth)
def doTweet(self):
self.api.update_status(status=self.tweet)
return []
def deleteLatestTweet(self):
latestTweetId = self.api.user_timeline(count=1)[0].id_str
self.api.destroy_status(latestTweetId)
return []

✔️ Checkpoint 4: Updated Actions File

Here is my actions.py at this stage. Carefully read through the code and you will understand how classes and objects are being used. It is simple and with little practice, you will get the flow.

actions.py

Notice the following details:

  • I created some utter templates to add more context. Remember to add extra functions and utterances as and when required for better user experience and caution. For example, I included a confirmation question for the deleteTweet feature.
  • So, how to come up with what additional supporting aspects are required? The answer lies in testing and debugging. You will never build the perfect product in the first go. Test your bot in several scenarios in real-time. Look for potential errors and places where the bot misbehaves, rectify and based on your own experience think how you can simply how users interact with it, and to avoid failure or confusion.
  • After doing the same, I defined some extra slots like topics_news_temp and utter actions like utter_ask_to_tweet, utter_ask_to_confirm, and utter_reply_to_deny. Basically, once the news is fetched, I am making the bot ask the user if he/she wants to tweet about it. If they want to, then the doTweet()method is called which I defined previously in TwitterEngine.py. The user also has an option to delete their latest tweet.
  • If you are still unsure of how the API calls are being made using tweepy, go to the official getting started documentation and test out the code given there manually in the iPython console or in a separate file to understand the details that need to be sent and what is retrieved or triggered. Don’t forget to cross-verify your twitter account to see that the API calls actually posted and deleted your tweets there.
  • Note that there are many other places to improvise further which we can cover in future tutorials.

✔️ Checkpoint 5: Updating Training Data And Domain.yml

  • All the new details included must be added to nlu.md, domain.yml, and stories.md as per rasa’s format as discussed in the first tutorial.
## intent:deleteTweet- delete the tweet
- delete my tweet
- remove the tweet you posted
- remove the tweet
- delete tweet

I added the NLU data for the intent to delete a tweet as above.

And here is my updated domain file, the heart of everything that makes Yuki.

domain.yml

Below are some basic training data stories that I added to stories.mdfor the features we implemented.

## deleteTweet flow 1
* deleteTweet
- utter_ask_to_confirm
* affirm
- delete_latest_tweet
## deleteTweet flow 2
* deleteTweet
- utter_ask_to_confirm
* deny
- utter_reply_to_deny

Once you are done with all these miscellaneous additions, you are all set for retraining the bot and do some interactive learning to check if the bot is working as expected. (Ps: Refer to part 1 for more info on these steps)

✔️ Checkpoint 6: Real-Time Testing

I have retrained my bot with all the new data. Now, let us see how it works. Userasa shell command in the terminal to start the bot, and run the actions server in a separate terminal with python -m rasa_sdk --actions actions command.

Here is a screenshot of the conversation in the terminal

Notice the yellow messages here. This is because I haven’t yet added the stories in the proper format that can be generated via interactive learning in the training data.

And Yuki tweeted as it said! It was authenticated to post on The Research Nest’s handle.

Here’s the tweet posted by Yuki on Research Nest’s Twitter account.

Now let’s see if its successfully able to delete a tweet, or respond when the user doesn’t want to tweet.

The delete conversation flow. (Added interactive training stories and retrained the bot at this stage)
The tweet was successfully deleted by Yuki. Hence no preview

This ideally helps when the user tells Yuki to tweet something by mistake.

The conversational flow when the user denies to tweet

So far, the twitter-based functionalities are working good. What does it signify? What else can we do?

✔️ Checkpoint 7: Thinking Beyond

The core step towards building software applications isn’t writing code. That, in fact, is the easiest of all. As you can see, integrating your app with Twitter API is a piece of cake. What really matters is how you use it after that, in a way that’s impactful and efficient. Here are some insights.

  • We are tweeting only news, but using the same logic, we can tweet anything else that the user wants.
  • Configuring an automated tweet response when something happens. You can have logic like if <something> happens, tweet this’. That ‘something’ can literally be any event that happens in real life or on the internet. Tweet when the ISS flies above your place, or tweet when it starts raining, tweet every time when Elon Musk tweets, and so on. And for everything like that, you can have a context-based algorithm that can generate the tweet.
  • Another interesting and widespread application of Twitter API is automated customer service. Let’s say someone tweets on twitter about your product. You can make functionality to fetch such a tweet, have a method to identify the context from the tweet and send back an appropriate reply to the user automatically.

✔️ Checkpoint 8: The Summary (And What’s Next For Yuki?)

We have successfully met the three small objectives we had in the beginning:

  1. Yuki can now tweet the news, as well as delete the latest tweet as per requirement.
  2. The project is now more structured, secure, and reusable as we separated the code into classes and removed secret tokens and keys. Remember that the classes I have implemented here can be used in any other kind of project by simply importing them to your workspace.

More stuff I plan to implement in the future:

  • Add more methods in the NewsEngine, like detecting the sentiment of the news, and fetching stuff from RSS feeds.
  • The TwitterEngine also needs some additions. Like tweeting other general stuff, etc.
  • I want to give Yuki a vision and a voice. I mentioned this in the previous article as well. I should see how I can make it happen.
  • Another small feature in the plans is to make Yuki understand and feel the weather. This can be used to make Yuki react with more context and add additional weather influenced functionalities. After all, Yuki means ‘snow’, it must have this ability!

Stay tuned for the next tutorial to explore more!

Endnotes:

Excited to see what you will build with the knowledge acquired. The possibilities are endless. Feel free to share in the responses below.

Got stuck up anywhere in development, let me know the issue in responses, and I’ll see if I can help you out. If you have read this far, a big thank you! I hope you found it useful and learned a thing or two along the way.

This article’s distribution settings are off, meaning it is not put under the paywall to ensure free access to everyone on the internet (at the expense of circulation by Medium curators). Share with a friend who might be interested and don’t forget to clap (it really helps!).

Do follow The Research Nest for more such tutorials and support our initiatives!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
XQ

XQ

Tech 👨‍💻 | Life 🌱 | Careers 👔 | Poetry 🖊️