← 목록으로
RTX 5090으로 Llama 3.1 파인튜닝하기
gcube · hands-on

RTX 5090으로 Llama 3.1 파인튜닝하기

on this page

GPU 한 장으로 끝내는 한국어 LLM 파인튜닝

gcube에서 Unsloth로 Llama 3.1 8B 직접 튜닝하기

📷 대표 이미지 — gcube 콘솔 + JupyterLab 화면 / Llama·GPU 썸네일

"파인튜닝은 GPU 서버 농장이 있어야 가능한 거 아닌가요?"

몇 년 전이라면 맞는 말이었습니다. 하지만 지금은 GPU 한 장이면 됩니다.

오늘은 Unsloth 라이브러리로 Meta의 Llama 3.1 8B 모델을 한국어 데이터셋으로 파인튜닝하는 과정을 처음부터 끝까지 따라가 보겠습니다. 그것도 gcube GPU 클라우드 서버 위에서요. 이 글을 다 읽고 나면, 여러분만의 한국어 LLM을 직접 만들 수 있게 됩니다. 👇

💡 왜 파인튜닝인가? — 프롬프트 엔지니어링과의 차이

LLM을 원하는 방향으로 동작시키는 방법은 크게 두 가지입니다.

  • 프롬프트 엔지니어링 — 모델은 그대로 두고, 입력 문장을 잘 짜서 원하는 답을 유도합니다. 빠르고 비용이 없지만, 모르는 도메인 지식이나 특정 말투·포맷을 안정적으로 따르게 만들기는 어렵습니다.
  • 파인튜닝 — 모델의 가중치 자체를 우리 데이터로 추가 학습합니다. 특정 도메인(사내 문서·법률·의료)이나 일관된 응답 스타일이 필요할 때, 프롬프트만으로는 도달할 수 없는 품질을 만듭니다.

"우리 회사 문서 톤으로만 답하는 챗봇", "특정 분야 질문에 정확히 답하는 모델"이 필요하다면 → 파인튜닝이 답입니다.

⚡ Unsloth — GPU 한 장으로 가능해진 이유

과거 8B급 모델의 풀 파인튜닝(Full Fine-Tuning)은 모든 파라미터를 다시 학습시켜야 해서 고사양 GPU 여러 장이 필요했습니다.

여기서 등장하는 게 QLoRA입니다. 베이스 모델의 가중치는 4비트로 양자화해 얼려두고(freeze), 작은 어댑터만 끼워 그 부분만 학습합니다. Llama 3.1 8B 기준 학습 대상 파라미터가 전체의 0.5%인 약 4,200만 개로 줄어드는데, 정확도는 99% 이상 유지됩니다.

Unsloth는 직접 작성한 Triton 커널 최적화로, 표준 Hugging Face Transformers 대비 약 2배 빠른 학습 속도약 70% 적은 VRAM을 달성합니다. (출처: Unsloth 공식 블로그, Towards Data Science)

📊 실측 VRAM 수치 — RTX 5090 환경에서 직접 측정

  • 4bit Llama 3.1 8B 로드 직후 → 약 5.7GB
  • LoRA 어댑터 + 학습 중 최대 → 약 12.5GB (16GB GPU 한 장이면 충분)
  • Colab T4(16GB) · RTX 4090 · L4 · A100 · RTX 5090 모두 가능
  • 단, Unsloth는 단일 GPU만 지원 (멀티 GPU는 TRL · Axolotl)

바로 이 지점에서 gcube가 빛을 발합니다. "복잡한 AI 인프라 없이, 몇 번의 클릭으로 GPU 워크로드를 실행·확장한다"는 메시지가 단일 GPU 파인튜닝과 정확히 맞아떨어지거든요.

📋 실습 준비물

  • gcube 계정 (워크로드 생성용 — 설정값은 STEP 0 참고)
  • Hugging Face 계정 및 Access Token (모델·데이터셋 다운로드용)

STEP 0 — gcube 워크로드(컨테이너) 설정

gcube 콘솔에서 Workload를 생성할 때 아래 값을 그대로 넣으면, 환경 세팅과 Unsloth 설치가 한 번에 끝납니다. unsloth/unsloth 이미지에 PyTorch·CUDA·Unsloth·JupyterLab이 모두 사전설치돼 있습니다.

