🧠

GASとChatGPTを組み合わせてZennとQiitaの急上昇記事を紹介するTwitter botを作った

2023/05/06に公開
1

はじめに

idea カテゴリで投稿するか迷いましたが、一応 ChatGPT へリクエストを投げる GAS のコードも紹介しているので、tech 記事で投稿することにしました。

ほしかったもの

Qiita には急上昇記事を紹介する公式アカウントが存在しています。

https://twitter.com/qiitapoi

が、Zenn には公式のそれが存在していませんでした。

一応公式アカウントがピックアップとして紹介しているものの、おそらく手動。(そう思うのは、GW 前から更新が止まっているから)

https://twitter.com/zenn_dev/status/1651043972050198528

とにかく一番欲しかったものは、Zenn の人気記事を数時間間隔で教えてくれるなにかでした。 そしてどうせなら Qiita の記事も紹介する機能をつけようと思いました。

"なにか"には Slack や LINE bot という選択肢があったのですが、しかし単に記事だけを紹介しつづける無機質な bot は可愛くないと思っていました。

せっかく"私"が作るのなら、よりかわいく・おもしろく・キャラがついたオタクらしいものを作りたいと考えていました

最終的に bot の選択肢から Twitter を選択したのですが、その理由はやはり急上昇記事を通していろんな人が交流したり、記事を書いた本人に反響が還元されればよいと考えたからです。

以上から、ほしかったものの要件を一覧にします。

  • bot は Twitter で動かす
  • Zenn のトレンド急上昇記事を紹介する
  • Qiita のトレンド急上昇記事を紹介する
  • かわいくておもしろく、キャラ付けされている

そして以上を満たしているものをつくりました。

つくったもの

https://twitter.com/ely_spencer

です!!フォローして活用してくれると嬉しいです!!

アカウント名は仮にエリーと名付けました。金髪ツインテール繋がりということで冴えカノのメインヒロインである澤村・S・英梨々からパ…もじっています。[1]

冴えカノのメインヒロイン、澤村・S・英梨々

bot の簡単な仕様としては、Zenn と Qiita のそれぞれで、2 時間おきに人気記事を 1 記事ずつ紹介してくれます。

bot の簡単な仕様としては、Zenn は 3 時間おきに、Qiita は 2 時間おきに人気記事を 1 記事ずつ紹介してくれます。

当初は Zenn も 2 時間で回していたのですが、Zenn の場合トレンドの上位に入る方はトレンドに入ってからさらにいいねを稼いでトレンドに残り続ける傾向があります。

そのため、意外と Zenn のトレンドは回転していないため、3 時間で回すことにしました。

また、かわいくておもしろくキャラ付けするために、ChatGPT を使ってクール系女性ソフトウェアエンジニアっぽい呟きを 8 時間おきにしてくれます。

Zenn

https://twitter.com/ely_spencer/status/1654566510751358977

Qiita

https://twitter.com/ely_spencer/status/1654589864740790272

女性風ソフトウェアエンジニアっぽい呟き

なかなか香ばしくていい感じ。右手に過去の遺失物とか封印されてそう w

https://twitter.com/ely_spencer/status/1654385256584327168

技術スタック

今回は GAS を採用しました。理由は 3 つあります。

  1. 無料で使えてメンテナンスが極小だから
  2. ChatGPT API という有料サービスへの API キーが漏洩する可能性が基本的に0で、不正に API が叩かれる可能性も基本的に0
  3. 定期実行できるアーキテクチャが必要

1 については、技術構成にこだわって CloudRun とか Cloud Functions を使っても構わんといえばそうなんですが、なんせ DB にお金がかかる。

(DB が必要なのは、すでにツイート済みの記事情報を保持しておくため)

じゃあ Firestore は?といえばそうなんですが、結局アプリケーションをホスティングするためのインフラにお金がかかります。

「いやいや、Firebase hosting とか使ってフロントから実行すれば…」

とおっしゃられるかもしれませんが、それだと定期実行の仕組みが利用できません。

また公開された場所へホスティングするのは、2 の観点からも嫌っていました。認証入れればできなくはないですが、そこまで労力をかけるつもりはありませんでした。

そしてもう一つネックだったのが、定期実行です。Cloud Scheduler を使えば Cloud Functions × FireStore or Cloud SQL などで実現はできますが、Cloud Scheduler 自体の費用が意外と馬鹿にならないので選択肢からは除外しました。

GAS で ChatGPT を使う Tips

GAS から ChatGPT へリクエストを投げるコードはこんな感じです。

やってることは単に POST を投げているだけなので、実装自体はめちゃくちゃ楽ちんでした。

/**
 * ChatGPTへのリクエスト処理
 * @param systemPrompt プロンプトの内容
 * @returns ChatGPTの解答
 */
