Korean LLM Fine-tuning Project

이 ν”„λ‘œμ νŠΈλŠ” Llama 3.1 8B λͺ¨λΈμ„ ν•œκ΅­μ–΄ QA λ°μ΄ν„°λ‘œ νŒŒμΈνŠœλ‹ν•˜λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€. LoRA(μ €λž­ν¬ μ–΄λŒ‘ν„°) 방법을 μ‚¬μš©ν•˜μ—¬ 효율적인 νŒŒμΈνŠœλ‹μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

🎯 λͺ©ν‘œ

  • Llama 3.1 8B λͺ¨λΈμ„ ν•œκ΅­μ–΄ λ°μ΄ν„°λ‘œ νŒŒμΈνŠœλ‹
  • LoRAλ₯Ό ν†΅ν•œ λ©”λͺ¨λ¦¬ 효율적인 ν•™μŠ΅
  • ν•œκ΅­μ–΄ μ§ˆμ˜μ‘λ‹΅ λŠ₯λ ₯ ν–₯상
  • 기술λ ₯ μž…μ¦μ„ μœ„ν•œ 데λͺ¨ ν”„λ‘œμ νŠΈ

πŸ“ ν”„λ‘œμ νŠΈ ꡬ쑰

korean-llm-finetune/
β”œβ”€β”€ README.md                 # ν”„λ‘œμ νŠΈ μ„€λͺ…
β”œβ”€β”€ requirements.txt          # ν•„μš”ν•œ νŒ¨ν‚€μ§€ λͺ©λ‘
β”œβ”€β”€ model_card.md            # λͺ¨λΈ μΉ΄λ“œ
β”œβ”€β”€ configs/
β”‚   └── lora_config.yaml     # LoRA μ„€μ •
β”œβ”€β”€ data/
β”‚   └── ko_samples.jsonl     # ν•œκ΅­μ–΄ μƒ˜ν”Œ 데이터
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ train_lora.py        # νŒŒμΈνŠœλ‹ 슀크립트
β”‚   β”œβ”€β”€ evaluate.py          # 평가 슀크립트
β”‚   └── preprocess.py        # μ „μ²˜λ¦¬ 슀크립트
β”œβ”€β”€ inference_demo.ipynb     # μΆ”λ‘  데λͺ¨ λ…ΈνŠΈλΆ
└── outputs/                 # ν•™μŠ΅ κ²°κ³Ό μ €μž₯

πŸš€ μ‹œμž‘ν•˜κΈ°

1. ν™˜κ²½ μ„€μ •

# ν•„μš”ν•œ νŒ¨ν‚€μ§€ μ„€μΉ˜
pip install -r requirements.txt

2. 데이터 μ€€λΉ„

data/ko_samples.jsonl νŒŒμΌμ— ν•œκ΅­μ–΄ QA 데이터λ₯Ό μ€€λΉ„ν•©λ‹ˆλ‹€:

{
  "instruction": "λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš”",
  "input": "ν•œκ΅­μ˜ AI 정책은?",
  "output": "μ •λΆ€λŠ” 2025λ…„λΆ€ν„° λ…μž AI νŒŒμš΄λ°μ΄μ…˜ λͺ¨λΈμ„ 개발 μ€‘μž…λ‹ˆλ‹€."
}

3. λͺ¨λΈ λ‹€μš΄λ‘œλ“œ

Llama 3.1 8B λͺ¨λΈμ„ Hugging Faceμ—μ„œ λ‹€μš΄λ‘œλ“œν•©λ‹ˆλ‹€:

from transformers import AutoTokenizer, AutoModelForCausalLM

# ν† ν¬λ‚˜μ΄μ € λ‹€μš΄λ‘œλ“œ
tokenizer = AutoTokenizer.from_pretrained("meta-llama/llama-3.1-8b")

# λͺ¨λΈ λ‹€μš΄λ‘œλ“œ (Meta λΌμ΄μ„ μŠ€ λ™μ˜ ν•„μš”)
model = AutoModelForCausalLM.from_pretrained("meta-llama/llama-3.1-8b")

4. νŒŒμΈνŠœλ‹ μ‹€ν–‰

cd scripts
python train_lora.py \
    --model_name_or_path meta-llama/llama-3.1-8b \
    --data_path ../data/ko_samples.jsonl \
    --output_dir ../outputs \
    --num_train_epochs 3 \
    --per_device_train_batch_size 1 \
    --learning_rate 2e-4

5. λͺ¨λΈ 평가

python evaluate.py \
    --base-model meta-llama/llama-3.1-8b \
    --adapter-path ../outputs/final_model \
    --test-data ../data/ko_samples.jsonl

6. μΆ”λ‘  데λͺ¨

