GPT-3.5 × AWS Lambda × Amazon DynamoDB × Amazon API Gatewayを使ったSlackのチャットボットをPythonで実装する

## 概要

Slack上でGPT-3.5を使用することができるBotを実装しました。GPT-3.5は今話題のChat GPTの基となるプロダクトであり、APIを用いて使用することができます。また、APIを使用すればファインチューニングが可能となるため、その強みを活かしたBotを実装しました。（[ファインチューニング](https://en.wikipedia.org/wiki/Fine-tuning)とは意図した出力となるように、既存のモデルに追加で学習させ、モデルのパラメータを調整するプロセスのことです。）
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/01c12f89-7dfb-f6c4-4949-c557335bcfcc.gif)



## 設計

全体の設計は以下の画像の通りです。
![スクリーンショット 2023-01-21 18.31.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/7d68a87e-b5f4-0f06-1467-6fc61a2884d0.png)
画像の設計図のうちの一部部分ずつを解説していきたいと思います。

## Slack & Amazon API Gateway

Slackが一定の処理を行うとAPI GatewayにHTTP Requestを送信するようにしています。

今回は以下のイベントが発生した際にAPI GatewayにHTTP Requestが送信されるようにしています。

- Botへのメンション付きメッセージ
- ショートカットの使用
- ボタン（Interactive Components）の使用
- モーダル（Interactive Components）の使用

※[Interactive Components](https://api.slack.com/reference/block-kit/interactive-components)とはSlackによって提供されるインタラクティブなUIキットです。ユーザーからのアクションによって発生するイベントが変化します。

また、Slackではイベントが発生した際に送信されるHTTP Requestの送信先を指定することができます。こちらはAPI Gatewayで生成したURLを指定しています。

## Amazon API Gateway & AWS Lambda

こちらは比較的簡単でAWS Lambdaのトリガーとして、Amazon API GatewayをAWSのUI上で設定するだけです。

lambda_function.pyというファイルにlambda_handlerという関数を実装しておくことで、処理が実行されます。

Amazon API GatewayからAWS Lambdaに送信されたデータは、AWS Lambda上でJSONからPythonの辞書型に変換され、そこに格納されるデータを識別して①GPTのAPIにRequestを送信するか②DynamoDBに格納するか③DynamoDBに格納されているデータを送り返すかを判定しています。

また、AWS Lambdaで使用されるPythonの外部モジュールは　レイヤーとしてZipファイルで格納します。この時のZipファイルの大きさに上限があり、上限を超える場合は[Amazon S3](https://aws.amazon.com/jp/s3/)に格納する必要があります。今回についても、Openaiによって提供さているGPT用のモジュールは非常に膨大であったためS3を利用しています。
![スクリーンショット 2023-01-21 19.52.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/49b64c3e-7b3f-1219-ddaf-b025454d2c1f.png)


## AWS Lambda & Amazon DynamoDB

Amazon DynamoDBには二つのテーブルを実装しました。

- Slackのモーダルやボタン等の送信データを格納するテーブル
- Slackでモーダルを利用した受信データを格納するテーブル

受信データを格納するテーブルのデータはファインチューニングに使用することを想定しています。
※モーダルとボタンはそれぞれ以下の通りに実装しました。
![スクリーンショット 2023-01-21 21.30.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/ebbaf0d1-e044-37dd-abb1-18a835e8efc7.png)
![スクリーンショット 2023-01-21 21.30.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/60482047-7a29-77fe-1e2b-90443e6b80e3.png)



## AWS Lambda & GPT-3.5

ここで行うのはGPT APIへのデータ送信とその返り値のSlackへの送信のみなのですが、単純にGPT-3.5にデータを送るだけでは文脈を理解してくれないので、SlackのスレッドのメッセージをまとめてGPT-3.5に送る必要があります。
![スクリーンショット 2023-01-21 20.44.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/9347653a-ef82-23f9-f3f6-7422a4a6263f.png)
具体的にはSlack APIを使用して、投稿のあったスレッドのテキストメッセージを一つの文章にしてGPTに送信しています。
![スクリーンショット 2023-01-21 21.53.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611951/5e6f4f14-4444-0ddc-d43c-5cd30f4b2a68.png)



## 総括
AWS自体をそこまで触ったことがなかったので、入門の入門ぐらいは触れたかなと思います。また、GPTのAPIも利用したことで、Genarative AIの可能性（情報ソースとして使うことは難しいですが、自分の思考のサポート役としては大変有能であると言った印象です。）や導入の簡単さを感じることができました。
今回取り上げたファインチューニングについては、必要なデータの数がOpen AI側から最低でも数百と指定されていたので、現時点での実際の使用には至っていません。ただ、この数百という数字もこれからもっと下がって行くのかなと思います。
最近、GPTではなくChat GPTのAPIの開発が発表されたので、どのような違いが出現するのか楽しみです。


## コード
https://github.com/SoichiroSugimoto/slack-based_fine-tuning

## 資料
- [Slack Interactive Messageリファレンス](https://qiita.com/hypermkt/items/b2ffaf610ac92235c4d6)
- [Handling user interaction in your Slack apps](https://api.slack.com/interactivity/handling)
- [【とりあえずハンズオン】AWSのクイズを出題するLINE bot作成してみた！](https://zenn.dev/cloudtech/articles/2021-10-28-cloudtech-line-event)
- [DockerとDocker ComposeでPythonの実行環境を作成する](https://zuma-lab.com/posts/docker-python-settings)
- [DockerでPython実行環境を作ってみる](https://qiita.com/jhorikawa_err/items/fb9c03c0982c29c5b6d5)
- [OpenAI API](https://platform.openai.com/docs/api-reference)
- [ChatGPTで用いられるGPT-3.5系のモデルをAPIから利用してみた](https://qiita.com/kaz2ngt/items/d26dd572bd82fcd3dfd3)