前回、Mergekit-Evolveによる進化的マージについて紹介した。

私の記事では評価モデルとしてローカルのLlama3-70Bを使ったのだが、その後、布留川さんが評価にGeminiのAPIを使うという画期的なアイデアを実装してくれた。

私は元々評価モデルにCohereのCommand R+のAPIを使いたかったのだが、無料枠は月に1000回しか叩けない。それでは1回Mergekit-Evolveを回したら使いきってしまって、次に枠が回復するまで一ヶ月待つハメになる。だから仕方なくローカルのモデルで評価する方法を探った。

一方、Gemini1.0ProのAPIは明日から有料化されるのだが、有料化された後もAPIの無料枠は維持されるらしい。その無料枠は1日あたり1500回もある!(Gemini1.5Proは50回)知らなかったがかなり太っ腹だ。
Mergekit-EvolveでElyzaTasks100を回す場合、デフォルトの100回のイテレーションの中で毎回10問ずつ評価するのだから、合計で1000回くらいAPIで評価する必要があるが、これならGeminiAPIの毎日の無料枠に収まる。
計算したところ、もし普通に金を払ってたら、1回Mergekit-Evolve回すのに75円くらいかかるようだ。毎日1回回したら一ヶ月で2250円。こんだけの計算資源がタダで使えてしまう。

で、布留川さんの素晴らしい記事を受けて、はちさんがこれらのスクリプトをGoogleColabからサクッと動かせるようにリポジトリに整理してくれた。

Hajime-Y/mergekit-evolve-elyzatask100: mergekit-evolve for elyza task 100 (github.com)

ちょうど自分でも布留川さんの記事を参考にGeminiで評価するようにスクリプト書き直さなきゃな…と思ってたところだったので、手間が省けて助かる。

何回か手元でMergekit-Evolveを回してて思ったんだが、メインPCのGPUがMergekit-Evolveに専有されてると、その間他の作業が出来なくて困る。だったら寝てる間に回せばいいやんと考えたが、GPUファンの音がうるさくて寝付けない。
だから、メインPC以外でMergekit-Evolveが回せねえかな…という事を考えていた。手元にはメインPC以外にサブのゲーミングノートPCがある。GPUはGTX1660Tiを積んでるが、VRAMは6GBしかない。

布留川さんの手法のように、Geminiを評価モデルとして使うなら、推論モデルと評価モデルを両方ローカルで動かす必要は無くなる。必要なリソース(メモリなど)はかなり減らせるわけだ。
それでも依然としてVRAMを20GBくらい消費してしまうのを何とかしないといけない。

Mergekit-EvolveでVRAMを消費してしまう局面は①Cudaマージと②推論の二つがある。どちらもVRAMに量子化されてないF16のモデルを読み込む必要があるので、どうしても20GBくらい必要だ。

しかし、色々工夫する事でVRAM6GBのノートPCでもMergekit-Evolveが回る事を確認できた。

どうやったのか?というと、まず①Cudaマージについては、単に使用しないようにオプションで–no-cuda-mergeを付ければいい。こうすればマージはGPU上ではなくCPU上で行われるようになる。遅くなる代わりにVRAMは不要になる。

②推論については、ズバリ4bit量子化でロードしてしまえばいい。量子化すると劣化があるだろうが、全部を量子化するんだから別に公平なんだから構わないだろう。

推論時に4bit量子化でロードさせるには、mergekitのソースコードを1行だけ弄る必要がある。mergekit/mergekit/evo/helpers.pyの84行目あたりにmodel_args["load_in_4bit"] = Trueと追加するだけだ。

量子化ロードのためにはbitsandbytesのインスコが必要になるだろう。

また、transformersで推論する必要があるので、vLLMオプション(–vllm)は使えない。さらに、インメモリマージ(–in-memory)オプションも使えなくなる。
transformers推論はvLLM推論より遅いし、通常のディスクマージはインメモリマージよりも遅い。とにかく諸々が遅くなってしまうが、その代わりにVRAM消費は5GBくらいに収まる。

この方法で実際にノートPCでMergekit-Evolveを動かしてみたところ、まあVRAM自体は無事に足りていたのだが、メインメモリの方に若干難があった。ノートPCにはメインメモリが16GBしかないのだが、それでは全然足りないようだ。仮想メモリに57GBくらいスワップしていた。ノートPCはメインドライブが240GBのSSD、もう一つ1TBのHDDを積んでるが、HDDを仮想メモリに使うとメッチャ遅くなるから仮想メモリはSSDにだけ確保した方がいい。
で、Mergekit-Evolveを動かしてる間、ディスクマージのせいで毎回ディスクにモデルが書き込まれるし、仮想メモリとメインメモリ間で激しくスワップし続けるわけで、つまりSSDに悲惨なくらいに書き込みが連続的に発生してしまう。おそらくSSD寿命を相当縮めてしまうだろう。

さらに、一回目の実行では途中で謎のCudaエラーが起きて落ちてしまっていて焦ったが、2回目は無事に最後まで実行できた。実行時間は26時間くらい。メインPCでは6時間ほどで終わっていたので、ノートPCでは4倍以上の時間がかかってしまう感じになっている。とは言え、どうせGeminiAPIの無料枠を考えると1日1回しか実行できないのだからちょうどいいペースなのかもしれない。

布留川さんはMergekit-EvolveをGoogleColabのA100で試していたが、7時間くらいかかったそうだ。ColabのA100は1時間当たり154円のコストがかかる。7時間なら1079円かかってしまう。少し高すぎるわけだが、今回の手法でVRAM消費が減らせれば、A100でなくともT4なんかで動かせる道が開けるかもしれない。上手く行けばColabのCPUインスタンスでも動かせる可能性がある。CPUインスタンスは1時間当たり1円くらいのコストしかかからないのでもし成功すればコスパがいいだろう。とは言えVRAMが足りてもメインメモリが足りない可能性も高い。GoogleColabは仮想メモリも使えないみたいだし。

