How to Build a Product that Dominates the Market!

I’ve been developing software products for over 5 years now. It’s not a very long time, but within these years my team was able to build a product that captured the marketplace and generates positive cash flow for the company. In this blog post, let me share some of my learnings and pointers to build a market-winning product that can be applied to any type of projects (be it a small, medium or large).

A Market Winning Product

What really is a Market Winning Product? Well, any product that wins the market has the following common characteristics.

  • It is easy to sell
  • It keeps the existing customers happy
  • It acquires new customers all the time
  • It attracts the competitors’ customers
  • It continuously evolves to stay the best

If your product has the above characteristics, Congratulations! you got a market-winning product. If not keep reading.

Get Everybody on the Same Page

You may be building your own product or you are working for somebody else. Either case, You must be sold to your product first. Not only yourself but also your teams i.e developers, QA guys, marketers, CTO, CEO, and everybody else must be 100% sold to the product you build and believe it is the best product that delivers great value to you and the customers.

When everybody in your team honestly believes that your product delivers great value, they will do whatever it takes to make it a winning product. Let me give you an example. If you are a salesperson, wouldn’t that be very easy for you to sell your product if you know how your product delivers value to yourself? You wouldn’t have to use cheap sales gimmicks in the sales process instead share your experience with the customer to close the deal.

Let’s take another example. If you are a developer of the product, wouldn’t that be easy for you to understand the pain points of your product as a consumer? You would also know what new features you’d really love to see in your product as well.

So, if your team believes on the product, everybody will be on the same page and always wanted to make it a winning product. Changing your team’s mindset is the foundation for the success of your product. With that right mindset, everything else mentioned in this post will be easy to achieve.

It’s All about Synergy

Most companies have multiple teams dedicated to a product. One team develop the product, Another team assures the quality of the product, Another team handles operations and another team does sales and marketing of the product. If the teams are synergized, trust and depend upon each other, there will be very fewer conflicts among teams. Everybody thinks they are equals and all that they do is contribute to building a great product that serves people.

Let me give an example, imagine that you are building a “GDPR Compliance Platform”. After the first release, marketers start the marketing process. This tool is new to the marketplace, hence there will be many feedbacks from potential customers. When these concerns are brought forward to developers, they should understand the importance of these new changes in order to convert those leads into actual paying customers. Same time, with regular and transparent communication between the marketing team and the development team, they will have a clear idea about what new features to be developed and what improvements are required. Hence, while marketers promise new features to potential buyers, the development team can focus on implementing the features.

In order to have synergy among teams, it is absolutely vital to have all the teams on the same page. So how to do that, remember the first point, They must be completely sold to the product they are building and do whatever it takes to make it a winning product.

Defeating the Obscurity

Obscurity is the number one challenge to any new product. No matter how great your product and its content is, if people don’t know about it, they will not buy it and your company will eventually fail.

How would you address obscurity? Both the marketing team and the development team must assume responsibility for that. Marketing team must exhaust all mediums to get your product out to the potential buyers. Be it offline marketing or online marketing, they must understand effective marketing strategies and invest the marketing budget on them. For example, it could be social media campaigns, search engine optimization, training videos, events, conferences, and even cold-calling customers.

How can the development team help to defeat marketplace inertia? It’s very important to make the user onboarding process a breeze. Potential buyers must be able to try out the product with minimum entry barrier. For example, users should be able to self sign up for the product (maybe via a trial subscription) and interact with it. They need enough time to build trust and confidence with the product before they make the purchasing decision. Another important area that developers should focus on, is the “User Experience (UX)” of your product. As we all know, the first impression matters. If users that are trying out your product, don’t find it intuitive and easy to use, they will probably pass the deal.

How about the ability of your product to integrate with other major products? When you are starting off, it is absolutely important to build trust with the customers. If you could build partnerships with major players who are already trusted by millions of people, your product and the brand will also prove its trustworthiness. So it is important for your development team to build the product that is easily pluggable with other products with standard integration technologies.

