こんにちは!

ここにいるということは、おそらくオープンソースのAIモデル(LLaMA、Mistral、GPT‑Jなど)を独自のデータやアプリケーションに合わせてファインチューニングする方法に興味があるのでしょう。以下に、ステップバイステップでわかりやすく概要を説明します。実際のプロジェクトで一般的に使用されるリンクやツールも紹介します。


1. 「オープンソースAIモデルのファインチューニング」とはどういう意味ですか?

ファインチューニングとは、次のことを意味します。

  • 事前学習済みモデル(例:大規模言語モデル)から始めます。
  • 独自のデータセットでさらに少しだけトレーニングします。
  • 結果として得られるモデルは次のようになります。
    • ベースモデルが知っていた一般的なことはすべて知っています。さらに
    • 特定のドメイン(コード、PDF、チャットスタイル、製品ドキュメントなど)でより優れたパフォーマンスを発揮します。

これは、モデルの重みを変更しない **RAG(検索拡張生成)**とは異なります。ベクターデータベースから関連するコンテキストを提供するだけです。多くのビジネスユースケースでは、RAGで十分です。ファインチューニングが役立つのは、次のような場合です。

  • 一貫してカスタムトーンまたはスタイルが必要な場合。
  • モデルに複雑な指示を確実に実行させたい場合。
  • モデルに非常に優れたニッチな技術またはビジネス言語を話させる必要がある場合。
  • 繰り返しのパターンに対して、プロンプトの長さとコストを削減したい場合。

2. 適切なオープンソースモデルを選択する

モデルを見つけるための一般的な場所:

選び方:

  • タスクの種類

    • チャット/一般的なアシスタント – 命令に合わせて調整されたLLMを選択します(例:*-instruct)。
    • コード – CodeLlamaのようなコードに特化したモデル。
    • 分類/埋め込み – より小さなトランスフォーマーエンコーダー(例:sentence-transformers)。
  • サイズ vs ハードウェア

    • 7B–8Bモデル:24GBの単一GPU(RTX 4090またはA5000など)に適しています。
    • 13B–34B+モデル:複数のGPUまたは4ビット量子化が必要になる場合があります。

3. ファインチューニング用のデータセットの準備

データセットは、モデルにどのように動作させたいかを反映している必要があります。

3.1 チャットモデルの典型的な形式

一般的なJSONL形式(1行に1つのJSONオブジェクト):

{"instruction": "ファインチューニングとは何かを説明してください。", "input": "", "output": "ファインチューニングとは…"}
{"instruction": "このテキストをフランス語に翻訳してください。", "input": "こんにちは", "output": "Bonjour"}

または会話形式(OpenAIスタイル):

{
  "messages": [
    {"role": "system", "content": "あなたは役に立つコーディングアシスタントです。"},
    {"role": "user", "content": "2つの数値を加算するPython関数を記述してください。"},
    {"role": "assistant", "content": "def add(a, b):
    return a + b"}
  ]
}

SEOと発見のために:「LLaMA JSONL形式のファインチューニング」または「命令ファインチューニングデータセットの例」を検索する人がたくさんいます。上記の2つの形式のいずれかを使用すると、通常、最新のファインチューニングスクリプトで動作します。

3.2 データの品質に関するヒント

  • 一貫性:同じ構造をすべての場所で使用します(同じキー、関数、形式)。
  • クリーンな応答:幻覚や不正確なコンテンツを避けます。
  • 多様性:簡単/中程度/難しい例とさまざまなフレーズを混ぜ合わせます。
  • 十分なデータ:
    • わずかな動作の調整:1k–5kの高品質な例で機能する場合があります。
    • より大きなドメインの適応:**10k–100k+**の例がより適しています。

4. ハードウェアと環境の要件

4.1 ハードウェア

  • **7B–8Bモデル(QLoRA / LoRA)**の場合:
    • 1 × 16–24 GB GPUで十分な場合が多いです。
  • 13B+モデルの場合:
    • 複数のGPUまたはより積極的な量子化。
  • CPUのみ:可能ですが、非常に遅いです。モデルが小さい場合を除き、推奨されません。

4.2 ソフトウェア

一般的なスタック:

基本をインストールします:

pip install "transformers[torch]" datasets accelerate peft bitsandbytes

5. ファインチューニングの方法:完全なファインチューン vs LoRA / QLoRA

5.1 完全なファインチューニング

  • モデルのすべての重みを更新します。
  • 利点:最大の容量と柔軟性。
  • 欠点:多くのメモリとGPU時間が必要です。

ほとんどのチームにとって、7B+モデルの完全なファインチューニングはやりすぎです。

5.2 LoRA / QLoRA(ほとんどの場合に推奨)

  • 凍結されたベースモデルの上に小さなアダプターレイヤーのみをトレーニングします。
  • QLoRA = LoRA + 量子化されたベースモデル(例:4ビット)。
  • 非常に安価で、以下に非常に適しています。
    • スタイル/動作の変更
    • ドメイン知識
    • 指示に従う

リソース:

オンラインで目にする「単一のGPUでオープンソースLLMをファインチューニングする方法」のチュートリアルのほとんどは、QLoRAを使用しています。


6. ステップバイステップ:LoRAを使用したオープンソースモデルのファインチューニング

以下は、Hugging Faceのtransformersとpeftを使用した縮小された例です。 これは本番環境向けのコードではありませんが、必要な正確なピースを提供します。

6.1 ベースモデルをロードする

from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = "mistralai/Mistral-7B-Instruct-v0.2"  # 例

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    load_in_4bit=True,            # QLoRAスタイルのロード
    device_map="auto"
)

6.2 データセットを準備する

from datasets import load_dataset

# データセットが{"instruction", "input", "output"}を含むJSONLファイルであると仮定
dataset = load_dataset("json", data_files={"train": "train.jsonl", "validation": "val.jsonl"})

def format_example(example):
    if example["input"]:
        prompt = f"Instruction: {example['instruction']}
Input: {example['input']}
Answer:"
    else:
        prompt = f"Instruction: {example['instruction']}
Answer:"
    return {
        "prompt": prompt,
        "label": example["output"]
    }

dataset = dataset.map(format_example)

def tokenize(batch):
    inputs = tokenizer(batch["prompt"], truncation=True, padding="max_length", max_length=1024)
    labels = tokenizer(batch["label"], truncation=True, padding="max_length", max_length=1024)
    inputs["labels"] = labels["input_ids"]
    return inputs

tokenized = dataset.map(tokenize, batched=True, remove_columns=dataset["train"].column_names)

6.3 LoRAアダプターをアタッチする

from peft import LoraConfig, get_peft_model, TaskType

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],  # モデルによって異なる場合があります
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM,
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

6.4 トレーニング

from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(
    output_dir="./mistral-finetuned",
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    learning_rate=2e-4,
    fp16=True,
    logging_steps=50,
    save_steps=500,
    evaluation_strategy="steps",
    eval_steps=500,
    save_total_limit=3,
    report_to="none"
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized["train"],
    eval_dataset=tokenized["validation"]
)

trainer.train()
model.save_pretrained("./mistral-finetuned-lora")
tokenizer.save_pretrained("./mistral-finetuned-lora")

これで、データセットでファインチューニングされたLoRA適応オープンソースモデルができました。


7. 本番環境でファインチューニングされたモデルを使用する

7.1 LoRAの重みをマージする(オプション)

デプロイメントを簡単にするために、LoRAアダプターをベースモデルにマージできます。

from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
lora_model = PeftModel.from_pretrained(base_model, "./mistral-finetuned-lora")
merged = lora_model.merge_and_unload()
merged.save_pretrained("./mistral-finetuned-merged")
tokenizer.save_pretrained("./mistral-finetuned-merged")

その後、次のことができます。

7.2 Laravelアプリケーションとの統合

一般的なパターン:

  1. モデルをHTTP API(Pythonマイクロサービス)として提供

    • ファインチューニングされたモデルを呼び出す/generateエンドポイントを公開します。
    • GuzzleまたはHttpクライアントを使用してLaravelから呼び出します。
  2. カスタムモデルをサポートする推論プロバイダーを使用

    • 例:Hugging Face Inference Endpointsまたはその他のクラウドプロバイダー。
    • モデルを非公開で保存し、LaravelバックエンドからREST経由で呼び出します。

一般的なLaravel構成の場合、「LaravelでファインチューニングされたLLaMAモデルを使用」または「LaravelをローカルLLMに接続」を検索する人がいます。重要なのは、モデルを別のサービスとして扱い、HTTP経由で通信することです。


8. ファインチューニングが必要ない場合

多くの実際のアプリケーションでは、以下を組み合わせることで優れた結果を得ることができます。

  1. 強力なオープンソースモデル(例:Llama 3 InstructまたはMistral Instruct)。
  2. プロンプトエンジニアリング(明確な指示、一貫したシステムメッセージ)。
  3. ベクターデータベースを使用したRAG:

ファインチューニングは、特に次の場合に価値があります。

  • 同様の質問を繰り返し行い、短いプロンプトが必要な場合。
  • ブランドボイスを持ち、ブランドにとって安全なアシスタントが必要な場合。
  • 特定のドメインで高品質でより小さなハードウェアで実行する必要がある場合。

9. 法的およびライセンスに関する考慮事項

オープンソースモデルをファインチューニングする前に:

  • Hugging Faceページでライセンスを確認してください。
    • 一部は商用利用を自由に許可しています。
    • その他は制限があります(例:Llama 2 / 3ライセンス、研究専用モデルなど)。
  • 使用するトレーニングデータのライセンスを確認してください(適切な同意とセキュリティなしにプライベート/機密データは使用しないでください)。

役立つ資料:


10. まとめ:オープンソースAIモデルをファインチューニングする方法

  1. タスクとハードウェアに適したHugging Faceからモデルを選択します。
  2. 安定したJSON/JSONLチャットまたは命令形式で高品質のトレーニングデータを準備します。
  3. PyTorch、transformers、datasets、peft、および(オプションで)bitsandbytesで環境を設定します。
  4. 手頃なコストで単一のGPUでファインチューニングするためにLoRA/QLoRAを使用します。
  5. 保持されたデータで評価し、プロンプトとトレーニングセットを改良します。
  6. サービスとしてデプロイし(例:vLLM、TGI、またはllama.cppを介して)、Laravelまたはその他のバックエンドから呼び出します。

もしあなたが私に

  • どのようなアプリケーションを構築しているか(チャットボット、コードアシスタント、コンテンツジェネレーターなど)、
  • どのようなハードウェアを持っているか、
  • オンプレミスまたはクラウドにデプロイしたいか、

を教えていただければ、あなたの正確なユースケースに合わせた具体的で最小限の構成を概説することができます。