Open9

OpenAI GPT-OSSファインチューニング実践手順書のアウトライン

hiraokuhiraoku

第1章: 前提条件と環境準備

1.1 ハードウェア要件

GPT-OSS 20B の場合

  • QLoRA (推奨): 14GB VRAM以上(例: RTX 4090、A10G)
  • LoRA (BF16): 60GB VRAM以上(例: A100 40GB×2、H100)

GPT-OSS 120B の場合

  • QLoRA: 65GB VRAM以上(例: A100 80GB、H100)
  • LoRA (BF16): 240GB VRAM以上(例: H100×4)

1.2 推奨GPU環境

MXFP4量子化サポート:NVIDIA Hopper (H100)、Grace Blackwell、RTX 50xxシリーズ
⚠️ 非サポート: MXFP4を使用しない場合、メモリ使用量が約4倍増加

1.3 クラウド環境オプション

プラットフォーム インスタンスタイプ 用途
AWS SageMaker ml.p4d.24xlarge (A100×8) 本番環境
Google Colab A100 (無料枠) 実験・学習
RunPod H100 SXM 高速学習
Lambda Labs A100 40GB コスト重視
hiraokuhiraoku

第2章: データセット準備

2.1 Harmonyフォーマットの理解

GPT-OSSはHarmony Response Formatを使用します。このフォーマットを理解することが重要です。

基本構造

<|start|>system<|message|>システム指示<|end|>
<|start|>developer<|message|>開発者指示<|end|>
<|start|>user<|message|>ユーザー入力<|end|>
<|start|>assistant<|channel|>analysis<|message|>推論過程<|end|>
<|start|>assistant<|channel|>final<|message|>最終回答<|return|>

ロール階層 (優先順位)

  1. system - システムレベル設定
  2. developer - 開発者指示
  3. user - ユーザー入力
  4. assistant - アシスタント応答
  5. tool - ツール応答

チャネルの種類

  • analysis - 内部推論(CoT)、ユーザーには非表示
  • final - 最終的なユーザー向け応答

2.2 推論レベルの設定

システムメッセージで推論レベルを指定:

<|start|>system<|message|>You are ChatGPT, a large language model trained by OpenAI.
Knowledge cutoff: 2024-06
Current date: 2025-10-04

Reasoning: medium

# Valid channels: analysis, commentary, final.
<|end|>
レベル 用途 トークン消費
low 高速応答が必要なタスク
medium バランス型(デフォルト)
high 複雑な推論タスク

2.3 データセット形式

Option 1: JSONLフォーマット(推奨)

{
  "messages": [
    {
      "role": "system",
      "content": "You are ChatGPT..."
    },
    {
      "role": "user",
      "content": "質問内容"
    },
    {
      "role": "assistant",
      "thinking": "推論プロセス(オプション)",
      "content": "回答内容"
    }
  ]
}

Option 2: Harmonyライブラリを使用

from openai_harmony import (
    Conversation,
    Message,
    Role,
    SystemContent,
    DeveloperContent,
    HarmonyEncodingName,
    load_harmony_encoding,
    ReasoningEffort
)

# Harmonyエンコーディングをロード
encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

# システムメッセージの作成
system_message = (
    SystemContent.new()
    .with_reasoning_effort(ReasoningEffort.MEDIUM)
    .with_conversation_start_date("2025-10-04")
)

# 開発者指示の追加
developer_message = (
    DeveloperContent.new()
    .with_instructions("You are a medical expert. Respond concisely with diagnosis in ≤5 words.")
)

# 会話の構築
conversation = Conversation.from_messages([
    Message.from_role_and_content(Role.SYSTEM, system_message),
    Message.from_role_and_content(Role.DEVELOPER, developer_message),
    Message.from_role_and_content(Role.USER, "What causes chest pain?"),
    Message.from_role_and_content(Role.ASSISTANT, "Coronary artery disease")
])

2.4 データセット例

推奨: HuggingFaceH4/Multilingual-Thinking

多言語推論データセット(OpenAI公式推奨)

from datasets import load_dataset

dataset = load_dataset("HuggingFaceH4/Multilingual-Thinking")

カスタムデータセットの作成

import json

# データセット構造
data = [
    {
        "messages": [
            {"role": "system", "content": "You are an expert assistant."},
            {"role": "user", "content": "What is machine learning?"},
            {
                "role": "assistant",
                "thinking": "User asks basic ML definition. Provide clear explanation.",
                "content": "Machine learning is a subset of AI..."
            }
        ]
    }
]