Jupyter λ…ΈνŠΈλΆμ„ μ‹€ν–‰ν•˜μ—¬ λͺ¨λΈμ„ ν…ŒμŠ€νŠΈν•©λ‹ˆλ‹€:

jupyter notebook inference_demo.ipynb

πŸ”§ μ£Όμš” κΈ°λŠ₯

LoRA νŒŒμΈνŠœλ‹

  • μ €λž­ν¬ μ–΄λŒ‘ν„°λ₯Ό ν†΅ν•œ λ©”λͺ¨λ¦¬ νš¨μœ¨μ„±
  • LoRAλ₯Ό ν†΅ν•œ μ μ‘ν˜• ν•™μŠ΅
  • CPU/M1/M2 ν™˜κ²½μ—μ„œλ„ ν•™μŠ΅ κ°€λŠ₯

ν•œκ΅­μ–΄ μ΅œμ ν™”

  • ν•œκ΅­μ–΄ ν”„λ‘¬ν”„νŠΈ ν¬λ§·νŒ…
  • ν•œκ΅­μ–΄ QA 데이터셋
  • ν•œκ΅­μ–΄ νŠΉν™” ν† ν¬λ‚˜μ΄μ§•

평가 및 데λͺ¨

  • μžλ™ν™”λœ 평가 슀크립트
  • Jupyter λ…ΈνŠΈλΆ 데λͺ¨
  • κ²°κ³Ό μ‹œκ°ν™”

πŸ“Š μ„±λŠ₯ μ§€ν‘œ

  • λͺ¨λΈ 크기: 3.2B νŒŒλΌλ―Έν„°
  • ν•™μŠ΅ κ°€λŠ₯ν•œ νŒŒλΌλ―Έν„°: ~0.85M (LoRA)
  • λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰: CPU/M1/M2 ν™˜κ²½ κΈ°μ€€
  • μ»¨ν…μŠ€νŠΈ 길이: 4096 토큰

πŸ“Š ν…ŒμŠ€νŠΈ κ²°κ³Ό μš”μ•½

  • λͺ¨λΈ: meta-llama/llama-3.1-8b
  • μ–΄λŒ‘ν„°: ../outputs/final_model
  • ν…ŒμŠ€νŠΈ 데이터: ../data/ko_samples.jsonl
  • ν…ŒμŠ€νŠΈ μƒ˜ν”Œ 수: 10
  • 평가 쑰건: max_new_tokens=128, temperature=0.7
  • μ‹œμŠ€ν…œ: Windows-11-10.0.26100-SP0, Intel64 Family 6 Model 183 Stepping 1, Python 3.13.5
