恋するプログラムをSinatraでWebアプリにするPart.10[CHAPTER7 学習のススメ]③
記事の概要
『恋するプログラム』の[CHAPTER7 学習のススメ]を参考に、形態素解析を利用して応答時の語彙を増やすチャットボットを作成します。
目次
開発環境
- OSX 10.11.2 El Capitan
- テキストエディタ: MacVim
- ターミナルエミュレータ: Macターミナル
- シェル: zsh
- パッケージマネージャ: Homebrew
- ブラウザ: Firefox - Ruby 2.0.0p645
- バージョンマネージャ: rbenv
- Webフレームワーク: Sinatra - MeCab 0.996
- 日本語辞書: IPA辞書
参考記事
Rubyの開発環境構築は、こちらの記事を参考にさせていただきました。
ノビィの辞書の種類を増やす
入力した会話の内容をランダム辞書に追加しつつ、形態素解析を利用して名詞を抽出し、名詞をキーワードにした応答をパターン辞書へ、名詞を除外した文の骨組みをテンプレート辞書へ追加します。
アプリケーションディレクトリの構成
~/programinlove
|- proto.rb // CUIチャットボットのメインファイル
|- unmo.rb // チャットボットオブジェクトのモデル
|- responder.rb // 応答オブジェクトのモデル
|- dictionary.rb // 辞書を読み込み管理するクラス
|- mecab_natto.rb // 形態素解析器MeCabを使うためのモジュール
|- morph.rb // MeCabNattoモジュールをunmo.rbで使うためのモジュール
|- log.txt // ユーザの入力履歴を保存するログファイル
|- /dics // 辞書ファイルを格納するディレクトリ
| |- random.txt // ランダムな応答を返すための辞書
| |- pattern.txt // パターンに合った応答を返すための辞書
| |- template.txt // テンプレートを使った応答を返すための辞書
|- noby.rb // Webアプリのメインファイル
|- /views // ビューのテンプレートを配置するディレクトリ
| |- index.erb // チャットのインターフェースを表示するビュー
|- /public // 静的ファイルを配置するディレクトリ
|- nobycanvas.js // キャラクターの画像をアニメーションさせるJavascript
|- styles.css // チャットのインターフェースをレイアウトするcss
|- /img // 画像ファイルを格納するディレクトリ
|- /normal // 平常時の画像を格納するディレクトリ
|- /blink // 瞬きの画像を格納するディレクトリ
|- /lookaround // 周囲を見回す画像を格納するディレクトリ
|- /talk // 喋る画像を格納するディレクトリ
~ 以下に表情ごとの画像を格納するディレクトリを配置
ソースコード
morph.rb
からmecab_natto.rb
を呼び出し、形態素解析の結果を配列に格納します。
サンプルプログラムと異なり形態素解析にMeCabを使用しているため、init_analyzer
メソッドとanalyze
メソッドの中身をMeCabの出力に合わせて変更しています。
Morph
モジュールの初期化は、noby.rb
のコンフィギュレーションでMorph::init_analyzer
メソッドを呼び出して行ないます。
その他のRubyファイルは、サンプルプログラムと同様の記述で、特に変更はありません。
morph.rb
require_relative 'mecab_natto' module Morph def init_analyzer MeCabNatto::setarg('-F%m\s%F-[0,1,2]') end def analyze(text) # 形態素解析の出力を表層形と品詞を要素にした配列にして # 解析結果の配列に格納する analysis_result = [] MeCabNatto::analyze(text).each do |part| analysis_result.push(part.feature.split(/ /)) if !part.is_eos? end return analysis_result end def keyword?(part) return /名詞-(一般|固有名詞|サ変接続|形容動詞語幹)/ =~ part end module_function :init_analyzer, :analyze, :keyword? end
noby.rb
require 'sinatra' require 'sinatra/reloader' require_relative 'unmo' # 会話ログを格納する配列 log_area = [] # 起動時にオプションを設定する # 状態を保持するオブジェクトの生成に使う configure do # ノビィ生成 set :noby, Unmo.new('noby') # 形態素解析のためにMorphモジュールを初期化 set :morph, Morph::init_analyzer end # ヘルパーメソッドを定義する # ルーティングメソッドの中で使う helpers do def noby # ノビィへアクセス noby = settings.noby end def prompt(resp_opt) # 応答を表示する際のプロンプトを作成 resp_opt ? "#{noby.name}:#{noby.responder_name}" : "#{noby.name}" end def change_looks # 感情値で表情を変化させる case noby.mood when -5..5 then 'talk' when -10..-5 then 'angry_talk' when -15..-10 then 'more_angry_talk' when 5..10 then 'happy_talk' when 10..15 then 'more_happy_talk' end end def save_log(log) # ファイルにログを書き込む noby.save open('log.txt', 'a') do |f| f.puts(log) end end end # URL'/'にアクセス get '/' do # 日時情報をログに格納 log = "\nUnmo System : #{noby.name} Log -- #{Time.now}" save_log(log) # 会話ログを初期化してnobyfomを表示 log_area = [] erb :index end # URL'/'にPOSTメソッドでアクセス post '/' do # ユーザの入力を取得 talk_text = params['inputarea'] # Responderを表示するチェックボックスの状態を取得 # チェックされてる場合は状態を維持 resp_opt = params['respoption'] @check = "checked" if resp_opt # ユーザの入力があれば応答して会話ログに表示 unless talk_text.empty? @responder_resp = noby.dialogue(talk_text) log_area << "> #{talk_text}<br>" log_area << "#{prompt(resp_opt)}> #{@responder_resp}<br>" @noby_state = change_looks save_log(talk_text) end @talk_log = log_area.join erb :index end
このコードのコミットには、[chapter7-4]のタグが付いてます。
実行結果
ターミナルでnoby.rb
を動かし、ブラウザにhttp://localhost:4567
を入力します。
~/programinlove
$ruby noby.rb
会話に含まれていた名詞が、会話の内容と共にパターン辞書に保存され、会話の内容から名詞を除外した文の骨組みがテンプレート辞書に保存されます。
0##すもも 0##すもももももももものうち 0##もも 0##すもももももももものうち 0##私 0##私はプログラムの女の子です 0##プログラム 0##私はプログラムの女の子です 0##女の子 0##私はプログラムの女の子です
3 %noun%も%noun%も%noun%のうち 3 %noun%は%noun%の%noun%です
参考書籍
参考記事
Sinatraについては、こちらの記事を参考にさせていただきました。
- Rubyの入門や書き捨てアプリを作る場合は sinatraがオススメ! - むかぁ~ どっと こむ
- SinatraとjQueryでおよそ100行で作るAjax掲示板アプリケーション - gaaamiiのブログ
- Sinatra: README (Japanese)
関連記事
- 恋するプログラムをSinatraでWebアプリにするPart.0[はじめに]
- 恋するプログラムをSinatraでWebアプリにするPart.1[CHAPTER3 ほんとに無能]
- 恋するプログラムをSinatraでWebアプリにするPart.2[CHAPTER4 あこがれのGUI]①
- 恋するプログラムをSinatraでWebアプリにするPart.3[CHAPTER4 あこがれのGUI]②
- 恋するプログラムをSinatraでWebアプリにするPart.4[CHAPTER4 あこがれのGUI]③
- 恋するプログラムをSinatraでWebアプリにするPart.5[CHAPTER5 辞書を片手に]
- 恋するプログラムをSinatraでWebアプリにするPart.6[CHAPTER6 感情コントロールの魔術師]①
- 恋するプログラムをSinatraでWebアプリにするPart.7[CHAPTER6 感情コントロールの魔術師]②
- 恋するプログラムをSinatraでWebアプリにするPart.8[CHAPTER7 学習のススメ]①
- 恋するプログラムをSinatraでWebアプリにするPart.9[CHAPTER7 学習のススメ]②
- 恋するプログラムをSinatraでWebアプリにするPart.11[CHAPTER8 文章を作り出す]
- 恋するプログラムをSinatraでWebアプリにするPart.12[CHAPTER9 ノビィ、ネットワークにつながる]
- 恋するプログラムをSinatraでWebアプリにするPart.13[おわりに]