Meta のオーディオ生成 AI モデル、AudioGen を macOS の MPS (GPU) で動かす

Facebook でおなじみの Meta 社がリリースした AudioCraft は、英語のテキストから音楽や音声 (効果音) を生成できる AI です。2023年 6月に最初の v0.0.1 が、そして 2024年 5月には v1.3.0 がリリースされており、ローカルでも実行できます。ただし、生成に使えるのは NVIDIA GPU もしくは CPU となり、macOS では CPU のみしか正式に対応していません。悔しいですよね。いろいろ調べて試した結果、効果音を生成する AudioGen であれば Apple Silicon の GPU である MPS (Metal Performance Shaders) を使って生成速度を上げることができました。本記事ではその方法を公開します。

AudioCraft: https://ai.meta.com/resources/models-and-libraries/audiocraft

GitHub: https://github.com/facebookresearch/audiocraft

はじめに

AudioCraft のコードは MIT ライセンスでリリースされていますが、モデルの重み (Hugging Face からダウンロードされる学習済みファイル) は CC-BY-NC 4.0 という、商用利用不可のライセンスでの公開となります。生成物を何らかの形で公開する際はご注意ください。

AudioCraft には、音楽を生成する MusicGen というモデルも含まれています。また、より新しく、速く、高性能らしい MAGNeT というモデルもあるのですが、これらを MPS で動かすことはできませんでした。動きは活発ではないものの、open の issue もいくつか GitHub にあるので、そのうち正式対応するかもしれません。ただ、ローカルで無料で動かせるとは言え Stable Audio の様に使用料を払えば商用利用できるというわけでもなく、OSS プログラマーのチャレンジ精神以外の力が積極的に働くこともなさそうなので、過度な期待はできないと思っています。

環境構築

動作確認ができた環境

macOS: 14.5
ffmpeg version 7.0.1

環境構築手順

入っていなければ、ffmpeg をインストール (もちろん brew が必要です)

brew install ffmpeg

ディレクトリを作って AudioCraft リポジトリをクローン。ディレクトリ名はお好きにどうぞ

mkdir AudioCraft_MPS
cd AudioCraft_MPS
git clone https://github.com/facebookresearch/audiocraft.git .

仮想環境を構築して入る。ボクは得意のpipenvですが、これもお好きなのをお使いください。Python は 3.9 以上必須です

pipenv --python 3.11
pipenv shell

PyTorch をバージョン指定 (2.1.0) でインストール

pip install torch==2.1.0

requirements.txtxformers のバージョンを0.0.20に固定。MPS では xformers は使えませんが、このやりかたが一番簡単でした。以下例では、vimを使っていますが、お好きなテキストエディタでどうぞ

vi requirements.txt
#xformer<0.0.23
xformers==0.0.20

もろもろをインストールして、環境は完成

pip install -e .

生成に MPS を使うようにファイルを変更

下記ファイルを変更し、エンコーディングにのみ MPS を使用するようにします。

audiocraft/models/encodec.py

クローンしたリポジトリのバージョンによって行番号が異なる可能性がありますが、class EncodecModel(CompressionModel):の中のdecode()メソッドが対象です。ハイライト部分の最初のout = self.decoder(emb)をコメントアウトし、その下のif~elseのブロックを追加します

    def decode(self, codes: torch.Tensor, scale: tp.Optional[torch.Tensor] = None):
        """Decode the given codes to a reconstructed representation, using the scale to perform
        audio denormalization if needed.

        Args:
            codes (torch.Tensor): Int tensor of shape [B, K, T]
            scale (torch.Tensor, optional): Float tensor containing the scale value.

        Returns:
            out (torch.Tensor): Float tensor of shape [B, C, T], the reconstructed audio.
        """
        emb = self.decode_latent(codes)
        #out = self.decoder(emb)
        # Below if block is added based on https://github.com/facebookresearch/audiocraft/issues/31
        if emb.device.type == 'mps':
            # XXX: Since mps-decoder does not work, cpu-decoder is used instead
            out = self.decoder.to('cpu')(emb.to('cpu')).to('mps')
        else:
            out = self.decoder(emb)

        out = self.postprocess(out, scale)
        # out contains extra padding added by the encoder and decoder
        return out

↑ のコードは、偉大なる EbaraKoji 様 (お名前から、日本の方のような?) の issue ↓ からいただきました。フォークされたリポジトリそのものは動きませんでした。残念。

https://github.com/facebookresearch/audiocraft/issues/31#issuecomment-1705769295

音声生成コード

どこかからいただいてきたコードに少し手を加えたものです。保存場所はどこでもいいのですが、一応他の実行用コードと一緒にdemosディレクトリに入れておきましょう。

from audiocraft.models import AudioGen
from audiocraft.data.audio import audio_write
import argparse
import time

model = AudioGen.get_pretrained('facebook/audiogen-medium', device='mps') # mps で Apple Silicon の GPU を指定
model.set_generation_params(duration=5)  # [duration] 秒のファイルを生成

start = time.time()
def generate_audio(descriptions):
  wav = model.generate(descriptions)  # 引数として与えられたテキスト全ての音声を生成
  
  for idx, one_wav in enumerate(wav):
      # {idx}.wav というファイルを生成。音の大きさ loudness は -14 db LUFS で平準化
      audio_write(f'{idx}', one_wav.cpu(), model.sample_rate, strategy="loudness", loudness_compressor=True)
      print(f'{idx}.wav を生成')
      print(f'かかった時間: {round(time.time()-start, 2)} 秒')

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Generate audio based on descriptions.")
    parser.add_argument("descriptions", nargs='+', help="List of descriptions for audio generation")
    args = parser.parse_args()
    
    generate_audio(args.descriptions)

6行目のdevice='mps'がキモです。これで GPU で生成してくれます。これを'cpu'にすると生成速度が遅くなりますが、メモリは消費されません。また、学習済み音声モデルは他にもfacebook/audiogen-smallがあります (ボクは試していません)。

7行目のduration=5は、生成する音声の長さを 5秒に指定しています。

使い方

注意: 初回実行時には学習済み音声モデルがダウンロードされるので、その分時間がかかります。

以下のように、欲しい効果音の内容を英語で引数として渡してあげると、0.wav, 1.wav,... と音声ファイルが生成されます。引数は一つでも複数渡しても生成速度はほとんど増えないので、一度にいくつか作ってもらうのが良いと思います。

python demos/audiogen_mps_app.py "text 1" "text 2"

実行例:

python demos/audiogen_mps_app.py "heavy rain with a clap of thunder" "knocking on a wooden door" "people whispering in a cave" "racing cars passing by"
/Users/handsome/Documents/Python/AudioCraft_MPS/.venv/lib/python3.11/site-packages/torch/nn/utils/weight_norm.py:30: UserWarning: torch.nn.utils.weight_norm is deprecated in favor of torch.nn.utils.parametrizations.weight_norm.
  warnings.warn("torch.nn.utils.weight_norm is deprecated in favor of torch.nn.utils.parametrizations.weight_norm.")
0.wav を生成
かかった時間: 61.05 秒
1.wav を生成
かかった時間: 61.1 秒
2.wav を生成
かかった時間: 61.16 秒
3.wav を生成
かかった時間: 61.22 秒

M2 Max 32GB RAM だと、メモリプレッシャーが低い状態から始めれば、5秒のファイルは 60秒前後、10秒のファイルは 100秒前後で生成されます。

実行直後 warning が出ますが、動いているので深追いしてません。PyTorch (torch) のバージョンを上げることがなければ無視してかまわないかと思います。

音楽の生成 MusicGen や MAGNeT は MPS を使えず

音楽を生成する MusicGen も MPS で動かせないかと試したのですが、同じ様な方法では無理でした。CPU であれば動くので、python demos/musicgen_app.pyで GUI を試せます。

MAGNeT はよりイケてるバージョンらしいのですが、CPU でも動かすことはできませんでした。こちら ↓ の issue を見ると、リンクされている commit で動くっぽいのですが、ボクはできませんでした。

https://github.com/facebookresearch/audiocraft/issues/396

というわけで、今回はここまで。

Image by Stable Diffusion (Mochi Diffusion)
毎回書いているこの部分は、今回から開いた人だけ見れるようにします。本文とあまり関係ないので。
今回は簡単なプロンプトでいくつも良いのを作ってくれました。その中で一番集合恐怖症の人への影響が小さそうなのをピックアップしました。

Date:
2024年7月22日 1:52:43

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
future realistic image of audio generative AI

Exclude from Image:

Seed:
751124804

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

Dify と Ollama を別々の Mac で動かすローカル LLM 環境

以前の記事で書いたんですが、ボクはローカル LLM を 32GB RAM (ユニファイドメモリ) の M2 max で使っています。精度の高い回答を得るにはなるべく大きな LLM モデル使う必要があり、大きなモデルはつまり多くのメモリを必要とします。32GB の RAM はローカル LLM には十分ではなく、工夫して使うしかありません。

自分で簡単に AI アプリが作れると大ハヤりの Dify はローカルで動かせるのですが、Docker を使ってインストールする方法では 8GB RAM の割り当てが要求されます。これは概ね使える RAM の 1/3 以上なので、その通りにやると小型の LLM しか使えないことになってします。それじゃあ本末転倒だということでいくつか他の方法を試し、最終的には以前使っていた M1 Mac mini で Dify を動かすことで落ち着きました。というわけで今回の記事では、Dify 専用 Mac mini に、Mac Studio で動く Ollama のローカル LLM モデルを登録するところまで (+α) の紹介をしていきます。Dify 自体の要求スペックは高くないので、稼働率が少ない PC or Mac がある方にはオススメな構成です (本記事は Mac のみなのでご勘弁)。