Customer Satisfaction vs Customer Acquisition

Let’s imagine you are in the early stages of your product. You have several paying customers. At this stage, which one is the most important? Existing customer satisfaction or new customer acquisition? In my opinion, customer satisfaction should not even be a concern for your product. Because you and the team have developed a culture within the team, that you always over-deliver to your customers as your team is highly engaged with the product and understands what customers really need and do whatever it takes to accomplish them. Of course, you will receive customer complaints from time to time. While handling them effectively, you should always focus on new customer acquisition simply because you have a strong belief that the customers who aren’t using your product are already unsatisfied and they don’t even know it.

Never be Satisfied, Always Improve

When your product has captured the attention of the market place and acquired many customers, you should never be satisfied with the current state of the product. It’s time to use all the resources within the team if not find/outsource new resources to invest in innovation. You should set the bar so high, where your competition will think that you are out of their league, thus dominate the market place.

When it comes to innovation, you should expand the thinking in all areas of the product. It could be technological innovations such as Machine Learning, Artificial Intelligence, Blockchain etc… or It could be UI/UX innovations to improve the usability of the product or it could be anything else really. You and the team must pay attention to new trends in the market that could be mainstream in the future and adjust your product to become the early adopters of that area.

Summary

In this blog post, I discussed what it takes to build a product that dominates the market place. Everything starts with a change of mindsets. If you and your team don’t trust and believe your product in the first place, why would anyone else want to buy it? With that changed mindsets of the right set of people in the team, you will find that all the above points are easy to achieve to drive your product to dominate the market place.

Please follow and like us:

Improving the UX of your website with an intelligent chatbot | AWS Lex

Note: The video series of this blog post is available here.

User Experience is one of the most important concerns in building modern web applications. No matter how feature-rich is your website, if people don’t find it intuitive to use, you will not reach out to your potential customers.

AWS Lex allows users to easily interact with your website using natural language via a conversational chatbot. Your users can chat in voice or in text and use your product services without having to go through complex user interfaces.

As a developer, you don’t have to be a Machine Learning/Deep Learning expert to have a chatbot embedded into the website. AWS Lex provides advance deep learning functionalities and automatic speech recognition techniques out of the box.

In this post, we are going to create a conversational bot that finds weather information as per user’s requests. Following are the technologies that we will be using in this project.

  1. Amazon Lex
  2. Amazon Cognito
  3. AWS Lambda
  4. AWS IAM
  5. Amplify Library
  6. Angular Framework

Please find the github repo related to this post at https://github.com/mjzone/weather-bot

Getting the bot ready for training

First, let’s create our bot and get it ready for training. We want our bot to search for weather information when a user has requested it. In this guide, let’s only consider communication via text.

Login to AWS console and Go to AWS Lex

If you haven’t created a bot before select get started and you will be directed to the create bot window.

Creating a Custom Bot

We can either select already created bot or create our custom bot. Let’s select Custom Bot.

Let’s give our bot a name(I named it “WeatherBot”)and fill the other configurations as above image. Since we don’t enable voice select text-based application option. Afterward, click create and you will be presented with a new screen as below.

We need to understand the terminology for our bot in AWS Lex. There are 5 main points to remember.

  1. Intents
  2. Utterances
  3. Slots
  4. Prompts
  5. Fulfillment

Intents are the intentions why someone would use the bot. In our example, someone might want to know the weather of a particular city in the world. We will have an intent called “FindWeather”. We can have more than one intents for the bot. Another intent would be “GreetUser”. Utterances are how a user interacts with the bot stating different phrases. An example utterance can be “How is the weather in Colombo?”

When a user utters a phrase in text or invoice, the bot will match it to a corresponding intent. “How is the weather in Colombo” utterance will be matched to “FindWeather” intent. In order to fulfill the user’s intent, the bot will ask other required questions from the user. These questions are called “Prompts”. Once a user replied to a prompt that will be stored in variables for later use. These variable are called “Slots”. When all the required slots for a intent is collected, the bot will fulfill the intention of the user. The “fulfillment” may involve calling a 3rd party service to search for information, talking to a database, executing some logic in lambda function etc… Our example WeatherBot will talk to OpenWeatherMap API with the user requested city to search for weather information and send it back to the user.