# JSONL形式で保存
with open('training_data.jsonl', 'w') as f:
    for item in data:
        f.write(json.dumps(item) + '\n')

2.5 データセットの品質基準

推論能力を維持する場合

  • ✅ 推論データ: 75%以上
  • ⚠️ 直接回答データ: 25%以下

最小データサイズ

  • 実験用: 100-500サンプル
  • 本番用: 1,000-10,000サンプル
hiraokuhiraoku

第3章: 環境セットアップ

3.1 依存関係のインストール

基本セットアップ(Transformers + TRL)

# 仮想環境の作成
conda create -n gpt-oss python=3.10
conda activate gpt-oss

# 必須パッケージ
pip install torch --index-url https://download.pytorch.org/whl/cu128
pip install transformers>=4.55.0
pip install accelerate>=0.30.0
pip install peft>=0.17.0
pip install trl>=0.20.0
pip install bitsandbytes>=0.43.0
pip install triton==3.4

# Harmony関連
pip install openai-harmony
pip install tiktoken

# ユーティリティ
pip install datasets
pip install wandb  # 実験トラッキング(オプション)

Unsloth使用(メモリ効率最適化)

# Unslothのインストール
pip uninstall unsloth -y
pip install --upgrade --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git

# 追加パッケージ
pip install xformers
pip install triton

SageMaker環境

# SageMaker Studioで実行
%pip install sagemaker>=2.200.0
%pip install transformers>=4.55.0
%pip install trl>=0.20.0
%pip install accelerate

3.2 Hugging Face認証

from huggingface_hub import notebook_login

# ブラウザでログイン
notebook_login()

# または環境変数で設定
import os
os.environ['HF_TOKEN'] = 'your_token_here'

3.3 Weights & Biases設定(オプション)

wandb login

# Pythonコード内
import wandb
wandb.init(
    project="gpt-oss-finetuning",
    name="experiment-1"
)
hiraokuhiraoku

第4章: モデルとトークナイザーの準備

4.1 モデルの選択

# GPT-OSS 20B (推奨: 実験・開発)
model_id = "openai/gpt-oss-20b"

# GPT-OSS 120B (本番環境向け)
model_id = "openai/gpt-oss-120b"

4.2 モデルのロード(Transformers)

Option 1: QLoRA(低VRAM)

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
from transformers import BitsAndBytesConfig

model_id = "openai/gpt-oss-20b"

# 4bit量子化設定
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True
)

# モデルロード
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True,
    torch_dtype=torch.bfloat16
)

# トークナイザー
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# LoRA準備
model = prepare_model_for_kbit_training(model)

Option 2: LoRA(BF16、高VRAM)

# BF16でロード
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    torch_dtype=torch.bfloat16,
    trust_remote_code=True
)

tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token

4.3 LoRA設定

from peft import LoraConfig, TaskType

# LoRAコンフィグ
lora_config = LoraConfig(
    r=16,                          # LoRAランク
    lora_alpha=32,                 # スケーリングファクター
    target_modules=[
        "q_proj",
        "k_proj", 
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj"
    ],
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM
)

# PEFTモデルの作成
model = get_peft_model(model, lora_config)

# 学習可能パラメータの確認
model.print_trainable_parameters()
# 出力例: trainable params: 167,772,160 || all params: 21,234,567,890 || trainable%: 0.79

4.4 Unslothを使用(推奨: 最大効率)

from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="openai/gpt-oss-20b",
    max_seq_length=8192,
    dtype=None,  # 自動選択
    load_in_4bit=True,
)

# LoRA適用
model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    target_modules=[
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj"
    ],
    lora_alpha=32,
    lora_dropout=0.05,
    bias="none",
    use_gradient_checkpointing="unsloth",
    random_state=3407,
)
hiraokuhiraoku

第5章: ファインチューニング実行

5.1 データセットの前処理

Harmonyフォーマット適用

from datasets import load_dataset

# データセットロード
dataset = load_dataset("HuggingFaceH4/Multilingual-Thinking", split="train")

# Harmonyフォーマット変換関数
def format_to_harmony(example):
    messages = example["messages"]
    
    # チャットテンプレート適用
    formatted_text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=False
    )
    
    return {"text": formatted_text}

# データセット変換
dataset = dataset.map(format_to_harmony, remove_columns=dataset.column_names)