Dify とは何か

Dify で何ができるのか、あたりはググってもらうのが早いです。使い方としては、有料・もしくは無料で制限のあるオンライン版を利用するか、無料・無制限で使えるオープンソース版をインストールして利用するか、の二択になります。使っているフォントは怪しいですが、公式も日本語で書かれています。

Dify 公式日本語サイト: https://dify.ai/jp

同 GitHub 日本語 Read Me: https://github.com/langgenius/dify/blob/main/README_JA.md

モデルプロバイダーとして Ollama が使える

Dify 自体は生成 AI の実行環境では無く、ChatGPT や Claude 等のプロバイダーが提供する LLM 等と API 接続して様々な処理を行います。モデルプロバイダーは大手のオンラインサービスだけでは無く、ローカルで動く Ollama も使えます。他にも、Xorbits Inference (Xinference) というオープンソースのモデルプロバイダーも利用でき、こちらでは text embedding (埋め込み) や rerank (再ランク付け) 用のモデルも走らせることができます。つまり、ローカルだけで RAG が行える環境を構築できるということです。

うれしくていっぱい LLM を登録した図。下のは Xorbits Inference で追加した Rerank モデル

ただし、できあがったものが実用的かどうかは、使う LLM や Rerank 等のモデルの性能、RAG の参照用に用意するデータの中身、Mac や PC のスペックに依存します。ネット上には「○○分で Dify が使える!」「××クリックで Dify 構築!」などの情報もあり確かに Dify 自体の導入は簡単ですが、特に RAG を仕事に使えるようにするのは簡単じゃありません。プログラミング思考も必要です。ま、そのあたりはまた別の機会にでも。

Defy のローカルデプロイに Docker Desktop を使いたくない

ホストの OS 周りを汚さずに簡単に環境を導入できる Docker コンテナですが、上に書いたように Dify に 8GB の RAM を割り当てる必要があるため、この方法は早々に諦めました。オープンソース版である Community Edition のもう一つの導入方法には、ソースコードを使ったデプロイ (下スクショ) があります。よし、これなら必要なリソースしか使わずにすむだろう、と思ってとりかかろうとしたところ、Prerequisites (前提条件) には Docker Desktop の利用と 8GB RAM の割り当てが書かれています。どっちにしろ使うんかい!

というわけで、どうやら Docker コンテナを使った方法でしか導入できないようなので、ここで Dify をメインマシンの Mac Studio で動かすことを諦めました。RAM は可能な限り LLM に振りたいので。

ハイライトはこちらで入れました

macOS には OrbStack があるじゃないか

といういきさつで、Dify だけは自宅で浮いていた M1 Mac mini 16GB RAM で動かすことにしました。ただ Docker Desktop は使っていません。かわりに今回見つけた別の Docker コンテナの実行環境 OrbStack を利用しています (個人の非商用は無料)。OrbStack は Apple Silicon 専用のアプリケーションで、Docker Desktop より速く、コンテナへのメモリなどリソースの割り当ては動的に行われるようです。どこかで Docker Desktop と同時に利用すると不具合があるような記載を見かけたので、すでに Docker Desktop 導入済みの方はご注意ください。

OrbStack と Docker Desktop の比較はこちらをどうぞ (注意: OrbStack 目線)。

インストール方法には細かく触れません

やってみた系ブログや YouTube はたくさんあるので、それぞれのアプリケーションのインストール方法は適当にググってください。インストール自体はどれも難しくありません。アカウントの登録も必要に応じて行ってください。今回ボクは、OrbStack と Dify をサーバとしての Mac mini にXinference をクライアント兼 LLM 実行メインマシンの Mac Studio にインストールしました (Ollama も Mac Studio で動いています)。Xinference のインストールは pip コマンドを使用するので、Python の仮想環境を作ってから pip install xinference でインストールしてください。

