「Modelfileでシステムプロンプトを調整してみたが、それだけでは回答の一貫性が改善しない場面がある…」
そんな悩みを抱えるインフラエンジニア・MLエンジニアは多いはずです。この記事では、Unslothを使ったLoRAによるfine-tuning、llama.cppでのGGUF変換、そしてOllamaへのModelfileインポートまでの一連の手順を解説します。RAGやModelfileのシステムプロンプトでは対応しきれない業務特化モデルを、手元のLinuxサーバーのGPUで作成し、チームで運用するまでの流れをカバーします。
この記事のポイント
・LoRA+Unslothで ollama run できるカスタムモデルをGPU1枚で作れる
・学習データはJSONL形式のinstruction-outputペアを100件以上用意するのが品質の目安
・llama.cppの convert_hf_to_gguf.py でHugging Face形式→GGUF変換後、Modelfileでインポートする
・量子化タグ q4_K_M でVRAMを抑えつつ本番運用に耐える品質を保てる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
ローカルLLMのfine-tuningとは|RAGやModelfileとの違いを整理する
fine-tuningは、既存の大規模言語モデルをベースに、追加データでモデルの重みを更新して新しいモデルを作る手法です。RAGが「検索して文脈に差し込む」手法であるのに対し、fine-tuningは「モデル自体の振る舞いを変える」手法です。RAGが得意なのは最新情報の参照や大量ドキュメントへのQ&Aです。一方で、回答のスタイルや口調・専門用語の使い方を一貫させたい場合はRAGでは限界があります。
Modelfileのシステムプロンプトで補える部分も多いですが、モデルが学習段階で触れていない特定の業界用語や固有名詞の正確な使い方は、プロンプトで指示するだけでは対応しきれません。
1. RAGとfine-tuningの使い分け基準
RAGで解決できる問題は、まずRAGで対応するのが鉄則です。fine-tuningはコストと時間がかかるため、本当に必要な場面に絞るべきです。fine-tuningが有効になるのは次のような場面です。
・回答フォーマットの一貫性をどれだけ指示しても保てない
・社内固有の略称・製品名・業界用語をモデルが誤読する
・特定の口調や文体でしか運用できない(カスタマーサポートBot等)
・RAGが不向きな短いQ&Aパターンが主な用途
社内でクラウドAIを使えない事情がある場合のローカルLLM導入背景については、社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢 で詳しく解説しています。
2. ベースモデルの選び方
fine-tuningするモデルを選ぶ基準はVRAMと用途のバランスです。現場のインフラエンジニアから聞く話では、7Bクラスのモデルが最も試しやすいとのことです。・Llama3.3(8B): 日本語・英語どちらにも対応し、instruction-followingが安定している
・Mistral(7B): 軽量で高速。英語特化タスクで強みを発揮
・Gemma 3(4B・8B): Googleが公開する新世代モデル。4Bでも品質が高く小型GPUでも動作する
70B以上のモデルをfine-tuningするにはVRAM 80GB以上が必要になるため、まず7B~12Bで検証してから規模を上げる判断をする方が現実的です。
モデルごとの性格の違いは ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント を参照してください。
fine-tuning環境を構築する|GPU・Python・Unslothのセットアップ
fine-tuning環境はOllamaの推論環境とは別に構築します。Ollamaのサーバーを動かしているLinuxマシンで作業するのが最も効率的です。Unslothはfine-tuningを高速化・メモリ効率化するライブラリで、通常のHugging Face Transformers+PEFTでのLoRA学習より2倍以上速く動作するとされています。
1. ハードウェア要件の確認
Llama3.3 8Bをfine-tuningする場合の目安は以下の通りです。・VRAM: 最低16GB(RTX 4080クラス)、推奨24GB(RTX 3090/4090クラス)
・RAM: 32GB以上(学習データの前処理に使う)
・ストレージ: ベースモデル+チェックポイントを含め500GB以上の空き
・OS: Ubuntu 22.04 LTS(CUDAドライバー 12.x 対応済み)
Ollamaの構築がまだの場合は先に Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド を読んでから進めてください。
GPUが搭載されているかどうかは次のコマンドで確認できます。
$ nvidia-smi --query-gpu=name,memory.total --format=csv,noheader NVIDIA GeForce RTX 4090, 24564 MiB
2. Python仮想環境とUnslothのセットアップ
Python仮想環境を作成してUnslothをインストールします。システムのPython環境を汚染しないよう、必ず仮想環境で作業してください。# Python仮想環境の作成とアクティベート $ python3 -m venv ~/finetune-env $ source ~/finetune-env/bin/activate # Unslothのインストール(CUDA 12.1向け) $ pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git" $ pip install --no-deps trl peft accelerate bitsandbytes datasets # CUDAが認識されているか確認 $ python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)" True 12.1
学習データを準備する|JSONLフォーマットとinstruction-outputペアの作り方
fine-tuningの品質は学習データの品質で9割が決まります。データの形式と内容の質にはとくに気を使う必要があります。100件のデータでも高品質であれば実用レベルのモデルが作れます。逆に1,000件あっても品質が低いデータは過学習を引き起こすリスクがあります。
1. Alpacaフォーマットのデータ構造
Llama系モデルのfine-tuningでは、Alpacaフォーマット(instruction・input・output の3フィールド)が定番です。JSONLファイル(1行1レコード)で準備します。# dataset.jsonl の例(1行1レコード) {"instruction": "次のLinuxエラーを日本語で解説してください", "input": "No space left on device", "output": "このエラーはディスクの空き容量が不足していることを示します。`df -h` でどのパーティションが満杯かを確認し、不要なファイルを削除するか、`/var/log` 以下の古いログをローテートしてください。"} {"instruction": "次のLinuxコマンドの用途を説明してください", "input": "journalctl -u nginx --since '1 hour ago'", "output": "このコマンドは過去1時間のnginxサービスのログを表示します。`-u` でサービスを絞り込み、`--since` で取得開始時刻を指定しています。"}
2. データ品質チェックのポイント
学習データを作る際に守るべき原則は次の通りです。・outputの文字数は50字以上500字以内を目安にする(短すぎると学習できず、長すぎると不安定)
・多様なinstruction形式(質問形・命令形・会話形)を混在させると汎化性能が上がる
・同じinstructionの繰り返しが多いと過学習になるため、類似レコードは削除か書き直しをする
事前にjqでレコードの件数とoutput文字数を確認してから学習を始めると安全です。
# レコード件数の確認 $ wc -l dataset.jsonl 124 dataset.jsonl # 各レコードのoutput文字数の分布確認(最大・最小・中央) $ cat dataset.jsonl | jq -r '.output | length' | sort -n | awk 'NR==1{min=$1} {max=$1; sum+=$1; n++} END{print "min=" min, "max=" max, "avg=" int(sum/n)}' min=42 max=498 avg=187
UnslothでLoRA学習を実行する|Pythonスクリプトの書き方と実行手順
環境とデータが揃ったら学習を実行します。LoRAはモデルの全パラメータを更新するのではなく、低ランク行列を追加して差分だけを学習する手法です。フルパラメータのfine-tuningと比べてVRAMを大幅に節約できます。UnslothはこのLoRA学習にさらに独自の最適化を加えており、同じGPUでもメモリ効率が大きく改善します。
1. ベースモデルのロードとLoRA設定
Pythonスクリプト `train.py` を作成します。`r=16` はLoRAのrank(ランク)で、値が大きいほど学習容量が増えますがVRAMも増えます。最初は16が安定した出発点です。# train.py from unsloth import FastLanguageModel from trl import SFTTrainer from transformers import TrainingArguments from datasets import load_dataset model, tokenizer = FastLanguageModel.from_pretrained( model_name="unsloth/llama-3.3-8b-instruct-bnb-4bit", max_seq_length=2048, load_in_4bit=True, ) model = FastLanguageModel.get_peft_model( model, r=16, target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], lora_alpha=16, lora_dropout=0, bias="none", use_gradient_checkpointing="unsloth", )
2. Trainerの設定と学習の実行
データセットを読み込み、SFTTrainerで学習を実行します。`num_train_epochs=3` は3周学習することを意味します。データが少ない場合は3周で十分なことが多いです。# train.py(続き) alpaca_prompt = """以下は指示です。適切な回答を作成してください。 ### 指示: {} ### 入力: {} ### 回答: {}""" def formatting_func(examples): texts = [] for inst, inp, out in zip(examples["instruction"], examples["input"], examples["output"]): text = alpaca_prompt.format(inst, inp, out) + tokenizer.eos_token texts.append(text) return {"text": texts} dataset = load_dataset("json", data_files="dataset.jsonl", split="train") dataset = dataset.map(formatting_func, batched=True) trainer = SFTTrainer( model=model, train_dataset=dataset, dataset_text_field="text", max_seq_length=2048, args=TrainingArguments( per_device_train_batch_size=2, gradient_accumulation_steps=4, num_train_epochs=3, learning_rate=2e-4, output_dir="./output", fp16=True, save_steps=50, logging_steps=10, ), ) trainer.train() model.save_pretrained("./finetuned-model") tokenizer.save_pretrained("./finetuned-model") print("学習完了。./finetuned-model に保存しました。")
$ python train.py ==((====))== Unsloth: Fast Llama patching. Transformers = 4.44.0. \\ /| GPU: NVIDIA GeForce RTX 4090. Max memory: 23.988 GB. ... {'loss': 1.4523, 'learning_rate': 0.0002, 'epoch': 0.5} {'loss': 1.1234, 'learning_rate': 0.00015, 'epoch': 1.0} {'loss': 0.8901, 'learning_rate': 0.0001, 'epoch': 2.0} {'loss': 0.7234, 'learning_rate': 0.00005, 'epoch': 3.0} 学習完了。./finetuned-model に保存しました。
HuggingFace形式からGGUFに変換する|llama.cppのconvert_hf_to_gguf.py手順
fine-tuningで出力されたモデルはHugging Face形式(PyTorchのsafetensors)です。Ollamaが読み込めるのはGGUF形式のみなので、変換が必要です。変換にはllama.cppが提供するPythonスクリプトを使います。
1. llama.cppのセットアップ
# llama.cppをクローンして変換用の依存ライブラリをインストール $ git clone https://github.com/ggerganov/llama.cpp $ cd llama.cpp $ pip install -r requirements.txt # quantizeツールのビルド(量子化に使う) $ make llama-quantize
2. GGUF変換と量子化の実行
まずfloat16のGGUFに変換し、続いて量子化します。変換とは別のステップになっているのがポイントです。# HuggingFace形式→GGUF(float16)に変換 $ python convert_hf_to_gguf.py \ ~/finetuned-model \ --outtype f16 \ --outfile ~/my-custom-model-f16.gguf # q4_K_M量子化(品質とVRAMのバランスが最良) $ ./llama-quantize ~/my-custom-model-f16.gguf \ ~/my-custom-model-q4_K_M.gguf q4_K_M main: build = 3743 llama_model_quantize_internal: model size = 15234.01 MB llama_model_quantize_internal: quant size = 4521.30 MB
変換後のファイルサイズが元のfloat16より75%程度小さくなっていれば成功です。
OllamaにカスタムGGUFをインポートする|Modelfileの書き方と登録手順
GGUFファイルが用意できたら、Ollamaに登録します。OllamaへのインポートはModelfileというテキストファイルでGGUFのパスとパラメータを定義する方式です。1. Modelfileの作成
Modelfileはモデルのメタ情報とシステムプロンプトを定義するファイルです。`FROM` にGGUFファイルの絶対パスを指定します。# ~/my-custom-model/Modelfile FROM /home/user/my-custom-model-q4_K_M.gguf PARAMETER temperature 0.7 PARAMETER num_ctx 4096 PARAMETER repeat_penalty 1.1 SYSTEM """ あなたは社内Linux運用専門のAIアシスタントです。 専門用語は社内標準定義に従って正確に使用してください。 回答は簡潔に、手順は番号付きで提示してください。 """
2. ollama createで登録とollama runで動作確認
# Ollamaにカスタムモデルを登録 $ ollama create my-linux-assistant -f ~/my-custom-model/Modelfile transferring model data creating model layer using existing layer sha256:a1b2c3... writing manifest success # 動作確認 $ ollama run my-linux-assistant "Permission deniedエラーの対処法を教えてください" このエラーはファイルやディレクトリへのアクセス権限が不足しています。 まず ls -la でファイルの権限を確認し、必要に応じて chmod または sudo を使用してください。 # 登録されたモデルの確認 $ ollama list | grep my-linux-assistant my-linux-assistant d3b4e5f6a7b8 4.5 GB 2 minutes ago
OllamaのREST APIからも同じモデル名でアクセスできます。既存アプリとの連携にはモデル名を差し替えるだけで対応できます。
fine-tuningで起きやすいトラブルと対処法|CUDA OOM・壊滅的忘却への対応
fine-tuningを試みたエンジニアから聞く話では、同じトラブルが繰り返し登場します。事前に対処法を知っておくことでデバッグ時間を大きく短縮できます。1. CUDA OOMエラーとVRAM不足への対応
学習中に `RuntimeError: CUDA out of memory` が発生する場合は、次の順で設定を調整します。・`per_device_train_batch_size` を2→1に下げる
・`gradient_accumulation_steps` を4→8に上げて実効バッチサイズを維持する
・`max_seq_length` を2048→1024に下げる
・`load_in_4bit=True` が指定されているか確認する
調整後も解消しない場合は、ベースモデルを Gemma 3(4B)に変更するのが最速の対応策です。
なお学習開始前にVRAMの空きを確認する習慣をつけると安全です。
# 学習開始前にVRAM空き容量を確認 $ nvidia-smi --query-gpu=memory.free,memory.total --format=csv,noheader 22431 MiB, 24564 MiB
2. 学習後に回答品質が下がる場合(壊滅的忘却)
fine-tuning後に「以前できていた一般的な質問への回答が劣化した」という壊滅的忘却(catastrophic forgetting)が起きることがあります。対策は次の通りです。
・LoRAのrankを16→8に下げてベースモデルへの影響を最小化する
・学習率を `2e-4` から `1e-4` 以下に下げる
・エポック数を3→1~2に抑えて過学習を防ぐ
・学習データに汎用的な質問(日本語説明・コード生成等)を2割程度混ぜる
壊滅的忘却が発生した場合でも、GGUFファイルはローカルに残っています。Modelfileを書き直してOllamaに再登録するだけで即座に元のモデルに戻せます。データを保護しながら反復実験できる点がローカルfine-tuningの大きなメリットです。
まとめ|OllamaでローカルLLMをfine-tuningして業務特化モデルを運用する
UnslothのLoRAによるfine-tuningは、クラウドAI不要・データ外部送信なしで業務特化モデルを作れる実用的な手段です。RTX 4090クラスのGPU1枚で7Bモデルのfine-tuningから本番投入まで完結できます。手順のポイントを整理します。
| 工程 | コマンド・ファイル | 備考 |
|---|---|---|
| 環境構築 | pip install "unsloth[colab-new] @ git+..." |
Python仮想環境内で実施・CUDA 12.x 必須 |
| データ準備 | dataset.jsonl(Alpacaフォーマット) | 100件以上・output 50~500字・品質優先 |
| LoRA学習 | python train.py |
RTX 4090で7Bモデル・120件なら約15分 |
| GGUF変換 | python convert_hf_to_gguf.py ... --outtype f16 |
llama.cppのclone・pip installが必要 |
| 量子化 | ./llama-quantize model-f16.gguf model-q4_K_M.gguf q4_K_M |
q4_K_Mが品質・サイズのバランス最良 |
| Ollamaへ登録 | ollama create my-model -f Modelfile |
Modelfileでシステムプロンプト・temperatureを設定 |
| 動作確認 | ollama run my-model "テスト質問" |
OOMはbatch_size↓・rank↓で対応、壊滅的忘却はepoch数↓ |
ローカルLLMのfine-tuningは一度手順を身につければ繰り返し使えます。最初は小さいデータセットで試して、lossの下がり方を見ながら改善サイクルを回すことが成功の近道です。
ローカルLLMのfine-tuningを2日間のハンズオンで実践する
この記事で解説したLoRAによるfine-tuning・GGUF変換・Ollamaへのインポートを、実機GPU環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:OllamaとText-to-SQLでPostgreSQLを自然言語で操作する方法|PythonとローカルLLMでSQLを自動生成して業務データを安全に検索する手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます