M4 Mac miniでローカルSLM

# はじめに
M4 Mac mini (RAM:32GB)を買ったので、ローカルSLM環境を構築します。
なお、dockerとbrewは使用しておりません。

# 環境
- M4 Mac mini (RAM:32GB , DISK:512GB)
- macOS Sequoia 15.1

## Ollama
コンテナではなく、アプリケーション版をインストールしました。

https://ollama.com/download/mac

外部ホストからも利用したかったため、全てのアドレスからの接続を受け付ける環境変数を設定してから起動します。
そのためターミナルを開いて、起動用シェルスクリプトを作成しました。

```shell:
% vi bin/startup.command
#!/bin/sh

# Set environment variable for Ollama
launchctl setenv OLLAMA_HOST "0.0.0.0"
open -a Ollama
% chmod +x bin/startup.command
```

[システム設定]の[一般]にある、[ログイン項目と機能拡張]で以下のようにシェルスクリプトを登録します。
Ollamaが登録されている場合は、削除してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/919441ce-76cf-605a-a9fe-126205e6da3a.png)

設定したら一旦ログアウトして、ログイン後にOllamaが起動されている事を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/7a56aaa9-f173-c4d0-4f1f-9e7de77a66bb.png)

モデルは好きなものをpullしました。

```shell:
% ollama list
NAME                       ID              SIZE      MODIFIED
llava:latest               8dd30f6b0cb1    4.7 GB    3 days ago
gemma2:2b                  8ccf136fdd52    1.6 GB    3 days ago
nomic-embed-text:latest    0a109f422b47    274 MB    4 days ago
codegemma:7b               0c96700aaada    5.0 GB    4 days ago
gemma2:27b                 53261bc9c192    15 GB     4 days ago
gemma2:9b                  ff02c3702f32    5.4 GB    4 days ago
llama3.2-vision:latest     38107a0cd119    7.9 GB    4 days ago
```

## Podman Desktop
インストーラ(dmgファイル)をダウンロードしてインストールしました。

https://podman-desktop.io/downloads

ダッシュボードの左下の[Settings]-[Resources]にある[Compose]をSetupしておいてください。(以下の画像はSetup済の画面です。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/f7e99b6b-9688-baf0-4d36-5579e160daca.png)

手順的には以下のドキュメントになりますが、内容は薄いです...

https://podman-desktop.io/docs/compose/setting-up-compose

## git
インストール方法は色々ありますが、私はXcode版をインストールしました。

```
% xcode-select install
```

## Dify
みんな大好きgit cloneで一括お取り寄せしました。

```
% git clone https://github.com/langgenius/dify
Cloning into 'dify'...
remote: Enumerating objects: 108540, done.
remote: Counting objects: 100% (12124/12124), done.
remote: Compressing objects: 100% (686/686), done.
remote: Total 108540 (delta 11683), reused 11633 (delta 11432), pack-reused 96416 (from 1)
Receiving objects: 100% (108540/108540), 56.08 MiB | 22.34 MiB/s, done.
Resolving deltas: 100% (78448/78448), done.
```

docker-compose.yaml を少し編集しました。
一括してimageにレジストリ名を付与しました。
dify-sandboxのイメージタグを0.2.10にしています。(これでコードブロックのpythonは動くようになりますが、JavaScriptは動きません)
最下部のnetwork定義にdefault(bridge)を追加しました。

```
% cd dify/docker-legacy
% perl -pi -e "s/image: /image: docker.io\//" docker-compose.yaml
% perl -pi -e 's/^(.*image: docker\.io\/langgenius\/dify-sandbox).*$/$1:0.2.10/' docker-compose.yaml
% vi docker-compose.yaml
% tail docker-compose.yaml
  : (略)
networks:
  # create a network between sandbox, api and ssrf_proxy, and can not access outside.
  ssrf_proxy_network:
    driver: bridge
    internal: true
  default:
    driver: bridge

#volumes:
#  oradata:
```

あとは起動させます。サービスが安定しないようであれば、各コンテナの healthcheck は全部コメントにしてみてください。

```
% podman compose -f docker-compose.yaml up -d
>>>> Executing external compose provider "/usr/local/bin/docker-compose". Please see podman-compose(1) for how to disable this message. <<<<

WARN[0000] /Users/haomei/podman/dify/docker-legacy/docker-compose.yaml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 9/9
 ✔ Container docker-legacy-ssrf_proxy-1  Started                                                                                                          0.2s
 ✔ Container docker-legacy-db-1          Started                                                                                                          0.1s
 ✔ Container docker-legacy-weaviate-1    Started                                                                                                          0.1s
 ✔ Container docker-legacy-sandbox-1     Started                                                                                                          0.1s
 ✔ Container docker-legacy-web-1         Started                                                                                                          0.1s
 ✔ Container docker-legacy-redis-1       Started                                                                                                          0.1s
 ✔ Container docker-legacy-api-1         Started                                                                                                          0.2s
 ✔ Container docker-legacy-worker-1      Started                                                                                                          0.2s
 ✔ Container docker-legacy-nginx-1       Started
```

Podman Desktopは起動時にコンテナを起動してくれませんので、起動用シェルスクリプトのopen -a Ollamaに続けて起動コマンドを追記します。
podman machineはすぐには起動しないので待ち合わせをします。

```
% cat bin/startup.command
#!/bin/sh

# Set environment variable for Ollama
launchctl setenv OLLAMA_HOST "0.0.0.0"
open -a Ollama

# Wait until Podman VM is running
until podman machine ls | grep -qi "running"; do
  echo "Waiting for Podman VM to start..."
  sleep 1
done

podman compose -p docker-legacy start
```


Difyのサービスが起動したら、ログイン設定をしてログインし、モデルプロバイダーの設定をします。
DifyからOllamaには host.containers.internal で接続できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/28095722-5f9a-c439-dd44-ce56fd37193d.png)

ワークフローを組んで、問題なく使えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/cbd5e69f-7b3d-6a31-c22f-d51a35c77024.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/3893e69c-df68-355d-8829-ad9b8ae18a12.png)

が、コードブロックのJavaScriptが動きません。

# おわりに
予算があれば、M4 Proの64GBが欲しかったー

# つづき

https://qiita.com/Y-Shikase/items/752e3156613c1b43b660