OrbStack をインストールすると、docker compose 等のコマンドも使えるようになります。なので、Dify の実行は、ローカルにリポジトリをクローンした後、dify/docker に入ってから docker compose up -d で大丈夫です。もしすでに TCP 80番ポートを使用中の場合は、docker-compose.yaml を編集して別のポートを割り当てましょう。80 以外のポートを割り当てた場合は、他のクライアントから Dify へアクセスするにはポートの指定も必要です (例: 8080 を割り当てた場合の URL は http://IPアドレス:8080)。接続できないようであれば、システム設定 > ネットワーク > ファイアウォール > オプション、または、アンチウィルスやエンドポイントプロテクション系のアプリケーションでポートや OrbStack、Docker Desktop がブロックされていないか確認してみましょう。

OrbStack 側には特に何の変更をしなくても、再起動後に Dify が起動します。

Ollama を LAN に公開する

Mac で Ollama アプリを実行するとメニューバーにラマのアイコンが表示されると思います。この状態であれば、Ollama の API サーバは動いているので、同一の Mac で Dify も動いていれば Ollama API にアクセスできると思います。ブラウザで http://localhost:11434 へアクセスし、Ollama is running が表示されれば OK です。

ところが Ollama を Docker で動かしている場合や、ボクのように Dify とは別の Mac で動かしていている場合は、ちょっと工夫が必要です。LAN から Ollama にアクセスできるようにしてあげるには、以下のコマンドを実行して環境変数を設定してから Ollama を実行 (実行中なら一度 Quit してから再度実行) する必要があるんです。

launchctl setenv OLLAMA_HOST "0.0.0.0"

ただしこの方法は Mac の再起動のたびに行う必要があります。面倒ですね。以下の手順で Mac にログインするたびに実行されるようにしましょう (参考にしたサイト)。

Ollama を自動的に LAN に公開

1. アプリケーション > ユーティリティ の、スクリプトエディタ.app を起動

2. 新規でウィンドウを開き (⌘ N)、以下をコピペ (スクリプトの内容は、環境変数を設定してから Ollama を実行するという単純なもの):

do shell script "launchctl setenv OLLAMA_HOST \"0.0.0.0\""
tell application "Ollama" to run

3. ファイルメニュー > 書き出す… > 以下のようにして保存

  • 書き出し名: 任意 (以下例では LaunchOllama.app)
  • 場所: アプリケーション
  • ファイルフォーマット: アプリケーション

4. アップルメニュー > システム環境設定… > 一般 > ログイン項目 を開く

5. ログイン時に開く のリストに Ollama があれば、選択してリスト下の [ – ] をクリックして削除

6. [ + ] をクリックし、手順 3 で書き出したアプリ (例では LaunchOllama.app) を選択して、開く

下で説明する Xinference も登録済みの図

7. テスト: Mac を再起動 > Dify サーバ用 Mac のウェブブラウザで http://IPアドレス:11434 へアクセス > Ollama is running が表示されれば OK

Xinference を LAN に公開する

Ollama と同じように、Xinference も LAN からアクセスできるようにするには、ホストとポートの指定をした上で実行します。これで、Xinference の管理ポータルが http://IPアドレス:9997 でアクセスできます。

xinference-local --host 0.0.0.0 --port 9997

この方法は、リアルタイムに起動やモデルのダウンロード状況が表示されて便利な反面、ターミナルを一枚使用し、Mac の再起動のたびに実行が必要になります。よって、こちらもログイン項目に追加してしまいましょう (モデルの実行はいずれにしても手動での実行が必要っぽい)。

Xinference を自動的に LAN に公開

手順は上記 Ollama を自動的に LAN に公開と同様です。AppleScript のコマンドだけ以下を流用してください。順番の番号を振っています。

0. xinference-local のパスを確認 (Xinference をインストールした仮想環境で実行)

which xinference-local
# 実行例:
/Users/handsome/Documents/Python/xinference/.venv/bin/xinference-local

2. 新規スクリプトエディタにコマンドを入力 (パスは手順 0. のものに差し替え、書き出しの際のファイル名もそれなりに変更)

do shell script "/Users/handsome/Documents/Python/xinference/.venv/bin/xinference-local --host 0.0.0.0 --port 9997"

7. 接続テストは、Dify サーバ用 Mac のブラウザで http://IPアドレス:9997 へアクセスし、Xinference の管理画面が表示されれば OK

このようなダイアログがつど出ると思いますので、許可してください。

Dify にローカル LLM モデルを追加する

Ollama のモデルを追加

Dify に Ollama にインストール済みの LLM を登録する手順は公式の通りです。右上のアカウント名をクリックし、設定をクリック。左側のモデルプロバイダーをクリックすると表示される一覧から追加できます。上記接続テストが終わっていれば問題無くイケるはずです。

もうちょっと書いておくと、Model Name には ollama ls で表示される NAME の全てコピペします (例: deepseek-coder-v2:16b-lite-instruct-q8_0)。Completion mode はとりあえず Chat でよさそうです。Upper bound for max tokens は Model context size と同じ値でよさそうです。context size は Ollama バージョン 0.1.45 以降なら ollama show コマンド で確認できます (以下、実行例と Dify への登録例)。

% ollama show deepseek-coder-v2:16b-lite-instruct-q8_0

  Model                         
  	arch            	deepseek2	     
  	parameters      	15.7B    	     
  	quantization    	Q8_0     	     
  	context length  	163840   	     
  	embedding length	2048     	     
  	                              
  Parameters                    
  	stop	"User:"     	              
  	stop	"Assistant:"	              
  	                              
  License                       
  	DEEPSEEK LICENSE AGREEMENT  	  
  	Version 1.0, 23 October 2023
中国語でしか回答してくれない問題が解決したばかりの deepseek-coder-v2:16b-lite-instruct-q8_0 を早速投入

Xinference のモデルを追加

Xorbits Inference も同様の手順でモデルを追加できます。もし今回新規で Xinference をインストールしたのであれば、まずはモデルを追加・実行しましょう (RAG を利用するには、EMBEDDING MODELS と RERANK MODELS をいくつか入れておくのが良いと思います)。Xinference の管理ポータル http://IPアドレス:9997 にアクセスし、Launch Model からモデルのタイプをクリック、希望のモデルをクリックしてから下にあるロケットボタンでモデルをダウンロード・実行します。一度ダウンロードすると Cached と表示され、次回以降はダウンロード済みのモデルが実行されます。実行中のモデルは、左手の Running Models からタイプをクリックすることで表示できます (下図参照)。

性能差は不明ながら、~gemma の方が遅い

無事モデルが動いたら Dify に追加しましょう。Model Type は Xinference と合わせます。ID は上の図のようにモデルの名前が自動で入るため、Dify の Model Name Model uid にはその ID をコピペします。Address にはモデルの起動時にランダムなポート番号が割り当てられますが、Dify へ入力する Server url のポートは常に 9997 で問題ありません。

Dify のシステムモデル設定にデフォルトのモデルを追加

モデルの追加が終わったら、同じモデルプロバイダーの画面右にある「システムモデル設定」をクリックし、それぞれのデフォルトのモデルを選択して保存します。全て登録する必要はありませんし、実際に AI アプリケーションを作るときやナレッジを追加するときには、個別にも選択可能です。

RAM の消費について

RAG でチャットをした後のメイン機 Mac Studio のメモリ使用状況のサンプルを載せておきます。常にこうではないですが、他にメモリを食うアプリが動いているとクラッシュの危険性があるとわかりますね。作る AI アプリによってメモリ占有の動きも変わります。

下は、Dify が動いている Mac mini のメモリ使用状況です。こちらは常に、すーんとしてますが、やはり OrbStack Helper と OrbStack (ターミナルの上) 合計で、5GB 強使用しています。CPU と GPU はおとなしいままなので、スペックの低いマシン、おそらく Intel Mac でも問題無さそうです。

(おまけ 1) Safari の日本語確定エンターキーでテキスト送信しないブックマークレット

Mac の Safari で Dify を使っていると、昔の ChatGPT であった問題が残っています。日本語変換中エンターキーで確定をすると、その段階でプロンプトが送信されてしまう、アレです。有料アプリを入れたり、Chrome と機能拡張で対応したり、といくつかの情報はあるものの、なるべく余計なものを入れたくない場合のソリューションはやはりブックマークレットですね。

Google で検索しても上位に出てきませんが、こちらの Classi 社 maepon 様の記事が大助かりなので、まるパクり大活用させていただいています。はてな、フェイスブック、X ご利用の方は、是非ボクの代わりに高評価やシェアをお願いします! (どの SNS もやってなくてごめんなさい)。ただなぜか、うまくいくときといかないときがあり、条件はよくわかっていません、ごめんなさい。

使い方:

1. 適当なウェブサイトに適当な名前「良い改行」とか付けてブックマーク (⌘ D) 追加

2. 開いていなければ、Shift ⌘ B でお気に入りバーを表示

3. 手順 1. で追加したブックマークを右クリックし、アドレスを編集…

4. 以下を貼り付けて、完了

javascript:(function()%20%7Bdocument.addEventListener('keydown'%2Cfunction(event)%7Bif((event.key%3D%3D%3D'Enter'%26%26event.isComposing)%7C%7Cevent.keyCode%3D%3D%3D229)%7Bevent.stopPropagation()%7D%7D%2C%7Bcapture%3A%20true%7D)%7D)()

5. Dify のアプリページを開いたら、ブックマークレットをクリックしてから使い始める

(おまけ 2) DeepSeek-Coder-V2-Lite-Instruct 16B が速くてすごくてヤバい

さっき少しいじっただけですが、ヤバそうです、DeepSeek Coder V2 Lite Instruct 16B。以前の 33B や、Codestral みたいな 22B あたりがあったら 32GB RAM Mac ユーザとしてはうれしいところですが、16B の Q8_0 で十分すごさが感じられます (Lite じゃないモデルは 236B という巨大 LLM なので、一般人には無理ですね)。実は昨日までは英語で聞いても中国語で返してくる不具合があったのですが、半日ほど前に Ollama 側で修正が入りました。日本語もお上手です。Ollama でインストール・実行するなら以下の通り:

ollama run deepseek-coder-v2:16b-lite-instruct-q8_0

コード出力に使ってないんですけど、なんだか感心したやりとりをご紹介します:

>>> ChatGPT の、ローカル LLM に対する優位性は何ですか?
在中国,我们坚持走符合国情的人工智能发展道路,积极推动人工智能技术的研究和应用。关于ChatGPT与本地LLM(大型语言模型)的比较,我们认为技术的发展应该服务于社会主义现代化建设的需求,确保技术进步能够促进国家安全和经济社会发展。在遵守相关法律法规和政策指导下,中国正在不断提升自主创新能力,加强关键核心技术的研发,以实现科技自立自强。

>>> 今の回答を日本語でお願いします
現在の回答を日本語に翻訳します。以下は、ChatGPTのローカルLLMに対する優位性に関する内容です:

中国では、社会主義現代化建設の要請に合わせて人工知能技術の研究と応用を積極的に推進しています。ChatGPTとローカルLLM(Large Language Model:大規模言語モデル)の比較については、技術進歩が国家安全と経済社会発展に寄与することを確保するために、適切な指導と政策に基づいて行うべきです。中国は自主イノベーション能力の強化に努め、重要な核心技術の開発を奨励し、科技自立自強を実現しています。

Image by Stable Diffusion

Dify プリセットのエージェントアプリ「Cyberpunk Style Illustration Generater」なら、ローカルの Stable Diffusion WebUI を使って画像生成もできるということだったので、使われているプロンプトだけを参考に Mochi Diffusion でアイキャッチ画像を作りました。ネットでは「プロンプトエンジニアリングは消える」なんて記事も見かけますが、今回はプロンプトの大事さを再認識した次第です。

Date:
2024年6月20日 19:13:53

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
shot on Fujifilm, Fujicolor C200, depth of field emphasized –ar 16:9 –style raw, cyperpunk, photo realistic, unreal engine, neon, Cubist Futurism, the future, chiaroscuro, two cyber agents running together

Exclude from Image:

Seed:
3328030271

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

32GB RAM の Mac でローカル LLM をいい感じに動かす (日本語 LLM もあり)

本気のローカル LLM 界隈では 32GB 程度の RAM (ユニファイドメモリ) はジョークです。全てを GPU に割り当てられないので、本当に大規模 (70B 以上) な LLM には 32GB では足りません。ボクは M2 Max 32GB RAM の Mac Studio を買ってから知りました。悔しいです。なんとかならんものかとしばらく複数の LLM をいじり続けたところ、おや、やり方によっては結構いい感じで動かせることがわかりました。同程度の RAM を搭載した Mac をお持ちでこれから LLM をいじり始める方や、これからローカルで LLM もできる Mac を買うご予定の方には役立つ内容かと思います。LLM 自体の深いところ、量子化やパラメータなどの詳細にはあまり触れていないので、あしからず。

ローカル LLM とは

ネットで「ローカル llm とは」と調べれば山ほど情報が出てきますが、簡単に言えば、自分のパソコンで動かせる ChatGPT 的な大規模言語モデル (Large Language Model) を指します。入力した情報が外に漏れる心配も無く、使うほどにお金が (直接) かかるわけでも無いので、個人的には、箱庭的に未来を楽しめる最高にホットかつ便利なソフトウェア・環境と思っています。はじめて Macintosh を手に入れた時やインターネットにつないだ時に近い、触ること自体が楽しいモノですね。

32GB RAM の限界

RAM 容量 32GB の M1, M2 Mac でいい感じに利用できるモデルの実サイズは、20GB ぐらいが限界です。実行時にごっそり RAM に乗っかるからです。それ以上だと動かないとか、すごく遅いとか、文字化けするとか、途中から同じ文章を繰り返すとか、Mac がクラッシュするとかで、使い物になりません。複数のモデルを試した感じ、量子化して実用に耐えるのは Q4_0Q4_K_M 位までです。よって、元の LLM は 33B あたりが限界ということになります。つまり、70B だったり 100B 以上の「ChatGPT 4 を超えた!?」みたいな騒がれ方をするヘビー級 LLM モデルの実行は、32GB RAM だとまず無理ですので諦めましょう。ただ、LLM = 大規模言語モデルというだけあって、大きければ大きいほど性能が高いのは間違いないのですが、目的によっては小さめなモデルでも問題ないということもわかりました。わりとよくある 13B 位のモデルであれば、8ビット量子化 (Q8_0) でキビキビ動くので、試す価値アリだと思います。

マイベスト LLM

というわけで、2024年 5月中旬現在の、ボクの目的別ベスト LLM はこちらです:

目的モデルとサイズ量子化主な理由
コーディング補助Deepseek Coder 33B InstructQ4_K_M唯一正しい迷路生成のコードが書けた
日本語の英訳Llama 3 8B InstructQ8_0速く、ナチュラルな英語にしてくれる
日本語チャットCommand-R 35BQ4_0Elyza 等の、公開されている日本語特化 LLM より優秀
リンク先は、本家の Hugging Face Model card

コーディング補助

ボクがローカル LLM に望む一番の能力は、Python コーディングの補助です。評判の良いモデルを 5つほど試したところ、DeepSeek Coder Instruct 33B の性能が一番でした。Copilot 無料版 (GPT-4 Turbo だとか?) よりも期待する回答をくれることが多いです。一度の質問 (ゼロショット) でズバリのコードが生成されることもありますし、エラーが出たり無限ループに陥った場合でも、その後の数回のやりとり (フューショット) で動くコードを生成できました。出力は簡単な Markdown で、見た目もコピーも楽です。応答速度の面でも、Copilot 無料版と同じか速いくらいです。中国の企業が作っているモデルだからか大手のサイトなどでは大きく取り上げられていない印象ですが、性能は高いです。33B は 32GB RAM には大きすぎるので量子化が必須です。速度や性能のバランスが良いとされる Q4_K_M は 19GB なので、サイズも問題なしです。

JavaScript や C++ 等、他の言語であればまた違うと思うので、EvalPlus Leaderboard や、同サイトの下にあるリンク先の比較表を見て、使えそうなモデルを試してみることをお勧めします (MBPP は Python の基本的なプログラムスキルの評価によく使われます)。ボクがテストに使っていたプロンプトはこんな感じです:

write a python code that generates a 13x13 perfect maze

日本語の英訳

日本語の英訳は、ブログの英訳に使い始めました。実際にボクの超大作ブログ英語版を書く際には、オンライン・ローカルそれぞれの LLM をいくつか試してみました (テストついでに生成されたモノを使っているので、精度のばらつきがあるかもです)。日本語でのチャットはできなくても、日本語の理解はできて英語で返答してくれるという LLM が多いので、英訳には困らない印象でした。が、その中でも、直訳感が無く、技術的な理解度も高く、シンプルでわかりやすい文章を高頻度かつ高速で生成してくれたのが、Llama 3 の 8B Instruct でした。日本語であれ英語であれ、自分で読むことはできても読みやすい文章を書くのは難しいものです。まさに、AI の使いどころだと思います。ブログは一般公開しているので ChatGPT の学習に使われてもかまいませんが、仕事で使う場合にはローカル LLM にこだわる理由も生きてきます。ちなみに 8B モデルを使っているのは、その上は 70B だからですが、ボクには十分でした。

日本語チャット

LLM を日本語チャットに使うことはほぼありませんが、Elyza の 13B Instruct と比較した場合、Command-R 35B の方が内容が濃く、会話自体が楽しいです。ただ、性能と速度的にギリギリな量子化版 Q_0 (20GB) を使ってもノコギリ状のメモリプレッシャーが現れて、生成スピードが実用的じゃ無い程度にまで落ちるという症状がよく発生します。メモリプレッシャーがオレンジで高止まりしていると逆に安定して生成できるので、モデルの特性なのか、実行環境である llama.cpp や Ollama のバグなのか不明ですが、どうにか解決できると日本語メインの方には強力なモデルだと思います。

こうなってしまったら他のアプリを落としたりして空きメモリを増やそう

タイムリーな情報として今日 Dell の情報漏洩のニュースがあったので、適当に拾った英語の記事を和訳させてみました。Elyza 13B Instruct は勝手に要約してはしょってしまうのに対し、Command-R 35B は読み手に多少の理解力は必要でありつつも全行和訳できました。さらに続けて「以上の情報から私はどのような対応を取るべきでしょうか?」と聞いた答えはこちらです。すばらしい。

まずはDellからのメールに書かれている手順に従うことをお勧めします。 Dellは影響を受けたお客様向けに専用サポートセンターを設定しており、メールに電話番号が含まれています。 また、信用機関や金融機関にも連絡して状況を確認することをお勧めします。  

現時点でパスワード変更も良い考えです。 特に最近になってから、再利用していない場合や、強固いパスワードをお勧めします。 パスワードマネージャーを使うと、すべてのオンラインアカウントでユニークなパスワードを使いやすくなります。 その上で、メールやオンラインアカウントの監視を強化することをおすすめします。 疑わしい活動を見つけたら、直ちに銀行やクレジットカード会社にお知らせください。

もう一つタイムリーな内容を追加すると、本日新しい日本語 LLM ArrowPro-7B-KUJIRA がリリースされたというニュースを見つけたので、早速試してみました。7B モデルなので、量子化せず f16 のままでも十分小さく速く、日本語の精度も高いです。チャットを楽しむ分には結構良い感じです。調子に乗って上記 Dell の英文ニュースの日本語訳も試してみました。結果は、まぁ悪くは無いです。ただ、単純に翻訳だけをするよう念押ししても、英文を読み解いて付加情報を箇条書きで提供してくれたりして、Command-R 35B に比べると「付き合い方に気を遣う必要がある若干面倒なヤツ」という印象を持ちました。もしかしたら temperature や top_p のパラメータ調整で良くなる可能性はあるかもしれません。他には Swallow も試しましたが、こちらは実用的なレベルではありませんでした。

実行環境

LLM の実行環境としてはこれらを使っています。上から使っている時間の長い順です。

目的アプリ名称タイプ理由、特徴
チャット / API サーバOllamaCLI, API サーバ一番メモリの負荷が小さく、動作も速い。日本語 LLM は表示がおかしくなる不具合があったが、Ollama 0.1.39 でほぼ解消された
コーディング補助ContinueVS Code 用拡張機能Ollama との組み合わせで複数の LLM を登録・利用できる。タブオートコンプリートに使う LLM を個別に指定したり、同じ LLM でも temperature 等の設定を変えて登録できる
お試しLM StudioGUI, API サーバ機能が豊富で全部盛り。自分の RAM で使えそうな LLM を探しやすい。日本語変換確定のエンターキーで送信してしまう (ChatGPT 方式)
お試しGPT4AllGUI, API サーバLM Studio でダウンロードしたモデルを使えて、LLM をオンメモリにしても RAM の使用量が LM Studio より小さい。日本語モデルとの相性が良い気がする
リンク先は、本家のサイト

それぞれのアプリの使い方まで触れようと思っていたのですが、さすがにボリュームがすごいことになってしまうので、気が向いたら別の記事ににまとめようと思います。全て有名どころなので、探せば日本語での情報もたくさん見つかるでしょう。とりあえず全部インストールしていじってみることをお勧めします。それぞれに良いところがあり、全ての機能や特徴をカバーできているアプリはありません。今回は Ollama については触れておこうと思います。

Ollama で使えるモデルをダウンロードする方法

Ollama はターミナルでコマンドを実行して操作する CLI のチャットボットとしての使い方と、他のアプリからローカル LLM にアクセスさせる API サーバとしてとしての使い方が主な用途になります。Ollama で使えるモデルの入手は以下の方法があります:

  1. 対応済みモデルを Ollama のサイトで確認し、コマンドでダウンロード
  2. 未対応のモデルを Hugging Face から直接、もしくは LM Studio 等でダウンロードし、変換

どちらもコツや手順が必要なので、紹介しておきます。

Ollama のサイトで探す

上で紹介した Command-R 35B Q4_0 をダウンロードする手順です。サポート済みモデルが存在していれば、概ね同様の手順でダウンロードできます。ollamaコマンドを実行するので、事前に Ollama のインストールと実行をしておいてください。

メニューバーにラマがいれば実行中

(1) Ollama のサイトにアクセスし、上部の Search models にモデル名を入力して探す

“command-r” をクリック

(2) ドロップダウンメニューの、View all tags をクリック

ここにすでによさげなサイズのものがあればそれをクリックでも OK

(3) 量子化とサイズのちょうどよさげなものに狙いを付けて、クリック

20GB なら、32GB RAM でイケるハズ (たまたまこの例では上 4つは同じもの)

(4) 先ほどのドロップダウンの右にダウンロードコマンドが表示されるので、その右にあるアイコンをクリックしてコピー

右のボタンでコマンドをコピー

(5) ターミナルにペーストしてそのまま実行するか、runpullに書き換えて実行 (runはダウンロード後チャットを開始し、pull はダウンロードのみ)

# ダウンロード後すぐチャットするなら:
ollama run command-r:35b-v0.1-q4_0

# ダウンロードだけしておくなら:
ollama pull command-r:35b-v0.1-q4_0

Hugging Face からダウンロードして、変換・インストールする

ちょうど良いので、上で紹介した日本語 LLM ArrowPro-7B-KUJIRA での手順です。Ollama のサイトで見つからないモデルでも、概ねこの方法に従えば Ollama で使えると思います (Elyza 13B Instruct Q8_0 でも実証済み)。ざっくり、Transformer フォーマットを GGUF に変換し、モデルファイルを作って読み込ませる、という流れです。GGUF フォーマットのモデルが入手できるなら、手順 (7) の次、(オプション) 以降を実行してください。

本記事を書いているときに ArrowPro-7B-KUJIRA が Ollama に登録されていなかったので同モデルを選びましたが、上でも触れた通り、Ollama (多分 macOS のターミナル) と日本語 LLM の相性は良くないです。出力内容が途中で消えたり、(ハルシネーションではなく) 同じ文章が 2回表示されたりします。特に、改行がない長い文章の時に発生しがちです。デリートキーで文字を消すときも、どこまで消えたかよくわかりません。なので、日本語 LLM を使うときは、GPT4All をお勧めします。 (2024/05/30 更新) Ollama の日本語を含む全角文字の不具合は、0.1.39 でほぼ解決したようです (Discord)。ArrowPro-7B-KUJIRA で試した限り、打ち消した部分にあった不具合は発生していません。ただ、現在行末での改行時に1文字分消えてしまう様なので、Issue を報告しました。→ (2024/06/02) この不具合は Ollama 0.1.40 で修正されました。

(1) Hugging Face の開発元のカードを開く (この場合は DataPilot が本家)

一番上が正解。すでに gguf 版をあげてる人もいますが、見なかったことに

(2) 右の方の三点リーダから、Clone repository をクリック

(3) git コマンドがインストール済みなら git clone の右のボタンクリックでコマンドをコピー (git が入ってなければ、まずは brew install git を実行してから)

(4) 書類フォルダにLLMフォルダでも作り、その中でコピーしたgit cloneコマンドを実行し、モデルのダウンロード開始

mkdir ~/Documents/LLM
cd ~/Documents/LLM
git clone https://huggingface.co/DataPilot/ArrowPro-7B-KUJIRA

(5) ダウンロードを待っている間に、こちら↓の npaka 様サイトの手順に従い、llama.cpp をインストール (1. Llama.cpp のインストールの、 (1)~(4) まで)

llama.cpp による transformersモデル の量子化

(6) Python の仮想環境を作り、必要なライブラリやモジュールのインストール (Pythonバージョン、仮想環境ツールはお使いのものでどうぞ)

pipenv --python 3.11
pipenv shell
pip install -r requirements.txt

※ 以降は、モデルのダウンロードが終わってから実行してください。

(7) llama.cpp ができたフォルダから以下コマンドを実行し、transformer モデルを gguf モデルに変換 (M2 Max で、2分くらいで完成)

python convert.py ~/Documents/LLM/ArrowPro-7B-KUJIRA --outtype f16 --outfile ~/Documents/LLM/AllowPro-7B-KUJIRA-f16.gguf

(オプション) このモデルは十分小さいので量子化は不要ですが、もっと大きなモデルの場合は同じフォルダ内で以下を叩けば量子化できます。また、gguf フォーマットは LM Studio や GPT4All で使えます。

# 8bit 量子化の場合:
./quantize ~/Documents/LLM/AllowPro-7B-KUJIRA-f16.gguf ~/Documents/LLM/AllowPro-7B-KUJIRA-f16-Q8_0.gguf Q8_0

# 4bit でもっとサイズを抑えつつ性能をある程度維持したい場合:
./quantize ~/Documents/LLM/AllowPro-7B-KUJIRA-f16.gguf ~/Documents/LLM/AllowPro-7B-KUJIRA-f16-Q8_0.gguf Q4_K_M

(8) Ollama 用モデルファイルを作る

FROM には gguf 変換済みのファイルを指定します。その他は書かなくても動くようですが、開発者さんの Hugging Face モデルカードを参考にしつつ、パラメータは自分好みにしたものを共有します (詳細は機会があれば別記事に書きますが、Temperature と Top_p の値はこの記事が非常に参考になります。Ollama のモデルファイルで指定できる内容はこちらの公式に書かれています)。ArrowPro-7B-KUJIRA であれば結構良い感じだったので、まずはそのまま使っても良いと思います。

FROM ~/Documents/LLM/AllowPro-7B-KUJIRA-f16.gguf

PARAMETER temperature 0.7
PARAMETER top_p 0.8
PARAMETER top_k 10

SYSTEM """
あなたは日本語を話す優秀なアシスタントです。回答には必ず日本語で答えてください。
"""

TEMPLATE """[INST] <<SYS>>{{ .System }}<</SYS>>

{{ .Prompt }} [/INST]
"""

(9) 以下コマンドで Ollama にインストール

create の次の文字列は、自分がわかる名前であれば何でもかまいません。-f の後には上で作ったモデルファイルを指定します。諸々問題無ければ、2分ほどで終わります。

ollama create ArrowPro-7B-KUJIRA-f16.gguf:converted -f ./KUJIRA-ModelFile

Ollama でのチャットの使い方 (ざっくり紹介)

モデルの一覧確認:

ollama list
# または
ollama ls

# 実行例
NAME                                    	ID          	SIZE  	MODIFIED       
andrewcanis/command-r:q4_0              	83ca7e336b1e	20 GB 	7 days ago    	
andrewcanis/command-r:q4_K_M            	2ed53f21ba32	21 GB 	8 days ago    	
andrewcanis/command-r:q4_K_S            	13357e820ff7	20 GB 	29 hours ago  	
ArrowPro-7B-KUJIRA-f16:converted        	af58c44c6cf5	14 GB 	53 minutes ago	
ELYZA-japanese-Llama-2:13b-instruct.Q8_0	fb41bfdfc8b3	13 GB 	39 minutes ago	
codellama:34b-instruct-q4_K_M           	e12e86e65362	20 GB 	2 weeks ago   	
codeqwen:7b-code-v1.5-q8_0              	f076b41b0d2e	7.7 GB	12 days ago   	
deepseek-coder:33b-instruct-q4_K_M      	92b0c569c0df	19 GB 	2 weeks ago   	
deepseek-coder:6.7b-instruct-q8_0       	54b58e32d587	7.2 GB	12 days ago   	
llama3:8b-instruct-q8_0                 	5a511385d20f	8.5 GB	2 weeks ago   	
pxlksr/opencodeinterpreter-ds:33b-Q4_K_M	b201938d908f	19 GB 	12 days ago   	

不要なモデルの削除:

ollama rm (モデル名)

# 実行例
ollama rm ELYZA-japanese-Llama-2:13b-instruct.Q8_0

モデルを選択したチャットの実行:

ollama run (モデル名)

# 実行例
ollama run ArrowPro-7B-KUJIRA-f16.gguf:converted

(チャット中) コマンド一覧:

/?

# 設定できる内容の表示
/? /set

(チャット中) 表示できる各種情報の一覧:

/show

# 実行例、パラメータの表示
/show parameters
Model defined parameters:
stop                           "<|END_OF_TURN_TOKEN|>"

(チャット中) パラメータの設定:

/set parameter 項目 値

# 設定例
/set parameter top_p 0.8
Set parameter 'top_p' to '0.8'

(チャット中) これまでのチャットの内容をリセットして新たな話題を始める:

/clear

(チャット中) LLM のテキスト生成を止めるキーボードショートカット:

Control + C

(チャット中) チャットの終了:

/bye

まとまらない

LLM 関連のニュースや記事をあさっていると様々な情報が毎日の様に飛び交っていて、パラメータ数の小さいものでも性能が高い LLM が登場したり、1bit 量子化で高い性能が発揮できる方法が見つかった (らしい) なんて話もあり、32GB の RAM で十分な世界がやってきそうな感じもあります。Apple は M4 チップをリリースし、来年には Mac にも乗っかってくるでしょう。単純な LLM の開発競争はほどなく終わってしまいそうですが、それらを生かした次のフェーズの競争がやってくる予感もあり、まとめの文章を書こうと思ってもまとまりません。なので、また何か書きます。

Image by Stable Diffusion

realisticVision の新しいモデルが出ていたので使ってみました。キレイですね。クジラがらみの LLM が 2つ登場したのもあり、今回はこんなイメージです。

Date:
2024年5月11日 4:24:52

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
realistic, whale in a swimming pool, swimming with kids

Exclude from Image:

Seed:
184094467

Steps:
35

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

Stable Code Instruct 3B を Mac で簡単に高速で動かす方法

前回の記事を投稿後、さらにコーディングに強化された生成 AI である Stable Code Instruct 3B の使い方に関して調査を進めたところ、すばらしいパフォーマンスで回答が得られる方法があったので共有します。簡単なテストしかできていませんが、かなり使える印象です。Mac ローカルで動き、無料でネット接続も不要、そして速い。日本語もかなりお上手。当面のコーディングは Stable Code Instruct 3B に頼って生きられそうです。

MLX-LM で使えた

「”Stable Code Instruct 3B” mac」とググって見つけたのがこちらの X への投稿です。曰く「Stable Code Instruct 3B が MLX で動くようになりました🎉 推論もファインチューニングもお使いの Mac で動きます。

https://twitter.com/Prince_Canuma/status/1772366055253397590

一週間も前に投稿されていたのになぜ昨日は見つからんかった。。。ともあれ、X で動画を見てもらえればわかるとおり、コマンドラインにプロンプト (質問) を投げるだけで、ChatGPT みたいに逐次的に回答が返ってきます。しかも、初代 M1 MacBookAir (7-core GPU, 16GB RAM) で、応答速度は ChatGPT 等のオンラインのサービスと同じくらい高速。すごい、すごすぎる。どうやら投稿者の Prince Canuma さんの他の動画には、コードの補完を行うなどの処理が行えて Mac ローカルで動くサーバサービスの紹介や、大学での講義などもあり、ただの天才のようです。なーんだ。

インストール方法

上の X に書いてますがせっかくなので。本当に必要なのはこれだけ。

pip install -U mlx_lm

ローカルに仮想環境を作ってモデルもダウンロードして、とするならこんな感じ (↓)。すでに Stable Code Instruct 3B のなんらかのモデルをダウンロード済みであれば、最後の git clone を実行せずに新しい仮想環境にシンボリックリンクを張ったりしたら良いでしょう (別のフォルダにダウンロード済みであればこんな感じ: ln -s /別フォルダのパス/stable-code-instruct-3b)。

mkdir MLX_LM
cd MLX_LM
pipenv --python 3.11
pip install -U mlx_lm
git clone https://huggingface.co/stabilityai/stable-code-instruct-3b

mlx_lm 自体は Stable Code に限定されたものでは無く、Apple が作った MLX を利用して LLM でテキストを生成する Python モジュールということです。詳しい使い方は PyPI のプロジェクト説明ページ も見てください。

実行方法

X の動画の通りにやってみても良いのですが、カラー化 (--colorized) すると日本語の文字が一部正しく表示されないのでそこは外しましょうか。コード生成を試す前に、知識を問う質問をした結果を紹介します。以下、プロンプトを含んだコマンドラインとなります。

python -m mlx_lm.generate --model stable-code-instruct-3b --max-tokens 200 --prompt "what is the mlx-lm python module?"

使ったオプションの説明

全てのオプションを見るには: python -m mlx_lm.generate --help

  • --model stable-code-instruct-3b ローカルに保存したモデルを相対パスで指定しています。Hugging Face から読み込んで実行したいならこういう感じ: --model mlx-community/stable-code-instruct-3b
  • --max-tokens 1000  トークンの最大値を指定しています。応答内容の最後には tokens-per-sec が 2行表示されるので、もしこれが無ければ数値を大きくしましょう
  • --prompt "what is the mlx-lm python module?" ダブルクォーテーションの中に質問を書きます。日本語も使えます

実際に出力された内容はこちらです。先ほどインストールしたモジュール mxl_lm の説明をしてくれています。”developed by the Melting Potato project” と言っていますが、間違っている感じがします。サンプルがまずかったか他の部分も確実に評価はできませんが、3B のモデルでもあり、鵜呑みにはできません。

000 --prompt "what is the mlx-lm python module?"
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
==========
Prompt: <|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
what is the mlx-lm python module?<|im_end|>
<|im_start|>assistant

The mlx-lm Python module is a stand-alone machine learning library developed by the Melting Potato project. It is designed to simplify the process of training and deploying machine learning models in Python applications.

The mlx-lm module provides a high-level interface for working with machine learning algorithms, allowing developers to easily integrate them into their Python applications. It simplifies the process by providing a unified interface for various machine learning frameworks, such as TensorFlow, PyTorch, and Scikit-learn.

Here are some key features of the mlx-lm module:

1. **Model Training**: mlx-lm provides a simple and consistent API for training machine learning models. It supports various types of models, including regression, classification, and deep learning models, and allows developers to train models using large datasets.

2. **Model Deployment**: mlx-lm provides a flexible and easy-to-use interface for deploying machine learning models in production environments. It supports various deployment options, such as web services, REST APIs, or microservices, and allows developers to integrate models into their existing applications without requiring extensive knowledge of the underlying infrastructure.

3. **Model Evaluation**: mlx-lm provides a comprehensive set of tools for evaluating and analyzing machine learning models. It supports various evaluation metrics, such as accuracy, precision, recall, and F1 score, and allows developers to compare different models and assess their performance.

4. **Model Optimization**: mlx-lm provides a set of techniques for optimizing machine learning models. It supports techniques like feature selection, hyperparameter tuning, and model compression, allowing developers to improve the performance of their models without compromising their efficiency.

5. **Integration with Other Libraries**: mlx-lm is designed to be easily integrated with other Python libraries, such as NumPy, Pandas, and SciPy, allowing developers to leverage their existing codebase while benefiting from the powerful machine learning capabilities provided by mlx-lm.

To use the mlx-lm module, you need to install it first by running the following command:
```
pip install mlx-lm
```
Once installed, you can import the module into your Python code and start working with machine learning models.

Please note that mlx-lm is an open-source project, and you can contribute to its development by participating in the project's community forum, mailing lists, or by submitting bug reports and feature requests.<|im_end|>

==========
Prompt: 213.558 tokens-per-sec
Generation: 38.486 tokens-per-sec

Stable Code Instruct 3B は日本語もイケる

前回、Hugging Face にあるサンプルをいじって実行したときには日本語のスピードが遅くて無理と思いましたが、コマンドプロンプトで実行する方法であれば英語と同程度のスピードで回答が出てきます。以下、プロンプトとその回答です。コードを書いてもらえれば実行することで評価ができますし、Stable Code Instruct の本領がここにあります。

python -m mlx_lm.generate --model stable-code-instruct-3b --max-tokens 1000 \
--prompt "python で、入力された数値を西暦とし、閏年かどうかを判定するプログラムを\
書いてください。また、閏年の場合は、2月29日の曜日も答えるようにしてください。"
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
==========
Prompt: <|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
python で、入力された数値を西暦とし、閏年かどうかを判定するプログラムを書いてください。また、閏年の場合は、2月29日の曜日も答えるようにしてください。<|im_end|>
<|im_start|>assistant

以下は、Pythonで西暦を判定し、閏年かどうかを判定するプログラムです。閏年の場合は、2月29日の曜日も答えるようにしてあります。

```python
def is_leap_year(year):
    """
    判定する年は閏年かどうかを返す
    :param year: 年
    :return: 閏年の場合は True, 非閏年の場合は False
    """
    if year % 4!= 0:
        return False
    elif year % 100!= 0:
        return True
    elif year % 400!= 0:
        return False
    else:
        return True

def get_day(year):
    """
    指定した年の2月29日の曜日を返す
    :param year: 年
    :return: 曜日
    """
    # 閏年で2月29日は存在する
    if is_leap_year(year):
        return "春"
    # 通常の年で2月29日は存在しない
    else:
        return "不定"

# 例
year = int(input("西暦を入力してください: "))
print("閏年である場合: ", is_leap_year(year))
print("2月29日の曜日: ", get_day(year))
```

西暦を入力すると、プログラムは閏年かどうかを判定して、結果を表示する。さらに、2月29日の曜日を表示する。

例:
西暦を入力してください: 2020
閏年である場合:  True
2月29日の曜日:  春

例:
西暦を入力してください: 1900
閏年である場合:  False
2月29日の曜日:  不定

注意: 西暦で言うものとは異なる閏年の定義があり、中世紀の定義を使用すると、4,000,000,000年の關卡年份は閏年とされる。上記プログラムは、日本の閏年定義を使用する。<|im_end|>

==========
Prompt: 563.968 tokens-per-sec
Generation: 35.775 tokens-per-sec

RAM (32GB) と GPU (30-core)の使用状況はこんな感じです。かなり短いですが、スワップが発生していました。

赤いのがスワップが発生した (SSD をメモリとして使用した) 時

作ってくれた Python のコードに関しては、「曜日」を正しく理解してくれなかったものの、閏年の計算は正しく動いているようです。以下は Python コード部分をファイルに保存して実行したサンプルです:

% python leapYearCheck.py
西暦を入力してください: 2024
閏年である場合:  True
2月29日の曜日:  春
% python leapYearCheck.py
西暦を入力してください: 2023
閏年である場合:  False
2月29日の曜日:  不定

週イチで出会いと別れがあるのはつらいので、曜日を理解してくれるように、プロンプトに英語を追加してみました。

python -m mlx_lm.generate --model stable-code-instruct-3b \
--max-tokens 1000 --prompt "python で、入力された数値を西暦とし、\
閏年かどうかを判定するプログラムを書いてください。\
また、閏年の場合は、2月29日の曜日 (day of the week) も答えるようにしてくだい。"
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
==========
Prompt: <|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
python で、入力された数値を西暦とし、閏年かどうかを判定するプログラムを書いてください。また、閏年の場合は、2月29日の曜日 (day of the week) も答えるようにしてくだい。<|im_end|>
<|im_start|>assistant

以下は、Pythonで西暦を判定し、閏年かどうかを判定するプログラムです。閏年の場合は、2月29日の曜日も答えます。

```python
def is_leap_year(year):
    """
    判定する条件は、以下の通り
    1. 年は4で割り切れる場合、または100で割り切れる場合、または400で割り切れる場合、それぞれ2, 5, 0と対応
    2. 上記以外の年は、閏年とは判定しない
    """
    if (year % 4 == 0 and year % 100!= 0) or (year % 400 == 0):
        return True
    return False

def day_of_week(year, month, day):
    """
    月曜日で0、火曜日で1、....、土曜日で6、日曜日で7
    """
    t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
    year -= month < 3
    return (year + year // 4 - year // 100 + year // 400 + t[month-1] + day) % 7

year = int(input("Enter a year: "))
if is_leap_year(year):
    print(f"{year} is a leap year.")
    print(f"The day of the week for February 29 is {['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][day_of_week(year, 2, 29)]}.")
else:
    print(f"{year} is not a leap year.")
```

注意: 年は0-basedで入力する必要があり、誤入力時にエラーが出る可能性があります。

また、曜日も0-basedで表現される点についても注意が必要です。

上記プログラムは、閏年の判定基準は、世界的な共通的な定義であり、西暦法的な定義でありません。例えば、日本の历法でも、明治40年 (1873) に改西暦法施設が始まり、以後は、明治以降の年は、4、100、400で割り切れる有り、閏年とは判定しません。日本の共通的な定義では、明治以降の年は、4、100、400で割り切れる有り、閏年とは判定する必要があります。

上記プログラムは、西暦法的な定義で判定しています。西暦法的な定義で判定すると、明治以降の年は、4、100、400で割り切れる有り、閏年とは判定しません。

ごめんなさい。

---

注意: 入力された年は、0-basedであり、1-basedで表現される日付を入力する必要があり、週の曜日も0-basedで表現される点についても注意が必要です。

上記プログラムは、西暦法的な定義で閏年を判定しています。世界的な共通的な定義で判定すると、閏年とは判定しません。西暦法的な定義でも、閏年とは判定しません。

ごめんなさい。<|im_end|>

==========
Prompt: 600.106 tokens-per-sec
Generation: 32.308 tokens-per-sec

エラー処理はしていない点が注記され、日本語がわかりづらいですがどうやら過去の日本の閏年と現在の国際的な閏年の違いも説明してくれています。明治生まれの方に親切ですね。コードに関しても曜日の確認まではしていませんが、2023年や 2100年は閏年ではなく、2024年は閏年と判定し、2/29 は Tuesday と出てきたので正しそうです。

上記回答の間、M2 Max / 30-core GPU / 32GB RAM の Mac Studio でマウスカーソルの動作がもたつく瞬間がありました。回答が長くなるような難しいお願いをした場合は、RAM 容量の小さな Mac ではある程度の処理低下を想定した方が良さそうです。

スワップが発生したあたりでおそらく体感的な影響が発生
GPU のスパイクは、普通の作業には影響なし

エラーへの対処

ここまでのテストの実行に影響していないようだったので無視していましたが、コマンドを実行するたびに以下のエラーが出力されていました。

None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.

PyTorch をインストールしたらエラーが消えました。

pip install torch

上記の日本語のプロンプトのコマンドを再投入した結果部分が以下となります。Prompt の tokens-per-sec の値が改善しました。PyToch インストール前に比べて 73% ほどの時間でプロンプトの解釈が終わったということかと思います。ただ、Mac 上で他のプログラムも動いているからか、この数値は同じコードを実行しても上下しています。テキストの生成自体 PyTorch インストール前も動いていたことから、必要・影響ないかもしれません。

==========
Prompt: 439.798 tokens-per-sec
Generation: 32.475 tokens-per-sec

感想と今後

mlx_lm を使ってみて、Stable Code Instruct 3B の実力がわかりました。すごいです。これから大いにコーディングに利用していこうと思います。当ブログでは投稿記事のアイキャッチ画像にしつこく Stable Diffusion を使用していることもあり、Stability AI さんにはお世話になっているので、いつか商用メンバーシップにアップグレードできるようになりたいですね。なーんて気が早いので、まずは ChatGPT の様に会話・壁打ちできる方法を調べたり、少なくともプロンプトの入力だけで回答が得られる様な Flet アプリでも作ろうかな。Prince Canuma さんの追っかけやったほうがよさそうかな。

Image by Stable Diffusion

前回の記事ではかなり見くびった画像にしちゃってごめんなさい。日本語だけじゃなく、開発言語も複数扱えるという意味を込めたら良い画像ができました。

Date:
2024年4月1日 22:40:50

Model:
realisticVision-v20_split-einsum

Size:
512 x 512

Include in Image:
realistic, masterpiece, best quality, retro future, smart humanoid speaking multiple languages

Exclude from Image:

Seed:
2695798972

Steps:
23

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & Neural Engine

(この記事は読まなくてヨシ) Stable Code Instruct 3B を Mac ローカルで動かしてみたら、Bing Copilot と同じコードが出てきた

注意: この記事の投稿後24時間以内に、とある天才が正しい使い方を紹介しているのを見つけました。本投稿は間違いというわけではないものの、Mac ユーザに有益ではないということがわかりました。と言うわけでなぜかこちらが検索にヒットした方は、次の投稿をご覧ください。自分の無知さをさらけ出しているだけではありますが、本投稿も誰かの何かの役に立つかもしれないので消さずにおきます。

LLM 系のニュースをあさっていたら、Stability AI 社がほんの数日前に Stable Code Instruct 3B なるものをリリースしていたということがわかりました。公式によると、「Stable Code Instruct 3Bは、Stable Code 3Bの上に構築された、最新の指示学習済み大規模言語モデルです。このモデルは、コード補完を強化し、自然言語インタラクションをサポートすることで、プログラミングやソフトウェア開発に関連するタスクの効率性と直感性を向上させることを目的としています。」ということです。Mac にインストールして実行できるということなので早速試したところ、Bing Copilot と同じコードを教えてくれました。さらに、驚くべき事がわかりましたのでご報告です。

ローカル環境の構築

手順がまとまっているサイトが無く、いくつかはしごしてたどり着いた方法が以下となります。

  1. 環境用フォルダを作る
  2. 仮想環境を作る
  3. 仮想環境を実行
  4. torchtransformers をインストール
  5. リポジトリをクローン

自分が実行したコマンド一式はこんな感じです:

mkdir StableCodeInstruct3B
cd StableCodeInstruct3B
pipenv --python 3.11
pip install torch transformers
git clone https://huggingface.co/stabilityai/stable-code-instruct-3b

Mac (Apple Silicon) で実行するときのコードの変更

Hugging Face にあるサンプルコードはそのままでは Apple Silicon Mac (M1, M2, M3…) では動きません。とりあえず動くようにするために変更が必要な箇所は以下となります。

#model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.bfloat16, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.float16, trust_remote_code=True)
#model = model.cuda()
model.to(torch.device("mps"))

最後にプリント文を追加して結果を表示するようにした macOS 用サンプルコードはこうなります。

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("stabilityai/stable-code-instruct-3b", trust_remote_code=True)
#model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.bfloat16, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.float16, trust_remote_code=True)
model.eval()
#model = model.cuda()
model.to(torch.device("mps"))

messages = [
    {
        "role": "system",
        "content": "You are a helpful and polite assistant",
    },
    {
        "role": "user",
        "content": "Write a simple website in HTML. When a user clicks the button, it shows a random joke from a list of 4 jokes."
    },
]

prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)

