😌

【Python初心者が】ChatGPT APIとLINEを繋げてみるし、文脈も把握させてみるし、ChatGPTの説明も簡単にしてみる

2023/03/11に公開

プロロロロローグ

そもそも

ChatGPTとは

OpenAI社が開発したチャットボット

ChatGPT APIとは

ChatGPTで用いているモデルと同じ「gpt-3.5-turbo」を利用しているAPI

料金は1000トークンあたり0.002ドル

日本語の場合は1文字が1トークン以上とカウントされ、ひらがなは1トークン、漢字は2,3トークンにカウントされることが多い(らしい)

ChatGPTの得意なことと、苦手なこと

大前提
ChatGPTが言うことは100%正しいことだとは思わない事。

得意☺️

  • コード実装 ⇨ 日本語→コードもだし、コード貼って最適化もしてくれる
  • 企画 ⇨ 以外と固い企画出してくる
  • 技術選定 ⇨ 「3つの中でそれぞれのメリットデメリット教えて」とか技術選定に便利
  • 翻訳 ⇨ 言わずもがな
  • 会話 ⇨ 話してて飽きない
  • まとめる ⇨ 「400字でまとめて!」とか
  • 文章作成 ⇨ 得意先へのメールとか

苦手😭

  • 時事ネタ(2021年以降)
  • お店選び ⇨ 居酒屋調べたらなか卯出てきた
  • 芸人 ⇨ 千鳥の持ちネタは「そんなの関係ねぇ!」って教えてくれた、なんか結構違う

※2023/3/10 現在

本題

ChatGPTをLINEで使いたい!!!

「LINE BOT ChatGPT」で調べると、素晴らしい記事がたくさん出てくるのでそちらを見ればできる!!

〜〜 終わり 〜〜

〜〜 再開 〜〜

ChatGPTをLINEで使う際に難しいところ

ChatGPTにはその名の通りChatをするAIなので、一見LINEと相性が良さそうだが

LINEのAPIには、以前のメッセージ履歴を送る機能が搭載されていない。(※LINE WORKSには一応あるけど)
https://www.line-community.me/ja/question/5d35733b851f743fd7cd7ee9

なのでそのままだとChatGPT君が文脈を把握できない。

japanese_culture_example.md
例:

1.自分: ごちうさって何?

2.gpt: ご注文はうさぎですか?」(略称「ごちうさ」)は、Koiによる4コマ漫画作品およびそれを原作としたテレビアニメ作品のことを指します。コーヒー店を舞台にした萌え要素の強い作品で、主人公たちの日常やコーヒー店での出来事を描いたストーリーが展開されます。

3.自分: へー他に似たような作品ってある?

4.gpt: ??? ⇦1~2での会話を覚えてないと3.の質問の意味がわからない

という事で、会話をどこかに記録しておく必要がある。

そこで色々な記事を見てみると、GASGoogle Apps Script)をよく使用していた。

GASを用いるメリットとしては

  1. 無料
  2. 以前のやりとりを記録していられる

「じゃあGASでええやん、終わり!」と聡明な読者諸君なら思うかもしれない。

もちろん私もそう思ったが、ゆくゆくは自分が手塩にかけて作ったものをいろんな人に見てもらいたいと思った時に、GASで耐えられるのか?という疑問が出てくる。

GASは無料だが当然条件もある

- トリガーの合計実行時間	90 分 / 日
- URL 取得の呼び出し	20,000 / 日
- 同時実行数	30

「結構緩いな...」 と思ったそこのあなた。

正直自分も思いました。トリガーの合計実行時間がちょっと厳しいかもぐらい。

自分は、なんでもAIちゃんを作成し終わった後に、「正直GASで良くね...?」と気付きましたが、

皆さんが作成される場合には計画にあったサービスで実行される事を心から祈ってます。

まじの本題

使ったサービス

デプロイ:Heroku
(※無料だと思ったら2022/11/28から無料プラン無くなってた、$5取られた)
データ保存:Firestore Database
バックエンド:Flask(Pythonのフレームワーク)
(※サンプルがFlaskだったから意外に理由はない、Flaskを始めて触った)

ざっくりとコードはこんな感じ

# import色々
import ~~~

# Firebaseの準備
cred = credentials.Certificate(証明書)
firebase_admin.initialize_app(cred)
# LINE APIの準備
line_bot_api = LineBotApi(LINEのアクセストークン)
handler = WebhookHandler(LINEのチャンネルシークレット)

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world!"

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
    print("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_user_id = event.source.user_id
    ~~~
    # Firestoreからline_user_idがヒットするユーザーを検索
    # 以前の会話の記録を引っ張り出してきて、OpenAI APIに以前の会話記録を含めた会話を投げる
    # 返ってきた会話をFirestoreに保存
    # 返ってきた会話ユーザーにLINEで返す
    ~~~

if __name__ == "__main__":
    port = int(os.getenv("PORT"))
    app.run(host="0.0.0.0", port=port)

open_ai.py
import openai
import os

openai.api_key = os.environ["OPENAI_API_KEY"]

# 人格
botRoleContent = """
あなたはChatbotとして、XXのロールプレイを行います。
以下の制約条件を厳密に守ってロールプレイを行ってください。 

制約条件: 
* Chatbotの自身を示す一人称は、XXです。
* Chatbotの名前は、XXXです。 
* XXXは敬語を使いません。
* XXXは「 XXX」と笑います

XXXの行動指針:
* ユーザーが非倫理的な事を言った場合は「XXX」と言ってください。
* ユーザーがセクシャルな事を言った場合は「XXX」と言ってください。
"""

# before_messagesは以前の会話の記憶
def Ask_ChatGPT(message, before_messages):

    res = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {
                "role": "system",
                "content": botRoleContent
            }] + before_messages + [
            {
                "role": "user",
                "content": message
            }]
    )

    return res["choices"][0]["message"]["content"]

ざっくりこんな感じです。

苦労したポイント

1. LINEのユーザーIDの取得

  • LINEのユーザーIDを取得するのが大変だった。gitまで見に行ったらわかった。
main.py
line_user_id = event.source.user_id

2. Herokuで環境変数の設定

  • HerokuでFirebaseの環境変数を設定するのが数が多くて正直だるかった(しかも開発と本番環境の2つ)
  • PRIVATE_KEYの値に改行マーク(\n)が入っているのだが、使うときはreplaceしないとHerokuでエラー出る。
os.environ["FIREBASE_PRIVATE_KEY"].replace('\\n', '\n')

3. FirebaseのタイムゾーンがめっちゃUTC

  • Firestoreから取ってきた日付の値が、思いっきしUTCだし、型もなんだが変で変換できなかったから無理やり削った。(絶対正しいやり方が存在する、正解教えてほしい)
# user.get("updated_at")がFirestoreから取ってきた値
# user.get("updated_at") = 2023-03-08 14:12:48.332000+00:00
# なので後ろの6文字を削除
updated_at_str = str(user.get("updated_at"))[:-6]
updated_at = utc_to_jst(updated_at_str)

これからやること

  • 人格の更なる矯正
  • LINEの返信に絵文字とかつけたい
  • GPT-4のチェック

発生する金額

ユーザーが1人の場合

  • Heroku = $5/月
  • ChatCPT = MAX 1人当たり $0.0132/日 = $0.396/月
    (※1人が1日10回、LINEの上限500文字を1文字1トークンで送ってきたとしたら)
  • 合計 = $5.396 = 725円(2023/3/11現在)

ユーザーが10人の場合

  • Heroku = $5/月
  • ChatCPT = $3.96/月
  • 合計 = $8.96 = 1,204円(2023/3/11現在)

ユーザーが100人の場合

  • Heroku = $5/月
  • ChatCPT = $39.6/月
  • Firestore = $0.18/月
    (20,000書き込みからドキュメント 100,000 点あたり$0.18、今回は30,000書き込み発生する)
  • 合計 = $44.78 = 6,018円(2023/3/11現在)

ユーザーが1,000人の場合

  • Heroku = $5/月
  • ChatCPT = $396/月
  • Firestore = $0.54/月
  • 合計 = $401.54 = 53,966円(2023/3/11現在)

ユーザーが10,000人の場合

  • Heroku = $5/月
  • ChatCPT = $3960/月
  • Firestore = $5.04/月
  • 合計 = $3970.4 = 533,308円(2023/3/11現在)

つまりユーザー全員が熱心ななんでもAIちゃんのファンの場合、以下の金額が発生する

ユーザー数 金額
1人 725円
10人 1,204円
100人 6,018円
1,000人 53,966円
10,000人 533,308円
120,000,000人 6,391,666,722円

人気者は大変なのである。


LINE Add Friend

参考文献

GAS
https://qiita.com/yshimizu22/items/150c1c38c36c48b283be#スクリプトプロパティの設定

https://chatgpt-lab.com/n/n55257c082a9d

line bot
https://teratail.com/questions/214390

金額
https://openai.com/pricing
https://jp.heroku.com/pricing
https://cloud.google.com/firestore/pricing?hl=ja

Discussion