CCCMKホールディングス TECH LABの Tech Blog

TECH LABのエンジニアが技術情報を発信しています

ブログタイトル

QnA MakerとAzure Bot Serviceで自分が住む街の粗大ごみ回収に必要な処理券を教えてくれるbotを作ろう!

こんにちは、技術開発ユニットの三浦です。今回はAzureのサービスであるQnA MakerとAzure Bot Serviceを使ってbotを作ってみた話を紹介します。自治体によってはゴミの出し方などを教えてくれるbotを導入しているところがあります。たとえば横浜市の「イーオのごみ分別案内」は話題になりました。

AIを活用したチャットボット「イーオのごみ分別案内」 横浜市

自分が住む街では粗大ごみを出す際にその品目に対応した処理券を購入し、粗大ごみに貼り付けて指定の日時に出す必要があります。出したい品目に対して必要な処理券の枚数を教えてくれるbotがあったら便利かなぁと思い、作ってみました。

QnA Maker と Azure Bot Service

どちらもMicrosoftのAzureで提供されるサービスです。QnA Makerは自然言語処理サービスでユーザが入力した言葉に対し、予め登録しておいたナレッジベース(FAQ集のようなもの)から最適な回答を選び、答えることができます。登録していたナレッジベースに完全に一致する言葉でなくともQnA Makerで推論、もっともらしい回答を返してくれます。Azure Bot Serviceはbotを作成、管理、様々なチャンネルに接続可能なサービスです。接続可能なチャンネルにはMicrosoftのチャットツールTeamsやLINEなどがあります。また、自分で作ったWebアプリに組み込むことも可能です。Azure Bot Serviceがフロントの役割を果たし、様々なチャンネルと連携し質問を受付け、QnA Makerで最適な回答を見つけユーザに返す、という流れになります。

実は当社のIT部門ではすでにこの仕組を使ってTeamsで社員向けのFAQ botを作っていて、先日私達研究所のメンバー向けにハンズオンをオンラインで開いてもらい、ノウハウを共有してもらいました。IT部門と研究所はそれぞれAzureを活用していますが業務内容も異なるため、Azureの活用方法も各々異なります。時々こういう機会を設けて双方のノウハウを共有したりしています。さて、約1時間のハンズオンを通じ、botの作成からTeamsへの連携まで実現することが出来ました。これを使えば社内だけでなく、たとえばお店の中に置いて来店客の質問に答えてくれるようなロボットも作れるかもしれません。これはワクワクもんだぁと思ったのですが、最初から風呂敷を広げすぎるのも良くないので、まずは身近なところで何か作ってみようと思いたち、粗大ごみの回収に必要な処理券を教えてくれるbotを作るに至った次第です。

ナレッジベースのソースを作る

早速botを作りたいのですが、まずはQnA Makerのナレッジベースのソースとなるデータを作る必要があります。具体的には次のようなデータです。

f:id:miu4930:20200618171408p:plain

左の列に質問、右の列に回答が入っています。QnA MakerではナレッジベースをFAQサイトのURLを指定して構築することも出来るようですが今回はファイルで構築します。ちなみに許容されているファイルの形式は.tsv, .pdf, .doc, .docx, .xlsx となっており、まさかのcsv非対応だったりします(これが分からずにだいぶ詰まりました。)。

さて、粗大ごみの処理券は「粗大ごみ受付センター」のサイトで調べることが出来ます。

粗大ごみ受付センター

このように品目と必要な処理券を一覧で見ることが出来ます。

f:id:miu4930:20200618171826p:plain
※粗大ごみ受付センターのサイトより
品目名と処理券の行が違うので、必要なデータを得るには少し工夫が必要です。また品目によっては家電リサイクル法の対象であるなどの注意書きもあります。これらも重要な情報なので、品目に対し答えられるようにしたいです。少し条件分岐が必要そうなので、解析用のプログラムを作ります。まずはブラウザでページのソースを表示し、品目一覧の部分<tbody>~</tbody>だけをコピーして別のテキストファイルに貼り付けて保存します。(プログラムからhtmlを取得して加工も可能ですが、プログラムからリクエストを投げる場合、プログラムにミスがあると大量のリクエストを投げつけてしまう恐れもあり、手動で行いました。)

htmlを解析し、必要なデータを抽出するためにPythonのスクレイピング用のライブラリBeautiful Soupを使います。pipでインストールできます。

pip install beautifulsoup4

プログラムは以下のように作りました。

import csv
from bs4 import BeautifulSoup

#テキストの読み込み
with open('table.txt','r',encoding='utf-8') as f:
    data = f.read()

#BeautifulSoupオブジェクトに格納する
soup = BeautifulSoup(data, 'html.parser')
#trタグをすべて取得
rows = soup.find_all('tr')

#値格納用のリスト
items = []
contents = []
content = []