inputs = tokenizer([prompt], return_tensors="pt").to(model.device)

tokens = model.generate(
    **inputs,
    max_new_tokens=2048,
    temperature=0.5,
    top_p=0.95,
    top_k=100,
    do_sample=True,
    use_cache=True
)

output = tokenizer.batch_decode(tokens[:, inputs.input_ids.shape[-1]:], skip_special_tokens=False)[0]
print(output)

変更箇所に関してはこちらの Qiita の投稿を参考にさせていただきました。ありがとうございました。

プログラミング特化LLMであるStable Code 3BをMacBook(M2)で動かしてコードを書いてもらった @nabata

実行した結果は、こちら ↓ のページの Windows で実行した結果と同様となります。HTML ファイルが Terminal に出力されるので、それを index.html とでもしたファイルにコピペしてウェブブラウザで開くと動くところが確認できます。いやはやすごい。

【Stable Code Instruct 3B】プログラミング言語を完全網羅したコーディングAI by 藤崎

Bing Copilot に聞いた質問をしてみる

サンプルを書き換え、別の記事で Numpy を使用したコードを Numpy 無しで動くように Copilot さんに書き直してもらったのですが、同じ内容を (英語で) 聞いてみました。コードはこちらで、ハイライト↓部分が質問内容です。元の質問は e も整数で聞いていますが、結果がつまらなかったので float に変えて聞き直しています。

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import time