それはいいんだが、Llama3やGeminiによる自動評価でMergekit-Evolveを回す手法は今日になって問題が上がっている。
というのは、利用規約的にもしかするとそういう使い方はできないかもしれないという話だ。

まず、Command R+などのCohereのモデル、APIは商用目的での合成データ出力を禁じてるらしい。LLMの採点出力は合成データなのか?と言われると微妙な気もするけど、ダメだと言われればダメかもしれない。まあ逆に言えば非商用なモデルなら使ってもよさそうだが。

だったら他のモデルはどうなんだ?と思って、まずGeminiの利用規約を見てみたら、「本サービスを使用して、本サービスと競合するモデルを開発する事はできません」と書かれている。
さて、Mergekit-Evolveの自動評価にGeminiを使う事は、”競合するモデルを開発する事”になるんだろうか?まず、ただ単にモデルを評価するためにGeminiを使うのは、全然競合モデル開発に関係ないだろう。だったらMergekit-Evolveの自動評価に使ったって、それは別に直接競合モデル開発してるわけじゃないからセーフでは?う~ん…必ずしもクロとは言い切れないが、シロとも言い切れないかも…。まあやらないに越した事はないといったところか。

さらに、Llama3の規約も確認してみたが、「利用者は、ラマ素材またはラマ素材の出力または結果を使用して、他の大規模言語モデル(Meta Llama 3またはその派生物を除く)を改善しないものとします。」と書かれている。Geminiの規約と同じような話みたいだが、違うのはLlama3自体を改善するのにLlama3を用いるのは問題なさそうという点だ。つまり、Llama3-8Bを進化的マージさせるのに、Llama3-70Bに自動評価させるのは問題ないだろう。

私は前回の記事でLlama3-70Bを評価モデルにしてMistral-7Bの派生モデルを進化的マージさせてJapanese-Chat-Umievo-itr001モデルを作ったが、あれも厳密に言えばグレーかもしれないので、念のためHuggingFaceに上げたモデルは非公開に切り替えた。

じゃあQwen1.5はどうなんだ?というと、やっぱり「 お客様は、他の大規模言語モデル(「同伊乾文」またはその派生物を除く)を改良するために、本マテリアルまたはその出力を使用することはできません。」と書かれている。Llama3と同じ話で、Qwen1.5自身を改善するためになら使っても良さそうだ。

もちろんOpenAIやAnthropicにも同様の規約がある。

「だったらどうすりゃええねん!」という話だが、実はMistralAIだけは規約にそのような制限が書かれてないらしい。

つまり、Mistralのモデル、APIならMergekit-Evolveの自動評価に使っても問題ないらしい。例えばMistral-MediumはNejumiリーダーボードでGeminiProと同等の性能が出ているので、評価用モデルに使っても問題なさそうだ。ただ、Geminiと違ってAPI無料枠とかそういうのは無さそうだが。

ここまでOKらしいとかNGらしいとか書いてきたが、結局のところ、実際には何がOKで何がNGなのかはハッキリしないし弁護士や専門家の意見でもないわけで、最終的には各自で判断していただく必要があるだろう。

今回の記事の話としてはこんなところだが、最後に今回サブノートPCのWindowsでMergekit-Evolveが動かせるまで環境をセットアップしたので、何かの参考になるかもしれないので手順をメモっておく。あらためて言っておくが、Geminiを評価モデルとしてMergekit-Evolve回すのは利用規約に触れるかもしれないので注意して欲しい。

サブノートPCでMergekit-Evolve動かすまでの手順

①Python環境としてAnacondaを入れる。

②メインのSSDドライブはカツカツなので、conda環境をHDDドライブに保存するようにする。Dドライブにanaconda_env/envsというディレクトリを切って、環境変数CONDA_ENVS_PATHで指定する。

③transformersのキャッシュもHDDに保存されるようにDドライブにフォルダを作って環境変数HF_HOMEで指定する。

④CUDAを使うのでCuda Toolkitの最新版をインスコする

⑤任意だけどVisualStudioCodeをインスコする。もうこれが無いとpython触れない。

⑥なんか後でフラッシュアテンションのホイールビルドでこけないように、VisualStudio2022をインスコする。VisualStudio2019が元から入ってたけどこれじゃダメらしい。多分、「C++によるデスクトップ開発」にチェックを入れる必要がありそう。

⑦Anaconda PowerShellを開いてconda環境作ってgit入れて、はちさんのリポジトリをクローンする。

⑧pipで諸々入れる(フラッシュアテンションのホイールビルドで数時間待たされる)

⑨上で書いた方法で4bit量子化でロードできるようにhelpers.pyを書き換え

⑩evol_merge_config.yamlを自分のやりたい設定に書き換える

⑪et100_metric.pyを開いて13行目にgeminiのAPIキーをベタ書きする。32行目のprompt_eval_llamacpp.txtのパスを現在の環境でのパスに書き換える。

⑫et100.yamlを開いて5行目のtest:を自分の環境でのarrowファイルのパスに書き換える。

⑬HuggingFaceにログイン(トークンコピペが必要)

⑭wandbにログイン(トークンコピペが必要)

⑮準備完了なのでMergekit-Evolveを実行

⑯終わるまで26時間待つ。待ってる間はリモートデスクトップで監視したり、wandbのログをチェックしたりする。

⑰終わったら最終モデルの生成

⑱HuggingFaceにモデルアップロード

お疲れさまでした。