# 確認
print(dataset[0]["text"][:500])

カスタムHarmonyフォーマット

from openai_harmony import (
    Conversation,
    Message,
    Role,
    DeveloperContent,
    load_harmony_encoding,
    HarmonyEncodingName
)

encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

def create_harmony_example(question, answer, instructions):
    conversation = Conversation.from_messages([
        Message.from_role_and_content(
            Role.DEVELOPER,
            DeveloperContent.new().with_instructions(instructions)
        ),
        Message.from_role_and_content(Role.USER, question),
        Message.from_role_and_content(Role.ASSISTANT, answer)
    ])
    
    # トークン化
    tokens = encoding.render_conversation_for_completion(
        conversation,
        Role.ASSISTANT
    )
    
    return tokenizer.decode(tokens)

# 適用
dataset = dataset.map(
    lambda x: {
        "text": create_harmony_example(
            x["question"],
            x["answer"],
            "You are a helpful assistant."
        )
    }
)

5.2 学習設定(TRL SFTTrainer)

from trl import SFTConfig, SFTTrainer

# 学習ハイパーパラメータ
training_args = SFTConfig(
    # 基本設定
    output_dir="./gpt-oss-20b-finetuned",
    num_train_epochs=1,
    
    # バッチサイズ
    per_device_train_batch_size=1,
    gradient_accumulation_steps=16,  # 実効バッチサイズ=16
    
    # 学習率
    learning_rate=2e-5,
    lr_scheduler_type="cosine",
    warmup_ratio=0.1,
    
    # 最適化
    optim="paged_adamw_8bit",
    weight_decay=0.01,
    max_grad_norm=1.0,
    
    # メモリ効率
    gradient_checkpointing=True,
    bf16=True,  # BF16サポートGPUの場合
    # fp16=True,  # それ以外
    
    # ロギング
    logging_steps=10,
    logging_dir="./logs",
    
    # 保存
    save_strategy="steps",
    save_steps=100,
    save_total_limit=3,
    
    # シーケンス長
    max_seq_length=2048,
    
    # その他
    report_to="wandb",  # Weights & Biases
    seed=42
)

# トレーナー初期化
trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    args=training_args,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=2048,
    packing=False  # Harmonyフォーマットでは無効化
)

5.3 学習実行

# 学習開始
trainer.train()

# 最終モデル保存
trainer.save_model("./gpt-oss-20b-final")
tokenizer.save_pretrained("./gpt-oss-20b-final")

5.4 SageMaker Training Jobs

学習スクリプト (train.py)

import argparse
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import SFTConfig, SFTTrainer
from datasets import load_dataset

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--model_id", type=str, default="openai/gpt-oss-20b")
    parser.add_argument("--dataset_path", type=str)
    parser.add_argument("--output_path", type=str, default="/opt/ml/model")
    args = parser.parse_args()
    
    # データロード
    dataset = load_dataset("json", data_files=args.dataset_path)
    
    # モデル・トークナイザー
    model = AutoModelForCausalLM.from_pretrained(
        args.model_id,
        torch_dtype="auto",
        device_map="auto"
    )
    tokenizer = AutoTokenizer.from_pretrained(args.model_id)
    
    # 学習設定
    training_args = SFTConfig(
        output_dir=args.output_path,
        num_train_epochs=1,
        per_device_train_batch_size=1,
        gradient_accumulation_steps=16,
        learning_rate=2e-5,
        bf16=True,
        logging_steps=10,
        save_strategy="epoch"
    )
    
    # トレーナー
    trainer = SFTTrainer(
        model=model,
        tokenizer=tokenizer,
        args=training_args,
        train_dataset=dataset["train"]
    )
    
    trainer.train()
    trainer.save_model(args.output_path)

if __name__ == "__main__":
    main()

SageMaker実行コード

import sagemaker
from sagemaker.huggingface import HuggingFace

# SageMakerセッション
sess = sagemaker.Session()
role = sagemaker.get_execution_role()

# Hugging Face Estimator
huggingface_estimator = HuggingFace(
    entry_point='train.py',
    source_dir='./scripts',
    instance_type='ml.p4d.24xlarge',  # A100×8
    instance_count=1,
    role=role,
    transformers_version='4.55.0',
    pytorch_version='2.5.0',
    py_version='py310',
    hyperparameters={
        'model_id': 'openai/gpt-oss-20b',
        'dataset_path': '/opt/ml/input/data/training',
        'output_path': '/opt/ml/model'
    }
)

