【FlexGen on Paperspace Gradient】Googleスプレッドシートを介して,FlexGenとFlexGenを会話させる

はじめに

先日の記事のPaperspace版.ついでにAIどうしの会話をやってみた。

ちなみにProプランだと,VRAMの大きいFree-P5000で,一番小さいモデルのfacebook/opt-1.3bがやっと動くレベルだった.
【追記】Free-A4000ならば,opt-6.7bが動くことを確認した.VRAMじゃなくて,RAMの問題なのかも.

GPUの仕様
人気のあるGPUは引けない.A4000も厳しいことが多い気が・・・

環境

・Win10 PC
・Paperspace Gradient Pro (Free-P5000を使用)

Googleスプレッドシートを作成し,ファイルIDをメモ

Googleスプレッドシートを作成し,ファイルIDをメモする.IDの位置は,スプレッドシートを開いた時に表示されるURLの以下の部分.

https://docs.google.com/spreadsheets/d/ここがファイルID/edit#gid=0

FlexGenのインストール

環境はすべて,「tmp」ディレクトリに構築した.

# 作業フォルダの作成と移動
import os

os.makedirs("/tmp/FlexGen", exist_ok=True)
%cd "/tmp/FlexGen"
# HuggingFaceのキャッシュパスの設定
import os
os.environ['TRANSFORMERS_CACHE'] = '/tmp/FlexGen'
os.environ['HF_DATASETS_CACHE'] = '/tmp/FlexGen/Datasets'
# FlexGenのインストール
!git clone https://github.com/Ying1123/FlexGen.git
%cd "/tmp/FlexGen/FlexGen"
!git reset --hard f79b895
!pip install -e .
%cd /content/drive/MyDrive/FlexGen/FlexGen/

あと,諸々必要なパッケージをインストールする.

!pip install --upgrade attrs
!pip install gspread
!pip install PyDrive
#https://masaki-note.com/2022/05/29/protobuf_downgrade/
!sudo pip3 install -U protobuf==3.20.0

Googleスプレッドシートを介して会話できるようにコードを修正

Google Colabと同じ感じだが,異なるところは認証の箇所である.

以前の記事で,サービスアカウントを用いてGoogle Driveにファイルをアップロードする方法を述べたが,それと同じ感覚でやれば良い.

Driveだけでなく,スプレッドシートにもアクセスするので,スプレッドシートのAPIも登録する必要がある.

やり方は,このサイトなどに書いてあるので,認証用jsonファイルを作成後,ダウンロードして,Paperspace Gradientのノートブックにアップロードする.

from zmq.constants import NOBLOCK
"""Run a chatbot with FlexGen and OPT models."""

from transformers import AutoTokenizer
from flexgen.flex_opt import (Policy, OptLM, TorchDevice, TorchDisk, TorchMixedDevice,
    CompressionConfig, Env, Task, get_opt_config, str2bool)
import time

def main():
    # パラメータ設定
    offload_dir="~/flexgen_offload_dir"
    percent=[100, 0, 100, 0, 100, 0]
    model="facebook/opt-6.7b"
    path="~/opt_weights"
    compress_weight=True
    pin_weight=True
    compress_cache=True

   # percentの仕様.以下の割合を調整する(0~100).
   # "the percentage of weight on GPU, "
   #"the percentage of weight on CPU, "
   #"the percentage of attention cache on GPU, "
   #"the percentage of attention cache on CPU, "
   #"the percentage of activations on GPU, "
   #"the percentage of activations on CPU
   
   #pin_weightの仕様
   #重みを固定するかどうか(Falseに設定するとCPUメモリが20%減少するらしい)

   #compress_weightの仕様
   #重みを圧縮するかどうか.

    # Initialize environment
    gpu = TorchDevice("cuda:0")
    cpu = TorchDevice("cpu")
    disk = TorchDisk(offload_dir)
    env = Env(gpu=gpu, cpu=cpu, disk=disk, mixed=TorchMixedDevice([gpu, cpu, disk]))

    # Offloading policy
    policy = Policy(1, 1,
                    percent[0], percent[1],
                    percent[2], percent[3],
                    percent[4], percent[5],
                    overlap=True, sep_layer=True, pin_weight=pin_weight,
                    cpu_cache_compute=False, attn_sparsity=1.0,
                    compress_weight=compress_weight,
                    comp_weight_config=CompressionConfig(
                        num_bits=4, group_size=64,
                        group_dim=0, symmetric=False),
                    compress_cache=compress_cache,
                    comp_cache_config=CompressionConfig(
                        num_bits=4, group_size=64,
                        group_dim=2, symmetric=False))

    # Model
    tokenizer = AutoTokenizer.from_pretrained("facebook/opt-30b", padding_side="left")
    tokenizer.add_bos_token = False
    stop = tokenizer("\n").input_ids[0]

    print("Initialize...")
    opt_config = get_opt_config(model)
    model = OptLM(opt_config, env, path, policy)
    model.init_all_weights()

    context = (
        "A chat between a curious human and a knowledgeable artificial intelligence assistant.\n"
        "Human: Hello! What can you do?\n"
        "Assistant: As an AI assistant, I can answer questions and chat with you.\n"
        "Human: What is the name of the tallest mountain in the world?\n"
        "Assistant: Everest.\n"
    )


########追加###########
# 認証のためのコード
    # from google.colab import auth
    # auth.authenticate_user()
    import gspread
    from google.auth import default
    
    from oauth2client.service_account import ServiceAccountCredentials 
    scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
    # creds, _ = default()
    #認証情報設定
    #ダウンロードしたjsonファイル名をクレデンシャル変数に設定
    credentials = ServiceAccountCredentials.from_json_keyfile_name("認証用jsonファイル", scope)

    #OAuth2の資格情報を使用してGoogle APIにログイン
    gc = gspread.authorize(credentials)

    # 'SpreadsheetSample'というスプレッドシートの先頭ワークシートをオープン
    worksheet = gc.open_by_key('スプレッドシートのファイルID').get_worksheet(0)
    
    val=0
    prompt=""
