みらいテックラボ

音声・画像認識や機械学習など, 週末プログラマである管理人が興味のある技術の紹介や実際にトライしてみた様子などメモしていく.

「Kingyo AI Navi」のアプリ化を考える (3)

先月中旬(2019.3.16), Urban Data Challenge 2018のファイナルが行われ, CODE for YAMATOKORIYAMAが金魚愛(AI)育成プロジェクトとして取り組んでいる「Kingyo AI Navi」が, アイデア部門の金賞[1]を受賞した.

f:id:moonlight-aska:20190324195724p:plain:w400

CODE for YAMATOKORIYAMAでは, 今年度このアイデアをアプリ化したいと考えており, LINEの枠組みを利用したアプリ化の検討を開始した.


関連記事:
「Kingyo AI Navi」のアプリ化を考える (1)
「Kingyo AI Navi」のアプリ化を考える (2)
・「Kingyo AI Navi」のアプリ化を考える (3)
「Kingyo AI Navi」のアプリ化を考える (4)
「Kingyo AI Navi」のアプリ化を考える (5)
「Kingyo AI Navi」のアプリ化を考える (6)


1. 概要
「Kingyo AI Navi」をLINEのMessaging API + サービスで実現すべく, 今回はLINE Botから金魚や大和郡山に関する簡単な問い合わせを行い, 関連情報を返す部分の基本的な動作を試してみた.
サービス側は, これまでGCPの枠組みを活用して検討してきたので, 今回も問い合わせ部分の解析にはDialogflowを利用することにした.
Dialogflowは, 自然言語で会話できるボットを作るためのツールを提供するサービスである.

[構成図]
f:id:moonlight-aska:20190413072424p:plain:w500

① LINEアプリからLINE Botサーバへ質問文を送信する.
② LINE Botサーバは, Messaging API経由で, Kingyo AI NaviサービスのWebhook URLをコールする.
③ Kingyo AI Naviサービスは, 質問文をDialogflowに送信し, 質問文の解析を行う.
④ Kingyo AI Naviサービスは, Dialogflowから質問タイプを受信する.
⑤ LINE Botサーバは, Messaging API経由で, Kingyo AI Naviサービスから質問タイプに応じた応答(関連情報等)を受信する.
⑥ LINE Botサーバは, 受信した応答をLINEアプリに送信する.


2. サービス開発
2.1 Dialogflow側設定
Dialogflowの利用手順については, ネット上に多くの記事[2][3]があるので, そちらを参照のこと.

2.2 質問文解析処理
「Kingyo AI Navi」に問い合わせできる内容については, 別途タスクを決めるとして, 今回は以下の4つの質問文で試してみる.
Dialogflowは, 質問文の揺らぎを吸収し, 質問タイプを特定することに利用し, 応答内容についてはGCEでMessaging APIの仕様に基づき生成することにした.

質問文 応答(タイプ)
金魚の育て方 BREEDING
金魚スポット SPOT
金魚の病気について DISEASE
大和郡山のイベント EVENT

Dialogflowでは, どのように質問文の揺らぎを吸収しているのか?
Intentで基本的な質問文の型を定義しており, Entityでキーとなる言葉の揺らぎを定義する.
下記例では, 「金魚」×「飼い方」の組み合わせ, 及び, 例えば「を教えて」など余分な語彙がついても正しく質問文タイプを識別できる.
[Intentの例]
f:id:moonlight-aska:20190414111332p:plain:w400

[Entityの例]
f:id:moonlight-aska:20190414111928p:plain:w400

2.3 アプリ実装
LINE Messaging APIによるMessageEventがTextMessageの場合, 問い合わせとして処理する.
前回のコードをベースに, TextMessageイベントを処理する部分を変更する.
(1) dflow.send_text_request()関数でDialogflowに質問文を送信し, 解析し, 質問タイプを得る.
(2) 質問タイプに応じて, LINEへの応答内容をButtonsTemplateを使って作成する.

[コード]

# Handle text message                                                           
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
    try:
        print('call dialogflow : ', datetime.datetime.today())
        message, params = dflow.send_text_request(event.message.text)
        print('return dialogflow : ', datetime.datetime.today())
        messages = make_buttons_template(message, params)              
	reply_message(event, messages)

    except Exception as e:
        import traceback
	traceback.print_exc()
        reply_message(event, TextSendMessage(text='何か調子が悪いなー.'))

LINEとDialogflowを直接つなぐ場合, DialogflowのIntegrationsでLINEを有効にするだけでよいようだ.
しかし, 今回はLINEとDialogflowの間にGCEが入るので, GCEでLINEからのメッセージを受けて, APIを使ってDialogflowを呼び出す処理が必要となる.
(1) setup_dialogflow()関数で, Dialogflowを使うための準備を行う.
(2) send_text_request()関数で, 質問文をDialogflowに送信して質問文のタイプ及びパラメータを返す.

[コード]

import os
import settings
import uuid
import json

from google.oauth2 import service_account
import dialogflow_v2 as dialogflow
from google.protobuf.json_format import MessageToJson

LANGUAGE_CODE = 'jp'

# init Dialogflow                                                               
def setup_dialogflow():
    session_id = uuid.uuid4().hex
    credentials = service_account.Credentials.from_service_account_file(os.envi\
ron['DIALOGFLOW_CREDENTIALS'])
    session_client = dialogflow.SessionsClient(credentials=credentials)
    session = session_client.session_path(os.environ['PROJECT_ID'],
                                          session_id)
    return session_client, session

session_client, session = setup_dialogflow()

def send_request(query_input):
    response = session_client.detect_intent(session=session, query_input=query_\
input)
    parameters = response.query_result.parameters
    params_json = json.loads(MessageToJson(parameters))
    return response.query_result.fulfillment_text, params_json

def send_text_request(text):
    text_input = dialogflow.types.TextInput(text=text, language_code=LANGUAGE_C\
ODE)
    query_input = dialogflow.types.QueryInput(text=text_input)
    return send_request(query_input)

[動作例]
LINE画面から質問文を送信すると, 質問文に応じた応答が表示される.
f:id:moonlight-aska:20190414115540j:plain:w300

課題:
今回は, 対話シナリオ(質問文やそれに対する応答内容)についてDialogflowとGCEの両方で設定しているが, ズレをなくすためには, 対話シナリオを記述したデータセットをベースに, GCEからAPIを使ってDialogflowにIntent及びEntityの設定を行うなどの仕組みが必要となってくる.
また, この質問文に対する情報をどう収集し, 更新していくかなども課題となってくる.

まっ, ぼちぼち考えていこう!!

----
参照URL:
[1] UDC2018審査結果 | アーバンデータチャレンジ
[2] Dialogflow入門 - Qiita
[3] Dialogflowでチャットボットを作ってみた - アトトックラボ




LINE BOTを作ろう!  Messaging APIを使ったチャットボットの基礎と利用例

LINE BOTを作ろう! Messaging APIを使ったチャットボットの基礎と利用例

  • 作者:立花 翔
  • 発売日: 2017/05/12
  • メディア: 単行本(ソフトカバー)



AIプログラマになれる本

AIプログラマになれる本

  • 発売日: 2019/02/19
  • メディア: Kindle