LLMLLM 파인튜닝 · 3중급

OpenAI 파인튜닝 — API로 GPT 모델 커스터마이징

LLMOpenAI파인튜닝GPTFine-tuning API

OpenAI 파인튜닝 지원 모델

모델특징
gpt-4o-mini가성비, 빠름, 권장
gpt-4o고성능, 비용 높음
gpt-3.5-turbo레거시

데이터 형식 (JSONL)

import json

# 각 줄이 독립적인 JSON 객체인 JSONL 형식
training_data = [
    {
        "messages": [
            {"role": "system", "content": "당신은 한국 법률 전문가입니다. 정확하고 이해하기 쉽게 답변합니다."},
            {"role": "user", "content": "전세 계약 시 주의해야 할 사항은?"},
            {"role": "assistant", "content": "전세 계약 시 반드시 확인해야 할 사항입니다:\n1. 등기부등본 확인: 근저당, 압류 여부 확인\n2. 전입신고와 확정일자: 대항력과 우선변제권 확보\n3. 전세보증보험 가입 검토\n4. 계약서 특약 사항 꼼꼼히 확인"}
        ]
    },
    # ... 최소 10개 이상 권장
]

# JSONL 파일로 저장
with open("training.jsonl", "w", encoding="utf-8") as f:
    for sample in training_data:
        f.write(json.dumps(sample, ensure_ascii=False) + "\n")

파인튜닝 전체 과정

from openai import OpenAI
import time

client = OpenAI()

# 1. 파일 업로드
print("1. 데이터 업로드 중...")
with open("training.jsonl", "rb") as f:
    file_response = client.files.create(
        file=f,
        purpose="fine-tune"
    )

file_id = file_response.id
print(f"파일 ID: {file_id}")

# 2. 파인튜닝 작업 생성
print("2. 파인튜닝 시작...")
job = client.fine_tuning.jobs.create(
    training_file=file_id,
    model="gpt-4o-mini-2024-07-18",
    hyperparameters={
        "n_epochs": 3,           # 에폭 수
        "batch_size": "auto",    # 자동 설정
        "learning_rate_multiplier": "auto",
    },
    suffix="legal-advisor",      # 모델명 접미사
)

job_id = job.id
print(f"작업 ID: {job_id}")

# 3. 진행 상황 모니터링
print("3. 학습 진행 중...")
while True:
    job_status = client.fine_tuning.jobs.retrieve(job_id)

    if job_status.status in ["succeeded", "failed", "cancelled"]:
        break

    # 최근 이벤트 확인
    events = client.fine_tuning.jobs.list_events(job_id, limit=5)
    for event in reversed(list(events)):
        print(f"[{event.created_at}] {event.message}")

    print(f"상태: {job_status.status}")
    time.sleep(30)

if job_status.status == "succeeded":
    model_id = job_status.fine_tuned_model
    print(f"\n✅ 완료! 모델 ID: {model_id}")
else:
    print(f"\n❌ 실패: {job_status.error}")

파인튜닝된 모델 사용

# 파인튜닝된 모델 ID 예시
FINE_TUNED_MODEL = "ft:gpt-4o-mini-2024-07-18:my-org:legal-advisor:abc123"

def ask_legal_question(question: str) -> str:
    response = client.chat.completions.create(
        model=FINE_TUNED_MODEL,
        messages=[
            {"role": "system", "content": "당신은 한국 법률 전문가입니다."},
            {"role": "user", "content": question},
        ],
        temperature=0.3,  # 법률 상담: 낮은 temperature
    )
    return response.choices[0].message.content

# 원본 vs 파인튜닝 비교
question = "임대차 계약 중도 해지 시 위약금은?"

print("=== 원본 모델 ===")
print(ask_legal_question_with_base(question))

print("\n=== 파인튜닝 모델 ===")
print(ask_legal_question(question))

모델 관리

# 파인튜닝 작업 목록
jobs = client.fine_tuning.jobs.list(limit=10)
for job in jobs:
    print(f"{job.id}: {job.status} ({job.model})")

# 특정 작업 취소
client.fine_tuning.jobs.cancel(job_id)

# 파인튜닝된 모델 삭제
client.models.delete(FINE_TUNED_MODEL)

비용 계산

# 파인튜닝 비용 추정 (2024년 기준)
# gpt-4o-mini: 학습 $3/1M tokens, 추론 $3/1M input + $12/1M output

def estimate_fine_tuning_cost(
    num_samples: int,
    avg_tokens_per_sample: int,
    n_epochs: int,
    model: str = "gpt-4o-mini"
) -> float:
    total_tokens = num_samples * avg_tokens_per_sample * n_epochs
    if model == "gpt-4o-mini":
        cost_per_million = 3.0
    return (total_tokens / 1_000_000) * cost_per_million

cost = estimate_fine_tuning_cost(
    num_samples=1000,
    avg_tokens_per_sample=500,
    n_epochs=3
)
print(f"예상 학습 비용: ${cost:.2f}")
# 예상 학습 비용: $4.50

정리

단계API설명
파일 업로드files.create()JSONL 파일 업로드
작업 생성fine_tuning.jobs.create()학습 시작
모니터링fine_tuning.jobs.retrieve()진행 상황
사용chat.completions.create(model=ft:...)파인튜닝 모델 추론

다음 편에서는 LoRA/QLoRA — 오픈소스 모델을 저비용으로 파인튜닝하는 방법을 배웁니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.