항목
컨테이너 이미지unsloth/unsloth
GPUVRAM 16GB 이상 (RTX 4090 / L4 / A100 / RTX 5090)
RAM16GB 이상
볼륨30GB 이상
포트8888 (JupyterLab WebUI) · 8000 (선택, 추론 API)
환경 변수HF_TOKEN = 본인의 Hugging Face 토큰 / JUPYTER_PASSWORD = JupyterLab 접속 비밀번호 / HF_HOME = /workspace/.cache/huggingface

HF_TOKEN을 환경 변수로 넣어두면 노트북 안에서 별도 로그인 코드 없이 모델·데이터셋이 바로 다운로드됩니다. 워크로드가 뜨면 8888 포트의 JupyterLab으로 접속해 아래 STEP들을 진행합니다.

🔗 gcube 공식 문서 바로가기 →

📷 gcube 워크로드 생성 화면 — 이미지 · GPU · 환경변수 입력 부분 캡처

※ 직접 환경을 구성하는 경우에만: Python 3.10/3.11 + CUDA 12.1 이상에서 pip install unsloth. 공식 이미지를 쓰면 신경 쓸 필요 없습니다.

STEP 1 — 4bit Llama 3.1 8B 모델 로드

Unsloth가 미리 4비트로 양자화해 둔 모델을 불러옵니다. 다운로드도 4배 빠릅니다.

from unsloth import FastLanguageModel
import torch

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.1-8B-bnb-4bit",
    max_seq_length = 2048,
    dtype = None,
    load_in_4bit = True,
)

핵심은 load_in_4bit = True입니다. 모델 가중치는 4비트로 VRAM에 올라가고, 학습 중 활성값·그래디언트는 더 높은 정밀도로 흐릅니다. 이 덕분에 8B 모델이 로드 직후 약 5.7GB만 차지합니다.

참고: unsloth/Meta-Llama-3.1-8B-bnb-4bit는 Unsloth가 재배포한 모델이라, Meta 원본처럼 별도 접근 승인 없이 바로 다운로드됩니다.

📷 모델 로드 완료 셀 캡처 — VRAM 5.7GB 출력 확인

STEP 2 — 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 = 16,
    lora_dropout = 0,
    bias = "none",
    use_gradient_checkpointing = "unsloth",
    random_state = 3407,
)
  • r — 어댑터의 랭크. 8·16·32·64 중 보통 16부터 시작
  • target_modules — 어텐션과 MLP 레이어 전체에 어댑터 부착
  • use_gradient_checkpointing="unsloth" — VRAM 30% 추가 절약 + 더 긴 컨텍스트 처리

학습이 끝나면 결과물은 수 기가짜리 전체 체크포인트가 아니라, 수십 MB짜리 어댑터 파일 하나입니다. 가볍게 배포할 수 있죠.

STEP 3 — 한국어 데이터셋 준비

이 실습의 핵심입니다. 영어로 사전학습된 Llama를 한국어에 맞추려면 양질의 한국어 instruction 데이터가 필요합니다.

이번에는 beomi/KoAlpaca-v1.1a를 사용합니다. 약 21,000건의 한국어 Q&A 쌍으로 구성돼 있고, 별도 접근 승인 없이 바로 다운로드됩니다. (KoAlpaca-RealQA는 더 자연스러운 실사용자 데이터지만 gated 데이터셋이라 HF에서 승인이 필요합니다.)

from datasets import load_dataset

dataset = load_dataset("beomi/KoAlpaca-v1.1a", split = "train")

# 이 데이터셋의 컬럼은 instruction / output 입니다.
def formatting_func(example):
    text = f"""### 질문:
{example['instruction']}

### 답변:
{example['output']}""" + tokenizer.eos_token
    return {"text": text}

dataset = dataset.map(formatting_func)

데이터셋별 컬럼명 주의
load 후 dataset.column_names로 먼저 확인하세요. 이 데이터셋은 output, KoAlpaca-RealQA는 response로 다릅니다.

STEP 4 — 파인튜닝 실행

이제 학습을 돌립니다. SFTTrainer를 사용합니다.

from trl import SFTTrainer
from transformers import TrainingArguments

trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset,
    dataset_text_field = "text",
    max_seq_length = 2048,
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,
        warmup_steps = 5,
        max_steps = 60,
        learning_rate = 2e-4,
        fp16 = not torch.cuda.is_bf16_supported(),
        bf16 = torch.cuda.is_bf16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
        report_to = "none",
    ),
)

trainer.train()

report_to = "none" 필수
일부 환경에서 SFTTrainer가 기본 로깅 연동(trackio)을 불러오다 huggingface_hub 버전과 충돌해 ImportError가 납니다. 로깅을 끄면 우회됩니다. ⚠ OOM 발생 시per_device_train_batch_size를 1~2로 낮추세요. 가장 흔한 메모리 에러 원인입니다.

학습 시간: T4에서 1,000 샘플 기준 약 2시간 / RTX 4090은 1시간 안쪽 / RTX 5090은 더 빠름.

📷 학습 진행 로그 캡처 — loss가 줄어드는 화면

STEP 5 — Before / After — 결과 비교

학습된 모델로 추론해 봅니다.

FastLanguageModel.for_inference(model)

inputs = tokenizer(
    ["### 질문:\n한국의 전세 제도에 대해 설명해줘.\n\n### 답변:\n"],
    return_tensors = "pt"
).to("cuda")

outputs = model.generate(**inputs, max_new_tokens = 256)
print(tokenizer.batch_decode(outputs)[0])

파인튜닝 전 베이스 모델은 한국어 질문에 영어로 답하거나 어색한 번역체를 내놓는 경우가 많습니다. 파인튜닝 후에는 자연스러운 한국어로, 질문 의도에 맞게 답하는 걸 확인할 수 있습니다.

📷 Before / After 응답 캡처를 나란히 — 이 글의 하이라이트 — 반드시 넣으세요!

STEP 6 — GGUF로 내보내고 Ollama로 서빙

학습이 끝났으면 실제 서비스에 올려야겠죠. Unsloth는 GGUF 내보내기를 지원해 Ollama·llama.cpp로 바로 서빙할 수 있습니다.

model.save_pretrained_gguf("korean_llama", tokenizer,
                           quantization_method = "q4_k_m")

첫 실행은 16비트 가중치 병합 + llama.cpp 빌드가 포함돼 10~20분가량 걸립니다. (한 번 빌드하면 다음부터 빠릅니다.)

출력 경로 주의"korean_llama"를 넘겨도 Unsloth는 실제로 korean_llama_gguf/ 폴더에 저장하고, 파일명도 베이스 모델 이름을 따릅니다. 아래로 실제 위치를 확인하세요.

import os
gguf_dir = "korean_llama_gguf"
print([f for f in os.listdir(gguf_dir) if f.endswith(".gguf")])
# 예: ['Meta-Llama-3.1-8B.Q4_K_M.gguf']  (약 4.9GB)

이 GGUF 파일을 Ollama에 등록하면, 우리만의 한국어 모델을 API로 호출할 수 있습니다.

여기까지가 GPU 한 장으로 완성하는 한국어 LLM 파인튜닝의 전 과정입니다. 🎉

🚀 마무리 — 그래서 GPU는 어디서?

파인튜닝의 모든 단계는 결국 하나로 귀결됩니다. "충분한 VRAM을 가진 GPU 한 장을, 필요할 때 바로 쓸 수 있느냐."

gcube(지큐브)는 바로 그 지점을 해결하는 GPU 클라우드 플랫폼입니다.

  • 이종 GPU 풀링 — RTX 4090부터 고성능 GPU까지, 워크로드에 맞게 유연하게 할당
  • 컨테이너 기반 멀티테넌트 격리 — 각자의 학습 환경이 안전하게 분리
  • 몇 번의 클릭으로 시작 — 복잡한 드라이버·CUDA 세팅 없이 파인튜닝에 바로 집중

오늘 실습한 Unsloth + Llama 3.1 8B 파인튜닝, gcube 인스턴스 하나면 충분합니다. 여러분만의 한국어 LLM, 지금 바로 시작해 보세요!

🔗 gcube 바로가기 → [링크 삽입]

※ gcube는 CES 2026 Innovation Award(AI 부문)를 수상한 GPU 클라우드 플랫폼입니다.