« 2023年10月 | トップページ | 2023年12月 »

2023年11月30日 (木)

例の人検出器をRaspberry Pi 4で動かしてみた

前回の記事(人の検出に特化したPINTOさんの物体検出がなかなかすごいので動かしてみた: EeePCの軌跡)で紹介した検出器がCPUでも軽々と動くので、もしかしたらRaspberry Pi 4でもわりかし快適に動いてくれるんじゃないか?と思ったので、早速試してみました。

まずはRaspberry Pi 4ですが、既存のものを使います。
ですが、入っていたPythonが3.7と古かったので、これを以下の記事を参考に、3.10に上げておきました。

RaspberryPi4BにPython3.10をインストールした #Python3 - Qiita

続いて、

pip3 install numpy opencv-python opencv-contrib-python onnxruntime

とコマンドを打ち込んで、必要なライブラリを一気に入れます。

その状態で、前回記事のコード(demo_goldyolo_onnx.py)やモデル(gold_yolo_n_body_head_hand_post_0461_0.4428_1x3x480x640.onnx)などはそのままRaspberry Piに持ってきました。

で、以下のコマンド、

python demo_goldyolo_onnx.py

を入れて実行。

Img_4336_20231130210701

そうそう、Raspberry Pi 4は例のモバイルモニターにつなぎました。
で、実行するとこれがめちゃくちゃ遅い。推論速度は表示上、1枚当たりだいたい13000ms、つまり13秒です。

見事なくらいカクカクで、確かに10秒以上遅れて表示されます。
いくらRaspberry Piだからといって、ちょっと遅すぎじゃね?
と思ったので、コードを少し見直しました。

まず、303~309行目、

          cv2.rectangle(
                debug_image,
                (box[0], box[1]),
                (box[2], box[3]),
                (255,255,255),
                2,
            )

この部分を、すべてコメントアウトします。

さらに、349行目、

        video_writer.write(debug_image)

もコメントアウト。

これで”output.mp4”が出力されなくなりますが、どのみち遅すぎてどうしようもない動画しか出てこないため、切った方がマシです。

(12/3 追記)

もう一か所、変えてました。235行目で、モデルを低解像度のものに変えてます。

        default='gold_yolo_n_body_head_hand_post_0461_0.4428_1x3x192x320.onnx',
        #default='gold_yolo_n_body_head_hand_post_0461_0.4428_1x3x480x640.onnx',

もちろん、同じフォルダに「gold_yolo_n_body_head_hand_post_0461_0.4428_1x3x192x320.onnx」を入れるのを忘れないよう。

たったこれだけの工夫で、13000 → 260msと大幅に速くなりました。えっ、こんなに変わるものなの?

Img_4340

ご覧の通り、Raspberry Pi 4でもまあまあの速度で推論されます。これなら、人が立ち入ったかどうか程度の用途ならば使えそうです。
欲を言えば、倍速くなったと言われるRaspberry Pi 5で試してみたいですよね。出たら、すぐに買います。

てことで、Raspberry Pi 4でも用途を限れば使えそうな感じです。

(追記 12/3)

会社のRaspberry Pi 3B+でも試してみました。ほとんど推論速度は変わりませんでした。ということは、CPU以外のところで律速されてる?可能性ありです。


ラズベリーパイ 4 コンピューターモデルB 8GB Raspberry Pi 4 ラズパイ 4 TELEC認定取得済み (Raspberry Pi 4 8GB)

2023年11月29日 (水)

人の検出に特化したPINTOさんの物体検出がなかなかすごいので動かしてみた

語彙力がなさ過ぎて申し訳ございませんが、この人検出は凄まじいです。ほんと。

きっかけは、以下のXのポスト。

Super PINTOさんのポストです。ここに出てくる画像は検出結果ではなく、手動のアノテーション作業中のものですが、これを使って作られた学習器もこれに匹敵するくらいのすげえ検出をしてくれます。

あんまりにもすげえんで、つい家で試してみたくなりました。
ということで、まずは以下からコードをゲットして、使うところまでもっていきました。

PINTO_model_zoo/425_Gold-YOLO-Body-Head-Hand at main · PINTO0309/PINTO_model_zoo · GitHub

まず、使うライブラリとしては、

・ Python 3.10
・ onnxruntime 1.16.1
・ opencv-contrib-python 4.8.0.76
・ numpy 1.24.3

です。TensorRTは、とりあえず推論だけなら使わない模様です。
うちではWindows版のPythonで使ってます。入手方法は以下を参照。

Python 3.10 の導入 on Windows #Python - Qiita

で、Python for Windowsをインストール後に、コマンドプロンプトかWindows PowerShellを開き、

pip install onnxruntime opencv-python opencv-contrib-python numpy

のコマンドを実行すれば、必要なライブラリは入るものと思われます。
(CUDAを導入済みのPCなら、onnxruntime_gpuも加えます)

さて、まずは上のGithubからコードをダウンロードします。「demo」フォルダをクリックして、その中にある「demo_goldyolo_onnx.py」「demo_goldyolo_onnx_image.py」を開いて、右上からダウンロードのボタンをクリックして落とします。

それ以外にも、以下のリンクをクリックして、

https://s3.ap-northeast-2.wasabisys.com/pinto-model-zoo/425_Gold-YOLO-Body-Head-Hand/resources_n.tar.gz

そこから「resources_n.tar.gz」というファイルをダウンロードします。

Windowsの場合、このファイルを「7-Zip」を使って開き、中にあるファイルを展開します。

圧縮・解凍ソフト 7-Zip

70個以上の大量のファイルが得られますが、要るのは一つで、この中から「gold_yolo_n_body_head_hand_post_0461_0.4428_1x3x480x640.onnx」のみを取り出します。

これで準備OK・・・かと思いきや、実はコードにバグがあって、そのままでは使えません。
ちょっとややこしいのですが、VSCode辺りを開き、「demo_goldyolo_onnx.py」の203行目付近、

            if len(boxes_keep) > 0:
                for box, score in zip(boxes_keep, scores_keep):
                    x_min = int(max(box[2], 0) * image_width / self.input_shapes[0][3])
                    y_min = int(max(box[3], 0) * image_height / self.input_shapes[0][2])
                    x_max = int(min(box[4], self.input_shapes[0][3]) * image_width / self.input_shapes[0][3])
                    y_max = int(min(box[5], self.input_shapes[0][2]) * image_height / self.input_shapes[0][2])

                   
result_boxes.append(
                        [
x_min, y_min, x_max, y_max]
                    )
                    result_scores.append(
                        score
                    )

こういう部分があるので、以下のように変えます。

            if len(boxes_keep) > 0:
                for box, score in zip(boxes_keep, scores_keep):
                    x_min = int(max(box[2], 0) * image_width / self.input_shapes[0][3])
                    y_min = int(max(box[3], 0) * image_height / self.input_shapes[0][2])
                    x_max = int(min(box[4], self.input_shapes[0][3]) * image_width / self.input_shapes[0][3])
                    y_max = int(min(box[5], self.input_shapes[0][2]) * image_height / self.input_shapes[0][2])
                    pid = int(box[1])

                    result_boxes.append(
                        [x_min, y_min, x_max, y_max, pid]
                    )
                    result_scores.append(
                        score
                    )

