ローカルLLM × ファインチューニング入門【2026年版】——自社データでAIを「うちの会社の専門家」にする方法(LoRA / QLoRA実践)

ローカルLLM × ファインチューニング入門【2026年版】——自社データでAIを「うちの会社の専門家」にする方法(LoRA / QLoRA実践)


  1. はじめに——「汎用AI」から「自社専用AI」へ
  2. RAGとファインチューニング——どちらを選ぶか
    1. RAGが向いているケース
    2. ファインチューニングが向いているケース
    3. 判断フローチャート
  3. LoRA / QLoRA とは何か——仕組みを直感的に理解する
    1. フルファインチューニングの問題
    2. LoRA:変化の「差分」だけ学習する
    3. QLoRA:4bit量子化でさらにVRAM節約
    4. LoRA vs QLoRA vs フルFT:何を選ぶか
  4. ハードウェア要件——手持ちのPCで本当にできるか
  5. 学習データの準備——品質がすべてを決める
    1. どんなデータがファインチューニングに使えるか
    2. Instruction形式(Alpaca形式)へのデータ変換
    3. データ品質の原則——量より質
    4. コピペで使える:データ生成プロンプト
  6. 【実践】QLoRAファインチューニングの手順(Llama 3.1 8B / ELYZA)
    1. 環境セットアップ
    2. 学習スクリプト(コピペで動く最小構成)
    3. 主要ハイパーパラメータの調整ガイド
    4. 学習の実行と進捗確認
    5. LoRAアダプタのマージとOllamaへの組み込み
  7. 品質評価——「うちの会社の専門家」になったか確認する
    1. 評価の3段階
    2. よくある失敗パターンとその対処法
  8. ファインチューニング済みモデルの社内展開
  9. 中小企業の実務ユースケース5選
  10. よくある質問(Q&A)
  11. まとめ——「専門家AI」を育てるための最初の一歩
  12. 参考リンク

  1. はじめに——「汎用AI」から「自社専用AI」へ
  2. RAGとファインチューニング——どちらを選ぶか
    1. RAGが向いているケース
    2. ファインチューニングが向いているケース
    3. 判断フローチャート
  3. LoRA / QLoRA とは何か——仕組みを直感的に理解する
    1. フルファインチューニングの問題
    2. LoRA:変化の「差分」だけ学習する
    3. QLoRA:4bit量子化でさらにVRAM節約
    4. LoRA vs QLoRA vs フルFT:何を選ぶか
  4. ハードウェア要件——手持ちのPCで本当にできるか
  5. 学習データの準備——品質がすべてを決める
    1. どんなデータがファインチューニングに使えるか
    2. Instruction形式(Alpaca形式)へのデータ変換
    3. データ品質の原則——量より質
    4. コピペで使える:データ生成プロンプト
  6. 【実践】QLoRAファインチューニングの手順(Llama 3.1 8B / ELYZA)
    1. 環境セットアップ
    2. 学習スクリプト(コピペで動く最小構成)
    3. 主要ハイパーパラメータの調整ガイド
    4. 学習の実行と進捗確認
    5. LoRAアダプタのマージとOllamaへの組み込み
  7. 品質評価——「うちの会社の専門家」になったか確認する
    1. 評価の3段階
    2. よくある失敗パターンとその対処法
  8. ファインチューニング済みモデルの社内展開
  9. 中小企業の実務ユースケース5選
  10. よくある質問(Q&A)
    1. Q1. ファインチューニングにはどれくらいのデータが必要ですか?
    2. Q2. ファインチューニングとRAGを両方使うことはできますか?
    3. Q3. 学習データに個人情報が含まれている場合はどうすればよいですか?
    4. Q4. 学習が終わったLoRAアダプタは、ベースモデルを変えたら使えなくなりますか?
    5. Q5. OpenAIのファインチューニングAPIと何が違いますか?
  11. まとめ——「専門家AI」を育てるための最初の一歩
  12. 参考リンク

はじめに——「汎用AI」から「自社専用AI」へ

ChatGPTやClaudeのような汎用AIは、幅広いトピックで高品質な回答を返します。しかし「自社の製品仕様書に基づいた回答」「自社の接客マニュアル通りの言い回し」「社内の申請手続きを正確に案内する応答」といった自社固有の知識・スタイル・業務ルールについては、どれほど優れた汎用AIでも限界があります。

この課題へのアプローチは大きく2つあります。RAG(Retrieval-Augmented Generation)ファインチューニングです。本サイトのRAG記事(ID 132)では「外部データを検索して回答させる」アプローチを解説しましたが、本記事ではその対となる「モデル自体に自社知識を学習させる」ファインチューニングを扱います。

