nikkie-ftnextの日記

イベントレポートや読書メモを発信

非公式のChatGPT APIのラッパーライブラリrevChatGPTを触る

はじめに

こころはやってんの、ChatGPT?1 nikkieです。

先日も取り上げましたが、ChatGPT、すごいですよね!
アプリケーションにマッシュアップしている例も見かけるようになり、プログラムからどうやってChatGPTのAPIを叩くかに興味を持ちました。
この記事ではPython製の非公式ライブラリrevChatGPTを試します。

※この記事は2023/02/25時点の情報です。
OpenAI次第なので、今後使えなくなる可能性は十分にあります。

目次

revChatGPT

PyPIに公開されており、pipでインストールできます!

Reverse Engineered ChatGPT API by OpenAI.

OpenAIによるChatGPTのAPIリバースエンジニアリングしたそうです。

ソースコードはこちら(18K star!!

動作環境

完全に再現させるための情報です:

% pip freeze
certifi==2022.12.7
charset-normalizer==3.0.1
idna==3.4
OpenAIAuth==0.3.2
requests==2.28.2
revChatGPT==2.3.8
urllib3==1.26.14

コマンドラインで動かす

READMEのConfigurationを実施する

https://github.com/acheong08/ChatGPT#configuration

(1) Open AIのアカウントがない場合は作りましょう。
私は既に作っていたので次の手順からやりました。

(2) Authentication method(認証方法)を1つ選びます。
私は「Access token」を選びました。
ChatGPTのWeb UIにログインした状態で https://chat.openai.com/api/auth/session を開くと確認できます。
キーaccessTokenの値を使って、config.jsonを作ります。

{
    "access_token": "https://chat.openai.com/api/auth/session で確認できるaccessTokenの値"
}

(3) (2)で作ったJSON$HOME/.config/revChatGPT/config.jsonに配置します。
私は今回、シンボリックリンクにしました3

% mkdir -p ~/.config/revChatGPT
% ln -s $PWD/config.json ~/.config/revChatGPT/config.json

以上でConfiguration完了です!

python -m revChatGPT.V1

https://github.com/acheong08/ChatGPT#command-line

コマンドラインpython -m revChatGPT.V1を実行すると、Web UIではなく、コマンドラインでChatGPTとお話しできます!!

Web UI同様、ChatGPTの応答が少しずつ表示されるんです!

このパッケージのUI(CUI)のポイントは以下です。

  • (ChatGPTのWeb UI同様)改行込みの入力をサポート
    • つまり、ChatGPTにテキストを送るにはEnterキーを2回連続で入力する必要がある(Press enter twice to submit your question.
    • Enterキー1回はテキストの改行になりChatGPTに送信されない
    • ChatGPTに送信されるとコマンドラインには「Chatbot:」と表示される
  • !で始まるいくつかのコマンドをサポート
    • これらのコマンドもEnterキー連続2回で実行される

スクリプトで動かす

https://github.com/acheong08/ChatGPT#developer-api

Basic example (streamed)を試す

import json

from revChatGPT.V1 import Chatbot

with open("config.json", encoding="utf8") as f:
    config = json.load(f)

chatbot = Chatbot(config=config)

while True:
    sentence = input("You (qで終了): ")
    stripped = sentence.strip()
    if not stripped:
        continue
    if stripped.lower() == "q":
        break

    print()
    print("Chatbot: ")
    prev_text = ""
    for data in chatbot.ask(stripped):
        message = data["message"][len(prev_text):]
        print(message, end="", flush=True)
        prev_text = data["message"]
    print()

これはpython -m revChatGPT.V1の実装4と同様です。
応答が少しずつ表示されるのでstreamedだと理解しました。

Basic example (single result)

こちらは1回にまとめて応答を出力する実装です。
差分だけ示します。

while True:
    # sentenceの取得処理は共通

    print()
    print("Chatbot: ")
    prev_text = ""
    for data in chatbot.ask(stripped):
-        message = data["message"][len(prev_text):]
-        print(message, end="", flush=True)
-        prev_text = data["message"]
+        response = data["message"]
+    print(response)  # ChatGPTからの応答が全部responseにまとまっている
    print()

少しずつ応答が表示される場合5と違って、処理が動いているのかやや不安になります。

宿題事項

コマンドラインで何回かお話ししてからWeb UIを見ると、たくさんNew chatができていました。

お片付けしなきゃ!

revChatGPT自体はconversation_idの指定をサポートしています。
conversation_idを指定して、続きから話せるようにする(結果的にNew chatばかりにならない)が、次回まず取り組みたいことです。

また、ソースコードにはdebugレベルのログ出力があります。
ログレベルをdebugにして実行することでrevChatGPTの動きをより正確に理解できそうです。

ソースコードにはマジックナンバーの定数がいくつかあるので、Discussionsも見るとよさそうに思いました。

終わりに

ChatGPTにプログラムからアクセスしたく、revChatGPTを触りました。
このライブラリ、簡単な設定で使えてすごいですね(あくまで2023/02/25時点の情報です。OpenAI次第なので明日は分かりません)。

このライブラリが使えている間は、ChatGPTを使ったアプリケーションがすごく開発しやすそうですね。
取り組んでいるシオン・プロジェクトマッシュアップできるという電波を受信したんですよ!

ChatGPTから始まりLLMが乱立、revChatGPT以外にもよさそうなライブラリはあると思うので、引き続き情報収集していきます。
よさそうなライブラリご存知の方、アウトプットしていただけるとみんな嬉しいんじゃないかと思います〜


  1. どうやら私は『かがみの孤城』のこころちゃんにChatGPTを使わせたいみたいです(←いや、なんでだ)。初出はこちら:動画や資料でChatGPTのヤバさを遅ればせながら認識!ワクワクもんだぁ! - nikkie-ftnextの日記
  2. 触ってから執筆している間に2.3.10になっていました https://github.com/acheong08/ChatGPT/releases/tag/2.3.10
  3. 設定を試行錯誤する必要があった時もエディタで開くのはワーキングディレクトリ1箇所だけにしたいという都合と、後述のスクリプトでの読み込みで同じディレクトリにあった方が書きやすいかなと考えました。今回はお試し優先で、アプリケーションを作るときにはシンボリックリンクでなくmvして配置するかなと思います
  4. https://github.com/acheong08/ChatGPT/blob/2.3.8/src/revChatGPT/V1.py#L526-L540
  5. askメソッドの実装を覗いたところrequestsでSessionを貼りstream=Trueを指定。ChatGPTのAPIからレスポンスを生データの行ごとにyieldしていました。これによりstreamedは少しずつ出力されます。ref:https://github.com/acheong08/ChatGPT/blob/2.3.8/src/revChatGPT/V1.py#L241-L290 single resultのスクリプトの実装は、for文でジェネレータ(すなわちAPI)が全部返し切るのを待っていますね