😎

AWSでlinebot✗chatGPT4を作るときに苦労したこと(備忘録)

2023/11/22に公開

はじめに

今回はlineのchatbot作成について考えてみる。ゆくゆくはchatbotとchatgptを繋げて作れるようにやってみようと考えているが、まずは基本の構造が分からなければならないので、一旦はchatbotができるようになってみる。できたらその後にchatGPTを導入して、最後にAWSという流れである。今回の記事では基本的な解説はせず、自分が以下の動画を見て、詰まったところのみを解説しておくという感じの備忘録である。

https://www.youtube.com/watch?v=jBsvdgFMZtg&t=0s

あとは、chatgptを導入する際に使ったこのサイトで使える技術も盗んで利用している。

備忘録

condaからpipへ

まず最初の関門であったのが、condaの環境ではline-bot-sdkが動かないということ。別に使わなくても開発はできるそうなのだが、JqueryのないJSみたいな辛さがあるのでpipに変えることに。以下は参考記事です。pipのvirtualenvを使った開発のほうが自由度が高くて良さそうだなぁと思ったが、今回はenvつくってpipだけで十分なので、一つ目の記事を主に参考にした。

https://rakuichi4817.github.io/posts/start-pipenv/
https://yurufuwadiary.com/conda-or-pip

venvの存在

全然知りませんでした。というかpython初心者なもんで、そもそも仮想環境をcondaでもあまり作らないまま世界を過ごしてきたので、こんな便利なものがあるんかい!と叫びたくなりますね。
https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e
https://zenn.dev/nekoallergy/articles/py-env-pipenv01

requirememts.txtの存在

これまた便利な機能です。

pip install -r requirements.txt

と打つと、requirememtsにあるパッケージをすべてインストールしてくれるよう。こりゃvenv使いやすくなるわけだ。あぁ。
https://note.nkmk.me/python-pip-install-requirements/

.envの存在とdotenvについて

dotenvを使うと、tokenの管理とかがしやすくなります。ベタ書きにしてしまうと、そのコード内でどこがプライベートな部分かの関心の分離ができなくなります。

# ChatGPT のAPI key
CHATGPT_API_KEY=sk-YFXXXXXXXXXXXXXXXXXXXX

# LINE公式アカウントのチャンネルシークレット
LINE_CHANNEL_SECRET=44b25f9xxxxxxxxxxxxxxxxxxxxxxx

# LINE公式アカウントのアクセストークン
LINE_CHANNEL_ACCESS_TOKEN=jowcSHZ2JxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXbswdB04t89/1O/w1cDnyilFU=

使い方はこのようにすればいい。おそらく、dotenvで環境変数を.envから設定することができて、environ.getでそれを取得しているという感覚だろう。

from dotenv import load_dotenv
from os import environ
load_dotenv(".env", verbose=True)
if not (access_token := environ.get("LINE_CHANNEL_ACCESS_TOKEN")):
    raise Exception("access token is not set as an environment variable")

if not (channel_secret := environ.get("LINE_CHANNEL_SECRET")):
    raise Exception("channel secret is not set as an environment variable")

configuration = Configuration(access_token = access_token)
handler = WebhookHandler(channel_secret)

https://qiita.com/harukikaneko/items/b004048f8d1eca44cba9

init.pyの仕様について

今まで__init__.pyが何なのか全く知らなかった。どんなものなのか分からなかったけれど、これをしてみるとうまくモジュールの分割ができるということに気づいてすっげーってなります。
https://qiita.com/msi/items/d91ea3900373ff8b09d7

chatGPTの仕様について

まずはopenAIを使えるようになるところから始めたが、核になるのは本当にこれだけだった。

chat_completion = client.chat.completions.create(
        messages=[
            {
                "role": "user",
                "content": event.message.text,
            }
        ],
        model="gpt-3.5-turbo",
        )

モデルの選択とインプットのテキストの選択、ロールの選択のみ。で、返ってくる文章が入っているのは

chat_completion.choices[0].message.content

である。それさえわかっていれば難なく改良可能であった。

ngrokについて

ngrokというものこれまた驚きのソフトウェアで、ローカルサーバーをリモートサーバーに反映させるという機能はまさに希望の星。なのだが、何故かホストサーバーが5000だとうまく行かない。そのため、5002や3000で実行することで難なくクリアした。検証の際は、ngrokをつけたままでflaskだけ再起動するのが良い。僕はngrokも同じく再起動していて、lineのwebhookURLを毎回変えなくてはならなかったから。マジでアホやん。

AWSについて

以下の記事がまじで参考になった。とりあえず載せておく。
https://qiita.com/grapefruit1030/items/727bedb2867d90c7d1a6
https://qiita.com/chaoticcast/items/74d4d1021fbece360289

ただそのまま使って成功しても仕方ないので、自分のコードでこれを実行しようとすると色々な罠があった。まじで苦労した。それぞれを見ていく。

zipをアップロードすることについて

zipをフォルダ単位でcompressすると、そのままアップロードしたときに階層構造がおかしくなってしまった。詳しくは以下の通り。

だから、zipをするときは複数ファイル選択でして、Archive.zipができるようにしておく。

flaskを使わない

なんか全然気づいてなかったけど、flaskを使ってなくって、lambda_handlerって関数を定義しないといけない。

layerの定義方法

https://qiita.com/k_hoso/items/78beb33e53abfdddabe7#注意点
importの時に全然通らんやんけって思ってたけどこれかい。

pydantic_coreが通らない

ふざけんな。まじで苦労した。
解決策:
そもそもの話として、pydantic_coreはかなりバイナリなどの依存性が高いっぽくて、なんか色々と試したけどdependencyがうまく行ってないっぽくてNo module errorってなってた。しかし!pipの最強機能を使うといとも簡単にできてしまうのだ!

pip install --platform manylinux2014_aarch64 --target=package --implementation cp --python-version 3.11 --only-binary=:all: --upgrade pydantic_core

これを仮想環境内でやってみるといい。package内に超きれいなdependencyの整ったフォルダが出来上がる。それをレイヤーにいれて置けばいい。
他のline-bot-sdkとかは依存性をあんま気にしなくていいので、適当につくって別レイヤーに仮想環境ごとアップしちゃえばいい。

Macのアーキテクチャについて

よくわからんかったけど、M1,M2のマックはarmの方を使っているみたい。
https://qiita.com/Lion_rion/items/bd17381031648fabaa81

Bad request

だいたいこれがサーバーから返ってくるときは、環境変数のコピペがミスってるか、なんか空白が入ってるとかそんな感じだと思う。

DynamoDBの使い方について

会話の履歴をchatGPTに持たせたいという仕様の改善。
DynamoDBを使ってこれを改善するのだが、これまた大変な作業になるので、とりあえず参考になりそうな記事を漁って見つけた。

https://qiita.com/michitomo/items/a10465b12bcca32bf63a

https://michimani.net/post/aws-put-item-to-dynamodb-by-boto3/#boto3-を使った-dynamodb-への書き込み方法

参考になりそうな記事一覧

chatGPTに会話の履歴を持たせたいならこれがいいかも。
https://qiita.com/michitomo/items/a10465b12bcca32bf63a
Amplifyを使ったらこれかな
https://zenn.dev/zuma_lab/articles/gpt-4-line-chatbot

Discussion