There are so many ways to build a chatbot by using a wide variety of collaboration platforms such as Slack, Facebook Messenger, and HipChat etc.
But here we will build a chatbot from scratch to production using Angular (latest release), DialogFlow, and AWS.
To get started, we have to create a brand new Angular project using the Angular CLI:
ng new smartchatbot --style=scss
Here we will split our chat application into different components and where each component will be able to communicate with each others using attribute directives
Here we create an empty class by using the following command:
ng generate class models/message
This message entity will have three fields:
export class Message {
content: string;
timestamp: Date;
avatar: string;
constructor(content: string, avatar: string, timestamp?: Date){
this.content = content;
this.timestamp = timestamp;
this.avatar = avatar;
}
}
Now generate a new component by using below command :
ng generate component components/message-list
Now, we can show(display) the messages by iterating over them:
<div class="chatlist">
<ul class="list-group">
<message-item *ngFor="let msg of messages" [message]="msg"></message-item>
</ul>
</div>
The component of this should look like this :
import { Component, OnInit, Input } from '@angular/core';
import { Message } from '@app/models';
@Component({
selector: 'message-list',
templateUrl: './message-list.component.html',
styleUrls: ['./message-list.component.scss']
})
export class MessageListComponent implements OnInit {
@Input('messages')
private messages : Message[];
constructor() { }
ngOnInit() {}
}
Note we have used @app/models
instead of the relative path; it's called an alias. To be able to use aliases, we have to add the paths(
as shown below) properties to our tsconfig.json
file like this:
"paths" : {
"@app/*" : ["app/*"],
"@env/*" : ["environments/*"]
}
Note: here we have also added @env
alias to be able to access environment variables from anywhere in our application.
Now let's build a component that will going display a message in our message list so now we will create a component as below :
ng generate component components/message-item
In message-item.component.html
, we will add the following :
<li class="list-group-item">
<img [src]="message.avatar" class="avatar"/>
<div class="message">
{{message.content}}
</div>
<div class="timeform">
<i class="fa fa-clock-o" aria-hidden="true"></i> <span class="timestamp">at {{message.timestamp | date : 'dd/MM/yyyy' }}</span>
</div>
</li>
The structure of this component should look like this:
import { Component, OnInit, Input } from '@angular/core';
import { Message } from '@app/models';
@Component({
selector: 'message-item',
templateUrl: './message-item.component.html',
styleUrls: ['./message-item.component.scss']
})
export class MessageItemComponent implements OnInit {
@Input('message')
private message: Message;
constructor() { }
ngOnInit() {
}
}
Now let's build the form through which we will be able to send the messages:
ng generate component components/message-item
Now, In message-form.component.html
, we will add the following :
<div class="chatcontrol">
<input type="text" class="form-control chatinput" [(ngModel)]="message.content"/>
<button class="btn btn-success sendbtn" (click)="sendMessage()">Send</button>
</div>
And here its corresponding typescript code in message-form.component.ts
:
import { Component, OnInit, Input } from '@angular/core';
import { Message } from '@app/models';
@Component({
selector: 'message-form',
templateUrl: './message-form.component.html',
styleUrls: ['./message-form.component.scss']
})
export class MessageFormComponent implements OnInit {
@Input('message')
private message : Message;
@Input('messages')
private messages : Message[];
ngOnInit() {
}
public sendMessage(): void {
this.message.timestamp = new Date();
this.messages.push(this.message);
this.message = new Message('', 'assets/images/user.png');
}
}
The sendMessage()
function will be called each time a user clicks the Send button.
That's it! Now you will see that it's working
ng serve
Right now At this moment, you won't get any kind response — that's where NLP comes in :
Here we have choose to go with DialogFlow. Sign up to DialogFlow and create a new chat agent:
Then, follow the step and enable the Small Talk feature to have a simple chat:
Note: Here you can easily change the responses to the questions if you don't like them. moving forward ,now you can create your own Intents & Entities
Now you have to copy the DialogFlow Client Access Token. It will be used for making queries.
And then Paste the token into your environments/environment.ts
file as shown below :
export const environment = {
production: false,
token: 'YOUR DIALOGFLOW TOKEN'
};
Now generate a DialogFlow Service that will make some calls the DialogFlow API to retrieve the corresponding response from it as shown below :
ng generate service services/dialogflow
This uses the DialogFlow API to process normal language in the form of text. Each API requests include the Authorization field in the HTTP header portion :
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import { environment } from '@env/environment';
@Injectable()
export class DialogflowService {
private baseURL: string = "https://api.dialogflow.com/v1/query?v=20150910";
private token: string = environment.token;
constructor(private http: Http){}
public getResponse(query: string){
let data = {
query : query,
lang: 'en',
sessionId: '12345'
}
return this.http
.post(`${this.baseURL}`, data, {headers: this.getHeaders()})
.map(res => {
return res.json()
})
}
public getHeaders(){
let headers = new Headers();
headers.append('Authorization', `Bearer ${this.token}`);
return headers;
}
}
Now we have to update the sendMessage()
function in MessageFormComponent
as follows:
public sendMessage(): void {
this.message.timestamp = new Date();
this.messages.push(this.message);
this.dialogFlowService.getResponse(this.message.content).subscribe(res => {
this.messages.push(
new Message(res.result.fulfillment.speech, 'assets/images/bot.png', res.timestamp)
);
});
this.message = new Message('', 'assets/images/user.png');
}
And finally, in app.component.html
, we will copy and paste the following code to include the message-list
and message-form
directives:
<div class="chatform">
<message-list [messages]="messages"></message-list>
<message-form [message]="message" [messages]="messages"></message-form>
</div>
Generate production-build :
ng build --env=prod
This build artifacts will be stored in the dist/
directory.
Next step is , we create an S3 bucket with the AWS CLI as below :
aws s3 mb s3://smartchatbot-mlabouardy
Now we will upload the build to the bucket:
aws s3 cp dist/ s3://smartchatbot-mlabouardy --recursive --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
Finally,we will turns website hosting on for the bucket:
aws s3 website s3://smartchatbot-mlabouardy --index-document index.html
Now If we point our browser to the S3 Bucket URL, we should see the chatbox.
Thanks,
Shreyash Singh