【会話入門】テキスト入力と音声応答で会話して遊んでみる♪

前回の[text2speak](https://qiita.com/MuAuan/items/74bc382af64aca8861f9)と[TF-IDFによるQA応答](https://qiita.com/MuAuan/items/dbd7dd56fa1b3ec9031a)の自然な発展としてテキスト入力に対するQA応答を利用するとテキスト入力に対して発話応答する会話ができる。ということで今回は会話実現に向けて、少し遊んでみました。
###やったこと
・会話アプリのための環境構築
・正規表現を使う
・テキスト応答で会話
・自己自動会話
###・会話アプリのための環境構築
前回までは、BoW上でTF-IDFなどをやり、text2speakはKeras-gpu環境で実施してきた。
つまり、text2speakとTF-IDFを同時に使うことができなかった。
これは、BoWでは(Pyaudioなどはインストールできたが)スピーカが使えず、一方、Windows環境ではMecab（辞書）がインストールできないということが原因であった。
ということで、どちらかの環境を作る必要があるが、BoWでのスピーカ認識の仕方がわからないので、参考のあるWindows上へのMecabのインストールを実施した。
エラー内容は以下の参考と同様です。参考では解決していませんがほぼ辞書がうまくインストール出来ていないということのようです。
【参考】
・[MeCabが使えない](https://teratail.com/questions/160674)
一方、Mecabのインストールは以下の手順や辞書の手順が参考になりました。
ただし、まんまやっても実は使えませんでした。
【参考】
・[WindowsでNEologd辞書を比較的簡単に入れる方法](https://qiita.com/zincjp/items/c61c441426b9482b5a48)
そこで、最後に以下のバイナリーで再度Mecabをインストールして、その後もう一度Mecabをインストールしなおすと辞書ipadicが正常に使えるようになりました。
※ここはあまり論理的な記事になっていませんが後で再整理したいと思います
【参考】
・[MeCab 0.996 64bit version](https://github.com/ikegami-yukino/mecab/releases)
###・正規表現を使う
もう一つの問題は、適当な会話（既存のQAやドキュメント）などの場合はテンポラリに文字が選ばれるのでアルファベット以外の文字も入ってきます。
ということで、正規表現を使ってもともと録音されていない音を削除することを考えました。
【参考】
・[Pythonの文字列を削除する方法まとめ](https://www.headboost.jp/python-delete-strings/)
今回はpykakasiでローマ字変換されたあとの文字削除なので、このローマ字のみを残します。
コードは以下を試します。

```py
import re
text = "abc123def456ghi,HP１２３４；：　ある意味koreｇa"
new_text = re.sub(r"[a-z]", "", text)
print(new_text)
new_text = re.sub(r"[^a-z]", "", text)
print(new_text)
```
123456,HP１２３４；：　ある意味ｇ
abcdefghikorea
うまく分離されました。そして、`re.sub(r"[^a-z]", "", text)`のコード使います。
###・テキスト応答で会話
コード全体は以下のリンクのとおり
・[something2speak/tfidf_speak.py](https://github.com/MuAuan/something2speak/blob/master/tfidf_speak.py)
ここは前回の[【NLP入門】気象庁のFAQをTF-IDFして遊んでみた♪](https://qiita.com/MuAuan/items/dbd7dd56fa1b3ec9031a)とほぼ同様です。
単に上記の回答をtext2speakで音声に変換するだけです。
ただし、ここで正規表現による文字入力改善等を実施しています。

```py
while True:
    line = input("> ")
    if not line:
        break
    sims = cosine_similarity(vectorizer.transform([mecab.parse(line)]), vecs)
    index = np.argsort(sims[0])
    print("({:.2f}): {}".format(sims[0][index[-1]],questions[index[-1]]))
    print()
    print(answers[index[-1]])
    text2speak(answers[index[-1]]) #ここを追記
    print()
    for i in range(2,5):
        print("({:.2f}): {}".format(sims[0][index[-i]],questions[index[-i]]))
    print()
```
もう一点の改善はFAQでは回答が長くてつまらないので、ここは以下のような会話を作成して実施してみました。
[something2speak/data/kaiwa_aruaru.txt](https://github.com/MuAuan/something2speak/blob/master/data/kaiwa_aruaru.txt)
以下実行例です。ローマ字部分が音声で発話します。

```
>python tfidf_speak.py -d C:\PROGRA~1\mecab\dic\ipadic kaiwa_aruaru.txt  -s stop_words.txt
> おはよう
(1.00): おはよう
ごきげんよう
ごきげんよう
ごきげんよう
['ご', 'き', 'げ', 'ん', 'よ', 'う']
['go', 'ki', 'ge', 'n', 'yo', 'u']
./pyaudio/aiueo/go.wav
./pyaudio/aiueo/ki.wav
./pyaudio/aiueo/ge.wav
./pyaudio/aiueo/n.wav
./pyaudio/aiueo/yo.wav
./pyaudio/aiueo/u.wav

(0.00): そう です か 。 お忙しい の でしょ う ね
(0.00): 最近 どう よ ？
(0.00): どんな 感じ ？
```
###・自己自動会話
ところでやはり人が介在すると、どうも調整して質問するので、自前にどんどん会話が進むかを試してみた。
こうすることにより、会話には何が必要なのかを見るのが今回の目的である。
コードは以下のとおり
・[something2speak/tfidf_cyclic.py](https://github.com/MuAuan/something2speak/blob/master/tfidf_cyclic.py)
会話の肝心な部分は、単一なQAだと延々同様な会話が繰り返される恐れがあるということで、ちょっと前の回答はできないように制限しました。
※それでも話題が固定化する傾向が見えてきます。
ということで、ここでは三回前までの回答はできないようにしました。

```py
line = input("> ")
line1=line
line2=line
line3=line
while True:
    sims = cosine_similarity(vectorizer.transform([mecab.parse(line)]), vecs)
    index = np.argsort(sims[0])

    print("({:.2f}): {}".format(sims[0][index[-1]],questions[index[-1]]))
    text2speak(questions[index[-1]])
      
    print()
    time.sleep(2)
    line3=line2
    line2=line1
    line1=line
    while True:
        line = questions[index[-np.random.randint(1,7)]]
        if line1==line or line2==line or line3==line:
            continue
        else:
            break
```
また、ここでこの自動応答では会話を目指すので、QAタイプではなく、全て文章というか質問ということにしました。
つまり、文章集vecsは以下のようなものとしました。
[something2speak/data/single_sentences.txt](https://github.com/MuAuan/something2speak/blob/master/data/single_sentences.txt)
つまり、こういう文章空間の中で会話が進むかどうかが今回の興味です。
そのために、上記では次の質問を選ぶのに関連はあるけど、７番目までの質問をランダムに選べるようにしています。
これでも以下の実施例を見ると少し会話が回っちゃってますが、。。。

```
>python tfidf_cyclic.py -d C:\PROGRA~1\mecab\dic\ipadic single_sentences.txt  -s stop_words.txt
> おはよう
(1.00): おはよう
(1.00): なかなか のんびり は でき ない です ね
(1.00): 体重 は 減らさ ない と だめ だ ね
(1.00): そう だ 、 食べ すぎる より 、 運動 し た ほう が いい ね
(1.00): いい 感じ だ よ 、 そっち は
(1.00): どんな 感じ ？
(1.00): 危険 は ない けど 、 とにかく 忙しい 感じ です
(1.00): 今 仕事 が 忙しい ので 大変 です
(1.00): 仕事 は 危険 は ない の です か
(1.00): しょうが ない なぁ 、 カレー 作る か
(1.00): ドライブ と 食事 と どっち が 楽しい か なぁ
(1.00): 箱根 も いい なぁ
(1.00): でも 外 暑い から なぁ
(1.00): ドライブ でも 行こ う か
(1.00): ドライブ と 食事 と どっち が 楽しい か なぁ
(1.00): しょうが ない なぁ 、 カレー 作る か
(1.00): 仕事 は 危険 は ない の です か
(1.00): 仕事 です か
(1.00): 今 仕事 が 忙しい ので 大変 です
(1.00): 忙しい けど 、 どうにか なっ て いる
(1.00): でも 何 も 食べ られ なく なっ ちゃう
```
###まとめ
・テキスト入力と音声応答で会話して遊んでみた
・工夫として正規表現とTry～exceptを導入した
・会話が途切れない工夫として記憶を導入した

・会話では、単なるQAと異なり、記憶と類似のバランスで意味空間を綺麗に遷移させる必要がある
・会話データ蓄積・学習型のアプリに拡張する
###おまけ
本文からの続き。。

```
(1.00): ドライブ でも 行こ う か
(1.00): どんぶり でも いい か な
(1.00): 伊豆 でも 行こ う か
(1.00): そう です か 。 お忙しい の でしょ う ね
(1.00): 天丼 食べよ う か
(1.00): 天丼 食べ たい な
(1.00): カレーライス が 食べ たい な
(1.00): 何 食べ たい
(1.00): 食べ たい けど 、 体 に 悪い よ
(1.00): ラーメン 食べ たい な
(1.00): 天丼 食べ たい な
(1.00): カレーライス が 食べ たい な
(1.00): おいしい もの 食べ たい な
(1.00): ラーメン 食べ たい な
(1.00): ラーメン 太る か な
(1.00): どんぶり でも いい か な
(1.00): ドライブ でも 行こ う か
(1.00): 伊豆 でも 行こ う か
(1.00): そう です か 。 お忙しい の でしょ う ね
(1.00): 天丼 食べよ う か
(1.00): 仕事 です か
(1.00): お 元気 です か
(1.00): ちょっと お 会い し たく て 来 まし た
(1.00): 今 は IT 系 の お 仕事 やっ て い ます
(1.00): IT って どんな お 仕事 です か
(1.00): お 元気 です か
(1.00): 仕事 です か
(1.00): 仕事 は 危険 は ない の です か
(1.00): しょうが ない なぁ 、 カレー 作る か
(1.00): 軽井沢 が いい なぁ
(1.00): IT 社長 とか 軽井沢 に 別荘 持っ て いる よ なぁ
(1.00): 今 は IT 系 の お 仕事 やっ て い ます
(1.00): まあ 、 ぼちぼち やっ て い ます 。 あなた は 何 を やっ て い ます か
(1.00): のんびり さ れ て い て いい です ね
(1.00): なかなか のんびり は でき ない です ね
(1.00): 体重 は 減らさ ない と だめ だ ね
(1.00): まあ 、 ね
(1.00): この ところ 忙しかっ た けど 、 まあ まあ
(1.00): ドライブ も 気持ちいい と 思う けど
(1.00): ドライブ と 食事 と どっち が 楽しい か なぁ
(1.00): しょうが ない なぁ 、 カレー 作る か
(1.00): 仕事 は 危険 は ない の です か
(1.00): 今 仕事 が 忙しい ので 大変 です
(1.00): 危険 は ない けど 、 とにかく 忙しい 感じ です
(1.00): どんな 感じ ？
(1.00): どんな 御用 です か
(1.00): 今日 は 何 の 御用 です か
(1.00): お 元気 です か
(1.00): そう いえ ば お 久しぶり です 。 今 は 何 を やっ て いる ん です か
(1.00): できれ ば カレーライス 作っ て よ
(1.00): いい よ 、 で そっち は ？
(1.00): いい 感じ だ よ 、 そっち は
(1.00): どんな 感じ ？
(1.00): 軽井沢 は 夏 は 混む よ
(1.00): IT 社長 とか 軽井沢 に 別荘 持っ て いる よ なぁ
(1.00): 忙しい けど 、 どうにか なっ て いる
(1.00): 危険 は ない けど 、 とにかく 忙しい 感じ です
(1.00): 今 仕事 が 忙しい ので 大変 です
(1.00): 仕事 です か
(1.00): お 元気 です か
(1.00): ちょっと お 会い し たく て 来 まし た
(1.00): 最近 お 顔 を 拝見 し て い ない ので 会い たく なり まし た
(1.00): それでも 、 何 も し て い ない という こと で は ない ので 一 日 が 早く 過ぎ ます
(1.00): なんとなく 一 日 が 過ぎ て い ます
(1.00): 今 は IT 系 の お 仕事 やっ て い ます
(1.00): まあ 、 ぼちぼち やっ て い ます 。 あなた は 何 を やっ て い ます か
(1.00): ウェブ の 開発 です 。 主 に デザイン やっ て ます
(1.00): そう いえ ば お 久しぶり です 。 今 は 何 を やっ て いる ん です か
(1.00): できれ ば カレーライス 作っ て よ
(1.00): いい よ 、 で そっち は ？
(1.00): 軽井沢 が いい なぁ
(1.00): 軽井沢 は 夏 は 混む よ
(1.00): いい 感じ だ よ 、 そっち は
(1.00): 高血圧 と 糖尿 病 だ けど 、 食事 制限 は し て ない よ
(1.00): 食事 制限 は し た ほう が いい ん じゃ ない の
(1.00): 筋肉 運動 が 成人病 に は いい と 聞い た けど 、 どう な ん だろ う
(1.00): そう だ 、 食べ すぎる より 、 運動 し た ほう が いい ね
(1.00): いい 感じ だ よ 、 そっち は
(1.00): どんな 感じ ？
(1.00): 軽井沢 は 夏 は 混む よ
(1.00): いい よ 、 で そっち は ？
(1.00): 軽井沢 が いい なぁ
(1.00): 箱根 も いい なぁ
(1.00): でも 外 暑い から なぁ
(1.00): どんぶり でも いい か な
(1.00): それ より 血圧 心配 か な
(1.00): ラーメン 食べ たい な
(1.00): 天丼 食べ たい な
(1.00): 天丼 食べよ う か
(1.00): そう です か 。 お忙しい の でしょ う ね
(1.00): はい そう です
(1.00): そう だ 、 食べ すぎる より 、 運動 し た ほう が いい ね
(1.00): いい 感じ だ よ 、 そっち は
(1.00): 高血圧 と 糖尿 病 だ けど 、 食事 制限 は し て ない よ
(1.00): 食事 制限 は し た ほう が いい ん じゃ ない の
(1.00): ラーメン じゃ だめ
(1.00): 体重 は 減らさ ない と だめ だ ね
(1.00): そう だ 、 食べ すぎる より 、 運動 し た ほう が いい ね
(1.00): 食事 制限 は し た ほう が いい ん じゃ ない の
(1.00): 適度 な 運動 が いい ん じゃ ない
(1.00): ラーメン じゃ だめ
(1.00): ラーメン 食べ たい な
(1.00): ラーメン 太る か な
(1.00): どんぶり でも いい か な
(1.00): ドライブ でも 行こ う か
(1.00): 伊豆 でも 行こ う か
(1.00): 天丼 食べよ う か
(1.00): そう です か 。 お忙しい の でしょ う ね
(1.00): はい そう です
(1.00): 忙しい けど 、 どうにか なっ て いる
(1.00): IT 社長 とか 軽井沢 に 別荘 持っ て いる よ なぁ
(1.00): 軽井沢 が いい なぁ
(1.00): 箱根 も いい なぁ
(1.00): しょうが ない なぁ 、 カレー 作る か
(1.00): ドライブ と 食事 と どっち が 楽しい か なぁ
(1.00): ドライブ でも 行こ う か
(1.00): どんぶり でも いい か な
(1.00): ラーメン 太る か な
(1.00): 仕事 です か
(1.00): 今 は IT 系 の お 仕事 やっ て い ます
(1.00): まあ 、 ぼちぼち やっ て い ます 。 あなた は 何 を やっ て い ます か
(1.00): それでも 、 何 も し て い ない という こと で は ない ので 一 日 が 早く 過ぎ ます
(1.00): それでも 体重 は 減らさ ない と いか ん なぁ
(1.00): 適度 な 運動 が いい ん じゃ ない
(1.00): 筋肉 運動 が 成人病 に は いい と 聞い た けど 、 どう な ん だろ う
(1.00): 食堂 が いい な
(1.00): いい よ 、 で そっち は ？
(1.00): いい 感じ だ よ 、 そっち は
(1.00): 危険 は ない けど 、 とにかく 忙しい 感じ です
(1.00): どんな 感じ ？
(1.00): どんな 御用 です か
(1.00): IT って どんな お 仕事 です か
(1.00): 今 は IT 系 の お 仕事 やっ て い ます
(1.00): ウェブ の 開発 です 。 主 に デザイン やっ て ます
(1.00): それでも 、 何 も し て い ない という こと で は ない ので 一 日 が 早く 過ぎ ます
(1.00): なんとなく 一 日 が 過ぎ て い ます
```