2025〜2026年にかけて、LoRA(Low-Rank Adaptation)とQLoRA(Quantized LoRA)という技術の実用化により、消費者向けGPU1枚(RTX 4090相当、24GB VRAM)で7〜8Bパラメータのモデルをファインチューニングできる時代になりました。かつては数百万円のコンピューティング資源が必要だった作業が、手持ちのワークステーションで数時間以内に完了します。

本記事では、RAGとファインチューニングの使い分け判断から、QLoRAの仕組み、データ準備、実際のトレーニングコード、社内展開まで、中小企業の担当者が一人で実施できるレベルで解説します。


RAGとファインチューニング——どちらを選ぶか

「自社データをAIに使わせたい」という目的に対して、RAGとファインチューニングは解決する問題が異なります。どちらが優れているかではなく、目的に応じて使い分けることが重要です。

RAGが向いているケース

RAGは「外部の文書データベースをリアルタイムで検索し、その結果を文脈に組み込んで回答させる」仕組みです。以下のような用途に適しています。

  • 頻繁に更新される情報へのQ&A(製品仕様・価格・法令・社内規程)
  • 大量の文書から特定の情報を探し出す(数百〜数千件の文書検索)
  • 回答の根拠(出典ページ・文書名)を明示したい
  • データを非公開のままモデルに「見せる」だけにしたい(モデルへの埋め込みが不要)
  • 明日から使いたい(学習不要ですぐに利用可能)

ファインチューニングが向いているケース

ファインチューニングは「モデルのパラメータ自体を更新し、特定のスタイル・知識・振る舞いを永続的に学習させる」仕組みです。以下の用途で真価を発揮します。

  • 文体・トーンの統一:自社ブランドの話し言葉・丁寧語の使い方・特定のキャラクターとして応答させたい
  • 業界専門用語・社内用語の習得:社内特有の略語・製品名・プロセス名を正確に使いこなしてほしい
  • 特定タスクの性能向上:特定のフォーマットで出力させる(見積書生成・コードレビューコメントなど)
  • 小さいモデルの能力向上:3B〜8Bの軽量モデルを特定タスク専用に鍛え、大型モデルと競合させる
  • ローカル・オフライン稼働が必要:インターネット接続なしで動作する専用AIを作りたい
  • 推論コストの削減:クラウドAPIへのリクエスト回数・費用を削減したい

判断フローチャート

質問YESNO
情報は週〜月単位で更新されるか?→ RAGが有利
回答の出典・根拠の明示が必要か?→ RAGが有利
文体・話し方の統一が主な目的か?→ FTが有利
社内固有の用語・知識体系の習得が必要か?→ FTが有利
上記どちらとも言えない?RAG + FTの組み合わせ(FTでスタイルを固定し、RAGで最新情報を補完)

実務では「まずRAGで試し、RAGでは解決しきれない問題(スタイル・用語・フォーマット)が見えてきたらFTを加える」という段階的なアプローチが最も効率的です。


LoRA / QLoRA とは何か——仕組みを直感的に理解する

フルファインチューニングの問題

LLMを「フルファインチューニング」——すべてのパラメータを学習データで更新する——するには、膨大なメモリが必要です。7BパラメータのモデルをフルFTするには100〜120GBのVRAMが必要(A100 GPU 2〜3枚相当)で、コストは単一のトレーニングランで約50万〜100万円になります。これは中小企業に非現実的です。

また、フルFTには「壊滅的忘却(Catastrophic Forgetting)」という問題があります。新しいデータで学習し直すと、モデルが元々持っていた汎用的な能力(日本語の文法・常識・推論力)が大幅に劣化することがあります。

LoRA:変化の「差分」だけ学習する

LoRA(Low-Rank Adaptation)の発想はシンプルです。「モデル全体のパラメータを更新するのではなく、変化の差分を表す小さな行列(アダプタ)だけを学習する」というものです。

技術的には、元のモデルの重み行列(巨大)を凍結したまま、2つの小さな低ランク行列(A行列・B行列)を挿入し、この2つだけを学習します。推論時は「元の重み+LoRAの差分(A×B)」として機能します。

この仕組みにより:

  • 訓練可能なパラメータ数が全体の0.1〜1%程度に削減される
  • 学習に必要なVRAMが10〜20分の1になる
  • 元のモデルの能力を維持しながら特定タスクを強化できる(壊滅的忘却を抑制)
  • LoRAアダプタのサイズは10〜100MB程度(ベースモデルは変更せず、アダプタだけ保管)