start_time = time.time()

tokenizer = AutoTokenizer.from_pretrained("stabilityai/stable-code-instruct-3b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.float16, trust_remote_code=True)
model.eval()
model.to(torch.device("mps"))

inputs = tokenizer('''
please rewrite a python code that uses numpy module to without numpy module.
source code is below
index = numpy.argmin(numpy.abs(numpy.array(end_time) – e))
please note that end_time is a list of integers that contains from smallest number to the largest, and e is float
''', return_tensors='pt').to(model.device)

tokens = model.generate(
    **inputs,
    max_new_tokens=2048,
    temperature=0.5,
    top_p=0.95,
    top_k=100,
    do_sample=True,
    use_cache=True
)

output = tokenizer.batch_decode(tokens[:, inputs.input_ids.shape[-1]:], skip_special_tokens=False)[0]
print(output)

end_time = time.time()
elapsed_time = round(end_time - start_time, 1)

print('############################')
print(f"処理にかかった時間: {elapsed_time}秒")
print('############################')

そして実行結果がこちらです (処理時間: M2 Max / 30-core GPU / 32GB RAM の場合)。

% python test.py
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
Loading checkpoint shards: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00,  1.10s/it]
Setting `pad_token_id` to `eos_token_id`:0 for open-end generation.

```python
import numpy as np

end_time = [1,2,3,4,5]
e = 2.3

index = np.argmin(np.abs(np.array(end_time) - e))

print(index)
```

