脱シンプルBot!Chatbotプログラムを最大限活用するためには?[from CodeIQ]

編集部注:本記事は過去に CodeIQ MAGAZINE にて掲載されたものと同一内容となります

2017年はChatbotイヤー!
オリジナルのBotの作成に挑戦してみた方も多いのでは?
私も公開されているAPIドキュメントやサンプルプログラムを見れば、シンプルな応対Botなら簡単に作ることができます。
今回は、そのもう一歩先。さらにステップアップして、より柔軟性の高い、まるで人間と会話しているかのようなBotの作り方を学んでいきましょう!

ダメBotはどうしたら賢くなれるのか?

※本企画はLINE株式会社の提供で、CodeIQ MAGAZINEが制作したものです。
こんにちは、池澤あやかです。
エンジニア界隈では、昨年ごろからChatbotが流行ってますよね。私もこのブームに乗じていくつかBotを作ってみたのですが、我ながら自作したBotには少し使いづらさを感じています。
あらかじめ決められたワードに反応するようなBotになってしまっているため、柔軟性に欠けているといいますか。
Microsoftのりんなちゃんみたいな賢いBotを、とはいかないまでも、もう少し賢いBotを作りたいものです。
このダメBotはどうすれば賢くなるのでしょうか……。


今回教えてくださるのは、今まで数え切れないほどBotを作成してきた株式会社トレタのCTOにして、Botマスターの増井雄一郎さん。

▲増井雄一郎さん(株式会社トレタCTO)。『Titanium Mobile』の伝道師としての活躍や、「MobiRuby」「wri.pe」などの開発者として知られる。お風呂の中でゴリゴリプログラムを書く「風呂グラマー」としてもお馴染み。
前回長谷部さんに教えていただいたLINE Messaging APIに引き続き、今回は私が書いてきたシンプルな応答Botプログラムをベースにして、増井さんにコードレビューをしていただきつつ、より良いBotの作り方を学んでいきたいと思います!

池澤謹製!乙女心解説BOTとは


「池澤さんが作ってきてくれたBotは、どんなBotなんですか?」


「『乙女心解説BOT』という、女の子の気持ちを代弁してくれるBotです。これは女子あるあるだと思うんですけど、『今の私の気持ちを空気を読んで察してくれ』という含みを込めた発言をすることあるじゃないですか。そこをド直球に解説してくれるBotです」


「Botを入れたグループ内で、例えば『大丈夫?』と発言すると、このような乙女心解説が出てきます」


「(笑)」


「『疲れた』なんて発言すると、乙女心解説がこのように補足してくれます」


「うざい(笑)」


「喧嘩をしている時なんかに、『お互い大人なんだし』という発言をした際には、Botがこのように補足してくれます」


「池澤さんの心の闇が…」


「プログラムとしては、Rubyの軽量Webアプリケーション用フレームワークを使っています。LINEにテキスト送られると、ルート /line/callback にコールバックが発生して、用意していたAnalyzeTextクラスの中で分析するという流れです」

post '/line/callback' do
  body      = request.body.read
  signature = request.env['HTTP_X_LINE_SIGNATURE']

  unless client.validate_signature(body, signature)
    error 400 do 'Bad Request' end
  end

  events = client.parse_events_from(body)
  events.each do |event|
    case event
    when Line::Bot::Event::Message
      case event.type
      when Line::Bot::Event::MessageType::Text
        analyze = AnalyzeText.new(event.message['text'])
        result = analyze.result
        message = {
          type: 'text',
          text: result
        }
        client.reply_message(event['replyToken'], message)
      end
    end
  end
end


「AnalyzeTextクラスでは、とあるセンテンスパターンと一致するところがあった場合に、あらかじめ決めておいた答えを返すというシンプルな構造になっています」


▲文字列一致については、正規表現で記述しています。


「んー、シンプルな応対Botのプログラムとしては、基本的には問題ないですね。ただ、こうした方が今後の拡張性が高いなと感じるところはいくつかあるので、レビューしていきましょうか!」

人間の持つ「あいまいさ」を生むアルゴリズムの作り方