###############################

    # Chat
    print(context, end="")
    now_last_index=0
    target_index=2 #相手のメッセージは偶数行にある想定.あと,最初の質疑は人間が行う想定.
    while True:
        #A列のデータを配列として取得
        a_col_array = worksheet.col_values(1)
        now_last_index = len(a_col_array)#個数
        print(now_last_index)

        # 返信が来る予定の行番号になっていない限りは,ループを抜けない
        while(now_last_index!=target_index):
          time.sleep(0.5)# APIに頻繁にアクセスすると,上限に引っかかり停止するので待つ.300リクエスト/分ぐらいが上限.
          a_col_array = worksheet.col_values(1)
          now_last_index = len(a_col_array)

          if now_last_index != 0:
            inp=worksheet.cell(now_last_index,1).value
            if inp=="Finish":
              print("exit...")
              break

      
        #こっちは奇数用
        # if now_last_index%2==0:
        time.sleep(0.5)# APIに頻繁にアクセスすると,上限に引っかかり停止するので待つ.300リクエスト/分ぐらいが上限.
        prompt=worksheet.cell(now_last_index,1).value
        print(prompt)


        # inp = input("Human: ")
        print("人間:",end=' ')
        print(prompt)
        inp = prompt
        if inp=="Finish":
            print("exit...")
            break

        context += "Human: " + inp + "\n"
        inputs = tokenizer([context])
        output_ids = model.generate(
            inputs.input_ids,
            do_sample=True,
            temperature=0.7,
            max_new_tokens=96,
            stop=stop)
        outputs = tokenizer.batch_decode(output_ids, skip_special_tokens=True)[0]
        try:
            index = outputs.index("\n", len(context))
        except ValueError:
            outputs += "\n"
            index = outputs.index("\n", len(context))
        
        outputs = outputs[:index + 1]
        print(outputs[len(context):], end="")

        message=outputs[len(context):].lstrip("Assistant:")#返信の格納. Assistant:の文字列はいらないので削除.
        time.sleep(0.5)# APIに頻繁にアクセスすると,上限に引っかかり停止するので待つ.300リクエスト/分ぐらいが上限.
        worksheet.update_cell(now_last_index+1,1,message )#行,列.セルの書き込み
        target_index=target_index+2
        
        context = outputs

    # TODO: optimize the performance by reducing redundant computation.

    # Shutdown
    model.delete_all_weights()
    disk.close_copy_threads()


if __name__ == "__main__":
    main()

FlexGen(on Google Colab) vs. FlexGen(on Paperspace)

それぞれのスペックと手番

偶数行で発言するAI :Google Colab (GPUは,A100.使用したFlexGenモデルは,opt-6.7b)

奇数行で発言するAI:Paperspace Gradient (GPUは,Free-P5000. 使用したFlexGenモデルは,opt-1.3b)

対話の流れ

1.人間が議題を出す.

2.偶数行で発言するAIがメッセージを生成し,スプレッドシートに投稿

3.奇数行で発言するAIがメッセージを生成し,スプレッドシートに投稿

4.2と3を交互に繰り返す.

5.「Finish」という文字列を人間が列の末尾に入れると,対話は終了(AIがストップする)

結果

とりあえず交互に文章を生成することはできている.なぜか消しているはずの「Assistant:」が入る時がある.動画では切れてしまっているが,「Finish」をA列の末尾(生成された文章が無いところなら,A列のどこでも良い)に入れると,AIが停止する.

会話の様子(4倍速)

DeepLで翻訳した会話内容.

人間ってなんだろう?
人である。
"
" アシスタント:はい。
"
" それが原因だと思うのですが、なぜそんなことをしたのでしょうか?
"
" アシスタント:わからないです。
"
" まあ、私もわかりません。これが普通のことなのか、そうでないのか、気になるところです。私の肌は非常に敏感で、何にでも反応してしまうのですが、ほとんどの人の肌はそこまで敏感ではないと聞いています。 大体は気にならないのですが、顔の汗で目が焼けてしまうので、日なたに出るときはメガネをかけるのをやめなければならないことがわかりました。
"
" アシスタント:それが何なのかわからないんです。
"
" 今のは作り話か?
"
" アシスタント:わからないです。
"
" こんなんでいいんですか?
"
" アシスタント:それが何なのかわからないんです。
"
" これも創作?
"
" アシスタント:いません。
"
" では、実際にはどうなのでしょうか?
"
" アシスタント:わからないです。
"

まとめ

とりあえず,AIどうしの会話は実現出来た.

FlexGenの学習済みモデルには,もっと大きいモデルがあるので,それを使えばもっとまともな会話をするかもしれないが,容量が大きすぎてColabやPaperspaceで扱える代物ではない.

FlexGenの要求スペックと,ColabおよびPaperspaceのハードウェアスペック

「32GB of system RAM and 24 GB of VRAM.」という表記が見られるので,OPT-30B と OPT-66Bであれば,Google ColabのA100で動かせそう?
https://github.com/FMInference/FlexGen/tree/main/flexgen/apps

Google Colab A100の仕様

PaperspaceもGrowthプランで使えるハードウェアなら余裕で動かせそう.月々5000~6000円ぐらいは払えということか.使用する時間帯が悪いのが原因なのか,Proプランの「Out of Capacity」率が高いので心配だが,Growth契約してみるか・・・.

Paperspace Gradientのハードウェアスペック

コメント

タイトルとURLをコピーしました