User Experience is given a lot of attention while building any application these days. More and more brands are leveraging chatbots to service their customers, market their brand, and even sell their products.
There
are a lot of awesome tools out there which helps in building an
intelligent bot very easily like Google’s DialogFlow, Amazon Lex, etc,
most of which implement their own Natural Language Processing (NLP)
logic. However, in some cases, we don’t really need an intelligent bot.
Whenever
we have a small application having a limited set of options to choose
from, it’s not really necessary to use NLP based tools like Google’s
DialogFlow. You need to integrate with them (which is pretty easy
though), and you need to make a network call to get the results.
Instead, you would want to define your rules locally in those cases.
Here we will build a simple chatbot using React Simple Chatbot library and add it to our pizza-builder app using which we can build our own customized pizza through a chatbot assistant. The final project will look like below:
Getting Started
React
Simple Chatbot is a simple library which provides us a Chatbot
component to which we can pass the flow of the conversation as props.
Also, we can customize the styling of the chatbot. Let’s get started
with this by diving into the code.
Clone the code from https://github.com/hjaiswal/pizza-builder-tutorial. (Make sure you are working on the master branch). Install the chatbot library with the following command:
npm install react-simple-chatbot styled-components --save
styled-components is one of the dependencies of react-simple-chatbot without which it will fail. For more info, read here
Create a Chatbot component /src/components/chatbot/CustomChatbot.js
import React from "react"; import ChatBot from "react-simple-chatbot";function CustomChatbot(props) { const steps = [ { id: "Greet", message: "Hello, Welcome to our shop", trigger: "Done" }, { id: "Done", message: "Have a great day !!", end: true } ]; return <ChatBot steps={steps} />; }export default CustomChatbot;
Include this component in your Pizza component
import React, { Component } from "react"; import "./Pizza.css";..... Rest of the code .....import CustomChatbot from "./chatbot/CustomChatbot";class Pizza extends Component {..... Rest of the code ..... return ( <div> <div className="container mt-5"> ...... Rest of the code ..... <CustomChatbot /> </div> </div> ); } }export default Pizza;
Start the application with
npm start
. You will get a chat window on the bottom left of your screen like this:
If you want to resize your chatbot and want to make it collapsible, you can pass width, height, and floating property as props to the component.
function CustomChatbot(props) { const config = { width: "300px", height: "400px", floating: true }; const steps = [ { id: "Greet", message: "Hello, Welcome to our shop", trigger: "Done" }, { id: "Done", message: "Have a great day !!", end: true } ]; return <ChatBot steps={steps} {...config} />; } export default CustomChatbot;
Now you will see a collapsible element on the right bottom of the page. On clicking that, the chat window will open
Configuration
const steps = [
{
id: "Greet",
message: "Hello, Welcome to our shop",
trigger: "Done"
},
{
id: "Done",
message: "Have a great day !!",
end: true
}
];
Currently,
steps array in CustomChatbot component has two JSON objects. These JSON
objects will represent the flow of the conversation.
- id: identifier of the current step. It can be a string or a number. But I will recommend string as it’s more descriptive and if we decided to add a step in between, we don’t have to change the numbering. Required for any step
- message: the message that will be displayed on the chat window once the step is called
- trigger: the id of the next step to be triggered. It can also be a function returning the id of the step to go next
- end: if true indicates that this step is the last
In our case, in step Greet we are displaying the message “Hello, Welcome to our shop” and then calling the Done step in the trigger. In Done step, we are displaying the message “Have a great day !!” and then ending the conversation with “end: true”. Let’s make this conversation more interactive.
const steps = [
{
id: "Greet",
message: "Hello, Welcome to our shop",
trigger: "Ask Name"
},
{
id: "Ask Name",
message: "Please type your name?",
trigger: "Waiting user input for name"
},
{
id: "Waiting user input for name",
user: true,
trigger: "Asking options to eat"
},
{
id: "Asking options to eat",
message: "Hi {previousValue}, Glad to know you !!",
trigger: "Done"
},
{
id: "Done",
message: "Have a great day !!",
end: true
}
];
- user: if true indicates that bot have to wait for a user type action
- previousValue: the value we get from the previous step (in this case from the user input)
Here,
we are Greeting the user in the first step and then asking for a name
in the second step. In the third step, the conversation is halted and
it’s waiting for user response. As the user enters the name, it will be
stored in previousValue variable which
will be available in the next step. Then in the fourth step, the bot is
again greeting the user with their name that we got from the previous
step and in the fifth step, the conversation ends.
Let’s add an “option” feature where a list of options will be displayed and based on what the user selects, the next steps will be configured.
{
id: "Displaying options to eat",
options: [
{
value: "pizza",
label: "Pizza",
trigger: "Asking for Tomatoes in Pizza"
},
{
value: "burger",
label: "Burger",
trigger: "Burger Not available"
}
]
}
- options: list of options for the user to chose from, need to click on the option. Every option in the list is a JSON with three attributes
- value: attribute of JSON in the option, value will be set if the user clicks on the option. For eg, in the above step, two options will be displayed Pizza & Burger. If the user clicks on Pizza, the value of the step will the pizza and if the user clicks on Burger, value of the step will the burger
- label: this is what will be displayed on the chat window
- trigger: If the user clicks on Pizza, the next step will be Asking for Tomatoes in Pizza and if the user clicks on Burger, the next step will be Burger Not available . The trigger can also be a function like below. The return values will be the id of the next step
{
id: "Displaying options to eat",
options: [
{ value: "pizza",label: "Pizza",trigger: () => {
console.log("Clicked on Pizza");
return "Asking for Tomatoes in Pizza";
},
{ value: "burger",label: "Burger",trigger: () => {
console.log("Clicked on Burger");
return "Burger Not available";
}
]
}
Complete Conversation
Lets now add the complete conversation for the application
const steps = [ { id: "Greet", message: "Hello, Welcome to our shop", trigger: "Ask Name" }, { id: "Ask Name", message: "Please type your name?", trigger: "Waiting user input for name" }, { id: "Waiting user input for name", user: true, trigger: "Asking options to eat" }, { id: "Asking options to eat", message: "Hi {previousValue}, Please click on what you want to eat!", trigger: "Displaying options to eat" }, { id: "Displaying options to eat", options: [ { value: "pizza", label: "Pizza", trigger: "Asking for Tomatoes in Pizza" }, { value: "burger", label: "Burger", trigger: "Burger Not available" } ] }, { id: "Burger Not available", message: "Sorry, We don't have burger available at the moment. Would you like to try our pizza?", trigger: "Asking for pizza after burger" }, { id: "Asking for pizza after burger", options: [ { value: true, label: "Yes", trigger: "Asking for Tomatoes in Pizza" }, { value: "false", label: "No", trigger: "Done" } ] }, { id: "Asking for Tomatoes in Pizza", message: "Would you like to have tomatoes in your pizza", trigger: "Adding Tomatoes in Pizza" }, { id: "Adding Tomatoes in Pizza", options: [ { value: true, label: "Yes", trigger: () => { props.eventHandler("tomato"); return "Asking for Mushroom in Pizza" } }, { value: "false", label: "No", trigger: "Asking for Mushroom in Pizza" } ] }, { id: "Asking for Mushroom in Pizza", message: "Would you like to have mushroom in your pizza", trigger: "Adding Mushroom in Pizza" }, { id: "Adding Mushroom in Pizza", options: [ { value: true, label: "Yes", trigger: () => { props.eventHandler("mushroom"); return "Asking for Corn in Pizza" } }, { value: "false", label: "No", trigger: "Asking for Corn in Pizza" } ] }, { id: "Asking for Corn in Pizza", message: "Would you like to have corn in your pizza", trigger: "Adding Corn in Pizza" }, { id: "Adding Corn in Pizza", options: [ { value: true, label: "Yes", trigger: () => { props.eventHandler("corn"); return "Asking for Veggies in Pizza" } }, { value: "false", label: "No", trigger: "Asking for Veggies in Pizza" } ] }, { id: "Asking for Veggies in Pizza", message: "Would you like to have veggies in your pizza", trigger: "Adding Veggies in Pizza" }, { id: "Adding Veggies in Pizza", options: [ { value: true, label: "Yes", trigger: () => { props.eventHandler("veggie"); return "Done" } }, { value: "false", label: "No", trigger: "Done" } ] }, { id: "Done", message: "Have a great day !!", end: true } ];
In Pizza component, pass clickEventHandler as props to Chatbot component
<CustomChatbot eventHandler={this.clickEventHandler} />
Looks complex? Yes, but it’s really easy to follow. Let’s break it down:
- In step Greet, Chatbot will display the greeting message on the window
- In step Ask Name, Chatbot will display the message asking for the name
- In step Waiting user input for name, Chatbot will wait for the user to type their name, the value will be stored and passed on to next steps
- In step Asking options to eat, Chatbot will display user name using previousValue
- In step Displaying options to eat, Chatbot will display two eating options, Pizza and Burger. If the user selects Pizza option, Asking for Tomatoes in Pizza step will be triggered else Burger Not available step will be triggered on selecting Burger option
- If step Burger Not available is triggered, it will display the message and trigger the step Asking for pizza after burger which will display two options. If Yes option is clicked, it will trigger Asking for Tomatoes in Pizza step and if No option is clicked, “Done” step will be triggered and conversation will be finished
- In step Asking for Tomatoes in Pizza, Chatbot will ask the user if they want or not tomatoes and trigger Adding Tomatoes in Pizza step, which will display Yes and No options. If Yes is selected, props.eventHandler method will be called which is clickEventHandler function in Pizza component which will render the tomato component. If No is selected, Asking for Mushroom in Pizza step will be triggered
- Similar things will happen for other ingredients. Finally, the conversation will be finished when Done step will be triggered.
Styling
Styles can be added to the chatbot like window color, font size, font-family, etc. We need to import ThemeProvider from “styled-components” library and wrap our Chatbot inside this like the following:
import React from "react"; import ChatBot from "react-simple-chatbot"; import { ThemeProvider } from "styled-components";function CustomChatbot(props) { ..... Rest of the code ..... const theme = { background: "white", fontFamily: "Arial, Helvetica, sans-serif", headerBgColor: "#00B2B2", headerFontColor: "#fff", headerFontSize: "25px", botBubbleColor: "#00B2B2", botFontColor: "#fff", userBubbleColor: "#fff", userFontColor: "#4c4c4c" }; ..... Rest of the code ..... return ( <ThemeProvider theme={theme}> <ChatBot steps={steps} {...config} /> </ThemeProvider> );
The
application can be further improved. Currently, buttons for adding
ingredients are still active. It can be disabled while we are adding
ingredients through the chatbot. I will leave that for the readers to
implement
Congratulations,
you have successfully build a chatbot on React which should be
functioning like the video posted at the starting. The final codebase
can be found at this git link: https://github.com/hjaiswal/pizza-builder-tutorial (git branch: pizza-builder-with-chatbot)
Thanks a lot for reading the article. If you have questions, feel free to comment down below.
Comments
Post a Comment