ローカルLLMファインチューニング実践ガイド【2026年版】——Ollama環境でQwen2.5を自社データで追加学習する完全手順
AI実践ガイド
2026.03.05
- 目次
- はじめに——「使えるAI」と「自社専用AI」の違い
- ファインチューニング基礎知識——4つのアプローチを整理する
- Qwen2.5をファインチューニング対象に選ぶ理由
- 必要なハードウェア・環境の確認
- ステップ1:環境構築——Ollama + Unsloth + Pythonの準備
- ステップ2:学習データの準備——「質」が成否を決める
- ステップ3:QLoRAでQwen2.5をファインチューニングする
- ステップ4:モデルの評価——学習できているか確認する
- ステップ5:Ollamaに取り込んでローカル実行する
- ユースケース別のデータセット設計——どんな会社でも応用できる
- よくあるトラブルと解決策
- コピペで使えるデータ整備プロンプト集
- よくある質問(Q&A)
- まとめ——ファインチューニングは「一度やれば資産になる」
- 参考リンク
目次
- はじめに——「使えるAI」と「自社専用AI」の違い
- ファインチューニング基礎知識——4つのアプローチを整理する
- Qwen2.5をファインチューニング対象に選ぶ理由
- 必要なハードウェア・環境の確認
- ステップ1:環境構築——Ollama + Unsloth + Pythonの準備
- ステップ2:学習データの準備——「質」が成否を決める
- ステップ3:QLoRAでQwen2.5をファインチューニングする
- ステップ4:モデルの評価——学習できているか確認する
- ステップ5:Ollamaに取り込んでローカル実行する
- ユースケース別のデータセット設計——どんな会社でも応用できる
- よくあるトラブルと解決策
- コピペで使えるデータ整備プロンプト集
- よくある質問(Q&A)
- まとめ——ファインチューニングは「一度やれば資産になる」
- 参考リンク
はじめに——「使えるAI」と「自社専用AI」の違い
ChatGPTやClaudeは確かに優秀です。しかし「自社の製品名・社内用語・業界特有の表現・過去の事例」を深く理解した回答を安定して出力させようとすると、プロンプトエンジニアリングだけでは限界があります。さらにクラウドAPIは通信コスト・プライバシーリスク・月額費用という3つの課題を抱えています。
この課題を解決するのがローカルLLMのファインチューニングです。自社のデータで追加学習させたモデルをローカル環境で動かすことで、「自社専用AI」が完成します。
当サイトではローカルLLM入門・ハードウェア構築ガイド・モデル選定ガイドとシリーズを展開してきましたが、本記事では「実際にファインチューニングを行う」最終ステップを完全手順で解説します。
対象モデルはQwen2.5(Alibaba製)、学習手法はQLoRA、実行フレームワークはUnsloth、運用環境はOllamaです。この組み合わせは2026年現在、コスト・速度・日本語性能のバランスが最も優れた構成として多くの実践者に採用されています。
ファインチューニング基礎知識——4つのアプローチを整理する
フルファインチューニング vs PEFT
LLMの追加学習には大きく「フルファインチューニング」と「PEFT(Parameter-Efficient Fine-Tuning)」の2つに分かれます。
| 手法 | 学習するパラメータ | 必要VRAM | 学習時間 | 現実的な用途 |
|---|---|---|---|---|
| フルファインチューニング | モデル全体(全パラメータ) | 非常に大きい(7Bで80GB+) | 長い | 研究機関・大企業のクラスタ環境 |
| LoRA | 追加した低ランク行列のみ(全体の1〜5%程度) | 中程度(7Bで16〜24GB) | 中程度 | 中規模GPU(RTX 4090等) |
| QLoRA | LoRAと同じ(元モデルを4bit量子化) | 少ない(7Bで8〜12GB) | 中程度 | コンシューマGPU(RTX 3090/4080等) |
| プロンプトチューニング | プロンプト埋め込みのみ | 最小 | 短い | タスク固定・大規模モデルの軽微な調整 |
本記事ではQLoRAを採用します。コンシューマGPU(VRAM 8GB〜24GB)で実用的なファインチューニングが可能であり、2026年現在の中小企業・個人開発者にとって最も現実的な選択肢です。
LoRA / QLoRAの仕組み
LoRAは、元のモデルの重みを変更する代わりに「小さな追加行列(アダプター)」を挿入し、そのアダプターのみを学習します。元モデルの重みは凍結されるため、学習コストが大幅に削減されます。
QLoRAはLoRAをさらに進化させ、元モデルを4ビット量子化(NF4形式)で保持することでVRAM使用量をさらに削減します。精度の低下は最小限に抑えられており、実用上問題にならないケースがほとんどです。
学習完了後は「元モデル + アダプター(LoRAウェイト)」の形で保存し、推論時にマージするか、アダプターを個別に読み込む運用が可能です。
アプローチ選択マトリクス
| やりたいこと | 推奨アプローチ | 理由 |
|---|---|---|
| 自社の専門用語・製品名を正確に扱わせたい | QLoRA(本記事) | 少量データでも専門知識の注入に効果的 |
| 特定のフォーマットで出力させたい(JSON・報告書等) | QLoRA or プロンプトチューニング | 出力形式の固定はLoRAが最も安定 |
| クラウドAPIとほぼ同等の汎用性を保ちつつ特化させたい | RAG(ファインチューニング不要) | 知識の更新が頻繁な場合はRAGが効率的 |
| まったく新しいタスク(翻訳・分類等)を覚えさせたい | QLoRA + 大量データ | タスク自体の学習にはある程度のデータ量が必要 |
| モデル全体の性格・トーンを変えたい | QLoRA(会話形式データセット) | キャラクター・ペルソナの注入はLoRAが有効 |
Qwen2.5をファインチューニング対象に選ぶ理由
本記事でQwen2.5を選ぶ理由は以下の通りです。
| 評価軸 | Qwen2.5の状況 | 日本語利用での優位性 |
|---|---|---|
| 日本語性能 | Qwen2.5は中国語・英語に加えて日本語のトークナイザー精度が高く、LLM日本語ベンチマークで上位の成績 | 日本語テキストのトークン効率が良く、同じVRAMでより多くの文脈を処理できる |
| モデルサイズの豊富さ | 0.5B・1.5B・3B・7B・14B・32B・72Bとバリエーションが豊富 | VRAMに合わせてモデルサイズを選択可能。7Bがコスパの基準点 |
| ライセンス | Qwen2.5はApache 2.0ライセンスで商用利用可能(72Bを除く) | 社内業務・商用サービスへの組み込みに制約が少ない |
| ファインチューニング実績 | Unsloth等の主要フレームワークが公式サポート。サンプルコードが豊富 | 情報収集・トラブル解決がしやすい |
| Ollamaサポート | Qwen2.5の各サイズがOllamaの公式モデルライブラリに掲載 | ファインチューニング後のGGUF変換→Ollama登録の手順が確立されている |
本記事ではQwen2.5-7Bをベースモデルとして使用します。VRAM 12GB前後のコンシューマGPUでファインチューニングが可能で、性能と実用性のバランスが最も取れたサイズです。
必要なハードウェア・環境の確認
GPU VRAM別の対応モデルサイズ
| GPU VRAM | 代表的なGPU | QLoRAで学習可能なQwen2.5サイズ | 推奨バッチサイズ |
|---|---|---|---|
| 8GB | RTX 3070・4060Ti・A10G(AWS) | 3B(快適)・7B(ギリギリ) | 1〜2 |
| 12GB | RTX 3080・4070・T4(GCP) | 7B(快適)・14B(設定次第) | 2〜4 |
| 16GB | RTX 3080Ti・4080・A100-16GB(クラウド) | 7B(余裕)・14B(快適) | 4〜8 |
| 24GB | RTX 3090・4090・A5000 | 14B(快適)・32B(可能) | 8〜16 |
| 80GB | A100-80GB・H100 | 72B(快適) | 16〜32 |
クラウドGPUの活用: 手元にGPUがない場合は、Google Colab Pro+(A100・L4)・Vast.ai・RunPod等のクラウドGPUを利用できます。Qwen2.5-7BのQLoRA学習は1〜3時間程度で完了するため、コストは数百円〜数千円程度に抑えられます。
推奨環境構成
| コンポーネント | 推奨スペック | 備考 |
|---|---|---|
| OS | Ubuntu 22.04 LTS | Windowsの場合はWSL2(Ubuntu 22.04)を使用 |
| GPU | NVIDIA RTX 3080以上(VRAM 12GB+) | CUDAドライバ 12.0以上が必要 |
| RAM | 32GB以上 | 学習データのロード・前処理に使用 |
| ストレージ | 100GB以上の空き容量(SSD推奨) | ベースモデル(〜15GB)+データセット+チェックポイント |
| Python | 3.10 / 3.11 | 3.12は一部ライブラリと非互換の場合あり |
| CUDA | 12.1以上 | nvidia-smiで確認可能 |
ステップ1:環境構築——Ollama + Unsloth + Pythonの準備
Ollamaのインストール
# Ollamaのインストール(Linux/WSL2)
curl -fsSL https://ollama.com/install.sh | sh
# インストール確認
ollama --version
# Qwen2.5-7Bの取得(推論・動作確認用)
ollama pull qwen2.5:7b
# 動作確認
ollama run qwen2.5:7b "こんにちは。あなたは何ができますか?"
Unslothのインストール
Unslothは2024年に登場した高速ファインチューニングライブラリです。HuggingFaceのtransformersと比較して学習速度が2〜5倍、VRAMが30〜60%少なく済むのが特徴です。Qwen2.5を含む主要モデルを公式サポートしています。
# 仮想環境の作成(推奨)
python -m venv venv_finetune
source venv_finetune/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
pip install datasets transformers sentencepiece
# バージョン確認
python -c "import unsloth; print(unsloth.__version__)"
Google Colabで実行する場合: Colabでは仮想環境不要です。セルの先頭に !pip install を追記し、ランタイムをGPU(T4またはA100)に設定して実行してください。
動作確認
import torch
print(f"CUDA利用可能: {torch.cuda.is_available()}")
print(f"GPU名: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB")
from unsloth import FastLanguageModel
print("Unsloth: インポート成功")
ステップ2:学習データの準備——「質」が成否を決める
学習データの形式
QLoRAでの学習に使用するデータセットは、「instruction(指示)」「input(入力)」「output(期待する出力)」の3フィールドを持つJSON Lines(.jsonl)形式が一般的です。
// train_data.jsonl のサンプル(1行が1サンプル)
{"instruction": "以下の問い合わせに、当社のサポートポリシーに基づいて回答してください。", "input": "製品の保証期間はいつまでですか?", "output": "弊社製品の保証期間は購入日より1年間です。保証期間内の自然故障については無償修理または交換対応いたします。なお、保証書と購入証明書のご提示が必要です。"}
{"instruction": "以下の技術用語を社内マニュアルの表現に沿って説明してください。", "input": "RAGとは何ですか?", "output": "RAG(Retrieval-Augmented Generation)とは、社内の文書データベースから関連情報を検索し、その情報をもとにAIが回答を生成する仕組みです。当社では顧客サポートシステムに採用しており、製品マニュアルQ&A機能の基盤技術として利用しています。"}
{"instruction": "以下のメール文章を、当社の標準ビジネスメールフォーマットに変換してください。", "input": "田中さん、昨日の件ですが来週月曜の14時でいかがでしょうか。", "output": "田中様\n\nお世話になっております。株式会社〇〇の山田でございます。\n先日はお時間をいただきありがとうございました。\n\nご相談させていただきました件につきまして、来週月曜日(〇月〇日)14時00分にてお時間をいただけますでしょうか。\n\nご都合をお聞かせいただけますと幸いです。\nどうぞよろしくお願いいたします。\n\n株式会社〇〇\n山田 太郎"}
自社データのクレンジング手順
学習データの質がファインチューニングの成否を決めます。以下の手順でデータをクレンジングしてください。
個人情報・機密情報の除去
顧客名・電話番号・メールアドレス・住所などは正規表現またはNER(固有表現認識)で検出し、プレースホルダー([顧客名]・[電話番号]等)に置換する。
重複データの除去
完全一致・類似文書の重複を除去する。重複が多いとそのパターンに過学習するリスクがある。
品質フィルタリング
出力が極端に短い(10文字以下)・明らかに誤った情報を含む・文字化けしているデータを除去する。
バランス調整
特定のトピックに偏らないようにデータの分布を確認する。偏りがある場合は少ないカテゴリのデータを追加収集するか、多いカテゴリをダウンサンプリングする。
フォーマット統一
instruction / input / output の3フィールドに変換する。既存のQ&Aデータ・マニュアル・過去のメール対応事例などを変換する作業が多くの企業で必要になる。
データ量の目安
| 目的 | 推奨データ件数 | 品質の目安 |
|---|---|---|
| 出力フォーマットの固定(JSON出力・定型報告書等) | 50〜200件 | 少量でも高品質なサンプルで十分 |
| 専門用語・社内知識の注入 | 200〜1,000件 | 用語ごとに複数の文脈で登場させる |
| 特定ドメインのQ&A特化(製品サポート等) | 500〜3,000件 | 実際の問い合わせ事例が最も有効 |
| 文体・トーンの調整 | 300〜1,000件 | ターゲットの文体で書かれた実例が必要 |
| 新しいタスクの学習(翻訳・要約等) | 3,000〜10,000件 | 多様な入力パターンを網羅する |
重要: データが少ない(50〜200件程度)場合は、learning_rateを低く(1e-5〜2e-5)・num_train_epochsを少なく(1〜2)設定して過学習を防ぐことが重要です。
ステップ3:QLoRAでQwen2.5をファインチューニングする
学習スクリプトの全体像
from unsloth import FastLanguageModel
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments
import torch
# ==============================
# 1. モデルのロード(4bit量子化)
# ==============================
max_seq_length = 2048 # 最大シーケンス長。VRAMに応じて調整
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "Qwen/Qwen2.5-7B-Instruct",
max_seq_length = max_seq_length,
dtype = None, # Noneで自動検出(bfloat16推奨)
load_in_4bit = True, # QLoRA: 4bit量子化でロード
)
# ==============================
# 2. LoRAアダプターの設定
# ==============================
model = FastLanguageModel.get_peft_model(
model,
r = 16, # LoRAランク。8〜64の範囲で調整
target_modules = [ # 学習対象のモジュール
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_alpha = 16, # LoRAスケーリング係数(通常はrと同値)
lora_dropout = 0, # Unslothでは0が最適化されている
bias = "none",
use_gradient_checkpointing = "unsloth", # VRAMを節約
random_state = 42,
)
# ==============================
# 3. データセットの準備
# ==============================
# Alpaca形式のプロンプトテンプレート
ALPACA_PROMPT = """以下は、タスクを説明するinstructionと、追加のcontextを提供するinputです。
要求を適切に満たすResponseを書いてください。
### Instruction:
{}
### Input:
{}
### Response:
{}"""
EOS_TOKEN = tokenizer.eos_token
def format_prompts(examples):
instructions = examples["instruction"]
inputs = examples["input"]
outputs = examples["output"]
texts = []
for instruction, input_text, output in zip(instructions, inputs, outputs):
text = ALPACA_PROMPT.format(instruction, input_text, output) + EOS_TOKEN
texts.append(text)
return {"text": texts}
# ローカルのJSONLファイルを読み込む場合
dataset = load_dataset("json", data_files="train_data.jsonl", split="train")
dataset = dataset.map(format_prompts, batched=True)
# ==============================
# 4. 学習設定
# ==============================
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = max_seq_length,
dataset_num_proc = 2,
args = TrainingArguments(
per_device_train_batch_size = 2, # VRAMが足りない場合は1に下げる
gradient_accumulation_steps = 4, # 実効バッチサイズ = 2 × 4 = 8
warmup_steps = 5,
num_train_epochs = 3, # データ量が少ない場合は1〜2
learning_rate = 2e-4,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 10,
optim = "adamw_8bit",
weight_decay = 0.01,
lr_scheduler_type = "cosine",
output_dir = "./outputs",
save_steps = 100,
),
)
# ==============================
# 5. 学習の実行
# ==============================
trainer_stats = trainer.train()
print(f"学習完了: {trainer_stats.metrics}")
# ==============================
# 6. モデルの保存(LoRAウェイト)
# ==============================
model.save_pretrained("./lora_model")
tokenizer.save_pretrained("./lora_model")
print("LoRAモデル保存完了: ./lora_model")
主要パラメータの解説
| パラメータ | 説明 | 調整の目安 |
|---|---|---|
| r(LoRAランク) | 低ランク行列のランク数。大きいほど表現力が高まるがVRAMと学習時間が増加 | 少量データ:8〜16、中〜大量データ:32〜64 |
| lora_alpha | LoRAの重みスケーリング係数。通常はrと同じ値を設定 | rと同じ値(8, 16, 32等) |
| learning_rate | 学習率。大きすぎると発散、小さすぎると未収束 | 1e-4〜3e-4(データが少ない場合は1e-5〜2e-5) |
| num_train_epochs | データ全体を何回学習するか | 通常2〜5。少量データは1〜2(過学習防止) |
| per_device_train_batch_size | 1ステップで処理するサンプル数。大きいほどVRAMを消費 | VRAM 12GB: 2〜4、8GB: 1〜2 |
| gradient_accumulation_steps | 勾配を積算するステップ数。実効バッチサイズ = batch_size × このパラメータ | 実効バッチサイズが8〜32になるよう調整 |
| max_seq_length | 処理できる最大トークン数。長いほどVRAMを消費 | 平均的な入力+出力長の1.5〜2倍を目安に設定 |
学習の実行と進捗確認
学習中は以下の指標をログで確認します。
- train/loss(学習損失):学習が進むにつれて減少するのが正常。減少しない場合は学習率が低すぎる可能性
- GPU VRAM使用量:
nvidia-smiで確認。上限に近い場合はper_device_train_batch_sizeを下げる - 学習速度(it/s):VRAM使用量と学習率の調整の参考に使用
# 学習中の別ターミナルでVRAM使用量を確認
watch -n 1 nvidia-smi
# TensorBoardで損失曲線を可視化(オプション)
pip install tensorboard
tensorboard --logdir ./outputs
ステップ4:モデルの評価——学習できているか確認する
定性評価:プロンプトで動作確認
from unsloth import FastLanguageModel
# 学習済みLoRAモデルのロード
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "./lora_model",
max_seq_length = 2048,
dtype = None,
load_in_4bit = True,
)
# 推論モードに切り替え(速度向上)
FastLanguageModel.for_inference(model)
ALPACA_PROMPT = """以下は、タスクを説明するinstructionと、追加のcontextを提供するinputです。
要求を適切に満たすResponseを書いてください。
### Instruction:
{}
### Input:
{}
### Response:
"""
def generate(instruction, input_text, max_new_tokens=512):
inputs = tokenizer(
[ALPACA_PROMPT.format(instruction, input_text)],
return_tensors = "pt"
).to("cuda")
outputs = model.generate(
**inputs,
max_new_tokens = max_new_tokens,
temperature = 0.7,
do_sample = True,
)
response = tokenizer.batch_decode(outputs, skip_special_tokens=True)
# ResponseパートのみをPrint
result = response[0].split("### Response:")[-1].strip()
print(result)
return result
# 学習データと同じ種類の問い合わせで評価
generate(
instruction="以下の問い合わせに、当社のサポートポリシーに基づいて回答してください。",
input_text="製品が故障した場合の修理費用はどのくらいかかりますか?"
)
# 学習データにない(汎化性のテスト)
generate(
instruction="以下の問い合わせに、当社のサポートポリシーに基づいて回答してください。",
input_text="海外から製品を購入した場合も保証は適用されますか?"
)
定量評価:損失とベンチマーク
| 評価指標 | 確認方法 | 良好な状態の目安 |
|---|---|---|
| 最終学習損失(train/loss) | 学習ログの最終値 | タスクによって異なるが、初期値から50〜70%以上の低下 |
| テストデータでの損失(eval/loss) | DatasetにTrain/Test分割を設定して評価 | train/lossと大きく乖離していなければ過学習なし |
| ターゲット回答との一致率 | 評価用データセットで出力を比較 | 用途依存。フォーマット固定タスクは90%以上を目指す |
| ベースモデルとの比較 | 同じプロンプトをベースモデルとファインチューニング済みモデルで実行し比較 | ターゲットタスクで明確な改善が確認できること |
ステップ5:Ollamaに取り込んでローカル実行する
GGUFへの変換
OllamaはGGUF形式のモデルを扱います。UnslothでLoRAをベースモデルにマージし、GGUF形式に変換します。
# LoRAウェイトをベースモデルにマージしてGGUF形式で保存
# Unslothが変換ツールを内蔵しているため、追加インストール不要
model.save_pretrained_gguf(
"gguf_model", # 保存ディレクトリ名
tokenizer,
quantization_method = "q4_k_m" # 推奨量子化方式
# 量子化オプション: q4_0, q4_k_m, q5_k_m, q8_0, f16
# q4_k_m: 品質と速度のバランスが最良(推奨)
# q8_0: 品質最優先(ファイルサイズ大)
)
# 保存されたGGUFファイルの確認
import os
gguf_files = [f for f in os.listdir("gguf_model") if f.endswith(".gguf")]
print(f"変換されたGGUFファイル: {gguf_files}")
Modelfileの作成とOllamaへの登録
# Modelfileの作成
cat > Modelfile << 'EOF'
# ファインチューニング済みGGUFモデルを指定
FROM ./gguf_model/model-q4_k_m.gguf
# システムプロンプト(モデルの役割・制約を定義)
SYSTEM """あなたは株式会社〇〇の専門AIアシスタントです。
当社の製品・サービスに関する問い合わせに、正確かつ丁寧に回答してください。
わからないことは「確認が必要です」と伝え、誤った情報を提供しないよう注意してください。"""
# 推論パラメータ
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER top_k 40
PARAMETER num_ctx 4096
PARAMETER stop "### Instruction:"
PARAMETER stop "### Input:"
EOF
# Ollamaにモデルを登録
ollama create mycompany-assistant -f Modelfile
# 登録確認
ollama list
# 動作テスト
ollama run mycompany-assistant "製品の保証期間について教えてください。"
APIからの呼び出し確認
# OllamaのREST APIからPythonで呼び出す例
import requests
import json
def query_local_llm(prompt, model="mycompany-assistant"):
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": model,
"prompt": prompt,
"stream": False,
"options": {
"temperature": 0.7,
"num_ctx": 4096,
}
}
)
return response.json()["response"]
# テスト
result = query_local_llm("製品の修理を依頼したいのですが、どうすればよいですか?")
print(result)
# OpenAI互換APIを使う場合(LangChain等との連携)
# OllamaはOpenAI互換エンドポイントも提供
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # 任意の文字列でOK
)
response = client.chat.completions.create(
model="mycompany-assistant",
messages=[
{"role": "user", "content": "製品の修理を依頼したいのですが?"}
]
)
print(response.choices[0].message.content)
ユースケース別のデータセット設計——どんな会社でも応用できる
| 業種・ユースケース | instructionの設計例 | データのソース | 必要件数目安 |
|---|---|---|---|
| 製造業:製品FAQボット | 「以下の製品に関する問い合わせに、技術仕様書と保証ポリシーに基づいて回答してください。」 | 過去の問い合わせ対応メール・FAQドキュメント | 300〜1,000件 |
| 不動産:物件説明文生成 | 「以下の物件情報から、魅力的な物件説明文を当社のスタイルガイドに沿って生成してください。」 | 過去に作成した物件説明文・スタイルガイド | 200〜500件 |
| 医療・介護:業務マニュアルQ&A | 「以下の業務手順に関する質問に、当施設のマニュアルに基づいて回答してください。」 | 施設内マニュアル・研修資料 | 500〜2,000件 |
| 法律・コンプライアンス:社内規程Q&A | 「以下の就業規則・コンプライアンスに関する質問に、社内規程に基づいて回答してください。」 | 就業規則・コンプライアンスガイドライン | 200〜500件 |
| ITサポート:障害対応ガイド | 「以下のシステム障害の症状について、社内の対応手順書に基づいてトラブルシューティング手順を提示してください。」 | 過去のインシデント対応ログ・手順書 | 300〜1,000件 |
| EC・小売:カスタマーサポート | 「以下の顧客からの問い合わせに、返品ポリシーと配送規定に従って丁寧に回答してください。」 | 過去のサポートチケット・対応テンプレート | 500〜3,000件 |
よくあるトラブルと解決策
| 症状 | 原因 | 解決策 |
|---|---|---|
| CUDA out of memory エラー | VRAMが不足している | per_device_train_batch_sizeを1に下げる。max_seq_lengthを短くする(2048→1024)。gradient_checkpointingが有効か確認する |
| 学習損失が下がらない | 学習率が低すぎる、またはデータの品質が低い | learning_rateを2〜5倍に上げる。データの品質(instruction/outputの対応関係)を再確認する |
| 過学習(trainは下がるがevalが上がる) | データ量に対してepoch数が多すぎる、学習率が高すぎる | num_train_epochsを下げる(3→1〜2)。learning_rateを下げる。weight_decayを増やす(0.01→0.1) |
| 学習後に出力が繰り返しになる | EOS_TOKENが正しく設定されていない | データセットの各サンプルの末尾にEOS_TOKENを付与しているか確認する |
| Ollamaへの登録後に文字化けする | GGUF変換時の量子化形式の問題、またはModelfileのテンプレート不一致 | q8_0など精度の高い量子化形式で再変換する。Modelfileのシステムプロンプト・ストップトークンをQwen2.5の形式に合わせる |
| 日本語の出力品質が低い | 学習データが少なすぎる、または英語データが多すぎる | 日本語データの比率を上げる。Qwen2.5の日本語ベースモデル(Instruct版を使用していない場合)を確認する |
コピペで使えるデータ整備プロンプト集
【プロンプト①】既存ドキュメントからの学習データ自動生成
以下の社内ドキュメントから、LLMのファインチューニング用学習データを生成してください。
【ドキュメント内容】
{ここに社内マニュアル・FAQ・ガイドラインのテキストを貼り付ける}
以下の要件に従ってデータを生成してください:
1. instruction / input / output の3フィールドを持つJSON形式で出力する
2. 一つのドキュメントから10〜20件のサンプルを生成する
3. instructionは「このエージェントの役割と応答スタイル」を記述する
4. inputは「ユーザーからの自然な質問・依頼文」とする
5. outputは「ドキュメントの内容に基づいた正確な回答」とする
6. 個人情報・固有の会社名・製品名は[プレースホルダー]に置換する
7. 同じ情報について「短い質問・長い質問・言い換え」など複数パターンのinputを作成する
出力形式:
{"instruction": "...", "input": "...", "output": "..."}
(1行1件のJSONL形式で出力)
【プロンプト②】データセットの品質評価
以下のファインチューニング用学習データセットを品質評価してください。
【データセットサンプル(10〜20件)】
{ここに学習データのサンプルをJSONL形式で貼り付ける}
以下の観点で評価し、問題のあるサンプルを特定してください:
1. instruction と output の一致性(instructionの指示に対して、outputが適切に応答しているか)
2. outputの品質(文法・敬語・情報の正確さ)
3. 個人情報・機密情報の混入(見落としていないか)
4. 重複・類似サンプルの多さ(過学習リスク)
5. output長のバランス(極端に短い・長いサンプルの有無)
6. データセット全体のトピックバランス
問題のあるサンプルには「問題の種類」「改善案」を付記してください。
また、データセット全体の品質スコア(10点満点)と総評を提示してください。
【プロンプト③】ファインチューニングパラメータの最適化相談
以下の条件でQwen2.5のQLoRAファインチューニングを行います。
最適なハイパーパラメータを推奨してください。
【環境・データの条件】
- GPU: {例:RTX 3090(VRAM 24GB)}
- モデルサイズ: {例:Qwen2.5-7B-Instruct}
- 学習データ件数: {例:500件}
- 1サンプルの平均トークン数(入力+出力): {例:約400トークン}
- 目的: {例:製品サポートFAQへの特化}
- 許容学習時間: {例:3時間以内}
以下のパラメータについて推奨値と理由を提示してください:
- r(LoRAランク)
- lora_alpha
- learning_rate
- num_train_epochs
- per_device_train_batch_size
- gradient_accumulation_steps
- max_seq_length
- warmup_steps
- weight_decay
また、この設定でのリスク(過学習・未収束等)と対処法も教えてください。
よくある質問(Q&A)
Q1. ファインチューニングとRAGのどちらを選ぶべきですか?
「知識の更新頻度」と「出力スタイルの要求」で判断してください。情報が週単位・月単位で更新され、常に最新情報を参照させたい場合はRAGが優れています。一方、出力の文体・フォーマットを統一したい、社内の専門用語や業界独自の表現パターンを深く学習させたい、クエリのたびにドキュメント検索のコストを発生させたくない場合はファインチューニングが有利です。実際には「ファインチューニング(文体・基礎知識)+RAG(最新情報・ドキュメント参照)」の組み合わせが最も効果的なケースが多いです。
Q2. Qwen2.5-7Bで業務利用しても法的に問題ありませんか?
Qwen2.5-7BはApache 2.0ライセンスで公開されており、商用利用・改変・再配布が許可されています(72Bモデルは独自のQwenライセンスのため要確認)。ただし、ライセンス条件の詳細は最新のHugging FaceのモデルページとQwenの公式ライセンスファイルをご確認ください。また、学習に使用する自社データの著作権・個人情報保護法への適合については、社内の法務担当者に確認することをお勧めします。
Q3. 学習データを社外のサービス(Google Colab等)で処理しても大丈夫ですか?
機密情報・個人情報を含むデータをそのまま社外のクラウド環境に送ることは避けてください。Google Colabを使用する場合は、①匿名化・マスキング処理を済ませたデータのみを使用する、②Google Colabのビジネス利用規約を確認する、③データは学習後に環境から削除する、の3点を守ってください。より確実な方法として、クラウドGPUをプライベートインスタンス(Vast.ai・RunPodのプライベート環境)として利用するか、社内のオンプレGPU環境を整備することを推奨します。
Q4. ファインチューニング後のモデルのアップデートはどうすればいいですか?
2つのアプローチがあります。①定期的に学習データを追加して再学習する(月次・四半期)、②新しいベースモデル(Qwen2.6等の後継モデル)がリリースされた際に同じLoRAスクリプトで再学習する。LoRAアダプターは元モデルとセットで管理する必要があるため、「どのベースモデルのどのバージョンで学習したか」をGit等でバージョン管理することを強くお勧めします。学習データもバージョン管理しておくと、再学習や品質比較が容易になります。
Q5. UnslothとHuggingFaceの標準的なPEFT/TRLを使った場合の違いは何ですか?
機能的にはほぼ同等ですが、UnslothはVRAMを30〜60%削減、学習速度を2〜5倍向上させる独自最適化が実装されています。コンシューマGPU環境での実用性は大幅に高く、RTX 3080(12GB)でQwen2.5-7Bのファインチューニングが現実的に行えます。標準的なPEFTでは同じGPUで実行困難なケースでも、Unslothなら動作することが多いです。デメリットはUnsloth固有の実装への依存ですが、標準的なLoRAウェイトとして保存できるため、後でHuggingFaceの標準ライブラリに移行することも可能です。
まとめ——ファインチューニングは「一度やれば資産になる」
ローカルLLMのファインチューニングは、初回のセットアップに手間がかかりますが、一度完成させた自社専用モデルは組織の知的資産になります。本記事の手順をまとめます。
- アプローチを選ぶ。 コンシューマGPUでの実用的なファインチューニングにはQLoRAが最適。Unsloth + Qwen2.5-7Bの組み合わせが2026年のベストプラクティス。
- データの質が最も重要。 1,000件の低品質データよりも200件の高品質データが学習効果で上回る。データ整備に全体工数の50〜70%を割く覚悟で臨む。
- 3フィールド(instruction / input / output)を意識する。 既存のドキュメントやQ&Aをこのフォーマットに変換する作業が実際の主作業になる。本記事のプロンプトを活用して効率化できる。
- 学習→評価→改善のサイクルを回す。 最初から完璧を目指さない。50〜100件のデータで試行し、品質を確認してからスケールする。
- Ollama登録で即座に実用化できる。 GGUFへの変換→Modelfile作成→
ollama createの3ステップで、ファインチューニング済みモデルをローカルAPIとして利用できる。OpenAI互換エンドポイントで既存のアプリケーションとも容易に連携可能。
「クラウドAPIに月額コストをかけ続けるか、一度ファインチューニングして自社資産にするか」——この判断が、AI活用における競争優位の分かれ目の一つになっています。本記事が最初の一歩のお役に立てば幸いです。
シリーズ記事としてローカルLLM入門・ハードウェア構築ガイド・モデル選定ガイドもあわせてご覧ください。
参考リンク
- Unsloth — 公式GitHubリポジトリ
- Qwen2.5-7B-Instruct — HuggingFace
- Ollama — 公式サイト
- QLoRA: Efficient Finetuning of Quantized LLMs(論文)
- HuggingFace TRL SFTTrainer ドキュメント
- HuggingFace PEFT ドキュメント
免責事項: 本記事は2026年3月時点の情報に基づいており、ライブラリのバージョンアップにより手順が変わる場合があります。実際の実装前に各ライブラリの最新ドキュメントをご確認ください。学習データに個人情報・機密情報を含める場合は、個人情報保護法および社内規定に従った適切な処理を行ってください。本記事の手順に基づく実装結果について、筆者は一切の責任を負いません。

コメント