コーディング補完のLLMがローカル環境に欲しいなと思って構築した時のメモ

環境

  • Debian 13
  • Docker version 29.8.0
  • vim
  • vim-ollama

Docker

GPU確認

DockerでGPUが有効になっている事を確認。こんな感じの表示が出たらOK(しょぼいGPU…)

1
2
3
4
5
6
7
8
9
10
11
$ docker run --rm --gpus all ubuntu nvidia-smi
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.163.01 Driver Version: 550.163.01 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce GTX 980 On | 00000000:01:00.0 Off | N/A |

(以下省略)

蛇足ですが、このGPUでは古すぎてDebianにドライバが見つからず、今回は結局使わずに終わりました

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
services:
# Ollama本体
ollama:
image: ollama/ollama:latest
container_name: llm-ollama
restart: "no"
ports:
- "${OLLAMA_PORT:-11434}:11434"
environment:
- OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-30m}
volumes:
- ${OLLAMA_DATA_DIR}:/root/.ollama
healthcheck:
test: ["CMD", "ollama", "list"]
interval: 5s
timeout: 5s
retries: 20
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

# モデルダウンロード用コンテナ(使い捨て)
ollama-pull:
image: ollama/ollama:latest
depends_on:
ollama:
condition: service_healthy
environment:
- OLLAMA_HOST=http://llm-ollama:11434
restart: "no"
entrypoint: ["/bin/sh", "-c"]
command:
- |
for m in ${OLLAMA_MODELS}; do
ollama pull "$$m"
done

.env

1
2
3
4
5
6
7
8
9
10
11
12
# 出力ファイルの保存先(絶対PATHで指定)
OLLAMA_DATA_DIR=/home/<ユーザー名>/.ollama

# 待ち受けポート
OLLAMA_PORT=11434

# モデルをVRAMに残す時間(デフォルトは5分)
OLLAMA_KEEP_ALIVE=30m

# 起動時にダウンロードするモデル(スペース区切りで複数指定可)
# OLLAMA_MODELS=llama3.1:8b
OLLAMA_MODELS=llama3.2:3b starcoder2:3b
パラメータ セット内容
OLLAMA_DATA_DIR 出力ファイルの保存先(絶対PATHで指定)
OLLAMA_PORT 待ち受けポート
OLLAMA_KEEP_ALIVE モデルをVRAMに保持する時間
OLLAMA_MODELS 起動時にダウンロードするモデル

OLLAMA_DATA_DIR

モデルをダウンロードする保存先。ダウンロードするモデルによっては、数GB必要になってくるので、ディスク容量に余裕のあるPathを絶対PATHで指定します

OLLAMA_KEEP_ALIVE

長く保持しておくほど、補完の応答が早くなります

OLLAMA_MODELS

ここが、補完の精度を決める勘所となります。ダウンロードするモデルをスペース区切りで指定します。
ダウンロード出来るモデルは、公式サイトで確認出来ます。

以下、Claudeにオススメのモデルを聞いてみました
★のついているモデルは、CPU推論の環境で最初に試すことをお勧めするものだそうです (つまり軽量のモデル)

チャット・レビュー系

開発元 モデル 容量 構造 CPUでの速度の目安 備考
Google gemma4:e2b 約7.2GB 密(実効2B) 速い 最軽量。多言語対応、ツール呼び出し対応
Google gemma4:e4b ★ 約9.6GB 密(実効4B) やや速い 既定のタグ。チャットの第一候補
Google gemma4:12b 要確認 遅い(毎秒2〜3) 2026年6月に追加。CPUには重い
Google gemma4:26b ★ 約18GB MoE(実効4B) 中(毎秒5〜8前後) レビュー向き。RAMに載る
Google gemma4:31b 約20GB 非常に遅い(毎秒1前後) 最高品質だが、実用的でない
Google gemma3:4b 約3GB(記憶ベース) 速い 旧世代。RAMを節約したいとき
Meta llama3.2:3b 約2GB 速い(毎秒約12、実測) 日本語は不自然になりやすい
Meta llama3.1:8b 約4.7GB やや遅い(毎秒4〜5) 無難な基準。日本語は控えめ
Meta llama3.3:70b、Llama 4系 40GB以上 密 / MoE 載らない RAM(約31GiB)に入らない

コード補完系