const chatGPTRequest = (systemPrompt) => {
    const apiKey = getChatGPTAPIKey();
    if (apiKey == null) {
        return "";
    }
    const apiUrl = "https://api.openai.com/v1/chat/completions";
    const messages = [{ role: "system", content: systemPrompt }];

    const requestBody = {
        model: "gpt-3.5-turbo",
        temperature: 0.7,
        max_tokens: 2048,
        messages: messages,
    };

    const request = {
        method: "POST",
        muteHttpExceptions: true,
        headers: {
            "Content-Type": "application/json",
            Authorization: "Bearer " + apiKey,
        },
        payload: JSON.stringify(requestBody),
    };

    try {
        const response = JSON.parse(
            UrlFetchApp.fetch(apiUrl, request).getContentText()
        );
        if (response.choices) {
            const choise = response.choices[0];
            return choise.message.content;
        } else {
            Logger.log(response);
            return "";
        }
    } catch (e) {
        Logger.log(e);
        return "";
    }
};

ポイントとしては、サンプルで見ていた記事などでは API キーをハードコードしていたり、もしくはスプレッドシート内部に保存していたりするのですが、見ていて「恐ろしい…」となっていました。

そういう機密情報はスクリプトプロパティに保存しましょう。プロジェクト設定 > スクリプト プロパティから保存できます。

保存したスクリプトプロパティはこんな感じで取得できます。

/**
 * ChatGPTのAPIキーを環境変数から取得する
 * @returns APIキー
 */
const getChatGPTAPIKey = () => {
    const val = PropertiesService.getScriptProperties().getProperty("API_KEY");
    return val;
};

ChatGPT の料金

今回使ったのはgpt-3.5-turboなのですがはっきり言って格安です。

テストも含めると、5/5 は 10 回程度 API を投げましたが利用料は$0.00135 と実質無料のような状態です。

エリー自身は毎日 3 回は呟くので、$0.000135 × 3 より一日あたりの料金は $0.000405です。

1 年換算すると$0.000405 × 365 = $0.147825 です。

ただし API 利用を始めた時にクレジットを$5 分くれるので、このサービスで利用するだけなら 35 年くらいは無料で使えそうです。

仮に課金されたとしても一年で$0.147825 程度であれば、ほぼノーダメです。

GAS で Twitter API からツイート投稿する方法

これらの記事が非常に有益でした。

https://prtn-life.com/blog/gas-twitter-api

https://qiita.com/yuzinet/items/ae4b9ca2b5cd989de435

ただしサンプルのソースは var を多用していて自分好みではなかったので、コード自体はそのあたりを踏まえつつ微妙に修正して利用しています。

気をつけたポイント:記事紹介ツイートの投稿間隔

無料プランを利用しているので、1ヶ月あたりの API からの投稿数は 1500 件に制限されています。

なので日割りで計算すると 1 日 50 ツイートが上限でした。

すると、毎時 Zenn と Qiita の記事を紹介してしまうと 48 ツイートになりますがそれだとギリギリです。

一方で Zenn や Qiita のトレンドの内容はそうそう頻繁に更新されているものでもないため、毎時の頻度で投稿する意義は薄そうです。

一応仕様的には、既に紹介済みの記事しか取得できなかった場合にはエリー(作った Twitter bot)自身が呟いてくれます。

ただそうすると ほぼ無料に近いとはいえ ChatGPT に課金されてしまうため、あまり好ましい状況ではありません。

なので一旦 2 時間おきにしておいて、うまくトレンド記事が回っていってくれるかを様子見しています。

今後の課題

他に技術記事を投稿できる媒体があるのであれば、追加していきたいです。

あと ChatGPT の機能をもう少し活用できないか思案中。

例えば記事タイトルに「reviewdog」というキーワードがあったとすれば、「reviewdog」について簡単に補足する Tweet をしてくれる、みたいなものなんかを考えています。

ただし、先にも挙げた Twitter API の制限が厳しいのでそのあたりの呟きをどこまでいれられるかは要検討かなと思っています。

おわりに

https://twitter.com/ely_spencer

ぜひフォローして活用してください!!

ツイート通知を設定しておくと、うまく機能してくれるんじゃないかと思います。

ちなみに Zenn の人気記事を紹介するアカウントは私が調べた限り存在していなかったので、おそらく私の作ったものが史上初なのでは?と勝手に思っています。

メンバー募集中!

サーバーサイド Kotlin コミュニティを作りました!

Kotlin ユーザーはぜひご参加ください!!

https://serverside-kt.connpass.com/

また関西在住のソフトウェア開発者を中心に、関西エンジニアコミュニティを一緒に盛り上げてくださる方を募集しています。

よろしければ Conpass からメンバー登録よろしくお願いいたします。

https://blessingsoftware.connpass.com/

脚注
  1. ということで CV は勝手に大西沙織さんということにさせていただいてます。なのでみなさんも脳内再生時は大西さんの声でお願いします。 ↩︎

Discussion

prtn-blogprtn-blog

はじめまして、prtn-blogと申します。
ブログ紹介いただき、ありがとうございます!

APIキーのハードコーディング、仰るとおり危険ですよね・・;
ブログ書くとき毎回迷うんですが、自分のブログは初心者の方向けの内容が多いので
ハードコーディングで書いてしまっています。

ブログ記事参考になりました!
Zennの人気記事ツイートいいですね。