#回答の末尾に付ける
matubi = 'ナリ'
for i, r in enumerate(rows):
    if len(r.find_all('td')) == 4: #番号,頭のひらがな,品目名,金額行の場合
        if i > 0:
            items.append(item)
            contents.append(''.join(content) + matubi)
            content = []
        item = r.find_all('td')[2].get_text()
       
    else:
         for c in r.find_all('td'):
            if c.find('a'): #他のサイトへのリンクの場合、aタグごと格納する
                content.append(c.get_text().strip() + '<br>')
                content.append(str(c.find('a')))
            else:
                if len(c.get_text().strip()) > 0: #それ以外で空白でない場合、テキストだけ格納する
                    content.append(c.get_text().strip())

#ファイルに書き出す。
with open('qna.tsv','w',newline='') as f:
    writer = csv.writer(f, delimiter='\t') #tsv形式
    for item, content in zip(items, contents):
        writer.writerow([item,content])

ちなみにmatubi = 'ナリ'は何かというと、回答の末尾に「ナリ」を付けたくて入れているだけです。キテレツ大百科のコロ助が好きなのです。

これでナレッジベースのソースとなるファイルが出来上がりました。

QnA Makerでナレッジベースを作る

まずQnA Makerのサイトにいき、サインインします。次にページの上の方にある、「Create a knowledge base」をクリックします。

f:id:miu4930:20200618172647p:plain
Create a knowledge baseをクリック

ここからは各STEPごとに進めていきます。

STEP1 Create a QnA service in Microsoft Azure.

QnA serviceを作ります。[Create a QnA service]ボタンをクリックするとAzure PortalのQnA Makerを作成するページが開きます。

  • 名前

    既に誰かが設定済みのものは使えません。

  • 価格レベル

    無料プランのFree F0にしました。ナレッジベースが3つしか作ることができない制限があります。

  • Azure Search価格レベル

    こちらも無料プランのFree Fにしました。

  • Azure Search・Webサイト・App Insightsの場所

    (Asia Pacific)東日本にします。

設定後、[作成]ボタンをクリックするとサービスのデプロイが開始されます。

STEP2 Connect your QnA service to your KB.

STEP1で作成したQnA serviceを指定します。

  • Microsoft Azure Directory ID

    「既定のディレクトリ」にします。

  • Azure QnA service

    STEP1で作成したserviceを選びます。

  • Language

    「Japanese」にします。

STEP3 Name your KB.

ナレッジベースの名前を付けます。日本語もOKでした。

STEP4 Populate your KB.

ここで先程作成したソースファイルを指定します。Add fileで作成したファイルをアップロードできます。ちなみに文字コードは"UTF-8"です。"Shift-JIS"では文字化けします。(Microsoftのサービスなので"Shift-JIS"で作るのかなと思っていたのですが・・・)

ちなみにChit-chatという、botに性格付けすることが出来る機能があるのですが、今回無料プランでserviceを作っている影響でChit-chat用のナレッジベースの容量が足りず、有効にすることが出来ませんでした。

STEP 5 Create your KB.

あとは[Create your KB]をクリックすればOKです。

無事に取り込めると以下のような画面が表示されます。

f:id:miu4930:20200618173146p:plain
質問と回答が表示されている

ちゃんと会話ができるかテストしてみましょう。[←Test]ボタンをクリックするとテスト用の会話が開始されます。試しに適当な品目を入力してみます。

f:id:miu4930:20200618173313p:plain
公開前に動作テストが出来る

返ってきました。ちなみにこのページ上でもナレッジベースを編集することが出来ます。編集後[Save and train]を実行することで編集内容を反映させることが出来ます。

動作に問題がなければ公開します。[PUBLISH]に進み、[Publish]ボタンをクリックします。以下の画面が表示されれば無事にサービスが公開されています。

f:id:miu4930:20200618173627p:plain
Success!

EndpointのURLが発行されるので、Bot Serviceを作らなくてもナレッジベースを使うことが出来ます。CURLなどの実行例を参考に、POSTでリクエストを投げてみると以下のようなレスポンスが得られました。

f:id:miu4930:20200618173757p:plain
リクエストは「アイロン」です

answerも正しいようです。自分で作ったアプリから使うことも可能なので、色々応用が出来そうです!

Azure Bot Serviceを作る

様々なチャンネルからナレッジベースを使えるようにするためにAzure Bot Serviceを作ります。

先程のナレッジベースのデプロイ完了画面に[Create Bot]というボタンがあるのでそちらをクリックします。Azure PortalのWebアプリボット作成画面が表示されるので、入力していきます。

  • ボット ハンドル

    botの名前を付けます。

  • 価格レベル

    F0 Freeにします。

  • App Serviceプラン/場所

    前の手順で作ったQnA service名を指定します。

  • Application Insightsの場所

    Japan Eastにします。

あとは[作成]ボタンをクリックするとBot Serviceの作成が開始されます。

色々なチャンネルから呼び出してみる

これでQnA Maker と Azure Bot Serviceが出来たので、色んなチャンネルからbotを呼び出してみます。