# 学習実行
huggingface_estimator.fit({
    'training': 's3://your-bucket/dataset/training_data.jsonl'
})
hiraokuhiraoku

第6章: モデル評価とテスト

6.1 推論テスト

from transformers import pipeline

# パイプライン作成
generator = pipeline(
    "text-generation",
    model="./gpt-oss-20b-final",
    tokenizer=tokenizer,
    device_map="auto"
)

# テストプロンプト
messages = [
    {"role": "system", "content": "You are a helpful assistant.\n\nReasoning: medium"},
    {"role": "user", "content": "Explain quantum computing in simple terms."}
]

# 生成
result = generator(
    messages,
    max_new_tokens=200,
    temperature=0.7,
    do_sample=True
)

print(result[0]["generated_text"])

6.2 Harmonyパーサーで評価

from openai_harmony import StreamableParser, Role, HarmonyEncodingName

encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

# ストリーミングパーサー
parser = StreamableParser(encoding, role=Role.ASSISTANT)

# トークンごとに処理
for token_id in generated_tokens:
    parser.process(token_id)
    
    # チャネル確認
    if parser.current_channel == "analysis":
        print(f"[推論] {parser.last_content_delta}")
    elif parser.current_channel == "final":
        print(f"[回答] {parser.last_content_delta}")

6.3 ベンチマーク評価

from datasets import load_dataset

# 評価データセット
eval_dataset = load_dataset("openai/gsm8k", split="test")

# 評価ループ
correct = 0
total = len(eval_dataset)

for example in eval_dataset:
    prompt = example["question"]
    true_answer = example["answer"]
    
    # 推論
    generated = generator(
        [{"role": "user", "content": prompt}],
        max_new_tokens=512
    )[0]["generated_text"]
    
    # 回答抽出と正解チェック
    if check_answer(generated, true_answer):
        correct += 1

accuracy = correct / total
print(f"Accuracy: {accuracy:.2%}")
hiraokuhiraoku

第7章: モデルのエクスポートと保存

7.1 LoRAアダプターの保存

# PEFTアダプターのみ保存
model.save_pretrained("./lora-adapters")
tokenizer.save_pretrained("./lora-adapters")

7.2 マージモデルの作成

from peft import PeftModel

# ベースモデルロード
base_model = AutoModelForCausalLM.from_pretrained(
    "openai/gpt-oss-20b",
    torch_dtype=torch.bfloat16,
    device_map="auto"
)

# アダプターマージ
model = PeftModel.from_pretrained(base_model, "./lora-adapters")
merged_model = model.merge_and_unload()

# 保存
merged_model.save_pretrained("./gpt-oss-20b-merged")
tokenizer.save_pretrained("./gpt-oss-20b-merged")

7.3 Unslothでのエクスポート

# BF16形式でマージ・エクスポート
model.save_pretrained_merged(
    "./gpt-oss-20b-merged-bf16",
    tokenizer,
    save_method="merged_16bit"
)

# Hugging Face Hubへプッシュ
model.push_to_hub_merged(
    "your-username/gpt-oss-20b-finetuned",
    tokenizer,
    save_method="merged_16bit",
    token="your_hf_token"
)

# GGUF形式でエクスポート(llama.cpp用)
model.save_pretrained_gguf(
    "./gpt-oss-20b-gguf",
    tokenizer,
    quantization_method="q4_k_m"
)

7.4 Hugging Face Hubへアップロード

from huggingface_hub import HfApi

api = HfApi()

# リポジトリ作成
api.create_repo(
    repo_id="your-username/gpt-oss-20b-finetuned",
    private=False
)

# モデルアップロード
api.upload_folder(
    folder_path="./gpt-oss-20b-merged",
    repo_id="your-username/gpt-oss-20b-finetuned",
    repo_type="model"
)
hiraokuhiraoku

第8章: デプロイメント

8.1 ローカル推論サーバー(vLLM)

# vLLMインストール
pip install vllm>=0.10.1

# サーバー起動
python -m vllm.entrypoints.openai.api_server \
    --model ./gpt-oss-20b-merged \
    --dtype bfloat16 \
    --max-model-len 8192 \
    --port 8000

クライアントコード

import openai

client = openai.OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="dummy"
)

response = client.chat.completions.create(
    model="./gpt-oss-20b-merged",
    messages=[
        {"role": "user", "content": "What is AI?"}
    ]
)

print(response.choices[0].message.content)

8.2 SageMaker Endpoint

モデル準備

import sagemaker
from sagemaker.huggingface import HuggingFaceModel

role = sagemaker.get_execution_role()

# Hugging Faceモデル
huggingface_model = HuggingFaceModel(
    model_data=f"s3://{bucket}/gpt-oss-20b-merged/model.tar.gz",
    role=role,
    transformers_version="4.55.0",
    pytorch_version="2.5.0",
    py_version="py310",
    env={
        'HF_MODEL_ID': 'your-username/gpt-oss-20b-finetuned',
        'HF_TASK': 'text-generation'
    }
)

# デプロイ
predictor = huggingface_model.deploy(
    initial_instance_count=1,
    instance_type="ml.g5.12xlarge"  # A10G×4
)

推論実行

# リクエスト
response = predictor.predict({
    "inputs": "What is machine learning?",
    "parameters": {
        "max_new_tokens": 200,
        "temperature": 0.7
    }
})

print(response[0]["generated_text"])

8.3 Ollama(ローカル実行)

# GGUF形式に変換(上記参照)

# Ollamaにインポート
ollama create gpt-oss-custom -f ./Modelfile

# 実行
ollama run gpt-oss-custom "Explain AI"

Modelfile例

FROM ./gpt-oss-20b-gguf/model.gguf

TEMPLATE """<|start|>user<|message|>{{ .Prompt }}<|end|><|start|>assistant<|channel|>final<|message|>"""

PARAMETER temperature 0.7
PARAMETER top_p 0.9
hiraokuhiraoku

第9章: トラブルシューティング

9.1 メモリ不足エラー

エラー: CUDA out of memory

解決策:

  1. バッチサイズを削減: per_device_train_batch_size=1
  2. Gradient Accumulationを増加: gradient_accumulation_steps=32
  3. Gradient Checkpointing有効化: gradient_checkpointing=True
  4. QLoRA使用: load_in_4bit=True
  5. シーケンス長削減: max_seq_length=1024

9.2 MXFP4サポートエラー

エラー: MXFP4 not supported on this GPU

解決策:

  • BF16モデルを使用: model_id = "unsloth/gpt-oss-20b-BF16"
  • GPU変更: Hopper (H100) またはRTX 50xxシリーズ

9.3 Harmonyフォーマットエラー

エラー: Invalid harmony format

解決策:

# チャットテンプレート使用
tokenizer.apply_chat_template(messages, tokenize=False)

# またはHarmonyライブラリ使用
from openai_harmony import load_harmony_encoding
encoding = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

9.4 学習が進まない

症状: Loss が下がらない

チェックリスト:

  • 学習率が適切か: 2e-5 ~ 5e-5
  • データフォーマットが正しいか
  • エポック数が十分か: 最低1エポック
  • LoRAランクが適切か: r=16 または r=32
  • Warmupが設定されているか: warmup_ratio=0.1

9.5 推論が遅い

解決策:

1. Flash Attention有効化

model = AutoModelForCausalLM.from_pretrained(
    model_id,
    attn_implementation="flash_attention_2"
)

2. vLLM使用

PagedAttentionで高速化

3. 量子化推論

AWQ、GPTQ、GGUF

9.6 AWS SageMaker特有の問題

S3アクセスエラー

# IAMロールに適切なS3権限を付与
{
    "Effect": "Allow",
    "Action": ["s3:GetObject", "s3:PutObject"],
    "Resource": "arn:aws:s3:::your-bucket/*"
}

エンドポイントタイムアウト

predictor = huggingface_model.deploy(
    model_data_download_timeout=1800,  # 30分
    container_startup_health_check_timeout=600  # 10分
)

📚 参考リソース

公式ドキュメント

コードサンプル

チュートリアル


✅ チェックリスト

事前準備

  • GPU環境の確認(VRAM容量、CUDA対応)
  • 必要なライブラリのインストール
  • Hugging Face / Weights & Biasアカウント作成
  • データセットの準備とHarmonyフォーマット変換

学習実行

  • モデルとトークナイザーのロード
  • LoRA/QLoRA設定
  • 学習ハイパーパラメータの設定
  • 学習開始とログ監視
  • 定期的なチェックポイント保存

評価とデプロイ

  • 推論テストの実施
  • ベンチマーク評価
  • モデルのマージとエクスポート
  • Hugging Face Hubへアップロード
  • 本番環境へのデプロイ