# 질문 μž…λ ₯ μ˜ˆμƒ λ‹΅λ³€ 생성 λ‹΅λ³€(μš”μ•½)
1 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” 파이썬으둜 νŒ©ν† λ¦¬μ–Ό ν•¨μˆ˜ λ§Œλ“€μ–΄μ€˜. def factorial(n):
return 1 if n == 0 else n * factorial(n-1)
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
print(factorial(5))
2 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” 사과와 λ°”λ‚˜λ‚˜μ˜ 차이점을 ν•œ λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ€˜. μ‚¬κ³ΌλŠ” μ•„μ‚­ν•˜κ³  λ‹¬μ½€ν•œ 과일이며, λ°”λ‚˜λ‚˜λŠ” λΆ€λ“œλŸ½κ³  λ‹¬μ½€ν•œ μ—΄λŒ€κ³ΌμΌμž…λ‹ˆλ‹€. μ‚¬κ³ΌλŠ” κ³ΌμΌλ‘œμ„œ μƒλž΅μ΄ κ°€λŠ₯ν•˜λ‹€. 과일은 과일이 μ•„λ‹ˆλ―€λ‘œ μƒλž΅ν•  수 μ—†λ‹€. μ‚¬κ³ΌλŠ” κ³ΌμΌλ‘œμ„œ μƒλž΅μ΄ κ°€λŠ₯ν•˜λ‹€. 과일은 과일이 μ•„λ‹ˆλ―€λ‘œ μƒλž΅ν•  수 μ—†λ‹€.
3 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” '인곡지λŠ₯'을 μ΄ˆλ“±ν•™μƒ μˆ˜μ€€μœΌλ‘œ μ„€λͺ…ν•΄μ€˜. 인곡지λŠ₯은 μ‚¬λžŒμ²˜λŸΌ μƒκ°ν•˜κ³  λ°°μš°λŠ” λ˜‘λ˜‘ν•œ 컴퓨터 ν”„λ‘œκ·Έλž¨μ΄μ—μš”. 인곡지λŠ₯은 μΈκ°„μ˜ μ§€λŠ₯을 μ΄ˆλž˜ν•œ 결과물이닀. μΈκ°„μ˜ μ§€λŠ₯을 μ œλŒ€λ‘œ μ„€λͺ…ν•˜κ³  μ‹Άλ‹€λ©΄, "μΈκ°„μ˜ μ§€λŠ₯은 인곡지λŠ₯을 μ œλŒ€λ‘œ μ„€λͺ…ν•˜λŠ” λŠ₯λ ₯이닀."라고 말해야 ν•œλ‹€.
4 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” νŒŒμ΄μ¬μ—μ„œ λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ˜ 차이점을 ν•œ λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ€˜. λ¦¬μŠ€νŠΈλŠ” 변경이 κ°€λŠ₯ν•˜μ§€λ§Œ, νŠœν”Œμ€ ν•œ 번 μƒμ„±ν•˜λ©΄ 값을 λ°”κΏ€ 수 μ—†μŠ΅λ‹ˆλ‹€. λ¦¬μŠ€νŠΈλŠ” μˆœμ„œκ°€ μ—†λ‹€. 리슀트의 λͺ¨λ“  μš”μ†Œκ°€ λ™μΌν•œ 값이 μ•„λ‹ˆλ‹€. νŠœν”Œμ€ μˆœμ„œκ°€ μžˆλ‹€. 리슀트의 λͺ¨λ“  μš”μ†Œκ°€ λ™μΌν•œ 값이 μ•„λ‹ˆλ‹€. νŠœν”Œμ˜ λͺ¨λ“  μš”μ†Œκ°€ λ™μΌν•œ 값이 μ•„λ‹ˆλ‹€.
5 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” '행볡'μ΄λž€ 무엇인지 짧게 μ •μ˜ν•΄μ€˜. 행볡은 기쁘고 만쑱슀러운 감정을 λŠλΌλŠ” μƒνƒœμž…λ‹ˆλ‹€. ν–‰λ³΅λž€, 행볡함, ν–‰λ³΅ν•œ μ‚¬λžŒ
6 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” 파이썬으둜 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ΅¬ν•˜λŠ” ν•¨μˆ˜λ₯Ό μž‘μ„±ν•΄μ€˜. def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
λ‹€μŒμ„ 톡해 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ΅¬ν•˜λŠ” ν•¨μˆ˜λ₯Ό μž‘μ„±ν•˜μ„Έμš”
#νŒŒμ΄μ¬μ—μ„œ λ°˜λ³΅λ¬Έμ„ μ‚¬μš©ν•  λ•ŒλŠ” 반볡 νšŸμˆ˜μ™€ λ°˜λ³΅λ˜λŠ” 숫자λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ£Όμ–΄μ•Ό ν•œλ‹€.
#반볡 νšŸμˆ˜λŠ” λ°˜λ³΅λ˜λŠ” 숫자λ₯Ό λœ»ν•˜λ©°, λ°˜λ³΅λ˜λŠ” μˆ«μžλŠ” 1λΆ€ν„° μ‹œμž‘ν•œλ‹€.
def fibo(n):
a = 0
b = 1
for i in range(n):
a,b = b,a+b
return a
n = int(input())
print(fibo(n))
7 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” 지ꡬ와 λ‹¬μ˜ 차이점을 ν•œ λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ€˜. μ§€κ΅¬λŠ” 생λͺ…체가 μ‚΄ 수 μžˆλŠ” 행성이며, 달은 μ§€κ΅¬μ˜ μœ„μ„±μœΌλ‘œ κ³΅μ „ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ§€κ΅¬μ˜ 3λ°°κ°€ λ˜λŠ” κ±°λ¦¬μ—μ„œ λ‹¬μ˜ 1.5λ°°κ°€ λ˜λŠ” 거리
8 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” '블둝체인'을 μ΄ˆλ“±ν•™μƒμ΄ 이해할 수 있게 μ„€λͺ…ν•΄μ€˜. 블둝체인은 정보λ₯Ό μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•˜λŠ” νŠΉλ³„ν•œ 컴퓨터 기둝μž₯μΉ˜μ˜ˆμš”. 블둝체인은 '이동'μ΄λž€ 의미둜, λΈ”λ‘μ²΄μΈμ—μ„œ '이동'ν•˜λŠ” 것은 데이터λ₯Ό '이동'ν•˜λŠ” 것이닀.
9 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” νŒŒμ΄μ¬μ—μ„œ λ”•μ…”λ„ˆλ¦¬μ™€ 리슀트의 차이점을 ν•œ λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ€˜. λ”•μ…”λ„ˆλ¦¬λŠ” 킀와 κ°’μ˜ 쌍으둜 데이터λ₯Ό μ €μž₯ν•˜κ³ , λ¦¬μŠ€νŠΈλŠ” μˆœμ„œλŒ€λ‘œ 값을 μ €μž₯ν•©λ‹ˆλ‹€. λ”•μ…”λ„ˆλ¦¬μ™€ 리슀트의 μ°¨μ΄λŠ” λ”•μ…”λ„ˆλ¦¬μ—μ„œ ν‚€λ₯Ό μ‚¬μš©ν•  λ•Œ, ν‚€λŠ” ν•­λͺ©μ˜ 이름, λ¦¬μŠ€νŠΈμ—μ„œλŠ” ν•­λͺ©μ˜ 값이닀.
10 λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš” 'μš°μ •'μ΄λž€ 무엇인지 짧게 μ •μ˜ν•΄μ€˜. μš°μ •μ€ μ„œλ‘œλ₯Ό 아끼고 λ„μ™€μ£ΌλŠ” 친ꡬ μ‚¬μ΄μ˜ μ†Œμ€‘ν•œ κ΄€κ³„μž…λ‹ˆλ‹€. "μš°μ •μ€ 두 μ‚¬λžŒμ΄ μ„œλ‘œ μ•ˆμ˜ κ°€μΉ˜λ₯Ό ν•¨κ»˜ 느끼고, μ„œλ‘œλ₯Ό μ‘΄μ€‘ν•˜κ³ , μ‚¬λž‘ν•˜κ³ , λ™κΈ°λΆ€μ—¬ν•˜κ³ , μ‘΄μ€‘ν•˜κΈ° μœ„ν•΄ μ„œλ‘œλ₯Ό μ§€μ§€ν•œλ‹€. μš°μ •μ€ μ„œλ‘œμ˜ κ°€μΉ˜μ— λŒ€ν•œ 동기뢀여가 ν•„μš”ν•˜λ©°, μ„œλ‘œμ˜ κ°€μΉ˜λ₯Ό μ‘΄μ€‘ν•œλ‹€. μš°μ •μ€ 두 μ‚¬λžŒμ΄ μ„œλ‘œμ—κ²Œ μ‘΄μ€‘ν•˜λŠ” κ°€μΉ˜λ₯Ό μ‘΄μ€‘ν•˜κΈ° μœ„ν•΄ μ„œλ‘œλ₯Ό μ‘΄μ€‘ν•œλ‹€."

πŸ› οΈ 기술 μŠ€νƒ

  • Transformers: Hugging Face Transformers 라이브러리
  • PEFT: Parameter-Efficient Fine-Tuning
  • PyTorch: λ”₯λŸ¬λ‹ ν”„λ ˆμž„μ›Œν¬
  • Datasets: 데이터 처리

πŸ“ μ‚¬μš© μ˜ˆμ‹œ

from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel

# λͺ¨λΈ λ‘œλ“œ
tokenizer = AutoTokenizer.from_pretrained("meta-llama/llama-3.1-8b")
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/llama-3.1-8b")
model = PeftModel.from_pretrained(base_model, "./outputs/final_model")

# μΆ”λ‘ 
prompt = "### 질문: λ‹€μŒ μ§ˆλ¬Έμ— λ‹΅ν•˜μ„Έμš”\nμž…λ ₯: ν•œκ΅­μ˜ μˆ˜λ„λŠ”?\n### λ‹΅λ³€:"
inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=128)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

🀝 κΈ°μ—¬ν•˜κΈ°

  1. 이 μ €μž₯μ†Œλ₯Ό ν¬ν¬ν•©λ‹ˆλ‹€
  2. μƒˆλ‘œμš΄ κΈ°λŠ₯ 브랜치λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€
  3. 변경사항을 μ»€λ°‹ν•©λ‹ˆλ‹€
  4. λΈŒλžœμΉ˜μ— ν‘Έμ‹œν•©λ‹ˆλ‹€
  5. Pull Requestλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€

πŸ“„ λΌμ΄μ„ μŠ€

이 ν”„λ‘œμ νŠΈλŠ” MIT λΌμ΄μ„ μŠ€ ν•˜μ— λ°°ν¬λ©λ‹ˆλ‹€. Llama 3.2 λͺ¨λΈ μ‚¬μš©μ„ μœ„ν•΄μ„œλŠ” Meta의 λΌμ΄μ„ μŠ€ λ™μ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

πŸ™ κ°μ‚¬μ˜ 말

  • Meta AI의 Llama 3.2 λͺ¨λΈ
  • Hugging Face νŒ€μ˜ Transformers 라이브러리
  • Microsoft의 PEFT 라이브러리

πŸ“ž 문의

ν”„λ‘œμ νŠΈμ— λŒ€ν•œ λ¬Έμ˜μ‚¬ν•­μ΄ μžˆμœΌμ‹œλ©΄ 이슈λ₯Ό μƒμ„±ν•΄μ£Όμ„Έμš”.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support