チャットボットの作り方(chatux+chatterbot+django)

前回の続きになります。前回の記事はこちら。

chatuxのサンプルプログラム

まずは、チャット画面を作ります。chatuxを使ってプログラミングしていきます。DjangoのtemplatesのHTML文書として作成します。サンプルのプログラムです。

{% load static %}
<!DOCTYPE html>

<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>チャットボット試作品1号</title>
</head>
<body>

<h2>チャットボットの試作品のサイトです。</h2>


<!-- ここから ↓ -->

<script src="https://riversun.github.io/chatux/chatux.min.js"></script>
<script>
    const chatux = new ChatUx();

    //ChatUXの初期化パラメータ
 const initParam =
        {
            renderMode: 'auto',
            api: {
                //echo chat server
                endpoint: 'https://tentoumushi.pythonanywhere.com/chatbot3/chatterbot/',
                //method: 'GET',
                //dataType: 'jsonp'
                method: 'POST',
                dataType: 'json'
            },
            bot: {
                botPhoto: 'https://hoppara.github.io/image/robot.png',
                humanPhoto: null,
                widget: {
                    sendLabel: '送信',
                    placeHolder: '何か話しかけてみてください'
                }
            },
            window: {
                title: 'チャットボット試作品1号',
                infoUrl: 'https://github.com/riversun/chatux'
            }
        };
    chatux.init(initParam);
    chatux.start(true);

</script>

<!-- ここまで ↑ をスニペットとしてコピー -->

</body>
</html>

18行目の

<script src=”https://riversun.github.io/chatux/chatux.min.js”>

で、chatuxのソースを読み込んでいます。 次の21行目の

const chatux = new ChatUx();

で、chatuxのインスタンスを作り、initParamの情報を格納して初期化処理をしています。

18行目から52行目までをスニペットとして、既存のWebサイトに追記することでチャットボット機能を追加することが可能です。

また、Apiのところで、methodがGET通信かPOST通信かで、後で出てくるviews.pyのコーディング内容が少し変わってきます。どちらかを選択してください。

GET/POSTの違いは、一般的な考え方と同じです。つまり、GETはURLの末尾にパラメータを付与、POSTは通信電文内にパラメータを付与して送受信します。取り扱う情報が個人情報など秘匿性の高い情報でなければ、どちらを使っても問題ないと思います。

view.pyのサンプルプログラム(その1)

次にサーバーサイド側のプログラミングです。Djangoのview.pyのサンプルプログラムを2つ説明します。まずは、チャットボットの入力値を元に’「入力値」ですね!’と回答するオウム返しのプログラムです。

GET/POSTで情報の取得/返信のコーディング方法が異なる点に注意下さい。POSTはJSON形式と呼ばれるデータ記述方式でデータを取得/返信するのに対して、GETはhttp request/response情報として情報の取得/返信をします。また、GETだけcallbackという情報が付与されます

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, 'chatbot3/index.html')


import json
from django.views.generic.base import TemplateView
from django.views.generic import View
from django.http import JsonResponse
from chatterbot import ChatBot
from django.core import serializers



class ChatterBotAppView(TemplateView):
    template_name = 'app.html'


class ChatterBotApiView(View):
    """
    Provide an API endpoint to interact with ChatterBot.
    """

    chatterbot = ChatBot("bot123")

    def post(self, request, *args, **kwargs):
        """
        Return a response to the statement in the posted data.

        * The JSON data should contain a 'text' attribute.
        """

        input_data = json.loads(request.body.decode('utf-8'))
        print (input_data)

        response = {
            'output': [
                {
                'type' : 'text',
                'value' : '「' + input_data['text'] + '」ですね!'
                }
            ]
        }

        return JsonResponse(response, status=200)

    def get(self, request, *args, **kwargs):
        """
        Return data corresponding to the current conversation.
        """

        text = request.GET['text']
        print(text)
        callback = request.GET['callback']
        print(callback)


        response = {
            'output': [
                {
                'type' : 'text',
                'value' : '「' + text + '」ですね!'
                }
            ]
        }

        responseText = callback + '(' + json.dumps(response) + ')'
        print(responseText)
        return HttpResponse( responseText , content_type = "application/javascript")



view.pyのサンプルプログラム(その2)

2つ目のサンプルプログラムは、いよいよchatterbotが登場します。このパッケージを使うことで、より一段とチャットボットらしい制御を組み込むことができます。POST通信のケースだけプログラムの記述を追加しています。

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, 'chatbot3/index.html')