Creating Intents

Click “Create Intent” button to create the first intent for our WeatherBot. Let’s call it “FindWeather” and Add it.

Now let’s add some sample utterances a user might ask. They will help our chatbot to learn about user inputs.

I have added three utterances as shown above. Note that two of those utterances has {City} variable. This is a required slot value for FindWeather intent. We can fill the slot using the user’s utterance itself. “Tell me about the weather” utterance doesn’t have {City} slot involved. So the bot will question the user about the city using a prompt.

In the Slots section, let’s add our City slot. We can define the Prompt message together with that. Our bot can use the intent to get the City slot filled from the user if it didn’t receive it already from the user’s initial utterance.

Our bot requires only one variable to search for the weather. That is the City. Once it is received from the user, the bot will call the action for Fulfillment of the intent.

In our case, let’s call a Lambda function that talks to OpenWeather API to search the weather for the requested City.

Creating the Lambda Function

Let’s use the Serverless Framework to create our lambda function. If you haven’t already installed Serverless Framework please visit this link.

Once you have installed the serverless framework and configure credentials with your AWS account, create a serverless service using below command.

serverless create --template aws-nodejs --path weather-bot

Once creation is completed, change directory into weather-bot folder and open the files in your favorite IDE.

serverless.yml

Let’s add a simple function as shown above. I will call it getWeather. The logic of the function lies in the handler.js file.

Lambda logic to obtain weather info from OpenWeatherMap API

I have obtained a free API key fromhttps://openweathermap.org/api and added it as a query parameter(APPID) in the URL. I extracted the “City” slot value that was taken by the user and passed it in the URL as well. “units” parameter is set to “metric” in order to get temperature values in Celsius.

I also used “axios” npm library to easily send HTTP requests to the server. You may also use the default “http” node module if you prefer. Note how the answer variable is constructed. It is created with string concatenation to form a natural language like the response. This response is returned from the lambda function as a special JSON object. This is required for our bot to read the answer properly. For more information about request/response JSON object template supported by AWS Lex see this link from official documentation.

Alright! Let’s deploy our lambda function using the following command. Before that, don’t forget to install axios library from npm

// First run
npm install axios
// Then run
serverless deploy

Once it is successfully deployed, go back to Lex console and select the lambda function name under the Fulfillment section.

Testing our bot

We have done all the configuration required from our side. Now let’s build the bot and let AWS Lex train its neural network. Once the build is complete we can test our bot.

Once it showed the success message, you can start testing it in the console itself.

The bot further asks a question since we didn’t provide it the city name.

As you can see, our bot successfully connected to OpenWeatherMap API sent us the Weather information for London city.

Adding our bot to the website

Now that we have an awesome bot, we need to add it to our production website so our users can directly interact with it.

Let’s create an angular website and use AWS Amplify library to connect to our WeatherBot securely. We need to install angular CLI and amplify CLI globally and configure amplify to with AWS credentials.

// Install angular cli globallynpm install -g @angular/cli
// Create a new angular projectng new my-bot-website --style=scss --routing
// Install amplify library globally
npm install -g @aws-amplify/cli
// Configure amplify with AWS IAM credentials
amplify configure

In order to communicate with our bot securely, we have to make sure only the logged in user can talk to it. As for the next steps let’s add a Login to the website and then use Amplify out of the box interaction component to connect to our WeatherBot.

Once a user is successfully logged into the application, AWS Cognito assigns him an IAM role. The Permission/Policies for invoking backend services are associated with this role. Since our user will communicate with the AWS Lex Chatbot, we need to provide permission for that authenticated role to call AWS Lex services. You can find the IAM role name that is assigned to logged in user at Cognito Identity Pool configuration.

I’m not going to add those steps in this blog as this post is already lengthy. Instead, let me share the Github URL for the code here.

