GPUを使わずにWindowsでローカルLLMを動かす
はじめに
近年、LLM(大規模言語モデル)をローカル環境で動かすことが注目されている。
しかし、多くのLLMはGPUを必要とするため、GPUを搭載していないWindowsマシンでは動作が難しい。
本記事では、GPUを使わずにWindowsでローカルLLMを動かす方法について解説する。
前提条件
- Git for WindowsなどでGitコマンドが使えること
- Docker Desktop for Windowsなどでdocker、docker composeコマンドが使えること
- Hugging Faceのアカウントを持っていること
- 必ずしも必要ないが、下記の説明ではgemma-3-1bを使用するため、アカウント作成してGoogleの利用規約に許諾する必要がある。
LLMモデルの準備
今回利用するのは以下の2つのモデルである。
- https://huggingface.co/google/gemma-3-1b-it (vLLMで利用)
- https://huggingface.co/google/gemma-3-1b-it-qat-q4_0-gguf (Ollama、llama.cppで利用)
モデルをクローンするのに、以下のコマンドを実行する。
git clone https://huggingface.co/google/gemma-3-1b-it
git clone https://huggingface.co/google/gemma-3-1b-it-qat-q4_0-gguf
Ollamaの場合
ディレクトリ構成は以下のようになる。
.
├ docker-compose.yaml
├ Modelfile
└ gemma-3-1b-it-qat-q4_0-gguf/gemma-3-1b-it-q4_0.gguf
docker-compose.yamlの内容は以下の通りである。
services:
ollama:
image: ollama/ollama:0.13.0
container_name: ollama
ports:
- "11434:11434"
ipc: host
volumes:
- ./gemma-3-1b-it-qat-q4_0-gguf/:/work/gemma-3-1b-it-qat-q4_0-gguf
- ./Modelfile:/work/Modelfile:ro
working_dir: /work
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:11434/health"]
interval: 10s
timeout: 10s
retries: 300
Modelfileの内容は以下の通りである。
FROM ./gemma-3-1b-it-qat-q4_0-gguf/gemma-3-1b-it-q4_0.gguf
PARAMETER stop <|end_of_turn|>
PARAMETER temperature 0.0
PARAMETER top_k 64
PARAMETER top_p 0.95
PARAMETER repeat_penalty 1.5
PARAMETER num_ctx 20480
TEMPLATE """
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1 }}
{{- if or (eq .Role "user") (eq .Role "system") }}<start_of_turn>user
{{ .Content }}<end_of_turn>
{{ if $last }}<start_of_turn>model
{{ end }}
{{- else if eq .Role "assistant" }}<start_of_turn>model
{{ .Content }}{{ if not $last }}<end_of_turn>
{{ end }}
{{- end }}
{{- end }}
"""
パラメータの値は https://ollama.com/library/gemma3:1b を参考に設定している。
以下のコマンドを実行する。
docker compose up -d
docker exec -it ollama ollama create gemma-3-1b -f Modelfile
以下のコマンドで動作確認を行う。
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-3-1b",
"messages": [
{"role": "user", "content": "こんにちは。"}
]
}'
vLLMの場合
ディレクトリ構成は以下のようになる。
vllmはgit clone https://github.com/vllm-project/vllm.gitで取得する。
.
├ docker-compose.yaml
├ vllm
├ vllm_entrypoint.sh
└ gemma-3-1b-it
docker-compose.yamlの内容は以下の通りである。
services:
vllm:
image: ubuntu:24.04
container_name: vllm
ports:
- "8000:8000"
volumes:
- ./gemma-3-1b-it/:/models/gemma-3-1b-it/:ro
- ./vllm_entrypoint.sh:/work/vllm_entrypoint.sh:ro
- ./vllm:/work/vllm
working_dir: /work/vllm
entrypoint: bash -c "/work/vllm_entrypoint.sh"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 10s
retries: 300
vllm_entrypoint.shの内容は以下の通りである。
#!/bin/bash
apt-get update -y
apt-get install -y gcc-12 g++-12 libnuma-dev python3-dev curl git
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 10 --slave /usr/bin/g++ g++ /usr/bin/g++-12
curl -LsSf https://astral.sh/uv/0.9.8/install.sh | env UV_INSTALL_DIR=/root/.local/bin sh
export PATH=$PATH:/root/.local/bin
uv venv --python 3.12 --seed
source ./.venv/bin/activate
uv pip install --upgrade setuptools
uv pip install --upgrade pip
uv pip install -r requirements/cpu-build.txt --index-strategy unsafe-best-match --torch-backend cpu
echo "END requirements/cpu-build.txt"
uv pip install -r requirements/cpu.txt --index-strategy unsafe-best-match --torch-backend cpu
echo "END requirements/cpu.txt"
VLLM_TARGET_DEVICE=cpu uv pip install . --no-build-isolation
echo "END all installations"
# TODO: 絶対パスに直す
python /absolute/path/to/vllm/entrypoints/openai/api_server.py --model /models/gemma-3-1b-it --served-model-name gemma-3-1b-it --host 0.0.0.0 --port 8000 --max-model-len 2048 --dtype bfloat16
以下のコマンドを実行する。
docker compose up -d
以下のコマンドで動作確認を行う。
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-3-1b-it",
"messages": [
{"role": "user", "content": "こんにちは。"}
]
}'
メモ
-
https://docs.vllm.ai/en/stable/getting_started/installation/cpu
-
Set up using Dockerセクションを参考にしていない。ホストOSがWindowsであるためうまく動作しなかった。 -
Set up using Pythonセクションを参考に環境構築している。- ただし、最初はbuild時にDockerfileでuv、sourceコマンドを実行しようとしたが、うまく動作しなかったため、entrypointスクリプトにまとめている。
- uv pip installに
--index-strategy unsafe-best-matchを追加している。これを追加しないと、依存関係の解決に失敗した。
-
llama.cppの場合
ディレクトリ構成は以下のようになる。
llama.cppはgit clone https://github.com/ggml-org/llama.cpp.gitで取得する。
.
├ docker-compose.yaml
├ llama.cpp
└ gemma-3-1b-it-qat-q4_0-gguf
llama.cpp/docs/docker.mdを参考に、以下のコマンドでイメージをビルドする。
cd llama.cpp
docker build -t local/llama.cpp:server-cpu --target server -f .devops/cpu.Dockerfile .
docker-compose.yamlの内容は以下の通りである。
services:
llamacpp:
image: local/llama.cpp:server-cpu
container_name: llamacpp
ports:
- "8080:8080"
volumes:
- ./gemma-3-1b-it-qat-q4_0-gguf/:/work/gemma-3-1b-it-qat-q4_0-gguf
command: >
--model /work/gemma-3-1b-it-qat-q4_0-gguf/gemma-3-1b-it-q4_0.gguf
--host 0.0.0.0
--port 8080
--ctx-size 2048
--verbose
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
resources:
limits:
memory: 8G
reservations:
memory: 4G
以下のコマンドを実行する。
docker compose up -d
以下のコマンドで動作確認を行う。
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-3-1b-it-q4_0",
"messages": [
{"role": "user", "content": "こんにちは。"}
]
}'
おわりに
本記事では、GPUを使わずにWindowsでローカルLLMを動かす方法について解説した。
Ollama、vLLM、llama.cppの3つの方法を紹介したが、用途や環境に応じて適切な方法を選択してほしい。
Discussion