Teamsから呼び出す

Azure PortalでWebアプリ ボットを開き、チャンネルをクリックします。

f:id:miu4930:20200618174425p:plain
Webボット アプリの設定

Teamsのアイコンをクリックし、[保存]ボタンをクリックします。サービス条件について同意を求められるので同意のチェックを入れて[Agree]ボタンをクリックします。これでTeamsからbotを呼び出すことが出来るようになります。Webアプリ ボットの設定画面から「Microsoft App ID (管理)」に記載されている文字列をコピーします。

f:id:miu4930:20200618174817p:plain
周りと比べて少し薄い字になっている箇所

続いてTeamsを起動し、新しいチャットを開き、メンバーの欄に先程の文字列をペーストします。すると作成したWebアプリ ボット名が表示されるのでクリックすると、botとの会話を開始することが出来ます。簡単!

f:id:miu4930:20200618174939p:plain
Teamsでbotとおしゃべり

LINEから呼び出す

次にLINEから呼び出してみましょう。手順はこちらのページに書いてあるようにまずLINE developer consoleでMessaging APIを作ります。

f:id:miu4930:20200618175231p:plain
Messaging API

Messaging APIが出来たら、まず[Basic settings]を開き、「Channel secret」の文字列を控えます。次に[Messaging API]を開き、「Channel access token (long-lived)」のところにある[issue]ボタンをクリックします。するとトークン文字列が表示されるので、それも控えておき、Azure PortalでWebアプリ ボットを開き、チャンネルの画面を開きLINEのアイコンをクリックします。チャンネルシークレットとチャンネルアクセストークンの欄に先程控えた文字列をそれぞれ入力します。[保存]ボタンをクリック後、表示されているwebhookのURLをコピーしておきます。

f:id:miu4930:20200618175539p:plain
webhookのURLをコピーする

次にLINE developer consoleに戻り、[Messaging API]の「Webhook settings」の「Webhook URL」の[Edit]ボタンをクリックします。コピーしたWebhookのURLを貼り付け(先頭にhttps://を追記します)、[Verify]ボタンをクリックして「Success」メッセージが表示されることを確認します。

これで上手くいくか・・・と思ったのですが、上手くいきません。

f:id:miu4930:20200622093621p:plain
何この通じ合わない感じ、と思った

どうもWebhookのメッセージがオフになっているようなので、有効にします。[Messaging API]で「Auto-reply messages」の[Edit]ボタンをクリックします。応答設定画面の「詳細設定」を

  • 応答メッセージ→オフ

  • Webhook→オン

にします。これでLINEからbotを呼び出すことが出来るようになりました。LINEのアプリで友だち追加画面を開き、QRコードリーダを起動します(ちなみに友達の少ない自分はどこで友だち追加できるのか分からずかなり悩みました。)。LINE developer consoleのMessaging APIで表示されているQRコードを読み込むと、友だちに追加されます。話しかけるとちゃんと返ってきました。

f:id:miu4930:20200622093632p:plain
「友だち追加ありがとうございます。粗大ごみです。」ってすごい自嘲的だと思った

Webページから呼び出す

最後に自分で作ったWebページからbotを呼び出してみます。Webボット アプリのチャンネルを開き、Web Chatの編集ページを開きます。シークレットキーと埋め込みコードが表示されるので、例えば以下のようなhtmlファイルを書きます。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <title>粗大ごみbot</title>
    </head>
    <body>
        <h1>粗大ごみbot</h1>
        <p>調べたい品目は?</p>
        <iframe src='https://webchat.botframework.com/embed/xxxxx?s=シークレットを入力'
          style='min-width: 400px; width: 100%; min-height: 500px;'>
        </iframe>
    </body>
</html>

<iframe>~</iframe>の部分は埋め込みコードをコピー&ペーストします。「シークレットキーを入力」の部分は表示させたシークレットキーを入力します。サーバ側のプログラムを例えばNode.jsで以下のように作ります。

const http = require('http');
const fs = require('fs'); 
var server = http.createServer(
    (req,res) => {
        fs.readFile('./index.html','UTF-8',
    (error,data)=>{
        res.writeHead(200,{'Content-Type':'text/html'});
        res.write(data);
        res.end();
    })
    }
);
server.listen(3000);
console.log('Server Start!');

index.htmlが作成したhtmlファイルです。あとはコマンド

node app.js

のようにしてjsのプログラムを実行し、localhost:3000にブラウザでアクセスします。するとこのように会話ウィンドウが表示され、botと会話することが出来ます。

f:id:miu4930:20200618181320p:plain

最後に

QnA MakerとAzure Bot Serviceでbotを作り、色んなチャンネルから呼び出す手順についてご紹介しました!非常に面白いサービスです!それにしても今回の作業で自分の住む街の粗大ごみに関する知識がだいぶ深まりました。bot作ってたら自分のほうが詳しくなっちゃったみたいな?そんなオチがついたところで本記事、締めくくらせて頂きます!