https://github.com/mjzone/weather-bot

You can clone the code from the repo and run amplify init to initialize with your AWS resources. To run it on browser use amplify serve

You can use Amplify library itself to host your website along with the bot in an S3 bucket.

I hope someone will find this post useful.

Cheers!

Please follow and like us:

Sentiment Analysis with AWS Comprehend | AI/ML Series

In the last post we discussed on how to add speaking ability to our applications using AWS Polly. Let’s extend the same example to analyze the sentiments of the text that user types.

As usual, I recommend to watch the following video before reading this blogpost and use this post as a reference when building out the application by your own.

AWS Comprehend Service

AWS comprehend uses NLP to extract the insight about the content without needing any preprocessing requirements. It is capable of recognizing Entities, Languages, Sentiments, Key Phrases and other common elements of the given text or the document. One of the common use case of AWS Comprehend is to analyze the social media feed about your product and take necessary actions upon analyzing users valid sentiments.

Calling Comprehend API Methods

Let’s use AWS Lambda, our serverless function to talk to AWS Comprehend service and do a sentiment analysis. We are going to be using the API methods detectSentiment and detectDominantLanguage from AWS Comprehend javascript SDK. Refer the full SDK documentation here.

Firstly, we are creating an endpoint that triggers the Lambda function. Goto your serverless.yml and add this piece of code.

functions:
analyze:
handler: handler.analyze
events:
- http:
path: analyze
method: post
cors: true

It will create a new endpoint in the API Gateway with the path /analyze that will trigger analyze Lambda function. Here is the analyze function code which needs to be in the handler.js.

module.exports.analyze = (event, context, callback) => {
let body = JSON.parse(event.body);

const params = {
Text: body.text
};

// Detecting the dominant language of the text
comprehend.detectDominantLanguage(params, function (err, result) {
if (!err) {
const language = result.Languages[0].LanguageCode;

const sentimentParams = {
Text: body.text,
LanguageCode: language
};

// Analyze the sentiment
comprehend.detectSentiment(sentimentParams, function (err, data) {
if (err) {
callback(null, {
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(err)
});
} else {
callback(null, {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
});
}
});
}
});
}

At the top of the handler function, you need a reference to the Comprehend API from AWS-SDK. Then let’s first identify the dominant language of the text by calling detectDominantLanguage API method and pass that language code to the next API call detectSentiment inside the callback of the first method.

As a result, you will get the matching Sentiment and the matching percentage of Negative, Positive, Neutral and Mixed sentiment. Now, send that back to the frontend.

IAM Permission for AWS Comprehend

We are now almost finished with the backend, except we have to add a policy that allows AWS Comprehend permission to the IAM role attached to the Lambda function. If you haven’t read the part 01 of this series, read/watch it where I showed you how to setup an IAM role for the lambda.

Our IAM role was youtube-polly-actual-role. It had an arn and we refereed it in the serverless.yml file as follows.

arn:aws:iam::<account-id>:role/youtube-polly-actual-role

Goto IAM console of your AWS account and attach a new policy to that same role as shown below.

Setting up the Frontend

We have been using an Angular app as the frontend in the earlier project. Let’s continue adding a button below the user text area and call our API endpoint.

Goto app.component.html and add this simple html code to display an additional button next to “speak” button. We will display the returned sentiment value with a color below the button as well.

<div style="margin: auto; padding: 10px; text-align: center;">
<h2>Write Something...</h2>
<div>
<textarea #userInput style="font-size: 15px; padding: 10px;" cols="60" rows="10"></textarea>
</div>
<div>
<select [(ngModel)]="selectedVoice">
<option *ngFor="let voice of voices" [ngValue]="voice">{{voice}}</option>
</select>
</div>
<div style="margin-top: 10px">
<button style="font-size: 15px;" (click)="speakNow(userInput.value)">Speak Now</button>
<button style ="font-size: 15px;" (click)="analyze(userInput.value)">Analyze</button>
</div>