QLoRA:4bit量子化でさらにVRAM節約

QLoRA(Quantized LoRA)はLoRAに加えて、ベースモデルの重みを4bit精度(NF4形式)に量子化します。通常16bitで保持する重みを4bitに圧縮することで、メモリ使用量をさらに約75%削減します。

QLoRAの3つの核心技術:

  • 4bit NormalFloat(NF4):正規分布に最適化された4bit量子化形式。一般的な4bit量子化より精度が高い
  • ダブル量子化:量子化定数自体をさらに量子化し、パラメータあたり平均0.5bitの追加節約を実現
  • ページド・オプティマイザ:学習中のメモリスパイクをCPUメモリにオフロードし、OOM(メモリ不足)エラーを防ぐ

QLoRAの代償として、学習速度がLoRAより約39%遅くなります(4bit→16bitの量子化復元の計算コスト)。ただし品質はLoRAの90〜95%を維持します。

LoRA vs QLoRA vs フルFT:何を選ぶか

手法必要VRAM(7B)学習速度品質推奨ユースケース
フルファインチューニング100〜120GB最速最高研究・大規模基盤モデル開発(一般企業には非推奨)
LoRA16〜20GB速い高(FTの98〜99%)RTX 4090(24GB)・A10G・RTX 3090が手元にある場合の第一選択
QLoRA8〜12GBやや遅い中〜高(FTの90〜95%)RTX 4070 Ti(16GB)・RTX 3080など予算・VRAM制約がある場合

実務上の結論:RTX 4090(24GB)を持っていればLoRA、それ以下のGPUや16GB前後ならQLoRAを選んでください。中小企業の初回チャレンジにはQLoRAが最もハードルが低く、失敗コストも小さい選択肢です。


ハードウェア要件——手持ちのPCで本当にできるか

モデルサイズ別の必要スペックを整理します。GPUのVRAMがボトルネックです。CPUとRAMは補助的な役割しかありません(ただしシステムRAMは32GB以上を推奨)。

モデルサイズLoRA
最低VRAM
QLoRA
最低VRAM
代表的なGPU学習時間目安
(1,000サンプル)
3B〜4B(Phi-3 Mini等)8GB6GBRTX 3060 / RTX 406030〜60分
7B〜8B(Llama 3.1 8B / ELYZA 8B等)16GB8〜12GBRTX 3080 / RTX 40702〜4時間
13B〜14B(Qwen2.5 14B等)28GB16GBRTX 4090 / A50006〜12時間
70B(Llama 3.3 70B等)160GB+48GBA100 80GB(×1〜2)24〜48時間

手持ちのGPUがない場合のクラウドオプション:

サービスGPU費用目安特徴
Google Colab Pro+A100(40GB)月額約3,000円最も入門しやすい。使用時間に制限あり
Vast.aiRTX 4090等0.5〜1.0ドル/時スポット価格で安い。不安定さがある
RunPodRTX 4090 / A1000.7〜2.5ドル/時Dockerテンプレートが充実・使いやすい
Lambda LabsA10 / A1000.6〜2.0ドル/時安定性が高い。ジュピターノート対応

1,000サンプルの7B QLoRAであれば、RunPodのRTX 4090インスタンスで約3〜4時間、コスト約2〜3ドル(300〜450円)で完了します。最初の実験はクラウドで行い、本格運用になってからGPUを購入するのが合理的です。


学習データの準備——品質がすべてを決める

どんなデータがファインチューニングに使えるか

ファインチューニングに使えるデータは、「指示(Instruction)→入力(Input)→期待する出力(Output)」の3点セットで構成します。企業の現場で使えるデータの典型例を示します。

データの種類具体例難易度品質目安
FAQデータ製品FAQ・社内規程Q&A・問い合わせ対応履歴🟢 低300〜1,000件で一定の効果
接客・応対トークカスタマーサポートのチャット履歴・メール対応文例🟢 低500件以上推奨。個人情報はマスキング必須
文書生成タスク見積書・報告書・提案書のテンプレートと完成例🟡 中100〜300件でフォーマット学習に十分
専門知識Q&A業界専門知識・社内業務手順の問答🟡 中200〜500件。専門家レビューが推奨
分類・判定タスク問い合わせのカテゴリ分類・文書の適切性判定🟢 低各クラス100件以上推奨

Instruction形式(Alpaca形式)へのデータ変換

ファインチューニング用のデータは、標準的なAlpaca形式(JSON Lines)に変換します。各サンプルは以下の3フィールドで構成されます。

// train_data.jsonl の各行の形式

{
  "instruction": "以下の問い合わせに、弊社の案内スタッフとして丁寧に回答してください。",
  "input": "新規会員登録はどうすればできますか?",
  "output": "ご入会のご案内をいたします。公式サイトのトップページ右上「新規会員登録」ボタンよりお手続きをお願いいたします。メールアドレスとパスワードをご入力いただくと、確認メールが届きます。メール内のURLをクリックして手続き完了となります。ご不明な点がございましたら、お気軽にお申し付けください。"
}

// inputが不要なタスク(文章生成など)の場合はinputを空にする
{
  "instruction": "以下の営業日報を500文字以内で要約してください。",
  "input": "本日は午前中にA社を訪問し、新製品のデモを実施しました……(長文の日報本文)",
  "output": "A社へのデモ実施後、価格面での検討が必要との意向を確認。B社では既存製品の更新が来期に決定。今週の商談進捗は3件中2件がポジティブ。来週のフォロー訪問を調整中。"
}

データ品質の原則——量より質

ファインチューニングにおいて最も重要な原則は「量より質」です。実験的に確認されているガイドラインを示します。

  • 最小限のデータ量:特定のタスク・スタイルの学習には100〜500件の高品質データで効果が出ます。粗悪なデータを10,000件用意するより、厳選した500件の方が圧倒的に良い結果になります。
  • 一貫したスタイル:outputの文体・語尾・敬語レベル・フォーマットが一貫していること。矛盾したスタイルのデータが混在すると、モデルが不安定な出力をするようになります。
  • ネガティブサンプル不要:「悪い回答例」を学習データに含める必要はありません。「良い回答例」だけを集中的に収集します。
  • データの多様性:同じパターンの繰り返しデータは過学習を招きます。同じトピックでも言い回し・状況・文長が異なるバリエーションを用意します。
  • 個人情報・機密情報のマスキング:実際の顧客名・社員名・口座番号等は、架空の名前(山田太郎・株式会社サンプル)に置換してから学習データとして使用します。

コピペで使える:データ生成プロンプト

自社の既存コンテンツ(マニュアル・FAQ・対応履歴等)をAIに渡して、ファインチューニング用データを生成させるプロンプトです。

以下の社内文書をもとに、ファインチューニング用の学習データを生成してください。

【元となる社内文書】
---
[マニュアルや対応事例の本文をここに貼り付け]
---

【生成形式】
以下のJSONL形式で、20件のinstruction-input-outputペアを生成してください。
各ペアは異なる質問パターン・言い回しにし、多様性を持たせてください。

{
  "instruction": "[タスクの指示文。「〜してください」の形式]",
  "input": "[ユーザーからの問い合わせや入力テキスト]",
  "output": "[期待する理想的な回答。実際の業務で使える丁寧な文体で]"
}

【品質基準】
- outputは弊社のカスタマーサポートとして実際に送信できるレベルの文章
- 敬語:丁寧語(〜です・〜ます)を基本とし、過度なへりくだりは避ける
- 長さ:1回答あたり100〜300文字
- 個人名・会社名は架空のものを使用(例:山田様、株式会社サンプル)

JSONLのみを出力してください(説明文・コードブロック記号は不要)。

【実践】QLoRAファインチューニングの手順(Llama 3.1 8B / ELYZA)

環境セットアップ

Pythonの仮想環境を作成し、必要なライブラリをインストールします。

# Python 3.10以上・CUDA 12.1以上が前提
# 仮想環境の作成
python -m venv venv
source venv/bin/activate  # Windowsは: venv\Scripts\activate

# 必要ライブラリのインストール
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
pip install transformers==4.44.0
pip install peft==0.12.0          # LoRA/QLoRA実装(PEFTライブラリ)
pip install bitsandbytes==0.43.3   # 4bit量子化(QLoRA必須)
pip install accelerate==0.33.0     # マルチGPU・混合精度学習
pip install trl==0.9.6             # SFTTrainer(シンプルなトレーニングAPI)
pip install datasets==2.21.0       # データセット管理
pip install wandb                  # 学習進捗の可視化(オプション)

# インストール確認
python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))"
# 期待値: True  NVIDIA GeForce RTX XXXX

学習スクリプト(コピペで動く最小構成)

以下のスクリプトは、QLoRAでLlama 3.1 8BまたはELYZA 8Bをファインチューニングする最小構成です。[ ]の部分を自社の設定に変えてください。

# fine_tune.py
# 動作確認:RTX 4070 Ti(16GB VRAM)でQLoRA実行

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer, SFTConfig
from datasets import load_dataset

