- HOME >
- Jamstack用語集 >
- Fine Tuning
Fine Tuning
ファインチューニング
Fine Tuning を分かりやすく
Fine Tuning(ファインチューニング)は、既に訓練された AI モデルを、あなたの特定の用途に合わせてカスタマイズする技術です。
例え話をしましょう。あなたが料理人を雇うとします:
ゼロから訓練する(Pre-training): 料理を全く知らない人に、基本から教える
- 包丁の使い方から始める
- 様々な料理の作り方を教える
- 時間: 数年
- コスト: 非常に高い
Fine Tuning: すでにプロの料理人を雇って、あなたのレストランのメニューを教える
- 既に料理の基本は知っている
- あなたのレストランの特別なレシピやスタイルだけを教える
- 時間: 数週間
- コスト: 比較的安い
AI のFine Tuning も同じです。GPT-4 や Llama などの大規模モデルは、膨大なデータで訓練されています(Pre-training)。これをベースに、あなたの会社の文書スタイル、製品知識、業界用語などを追加で学習させる(Fine Tuning)ことで、特化したAIを作れます。
Fine Tuning が必要なケース
- 特定のドメイン知識: 医療、法律、金融など専門分野
- 独自のスタイル: 会社の文章スタイル、トーン
- カスタム機能: 特定のタスクに特化した性能向上
- コスト削減: 小さなモデルで大きなモデルと同等の性能
Fine Tuning vs RAG vs Prompt Engineering
どの手法を使うべきか迷うかもしれません。比較してみましょう:
// lib/comparison.ts
type AICustomizationMethod = {
name: string
cost: 'Low' | 'Medium' | 'High'
complexity: 'Low' | 'Medium' | 'High'
updateEase: 'Easy' | 'Medium' | 'Hard'
useCases: string[]
}
const methods: AICustomizationMethod[] = [
{
name: 'Prompt Engineering',
cost: 'Low',
complexity: 'Low',
updateEase: 'Easy',
useCases: [
'一般的なタスク',
'プロトタイピング',
'頻繁に要件が変わる場合',
],
},
{
name: 'RAG (Retrieval Augmented Generation)',
cost: 'Medium',
complexity: 'Medium',
updateEase: 'Easy',
useCases: [
'最新情報が必要',
'社内文書の活用',
'頻繁に更新されるデータ',
],
},
{
name: 'Fine Tuning',
cost: 'High',
complexity: 'High',
updateEase: 'Hard',
useCases: [
'特定のスタイルやトーンが必要',
'高度な専門知識',
'安定した要件',
],
},
]
Next.js × TypeScript で Fine Tuning を実装する
ステップ 1: 訓練データの準備
Fine Tuning には、高品質な訓練データが必要です。
// lib/fine-tuning/prepare-data.ts
export type TrainingExample = {
messages: Array<{
role: 'system' | 'user' | 'assistant'
content: string
}>
}
// カスタマーサポート用の訓練データを作成
export function prepareCustomerSupportData(): TrainingExample[] {
return [
{
messages: [
{
role: 'system',
content:
'あなたは〇〇社のカスタマーサポートです。丁寧で親切に対応してください。',
},
{
role: 'user',
content: '商品の返品方法を教えてください',
},
{
role: 'assistant',
content:
'ご購入いただきありがとうございます。返品は購入から30日以内であれば承っております。以下の手順で返品をお願いいたします:\n\n1. マイページにログイン\n2. 注文履歴から該当商品を選択\n3. 「返品申請」ボタンをクリック\n4. 返品理由を選択して送信\n\n返品送料は弊社負担となります。ご不明な点がございましたら、お気軽にお問い合わせください。',
},
],
},
// ... さらに多くの例
]
}
// JSONL 形式に変換(OpenAI の形式)
export function convertToJSONL(examples: TrainingExample[]): string {
return examples.map((example) => JSON.stringify(example)).join('\n')
}
ステップ 2: OpenAI でFine Tuning を実行
// lib/fine-tuning/openai.ts
import OpenAI from 'openai'
import fs from 'fs'
import path from 'path'
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
// 訓練ファイルをアップロード
export async function uploadTrainingFile(filePath: string) {
const file = await openai.files.create({
file: fs.createReadStream(filePath),
purpose: 'fine-tune',
})
return file.id
}
// Fine Tuning ジョブを開始
export async function startFineTuning(
trainingFileId: string,
model: 'gpt-3.5-turbo' | 'gpt-4' = 'gpt-3.5-turbo',
suffix?: string
) {
const fineTune = await openai.fineTuning.jobs.create({
training_file: trainingFileId,
model,
suffix, // カスタムモデル名のサフィックス
})
return fineTune
}
// Fine Tuning の進捗を確認
export async function checkFineTuningStatus(jobId: string) {
const job = await openai.fineTuning.jobs.retrieve(jobId)
return job
}
// Fine Tuning されたモデルを使用
export async function useFineTunedModel(
modelName: string,
messages: Array<{ role: string; content: string }>
) {
const response = await openai.chat.completions.create({
model: modelName, // 例: "ft:gpt-3.5-turbo:my-org:custom-suffix:id"
messages,
})
return response.choices[0].message.content
}
ステップ 3: Fine Tuning 管理 API
// app/api/fine-tuning/create/route.ts
import { prepareCustomerSupportData, convertToJSONL } from '@/lib/fine-tuning/prepare-data'
import { uploadTrainingFile, startFineTuning } from '@/lib/fine-tuning/openai'
import fs from 'fs'
import path from 'path'
export async function POST(req: Request) {
try {
// 訓練データを準備
const trainingData = prepareCustomerSupportData()
const jsonlContent = convertToJSONL(trainingData)
// 一時ファイルに保存
const tempFilePath = path.join(process.cwd(), 'temp', 'training-data.jsonl')
fs.writeFileSync(tempFilePath, jsonlContent)
// OpenAI にアップロード
const fileId = await uploadTrainingFile(tempFilePath)
// Fine Tuning を開始
const fineTune = await startFineTuning(fileId, 'gpt-3.5-turbo', 'customer-support')
// 一時ファイルを削除
fs.unlinkSync(tempFilePath)
return Response.json({
success: true,
jobId: fineTune.id,
status: fineTune.status,
})
} catch (error) {
console.error('Fine Tuning Error:', error)
return new Response('Fine Tuning の開始に失敗しました', { status: 500 })
}
}
// app/api/fine-tuning/status/route.ts
import { checkFineTuningStatus } from '@/lib/fine-tuning/openai'
export async function GET(req: Request) {
try {
const { searchParams } = new URL(req.url)
const jobId = searchParams.get('jobId')
if (!jobId) {
return new Response('jobId が必要です', { status: 400 })
}
const status = await checkFineTuningStatus(jobId)
return Response.json({
jobId: status.id,
status: status.status,
model: status.fine_tuned_model,
createdAt: status.created_at,
finishedAt: status.finished_at,
})
} catch (error) {
console.error('Status Check Error:', error)
return new Response('ステータスの確認に失敗しました', { status: 500 })
}
}
ステップ 4: Fine Tuned モデルの使用
// app/api/chat/fine-tuned/route.ts
import { useFineTunedModel } from '@/lib/fine-tuning/openai'
export async function POST(req: Request) {
try {
const { messages, model } = await req.json()
if (!model) {
return new Response('model が必要です', { status: 400 })
}
const response = await useFineTunedModel(model, messages)
return Response.json({
message: response,
})
} catch (error) {
console.error('Fine Tuned Model Error:', error)
return new Response('エラーが発生しました', { status: 500 })
}
}
ステップ 5: Fine Tuning 管理 UI
// app/fine-tuning/page.tsx
'use client'
import { useState } from 'react'
type FineTuningJob = {
jobId: string
status: string
model: string | null
createdAt: number
finishedAt: number | null
}
export default function FineTuningPage() {
const [jobId, setJobId] = useState('')
const [jobStatus, setJobStatus] = useState<FineTuningJob | null>(null)
const [isCreating, setIsCreating] = useState(false)
const [isChecking, setIsChecking] = useState(false)
const createFineTuning = async () => {
setIsCreating(true)
try {
const response = await fetch('/api/fine-tuning/create', {
method: 'POST',
})
const data = await response.json()
setJobId(data.jobId)
alert(`Fine Tuning ジョブを開始しました: ${data.jobId}`)
} catch (error) {
console.error('Error:', error)
alert('エラーが発生しました')
} finally {
setIsCreating(false)
}
}
const checkStatus = async () => {
if (!jobId) return
setIsChecking(true)
try {
const response = await fetch(`/api/fine-tuning/status?jobId=${jobId}`)
const data = await response.json()
setJobStatus(data)
} catch (error) {
console.error('Error:', error)
alert('エラーが発生しました')
} finally {
setIsChecking(false)
}
}
return (
<div className="container mx-auto max-w-4xl p-4">
<h1 className="text-3xl font-bold mb-6">Fine Tuning 管理</h1>
{/* Fine Tuning の説明 */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<h2 className="font-semibold mb-2">Fine Tuning とは?</h2>
<p className="text-sm">
既存の AI モデルを、あなたの特定の用途に合わせてカスタマイズする技術です。
</p>
<ul className="list-disc list-inside mt-2 text-sm">
<li>特定のドメイン知識を追加</li>
<li>独自のスタイルやトーンを学習</li>
<li>タスク固有の性能を向上</li>
</ul>
</div>
{/* Fine Tuning 作成 */}
<div className="border border-gray-200 rounded-lg p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">新しい Fine Tuning ジョブを作成</h2>
<button
onClick={createFineTuning}
disabled={isCreating}
className="bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 disabled:bg-gray-300"
>
{isCreating ? '作成中...' : 'Fine Tuning を開始'}
</button>
</div>
{/* ステータス確認 */}
<div className="border border-gray-200 rounded-lg p-6">
<h2 className="text-xl font-semibold mb-4">Fine Tuning ステータス確認</h2>
<div className="flex gap-2 mb-4">
<input
type="text"
value={jobId}
onChange={(e) => setJobId(e.target.value)}
placeholder="ジョブ ID を入力..."
className="flex-1 border border-gray-300 rounded-lg px-4 py-2"
/>
<button
onClick={checkStatus}
disabled={isChecking || !jobId}
className="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 disabled:bg-gray-300"
>
{isChecking ? '確認中...' : 'ステータス確認'}
</button>
</div>
{jobStatus && (
<div className="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-sm text-gray-600">ジョブ ID</p>
<p className="font-mono text-sm">{jobStatus.jobId}</p>
</div>
<div>
<p className="text-sm text-gray-600">ステータス</p>
<p className={`font-semibold ${
jobStatus.status === 'succeeded' ? 'text-green-600' :
jobStatus.status === 'failed' ? 'text-red-600' :
'text-yellow-600'
}`}>
{jobStatus.status}
</p>
</div>
{jobStatus.model && (
<div className="col-span-2">
<p className="text-sm text-gray-600">モデル名</p>
<p className="font-mono text-sm">{jobStatus.model}</p>
</div>
)}
</div>
</div>
)}
</div>
</div>
)
}
Fine Tuning のベストプラクティス
1. データ品質が最重要
// 良い訓練データの例
const goodExample = {
messages: [
{ role: 'system', content: '明確な指示' },
{ role: 'user', content: '具体的な質問' },
{ role: 'assistant', content: '高品質で一貫性のある回答' },
],
}
// 悪い訓練データの例
const badExample = {
messages: [
{ role: 'system', content: '' }, // 指示が不明確
{ role: 'user', content: 'あれ' }, // あいまい
{ role: 'assistant', content: 'うーん' }, // 低品質
],
}
2. 適切なデータ量
- 最低: 50〜100 例
- 推奨: 500〜1,000 例
- 理想: 数千例以上
3. バリデーションデータで評価
// 訓練データとバリデーションデータに分割
export function splitData(data: TrainingExample[], splitRatio: number = 0.8) {
const shuffled = data.sort(() => 0.5 - Math.random())
const splitIndex = Math.floor(data.length * splitRatio)
return {
training: shuffled.slice(0, splitIndex),
validation: shuffled.slice(splitIndex),
}
}
まとめ
Fine Tuning は、AI モデルをあなたの特定の用途に最適化する強力な手法です。Next.js と TypeScript を組み合わせることで、Fine Tuning のプロセスを管理し、カスタムモデルを効果的に活用できます。
重要なポイント:
- 適切な手法選択: Prompt Engineering、RAG、Fine Tuning を適切に使い分ける
- データ品質: 高品質な訓練データが成功の鍵
- 継続的な評価: バリデーションデータでモデルの性能を評価
- コスト管理: Fine Tuning には時間とコストがかかることを理解
- バージョン管理: 複数のモデルバージョンを管理して比較
Fine Tuning を活用することで、汎用 AI モデルでは実現できなかった、高度に専門化された AI アプリケーションを構築できます。