<!-- Following section will show the returned sentiment value with a suitable color -->

<div>
<h2 *ngIf="sentiment=='POSITIVE'" style="color: green;">{{sentiment}}! </h2>
<h2 *ngIf="sentiment=='NEUTRAL'" style="color: orange;">{{sentiment}} </h2>
<h2 *ngIf="sentiment=='NEGATIVE'" style="color: red;">{{sentiment}}! </h2>
</div>
</div>

Let’s add the analyze function in the app.compotent.ts file and make use of a service to call the API Gateway Endpoint.

import { Component } from '@angular/core';
import { APIService } from './api.service'

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})

export class AppComponent {
sentiment = null;
constructor(private api: APIService){}

analyze(input) {
let
data = {
text: input
}
this
.api.analyze(data).subscribe((result:any) => {
this
.sentiment = result.Sentiment;
});
}

}

Let’s call frontend API service to call the /analyze endpoint and return the data. Goto api.service.ts and add this code.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class APIService {

ENDPOINT = 'https://461xegl8zf.execute-api.us-east-1.amazonaws.com/dev';

constructor(private http:HttpClient) {}

speak(data) {
return this.http.post(this.ENDPOINT + '/speak', data);
}

analyze(data) {
return this.http.post(this.ENDPOINT + '/analyze', data);
}
}

Our frontend is now completed. It will send the user input to the backend endpoint and lambda function will figure out the language of the text and send sentiment analysis.

Result

Cheers!

Please follow and like us:

Building a Talking App | AI/ML Series

Welcome to another practical AWS tutorial. This is the written version of following YouTube video. I would recommend you to watch the video before reading the blog. Use this blog as the source to copy the code and practice by building the app by yourself.

AWS services used in the App

  • Amazon Polly
  • Amazon S3
  • AWS IAM
  • AWS Lambda

Creating a Serverless Project/Service

Install serverless framework by with npm and create a new nodejs project/service called backend.

npm install serverless -g
serverless create --template aws-nodejs --path backend

Now replace to serverless.yml file with following code, that creates a lambda function called “speak”.

service: talking-backend 

provider:
name: aws
runtime: nodejs8.10
region: us-east-1
role: arn:aws:iam::<account-id>:role/talking-app-role

functions:
speak:
handler: handler.speak
events:
- http:
path: speak
method: post
cors: true

The “speak” lambda function will send the text payload to AWS Polly and return the voice file from S3 bucket.

Creating a S3 Bucket

We need a S3 bucket to store all the voice clips that is returned by AWS Polly. Use AWS console to create the bucket with a unique name. In my case S3 bucket name is “my-talking-app”.

Create an IAM Role

Serverless framework creates two Lambda functions that interact with AWS Polly and AWS S3 services. (We shall see the code later in the blog). In order to communicate with these services, our Lambda function must be assigned an IAM role that has permission to talk to S3 and Polly. So create an IAM role with a preferred name i.e. “talking-app-role” with the following IAM policy.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "polly:*",
                "s3:PutAccountPublicAccessBlock",
                "s3:GetAccountPublicAccessBlock",
                "s3:ListAllMyBuckets",
                "s3:HeadBucket"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::my-talking-app",
                "arn:aws:s3:::my-talking-app/*"
            ]
        }
    ]
}

Copy the ARN of the IAM role and add it under the provider section of the serverless.yml file.

provider:
name: aws
runtime: nodejs8.10
region: us-east-1
role: arn:aws:iam::885121665536:role/talking-app-role

“Speak” Lambda Function

Speak Lambda function does three main tasks.

  1. Call AWS Polly synthesizeSpeech API and get the audio stream (mp3 format) for text that user entered
  2. Save the above audio stream in the S3 bucket
  3. Get a signed URL for the saved mp3 file in the S3 and send it back to the frontend application

First of all, let’s install the required npm modules inside the backend folder.

npm install aws-sdk 
npm install uuid