# ===================================================
# 設定(ここを自社の用途に合わせて変更)
# ===================================================

# ベースモデル(HuggingFaceのモデルIDを指定)
# 日本語タスク → "elyza/Llama-3-ELYZA-JP-8B" または "llm-jp/llm-jp-3-13b-instruct"
# 英語タスク → "meta-llama/Meta-Llama-3.1-8B-Instruct"
MODEL_ID = "elyza/Llama-3-ELYZA-JP-8B"

# 学習データのパス(JSONL形式)
TRAIN_DATA_PATH = "./data/train_data.jsonl"

# 出力先(LoRAアダプタの保存場所)
OUTPUT_DIR = "./output/my-company-llm-adapter"

# ===================================================
# QLoRA設定(4bit量子化)
# ===================================================
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,              # 4bit量子化を有効化(QLoRA)
    bnb_4bit_quant_type="nf4",      # NormalFloat4形式(最も精度が高い)
    bnb_4bit_compute_dtype=torch.bfloat16,  # 計算時は16bitで実行
    bnb_4bit_use_double_quant=True, # ダブル量子化で追加節約
)

# ===================================================
# モデルとトークナイザーのロード
# ===================================================
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
tokenizer.pad_token = tokenizer.eos_token  # パディングトークンの設定

model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID,
    quantization_config=bnb_config,  # QLoRAの量子化設定を適用
    device_map="auto",               # GPUへの自動割り当て
    trust_remote_code=True,
)

# QLoRA用にモデルを準備(量子化パラメータの勾配計算を無効化)
model = prepare_model_for_kbit_training(model)

# ===================================================
# LoRA設定
# ===================================================
lora_config = LoraConfig(
    r=16,                            # LoRAのランク。小さいほど軽量・大きいほど表現力が上がる
                                     # 初回は r=16 から試すこと
    lora_alpha=32,                   # LoRAのスケーリング係数。通常 lora_alpha = 2 * r
    target_modules="all-linear",     # すべての線形層にLoRAを適用(推奨)
    lora_dropout=0.05,               # ドロップアウト(過学習防止)
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_config)

# 学習可能パラメータ数を確認(全体の約0.5〜1%になるはず)
model.print_trainable_parameters()
# 例: trainable params: 20,971,520 || all params: 8,051,232,768 || trainable%: 0.26

# ===================================================
# データセットのロードとフォーマット
# ===================================================
dataset = load_dataset("json", data_files={"train": TRAIN_DATA_PATH})["train"]

def format_instruction(sample):
    """Alpaca形式のデータを会話テンプレートに変換"""
    if sample.get("input"):
        text = (
            f"<|system|>\n{sample['instruction']}\n"
            f"<|user|>\n{sample['input']}\n"
            f"<|assistant|>\n{sample['output']}"
        )
    else:
        text = (
            f"<|system|>\n{sample['instruction']}\n"
            f"<|user|>\n{sample['output']}"  # inputなし形式
        )
    return {"text": text}

dataset = dataset.map(format_instruction)

# ===================================================
# トレーニング設定
# ===================================================
training_config = SFTConfig(
    output_dir=OUTPUT_DIR,
    num_train_epochs=3,             # エポック数。小データ(〜1000件)は3〜5エポック
    per_device_train_batch_size=2,  # バッチサイズ。VRAMと相談しながら増やす
    gradient_accumulation_steps=4,  # 実質バッチサイズ = 2 × 4 = 8
    gradient_checkpointing=True,    # VRAMを節約(速度は少し低下)
    learning_rate=2e-4,             # 学習率。LoRAのデフォルト推奨値
    lr_scheduler_type="cosine",     # コサイン学習率スケジューラ
    warmup_ratio=0.05,              # 全ステップの5%をウォームアップに使用
    logging_steps=10,               # 10ステップごとにlossを記録
    save_steps=100,                 # 100ステップごとにチェックポイント保存
    max_seq_length=1024,            # 最大トークン長
    fp16=False,
    bf16=True,                      # bfloat16混合精度(Ampere以降のGPU推奨)
    dataset_text_field="text",
)

# ===================================================
# トレーナーの作成と学習開始
# ===================================================
trainer = SFTTrainer(
    model=model,
    args=training_config,
    train_dataset=dataset,
    tokenizer=tokenizer,
    peft_config=lora_config,
)

print("学習を開始します...")
trainer.train()

# LoRAアダプタの保存
trainer.save_model(OUTPUT_DIR)
print(f"アダプタを {OUTPUT_DIR} に保存しました")

主要ハイパーパラメータの調整ガイド

