はじめに
GAS(Google Apps Script)でLINEのbotを作り、そのbotが受け取ったメッセージをDialogflowで自然言語解析して応答させてみた、というお話です。
GASでLINEのbotを作る
ひとまずDialogflowはおいておいて、オウム返しするだけのbotを作ります。
環境構築
まずは以下の記事を参考にしつつ、GASのローカル開発環境を構築しました。
Google Apps Script をローカル環境で快適に開発するためのテンプレートを作りました
GAS を npm パッケージ + Webpack + TypeScript で開発する
実装
LINEのbotの実装については非常に多くの情報があるのでここでは深くは触れないことにします。
import { reply } from "./reply";
global.doPost = (e: any): void => {
reply(e);
};
export const reply = (e: any) => {
const accessToken: string = PropertiesService.getScriptProperties().getProperty(
"LINE_ACCESS_TOKEN"
);
const json = JSON.parse(e.postData.contents).events[0];
const replyToken: string = json.replyToken;
const userMessage: string = json.message.text;
const url: string = "https://api.line.me/v2/bot/message/reply";
const headers = {
Authorization: "Bearer " + accessToken,
"Content-Type": "application/json; charset=UTF-8",
};
const postDatas = {
messages: [
{
text: userMessage,
type: "text",
},
],
replyToken,
};
const options: any = {
headers,
method: "POST",
payload: JSON.stringify(postDatas),
};
UrlFetchApp.fetch(url, options);
return ContentService.createTextOutput(
JSON.stringify({ content: "post ok" })
).setMimeType(ContentService.MimeType.JSON);
};
これをデプロイしてLINEのチャネルのWebhookURLにしてあげればオウム返しbotの完成です。
Dialogflow
ここからが本題
Dialogflowって何?
私の言葉で説明するよりも上記を読んで頂くほうがいいと思いますが、つまりは自然言語の解析をGoogle先生のパワーで簡単にしてくれた優れものという感じです。
実装
まずユーザーに応答するreply
関数を修正して、createReply
関数によって作られたテキストを応答するようにします。
import { createReply } from "./messages/createReply";
export const reply = (e: any) => {
// 略
const postDatas = {
messages: [
{
text: createReply(userMessage),
type: "text",
},
],
replyToken,
};
// 略
};
次に、リプライの内容を作るcreateReply
を書きます。
私の実装が最適かどうかはさておき、今回はDialogflow
というクラスを作り、会話のたびにインスタンスを生成します。Dialogflow
の実装は後ほど。
import { Dialogflow } from "./dialogflow";
export const createReply = (userMessage: string): string => {
const queryResult = new Dialogflow(userMessage).postQuery();
const intent: string = queryResult.intent.displayName;
switch (intent) {
case "foo":
return "intentはfooでした";
case "bar":
return "intentはbarでした";
default:
return userMessage;
}
};
createReply
は、ユーザーからのメッセージを引数にとり、そのメッセージをDialogflowのAPIに渡してintentを受け取ります。
ここではintentに応じて返答する内容を変えるような関数にしています。
最後にDialogflow
クラスを実装します。
const scriptProperties = PropertiesService.getScriptProperties();
const dfUrlFormat: string = scriptProperties.getProperty("DF_URL_FORMAT");
export class Dialogflow {
private sessionID: string;
private message: string;
public constructor(message: string) {
this.sessionID = Math.random().toString(32).substring(2);
this.message = message;
}
public postQuery() {
const body: any = {
queryInput: {
text: {
languageCode: "ja",
text: this.message,
},
},
queryParams: {
timeZone: "Asia/Tokyo",
},
};
const options: any = {
contentType: "application/json; charset=utf-8",
headers: {
Authorization: "Bearer " + getAccessToken(),
},
method: "POST",
payload: JSON.stringify(body),
};
const response = UrlFetchApp.fetch(
dfUrlFormat.replace(/{{sessionID}}/g, this.sessionID),
options
);
return JSON.parse(response.getContentText()).queryResult;
}
}
const getAccessToken = () => {
const jsonKey = JSON.parse(
scriptProperties.getProperty("GOOGLE_APPLICATION_CREDENTIALS")
);
const serverToken = new GSApp.init(
jsonKey.private_key,
["https://www.googleapis.com/auth/cloud-platform"],
jsonKey.client_email
);
const tokens = serverToken
.addUser(jsonKey.client_email)
.requestToken()
.getTokens();
return tokens[jsonKey.client_email].token;
};
Dialogflowは、エンドユーザーとの会話をセッションと呼んでいます。それぞれのセッションにセッションIDがあり、このIDはAPIの呼び出し元(つまり私たち)の責任で適切に選択しなければなりません。
今回実装したDialogflow
クラスはインスタンスごとにセッションIDをランダムに生成します。(だったらSession
というクラス名にすればよかった)
また、postQuery
メソッドを持っていて、detectIntentを取得します。
公式リファレンス: Method: projects.agent.sessions.detectIntent
OAuth認証は以下の記事を参考に実装しました。
ここでかなり悩んでいたんですが、先人の偉大な知恵に助けられました。
Hangouts Chatbotをdialogflowを利用してもっとbotらしくする
これでDialogflowによる言語解析をLINEbotが出来上がりました。
Dialogflowで簡単に言語解析を体験できるのでぜひお試しあれ。
おわりに
自然言語解析と聞くと難しそうですがDialogflowを使ってみるとかなり簡単にできますね