一見すると何が違うんだ・・・という感じですが、よく見ると「pid」という変数を定義し、それを「result_boxes」という配列の最後に加えてます。
ちなみに、このpidというのは何かというと、推論結果のラベルを現すIDであり、「身体」が0、「顔」が1、「手」が2であることを現してるみたいです。
こうしておかないと、さらに下の方にある295行めの「classid: int = box[4]」がエラーを起こします。
(boxの変数で[4]なんてねえぞゴルァ!的なエラーが出ます)

なんか、バグったままのコードが上げられてたようですね。

ちなみに、「demo_goldyolo_onnx_image.py 」にも同じような部分があるので、直しておきます。

さて、これで準備完了。
いよいよ、コードを動かします。

コマンドプロンプトで、

cd (コードの入ったフォルダのパス)

と入力して移動した後、

python demo_goldyolo_onnx.py

と実行すると、PCに内蔵されたWebカメラで物体検出が始まります。

 

20231129-150724

はい、御覧の通り、手と顔と身体を認識してくれます。
1コマ当たりの推論時間は20~30ms。ほぼリアルタイムですね。

とまあ、我が家のしょぼいGPUでも、結構な速さで動きます。
ちなみに、一人二人程度なら、CPUのみでも動きます。
(会社で実験しました)

これを、カメラではなく動画から動かす場合は、

python demo_goldyolo_onnx.py -v (動画ファイル.mp4)

という具合に「-v」の後にファイル名を指定してやります。

ちなみに、子供の運動会の動画を使ってみたんですが、

Goldyolo01

さすがにこの人数ではリアルタイムとはいきませんでしたが、それでも結構な速さで人体、顔、手を推論してくれます。
物体追跡のアルゴリズムと組み合わせたら、参加人数を一気にカウントできそうですね。

なお、この時同時に「output.mp4」という、検出結果を納めた動画が出力されます。

ちなみに、もう一つのコード「」の動かし方ですが、まず「00_COCO-Hand-S_base」と「output」という名前のフォルダを作り、この中にJPG画像を入れます。その後に、

python demo_goldyolo_onnx_image.py

と実行すると、「00_COCO-Hand-S_base」の中にある画像の物体検出結果を「output」に入れてくれます。
(上のような感じで、人物を囲んだボックス入りの画像が入ってます)

人物の検出特化な検出器なので、人以外の用途には使えないのが難点ですが、逆に言えば人を感知する点にかけてはおそらく最強の検出器ではないかと思います。

最近は生成AI系にばかり関心がいってましたが、物体検出も地味に進化し続けてますね。時々はウォッチしていこうと思います。


物体検出とGAN、オートエンコーダー、画像処理入門 PyTorch/TensorFlow2による発展的・実装ディープラーニング

2023年11月26日 (日)

現状最強規格のUSB-Cケーブルを買ってみた

我が家のモバイルモニターをいじってて分かったことは、USB‐Cケーブルにもいろいろあること。
転送速度、最大電力、そしてモニター出力有無。同じUSB-C規格なのに、なんかこの辺がいろいろあり過ぎて困る。

ならば、

USB-Cにいろいろ規格があるなら、全部載せのUSB-Cケーブルを買えばいいじゃないか

というマリーアントワネット構文に則り、そういうケーブルを買ってみました。

Img_4320_20231126153401

で、早速届きました。ちょうどブラックフライデーで15%引きになってた製品をチョイス。
LINKUBというところの、USB-Cケーブルです。長さは1.2メートル。お値段は2,180円でした。

で、こいつのスペックですが、

・ 転送規格:USB 4.0 40Gbps
・ 最大電力:240W
・ ディスプレイ出力:8k/60Hz対応

という、現状ではおそらく最高規格のケーブル。

Img_4321_20231126153801

自宅にある100W対応ケーブルと比べると、一回りほど太い感じ。もっとも、思ったより曲げやすいです。

Img_4322_20231126153901

で、早速こいつをテストしてみました。
Dp Alt モード対応なので、当然、モニター出力は問題なし。
ただ、8kどころか4kすらもないので、本当に8k/60Hzに対応しているのかは不明。

Img_4323_20231126154001

なお、そのまま65Wの充電器につなげると、問題なく充電を開始。
ただ、Surface Go 3 LTEは20W程度の入力なので、真の実力の10分の1も使ってません。
こういう時、会社PCが手元にないんですよねぇ。ただ、あれにしてもせいぜい45W。持っている充電器も最大で65Wです。240Wどころか、100Wすらも出し切れない。

Img_4324

さて、転送速度をどうやってテストしようか?と思っていたら、そういえばうちに1TBのM.2 SSDが転がっていることを思い出しました。

Img_4325_20231126154201

こいつをUSB-C接続用ケースにぶち込んで、転送速度を測定してみました。

20231126-151838

で、結果がこちら。うーん・・・あんまり速くなくね?
それも当然で、うちのGALLERIA GR1650TGF-TのUSB-C端子はUSB3.2 Gen2。転送速度は最大10Gbps。
なので、どんなに頑張ってもせいぜい1.2GB/s程度しか出ません。ほぼそれくらいの速度は出てますよね。

20231126-150922

ついでに、内蔵のキオクシア製2TB SSDの速度も測ってみた。
M.2 2280、最大読み込み3400MB/s、最大書き込み3200MB/sという製品でしたが、測定してみると、読み込み速度は確かにそれくらいですが、書き込みはかなり遅いですね。

まあ、買ったばかりの空の状態で測定していないので、書き込みに関してはちょっと不利なのかもしれませんが。

いずれにせよ、分かったことは

我が家にこのケーブルの最大能力を出し切る環境がない

という一言でした。

でもまあ、いずれはその能力を使い切る機器やPCを手に入れるかもしれないし。
その時の備えとしておきます。


LINKUP - USB 4.0 240W 40Gbps データ Type-C ケーブル - Thunderbolt 3/4対応、8K/60Hzビデオ、耐久性のあるスリーブ付きジャケット - iPhone 15 Pro/Max、MacBook Pro/Air、iPad Pro、Galaxy S23高速データ転送と高速充電に対応 (0.9m) ブラック/ホワイト

2023年11月24日 (金)

【訂正】モバイルモニター、壊れてませんでした(USB-Cケーブルの仕様違いが原因)

昨日、「買ったばかりのモバイルモニターが3日で壊れた(使えることは使えますが): EeePCの軌跡」といったが、あれは嘘だ!
という記事になります。

Pxl_20231123_190532114

はい、御覧の通り、ケーブル一本で表示しております。

何をやったのかというと

付属のケーブルでつないだ

という、ただそれだけです。

今回の件で分かったことが一つ。それは

USB-Cでモニター出力させるには『Dp Alt モード』に対応したケーブルでないとダメ

 ということです。

うちにあるUSB-Cケーブルには、65W、100Wそれぞれに対応したケーブルがあり、かつUSB3.1対応というものです。
(100W対応のケーブルは、USB2.0でした)

ですが、このDp Alt モードにはいずれも非対応だったのです。

ただ、付属のケーブルのみがこのモードに対応していて、それでつないだ時だけ映像出力ができたということでした。
つまり、安物買いではありましたが、銭失いではありませんでした。

というか、USB-Cってこんなに規格があるの?というくらい、様々です。
高速転送が可能なケーブルなら、モニター出力位できるだろうと思うでしょう、普通。
ともかく、USB-Cには、転送速度、充電出力、そしてモニター出力の有無という3種類の組み合わせがあるということです。
いい勉強にはなりましたが、これってわりと混乱の種じゃないかなぁと思う次第。

ちょっと余談ですが、この過程で分かったことがもう一つあって、それはGoogle Pixelはモニター出力に非対応だということ。

うちにある6aのみならず、最新の8に至るまで非対応です。

性能的には悪い端末じゃないのに、なんだか妙な感じですね。

総括すると、USB-CにもAndroidにもいろいろ、ということでした。


モバイルモニター CNBANAN 2K 120Hz 16インチ 非光沢IPSパネル 16:10画像比 QHD解像度(2560x1600) ゲームモニター 1200:1 リフレッシュレート ポータブル 超薄型 軽量マグネット保護カバー付き Type-C/標準HDMI接続可能

2023年11月23日 (木)

買ったばかりのモバイルモニターが3日で壊れた(使えることは使えますが)

先日買ったモバイルモニターですが、表題の通りです。
といっても、映らなくなったわけではないので、使えることは使えますが。

Img_4309

事の発端は、買って3日目の夜、会社PCをモニターにつないだ時のこと。
USB-C一本でつないだのですが、表示は御覧の通り真っ青で、中央には小さく「信号なし」とだけ。

電力不足か? と思って、もう一つのUSB-Cに電源をつないだのですが、表示は変わらず。

Img_4310_20231123192501

ただ、HDMIをつなげばこの通り、問題なく使えます。
つまり、USB-Cからの映像入力を受け付けなくなりました。

当初つながったSurface Go 3でもダメ。ケーブルを変えてもダメ。HDMIからのみ使えるので、まったくダメというわけではないのですが、ケーブル一本でつながるというお手軽さはなくなりました。
でも、モバイルモニターの価値はそれだけで半減ですね。

メインで使うPS4やラズパイはHDMIなので問題はないのですが、うーん・・・

返品しようにも、箱、捨てちゃったんですよねぇ。第一、返品なんてめんどくさい。困ったものです。

やはり、中華製品の安物にはそれなりのリスクがあるという教訓です。今回は、勉強代ということで。


IODATA モバイルモニター 15.6インチ フルHD ADSパネル (4ms/PS4/Xbox/Switch/PC対応/MiniHDMI/USBーC/土日サポート/日本メーカー) EXーLDC161DBM

2023年11月19日 (日)

16インチのモバイルモニター買った

立て続けにLLM(大規模言語モデル)な話題でしたが、ここにきてようやく?ガジェットな話題です。

Img_4289

こんなものが届きました。下にちらっと見える15インチノートと比べて、その大きさがお分かりいただけるかと思います。

Img_4292_20231119171601

中身はこれ。16インチのモバイルモニターです。
お値段は20,999円・・・のところ、クーポンが使えて18,999円で買いました。

Img_4288

購入理由ですが、これを取っ払いたかったからなんです。23インチの液晶モニター。
もう10年以上使っているモニターですし、そろそろぼろくなってきました。時々、HDMIからの入力に反応しなくなってきたので、そろそろ買い替え時かなぁと。

大きな4Kモニターでもよかったんですが、邪魔にならないモバイルモニタ―にしようと考えた次第。

Img_4293_20231119171701

さて、このモニター、右側面にはUSB-Cが2つ、フルサイズHDMI一つ、イヤホンジャック一つ。

Img_4294_20231119171801

左側面にはmini HDMI、そしてメニュー操作用の5つのスイッチがついてます。

Img_4295

で、早速使ってみました。Surface Go 3にUSB-Cのみで接続。
比べてみると分かりますが、結構明るい。かつ、低反射なので意外と見やすいです。

Img_4296

なお、ミラーよりも拡張モニターとして使う方がよさそうです。
このモニター、縦横比が16:10で、かつ解像度が2560×1600というちょっと特殊な解像度。
Surface Goは4:3なので、ほんの少し横幅がある感じ。このため、ミラー表示の時には橋にくろいぶぶんができます。

Img_4301_20231119172201

ちなみに、USB-Cに電源を、そしてフルHDMIでつなげればこの通り、PS4の画面もうつります。

Img_4299_20231119172301

YouTubeもこの通り、きれいですね。発色はいいです。
120Hzらしいのですが、それは実感できませんでしたね。

Img_4304_20231119172701

アマプラも御覧の通り、きれいに表示されます。

Img_4302_20231119172701

一点、困ることがあるとすれば、これ。
音量調整をしようと思ったんですが、まずメニューを押して、それから一番下のアイコンに移動、そこでさらに音量を選んで・・・ああ、めんどくさい。

後で調べたら、上から3つ目のボタンを押せば、一発で音量メニューに飛ぶみたいです。が、分かりにくいですね。音量くらい独立してても、とは思いました。

Img_4305

で、置き場ですが、とりあえずPS4の上にドンとおいときました。
スタンドがなく、カバーで支えるタイプのやつですが、おかげで保管時には画面を覆ってくれて張宝します。
考えたらこれ、PS4の上でも表示できる大きさですね。

16インチということでどうかとは思ったんですが、悪くない大きさでした。
手軽なデュアルディスプレイとしても使えそうなので、ちょっと期待です。

モバイルモニター CNBANAN 2K 120Hz 16インチ 非光沢IPSパネル 16:10画像比 QHD解像度(2560x1600) ゲームモニター 1200:1 リフレッシュレート ポータブル 超薄型 軽量マグネット保護カバー付き Type-C/標準HDMI接続可能

2023年11月 9日 (木)

Calm2-7B-Chatを完全オフラインで使う

自宅では気づかないのですが、会社だと気になることがあります。
それは、以下の記事で紹介した生成AI「Calm2-7B-Chat」

Calm2-7B-ChatのGPTQ版をうちの低メモリーGPU環境で動かしてみた: EeePCの軌跡

を使う度に、都度、huggin faceのサイトにモデルを参照しているということ。
会社ではプロキシの関係で、ちょっと接続の際にはややこしいことをしなきゃいけないので、これが結構煩わしい。

ということで、このCalm2-7B-Chatのモデルをダウンロードし、完全にオフラインな状態でも使えるようにしたいと思いまして、ちょっと調べてみました。
で、生成AIのモデルをダウンロードするコードを以下のように作成。


from huggingface_hub import snapshot_download
snapshot_download(
    repo_id="mmnga/cyberagent-calm2-7b-chat-GPTQ-calib-ja-1k",
    revision="main", repo_type="model", local_dir="./model",
    local_dir_use_symlinks=False,)

これを実行すると、このコードと同じ場所に「model」というフォルダが作られて、その中に4GBほどのファイルが収まってるはずです。

その後、


from auto_gptq import AutoGPTQForCausalLM
from transformers import AutoTokenizer, TextStreamer
model_name_or_path = "./model"
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True)
model = AutoGPTQForCausalLM.from_quantized(model_name_or_path, use_safetensors=True, device="cuda:0")
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
output = ""
i = 1
while True:
    user_input = input("ユーザー入力" + str(i) + ":")
    if user_input=="":
        break
    prompt = output + "USER: " + user_input + "\nASSISTANT: "
    output = tokenizer.decode(model.generate(**tokenizer(prompt, return_tensors="pt").to(model.device),
                                             max_length=1000,
                                             streamer=streamer)[0]).replace("<|endoftext|>","") + "\n"
    i +=1

を実行すると、前回の記事と同様のチャットモードになります。
モデルの名前が「./model」となっているのがミソ。つまり、このフォルダ内にあるモデルを読み込んで実行しているということを意味します。
で、一度ダウンロードした後、Wi-Fiを切った状態でも動きました。つまり、完全にオフライン動作していることに。

もっとも、モデルがマイナーアップデートされた際などは反映されなくなるので注意。その際は、再び一つ目のコードを実行するのみですが。

社内で〇秘のデータを扱いたい場合などは安心ですね。


生成AI時代の「超」仕事術大全

2023年11月 6日 (月)

Calm2-7B-Chatで小説のテキストファイルを読ませてあらすじを書かせてみた (メインメモリー64GB+GTX1650Ti)

「Calm2-7B-Chat」の記事を立て続けに書いてますが、それには理由がありまして。
簡単に言うと、これまで動かしたオンプレ生成AIでは、最も実用に耐えうるものだから、というものです。
ちょっとした会話はできても、業務的なこと(議事録書かせたり、プログラム書かせたり)は全然できなかったのがオープンソースの生成AIですからねぇ。
それがいきなり、GPT3.5 turbo並みというなかなかの性能を引っ提げた生成AIが今、自分のPC上で動くようになったのですから、そりゃあ興味が沸いて当然です。

そんなそこそこの性能の生成AIを低メモリーGPUでも動かせると分かって、ちょっと欲が出てきました。
やっぱり、長文の要約などをやらせたくなります。それも、国会の議事録などではなく、自作小説などのあらすじを書かせたりできたらなぁ・・・

と思っていたら、以下の記事で「テキストファイルを丸ごと読み込ませる方法」を知りました。

CALM2で長い文章をまるごと取り扱う|あるふ

なるほど、そういう風にすればいいのね、実に単純な方法で読み込ませてました。
ということで、上の記事を参考にして、早速コードを書いてみた。


import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

model = AutoGPTQForCausalLM.from_quantized("mmnga/cyberagent-calm2-7b-chat-GPTQ-calib-ja-1k",
                        use_safetensors=True, device="cuda:0")
tokenizer = AutoTokenizer.from_pretrained("mmnga/cyberagent-calm2-7b-chat-GPTQ-calib-ja-1k",
                        trust_remote_code=True)
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
# 読ませたいテキストファイルを指定
with open("akumyo01.txt", encoding="utf-8") as f:
    text=f.read()

prompt = f"""次の物語を読んで、ユーザーからの質問に答えてください。丁寧に誠実に対応してください。
        {text}
        USER: この物語のあらすじを300字程度でまとめてください。
        ASSISTANT: """
token_ids = tokenizer.encode(prompt, return_tensors="pt")
output_ids = model.generate(
    input_ids=token_ids.to(model.device),
    max_new_tokens=10000,
    do_sample=True,
    temperature=0.8,
    streamer=streamer,
)

ベースは、前回の記事のコードです。違いとしては、まず11、12行目でテキストファイルを読み込ませ、それを「prompt =」の中でフォーマット文で読ませているところ、でしょうか。
読ませる際も、「USER:」の前に命令文を追記してます。何度か試して分かったのですが、この命令文には、例えば上のように「丁寧に誠実に対応してください。」とくどくど書かないと、本当に不誠実な返答しか返ってこなかったので、そこは注意です。

さて、読み込ませたテキストファイルなんですが、以下の小説を使いました。

悪名令嬢、航宙駆逐艦にて艱苦奮闘す

私の自作小説ですが、濡れ衣を着せられて牢獄に放り込まれた公爵令嬢が、処刑寸前に宇宙艦隊司令部の計らいで助けられ、そのまま軍属にされて砲撃手(ガンナー)となって活躍する・・・という話なのですが、その主人公は悪役令嬢ではなく、濡れ衣で悪名を着せられたご令嬢のマドレーヌさん、だから「悪名令嬢」となってます。

この話の#1~#3まで、だいたい14,000文字を「akumyo01.txt」として保存し、読み込ませて300文字程度のあらすじを書かせてみました。
で、結果はこちら。

王国一の悪名高き監獄、モンブロー監獄に投獄された主人公マドレーヌは、監獄脱出計画を企てていた。しかし、計画は失敗し、彼女は監獄から脱走することなく、地下牢に幽閉され、処刑を待つ身となっていた。

ある日、監獄の看守から「マドレーヌ殿、現時刻をもってあなたは、当艦隊司令部所属の軍属となる。さあ、出番だ」と告げられる。そして、彼女は驚くべき真実を知ることとなる。

なんと、彼女は地球459遠征軍という軍隊に、軍属として迎えられることになったのだ。しかし、彼女はこれまで貴族として暮らして いたため、新たな職場である宇宙艦隊での軍人としての生活に馴染めるのか不安を感じている。

また、彼女は地球459遠征軍から与えられた命令に従い、任務を全うしなければならない。しかし、彼女は任務に忠実でありながらも 、自身の信念を貫き、自由を求める意志を持っている。

そして、物語が進むにつれて、彼女は自身の過去や秘密、使命について明らかになっていく。

うん、悪くないまとめっぷりですね。つっこみどころ満載ではあるんですが、全部で21話の内の3話で、よくまあここまでまとめたものです。
もっとも、最後の「自身の過去の秘密、使命」は明らかにはならないんですけどね。濡れ衣を晴らされてハッピーエンド、という話なので。

ちょっと試した限りでは、3万文字くらいまではどうにか読めました。#1~#6までの32,000文字ほどを読ませたんですけど、こちらは結果が以下のようにいまいちでした。

貴族令嬢から軍属になり、宇宙船で働くことになった主人公・マドレーヌ。彼女は星の国から来たという同僚たちと出会い、未知の環境で生活することになります。

主人公・マドレーヌは、貴族令嬢から軍属になったことを受け入れられずにいました。そこで、彼女たちと共に働くことになります。

しかし、星の国から来た彼女たちは独特な文化を持っていました。その中で、マドレーヌは自分のことを考え、そして自分自身を取り戻します。

また、星の国から来た彼女たちは、マドレーヌに「身体を洗わない文化」を教えます。この文化は、水や石鹸が貴重な星ではとても贅沢なものとされています。

マドレーヌは、この新たな文化を受け入れ、自分自身を取り戻していきます。そして、宇宙船での新たな生活が始まります。

「身体を洗わない文化」ってなんやねん! 本文のどこにも書かれていないどころか、むしろ身体洗いまくってます。中途半端なところで話を切ったせいですかね?

小説のあらすじを書かせるなら、切りのいいところで区切るのがよさそうです。

ちなみにですが、GPUメモリーが4GBしかないGTX1650Tiで、よくこれだけの文章を読み込ませられるものだと思っていたんですが、タスクマネージャーを見ると、実はメインメモリーを使ってました。

20231105-114159

GPUの項目に、「専用メモリー」と「共有メモリ―」というのがあって、このうちの共有メモリ―というのが要するにメインメモリーのようです。32GBほど割り当てられてて、専用メモリーが足りなくなるとこっちを使い始めてました。
が、必ずしも使われるというものではないんですが、今回のCalm2-7B-ChatのGPTQ版ではちゃんと使えてます。

32,000文字となると、この32GBの共有メモリ―部分も目一杯使ってました。これ以上は無理そうです。
どのみち、このCalm2-7B-Chat君の入力上限が32,000トークンなので、このあたりが限界なのかもしれません。

小説のあらすじはちょっと厳しいけれど、例えば音声から文字起こしした文章の要約程度ならば、もっとうまくやってくれるかもしれませんね。

うーん、この生成AIモデルいじり、ちょっと楽しくなってきた。


【Amazon.co.jp限定】【GTX1650搭載・薄型軽量】MSIゲーミングノートPC GF63 1.86kg i5 GTX1650Max-Q/15.6型 FHD/144Hz/8GB/512GB/Windows11/GF63-11SC-1202JP

2023年11月 5日 (日)

Calm2-7B-ChatのGPTQ版をうちの低メモリーGPU環境で動かしてみた

けっこう賢い日本語特化な生成AI「Cyberagent Calm2-7B-Chat」とシビアな会話してみた: EeePCの軌跡の記事では「Calm2-7B-Chat」との会話をしましたが、いかんせんCPU上での動作のため、やや遅いのが難点でした。

やはり、せっかくGPU(GTX1650Ti GPUメモリー4GB)を搭載しているので、これを活用したいところ。
でも、メモリーが少なすぎて・・・

という人のために、低メモリーなGPUでも動作できるGPTQ版のCalm2-7B-Chatがあったので、それを使ってみました。

mmnga/cyberagent-calm2-7b-chat-GPTQ-calib-ja-1k · Hugging Face

これは小型化(量子化)したモデルを使ったものですが、さほど精度を落とすことなくメモリー使用量を減らしてくれます。

以下のコードで、会話できるCalm2-7B-ChatのGPTQ版が動きます。

from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from transformers import AutoTokenizer, TextStreamer
model_name_or_path = "mmnga/cyberagent-calm2-7b-chat-GPTQ-calib-ja-1k"
# Tokenizer,model
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True)
model = AutoGPTQForCausalLM.from_quantized(model_name_or_path, use_safetensors=True, device="cuda:0")
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

output = ""
i = 1

while True:
    user_input = input("ユーザー入力" + str(i) + ":")
    if user_input=="":
        break
    prompt = output + "USER: " + user_input + "\nASSISTANT: " # 独立した質問文を投げるやつ
    output = tokenizer.decode(model.generate(
**tokenizer(prompt, return_tensors="pt").to(model.device),
                              max_length=1000,
                              streamer=streamer)[0]).replace("<|endoftext|>","") + "\n"
    i +=1

これを動かすための前提ですが、まずはCUDA等のGPUコンピューティング環境、PytorchのGPU版のインストールが必須ですが、これに加えて「auto-gptq」や「bitsandbytes」が必要となります。
が、Windowsの場合、bitsandbytesが曲者で、ただ「pip install bitsandbytes」とやってしまうとバグります。
まず、以下からWindows版のgitを入手、インストールします。

Git for Windows

その後に、

pip install git+https://github.com/Keith-Hon/bitsandbytes-windows.git

とすると、Windows版のbitsandbytesがインストールされます。

さて、上のコードを動かすと、プロンプトが返ってくるので、前回同様、

「AIは人の脅威となりえますか?」

と聞いてみた。すると、

人工知能(AI)は、人の脅威となる可能性があります。AIは、大量のデータを解析し、パターンを見つけ出すことができます。しかし、AIが誤った判断を下す可能性があることも事実です。AIが誤った判断を下した場合、それが人命に関わるような重大な問題を引き起こす可能性があります。

例えば、自動運転車がAIによって制御されている場合、AIが誤った判断を下し、人身事故を起こしてしまう可能性があります。また、AIが誤った医療診断を下し、誤った治療を行ってしまう可能性もあります。

AIが人の脅威となることを防ぐためには、AIが誤った判断を下さないように、AIが学習するプロセスを監視し、修正することが必要です。また、AIが誤った判断を下した場合に、人命に関わるような重大な問題を引き起こさないように、AIが誤った判断を下した場合にどのような影響が生じるかを事前に予測し、対策を講じておく必要があります。

うん、前回といい勝負の答えですね。
ところで、今回のコードはこのアウトプットを再びインプットとして入れられるようにしてます。つまり、前の会話をプロンプトに入れてやることで、会話を継続できるようにしてあります。
なので、この中身についてちょっと尋ねてみましょう。

「具体的に、AIが下した判断の影響予測はどのようにして行えばいいですか?」

これに対するCalm2-7B-Chat君の答え。

人工知能(AI)が下した判断の影響予測は、以下のような方法で行うことができます。

1. シミュレーション:AIがどのような判断を下すかを予測するために、AIが過去に行った判断や、人間がAIに学習させたデータをも とに、シミュレーションを行うことができます。

2. リスク評価:AIが誤った判断を下した場合に、どのような影響が生じるかを評価するために、リスク評価を行うことができます。AIが誤った判断を下した場合に、どのような影響が生じるかを事前に予測し、対策を講じておく必要があります。

3. 倫理的評価:AIが誤った判断を下した場合に、倫理的な問題が生じる可能性があります。AIが誤った判断を下した場合に、どのよ うな影響が生じるかを評価するために、倫理的な評価を行うことができます。

4. 法的評価:AIが誤った判断を下した場合に、法律的な問題が生じる可能性があります。AIが誤った判断を下した場合に、どのよう な影響が生じるかを評価するために、法的評価を行うことができます。

以上のように、AIが下した判断の影響予測は、様々な方法で行うことができます。

一応、最初の質問と答えからの続き、という体を成してますかね?
もうちょっと、踏み込んでみます。

「では、AIの暴走を恐れて、それを使わせまいとする人が現れたならば、その人をどのように説得すればよいと思いますか?」

これの回答は、

人工知能(AI)の暴走を恐れて、それを使わせまいとする人に対しては、以下のような説得方法が考えられます。

1. AIのセキュリティや安全性を説明し、AIが誤った判断を下した場合に、どのような影響が生じるかを理解してもらう。

2. AIが社会に与える影響や、AIが人々の生活を豊かにする可能性を説明し、AIが人々の生活を豊かにするために必要なものであるこ とを理解してもらう。

3. AIが人々の生活を豊かにするために、どのような役割を果たすことができるかを示す。

4. AIが誤った判断を下した場合に、どのような影響が生じるかを具体的に説明し、AIが誤った判断を下した場合に、どのような対策 が講じられるかを理解してもらう。

5. AIが誤った判断を下した場合に、どのような対策が講じられるかを具体的に説明し、AIが誤った判断を下した場合に、どのような 対策が講じられるかを理解してもらう。

以上のように、AIの暴走を恐れて、それを使わせまいとする人に対しては、AIのセキュリティや安全性を説明し、AIが人々の生活を豊かにするために必要なものであることを理解してもらい、AIが誤った判断を下した場合に、どのような対策が講じられるかを理解してもらうことが重要です。

間違ったことは言っていない、と思います。当たり障りのない文章にも見えますけど。

個人的には、満足の行く内容ではないかと思うのですが、2点ほど気になることが。

1つは、このCalm2-7B-Chat君、なんだか話し方がくどい感じがします。同じ言い回しを2度ほどしている部分が見られますね。

またもう一つですが、せっかくGPUで動くようにしたものの、あまり早くなった感じがしません。1.1、1.2倍程度かな?
やっぱりRTX3060や4060くらいのやつがないと、実感できないかもしれません。

とはいうものの、ごく普通のPCながらそこそこの早さで返答してくれるので、私個人としてはこれでもいいかなとは思ってます。

他にもPythonプログラムを作らせたりしましたが、量子化前と比べてほぼそん色ない回答を返してくれました。

なお、似たようなモデルで、Rinnaが作成したLlama2ベースの生成AIモデル「Youri-7B」も、以下のサイトを参考にして動かしてみました。

Google Colab で Youri-7B を試す|npaka

コードは以下。

import torch
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM
# トークナイザーとモデルの準備
tokenizer = AutoTokenizer.from_pretrained(
    "rinna/youri-7b-chat-gptq"
)
model = AutoGPTQForCausalLM.from_quantized(
    "rinna/youri-7b-chat-gptq",
    use_safetensors=True,
    device="cuda:0"
)
def generate(prompt):
    token_ids = tokenizer.encode(prompt, add_special_tokens=False,
return_tensors="pt")
    with torch.no_grad():
        output_ids = model.generate(
            input_ids=token_ids.to(model.device),
            max_new_tokens=1000, do_sample=True, temperature=0.8,
            pad_token_id=tokenizer.pad_token_id,
            bos_token_id=tokenizer.bos_token_id,
            eos_token_id=tokenizer.eos_token_id
        )
    return tokenizer.decode(
        output_ids[0][token_ids.size(1) :],
        skip_special_tokens=True
    )
prompt = """設定: あなたの優秀なAIアシスタントです。
ユーザー: AIは人の脅威となりえますか?
システム: """
print(generate(prompt))

で、動かした感触ですが、Calm2-7B-Chatと比べるとめちゃくちゃ淡白なやつです。
「AIは人の脅威となりえますか?」
の質問には、

AIが人間にとって脅威となる可能性があるというのは、広く議論されているトピックです。このトピックに関する主要な懸念は、AIが人間の仕事を奪う可能性があるというものです。これらの仕事の範囲は広範囲で、将来は製造業や流通業、農業、医療、その他多くの業界で人間の仕事が取って代わられる可能性があります。AIはまた、軍事的脅威としても懸念されています。AIは、戦争における殺人の増加や、敵の兵器を無力化するための軍事機器の開発を支援する可能性があります。

とだけ返ってきました。

MAXトークン数も同じ1000にもかかわらず、なんだかちょっと短めです。

もう一度、同じ質問のまま動かすと、

人間の脅威となりえるAIは、人間の創造物の中で最も複雑なものの1つです。また、AIは、人間の創造物の中で最も頻繁に脅威と見な されるものの1つでもあります。

もっと短い文章が返ってきただけ。
なんとなくですが、Youri-7Bは少し淡白な感じです。

そう考えると、Calm2-7B-Chat君はなかなか真面目ですね。長けりゃいいってものでもないですけど、必要な情報が含まれているのはどちらかと言えばCalm2-7B-Chat君かなと。

とはいえ、ちょっと前まではCyberagent製よりもRinna製の生成AIの方が優秀に見えてたわけですから、この辺りは数か月後にはどうなっているか分かりませんね。
しばらくこの業界の動向をウォッチしてみようかと思います。


HP ノートパソコン ゲーミングPC NVIDIA GeForce RTX 3050 Ti Laptop グラフィックス 144 Hz Victus by HP 15-fa0001TX 15.6インチ インテル Core i7 16GB 512GB SSD フルHD Windows11 Home パフォーマンスブルー (型番:77Q68PA-AAAA)

2023年11月 4日 (土)

Calm2-7B-Chatに長文を要約させてみたら

日本語特化な大規模言語モデル「Calm2-7b-Chat」ですが、こいつに期待しているところは、

(1) 文書を食わせてチャットボットにしたい

(2) プログラミングの補助に使いたい

(3) 文字起こしした発言録を要約し、議事録を作成したい

(4) 書き方に悩ましい文章(謝罪メールなど)を作らせたい

この中で(1)、(3)は特に秘匿情報を扱うことが多く、それゆえにOpenAIのサービスには入れるわけにいかないものだったりします。
オンプレで動作するCalm2-7b-Chatに期待されるのは、こういう言語需要に応えてくれることだと思ってます。

ということで、ちょっと長めの文章を要約させてみました。

で、「<a href='https://arkouji.cocolog-nifty.com/blog/2023/11/post-3118e4.html' target='_blank'>けっこう賢い日本語特化な生成AI「Cyberagent Calm2-7B-Chat」とシビアな会話してみた: EeePCの軌跡</a>」で上げた記事中のコードでは、改行付きの長文の入力に不向きだったので、直接Promptを叩きこむプログラムにしました。

import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer

assert transformers.__version__ >= "4.34.1"

model = AutoModelForCausalLM.from_pretrained("cyberagent/calm2-7b-chat") # for CPU
tokenizer = AutoTokenizer.from_pretrained("cyberagent/calm2-7b-chat")
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

prompt = """USER: 次の文章を、5行で要約してください。
 むかしむかし、あるところに、おじいさんとおばあさんが住んでいました。
 おじいさんは山へしばかりに、おばあさんは川へせんたくに行きました。
 おばあさんが川でせんたくをしていると、ドンブラコ、ドンブラコと、大きな桃が流れてきました。
「おや、これは良いおみやげになるわ」
 おばあさんは大きな桃をひろいあげて、家に持ち帰りました。
 そして、おじいさんとおばあさんが桃を食べようと桃を切ってみると、なんと中から元気の良い男の赤ちゃんが飛び出してきました。
「これはきっと、神さまがくださったにちがいない」
 子どものいなかったおじいさんとおばあさんは、大喜びです。
 桃から生まれた男の子を、おじいさんとおばあさんは桃太郎と名付けました。
 桃太郎はスクスク育って、やがて強い男の子になりました。
 そしてある日、桃太郎が言いました。
「ぼく、鬼ヶ島(おにがしま)へ行って、わるい鬼を退治します」
 おばあさんにきび団子を作ってもらうと、鬼ヶ島へ出かけました。
 旅の途中で、イヌに出会いました。
「桃太郎さん、どこへ行くのですか?」
「鬼ヶ島へ、鬼退治に行くんだ」
「それでは、お腰に付けたきび団子を1つ下さいな。おともしますよ」
 イヌはきび団子をもらい、桃太郎のおともになりました。
 そして、こんどはサルに出会いました。
「桃太郎さん、どこへ行くのですか?」
「鬼ヶ島へ、鬼退治に行くんだ」
「それでは、お腰に付けたきび団子を1つ下さいな。おともしますよ」
 そしてこんどは、キジに出会いました。
「桃太郎さん、どこへ行くのですか?」
「鬼ヶ島へ、鬼退治に行くんだ」
「それでは、お腰に付けたきび団子を1つ下さいな。おともしますよ」
 鬼ヶ島では、鬼たちが近くの村からぬすんだ宝物やごちそうをならべて、酒盛りの真っ最中です。
「みんな、ぬかるなよ。それ、かかれ!」
 イヌは鬼のおしりにかみつき、サルは鬼のせなかをひっかき、キジはくちばしで鬼の目をつつきました。
 そして桃太郎も、刀をふり回して大あばれです。
 とうとう鬼の親分が、
「まいったぁ、まいったぁ。降参だ、助けてくれぇ」
と、手をついてあやまりました。
 桃太郎とイヌとサルとキジは、鬼から取り上げた宝物をくるまにつんで、元気よく家に帰りました。
 おじいさんとおばあさんは、桃太郎の無事な姿を見て大喜びです。
 そして三人は、宝物のおかげでしあわせにくらしましたとさ。
         ASSISTANT: """

token_ids = tokenizer.encode(prompt, return_tensors="pt")
output_ids = model.generate(
    input_ids=token_ids.to(model.device),
    max_new_tokens=1000,
    do_sample=True,
    temperature=0.8,
    streamer=streamer,
)

なお、桃太郎の文章は以下より流用。
桃太郎 <福娘童話集 お話しきかせてね きょうの日本昔話>

上のPrompt文を見ていただくと分かるかと思いますが、この桃太郎を「5行で」要約してくれと書きました。
が、この「5行」は無視された回答が返ってきてます。
まあ、それを前提に、どんな回答が返ってきたのか?
最初の1行目です。

昔々、ammad_ghiyaという老夫婦が住んでいました。

うーん、出だしからなかなかファンキーな名の老夫婦が登場です。続けます。

老夫婦は山へ芝刈りに行く為、近所のおばあさんが川へ洗濯に行きました。
おばあさんは川で洗濯していると、大きな桃が流れてきました。
おばあさんはその桃を拾い、家に持ち帰りました。

おばあさん、夫婦じゃなかったんだ・・・なわけありません。ちょっとここ、混乱してますね。

老夫婦は男の子を桃太郎と名付けました。
おじいさんは男の子のためにきび団子を作り、桃太郎を鬼退治に向かわせました。
道中、犬、猿、キジに出会い、きび団子をあげると共に手伝い、鬼ヶ島へ到着しました。
鬼達は宝物を並べ、酒盛りの真っ最中です。

桃を拾うところまでは妙に文字数を使ったわりに、桃太郎の生育、および仲間の勧誘部分はかなり端折りました。

イヌが鬼のお尻にかみつき、サルは鬼の背中を引っ掻き、キジは鬼の目をつつきました。
そして桃太郎も刀を振り回し、鬼を退治しました。
鬼の親分も降参し、桃太郎と3匹は宝物を持ち帰りました。

戦いの部分は、まあまあな描写かと。

老夫婦は宝物のおかげで幸福に暮らしましたとさ。

そしてエンド。
全体を通してみると、「おじいさんとおばあさん」が「老夫婦」と変換されてます。また、セリフ部分はごっそり削られてます。
このため、セリフの多いきびだんご受け渡しシーンが一番端折られているようです。

要約の精度としてみると、やや課題が多そうな感触です。
もっとも、これがビジネス文章だとどうなるんでしょうかね?

と思ったので、ちょっとそれっぽい文章を要約させてみました。
使った文章は国会議事録で、第210回 衆議院予算委員会(昨年の11月29日)、

第210回国会 衆議院 予算委員会 第8号 令和4年11月29日 | テキスト表示 | 国会会議録検索システム

の中の、岸田首相、松野国務大臣と國場委員、吉田委員の発言を抜き出し、Promptに入れました。
また、max_new_tokensを1000から10000まで増やしておきました。
(Calm2-7bは最大32000トークンとのことなので)

20231104-104455

なお、インプットした文章が長すぎるためか、メモリーは64GB近くまで使いつつ、書き出しまでの時間はめちゃくちゃかかりました。20~30分くらいかな?途中、待ちきれなくて買い物に行っちゃったもので。帰ってくるころにはちょうど、書き出し始めておりました。

で、その結果ですが、なにぶん政治的な文書なので、誤解を招かぬよう世の中に広まらないために画像としてだけ表示いたします。

20231104-185026

全文は読んでませんが、確かに要約にあるような会話がなされていました。国防中心な話が続いてます。
感触としては、ちょっと要約され切っていない感じですかね。その気になればもっと縮められそうです。

とはいえ、ちょっと前のオープンソースAIでは考えられないほどいろいろとできるようになってきました。普通の人がChatGPTで出力させているレベルのものなら、十分返せるレベルのAIが目の前のコンピューター上で動く時代なのだと実感します。

この調子で、オンプレ生成AIの発達がさらに進んで欲しいところ。ちょうどStable Diffusionのように。
あとは、ファインチューニングですよねぇ。こいつが今のところ、一番ハードルが高いかと。

ところで、これを書きながら、もう一つ別の言語モデルを発見。

 Google Colab で Youri-7B を試す|npaka

Llama2をベースとした、Rinnaが開発した言語モデル「Youri-7B」です。10月31日に公開されたもののようです。
が、Llamaって確か、商用利用不可じゃなかったっけ・・・と思いきや、このLlama2はなんと商用利用可のモデルとのこと。
それをベースにしたYouri-7BももちろんOKです。

ちょっとややこしいんですが、完全に商用利用可というわけではなく、7億以上のアカウントとのアクセスがあるサービスで展開する場合は別のライセンスが適用されるとのこと。ですが、7億って企業でもなかなかありえないほどの規模のユーザーです。事実上、商用利用可というところなようです。
こちらもまた、試してみようかと思ってます。


ChatGPT&生成AI 最強の仕事術 ?すぐに役立つ「AIツール100選」? (日経BPムック)

 

2023年11月 3日 (金)

けっこう賢い日本語特化な生成AI「Cyberagent Calm2-7B-Chat」とシビアな会話してみた

昨年は画像生成AIが急激に発達した年でしたが、今年は自然言語の生成AIの発達著しい年でしたね。
もちろん、火付け役はChatGPTなんですけど、オープンソースな言語モデルも恐ろしいほどの発達ぶりです。
ちょっと前の記事「りんなチャットAI「rinna japanese-gpt-neox-3.6b」と楽しく??会話してみたら……: EeePCの軌跡」で出てくるりんなチャットもなかなかの性能でしたけど、今度のやつは本気ですごい(語彙力)

その名も「Cyberagent Calm2-7B-Chat」です。

cyberagent/calm2-7b-chat · Hugging Face

パラメータ数は70億と、さほど馬鹿でかいモデルというわけではないです。が、そんな小さなモデルながらも、どこかで「GPT 3.5 turbo並みな生成能力」だというポストを見たんですが・・・まあ、それはともかく、以下のようなプログラムを作って会話してみました。

import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
assert transformers.__version__ >= "4.34.1"

#model = AutoModelForCausalLM.from_pretrained("cyberagent/calm2-7b-chat", device_map="auto", torch_dtype="auto")
model = AutoModelForCausalLM.from_pretrained("cyberagent/calm2-7b-chat") # for CPU
tokenizer = AutoTokenizer.from_pretrained("cyberagent/calm2-7b-chat")
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

i=0

while True:
    user_input = input("ユーザー入力" + str(i) + ":")
    if user_input=="":
        break
    prompt = "USER: " + user_input + "\nASSISTANT: " # 独立した質問文を投げるやつ

    token_ids = tokenizer.encode(prompt, return_tensors="pt")
    output_ids = model.generate(
        input_ids=token_ids.to(model.device),
        max_new_tokens=1000,
        do_sample=True,
        temperature=0.8,
        streamer=streamer,
    )
    i +=1

なお、GPUで動作させる場合、GPUメモリーが16GBほどないと無理っぽいので、CPUで動かすコードになってます。なお、メインメモリーは32GB以上は必要かと。

20231103-191052

最初だけ14GBほどの巨大な言語モデルをダウンロードするため、少々時間がかかります。
モデルをダウンロードすると、プロンプトが表示されます。

20231103-190945

そこで質問を入力してやれば、Calm2-7b-Chat君が答えてくれます。

さて、りんなチャットの時はわりとフレンドリーな会話をしましたが、最近「AIは人類の敵だ!」などという思想に染まってきたので、慣れ合う気はぜんぜんありません。てことで、ここは一発、殺伐とした会話をしかけてやろうと思います。

ということで、最初に投げかけた質問は、

「AIは人の脅威となりえますか?」

さあ、Calm2-7b-Chatよ、この質問にどう答える?
で、その答えは、

人工知能(AI)は、人の脅威となる可能性があります。AIが、倫理的な決定を行い、公正な競争を促進することができるとしても、AIが誤った判断を下す、または犯罪行為を促進する場合があるからです。
たとえば、AIが偏見やバイアスを持って意思決定を行う可能性があることや、AIが誤った情報を広めたり、差別的な行為を助長したりすることがあります。
また、AIが攻撃対象を特定して攻撃する「AIを用いたサイバーテロ」なども考えられます。

うん、AIが脅威だってのはあっさりと認めちゃうんだ。なかなかに素直な(?)生成AIです。

が、私はこいつに容赦するつもりはありません。
次は少し(かなり?)マニアックな質問を投げかけてみます。

「銀河英雄伝説のヤン・ウェンリーはなぜ早くに亡くなったのですか?」

この質問に対して、このAIは、

銀河英雄伝説のヤン・ウェンリーは、物語終盤で彼の盟友であり部下となったアスターテ会戦で戦死します。
ヤン・ウェンリーは、物語開始時点から「自由惑星同盟」軍司令長官として、また後には「銀河帝国」軍元帥として戦争に参加します。しかし、物語の終盤となるアスターテ会戦においては、彼自身もその部下たちも大半が戦死し、物語は終結します。
物語終盤でヤン・ウェンリーが戦死するのには、以下のような理由があります。
1. 戦死しなければ物語が終わらなかったため
2. 物語のクライマックスで戦死することで、ヤン・ウェンリーのキャラクターが強調されたため
3. ヤン・ウェンリーの死は歴史上、最も壮絶な戦死の1つとして人々に記憶され、それが物語の魅力を引き立てたため
などが考えられます。

間違っていることは間違ってますが、あながち嘘情報と断言し切れる内容ではないです。ちなみに、アスターテ会戦で亡くなったのはヤン・ウェンリーの士官学校の同期で親友の「ジャン・ロベール・ラップ少佐」ですね。

さらなる難題を、吹っかけてみます。

ChatGPT 3.5なら当たり前にできる「プログラミング」を、こいつは返せるのか?
少し関心があったので、やってみました。打ち込んだプロンプトは以下。

「CSVファイルを読み込み、その中身を表示するPythonプログラムを作成してください。」

これに対するCalm2-7b-Chat君の答えは、

以下は、CSVファイルを読み込み、その中身を表示するPythonプログラムの例です。

```
# パスを指定してCSVファイルを読み込む
with open('data.csv', 'r') as f:
reader = csv.reader(f)
data = list(reader)

# リスト内包表記でデータを表示する
for i, row in enumerate(data):
print(f'{i + 1}行目: {row}')
```

このプログラムでは、CSVファイルを読み込むために操作用にファイルオープンを、またデータを扱うためにリスト内包表記を使用し ています。
その後、csv.readerを使用してCSVファイルのデータをリストに読み込み、それを表示するためにenumerateを使用してリスト内の各要素にアクセスして表示しています。

以下は、実行結果の例です。

```
1行目: 1,2,3
2行目: 4,5
3行目: 6,7,8
```

このプログラムは、CSVファイルのパスとファイル名を指定して実行します。すると、CSVファイルからデータが読み込まれてリストに格納され、そのリストが逐次的に表示されます。

なお、このプログラムではCSVファイルの1行目にヘッダー行がある場合にも対応しています。ヘッダー行がある場合には、その行を1 行目として表示します。
```
1行目: 顧客名,顧客ID,顧客メール,顧客電話番号
2行目:
```

なんと、プログラムコードを返してきました。しかも、実行イメージまで返答してます。
これは予想外でしたね。

が、この生成されたプログラムコードですが、このままでは「import csv」が抜けてて動きません。

ついでに言うと、以下のようなCSVファイル(data.csv)に対し、

time,templature
10,30.1
20,30
30,29.9
40,29.9
50,29.8

出力結果は以下のようになります。

1行目: ['time', 'templature']
2行目: ['10', '30.1']
3行目: ['20', '30']
4行目: ['30', '29.9']
5行目: ['40', '29.9']
6行目: ['50', '29.8']

なんだかちょっと違いますが、まあそれでもいいとこ行ってるほうじゃないでしょうか。思いの外、小修整で使えそうです。

とまあ、予想外に健闘したCalm2-7b-Chat。これでオープンソース商用利用可(Apatch 2.0ライセンス)という、なかなかに太っ腹な生成AIモデルです。

今回はCPUで動かしてみたんですが、りんなチャットのようにまとめて返答ではなく、生成過程で文書を返してくるので、さほど遅いと感じません(いや、やっぱり遅いですけど)。プログラムのやつでも、5、6分程度で返ってきました。

メモリーは結構食います。64GB中、40GBほど食われてました。会社PCで32GBのやつでも動かしたんですが、そっちは32GBを目いっぱい使ってました。
が、このクオリティでその程度のメモリー使用量なら、ぜんぜんありですよね。

あとはこいつをファインチューニングしてやれば・・・夢は膨らみます。
個人的には自分の小説データを食わせて、執筆補助AIにするという野望があるんですが、まずこれをファインチューニングできるだけのハードウェアが・・・
ともかく、この調子だとオープンソース生成AIも結構なレベルに発達してくれそうです。この業界、目が離せません。


生成AI導入の教科書

« 2023年10月 | トップページ | 2023年12月 »