パラメータ初回推奨値調整の方向性注意点
r(LoRAランク)16出力品質が足りなければ32→64に増加増やすとVRAM消費が増える。r=64以上は効果が薄れる
lora_alphar × 2(32)適応が弱すぎれば r×3 に、忘却が起きれば r×1.5 に基本は r の2倍で始める
learning_rate2e-4Lossが不安定なら1e-4に下げる1e-3以上は過学習リスクが高い
num_train_epochs3検証セットでLossが上がりだしたら早期停止データが少ない(〜300件)なら5〜10エポック
per_device_train_batch_size2OOMが出なければ4〜8に増加(速度向上)gradient_accumulation_stepsとセットで調整
max_seq_length1024長文対応なら2048〜4096(VRAMが増加)FAQなら512で十分な場合が多い

学習の実行と進捗確認

# 学習の実行
python fine_tune.py

# 進捗はコンソールにリアルタイム出力される
# 例:
# {'loss': 2.3421, 'learning_rate': 0.0002, 'epoch': 0.1}  ← 学習初期
# {'loss': 1.2105, 'learning_rate': 0.00018, 'epoch': 1.0}  ← 1エポック後
# {'loss': 0.8432, 'learning_rate': 0.0001, 'epoch': 2.0}  ← 2エポック後
# {'loss': 0.7218, 'learning_rate': 0.00002, 'epoch': 3.0}  ← 3エポック後(完了)

# Lossが以下のパターンを示せば概ね正常:
# 2.0以上 → 1.5 → 1.0 → 0.8以下(3エポックで0.5〜0.8が目安)

# VRAM使用量の確認(別ターミナルで実行)
watch -n 1 nvidia-smi

Lossの解釈: Lossが下がりすぎ(0.1以下)になっている場合は過学習のサインです。学習データを暗記してしまい、見たことのない質問には対応できなくなります。学習データの10〜20%を検証データとして分割し、検証Lossが上昇しはじめたら学習を停止してください。

LoRAアダプタのマージとOllamaへの組み込み

学習が完了したLoRAアダプタをベースモデルにマージし、Ollamaで使用できる形式(GGUF)に変換します。

# merge_and_convert.py
# ステップ1:LoRAアダプタをベースモデルにマージ

from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
import torch

BASE_MODEL_ID = "elyza/Llama-3-ELYZA-JP-8B"
ADAPTER_PATH = "./output/my-company-llm-adapter"
MERGED_OUTPUT = "./output/my-company-llm-merged"

print("ベースモデルをロード中...")
base_model = AutoModelForCausalLM.from_pretrained(
    BASE_MODEL_ID,
    torch_dtype=torch.bfloat16,
    device_map="cpu",       # マージはCPUで実行(VRAMを温存)
)
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_ID)

print("LoRAアダプタをロード中...")
model = PeftModel.from_pretrained(base_model, ADAPTER_PATH)

print("アダプタをマージ中...")
merged_model = model.merge_and_unload()  # アダプタを重みに統合

print(f"マージ済みモデルを保存中 → {MERGED_OUTPUT}")
merged_model.save_pretrained(MERGED_OUTPUT, safe_serialization=True)
tokenizer.save_pretrained(MERGED_OUTPUT)
print("完了")
# ステップ2:GGUF形式に変換(llama.cppを使用)

# llama.cppのclone(初回のみ)
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j

pip install -r requirements.txt

# HuggingFace形式 → GGUF変換
python convert_hf_to_gguf.py \
  ../output/my-company-llm-merged \
  --outfile ../output/my-company-llm.gguf \
  --outtype q4_k_m     # 4bit量子化(ファインチューニング結果を保ちつつ軽量化)

# ステップ3:OllamaのModelfileを作成
cat > Modelfile &lt;&lt;'EOF'
FROM ./my-company-llm.gguf

PARAMETER temperature 0.3     # 低め:安定した一貫性のある回答
PARAMETER top_p 0.9
PARAMETER repeat_penalty 1.1
PARAMETER num_ctx 4096

SYSTEM """
あなたは[会社名]のカスタマーサポート担当AIアシスタントです。
お客様からのお問い合わせに、丁寧かつ正確にお答えします。
"""
EOF

# Ollamaモデルとして登録
ollama create my-company-llm -f Modelfile

# 動作テスト
ollama run my-company-llm "新規会員登録の方法を教えてください"

品質評価——「うちの会社の専門家」になったか確認する

評価の3段階

ファインチューニング完了後の評価は、3つの段階で行います。

第1段階:定性評価(目視確認)
学習データに含まれなかった20〜30件のテスト質問を用意し、ベースモデルとファインチューニング済みモデルの回答を並べて比較します。以下の観点で確認してください。

  • 自社固有の用語・製品名を正しく使っているか
  • 文体・語尾・敬語レベルが学習データと一致しているか
  • 業務的に間違った情報を返していないか
  • 学習していないトピックへの質問に対して、「わかりません」「担当者に確認します」と適切に応答するか(幻覚が増えていないか)

第2段階:定量評価(BLEUスコア・ROUGE)
正解回答が存在するテストセット(50〜100件)に対して、ファインチューニング前後のBLEUスコアまたはROUGEスコアを比較します。厳密な評価が必要な場合に実施します。初回の実験では定性評価だけで十分です。

第3段階:実務テスト(A/Bテスト)
社内の一部ユーザーにファインチューニング済みモデルを使ってもらい、「回答の正確さ・適切さ」を5段階評価で記録します。ベースモデル+RAGとの比較も有益です。

よくある失敗パターンとその対処法

症状原因対処法
同じ文章を繰り返す・ループする過学習・learning_rateが高すぎるlearning_rateを半分に下げる・repeat_penaltyを1.2に設定
回答が短すぎる・「はい」だけ返す学習データのoutputが短すぎる・データの多様性不足outputの文字数を均一化(100字以上)・データを追加
ベースモデルより回答品質が下がった学習データの品質が低い・矛盾したデータが混在データを再精査・矛盾するペアを削除・データ量を減らしてでも質を上げる
学習前は答えられた質問に答えられなくなった壊滅的忘却・エポック数が多すぎるエポック数を2〜3に削減・lora_dropoutを0.1に増加
OOM(Out of Memory)エラーVRAM不足batch_sizeを1に・max_seq_lengthを512に・QLoRAに切替・モデルサイズを落とす
Lossが下がらない(2.0以上で停滞)learning_rateが低すぎる・データ形式の不整合learning_rateを5e-4に増加・データのフォーマットを再確認

ファインチューニング済みモデルの社内展開

品質確認が完了したモデルを社内で展開する方法は、ローカルLLMシリーズの「チーム共有・APIサーバー化ガイド」で詳しく解説しています(関連記事参照)。ここではファインチューニング済みモデル固有の注意点だけ整理します。

モデルバージョン管理:
LoRAアダプタは10〜100MB程度と軽量なため、Gitで管理することができます(ただしGit LFSが推奨)。アダプタのバージョン名に「学習データのバージョン・エポック数・実施日」を含めると管理しやすくなります(例:adapter-v1.2-ep3-20260315)。

ベースモデルとアダプタの分離管理:
ベースモデル(数GB)は変更しないため、アダプタだけを差し替えることで複数の専用モデルを管理できます。「カスタマーサポート用アダプタ」「技術マニュアル用アダプタ」のように、用途別アダプタを一つのベースモデルに重ねて使い分けることが可能です。

継続学習(追加学習):
自社のデータが増えたり、業務内容が変わったりした場合は、既存のLoRAアダプタを起点に追加のファインチューニングができます(ただし、新旧データをバランスよく混合することが推奨されます)。


中小企業の実務ユースケース5選

LoRA/QLoRAファインチューニングが実際に価値を発揮した中小企業向けのユースケースを示します。

業種ユースケース学習データ期待効果
小売・EC商品Q&Aチャットボット(自社商品の仕様・在庫・配送に特化)製品FAQ 500件、過去の問い合わせ対応メール 1,000件問い合わせ対応工数を50〜70%削減。24時間対応を実現
製造業技術マニュアルアシスタント(機械操作手順・トラブルシューティング)操作マニュアル→Q&A変換 300件、ベテラン担当者の回答例 200件新入社員のオンボーディング期間を短縮。ベテランの暗黙知の継承
士業・コンサル文書ドラフト生成(自社の文体・クライアントへの言い回しに特化)過去の提案書・報告書・メール 200〜500件初稿作成時間を60〜80%短縮。文体の一貫性を保証
宿泊・観光多言語対応フロントデスクアシスタント(施設・サービス・周辺情報への回答)日本語FAQ 200件をAIで多言語展開 → 各言語200件多言語スタッフ不在時でも一定品質の案内が可能に
医療・介護社内向け記録補助(SOAPフォーマットでの記録ドラフト自動生成)匿名化した過去の記録(SOAP形式) 500〜1,000件記録作業時間を削減。記録品質の均一化

共通する成功条件: ①学習データがすでに自社内に存在する(過去の対応履歴・文書類)、②回答の品質評価を担当できる業務知識者が社内にいる、③完璧を求めず「60〜80点の自動化」として捉えられる——この3点が揃っている組織で高い成功率が見られます。