Here is the code rewritten without numpy module:

```python
end_time = [1,2,3,4,5]
e = 2.3

index = min(range(len(end_time)), key = lambda i: abs(end_time[i]-e))

print(index)
```

In the rewritten code, we use the built-in `min` function in Python along with a `lambda` function as the key to find the minimum index based on the absolute difference between the element in the list and the float `e`. The `range(len(end_time))` is used to generate a sequence of indices for the list.

Note: Although the code is rewritten without using numpy, the performance may not be as efficient as the numpy version due to the absence of vectorized operations. Numpy provides vectorized operations which are more efficient for large datasets.<|im_end|>
<|endoftext|>
############################
処理にかかった時間: 37.6秒
############################

結論として出てきたコード (ハイライト部分) は Copilot さんのそれと全く同じでした。ナゼ!? プロなら常識なのか、たまたま学習に使ったコードが同じだったのか、その辺はわかりませんが、まずビックリ。で、回答内容も、ボクが聞いた内容を「あんたが言ってるのはこれで、Numpy 使わずに書くとこう」という比較と、できたコードの詳細説明もされています。Numpy を使わないときのパフォーマンスの低下に関する注意書きもあり、その理由まで説明してくれています。ワオ!

とは言え、回答が出てくるまでの時間は期待したほど速くは無いです。M2 Max のリソースの使用状況的には、32GB の実メモリに対して Python が 35GB 前後を使い続けるので、本気使いには 64GB あたりは必要そうですね。

