動機
少し前に大学の研究室のGPUサーバーでLM Studioを使おうとしてうまくいかず断念してしまい、そんな中で下の記事を偶然見つけ、まずはローカル環境でやってみようと思った。
実行環境
- MacBook Pro 14-inch (2023, M2 Pro, 16GB)
- macOS Tahoe 26.0.1
試行錯誤
上の記事の内容に基づき、実行していきました。
# 1. インストール
brew install --cask lm-studio
# 出力結果
Cask lm-studio depends on hardware architecture being one of [{type: :arm, bits: 64}], but you are running {type: :intel, bits: 64}.
結果を読むと、インストールしようとしたアプリはarmなのに、実行環境はintelだよ、とのこと。
しかし、M2 Proなのでarmのはず…
というわけでGemini監督のもと確認作業
まずは、ターミナルがRosetta2経由で動いていないか確認。ほとんど使ったことがないため、可能性は低いと思いつつ念の為
# アーキテクチャの確認
uname -m
# 出力結果
arm64
armのため問題なし。
続いてIntel版のhomebrewで実行していないか確認。
# homebrewの場所の確認
which brew
# 出力結果
**/usr/local/bin/brew**
ネイティブのApple Silicon版(/opt/homebrew/bin/brew)よりも先に読み込まれているため、brewはbrewでも、Intel版のものが呼び出されてしまっている状態でした。
おそらくは、以前にhomebrewを利用しようとした際に、生成AIに言われるがままにやってやらかしたのだと思われます。
Intel版のhomebrewは現状使わないので、削除します。
# 公式のアンインストールコマンド
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
# 実行後、どのhomebrewを参照しているか確認
which brew
# 出力結果
/opt/homebrew
無事に正常な状態に戻すことができ、インストールを完了させることができました!
Intel版HomeBrewの削除以外にも、シェルの設定ファイルでPATH設定を変えることでもエラー解消ができるとのこと。
エラーも解消されたので、再び手順に戻って進めていきます。
# 2. GUIも起動できるか一応確認(おそらく手順上は不要。開いてもGUIでは何もする必要がなかったです)
open -a "LM Studio"
→問題なく起動できました。
# 3. CLI有効化
~/.lmstudio/bin/lms bootstrap
"bootstrap”を利用することで、PATHに追加され、単に"lms"と入力するだけでLM StudioのCLIをどこからでも呼び出せるようになる。
# 出力結果
***
Permission denied
***
長々と出力されましたが、最もクリティカルな部分は上の内容になります。
特定のファイルに書き込もうとしたものの、権限がないために書き込めなかったためエラーが出たようです。
sudoを使ってそのファイルを作成または編集したことがある場合に発生しやすいとのこと。
今回やりたいこととしては、PATHへの追加なのでbootstrapではなく手動でPATH追加を行います。
denyされたファイルの権限をsudoで変更することでも改善可能。
# PATH設定を書き込む
echo 'export PATH="$PATH:***"' >> ~/.zshrc
# 設定を有効化
source ~/.zshrc
# 設定できたか確認
llm
# 出力結果
__ __ ___ ______ ___ _______ ____
/ / / |/ / / __/ /___ _____/ (_)__ / ___/ / / _/
/ /__/ /|_/ / _\ \/ __/ // / _ / / _ \ / /__/ /___/ /
/____/_/ /_/ /___/\__/\_,_/\_,_/_/\___/ \___/____/___/
lms - LM Studio CLI - v0.0.47
無事に出力が確認できたため設定完了!
再び手順に戻って進めていきます。
# 4. サーバー起動
lms server start --port 1234
# 出力結果
Waking up LM Studio service...
Success! Server is now running on port 1234
無事にサーバー起動できました!
# 5. モデルダウンロード(対話的に選択が必要です)
lms get --gguf "TinySwallow-1.5B-Instruct"
No exact match found. Please choose a model from the list below.
! Use the arrow keys to navigate, type to filter, and press enter to select.
? Select a model to download SakanaAI/TinySwallow-1.5B-Instruct-GGUF
! Use the arrow keys to navigate, and press enter to select.
? Select an option to download Tinyswallow 1.5B Instruct [Q8_0] (1.65 GB)
Downloading Tinyswallow 1.5B Instruct [Q8_0] (1.65 GB)
どうやらモデル名に厳密にマッチするものがなかったようで、いくつかの選択肢が提示され、その中から選ぶことができました。
optionでは、quantizeの形式を選び、その後モデルのロードが始まりました。
Finalizing download...
Download completed. You can load the model with:
lms load tinyswallow-1.5b-instruct
モデルのロードが完了しました!
# 6. サーバーにモデルをロード(context-lengthは各自でよしなに)
lms load tinyswallow-1.5b-instruct --identifier tinyswallow --gpu max --context-length 4096
- --idenifier tinyswallow : ロードしたモデルに tinyswallow という短いニックネーム(別名)を付ける
- --gpu max : モデルの計算処理をGPUに最大限オフロード(委任)する
- --context-length 4096 : モデルのコンテキスト長(Context Length)を4096トークンに設定
# 出力結果
Loading model "SakanaAI/TinySwallow-1.5B-Instruct-GGUF/tinyswallow-1.5b-instruct-q8_0.gguf"...
Model loaded successfully in 2.67s. (1.65 GB)
To use the model in the API/SDK, use the identifier "tinyswallow".
無事に推論可能な状態になりました!
# 7. JSON構造化出力テスト
curl http://localhost:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "tinyswallow",
"messages": [{"role":"user","content":"今の気分は?"}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "Tasks",
"strict": true,
"schema": {
"type": "object",
"properties": {
"tasks": {
"type": "array",
"items": {"type": "object"}
}
}
}
}
}
}'
- curl http://localhost:1234/v1/chat/completions : localhost:1234で動作しているLM Studioサーバーの、OpenAI互換チャットAPIエンドポイントを指して、HTTPリクエストを送信
- -H "Content-Type: application/json" : 「これから送信するデータ(-dの中身)はJSON形式ですよ」とHTTPヘッダーで指定
- -d '{...}' : HTTPリクエストの中身を示す
# 出力結果
{
"id": "chatcmpl-kmb5lsjgdcm4gh0vo4ddf",
"object": "chat.completion",
"created": 1759478416,
"model": "tinyswallow",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{ \"tasks\": [{ \"task_name\" : \"inform\", \"msg\":\"I am a TinySwallow, an AI assistant. I'm here to help people with their tasks and provide information.\" }]}",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 54,
"completion_tokens": 47,
"total_tokens": 101
},
"stats": {},
"system_fingerprint": "tinyswallow"
}
無事に返答が返ってきました!
まとめ
過去の自分の杜撰な処理から苦労することもありましたが、無事にCLIでLM Studioを動かすことができました。
今回は例にあった比較的小さなモデルで、かつローカル環境で試しましたが、今後リモート環境でも同様に動作可能か、検証してみたいと思います。