Pythonでチャットボット(chatbot):DjangoでHerokuにアップ(後編)

前回の続きになります。前回の記事はこちら。「パターン3.Web上でボットとチャットする(Pythonパッケージで作成)」の後半の説明です。

ボットのプログラムを動かしてみる

Djangoで作成した初期ファイル群に対して以下のように修正を加えます。できたら、「heroku local web」でローカル(自分のPC)で動かすか、前回説明したやり方で「git push heroku main」まで実行してHerokuサーバー上で動かしてください。

ローカルだとURLは「http://127.0.0.1:(指定したポート番号。デフォルトは8000)/chatbot1/」サーバーだとURLは「https://(アプリ名).herokuapp.com/chatbot1/」です。

なお、このプログラムは、

GitHub - gunthercox/ChatterBot: ChatterBot is a machine learning, conversational dialog engine for creating chat bots
ChatterBot is a machine learning, conversational dialog engine for creating chat bots - GitHub - gunthercox/ChatterBot: ChatterBot is a machine learning, conver...

を引用し、修正を加えて作成させて頂きました。

また、Herokuは無料版だと、30分アクセスがないとsleepモードになり画面表示に時間がかかります。まあ、無料だし仕方ないですね。

まずは各フォルダ・ファイルの構成図です。コマンドプロンプトを立ち上げ、treeコマンドで表示します。

C:\github\ chatbot_project >tree /f
C:.
│  .env
│  .gitignore
│  app.json
│  manage.py
│  Procfile
│  Procfile.windows
│  README.md
│  requirements.txt
│  runtime.txt
│
├─.github
│      PULL_REQUEST_TEMPLATE.MD
│
├─chatbot1
│  │  admin.py
│  │  apps.py
│  │  models.py
│  │  tests.py
│  │  urls.py
│  │  views.py
│  │  __init__.py
│  │
│  ├─migrations
│  │  │  __init__.py
│  │  │
│  │  └─__pycache__
│  │          __init__.cpython-39.pyc
│  │
│  ├─static
│  │  ├─css
│  │  │  │  bootstrap.min.css
│  │  │  └─ style.css
│  │  └─js
│  │      │  dev-vue.js
│  │      └─ script.js
│  │     
│  ├─templates
│  │      base_bot.html
│  │      home.html
│  │
│  └─__pycache__
│
├─chatbot_project
│  │  settings.py
│  │  urls.py
│  │  wsgi.py
│  │  __init__.py
│  │
│  ├─static
│  │
│  └─__pycache__
│
└─staticfiles
 
(略)
 

次にchatbot_projectフォルダのファイルのソースです。修正したもののみ。

[urls.py](プロジェクトの方)

from django.urls import path, include

(略)

# Djangoのurls.pyは上から順番にURLのパターンマッチを探すので、順番は大事です。
urlpatterns = [
    path('chatbot1/', include('chatbot1.urls')),

   (略)

    path("admin/", admin.site.urls),
]
[settings.py]

(略)

import os
import django_heroku

(略)

# Application definition
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "chatbot1",
]

(略)

次からはchatbot1フォルダのファイルのソースです。こちらも追加・修正したもののみ。

[urls.py] (アプリケーションの方)

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('get-response/', views.get_response, name='get_response'),
]
[views.py]

from django.http import HttpResponse
import cgi
from django.shortcuts import render
import json
from django.views.decorators.csrf import csrf_exempt
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer



def index(request):
    return render(request,"home.html")


chatbot = ChatBot('チャットボット1号')
trainer = ListTrainer(chatbot)

trainer.train([
    "こんにちは",
    "はじめまして!!",
])

trainer.train([
    "調子は?",
    "元気元気!",
    "それはよかった",
])

@csrf_exempt
def get_response(request):
	response = {'status': None}

	if request.method == 'POST':
		data = json.loads(request.body.decode('utf-8'))
		message = data['message']

		chat_response = chatbot.get_response(message).text
		response['message'] = {'text': chat_response, 'user': False, 'chat_bot': True}
		response['status'] = 'ok'

	else:
		response['error'] = 'no post data found'

	return HttpResponse(
		json.dumps(response),
			content_type="application/json"
		)

次は、chatbot1フォルダの下のtempletesフォルダのファイルです。

[home.html]

{% extends 'base_bot.html' %}
{% load static %}

{% block js %}
  <script type="text/javascript" src="{% static 'js/script.js' %}"></script>
{% endblock %}