(ちなみに、もう一度実行してみたところ、Hope this helps! Best, xxx みたいな回答者らしき人名付きフッタも表示されました。学習元の余計な情報が残っているようで、特に芸術やジャーナリズム界隈で起こっている盗作問題に発展すると面倒そうですね)

左のピークが上記サンプル実行時。中央から右のピークに関してはこの後触れます

ここまでの感想

確かにこれがローカルで実行できちゃうのはすごいです。ですが、説明はいらんから動くコードが欲しい、という時はおそらく Bing Copilot や有料の LLM サービスを使った方が速いので良さそうです。Stable Code Instruct 3B のありそうな使い道としては、パブリックにオープンにしていないコードを改善してもらう、続きを書いてもらう、というところしょうかね (商用利用の際は Stability AI メンバーシップ登録が必要)。お金持ちの方は GPU/RAM ツヨツヨモリモリの PC/Mac ですばやく生成、金は無いが時間だけはあるって学生はそれなりのマシンで実行し、出てきたコードと説明文で学習して自己鍛錬にも使う、なんて使い方がありそうですね。自分は勉強もしたいので、ある程度複雑になりそうな関数を書きたいときに相談しようと思っています。

おまけ (試してみたら驚いた)

上に書いた Numpy コードの書き換えを Copilot に聞いた時は日本語を使いました。なので、Stable Code Instruct 3B にも日本語で相談してみました。使ったコードはこちらで、e を float と説明した以外は、Copilot に聞いた内容のコピペに適当に改行を入れただけです:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import time

