所要時間: 約40分 | 難易度: ★★☆☆☆

この記事で作るもの

  • Apple Silicon(M1/M2/M3/M4)に最適化されたフレームワーク「MLX」を使い、Llama 3.1やGemma 2といった最新のLLMをローカル環境で高速に動かすPythonスクリプト
  • Hugging Faceからモデルを自動取得し、ストリーミング形式(逐次出力)で回答を生成するチャットインターフェース
  • 外部APIを一切使わず、完全にオフラインかつ無料で動作するプライベートなAI環境

📦 この記事に関連する商品(楽天メインで価格確認)

Mac Studio M2 Max

64GBの統一メモリで70BクラスのLLMもローカルで実用的に動作可能

楽天で価格を見る Amazonでも確認

※アフィリエイトリンクを含みます

先に確認するスペック・料金

Apple Siliconを搭載したMacであることが絶対条件です。 Intel Macでは動作しません。 MLXは「Unified Memory(統一メモリ)」をGPUメモリとしてフル活用するため、搭載メモリ量がそのまま動かせるモデルのサイズに直結します。

具体的には、8GBモデルのMacだと最小クラスのモデル(Llama 3.1 8Bの4-bit量子化版など)で限界です。 OSやブラウザがメモリを食っていると、生成が極端に遅くなるかクラッシュします。 快適に動かすなら16GB以上、70Bクラスの巨大なモデルを試すなら64GB以上のメモリを積んだMac StudioやMac Proが必要です。

GPUを別途買う必要はありませんが、この記事で紹介するコードを動かすにはディスク容量が最低でも10GB程度空いていることを確認してください。 モデルデータは1つあたり数GBから数十GBのサイズがあるため、ストレージの空き容量は死活問題になります。

なぜこの方法を選ぶのか

MacでローカルLLMを動かす選択肢には、OllamaやLM Studio、llama.cppなどがあります。 その中で私が「MLX」を推す理由は、Appleの機械学習チームが直接開発しており、OSレベルでハードウェアの性能を限界まで引き出せるからです。

PyTorchをMacで動かす(MPSバックエンド)場合と比較しても、MLXはメモリコピーのオーバーヘッドが少なく、推論速度が1.5倍から2倍近く変わることも珍しくありません。 また、Pythonライブラリとしての完成度が高く、既存のデータ処理パイプラインに組み込みやすいのが大きなメリットです。 「ただチャットができればいい」ならOllamaで十分ですが、「AIを使った自作ツールを作りたい」ならMLX一択だと思います。

Step 1: 環境を整える

まずはPython環境を作成します。 MLXは依存関係がシビアなことがあるため、必ず仮想環境を切りましょう。 私はパッケージマネージャーに高速な uv を使っていますが、標準の venv でも問題ありません。

# プロジェクトディレクトリの作成
mkdir mlx-test && cd mlx-test

# 仮想環境の作成と有効化
python3 -m venv .venv
source .venv/bin/activate

# 必須ライブラリのインストール
pip install mlx-lm huggingface_hub

mlx-lm はMLX本体をラップし、Hugging Face形式のモデルを簡単に扱えるようにした高レイヤーライブラリです。 これを入れるだけで、複雑な計算グラフの定義をスキップして、数行のコードで推論を始められます。 huggingface_hub は、モデルをダウンロードする際の認証や管理に使用します。

⚠️ 落とし穴: macOSのバージョンが古いとMLXが入りません。 macOS 13.5(Ventura)以上が必須ですが、性能をフルに発揮させるならmacOS 14.x(Sonoma)以降へのアップデートを強く推奨します。 また、Pythonは3.10〜3.12の範囲で使ってください。3.13はライブラリ側の対応が追いついていない場合があります。

Step 2: 基本の設定

次に、動かしたいモデルを選びます。 ローカルLLMの世界では、モデルを軽量化した「量子化(Quantization)」版を使うのが定石です。 今回は、Metaが公開している最強クラスの小型モデル「Llama-3.1-8B-Instruct」をMLX専用に最適化したものを使います。