AWS Polly synthesizeSpeech API requires the text input and the voice id to convert the text into speech. Here, we use the voice of “Joanna” to speak the text that is passed from the frontend.

let AWS = require("aws-sdk");
let polly = new AWS.Polly();
let s3 = new AWS.S3();
const uuidv1 = require('uuid/v1');

module.exports.speak = (event, context, callback) => {
let data = JSON.parse(event.body);
const pollyParams = {
OutputFormat: "mp3",
Text: data.text,
VoiceId: data.voice
};

// 1. Getting the audio stream for the text that user entered
polly.synthesizeSpeech(pollyParams)
.on("success", function (response) {
let data = response.data;
let audioStream = data.AudioStream;
let key = uuidv1();
let s3BucketName = 'my-talking-app';

// 2. Saving the audio stream to S3
let params = {
Bucket: s3BucketName,
Key: key + '.mp3',
Body: audioStream
};
s3.putObject(params)
.on("success", function (response) {
console.log("S3 Put Success!");
})
.on("complete", function () {
console.log("S3 Put Complete!");
let s3params = {
Bucket: s3BucketName,
Key: key + '.mp3',
};

// 3. Getting a signed URL for the saved mp3 file
let url = s3.getSignedUrl("getObject", s3params);

// Sending the result back to the user
let result = {
bucket: s3BucketName,
key: key + '.mp3',
url: url
};
callback(null, {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : "*"
},
body: JSON.stringify(result)
});
})
.on("error", function (response) {
console.log(response);
})
.send();
})
.on("error", function (err) {
callback(null, {
statusCode: 500,
headers: {
"Access-Control-Allow-Origin" : "*"
},
body: JSON.stringify(err)
});
})
.send();
};

Now, deploy the backend API and the Lambda function

sls deploy

Frontend Angular App

In order to test our backend we need a frontend that makes speak request with user inputted text. So let’s create an angular application.

ng new client
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? SCSS

Let’s create an angular service that talks to our Amazon Polly backend.

ng g s API

Add the following code to the api.service.ts file. It will create speak function that call the lambda function with the selected voice and the inserted text by the user.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class APIService {

ENDPOINT = '<YOUR_ENDPOINT_HERE>';

constructor(private http:HttpClient) {}

speak(data) {
return this.http.post(this.ENDPOINT, data);
}
}

Let’s use the main appcomponent to render our UI for the “Talking App”. Goto app.component.html and replace the file with following HTML code. It will add a basic text-area, selection of preferred voice and speak action button.

<div style="margin: auto; padding: 10px; text-align: center;">
<h2>My Talking App</h2>
<div>
<textarea #userInput style="font-size: 15px; padding: 10px;" cols="60" rows="10"></textarea>
</div>
<div>
<select [(ngModel)]="selectedVoice">
<option *ngFor="let voice of voices" [ngValue]="voice">{{voice}}</option>
</select>
</div>
<div style="margin-top: 10px">
<button style="font-size: 15px;" (click)="speakNow(userInput.value)">Speak Now</button>
</div>
</div>

Goto app.component.ts file and add the corresponding hander function for the view. Replace it with the following code.

import { Component } from '@angular/core';
import { APIService } from './api.service'

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
voices = ["Matthew", "Joanna", "Ivy", "Justin"];
selectedVoice = "Mattew";

constructor(private api: APIService){}

playAudio(url){
let audio = new Audio();
audio.src = url;
audio.load();
audio.play();
}

speakNow(input){
let data = {
text: input,
voice: this.selectedVoice
}
this.api.speak(data).subscribe((result:any) => {
this.playAudio(result.url);
});
}
}

Since we are using, ngModel in the app.component.html we need to import the FormsModule in the app.module.ts file. Goto app.module.ts file and replace the content with,

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
FormsModule,
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Running the Application

Now that our backend and the frontend are ready, let’s play with our app.

Go to the client directory and run the angular app locally,

ng serve

Type some text on the text area and select a voice from the dropdown. When you click Speak Now it should speak the text aloud!

Cheers!

Please follow and like us: