AWSでlinebot✗chatGPT4を作るときに苦労したこと(備忘録)
はじめに
今回はlineのchatbot作成について考えてみる。ゆくゆくはchatbotとchatgptを繋げて作れるようにやってみようと考えているが、まずは基本の構造が分からなければならないので、一旦はchatbotができるようになってみる。できたらその後にchatGPTを導入して、最後にAWSという流れである。今回の記事では基本的な解説はせず、自分が以下の動画を見て、詰まったところのみを解説しておくという感じの備忘録である。
あとは、chatgptを導入する際に使ったこのサイトで使える技術も盗んで利用している。
備忘録
condaからpipへ
まず最初の関門であったのが、condaの環境ではline-bot-sdkが動かないということ。別に使わなくても開発はできるそうなのだが、JqueryのないJSみたいな辛さがあるのでpipに変えることに。以下は参考記事です。pipのvirtualenvを使った開発のほうが自由度が高くて良さそうだなぁと思ったが、今回はenvつくってpipだけで十分なので、一つ目の記事を主に参考にした。
venvの存在
全然知りませんでした。というかpython初心者なもんで、そもそも仮想環境をcondaでもあまり作らないまま世界を過ごしてきたので、こんな便利なものがあるんかい!と叫びたくなりますね。
requirememts.txtの存在
これまた便利な機能です。
pip install -r requirements.txt
と打つと、requirememtsにあるパッケージをすべてインストールしてくれるよう。こりゃvenv使いやすくなるわけだ。あぁ。
.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)
init.pyの仕様について
今まで__init__.pyが何なのか全く知らなかった。どんなものなのか分からなかったけれど、これをしてみるとうまくモジュールの分割ができるということに気づいてすっげーってなります。
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について
以下の記事がまじで参考になった。とりあえず載せておく。
ただそのまま使って成功しても仕方ないので、自分のコードでこれを実行しようとすると色々な罠があった。まじで苦労した。それぞれを見ていく。
zipをアップロードすることについて
zipをフォルダ単位でcompressすると、そのままアップロードしたときに階層構造がおかしくなってしまった。詳しくは以下の通り。
だから、zipをするときは複数ファイル選択でして、Archive.zipができるようにしておく。
flaskを使わない
なんか全然気づいてなかったけど、flaskを使ってなくって、lambda_handlerって関数を定義しないといけない。
layerの定義方法
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の方を使っているみたい。
Bad request
だいたいこれがサーバーから返ってくるときは、環境変数のコピペがミスってるか、なんか空白が入ってるとかそんな感じだと思う。
DynamoDBの使い方について
会話の履歴をchatGPTに持たせたいという仕様の改善。
DynamoDBを使ってこれを改善するのだが、これまた大変な作業になるので、とりあえず参考になりそうな記事を漁って見つけた。
参考になりそうな記事一覧
chatGPTに会話の履歴を持たせたいならこれがいいかも。
Amplifyを使ったらこれかな
Discussion