FIM対応が必須(後述の追記)

開発元 モデル 容量 CPUでの速度の目安 備考
Google codegemma:2b ★ 約1.6GB 速い(毎秒15前後) 1行の補完の成功率が高い(Googleの公開データ)
Google codegemma:7b-code 約5GB 遅い(毎秒4〜5) 複数行の補完に強い。7b はinstruct版の可能性があり、要確認
Meta codellama:7b-code 約3.8GB やや遅い(毎秒5〜6) 2023年の世代で、精度は控えめ(HumanEval 33.5%)

とりあえず今回は、このようにしてみました

1
OLLAMA_MODELS=starcoder2:3b gemma4:e4b gemma4:26b codegemma:2b llama3.2:3b codellama:7b-code

(追記) gemma系を使用する場合はFIM設定ファイルが必要

補完の際、「FIMファイル」という、モデルに「カーソルの前のコード」と「カーソルの後ろのコード」を渡して、「このモデルには、こういう目印で渡す」という対応表を書いた、小さなテキストファイル(JSON)が必要なようで、gemma系のモデルを使用すると、ずっと以下のようなエラーが出ていました

OllamaLogger - ERROR - Config file not found for codegemma

これを解決するために、以下の事をしました

1
2
3
4
5
6
7
$ cat ~/.vim/plugged/vim-ollama/python/configs/codegemma.json
{
"pre": "<|fim_prefix|>",
"middle": "<|fim_middle|>",
"suffix": "<|fim_suffix|>",
"eot": "<|file_separator|>"
}

構成確認&構築

設定値が反映されているか、最終確認して、

1
$ docker compose config

コンテナをビルド&起動します

1
$ docker compose up -d

ログを眺めてみると、このようにモデルのダウンロードが進行すると思います。 successが表示されるまで待ちましょう

1
2
3
4
5
6
7
8
9
$ docker compose logs -f ollama-pull

pulling manifest
ollama-pull-1 | pulling 4c27e0f5b5ad: 100% ▕█████████████████ ▏ 9.6 GB/9.6 GB 19 MB/s 0s
pulling manifest
ollama-pull-1 | pulling 4c27e0f5b5ad: 100% ▕█████████████████ ▏ 9.6 GB/9.6 GB 19 MB/s 0s
ollama-pull-1 | verifying sha256 digest
ollama-pull-1 | writing manifest
ollama-pull-1 | success

ダウンロードが完了すると、以下のコマンドでモデルの一覧が確認出来ます

1
2
3
4
5
6
7
$ docker compose exec ollama ollama list
NAME ID SIZE MODIFIED
gemma4:e4b c6eb396dbd59 9.6 GB 26 minutes ago
gemma4:26b 08ae7ec1744b 18 GB 10 minutes ago
codegemma:2b 926331004170 1.6 GB 10 minutes ago
codellama:7b-code 8df0a30bb1e6 3.8 GB 10 minutes ago
llama3.2:3b a80c4f17acd5 2.0 GB 10 minutes ago

Ollama

主要コマンド

管理系コマンドの一覧

1
2
3
4
$ docker compose exec ollama ollama list                # ダウンロード済みのモデル一覧
$ docker compose exec ollama ollama ps # 今メモリに載っているモデル
$ docker compose exec ollama ollama show <モデル名> # モデルの詳細
$ docker compose exec ollama ollama rm <モデル名> # 削除

チャット

使ってみる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker compose exec -it ollama ollama run gemma4:26b --verbose
>>> おはよウサギ
Thinking... ...done thinking.

おはよウサギ!🐰🥕
今日も一日、楽しく元気に過ごしましょうね!✨

total duration: 1m13.376420431s
load duration: 1.270989ms
prompt eval count: 22 token(s)
prompt eval cached: 16 token(s)
prompt eval duration: 411.722ms
prompt eval rate: 14.57 tokens/s
eval count: 544 token(s)
eval duration: 1m12.887118s
eval rate: 7.46 tokens/s

貧弱なPCなので、ずいぶん時間がかかりました

1
>>> /bye

終了は /byeです

Vim

プラグインのインストール

gergap/vim-ollamaをインストールします。ご自身で使用しているパッケージマネージャでインストールして下さい(本記事では vim-plug使用)

1
2
3
4
5
// .vimrcに追記
Plug 'gergap/vim-ollama'

