1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

現役高校生がチャットボットに挑戦してみた結果

Last updated at Posted at 2019-06-19

AIってすげえや

最近AI関連のものにどっぷりハマってしまいまして、SiriやらGoogleAsisstantやらに興味を持ち始め、某アイアンマンに出てくる某ジャービスや某フライデーみたいなものを作ってみようと思い、いろんなところを探索しに行きました。

今は何でもある世の中。誰かが必ず先陣を切ってやっています。必ず。

知識の乏しい現役高校生の僕でさえ、ネットの海に潜り続けていればあっさりとそれっぽいモノができてしまいます。

[○とりあえずそれっぽいものを考えてみる]
(#とりあえずそれっぽいものを考えてみる)
[○必要なもの・開発環境]
(#必要なもの開発環境)

#とりあえず、それっぽいものを考えてみる
AIアシスタントを作るためにはAIアシスタントを知るのが手っ取り早い。
身近なもので言えば、
・GoogleAsisstant ・Siri ・Cortana なんかが有名どころ

それでそいつらがやってることと言えば、
・アプリケーション、webサイトへの誘導
・簡単な情報(天気情報・ニュース等)をネット上から収集
・ユーザーとの自然会話
・音声認識&合成音声出力
まぁこれが主な機能として挙げられます。

それを踏まえつつ作ってみたのがこれ
拡大.jpg

まぁ、どシンプルですね・・・  UIは二の次です。はい。
仕様をざっくり説明すると、Sendボタンで横にある空欄に入力された文字をチャットボットに対して送りつけ、Talkボタンで音声入力をします。
んで上にある空欄にはユーザとボットのトーク履歴が残るようになっています。

#必要なもの・開発環境
python3が書けて実行できる環境があれば大丈夫だと思います。
参考までに、自分はPycharm+Anaconda を使用しています。 各自お好きなモノを使用してもらっても大丈夫だと思います。

次に必要になってくるのがA3RT  TalkAPIです。
こいつがないとボットとの自然な会話ができなくなってしまいます。
a3rt.png

[A3RT TalkAPI]
(https://a3rt.recruit-tech.co.jp/product/talkAPI/:embed:cite)

上のリンクから飛んでもらって、API KEY発行→メールアドレス入力 でAPI KEYがもらえます。

それが終わったら、入出力装置の準備にかかります。 なんでもいいのでマイクが必要です。
できれば無線の方が近未来感あっていいと思います。(あくまでも個人の意見です)
BlueToothスピーカなんかもあったらいいのかもしれません。ちなみに僕はこれつかってます。
speakar.jpg

マイクとスピーカー内臓でおまけにBlueTooth
これ、このためだけに作られたものなんじゃないかなと思ってます。はい。
あと、棒読みちゃん(読み上げソフト)もダウンロードしておいてください。

[棒読みちゃん]
(https://chi.usamimi.info/Program/Application/BouyomiChan/:embed:cite)

#ソースコードの解説
##import群
まずはimport群の解説です

import tkinter as tk
import datetime 
import requests
import pya3rt
import time
import webbrowser
import subprocess
from bs4 import BeautifulSoup
import pygame
from mutagen.mp3 import MP3 as mp3
import speech_recognition as sr
import pyperclip

とりあえずこいつらをコマンドラインからpipでインストールしておいてください

$ pip install package-name

でだいたいはインストールできたはずです。

##URL&API 前提ファイル
ここでいろいろ設定と取得をしていきます。

#棒読みちゃんを起動
p = subprocess.Popen(r'棒読みちゃんまでの絶対パス')

#APIの取得
apikey = "XXXXXXXX"
client = pya3rt.TalkClient(apikey)

#天気情報を取得
weatherUrl = 'http://weather.livedoor.com/forecast/webservice/json/v1'
payload = {'city':'お住まいの地域番号'}
data = requests.get(weatherUrl,params=payload).json()

#音声認識に必要なオブジェクトを生成
r = sr.Recognizer()
mic = sr.Microphone()

#ウィンドウ生成
root = tk.Tk()

#ウィンドウのタイトルを定義
root.title(u'chatbot')
#ウィンドウサイズを定義
root.geometry('500x300+1400+700')

#日付を取得する
now = datetime.datetime.now()
date = now.strftime("%Y-%m-%d %H:%M")

#音源ファイルの処理
filename = 'se.mp3' #再生したいmp3ファイル
pygame.mixer.init()
pygame.mixer.music.load(filename) #音源を読み込み
mp3_length = mp3(filename).info.length #音源の長さ取得

棒読みちゃんにボットの返答を読ませるために、ソフトの起動と同時に棒読みちゃんを起動させておきます。
このとき棒読みちゃんの設定を「クリップボードの監視」にしておいてください。

apikeyにはメールで送られてきたa3rtのapikeyをはっつけておいてください。

天気情報に関するところは任意なので実装してもしなくてもいいのですが、もしやろうとしている方がいるのであれば、
'お住まいの地域番号' は下の記事を参照してもらえるといいかもしれません。

[livedoor 天気情報]
(http://weather.livedoor.com/forecast/rss/primary_area.xml:title)

ここからお住まいの地域をさがして、
id= の後のコード(例:東京→"130010")をはっつけてください。

次はTalkボタンを押したときにならす音の処理です。
mp3形式でお好みの効果音をダウンロードして名前を付けて(このプログラムだと se.mp3 です)、pythonファイルと同じディレクトリ内に保存しておいてください。じゃないと動作しません。

あとはソースコード通り入力していけばいいと思います。

##音声入力の処理

def btn_click():
    # 録音 r.adjust_for_ambient_noise(source)はノイズ対策

    pygame.mixer.music.play(1)  # 再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること)
    time.sleep(1.1)
    pygame.mixer.music.stop()  # 音源の長さ待ったら再生停止

    with mic as source:
         r.adjust_for_ambient_noise(source)
         audio = r.listen(source)
    try:
         Entry1.insert(tk.END, r.recognize_google(audio, language='ja-JP'))
         addList(Entry1.get())
    except:
         pass

音声入力を実装するにあたって参考にしたのはこの記事です。
https://futurismo.biz/speech-recognition-with-python/:embed:cite

んで自分が付け足したのがこの部分


    pygame.mixer.music.play(1)  # 再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること)
    time.sleep(1.1)
    pygame.mixer.music.stop()  # 音源の長さ待ったら再生停止

と、

try:
     Entry1.insert(tk.END, r.recognize_google(audio, language='ja-JP'))
     addList(Entry1.get())
except:
     pass

の部分です。

上段の処理は先ほども言いましたがボタンを押したときにならす効果音の処理になります。

下段の処理は、自分の発言をトーク履歴に残すための処理です。

##ユーザーとボットの入出力処理

def addList(text):
    mysay = 'you: ' + text
    print(mysay)
    ListBox1.insert(tk.END, mysay)
    print('chatbot: '+talk(text))
    chatbot = 'chatbot: ' + talk(text)
    Entry1.delete(0,tk.END)
    addRep(chatbot)

def addRep(chatbot):
    ListBox1.insert(tk.END,chatbot)

ここでは入力用の空欄に入力された文字列をボットに対して送り付ける&トーク履歴に残したり、ボットからの返答をトーク履歴に残したりする処理をしています。

んでここで注意してほしいのがこのコード

Entry1.delete(0,tk.END)

コイツを入れ忘れると、送信したはずの文字列が残ってしまいます。
要は前回入力したものが消されることがなくずっと入力欄に居座ってしまうのです。
書き忘れることの無いようにしてくださいね。

##ボットからの処理

#botの返答
def talk(say):

    if say == '今日の天気は':
        rep = 'nnn、'+ data['title']+''+data['forecasts'][0]['telop']+'となっています。' \
            '明日の天気は'+ data['forecasts'][1]['telop']+'の模様です。'
        pyperclip.copy(rep)
        return(rep)



    elif say == 'Hey Siri':
        rep = 'nn、 お使いのデバイスはパソコンです。勘違いしないでよね!'
        pyperclip.copy(rep)
        return(rep)



    elif say =='Google を開いて':
        webbrowser.open('https://www.google.com')
        Entry1.delete(0,tk.END)



    elif say == '今日のニュース':
        Entry1.delete(0, tk.END)
        html = requests.get('https://news.yahoo.co.jp/pickup/rss.xml')
        yahoo = BeautifulSoup(html.content, "html.parser")

        for title in yahoo.select("title"):
             print(title.getText())
             ListBox1.insert(tk.END,title.getText())



    elif say == '終了':
        rep = 'nn、動作を終了します'
        pyperclip.copy(rep)
        time.sleep(2)
        root.quit()
        return(rep)



    else:
        ans_json = client.talk(say)
        ans = 'nn、'+ ans_json['results'][0]['reply']
        pyperclip.copy(ans)
        return(ans)

コイツがボット側の処理です。
if文で羅列しています。見にくいしわかりずらい。これでも絞って乗せた方なんですよ。
性格まるわかりですねこりゃあ...
とりあえず上から解説していきます。

    if say == '今日の天気は':
        rep = 'nnn、'+ data['title']+''+data['forecasts'][0]['telop']+'となっています。' \
            '明日の天気は'+ data['forecasts'][1]['telop']+'の模様です。'
        pyperclip.copy(rep)
        return(rep)

'今日の天気は' という入力で取得した天気情報を読み上げてくれます。これ意外に便利。

pyperclip.copy(rep)でボットの返答をクリップボードに貼り付けます。
それでクリップボードを監視している棒読みちゃんが読み上げてくれる っていう仕組みです。
返答文の最初に「nnn、」っていうよくわからないものがくっついていますが、これはbluetoothスピーカーとのラグを解消するためのものです。
bluetoothスピーカー使わないよ っていう人は消してください。

    elif say == 'Hey Siri':
        rep = 'nn、 お使いのデバイスはパソコンです。勘違いしないでよね!'
        pyperclip.copy(rep)
        return(rep)

ボットちゃんに言わせたい返答です。
これが基本的な構文なのでコイツを参考に、ボットに読ませたい返答をお好みで追加していって、自分好みのボットに仕上げてみてはいかがでしょうか。

    elif say =='Google を開いて':
        webbrowser.open('https://www.google.com')
        Entry1.delete(0,tk.END)

指定したurlを開くための処理です。
自分はgoogleのほかにも、Youtubeを開かせたりしています。
(ぶっちゃけなくてもいいかも)

こういう外部実行系の返答を決め、呼び出し元に返したりするとなぜかダブって実行されてしまうんです。謎です。
なので「どうせ実行するんだし、返答しなくてよくね?」
という結論に至りました。
なのでEntry1.delete(0,tk.END)を最後に書くのを忘れないでください。

##ウィンドウの設定
いよいよ最後のプログラムです。これの設定をミスしてしまうと大変なことになってしまいます。

#ラベルを表示
Sratic = tk.Label(text=u'トーク')
Sratic.pack(anchor="nw")

#リストボックスを設置する
ListBox1 = tk.Listbox(width=70,height=13)
ListBox1.pack()

#ラベルを表示
Sratic1 = tk.Label(text=u'下に入力して検索')
Sratic1.pack(anchor="nw")

#Entryを出現させる
Entry1 = tk.Entry(font=("",17),width=30)
Entry1.pack(anchor="nw",side="left")

#"Talk'ボタンを生成
Button = tk.Button(text=u'Talk',width=5,height=2,command=btn_click)
Button.pack(anchor="ne",side="right")

#"Send'ボタンを生成
Button1 = tk.Button(text=u'Send',width=5,height=2,command=lambda:addList(Entry1.get()))
Button1.pack(anchor="ne",side="right")

root.mainloop()

ウインドウの表示や構築は’Tkinter'というPython標準のライブラリを使用しています。比較的簡単なコードで実装ボタンや入力欄を実装できちゃいます。
最後のroot.mainloop()を忘れてしまうとウインドウが実装されません。気を付けてください。

#最後に
現役高校生でもこんな感じで簡単なチャットボットが作れるのでみなさんもやってみてはいかがでしょうか。
自分好みに調教するのも全然アリです。お試しあれ!
chatbot ソースコード
https://github.com/eara4005/chatbot.py

1
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?