ChatterBotのチャットボットとWebアプリでやり取りできるようにする¶
今回の位置づけ¶
前回までの復習¶
- チャットボット=自動応答するプログラム(チャットボットの概要)
- ライブラリ
chatterbot
を使ったPythonスクリプトをまず動かした - スクリプトだけでなく、Webアプリとしてもチャットボットを動かしたい
- オウム返しするチャットボットとやり取りするWebアプリを作った
Djangoのカスタムコマンド¶
カスタムコマンドとは¶
Djangoの カスタムコマンド という仕組みを使います。 アプリケーションごとにコマンドを持たされます。
開発者が使えるよう、Djangoにデフォルトで用意されているコマンドがあります。 python manage.py --help でコマンドの一覧が見られます。
- 例えば、runserver は
django
アプリケーションのコマンドです。
カスタムコマンドを実装して、このコマンド一覧にチャットボットを訓練するコマンドを追加します。
カスタムコマンドに必要なディレクトリ構成¶
Djangoのカスタムコマンドは ディレクトリ構成のルールが決まっています。 ルールに沿ってディレクトリとファイルを配置し、実装します。
https://docs.djangoproject.com/ja/3.2/howto/custom-management-commands/
独自のコマンドを追加するためには、``management/commands``ディレクトリをアプリケーションに追加してください。
$ mkdir -p chat/management/commands
$ touch chat/management/__init__.py
$ touch chat/management/commands/__init__.py
$ touch chat/management/commands/bot_train.py
__init__.py
はPythonパッケージにするために置きます。
中身は空で大丈夫です。
chat/management/commands/bot_train.py
を編集していきます。
初めてのカスタムコマンド!¶
まずは、簡単なカスタムコマンドを作りましょう。
chat/management/commands/bot_train.py
に以下を書いてください。
1from django.core.management.base import BaseCommand
2
3
4class Command(BaseCommand):
5 def handle(self, *args, **kwargs):
6 self.stdout.write("bot_trainコマンドです")
実行してみましょう。
$ python manage.py bot_train
bot_trainコマンドです
python manage.py --help で見られるコマンド一覧にも追加されていることが確認できます。
プログラムの解説¶
アプリケーションの management/commands
に置いたファイルの名前がコマンド名になります(bot_train
)。
ファイル名以外にも、カスタムコマンドでは「こう実装してください」というルールが決まっています。
BaseCommand クラスもしくはその サブクラス の一つを継承した Command クラスを定義する必要が有ります。
https://docs.djangoproject.com/ja/3.2/howto/custom-management-commands/
これに沿って Command
クラスを実装しています(4行目)。
Command
クラスには handle
というインスタンスメソッドを実装します。
コマンドラインに出力するために self.stdout.write
を使います。
管理コマンドを利用してコンソールへの標準出力を行いたい場合、stdout と stderr に直接文字列を渡すのではなく、self.stdout および self.stderr を利用するべきです。(上と同じリンクより)
ヒント
色付きでコマンドラインに出力できる
self.stdout.write
の引数に、色などの スタイル を指定した文字列を渡せます。
self.style.SUCCESS("bot_trainコマンドです")
:緑色で表示されますself.style.ERROR("bot_trainコマンドです")
:赤色で表示されます
引数 "bot_trainコマンドです"
を上記に変えて試してみてください。
スタイル指定は訓練コマンドでも使います。
チャットボット訓練コマンド¶
コーパスを使って訓練したチャットボット(日本語) で行ったのと同じ訓練を、Webアプリでもできるようにします。 bot_train コマンドを実装します。
以下のファイルを変更します。
- プロジェクトの
settings.py
- アプリケーションの
management/commands/bot_train.py
設定変更¶
INSTALLED_APPS
にChatterBotのDjangoアプリケーションを追加- ChatterBot用の設定を示す変数を追加
INSTALLED_APPS
¶
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"chat.apps.ChatConfig",
"chatterbot.ext.django_chatterbot",
]
参考:https://chatterbot.readthedocs.io/en/stable/django/index.html#installed-apps
ChatterBot用の設定追加¶
コーパスを使って訓練したチャットボット(日本語) で作ったスクリプトは、以下のように ChatBot
クラスのインスタンスを初期化しています。
11 chatbot = ChatBot("Training from corpus bot", tagger_language=CustomJPN)
この引数をプロジェクトの settings.py
で指定します。
末尾に追加してください。
# ChatterBot settings
from chatterbot.languages import JPN
class CustomJPN(JPN):
ISO_639_1 = "ja_core_news_sm"
CHATTERBOT = {
"name": "Training from corpus bot on Web app",
"tagger_language": CustomJPN
}
参考:https://chatterbot.readthedocs.io/en/stable/django/settings.html
辞書を指す変数 CHATTERBOT
を追加しています。
この変数は、Webアプリで ChatBot
クラスのインスタンスを初期化するときに使われます。
実は ChatBot
というイニシャライザの第1引数は name
です。
chatbot = ChatBot(
name="Training from corpus bot",
tagger_language=CustomJPN
)
my_chatbot.py
同様に日本語を扱うように指定しています(tagger_language
)。
説明は ChatterBot はじめの一歩 を参照してください。
訓練するカスタムコマンドを実装¶
1from chatterbot import ChatBot
2from chatterbot.ext.django_chatterbot import settings
3from chatterbot.trainers import ChatterBotCorpusTrainer
4from django.core.management.base import BaseCommand
5
6
7class Command(BaseCommand):
8 def handle(self, *args, **kwargs):
9 chatbot = ChatBot(**settings.CHATTERBOT)
10
11 trainer = ChatterBotCorpusTrainer(chatbot)
12 trainer.train("chatterbot.corpus.japanese")
13
14 self.stdout.write(self.style.SUCCESS("Training completed."))
9〜11行目は my_chatbot.py
でコーパスから訓練しているコードと同様です。
13行目は訓練終了を出力しています。
ヒント
**settings.CHATTERBOT
について
この書き方は初めて見たときに混乱するかもしれません。
辞書に **
を付けて、関数に渡すと、辞書のキー=値
と キーワード引数を渡した ことになります。
>>> def f(a, b):
... print("a", a)
... print("b", b)
...
>>> f(a=1, b=2)
a 1
b 2
>>> d = {"a": 1, "b": 2}
>>> f(**d) # f(a=1, b=2) という呼び出しと同じになる
a 1
b 2
訓練コマンドを動かすために¶
- データベースのセットアップ
- ライブラリ
chatterbot_corpus
インストール
後者のインストールについては コーパスを使って訓練したチャットボット(日本語) に対処法を追加しています。
データベースのセットアップ¶
ChatterBotは訓練に使うコーパスを データベースに保存 します。
Djangoでデータベースの操作を担うのが モデル です。
今回の実装の範囲で、私たちがモデルを使ってデータベースを操作することはありませんが、仕組みとして紹介しました (ChatterBot側でモデルを使ったコードが用意されています)。
データベースのセットアップには python manage.py migrate を実行します。 migrate(マイグレート)はデータベースの定義をバージョン管理するイメージです。 DjangoやChatterBotが用意したデータベースの定義を適用しています。
データベースのセットアップが終わったら python manage.py bot_train を実行しましょう。
訓練に使ったコーパスの文章がデータベースに保存され、ChatBot
が検索して返せる状態になります。
発展:訓練コマンドの最終形¶
1from chatterbot import ChatBot
2from chatterbot.ext.django_chatterbot import settings
3from chatterbot.ext.django_chatterbot.models import Statement
4from chatterbot.trainers import ChatterBotCorpusTrainer
5from django.core.management.base import BaseCommand
6
7
8class Command(BaseCommand):
9 help = "Train chatbot with corpus"
10
11 def handle(self, *args, **kwargs):
12 statements = Statement.objects.all()
13 if statements:
14 statements.delete()
15 self.stdout.write(
16 self.style.SUCCESS("All data have been deleted.")
17 )
18
19 chatbot = ChatBot(**settings.CHATTERBOT)
20
21 trainer = ChatterBotCorpusTrainer(chatbot)
22 trainer.train("chatterbot.corpus.japanese")
23
24 self.stdout.write(self.style.SUCCESS("Training completed."))
- 9行目の
help
変数が指す文字列は python manage.py bot_train --help で表示されます - すでに訓練されている場合、データベースに
Statement
が保存されています。保存が重複しないよう、データベースに保存されたStatementをすべて削除する という実装にしています(このStatement
がモデルです)
訓練したチャットボットとやり取りできるようにする¶
カスタムコマンドでチャットボットを訓練したら、ユーザーがやり取りできるようにしましょう。 オウム返しするチャットボットと差し替えます。
これまでにチャットボットの応答をWebアプリに表示する部分を作成済みなので、 チャットボットを差し替えるだけ です。
アプリケーションの views.py
を修正します。
チャットボットが応答するようにビューを変更¶
my_chatbot.py
でチャットボットとやり取りする部分の実装は以下のようになっています。
19 response = chatbot.get_response(user_input)
chatbot
の get_response
メソッドを呼んでいますね。
Webアプリでも、ビューの bot_response
関数も同様の実装にします
(フォームから bot-response/
にPOSTリクエストが送られるたびに呼ばれる関数でしたね)。
参考
- https://chatterbot.readthedocs.io/en/stable/django/views.html
- https://github.com/gunthercox/ChatterBot/blob/master/examples/django_app/example_app/views.py
変更前¶
1def bot_response(request):
2 if request.method == "POST":
3 form = ChatMessageForm(request.POST)
4 if form.is_valid():
5 response_message = form.data["message"]
6 http_response = HttpResponse()
7 http_response.write(response_message)
8 return http_response
オウム返しするチャットボットなので、入力されたテキストをそのまま返しています。
変更後¶
ChatBot
インスタンスを初期化します。
ビュー関数が呼び出されるたびに初期化したくないので、関数の外側に書いています。
from chatterbot import ChatBot
from chatterbot.ext.django_chatterbot import settings
from django.http import HttpResponse
from django.shortcuts import render
from .forms import ChatMessageForm
chatbot = ChatBot(**settings.CHATTERBOT)
入力されたテキストを get_response
メソッドに渡し、その返り値をレスポンスとして返します。
1def bot_response(request):
2 if request.method == "POST":
3 form = ChatMessageForm(request.POST)
4 if form.is_valid():
5 input_message = form.data["message"]
6 response_message = chatbot.get_response(input_message)
7 http_response = HttpResponse()
8 http_response.write(response_message)
9 return http_response
python manage.py runserver してから http://127.0.0.1:8000/ をブラウザで開くと、訓練したチャットボットとやり取りできます!!