// インストール
:PlugInstall

vim-ollamaの設定

:Ollama configを実行するか、 ~/.vim/config/ollama.vimファイルを直接開きます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
" Use Python virtual environment (and install packages via pip)
let g:ollama_use_venv = 1
" Ollama base URL
let g:ollama_host = 'http://localhost:11434'

" コード補完
let g:ollama_model = 'starcoder2:3b'

" チャット・レビュー
let g:ollama_chat_model = 'gemma4:e4b'
let g:ollama_edit_model = 'gemma4:e4b'

" 補完に際にモデルに渡すカーソル前後のコードの行数
let g:ollama_context_lines = 5
" 候補の数
let g:ollama_completion_candidates = 1

" 入力が止まってから、補完を開始するまでの待ち時間(ミリ秒)
let g:ollama_debounce_time = 500

" このファイルタイプだけ入力補完を行う
let g:ollama_completion_allowlist_filetype = ['sh', 'markdown', 'terraform', 'python']
" このファイルタイプは入力補完を行わない
"let g:ollama_completion_denylist_filetype = []

" チャットに渡すプロンプト
let g:ollama_chat_systemprompt = 'Always respond in Japanese (日本語で回答してください). Keep code, identifiers and technical terms in English. Be concise.'

" デバッグ・ログ設定
" let g:ollama_debug = 4
" general log file location
" let g:ollama_logfile = '/tmp/logs/vim-ollama.log'
" ollama chat conversation log
"let g:ollama_review_logfile = '/tmp/logs/vim-ollama-review.log'

" Setting to display suggestions manually instead of automatically
" let g:ollama_debounce_time = 0
" imap <silent> <C-l> <Plug>(ollama-trigger-completion)
" vim: filetype=vim.ollama

主要な設定だけピックアップします

モデル

使用するモデルを設定

1
2
3
4
5
6
" コード補完
let g:ollama_model = 'starcoder2:3b'

" チャット・レビュー
let g:ollama_chat_model = 'gemma4:e4b'
let g:ollama_edit_model = 'gemma4:e4b'

補完

いずれも、少なくすると補完が早くなります

1
2
3
4
" 補完に際にモデルに渡すカーソル前後のコードの行数
let g:ollama_context_lines = 5
" 補完する候補の数
let g:ollama_completion_candidates = 1

ファイルタイプ

補完する,しないファイルタイプをここで設定。補完の必要ないファイルでムダな補完が行われなくなります

1
2
3
4
" このファイルタイプだけ入力補完を行う
let g:ollama_completion_allowlist_filetype = ['sh', 'markdown', 'terraform', 'python']
" このファイルタイプは入力補完を行わない
"let g:ollama_completion_denylist_filetype = []

プロンプト

チャットの時に、日本語で返してくれなかったので設定してます

1
2
" チャットに渡すプロンプト
let g:ollama_chat_systemprompt = 'Always respond in Japanese (日本語で回答してください). Keep code, identifiers and technical terms in English. Be concise.'

vim-ollamaの操作方法

入力モードで、 let g:ollama_debounce_time = 500で設定した秒数が経過すると補完が開始されます

001

Tabを押すと補完確定

他には、以下のようなコマンドで操作出来るみたいですが、自分の環境では Tab以外動きませんでした
他のプラグインのキーバインドと被ってたのかもしれません

操作 内容
Tab 提案をすべて採用する
Alt + → 提案の次の1行だけ採用する
Ctrl + Alt + → 提案の次の1単語だけ採用する
Ctrl + ] 提案を消す
Alt + ↓ / Alt + ↑ 別の候補に切り替える( g:ollama_completion_candidates を2以上の時のみ)

他には、以下のような操作もあります

コマンド 内容 変更されるか
:’<,’>OllamaReview 選択範囲のコードレビュー 変更されない。結果はチャット画面に出る
:’<,’>OllamaExplain 選択範囲の解説 変更されない(読み取り専用)
:’<,’>OllamaTask “指示” 任意の指示(例: “日本語でコメントを付けて”)。結果はチャット画面に出て、手でコピーする必要がある 変更されない
:’<,’>OllamaSpellCheck スペルチェック 変更されない
:’<,’>OllamaEdit “指示” 指示に従って、選択範囲を書き換える 変更される