LoginSignup
4
4

More than 5 years have passed since last update.

Rails Heroku × linebot Repl-AIで対話できるbotを作ってみた

Last updated at Posted at 2016-07-11

ハッカソンで動くものができたので、メモ。
全ソースは以下です。
https://github.com/hiranoi/kuidaore_bot

INDEX

  1. この記事のゴール
  2. Rails Heroku × lineapiでオウム返しするbotを作る
  3. Rails Heroku × Repl-AIで会話できるbotを作る
  4. Repl-AIの会話を大阪弁に変換すして返すbotを作る

この記事のゴール

  • これを作る(参加者募集時に作った資料)
    Cm0IepEVYAAaci1.jpg

  • こうなる(会話が成り立っていないのは、Repl-AIのチューニングをしていないから、、、)
    slack_for_ios_upload_1024-1.jpg

Rails Heroku × lineapiでオウム返しするbotを作る

Rails Heroku × Repl-AIで会話できるbotを作る

/lib/repl_ai_client.rb
require "faraday"
require "faraday_middleware"
require "json"
require "pp"

class ReplAiClient
  URL_HEAD = 'https://api.repl-ai.jp'

  def initialize(api_key, bot_id = 'normal', scenario ='greeting')
    @api_key = api_key
    @bot_id  = bot_id
    @scenario = scenario
  end

  def get_user_id
    res = post('/v1/registration',{
      botId: @bot_id
      })
    res.body
  end

  def get_message(user_id, message, flag = true)
    res = post('/v1/dialogue',{
        appUserId: user_id,
        botId: @bot_id,
        voiceText: message,
        initTalkingFlag: flag,
        initTopicId: @scenario,
        appRecvTime: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
        appSendTime: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
      })
    res.body
  end

  private

  def post(path, data)
    client = Faraday.new(:url => URL_HEAD) do |conn|
      conn.request :json
      conn.response :json, :content_type => /\bjson$/
      conn.adapter Faraday.default_adapter
      # conn.proxy @proxy
    end

    res = client.post do |request|
      request.url path
      request.headers = {
          'Content-type' => 'application/json; charset=UTF-8',
          'x-api-key' => @api_key
      }
      request.body = data
    end
    res
  end
end
/app/controllers/webhook_controller.rb
class WebhookController < ApplicationController
  protect_from_forgery except: :callback # CSRF対策無効化

  CHANNEL_ID = ENV['LINE_CHANNEL_ID']
  CHANNEL_SECRET = ENV['LINE_CHANNEL_SECRET']
  CHANNEL_MID = ENV['LINE_CHANNEL_MID']
  OUTBOUND_PROXY = ENV['LINE_OUTBOUND_PROXY']
  REPL_API_KEY = ENV['REPL_API_KEY']

  def callback
    unless is_validate_signature
      render :nothing => true, status: 470
    end
    result = params[:result][0]
    logger.info({from_line: result})

    req_message = result['content']['text']
    from_mid = result['content']['from']

    repl_client = ReplAiClient.new(REPL_API_KEY)
    res_message = repl_client.get_message('TODO:USER_IDを入れる', req_message)

    client = LineClient.new(CHANNEL_ID, CHANNEL_SECRET, CHANNEL_MID, OUTBOUND_PROXY)
    res = client.send([from_mid], res_message['systemText']['expression'])

    if res.status == 200
      logger.info({success: res})
    else
      logger.info({fail: res})
    end
    render :nothing => true, status: :ok
  end

  private
  # LINEからのアクセスか確認.
  # 認証に成功すればtrueを返す。
  # ref) https://developers.line.me/bot-api/getting-started-with-bot-api-trial#signature_validation
  def is_validate_signature
    signature = request.headers["X-LINE-ChannelSignature"]
    http_request_body = request.raw_post
    hash = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, CHANNEL_SECRET, http_request_body)
    signature_answer = Base64.strict_encode64(hash)
    signature == signature_answer
  end
end
terminal上で
# 定数を設定する
$ heroku config:add REPL_API_KEY="XXXXXXXXXXXXXXXXXXX"

※注意

  • ハッカソンの時間の都合上、ユーザごとにID払い出す処理を行っていません。(LINEのIDとRepl-AIのIDを紐付けるのが面倒だった)そのため、ユーザAの会話情報がユーザBにも引き継がれます。

Repl-AIの会話を大阪弁に変換すして返すbotを作る

/lib/convert_to_osaka.rb
require 'yaml'

class ConvertToOsaka
  def initialize(tm)
    @tm = tm
  end

  def convert
    d = YAML.load_file("#{Rails.root}/lib/osaka.yml")
    # 文章にhashのキーが含まれているかを確認する
    d.each do |k, v|
      # 一致すればvalueに置換する
      @tm.gsub!(k, v)
    end
    @tm
  end
end
  • センスはないが、標準語→大阪弁の対応表はHashで持つ
/lib/osaka.yml
ありがとうございました: おおきに
あなた: あんさん
あんな: あないな
りますので: るさかいに
りますから: るさかいに
あります: あるんや
あるいは: せやなかったら
或いは: せやなかったら
ありません: おまへん
ありました: おました
いない: おらへん
いまどき: きょうび
いわゆる: なんちうか,ようみなはんいわはるとこの


 # 長いので割愛
/app/controllers/webhook_controller.rb
# 以下の部分を編集
res = client.send([from_mid], ConvertToOsaka.new(res_message['systemText']['expression']).convert)

こんな感じです。まだまだ改善の余地はありますが、一旦これで動きます。

4
4
0

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
4
4