LoginSignup
12
4

More than 1 year has passed since last update.

LambdaとAPI Gatewayを使用してChatBotを作成する【Ruby】

Last updated at Posted at 2023-03-24

今回は、AWS Lambda + API Gatewayを使った簡単なChatBotを作ってみたので、その紹介をしていきます。
とりあえず動くというところをゴールにして作ったので、実際に運用するにはもう少し作り込みが必要です。チュートリアルとして参考にしてもらえればと思います。

前提条件

  • LINE Developersのコンソールにアクセスできる(LINEのアカウントがあれば簡単に可能です)
  • AWSコンソールで作業ができる
  • Rubyのソースが読める(LambdaではRubyを使ってコードを書きます)

実装していく

Lambdaの準備

まず、LINEから送られるメッセージのパラメータを検証するためのAWS Lambdaを準備しておきます。
関数の内容は以下の通りです。

lambda_function.rb
require 'json'

def lambda_handler(event:, context:)
    logger = Logger.new(STDOUT)
    log_formatter = proc { |severity, timestamp, _, msg|
        JSON.dump({ time: timestamp, level: severity, message: msg })
    }
    logger.formatter = log_formatter
    
    logger.info event
end

LINEから受け取ったパラメータの詳細を確認するために、eventの内容をログに書き出しておきます。ログの形式をJSON形式で書き出すようにしておくとCloudWatch Logsで確認する時に見やすくなるのでオススメです!

このLambda関数が通信を受けられるようにするために、前段にAPI Gatewayを設定します。
Lambdaの設定にあるトリガーの項目から、API Gatewayを利用したトリガーを追加してください。API Gatewayの設定内容は以下の通りです。
インテント: 新規APIを作成
APIタイプ: HTTP API
セキュリティ: 開く
スクリーンショット 2023-03-23 15.30.02.png
APIエンドポイントは後から使うのでコピーしておいてください。

LINEチャネルを作成する

メッセージを送るためのLINEチャネルを作成するために、LINE Developersのコンソールにアクセスします。
スクリーンショット-2023-03-23-15.17.23.png
プロバイダーを作成し、プロバイダーのチャネル設定からMessaging APIチャネルを作成します。チャネル名、チャネル説明、大業種、小業種等の項目の入力が必要です。内容は適宜埋めてください。
スクリーンショット-2023-03-24-13.43.31.png
チャネルの作成が完了すると上の画像のような画面が表示されるので、Messaging API設定から、Webhook URLの設定を行います。
スクリーンショット-2023-03-24-14.14.24.png
Webhook URLには先ほど作成したAPI GatewayのAPIエンドポイントURLを指定してください。
スクリーンショット 2023-03-24 14.04.11.png
Webhookの利用はデフォルトはOFFになっているのでONにしておいてください。
検証ボタンを押して成功と表示されれば完了です。
スクリーンショット 2023-03-23 15.30.41.png
ついでに、LINEにメッセージを送る時に必要になるチャネルアクセストークンを発行しておきます。
スクリーンショット-2023-03-23-15.20.50.png

LINEメッセージのパラメータを確認する

Messaging API設定の中にQRコードが表示されているので、それを利用して友達登録します。
とりあえずメッセージを送ってみると次のようになりました。
Screenshot_20230323-154038.png
LINE側で勝手にメッセージが返却されているので、応答メッセージの設定をOFFにしておきます。

Lambdaに送られたパラメータをCloudWatch Logsで見てみると、JSON型で送られてきていることが確認できました。
スクリーンショット 2023-03-23 15.38.00.png
bodyJSON.parseを用いてログに書き出してみると、メッセージ送信時のパラメータが確認しやすくなりました。
スクリーンショット-2023-03-24-13.20.24.png

メッセージを返す仕組みを作る

最後に、受け取ったメッセージに合わせて返答する仕組みを作っていきます。
LINEのチャネルアクセストークンはソースコード上に直接書きたくないので、今回はAWS Systems Managerのパラメータストアを使って管理するようにしました。
スクリーンショット 2023-03-23 16.19.12.png

Lambdaからパラメータを取得するために実行ロールにssm:GetParameterを許可する設定を加えています。
ソースコードは以下になります。

lambda_function.rb
require 'json'
require 'aws-sdk-ssm'

def lambda_handler(event:, context:)
    logger = Logger.new(STDOUT)
    log_formatter = proc { |severity, timestamp, _, msg|
        JSON.dump({time: timestamp, level: severity, message: msg})
    }
    logger.formatter = log_formatter

    lambda_event_body = JSON.parse(event['body'])
    logger.info lambda_event_body
    # lineから送られてきたイベントを取得
    line_event = lambda_event_body['events'][0]
    if line_event['type'] == 'message'
        # テキストメッセージのみを受け付ける
        return unless line_event['message']['type'] == 'text'

        line_user_id = line_event['source']['userId']
        # 受け取ったテキストメッセージの内容に合わせてメッセージを返却
        case line_event['message']['text']
        when 'おはよう'
            push_line_message(line_user_id, 'おはよう')
        when 'こんばんは'
            push_line_message(line_user_id, 'こんばんは')
        else
           push_line_message(line_user_id, 'こんにちは')
        end
    end
end

# ラインメッセージ送信処理
def push_line_message(line_user_id, message)
    ssm_client = Aws::SSM::Client.new
    access_token = ssm_client.get_parameter({ name: '/line/access_token', with_decryption: true }).parameter.value
    headers = {
        'Content-Type': 'application/json',
        'Authorization': "Bearer #{access_token}"
    }
    data = {
        'to': line_user_id,
        'messages': [{ 'type': 'text', 'text': message }]
    }
    http_post_request('https://api.line.me/v2/bot/message/push', headers, data)
end

def http_post_request(api_url, headers, data)
    uri = URI.parse(api_url)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = uri.scheme === 'https'
    req = Net::HTTP::Post.new(uri.path)
    req.body = JSON.generate(data)
    req.initialize_http_header(headers)
    http.request(req)
end

難しいことは考えずに「おはよう」「こんにちは」「こんばんは」を返すようにしてみました。Lambdaの関数をデプロイ後、実際にメッセージを送ってみると、想定通りの返事がくることを確認できました!
screen-20230324-104235_2_AdobeExpress (1).gif

終わりに

今回作ったChatBotのメッセージ返却ロジックを作り込むだけでも十分使えるChatBotになっていくと思います。メッセージの返却部分に流行りのChatGPTのAPIを使ってみても面白いかなと考えています。

業務ではSlackを使っている人も多いと思います。SlackのChatBotを作る時も、LINEチャネルの代わりにSlackAppを作成して設定すること以外作り方は基本同じです。
上手く利用すれば、チャットを利用してのデプロイやサポートツールとしての利用等、各種ツールと組み合わせての業務効率化に役立つので是非試してみてください。

参考

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