よくある質問(Q&A)

Q1. ファインチューニングにはどれくらいのデータが必要ですか?

タスクの複雑さによりますが、特定のスタイル・フォーマットの学習には100〜500件の高品質データで効果が確認されています。業界の専門知識を習得させるなら500〜2,000件が目安です。重要なのは件数より質です。矛盾のない、一貫したスタイルのデータを用意することを最優先にしてください。

Q2. ファインチューニングとRAGを両方使うことはできますか?

はい、これが多くの実務用途で最も効果的な組み合わせです。ファインチューニングで「自社の文体・用語・振る舞い」をモデルに習得させ、RAGで「最新の文書・頻繁に更新されるデータ」を動的に参照させます。例えば、「丁寧な接客トーン」はFTで固定し、「今月のキャンペーン情報」はRAGで都度参照させる設計です。

Q3. 学習データに個人情報が含まれている場合はどうすればよいですか?

学習データに含まれる個人情報は必ずマスキング(匿名化)してから使用してください。氏名→「山田様」、会社名→「〇〇株式会社」、電話番号・メールアドレス→ダミー値への置換が必要です。また、顧客データをAI学習に使用する場合は、プライバシーポリシーと利用規約を確認し、必要に応じて利用者の同意を取得することをお勧めします。ローカルLLMのファインチューニングはデータがインターネットに出ないため、クラウドAPIを使うよりデータ管理上安全です。

Q4. 学習が終わったLoRAアダプタは、ベースモデルを変えたら使えなくなりますか?

はい、LoRAアダプタは特定のベースモデルのアーキテクチャに依存しているため、ベースモデルを変更した場合は再学習が必要です。ただし、LoRAアダプタのサイズは非常に小さい(10〜100MB)ため、新しいベースモデルへの再学習コストはゼロからの学習に比べて小さいです。

Q5. OpenAIのファインチューニングAPIと何が違いますか?

OpenAIのファインチューニングAPIは手軽ですが、①学習データをOpenAIのサーバーに送信する必要がある(機密データには不向き)、②学習済みモデルはOpenAIのクラウドでのみ動作する、③費用がトークン量に比例して増加する——という制約があります。LoRA/QLoRAによるローカルファインチューニングは、データが社内を出ず、一度GPUコストを投資すれば追加費用なく何度でも学習・再学習でき、OllamaなどでオフラインのAPIとして稼働できる点が最大の差別化です。


まとめ——「専門家AI」を育てるための最初の一歩

本記事で解説した内容を振り返ります。

RAGとファインチューニングの使い分け: 頻繁に更新されるデータ・出典の明示が必要なケースはRAG。文体・用語・特定タスクの性能向上が目的のケースはファインチューニング。多くの実務では組み合わせが最適解です。

LoRA/QLoRAの民主化: かつては数百万円のコンピューティングが必要だったLLMのファインチューニングが、RTX 3080相当のGPU1枚・数時間・数ドルのクラウドコストで実行できる時代になっています。QLoRAで7B〜8Bモデルをファインチューニングするのに必要なVRAMは8〜12GBです。

品質を決めるのはデータ: アルゴリズムよりも、学習データの品質が最終的な出力品質を決定します。100件の厳選されたデータが、粗悪な10,000件より優れた結果をもたらします。既存の社内文書(FAQ・対応履歴・マニュアル)から出発し、AIを使ってInstruction形式に変換することで、データ準備のコストは大幅に削減できます。

最初の一歩は小さく: まず特定の1タスク(例:FAQ回答)に絞り、100〜300件のデータでQLoRAを試してみてください。Colabの無料GPUでも実験できます。その結果を評価し、改善することで、自社固有の「専門家AI」が少しずつ育っていきます。

ローカルLLMシリーズで構築したOllamaサーバー基盤の上に、ファインチューニングという「専門化」の層を重ねることで、単なる「汎用AIの社内展開」から「自社ビジネスに深く統合されたAI基盤」へと進化させることができます。


参考リンク

免責事項:本記事は2026年3月時点の情報に基づく情報提供です。HuggingFace Transformers・PEFT・TRL等のライブラリはバージョンアップが頻繁であり、コードの動作確認は各ライブラリの最新ドキュメントを参照してください。ファインチューニングに使用するベースモデルのライセンス(Llama 3.1はMeta Llama License・ELYZAはLlama 3 Community License等)を必ず確認した上で、商用利用の可否を判断してください。

コメント

タイトルとURLをコピーしました