Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Chatbot With Angular 5 and DialogFlow

DZone's Guide to

Chatbot With Angular 5 and DialogFlow

I have seen many posts on how to build a chatbot for a wide variety of collaboration platforms such as Slack, Facebook Messenger, HipChat ... So I decided to...

· AI Zone ·
Free Resource

Easily enforce open source policies in real time and reduce MTTRs from six weeks to six seconds with the Sonatype Nexus Platform. See for yourself - Free Vulnerability Scanner. 

I have seen many posts on how to build a chatbot for a wide variety of collaboration platforms such as Slack, Facebook Messenger, and HipChat. So, I decided to build a chatbot from scratch to production using Angular (latest release v5.0.0), DialogFlow, and AWS.

Here is how our chatbot will look at the end of this post:

Note: This project is open-source and can be found on my GitHub.

To get started, create a brand new Angular project using the Angular CLI:

ng new smartbot --style=scss

1. Chatbot Architecture

We will split our chat app into different components and each component will be able to communicate with others using attribute directives:

2. Message Entity

Create an empty class by issuing the following command:

ng generate class models/message

The message entity has 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;
  }
}

3. Message List Component

Generate a new component:

ng generate component components/message-list

Now, we can 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 code of this component 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 the usage of @app/models instead of the relative path; it's called an alias. To be able to use aliases, we have to add the paths properties to our tsconfig.json file like this:

"paths" : {
  "@app/*" : ["app/*"],
  "@env/*" : ["environments/*"]
}

Note: I also added @env alias to be able to access environment variables from anywhere in our application.

4. Message Item Component

Let's build a component that will simply display a message in our message list:

ng generate component components/message-item

In message-item.component.html, add the following content:

<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 code of the 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() {
  }

}

5. Message Form Component

Let's build the form that will be responsible for sending the messages:

ng generate component components/message-item

In message-form.component.html, add the following content:

<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 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() method will be called each time a user clicks the Send button.

That's it! Try it by yourself and you will see that it's working.

ng serve

At this moment, you won't get any response — that's where NLP comes into play

6. NLP Backend

I choose to go with DialogFlow. Sign up for DialogFlow and create a new agent:

Then, enable the Small Talk feature to have a simple chat:

Note: You can easily change the responses to the questions if you don't like them. To go further, you can create your own Intents & Entities as described in my previous tutorial.

Copy the DialogFlow Client Access Token. It will be used for making queries.

Paste the token into your environments/environment.ts file:

export const environment = {
  production: false,
  token: 'YOUR DIALOGFLOW TOKEN'
};

7. DialogFlow Service

Generate a DialogFlow Service that will make calls the DialogFlow API to retrieve the corresponding response:

ng generate service services/dialogflow

It uses the DialogFlow API to process natural language in the form of text. Each API requests include the Authorization field in the HTTP header.

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;
  }
}

Update the sendMessage() method 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');
  }

Finally, in app.component.html, 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>

8. Deployment to AWS

Generate production-grade artifacts:

ng build --env=prod

The build artifacts will be stored in the dist/ directory.

Next, create an S3 bucket with the AWS CLI:

aws s3 mb s3://smartbot-mlabouardy

Upload the build artifacts to the bucket:

aws s3 cp dist/ s3://smartbot-mlabouardy --recursive --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers

Finally, turns website hosting on for your bucket:

aws s3 website s3://smartbot-mlabouardy --index-document index.html

If you point your browser to the S3 Bucket URL, you should see the chatbox:

And that's it!

Automate open source governance at scale across the entire software supply chain with the Nexus Platform. Learn more.

Topics:
ai ,tutorial ,chatbot ,bot development ,angular 5 ,dialogflow ,aws ,nlp

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}