{% block content %}

<div id="app" class="container top-padding">
	<div id="text-box" class="row top-padding">
  	  <div class="col-md-12">
		<textarea class="form-control" v-bind:placeholder="placeholder" v-model="input" v-bind:class="{ 'border-danger': send_blank}" v-on:change="check_content"></textarea>
		<i class="fas fa-arrow-alt-circle-down send-btn" v-on:click="add_message"></i>
	  </div>
	</div>
	<div class="row">
		<div class="col-md-12">
			<div class="card col-md-6" v-for="message in messages" v-bind:class="{ 'user-message': message.user,  'chat-message': message.chat_bot, 'offset-md-6': message.chat_bot}">
				<div class="card-body">
					[[message.text]]
				</div>
			</div>
		</div>
	</div>


</div>
{% endblock %}

[base_bot.html]

<!DOCTYPE html>
{% load static %}
<html>
<head>

	<meta charset="utf-8"/>

	<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
	<link rel="stylesheet" type="text/css" href="/static/css/style.css">
	<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
	<script type="text/javascript" src="/static/js/dev-vue.js"></script>
	
	{% block css %} {% endblock %}
	{% block js %}{% endblock %}
</head>
<body>
	{% block content %}{% endblock %}
</body>
</html>

最後に、staticフォルダの下のjsとcssです。なお、bootstrap.min.css、dev-vue.jsはフレームワークです。詳しくは、それぞれのWebサイトをご確認下さい。bootstrap.min.cssはこちら、dev-vue.jsはこちらです。

[script.js]

window.onload = function () {

	var app = new Vue({
	  delimiters: ['[[', ']]'],
	  el: '#app',
	  data: {
	    messages: [],
	    input: '',
	    send_blank: false,
	    placeholder: 'Send a message to the chatbot...',
	  },
	  created: function() {
	  	
	  },
	  methods: {
		add_message: function() {
			if (this.input.length > 0) {
				var message = {
					'text': this.input,
					'user': true,
					'chat_bot': false,
				};
				this.messages.push(message);
				this.input = '';

				this.send_blank = false;
				this.placeholder = "Send a message to the chatbot...";

				fetch("/chatbot1/get-response/", {
			        body: JSON.stringify({'message': message['text']}),
			        cache: 'no-cache', 
			        credentials: 'same-origin', 
			        headers: {
				        'user-agent': 'Mozilla/4.0 MDN Example',
				        'content-type': 'application/json'
			        },
			        method: 'POST',
			        mode: 'cors',
			        redirect: 'follow',
			        referrer: 'no-referrer',
			        })
			        .then(response => response.json()).then((json) => {
			          	this.messages.push(json['message'])
			    	})
			} else {
				this.send_blank = true;
				this.placeholder = "Please put in some text";
			}

		},
		check_content: function() {
			if (this.input.length > 0) {
				this.send_blank = false;
				this.placeholder = "Send a message to the chatbot...";
			} else {
				this.send_blank = true;
				this.placeholder = "Please put in some text";
			}
		},
	  }
	});
};

[style.css]

.top-padding {
	margin-top: 10px;
}

.user-message {
	background-color: rgba(0, 67, 255, 0.33);
}

.chat-message {
	background-color: rgba(128, 0, 95, 0.35);
}

.send-btn {
	position: absolute;
    top: 12px;
    font-size: 30px;
    color: grey;
    right: 20px;
}

.send-btn:hover {
	color: rgba(0, 128, 0, 0.61);
}

#text-box {
	position: static;
	bottom: 8px;
	width: 95%;
}

#text-box textarea {
	border: 2px solid;
}

.navbar {
	background-color: #0006;
}

#app {
	margin-left: 0px;
}

#app .card {
	margin-bottom: 5px;
}

#app p {
	margin-bottom: 0px;
}

以上を配置して、サーバーに配置、実行すると、以下のような画面が出て、ボットとやりとりできます。

まとめ

この記事では、PythonのWebフレームワークDjangoを使って、Heroku上で簡単なチャットボットを動かすところまでやってみました。

私は、herokuにローカルで作成したファイルを反映(push)(git push heroku main)するところで、Pythonパッケージのバージョン不整合エラーになり、pushが何度か失敗しました。そういったときは、requirements.txtのバージョンを「chatterbot>=0.7.6,<0.7.7」といった感じで、あえて最新版を使わずバージョン整合性がとれるように調整してみて下さい。

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