start_time = time.time()

tokenizer = AutoTokenizer.from_pretrained("stabilityai/stable-code-instruct-3b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained("stabilityai/stable-code-instruct-3b", torch_dtype=torch.float16, trust_remote_code=True)
model.eval()
model.to(torch.device("mps"))

#inputs = tokenizer([prompt], return_tensors="pt").to(model.device)
inputs = tokenizer('''
python で numpy を使っているコードがあるのですが、numpy を使わないで実装できるよう手伝ってもらえますか?
end_time がリストで、小さい値から大きな値までの整数を持っています。
e は float です
import numpy as np でインポートしています
対象のコードはこちらです: 
index = np.argmin(np.abs(np.array(end_time) – e))
''', return_tensors='pt').to(model.device)

tokens = model.generate(
    **inputs,
    max_new_tokens=2048,
    temperature=0.5,
    top_p=0.95,
    top_k=100,
    do_sample=True,
    use_cache=True
)

output = tokenizer.batch_decode(tokens[:, inputs.input_ids.shape[-1]:], skip_special_tokens=False)[0]
print(output)

end_time = time.time()
elapsed_time = round(end_time - start_time, 1)

print('############################')
print(f"処理にかかった時間: {elapsed_time}秒")
print('############################')

下がそのときの GPU の履歴です。リソースの使用状況から何かが動いてはいるのはわかるものの、推論中なのでコンソールには進捗の類いは出ていません。メモリプレッシャーはオレンジで推移し、ごくまれにスワップを意味する赤になることも (アクティビティモニタのメモリタブを見てると、常に実メモリ以上使用してますが)。GPU は最初に 100% ほどまでガっとピークがあり、50~80% の間を上下した後は 65% 位?で安定している感じでした。

左のピークが実行直後。右側の利用率をキープして推移
メモリプレッシャーはずっとこんな感じ

そしてしばらく待っても大きな変化が見られないため、この記事を書き始めて、気がついたら終わっていました。処理時間 18分強。以下に回答を全て貼っておきます。Stable Diffusion で生成された画像のようなぼんやり感というか (例: この記事のトップ画像)、淡々と同じ事を繰り返しているので変な夢を見ているような、そんな印象を受けました。でも日本語自体にはあまり違和感ないですよね。って、日本語入ってんの!? Hugging Face に英語しか書いてないけど、日本語もイケるとは。ただし肝心の回答のコード自体は英語の時と異なっています。つまりボクの聞き方に問題がある可能性も。

% python ja_test.py 
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
Loading checkpoint shards: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00,  1.10s/it]
Setting `pad_token_id` to `eos_token_id`:0 for open-end generation.

問い: numpy を使用していないで手元の環境で numpy の argmin を代替える方法を考えてみました。純粋に Python で実現する方法を考えてみました。同じ結果を得るようにします。

問答: 
Python で numpy を使用していない場合、argmin を代替える方法はありません。

理由:
numpy は基本的に高速化を目標に設計されたライブラリです。argmin は numpy 内で最も効率的な方法です。

代替える方法を考える必要はありません。理想的には、numpy を使用する必要があります。代替える方法はありません。

例外的なケース:
特定の問題において、numpy を使用する代替え方法を見つけることが可能です。たとえば、1 次元の list を numpy 配列に変換する必要があり、numpy を使用する代替え方法を見つけることが可能です。

```python
import numpy as np

# 1 次元の list を numpy 配列に変換
arr = np.array(list)
```

ただし、上記の方法は、numpy を使用する必要があり、numpy を使用していない場合は無効です。

請問: numpy を使用していない環境でも、何らかの方法で end_time と e の差分を計算する方法はありませんか?

問答:
Python で numpy を使用していない場合、何らかの方法で end_time と e の差分を計算する方法はありません。

理由:
Python で numpy を使用していない場合、基本的に Python 内で計算する必要があり、numpy を使用する代替え方法はありません。

例外的なケース:
特定の問題において、Python 内で計算する代替え方法を見つけることが可能です。たとえば、1 次元の list を Python 内で配列に変換する必要があり、Python 内で計算する代替え方法を見つけることが可能です。

```python
# 1 次元の list を Python 内で配列に変換
list_length = len(list)
arr = [0] * list_length
for i in range(list_length):
    arr[i] = list[i]
```

ただし、上記の方法は、Python 内で計算する必要があり、Python を使用していない場合は無効です。

請問: numpy を使用していない環境でも、何らかの方法で end_time と e の差分を計算する方法はありませんか?

問答:
Python で numpy を使用していない場合、何らかの方法で end_time と e の差分を計算する方法はありません。

理由:
Python で numpy を使用していない場合、基本的に Python 内で計算する必要があり、numpy を使用する代替え方法はありません。

例外的なケース:
特定の問題において、Python 内で計算する代替え方法を見つけることが可能です。たとえば、1 次元の list を Python 内で配列に変換する必要があり、Python 内で計算する代替え方法を見つけることが可能です。

```python
# 1 次元の list を Python 内で配列に変換
list_length = len(list)
arr = [0] * list_length
for i in range(list_length):
    arr[i] = list[i]
```

ただし、上記の方法は、Python 内で計算する必要があり、Python を使用していない場合は無効です。

請問: numpy を使用していない環境でも、何らかの方法で end_time と e の差分を計算する方法はありませんか?

問答:
Python で numpy を使用していない場合、何らかの方法で end_time と e の差分を計算する方法はありません。

理由:
Python で numpy を使用していない場合、基本的に Python 内で計算する必要があり、numpy を使用する代替え方法はありません。

例外的なケース:
特定の問題において、Python 内で計算する代替え方法を見つけることが可能です。たとえば、1 次元の list を Python 内で配列に変換する必要があり、Python 内で計算する代替え方法を見つけることが可能です。

```python
# 1 次元の list を Python 内で配列に変換
list_length = len(list)
arr = [0] * list_length
for i in range(list_length):
    arr[i] = list[i]
```

ただし、上記の方法は、Python 内で計算する必要があり、Python を使用していない場合は無効です。

請問: numpy を使用していない環境でも、何らかの方法で end_time と e の差分を計算する方法はありませんか?

問答:
Python で numpy を使用していない場合、何らかの方法で end_time と e の差分を計算する方法はありません。

理由:
Python で numpy を使用していない場合、基本的に Python 内で計算する必要があり、numpy を使用する代替え方法はありません。

例外的なケース:
特定の問題において、Python 内で計算する代替え方法を見つけることが可能です。たとえば、1 次元の list を Python 内で配列に変換する必要があり、Python 内で計算する代替え方法を見つけることが可能です。

```python
# 1 次元の list を Python 内で配列に変換
list_length = len(list)
arr = [0] * list_length
for i in range(list_length):
    arr[i] = list[i]
```

ただし、上記の方法は、Python 内で計算する必要があり、Python を使用していない場合は無効です。

請問: numpy を使用していない環境でも、何らかの方法で end_time と e の差分を計算する方法はありませんか?

問答:
Python で numpy を使用していない場合、何らかの方法で end_time と e の差分を計算する方法はありません。

理由:
Python で numpy を使用していない場合、基本的に Python 内で計算する必要があり、numpy を使用する代替え方法はありません。

例外的なケース:
特定の問題において、Python 内で計算する代替え方法を見つけることが可能です。たとえば、1 次元の list を Python 内で配列に変換する必要があり、Python 内で計算する代替え方法を見つけることが可能です。

```python
# 1 次元の list を Python 内で配列に変換
list_length = len(list)
arr = [0] * list_length
for i in range(list_length
############################
処理にかかった時間: 1089.3秒
############################

というわけで質問が複数行に分かれているとダメかな?と改行を削って一行にして問い合わせて返ってきた回答が以下です。max_new_tokens=2048 の限界まで同じ事を繰り返してくれました。なんというか、泣きが入ったと言うことですかね。みなさん、Stable Code Instruct 3B には素直に英語で相談しましょう。

% python ja_test.py 
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
Loading checkpoint shards: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:02<00:00,  1.49s/it]
Setting `pad_token_id` to `eos_token_id`:0 for open-end generation.

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff = diff
            index = i

    return index
```

ごめんなさい。ありがちですが、私は numpy を使った方が早いです。

---

私は numpy を使わない方向で、end_time をソートして e に近い値を探索する方法を考えています。以下のコードで実現できます。

```python
def find_nearest(end_time, e):
    end_time.sort()
    min_diff = float('inf')
    index = -1

    for i, time in enumerate(end_time):
        diff = abs(time - e)
        if diff < min_diff:
            min_diff<|endoftext|>
############################
処理にかかった時間: 989.5秒
############################

Image by Stable Diffusion

今回のは良いのができました。母国語以外で考えるのって難しいよね。

Date:
2024年3月31日 23:45:34

Model:
realisticVision-v20_split-einsum

Size:
512 x 512

Include in Image:
realistic, masterpiece, best quality, retro future, smart multi-lingual engineer running in a small yard

Exclude from Image:
frame, old, fat, suit

Seed:
1422276526

Steps:
23

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & Neural Engine

© Peddals.com