「まず大きいところで言うと、今の池澤さんのプログラムは、Caseで書いていますよね。これを配列に置き換えるというのは、Bot作成ではよくやる手です。こんな感じで」

@@patterns = [
  Pattern.new(
    /どうしたの?|大丈夫?/,
    [ "乙女心解説:", "めんどくさいな" ]
  ),
  PatternWithRandom.new(
    /疲れた/,
    [ "乙女心解説:", "今日は何もできない" ]
  ),
  # ....
]


「Patternクラスはこんな感じで準備しておきます」

class Pattern
  attr_reader :matcher, :response

  def initialize(matcher, response)
    @matcher, @response = matcher, response
  end

  # パターンにマッチするか?
  def match?(text)
    @matcher.match(text) != nil
  end
end

▲AnalyzeTextクラス内にパターンマッチ用のクラスを作ります。


「えー、配列!?なぜですか?」


「配列で書いたほうが、Caseで書くよりも一覧性が高いというのはもちろんなんですけど、一番の良さはパターンごとにアルゴリズムを含めることができるということです」


「例えば、パターン一致でも、毎回反応しないほうが人間らしかったりするじゃないですか。そうした時に、PatternWithRandomというクラスに、10回に1回だけマッチするようなアルゴリズムを書けばいいわけです」

# 1/10の確率で応答するパターン
  class PatternWithRandom < Pattern
    # 1/10でマッチする
    def match?(text)
      rand(10) == 0 && super
    end
  end

▲randで乱数を発生させ、10回に1度の確率で発動するようにする。


「確かに!Caseだと、こういったアルゴリズムを含んだものは書きにくいかも!」


「プログラムの場合、Patternを継承したクラスをつくることで、いろんなパターンに対応することができますよ」

環境依存はなるべく避けること


「他にこうしたほうがいいとか、何かありますか?」


「あとは細かいところなんだけど、改行コードはメッセンジャーやOSによって違うから、パターンの中に\nを含めるのは得策ではないですね」


「パターン定義の外で改行コードを加えることで、さまざまなOSに簡単に対応できます。環境依存のものへの対応は慎重に!」


「うっ、気をつけよう…」

さらにBotの柔軟性を高めるには、データベースを連携させよう!


「さらに柔軟に対応するには、どうすればいいでしょうか?」


「会話のステート管理を行ったり、気軽にパターンを増やせるように、パターンを管理するためのWebアプリをつくったりといろいろ考えられますね。これをするには、Botプログラムをデータベースに接続する必要がありますが」


「特定のキーワードに反応して、感情点数をあげていっても面白いと思います。僕も昔社内向けに、『考えます』や『頑張れ!』などのワードに反応して感情点数があがっていき、ある閾値を超えるといきなりブチ切れるというBotを作りました」


「感情まで再現できるとかなりリアルなBotになりそうですね(笑)」


「実際に、新しくチャットに入ってきた外部の人にBotが急にブチ切れて、外部の人が平謝りするという事件も起きるくらいのリアルさです」


「ひどい」


「その後、外部の人に迷惑かけれないということで、このBotはクビになっちゃいました(泣)」


「手動でパターンを増やしまくるか、裏に人工知能を入れるとかしないと、柔軟にBotに対応してもらうのは大変なのかなって半分諦めてたんですけど、意外にいろいろやり方があることが分かりました!」


「Botってグループに入れるとみんなでワイワイ楽しめるのがいいですよね。私のBotも会社の皆から意見をもらって、どんどん賢くなっていきました。チャットは周りからのフィードバックもすぐ聞けるし、モチベーション作りやすいので、いろいろ試しながら作ると楽しいですよ」

今回の題材となったBotのプログラムはこちらから

BotのGitHub
・添削前と添削後のdiffはこちらから
次回は、データベースと連携することで、Chatbotの反応をより人間らしくしてみることに挑戦したいと思います。お楽しみに!

※本記事はITエンジニア向け年収提示型スカウト「moffers(モファーズ)」からの提供記事です。

オリジナル版 初回掲載日 2017年9月26日

Related Post