반응형
GPT-4급 성능을 API 비용 없이. 내 도메인 데이터로 특화된 모델을.
Gemma 4는 2026년 4월 2일 Google DeepMind가 출시한 오픈소스 모델이에요. Apache 2.0 라이선스 — 상업적 사용, 재배포, 수정 모두 자유예요.
파인튜닝이 필요한 이유:
프롬프트 엔지니어링: "항상 JSON으로 응답해줘" → 30% 실패율
RAG: 지식 주입엔 좋지만 스타일/형식 제어 어려움
파인튜닝: 99% 이상 일관된 출력, 도메인 특화 지식
언제 파인튜닝이 답인가:
→ 출력 형식이 항상 일정해야 할 때
→ 특정 도메인 용어/스타일이 필요할 때
→ 프롬프트가 너무 길어서 비용 문제가 될 때
→ API 없이 로컬/온프레미스 배포가 필요할 때
Unsloth가 뭔가
HuggingFace 기본 방식 대비:
속도: 2배 빠른 학습
메모리: 최대 70% 절약
기본 HuggingFace로 E4B 파인튜닝:
→ VRAM 15GB 필요
Unsloth QLoRA로:
→ VRAM 8GB면 충분 (RTX 3070, 3060 ti 가능)
0단계 — 모델 선택
E2B (2B): 스마트폰/라즈베리파이 수준
→ 매우 가벼운 분류/추출 작업
E4B (4B): ← 이 글의 대상
무료 Google Colab T4 GPU에서 가능
RTX 3060 이상이면 로컬에서도 가능
텍스트 + 이미지 + 오디오 지원
26B A4B: A100 Colab 또는 RTX 4090 필요
MoE 구조 → QLoRA 비권장, 16bit LoRA 권장
31B: RTX 4090 24GB + QLoRA
최고 품질
1단계 — 환경 설치
# 가상환경 생성
python -m venv gemma4-finetune
source gemma4-finetune/bin/activate # Windows: .\gemma4-finetune\Scripts\activate
# Unsloth 설치 (의존성 전부 포함)
pip install unsloth
# GPU 없이 CPU만 있는 경우
pip install unsloth[cpu]
# 추가 라이브러리
pip install datasets trl transformers
Google Colab에서 할 경우 (무료 T4 GPU):
# Colab 첫 셀에 실행
!pip install unsloth
!pip install datasets trl
2단계 — 학습 데이터 만들기
파인튜닝의 핵심은 데이터예요. 코드보다 훨씬 중요해요.
데이터 형식
{"messages": [
{"role": "user", "content": "FastAPI에서 JWT 인증 미들웨어 만들어줘"},
{"role": "assistant", "content": "```python\nfrom fastapi import Request, HTTPException\nfrom jose import jwt\n...\n```\n\n위 코드는 Bearer 토큰을 검증합니다..."}
]}
{"messages": [
{"role": "user", "content": "PostgreSQL 연결 풀 설정하는 법"},
{"role": "assistant", "content": "```python\nfrom sqlalchemy.ext.asyncio import create_async_engine\n...\n```"}
]}
데이터 수집 방법
# 방법 1: 직접 작성 (품질 최고)
training_data = [
{
"messages": [
{"role": "user", "content": "질문"},
{"role": "assistant", "content": "답변"}
]
},
# ...
]
# JSONL로 저장
import json
with open("training_data.jsonl", "w", encoding="utf-8") as f:
for item in training_data:
f.write(json.dumps(item, ensure_ascii=False) + "\n")
# 방법 2: 기존 문서/로그에서 자동 생성
import anthropic
client = anthropic.Anthropic()
def generate_qa_pairs(document: str, n: int = 10) -> list:
"""문서에서 Q&A 쌍 자동 생성"""
response = client.messages.create(
model="claude-haiku-4-5", # 생성은 Haiku로 절약
max_tokens=2000,
messages=[{
"role": "user",
"content": f"""
다음 문서를 기반으로 Q&A 쌍 {n}개를 만들어줘.
실제 사용자가 물어볼 법한 질문과 정확한 답변으로.
JSON 배열로만 응답해줘:
[{{"user": "질문", "assistant": "답변"}}, ...]
문서:
{document}
"""
}]
)
pairs = json.loads(response.content[0].text)
return [
{"messages": [
{"role": "user", "content": p["user"]},
{"role": "assistant", "content": p["assistant"]}
]}
for p in pairs
]
# 내 회사 문서에서 생성
docs = ["API 문서 내용", "코딩 가이드라인", "도메인 지식 문서"]
all_pairs = []
for doc in docs:
pairs = generate_qa_pairs(doc, n=20)
all_pairs.extend(pairs)
print(f"총 {len(all_pairs)}개 학습 데이터 생성")
최소 데이터 기준
50개: 기본적인 스타일/형식 학습 가능
100개: 도메인 용어 습득
200개: 대부분의 도메인 특화 작업에 충분
500개+: 전문가 수준 도메인 모델
3단계 — 파인튜닝 실행
from unsloth import FastLanguageModel
import torch
from datasets import load_dataset
from trl import SFTTrainer, SFTConfig
# ── 1. 모델 로드 ──────────────────────────────────
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/gemma-4-E4B-it", # E4B 권장
max_seq_length=2048, # 보수적으로 시작
load_in_4bit=True, # QLoRA — VRAM 절반으로
dtype=None, # 자동 감지
)
# ── 2. LoRA 어댑터 추가 ───────────────────────────
model = FastLanguageModel.get_peft_model(
model,
r=16, # LoRA 랭크 (8~32 권장)
lora_alpha=16, # 스케일링 파라미터
lora_dropout=0, # Unsloth 최적화 — 0 유지
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
use_gradient_checkpointing="unsloth", # VRAM 30% 추가 절약
bias="none",
)
# ── 3. 데이터셋 로드 ──────────────────────────────
dataset = load_dataset(
"json",
data_files="training_data.jsonl",
split="train"
)
# 채팅 템플릿 적용
def apply_chat_template(examples):
texts = []
for messages in examples["messages"]:
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=False
)
texts.append(text)
return {"text": texts}
dataset = dataset.map(apply_chat_template, batched=True)
# ── 4. 학습 설정 ──────────────────────────────────
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
args=SFTConfig(
output_dir="./gemma4-finetuned",
# 핵심 설정
num_train_epochs=3, # 데이터 200개 이하면 3, 이상이면 1~2
per_device_train_batch_size=2, # VRAM 부족하면 1로
gradient_accumulation_steps=4, # 사실상 배치 8
# 학습률
learning_rate=2e-4,
warmup_ratio=0.1,
lr_scheduler_type="cosine",
# 정밀도
bf16=True, # RTX 30xx 이상 지원
fp16=False,
# 로깅
logging_steps=10,
save_strategy="epoch",
# 최적화
dataset_text_field="text",
max_seq_length=2048,
packing=True, # 짧은 샘플 묶어서 효율 향상
),
)
# ── 5. 학습 시작 ──────────────────────────────────
print("학습 시작...")
trainer.train()
print("완료!")
4단계 — 결과 확인
# 학습 전후 비교
from unsloth import FastLanguageModel
# 추론 모드로 전환 (필수!)
FastLanguageModel.for_inference(model)
def ask(prompt: str) -> str:
messages = [{"role": "user", "content": prompt}]
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_tensors="pt"
).to("cuda")
outputs = model.generate(
input_ids=inputs,
max_new_tokens=512,
temperature=0.7,
do_sample=True,
)
# 입력 부분 제거하고 응답만 추출
response = tokenizer.decode(
outputs[0][inputs.shape[-1]:],
skip_special_tokens=True
)
return response
# 테스트
print(ask("FastAPI에서 JWT 인증 어떻게 구현해?"))
5단계 — GGUF로 내보내서 Ollama에 배포
# GGUF 변환 + 저장
model.save_pretrained_gguf(
"gemma4-custom",
tokenizer,
quantization_method="q4_k_m" # 권장: q4_k_m (품질/크기 균형)
# 옵션: q8_0 (고품질), q4_0 (소형), q2_k (초소형)
)
Ollama에 등록:
# Modelfile 생성
cat > Modelfile << 'EOF'
FROM ./gemma4-custom-Q4_K_M.gguf
SYSTEM """
당신은 우리 회사 FastAPI/Python 전문 코딩 어시스턴트입니다.
항상 실행 가능한 코드를 제공하고, 우리 프로젝트 구조를 따릅니다.
"""
EOF
# Ollama에 등록
ollama create my-gemma4 -f Modelfile
# 실행
ollama run my-gemma4
GPU별 예상 시간 (데이터 200개 기준)
무료 Colab T4 (16GB): 약 25~35분
RTX 3060 (12GB): 약 40~50분
RTX 3090 (24GB): 약 15~20분
RTX 4090 (24GB): 약 10~15분
A100 (40GB): 약 5~10분
흔한 실수와 해결법
OOM (Out of Memory):
→ per_device_train_batch_size=1 로 줄이기
→ max_seq_length=1024 로 줄이기
→ gradient_accumulation_steps=8 으로 늘리기
Loss가 안 떨어짐:
→ learning_rate=5e-4 로 높이기
→ 데이터 품질 확인 (형식 일관성)
→ num_train_epochs=5 로 늘리기
파인튜닝 후 성능 저하:
→ r=8 로 낮추기 (과적합 방지)
→ 데이터에 일반 지식 샘플 20~30% 섞기
→ epoch 3에서 멈추기 (더 이상 하면 오히려 나빠짐)
추론 모드 안 함:
→ FastLanguageModel.for_inference(model) 반드시 호출
→ 안 하면 학습 모드로 동작 → 느리고 이상한 출력
전체 파이프라인 요약
1. 데이터 준비 (15분)
→ JSONL 형식 200개 이상
→ 기존 문서/로그에서 AI로 자동 생성 가능
2. 학습 실행 (10~35분, GPU에 따라)
→ pip install unsloth 한 줄
→ 코드 복붙 후 dataset 경로만 수정
3. 결과 확인 (5분)
→ 학습 전/후 같은 질문으로 비교
4. GGUF 내보내기 (5분)
→ Ollama에 등록하면 어디서든 사용
반응형
'LLM' 카테고리의 다른 글
| GPT-5.5 출시 완전 분석 — Claude Opus 4.7에 일주일 만에 날린 OpenAI의 반격 (0) | 2026.04.24 |
|---|---|
| OpenRouter 완전 가이드 — API 키 하나로 GPT, Claude, Gemini, Llama 200개+ 모델 전부 쓰기 (0) | 2026.04.23 |
| LLM 사설 평가셋 50개 만들고 모델 비교하기 — 벤치마크를 믿지 마세요 (1) | 2026.04.20 |
| Opus 4.7 에이전트 비용 제어 실전 — effort + Task Budget 완전 가이드 (0) | 2026.04.20 |
| Claude Opus 4.7 토크나이저 함정 — 같은 가격, 더 많은 비용 (0) | 2026.04.20 |