所要時間: 約30分 | 難易度: ★★☆☆☆
この記事で作るもの
Apple Silicon(M1/M2/M3/M4チップ)に最適化された計算ライブラリ「MLX」を使い、Llama 3やQwenといった最新のLLMをMac上で高速に動かすPythonスクリプトを作成します。 Pythonの基本的な読み書きができれば、自分のMacが即座に高性能なAIサーバーに変わります。
- ローカル環境でプロンプトを入力し、即座に回答を得るチャットスクリプト
- モデルのロード、量子化の選択、ストリーミング出力の実装
- Hugging Faceからモデルを自動取得し、MLX形式で実行する一連の流れ
先に確認するスペック・料金
Apple Siliconを搭載していないIntel Macでは動作しません。 最も重要なのは「ユニファイドメモリ(RAM)」の容量です。 ローカルLLMを動かす場合、GPUとシステムでメモリを共有するため、メモリ不足は致命的です。
8GBモデルのMacでも動かせますが、7B(70億パラメータ)クラスのモデルを動かすとOS全体が重くなり、実務では使い物になりません。 快適に動かすなら16GB以上、本格的にパラメータ数の多いモデル(30B以上)を試すなら32GB以上のメモリを積んだモデルが必須です。 「とりあえず試す」だけなら、既存のMac miniやMacBook Airで十分ですが、仕事で使うならM2/M3 Pro以上のチップと32GB以上のメモリ構成を強く推奨します。
ソフトウェア面では、macOS 13.5以上が必須、推奨は最新のmacOS 14 (Sonoma) 以降です。 MLXはAppleが開発しているため、OSのアップデートによって最適化が進む傾向があります。 API料金は一切かかりませんが、Hugging Faceから数GB〜数十GBのモデルをダウンロードするため、高速なインターネット環境と、SSDの空き容量(50GB以上)を確保してください。
なぜこの方法を選ぶのか
MacでローカルLLMを動かす方法は、他にも「Ollama」や「llama.cpp」があります。 しかし、Pythonエンジニアが「自分のプログラムにAIを組み込みたい」のであれば、MLX一択です。 Ollamaは手軽ですがカスタマイズ性に欠け、llama.cppはC++ベースのためPythonからの制御が一段階遠くなります。
MLXはAppleの機械学習チームが直々に開発しており、Apple SiliconのGPUパワーを最大限に引き出すように設計されています。 PyTorchに近い記法で書けるため、普段から機械学習に触れている人なら学習コストはほぼゼロです。 また、Unified Memoryを直接叩く設計のため、PyTorchをMacで無理やり動かすよりも、推論速度(Tokens per second)が私の環境では約1.5倍から2倍近く向上しました。
Step 1: 環境を整える
まずはMLX専用の仮想環境を作ります。 グローバルな環境を汚すと、後で別のライブラリと依存関係が衝突して泣くことになるので、必ず仮想環境を切りましょう。
# プロジェクトディレクトリの作成
mkdir mlx-test && cd mlx-test
# Python仮想環境の作成(Python 3.10以上を推奨)
python3 -m venv .venv
# 仮想環境の有効化
source .venv/bin/activate
# 必須ライブラリのインストール
# mlx-lmはMLX公式が提供する、LLMに特化した高レベルライブラリです
pip install mlx-lm huggingface_hub
mlx-lm は、Hugging FaceにアップロードされているモデルをMLX用に変換・実行するためのユーティリティが含まれています。
これを使うことで、複雑な変換プロセスをスキップして、直接モデル名を指定するだけで動かせるようになります。
⚠️ 落とし穴:
Macにデフォルトで入っているPythonではなく、Homebrewなどで入れた最新のPythonを使用してください。
また、pip install 時にエラーが出る場合は、Command Line Toolsが古い可能性があります。xcode-select --install で最新の状態に更新しておきましょう。
Step 2: 基本の設定
Pythonスクリプトを作成します。 ここでは、モデルの指定方法と、なぜそのモデルを選ぶのかという基準を明確にします。
# main.py
from mlx_lm import load, generate
# 1. 使用するモデルの指定
# 最初は軽量で高性能な「Llama-3-8B」の4bit量子化版がおすすめです。
# 量子化(Quantization)とは、モデルの精度をわずかに下げてメモリ消費を激減させる技術です。
model_path = "mlx-community/Meta-Llama-3-8B-Instruct-4bit"
# 2. モデルとトークナイザーの読み込み
# load関数は、ローカルにモデルがなければHugging Faceから自動でダウンロードします。
print("モデルを読み込んでいます...")
model, tokenizer = load(model_path)
# 3. プロンプトの準備
# LLMには「型」があります。Llama 3の場合、特定のタグで囲む必要がありますが、
# mlx-lmのtokenizer.apply_chat_templateを使えば自動で最適化されます。
messages = [
{"role": "system", "content": "あなたは優秀なエンジニアです。簡潔に回答してください。"},
{"role": "user", "content": "Apple SiliconでMLXを使うメリットを3つ教えて。"}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
mlx-community というアカウントがHugging Face上に存在し、そこには既にMLX形式に最適化されたモデルが多数アップロードされています。
自分で変換(Quantize)することも可能ですが、最初は既に公開されている「4bit」モデルを使うのが正解です。
8bitよりも4bitの方が圧倒的に速く、メモリ消費も半分で済みます。
Step 3: 動かしてみる
次に、生成処理を実行するコードを追加します。
# 生成の実行
# max_tokens: 生成する最大文字数。短すぎると途中で切れます。
# temp: 自由度。0に近いほど堅実、1に近いほど創造的な回答になります。仕事用なら0.7前後が安定します。
response = generate(
model,
tokenizer,
prompt=prompt,
max_tokens=512,
verbose=True # 生成プロセスを表示する
)
# 結果はすでに出力されていますが、変数にも格納されます
# print(response)
期待される出力
モデルを読み込んでいます...
Fetching 5 files: 100%|██████████████████████████| 5/5 [00:00<00:00, 150.31it/s]
Apple SiliconでMLXを使うメリットは以下の3つです。
1. ユニファイドメモリの活用: CPUとGPUが同じメモリを共有するため、巨大なモデルでも高速にデータを転送できます。
2. ハードウェア最適化: Apple純正ライブラリのため、MシリーズチップのGPUコアを最大限に引き出せます。
3. 低消費電力: 高い推論パフォーマンスを維持しつつ、MacBookなどではバッテリー消費を抑えて動作します。
もしここで「Bus error」や「Memory error」が出る場合は、Macのメモリが不足しています。 ブラウザ(Chromeなど)を閉じてから再試行するか、より小さなモデル(1Bや3Bクラス)を試してください。
Step 4: 実用レベルにする
実務で使う場合、生成が終わるまで待たされるのはストレスです。 1文字ずつ出力される「ストリーミング」を実装し、さらに再利用可能なクラスにまとめます。
import sys
from mlx_lm import load, stream
class LocalAI:
def __init__(self, model_name):
# 実務ではモデルのロード時間を短縮するため、一度ロードしたら使い回します
self.model, self.tokenizer = load(model_name)
def ask(self, question, system_prompt="あなたは親切なアシスタントです。"):
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": question}
]
prompt = self.tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
print(f"\nAI: ", end="", flush=True)
# stream関数を使うことで、トークンが生成されるたびに逐次処理できます
for response in stream(self.model, self.tokenizer, prompt, max_tokens=1000):
print(response, end="", flush=True)
print("\n")
# 実装例
if __name__ == "__main__":
# Qwen2.5-7Bは日本語能力が非常に高く、現在Macで動かすのに最もおすすめのモデルの一つです
ai = LocalAI("mlx-community/Qwen2.5-7B-Instruct-4bit")
while True:
user_input = input("質問を入力(exitで終了): ")
if user_input.lower() == "exit":
break
ai.ask(user_input)
このコードでは stream 関数を使用しています。
generate と異なり、イテレータとして動作するため、生成されたそばから print で表示できます。
これにより、ユーザー体感としての待ち時間をほぼゼロにできます。
また、Qwen2.5-7B を指定しました。
Llama 3も良いですが、日本語の自然さと論理構成の強さでは、現時点ではQwenシリーズがMacローカル環境では最強クラスです。
私のM2 Max(64GBメモリ)環境では、このモデルが秒間約40トークンで動きます。これは人間が読むスピードを遥かに上回る速さです。
よくあるトラブルと解決法
| エラー内容 | 原因 | 解決策 |
|---|---|---|
ModuleNotFoundError: No module named 'mlx' | 仮想環境が未有効、またはインストール失敗 | source .venv/bin/activate を実行し pip install mlx-lm をやり直す |
Killed: 9 | メモリ(RAM)不足によるOSの強制終了 | より小さいモデル(3B以下)を使うか、他のアプリをすべて閉じる |
Permission denied | Hugging Faceの認証が必要なモデルを叩いている | huggingface-cli login でトークンを入力するか、公開モデル(Qwen等)を使う |
| 生成速度が極端に遅い | バッテリー駆動で省電力モードがオン | 電源アダプタを接続し、ハイパフォーマンス設定を確認する |
次のステップ
MLXでローカルLLMを動かせるようになったら、次は「RAG(検索拡張生成)」に挑戦してください。 自分の持っているPDFやテキストファイルを読み込ませ、その内容に基づいて回答させる仕組みです。 MLXには、推論だけでなく「LoRA(低ランク適応)」という手法を用いた追加学習(ファインチューニング)のサンプルも公式に用意されています。
自分の特定の業務知識を学習させた「自分専用モデル」をMacの中で完結して作れるのが、ローカル環境の醍醐味です。 まずは今回作成したスクリプトをベースに、Slackボット化したり、ローカルのファイル一括要約ツールを作ってみるのが良いでしょう。 クラウドAPIを使わないため、どれだけ回しても無料ですし、個人情報や機密情報が外に漏れる心配もありません。
よくある質問
Q1: プロンプトを変えても英語で返ってくることが多いです。
モデルが「日本語特化」でない場合、システムプロンプトを「必ず日本語で回答してください」と強く指定する必要があります。また、使用するモデル名が -Instruct で終わるもの(対話用)であることを確認してください。
Q2: 4bit量子化は精度が落ちませんか?
理論上はわずかに落ちますが、実務で使ってみた感想としては、8Bクラスのモデルであれば4bitでも十分な論理的回答が得られます。むしろ量子化せずにメモリを圧迫してスワップが発生し、動作がガタガタになるデメリットの方が遥かに大きいです。
Q3: GPU使用率が100%になりませんが、正常ですか?
MLXはユニファイドメモリの帯域幅(メモリバス幅)がボトルネックになることが多く、GPUコア自体が常に100%を叩くとは限りません。アクティビティモニタの「GPUの履歴」で、生成中にグラフが跳ねていれば正常に動作しています。
📦 この記事に関連する商品(楽天メインで価格確認)
Mac StudioMLXでの巨大モデル検証や複数並列実行に耐える最強のローカルAI環境
※アフィリエイトリンクを含みます