# config.py という名前で保存
import os

# 使用するモデルのHugging Faceリポジトリ名
# mlx-community が提供しているモデルは、MLX用に最適化済みなので読み込みが速いです
MODEL_ID = "mlx-community/Meta-Llama-3.1-8B-Instruct-4bit"

# 生成パラメータの設定
# temperature: 値が高いほど創造的(ランダム)、低いほど堅実な回答になります
# max_tokens: 生成する最大トークン数。最初は短めにして動作を確認します
GENERATE_CONFIG = {
    "temp": 0.7,
    "max_tokens": 512,
}

「なぜ4bitなのか」と疑問に思うかもしれませんが、これはメモリ消費を1/4に抑えるためです。 8B(80億パラメータ)のモデルをそのまま読み込むと15GB以上のメモリが必要ですが、4bit量子化なら約5GB強で済みます。 精度低下は実用上ほとんど気にならないレベルなので、個人開発では4bit版を選ぶのが最も賢い選択です。

Step 3: 動かしてみる

それでは、最小構成の推論スクリプトを書いて動かしてみましょう。 この段階では、まだストリーミング(逐次表示)は行わず、一括で結果を受け取る形式にします。

# main.py
from mlx_lm import load, generate
from config import MODEL_ID, GENERATE_CONFIG

print(f"モデルをロード中: {MODEL_ID}...")

# モデルとトークナイザーの読み込み
# Apple Siliconの各コアに最適化された形でメモリに配置されます
model, tokenizer = load(MODEL_ID)

# プロンプトの準備
# Llama 3.1の形式に合わせたメッセージ構造
messages = [
    {"role": "system", "content": "あなたは親切で優秀なAIアシスタントです。"},
    {"role": "user", "content": "Apple SiliconでMLXを使うメリットを3点、簡潔に教えてください。"}
]

# モデルが理解できる形式(プロンプトテンプレート)に変換
prompt = tokenizer.apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True
)

print("回答を生成中...\n" + "-"*20)

# 推論の実行
response = generate(
    model,
    tokenizer,
    prompt=prompt,
    temp=GENERATE_CONFIG["temp"],
    max_tokens=GENERATE_CONFIG["max_tokens"]
)

print(response)

期待される出力

モデルをロード中: mlx-community/Meta-Llama-3.1-8B-Instruct-4bit...
回答を生成中...
--------------------
Apple SiliconでMLXを使う主なメリットは以下の3点です。

1. 統一メモリ(Unified Memory)の活用: CPUとGPUが同じメモリ空間を共有するため、巨大なモデルも高速に読み書きでき、データの転送遅延がほとんどありません。
2. ハードウェア最適化: AppleのGPUやNeural Engineを最大限に引き出す設計となっており、PyTorchなどの他フレームワークよりも高い電力効率と推論速度を実現します。
3. Pythonとの親和性: NumPyに近い直感的なAPIを持ちながら、遅延評価や自動微分をサポートしているため、開発者がカスタマイズや独自の実装を行いやすい点です。

結果の読み方について補足します。 最初の実行時はモデルのダウンロードが行われるため、ネット環境によっては数分かかります。 2回目以降はローカルキャッシュから読み込まれるため、数秒で起動するはずです。 もし出力が途中で切れる場合は、GENERATE_CONFIGmax_tokens を増やしてみてください。

Step 4: 実用レベルにする

実務で使うなら、回答が返ってくるのをじっと待つのは苦痛です。 ChatGPTのように、文字がポツポツと出てくる「ストリーミング出力」を実装しましょう。 また、メモリ管理のために不要なモデルを明示的に解放する仕組みも考慮します。

# chat.py
import sys
from mlx_lm import load, stream
from config import MODEL_ID, GENERATE_CONFIG