import json
from django.views.generic.base import TemplateView
from django.views.generic import View
from django.http import JsonResponse
from chatterbot import ChatBot
from chatterbot.comparisons import LevenshteinDistance
from chatterbot.response_selection import get_first_response
from chatterbot.response_selection import get_most_frequent_response
from chatterbot.trainers import ListTrainer
from chatterbot.trainers import ChatterBotCorpusTrainer

chatbot123 = ChatBot('bot123',read_only=True,#登録データを利用しない
                     logic_adapters=[
                         {
                          'import_path': 'chatterbot.logic.BestMatch',
                          'statement_comparison_function': LevenshteinDistance,
                          'response_selection_method': get_first_response,
                          'default_response': 'すいません。わかりません。',
                          'maximum_similarity_threshold': 0.50
                         }
                     ]
            )

trainer = ChatterBotCorpusTrainer(chatbot123)
trainer.train('chatterbot.corpus.japanese')

trainer = ListTrainer(chatbot123)
trainer.train([
    "こんにちは",
    "はじめまして!!",
])
trainer.train([
    "調子は?",
    "元気元気!",
    "それはよかった",
])

class ChatterBotApiView(View):
    """
    Provide an API endpoint to interact with ChatterBot.
    """
    def post(self, request, *args, **kwargs):
        """
        Return a response to the statement in the posted data.
        * The JSON data should contain a 'text' attribute.
        """
        input_data = json.loads(request.body.decode('utf-8'))
        print (input_data)

        if input_data['text'] == "動物":
            response = {
                'output': [
                    {
                    'type': 'text',
                    'value': '好きな動物は?',
                    'delayMs': 200  #表示ディレイ(ミリ秒)
                    },
                    {
                    'type': 'option',
                    'options': [
                        {'label': 'イヌ', 'value': '犬'},
                        {'label': 'ネコ', 'value': '猫'},
                        {'label': 'タヌキ', 'value': '狸'}
                    ]}
                ]
            }
        elif input_data['text'] == "犬":
           response = {
               'output': [
                    {
                    'type': 'image',
                    'value': 'http://hoppara.github.io/image/inu.jpg'
                    }
                ]
            }
        elif input_data['text'] == "猫":
           response = {
               'output': [
                    {
                    'type': 'image',
                    'value': 'http://hoppara.github.io/image/neko.jpg'
                    }
                ]
            }
        elif input_data['text'] == "狸":
           response = {
               'output': [
                    {
                    'type': 'image',
                    'value': 'http://hoppara.github.io/image/tanuki.jpg'
                    }
                ]
            }

        else:
            response = {
                'output': [
                    {
                    'type' : 'text',
                    # 'value' : '「' + input_data['text'] + '」ですね!'
                    'value' : chatbot123.get_response(input_data['text']).text
                    }
                ]
            }

        return JsonResponse(response, status=200)

    def get(self, request, *args, **kwargs):
        """
        Return data corresponding to the current conversation.
        """

        text = request.GET['text']
        print(text)
        callback = request.GET['callback']
        print(callback)


        response = {
            'output': [
                {
                'type' : 'text',
                'value' : '「' + text + '」ですね!'
                }
            ]
        }
        responseText = callback + '(' + json.dumps(response) + ')'
        print(responseText)
        return HttpResponse( responseText , content_type = "application/javascript")



21行目の「chatbot123 = ChatBot(‘bot123’・・・」でChatBotインスタンスを作成し、そのインスタンスに対してtrainすることで、特定の入力値に対する回答を準備します。

そしてif文の最後のelseの「chatbot123.get_response(input_data[‘text’]).text」で入力値に対する回答をvalueにセットしています。Chatterbotについては、次回の解説で詳しく説明したいと思います。

また、59行目の「if input_data[‘text’] == ・・」から、特定の文言が入力された場合の分岐ロジックを書いています。

 ・入力値が「動物」のとき、犬、猫、狸の3択が表示され、それぞれを選ぶとその絵が出てきます。

 ・入力値が「犬」のとき、犬の絵が表示されます。

 ・入力値が「猫」のとき、猫の絵が表示されます。

 ・入力値が「狸」のとき、狸の置物の絵が表示されます。

 ・上記以外のとき、ChatBotの訓練データを元に応答値を表示します。

まとめ

初見で難しいと感じた方は、とりあえず、プログラムをコピー&ペーストして自分のPCのローカル環境で、まずは動かしてみて下さい。それから、chatux、chatterbotのサイトの説明を読んで、少しずつ自分の好きなようにカスタマイズしていくと理解が深まると思います。

Chatterbotのコーディングパターンについては次回、詳しく説明します。

タイトルとURLをコピーしました