def run_chat():
    model, tokenizer = load(MODEL_ID)

    # ユーザー入力を受け取るループ
    while True:
        user_input = input("\n質問を入力してください (exitで終了): ")
        if user_input.lower() == "exit":
            break

        messages = [
            {"role": "user", "content": user_input}
        ]
        prompt = tokenizer.apply_chat_template(
            messages, tokenize=False, add_generation_prompt=True
        )

        print("\nAI: ", end="", flush=True)

        # stream関数を使うことで、トークンが生成されるたびに取得可能
        # これにより体感の待ち時間(Time To First Token)が大幅に短縮されます
        for response in stream(
            model,
            tokenizer,
            prompt=prompt,
            temp=GENERATE_CONFIG["temp"],
            max_tokens=GENERATE_CONFIG["max_tokens"],
        ):
            print(response, end="", flush=True)
        print()

if __name__ == "__main__":
    try:
        run_chat()
    except KeyboardInterrupt:
        print("\n終了します。")

このコードのポイントは stream 関数の使い方です。 generate と異なり、イテレータとして動作するため、for ループ内で逐次 print できます。 flush=True を忘れると、標準出力のバッファに溜まってしまい、結局まとめて表示されてしまうので注意してください。

実務への応用として、この run_chat 関数を FastAPI などの Web フレームワークでラップすれば、自社専用のローカルAIサーバーを爆速で構築できます。 インターネットへのデータ流出を気にせず、機密情報を含んだコードのレビューやドキュメント要約を行える環境は、エンジニアにとって大きな武器になります。

よくあるトラブルと解決法

エラー内容原因解決策
ImportError: DLL load failedPythonのバージョン不整合またはOSの未対応macOS 14以上、Python 3.11を推奨。
Killed または Memory Errorメモリ(RAM)不足ブラウザ(Chrome等)を閉じるか、より小さいモデル(Qwen2-1.5B等)を試す。
Invalid chat templateモデル特有のプロンプト形式の欠如Hugging Faceのモデルページを確認し、正しいテンプレートを手動で指定する。

次のステップ

MLXでモデルを動かせるようになったら、次は「RAG(検索拡張生成)」に挑戦することをお勧めします。 ローカルLLMの最大の弱点は「最新情報や自分の持っているファイルの中身を知らないこと」です。 langchain-mlx などのライブラリを組み合わせれば、自分のPC内にあるPDFやMarkdownファイルをAIに読み込ませて、それに基づいた回答をさせることが可能です。

また、MLXは推論だけでなく「LoRA(低ランク適応)」という手法を用いた追加学習も非常に得意としています。 MacのGPUを使って、数十分から数時間で自分の口癖や特定のプログラミングスタイルをAIに覚えさせることができます。 「動かしてみた」の先にある、自分だけの特化型AIを育てる楽しさをぜひ味わってください。 RTX 4090を回すのも快感ですが、静かなMacBookで高度なLLMがヌルヌル動く体験も、また格別なものですよ。

よくある質問

Q1: M1 Macの8GBモデルでも動きますか?

動きますが、かなり工夫が必要です。2Bクラス(Gemma-2-2Bなど)や1Bクラスのモデルであればサクサク動きますが、8Bクラスはメモリ不足でスワップが発生し、レスポンスが10秒以上かかることもあります。まずは軽量モデルから試すのが定石です。

Q2: 実行中にMacが熱くなるのですが、壊れませんか?

LLMの推論はGPUを100%近く使うため、ファンレスのMacBook Airなどはかなり熱くなります。サーマルスロットリングで速度が落ちることはありますが、OS側で制御されるため故障の心配は低いです。長時間回すなら、冷却台を使うか、ファンのあるPro/Studioモデルが有利です。

Q3: MLXとOllama、結局どっちを使い続けるべきですか?

「手軽にチャットアプリとして使いたい」ならOllamaが便利です。しかし「Pythonスクリプトの一部として組み込みたい」「自分でモデルをカスタマイズ・微調整したい」ならMLXを学ぶ価値があります。私は、検証にはOllama、実装にはMLXと使い分けています。


あわせて読みたい