AI

더 나은 결과를 위한 최신 웹 데이터로 Llama 4 미세 조정

데이터셋 생성부터 모델 훈련 및 테스트까지, 웹 스크래핑 데이터를 활용해 Llama 4를 미세 조정하는 방법을 알아보세요.
2 분 읽기
Fine-tuning Llama 4

웹 데이터로 Llama 4를 미세 조정하는 이 가이드에서는 다음을 배울 수 있습니다:

  • – 미세 조정이란 무엇인가
  • 스크래핑 API를 활용해 미세 조정용 데이터셋을 수집하는 방법
  • – 미세 조정 프로세스를 위한 클라우드 인프라 설정 방법
  • 단계별 튜토리얼을 통한 Llama 4 미세 조정 방법

시작해 보겠습니다!

파인 튜닝이란?

미세 조정 (SFT, 감독형 미세 조정)은사전 훈련된 대규모 언어 모델(LLM)의 특정 지식이나 능력을 향상시키기 위해 사용되는 과정입니다. LLM의 맥락에서 사전 훈련은 AI 모델을 처음부터 훈련시키는 것을 의미합니다.

모델은 훈련 데이터를 모방하기 때문에 SFT가 사용됩니다. 그러나 현재까지 LLM은 주로 범용 모델입니다. 즉, 모델이 특정 지식을 학습하도록 하려면 미세 조정이 필요합니다.

SFT에 대해 더 자세히 알고 싶다면, LLM의 감독형 미세 조정 가이드를 읽어보세요.

LLama 4 미세 조정을 위한 데이터 스크래핑

LLM을 미세 조정하려면 먼저 미세 조정 데이터 세트가 필요합니다. 이 섹션에서는 Bright Data의 웹 스크레이퍼 API를사용하여 웹사이트에서 데이터를 검색하는 방법을 안내합니다. 100개 이상의 도메인에 대한 전용 엔드포인트로, 최신 데이터를 스크레이핑하여 원하는 형식으로 검색해 줍니다.

대상 웹페이지는 아마존 베스트셀러 사무용품 페이지입니다:

The Amazon best-seller products in the category “office products”

아래 단계를 따라 미세 조정 데이터를 수집하세요!

필요 사항

Amazon에서 데이터를 추출하는 코드를 사용하려면 다음이 필요합니다:

API 키를 검색하려면 Bright Data 문서를 따르십시오.

프로젝트 구조 및 종속성

프로젝트의 메인 폴더를 amazon_scraper/라고 가정합니다 . 이 단계가 완료되면 폴더 구조는 다음과 같습니다:

amazon_scraper/
    ├── scraper.py
    └── venv/

여기서:

  • scraper.py는 코딩 로직이 포함된 Python 파일입니다.
  • venv/에는 가상 환경이 포함됩니다.

다음과 같이 venv/ 가상 환경 디렉터리를 생성할 수 있습니다:

python -m venv venv

활성화하려면 Windows에서 다음을 실행하세요:

venvScriptsactivate

macOS 및 Linux에서는 다음과 같이 실행합니다:

source venv/bin/activate

활성화된 가상 환경에서 다음 명령어로 종속성을 설치하세요:

pip install requests

여기서 requests는 HTTP 웹 요청을 생성하는 라이브러리입니다.

좋습니다! 이제 Bright Data의 Scraper API를 사용하여 관심 있는 데이터를 가져올 준비가 되었습니다.

1단계: 스크래핑 로직 정의

다음 코드 조각은 전체 스크래핑 로직을 정의합니다:

import requests
import json
import time


def trigger_amazon_products_scraping(api_key, urls):
    # 웹 스크레이퍼 API 작업을 트리거할 엔드포인트
    url = "https://api.brightdata.com/datasets/v3/trigger"

    params = {
        "dataset_id": "gd_l7q7dkf244hwjntr0",
        "include_errors": "true",
        "type": "discover_new",
        "discover_by": "best_sellers_url",
    }

    # API 호출을 위해 입력 데이터를 원하는 형식으로 변환
    data = [{"category_url": url} for url in urls]

    headers = {
      "Authorization": f"Bearer {api_key}",
      "Content-Type": "application/json",
    }

    response = requests.post(url, headers=headers, params=params, json=data)

    if response.status_code == 200:
        snapshot_id = response.json()["snapshot_id"]
        print(f"요청 성공! 응답: {snapshot_id}")
        return response.json()["snapshot_id"]
    else:
        print(f"요청 실패! 오류: {response.status_code}")
        print(response.text)

def poll_and_retrieve_snapshot(api_key, snapshot_id, output_file, polling_timeout=20):
    snapshot_url = f"https://api.brightdata.com/datasets/v3/snapshot/{snapshot_id}?format=json"
    headers = {
        "Authorization": f"Bearer {api_key}"
    }

    print(f"ID: {snapshot_id} 스냅샷 폴링 중...")

    while True:
        response = requests.get(snapshot_url, headers=headers)

        if response.status_code == 200:
            print("스냅샷 준비 완료. 다운로드 중...")
            snapshot_data = response.json()

            # 스냅샷을 출력 JSON 파일에 기록
            with open(output_file, "w", encoding="utf-8") as file:
                json.dump(snapshot_data, file, indent=4)

            print(f"스냅샷이 {output_file}에 저장되었습니다")
            return
        elif response.status_code == 202:
            print(F"스냅샷이 아직 준비되지 않았습니다. {polling_timeout} 초 후에 재시도 중...")
            time.sleep(polling_timeout)
        else:
            print(f"요청 실패! 오류: {response.status_code}")
            print(response.text)
            break

if __name__ == "__main__":
    BRIGHT_DATA_API_KEY = "<your api key>" # Bright Data의 웹 스크레이퍼 API 키로 교체하거나 환경 변수에서 읽어오세요
    # 데이터를 가져올 베스트셀러 제품 URL
    urls = [
        "https://www.amazon.com/gp/bestsellers/office-products/ref=pd_zg_ts_office-products"
    ]
    snapshot_id = trigger_amazon_products_scraping(BRIGHT_DATA_API_KEY, urls)
    poll_and_retrieve_snapshot(BRIGHT_DATA_API_KEY, snapshot_id, "amazon-data.json")

이 코드는:

    • 스크레이퍼 API 엔드포인트를 정의하여 트리거합니다.
    • 스크래핑 활동에 대한 매개변수를 설정합니다.
    • 입력 URL 을 API가 요구하는 JSON 구조로 포맷팅합니다.
    • 지정된 엔드포인트, 헤더, 매개변수 및 데이터를 포함하여 Bright Data Scraper API로 POST 요청을 전송합니다.
    • 응답 상태를 관리합니다.
  • 스크래핑 작업( snapshot_id로 식별)의 상태를 확인하고 준비 완료 시 데이터를 가져오는 poll_and_retrieve_snapshot() 함수를 생성합니다.

스크래핑 API는 단일 URL로 호출되었음을 유의하십시오. 따라서 위 코드는 하나의 대상 아마존 페이지에서만 데이터를 가져옵니다. 이 튜토리얼 범위에는 충분하지만, 원하는 만큼 아마존 URL을 목록에 추가할 수 있습니다.

추가하는 URL이 많을수록 데이터셋 크기도 증가한다는 점을 고려하세요. 잘 관리된 대규모 데이터셋은 더 나은 미세 조정을 의미합니다. 반면 데이터셋이 클수록 필요한 계산 시간도 길어집니다.

완벽합니다! 스크래핑 로직이 명확히 정의되었으며, 이제 스크립트를 실행할 준비가 되었습니다.

2단계: 스크립트 실행

대상 웹페이지를 스크래핑하려면 다음 명령어로 스크립트를 실행하세요:

python scraper.py

다음과 같은 결과를 얻을 수 있습니다:

요청 성공! 응답: s_m9in0ojm4tu1v8h78
ID: s_m9in0ojm4tu1v8h78에 대한 스냅샷 폴링 중...
스냅샷이 아직 준비되지 않았습니다. 20초 후에 재시도 중...
# ...
스냅샷이 아직 준비되지 않았습니다. 20초 후에 재시도 중...
스냅샷 준비 완료. 다운로드 중...
스냅샷이 amazon-data.json에 저장되었습니다.

프로세스 완료 시 프로젝트 폴더에는 다음이 포함됩니다:

amazon_scraper/
    ├── scraper.py
    ├── amazon-data.json # <-- 미세 조정 데이터셋 참고
    └── venv/

스크랩된 데이터가 포함된 amazon-data.json 파일이 자동 생성되었습니다. JSON 파일의 예상 구조는 다음과 같습니다:

[
    {
        "title": "Amazon Basics 다목적 복사 프린터 용지, 8.5 x 11 인치, 20 lb, 1 리임, 500 매, 92 광택, 흰색",
        "seller_name": "Amazon.com",
        "brand": "Amazon Basics",
        "description": "제품 설명 Amazon Basics 다목적 복사 프린터 용지, 8.5 x 11 인치 20Lb 용지 - 1 뭉치 (500매), 92 GE 밝은 흰색 제조사 AmazonBasics",
        "initial_price": 6.65,
        "currency": "USD",
        "availability": "재고 있음",
        "reviews_count": 190989,
        "categories": [
            "사무용품",
            "사무 및 학용품",
            "종이",
            "복사 및 인쇄용지",
            "복사 및 다목적 용지"
        ],
        ...
      // 생략...
}

아주 좋습니다! 아마존에서 데이터를 성공적으로 스크래핑하여 JSON 파일에 저장했습니다. 이 JSON 파일은 나중에 미세 조정 과정에서 사용할 미세 조정 데이터셋입니다.

Hugging Face 설정: Llama 4 사용하기

사용할 모델은 Hugging Face의 Llama -4-Scout-17B-16E-Instruct입니다.

Hugging Face를 처음 사용하시는 경우, 링크를 처음 클릭하면 계정 생성을 요청받게 됩니다:

Logging in or signing up to Hugging Face

계정 생성 후 Llama 4 모델을 사용한 적이 없다면 동의서를 작성해야 합니다. “Expand to review and access”를 클릭하여 동의서를 읽고 작성하세요:

Expand to read and compile the form

서식을 작성하면 요청이 검토됩니다:

The result after filling in the form

Gated Repositories” 섹션에서 요청 상태를 확인하세요:

Checking the status in the Gated Repositories section

승인되면 새 토큰을 생성할 수 있습니다. “액세스 토큰“으로 이동하여 쓰기 권한이 있는 토큰을 생성하세요. 생성된 토큰을 안전한 곳에 복사하여 저장해 두세요:

Setting the right permissions in the access token

축하합니다! Hugging Face에서 Llama 4 모델을 사용하기 위한 모든 필수 단계를 완료하셨습니다.

Llama 4 모델을 파인 튜닝하기 위한 클라우드 인프라 설정

Llama 4 모델은 매우 큽니다. 모델 이름만 봐도 그 규모를 짐작할 수 있습니다. 예를 들어, Llama-4-Scout-17B-16E-Instruct는 170억 개의 매개변수와 128개의 전문가 그룹을 의미합니다.

미세 조정 과정에서는 앞서 가져온 미세 조정 데이터셋을 사용하여 모델을 훈련시켜야 합니다. 모델이 170억 개의 매개변수를 가지고 있기 때문에 이를 수행하려면 많은 하드웨어가 필요합니다. 구체적으로, 하나 이상의 GPU가 필요합니다. 이러한 이유로 미세 조정 과정을 수행하기 위해 클라우드 서비스를 사용할 것입니다.

이 튜토리얼에서는 클라우드 서비스로 RunPod를 사용합니다. “RunPod”로 이동하여 계정을 생성하세요. 그런 다음 “Billing” 메뉴로 이동하여 신용카드로 25달러를 충전하세요:

The billing section in RunPod

참고: 즉시 25$가 결제되며 RunPod는 계정에 25$ 상당의 크레딧을 추가합니다. 크레딧은 포드가 배포된 후 가동되는 시간에 따라 시간당 소모됩니다. 따라서 사용이 확실할 때만 배포하세요. 그렇지 않으면 실제 사용 없이 크레딧이 소모됩니다. 실제 시간당 소모량은 다음 단계에서 선택할 GPU의 종류와 수에 따라 달라집니다.

“Pods” 메뉴로 이동하여 포드 구성을 시작하세요. 포드는 작업에 필요한 CPU, GPU, 메모리 및 스토리지를 제공하는 가상 서버 역할을 합니다. “배포(Deploy)” 버튼을 클릭하세요:

The Pods section in RunPod

다양한 구성 중에서 선택할 수 있습니다:

Choosing different types of GPUs in RunPod

“H200 SXM GPU” 옵션을 선택하세요. 포드에 이름을 지정하고 GPU 수를 선택하세요. 이 튜토리얼에는 3개의 GPU로 충분합니다:

Choosing the number of GPUs in RunPod

“Jupyter Notebook 시작”을 선택하고 “수요에 따른 배포”를 클릭하세요. 이제 “Pods” 섹션으로 이동하여 Pod를 편집하세요:

Editing a Pod in RunPod

아래와 같이 “내장 디스크”와 “볼륨 디스크” 값을 변경한 후 저장하세요:

Changing the settings of a Pod in RunPod

설정이 완료되면 “연결” 버튼을 클릭하세요:

Connect the Pod to a Jupyter Lab notebook

이를 통해 포드를 Jupiter Lab 노트북에 연결할 수 있습니다:

Go to the Jupyter Lab notebook

“Python 3 (ipykernel)” 카드가 있는 노트북을 선택하세요:

Select a Python 3 notebook

잘하셨습니다! 이제 Llama 4 모델을 훈련할 수 있는 적절한 인프라를 갖추셨습니다.

스크랩한 데이터로 Llama 4 미세 조정하기

모델 미세 조정을 시작하기 전에 amazon-data.json 파일을 Jupyter Lab 노트북에 업로드하세요. 이를 위해 “파일 업로드” 버튼을 클릭하세요:

Uploading files in Jupyter Lab notebooks

이 튜토리얼의 미세 조정 목표는 amazon-data.json 데이터셋을 사용하여 Llama 4를 훈련시키는 것입니다. 이를 통해 Llama 4가 물체의 이름과 특징 같은 특성을 바탕으로 사무실 물체에 대한 설명을 생성하는 방법을 가르칩니다.

이제 모델 훈련을 시작할 준비가 되었습니다. 아래 단계를 따라 최신 웹 데이터로 Llama 4를 미세 조정하세요!

단계 #1: 라이브러리 설치

노트북의 첫 번째 셀에서 필요한 라이브러리를 설치하세요:

%%capture
!pip install transformers==4.51.0
%pip install -U datasets 
%pip install -U accelerate 
%pip install -U peft 
%pip install -U trl 
%pip install -U bitsandbytes
%pip install huggingface_hub[hf_xet]

해당 라이브러리는 다음과 같습니다:

  • transformers: 수천 개의 사전 훈련된 모델을 제공합니다.
  • datasets: 방대한 데이터셋 컬렉션과 효율적인 데이터 처리 도구를 제공합니다.
  • accelerate: 최소한의 코드 변경으로 다양한 분산 환경에서 PyTorch 훈련 스크립트 실행을 간소화합니다.
  • peft: 소규모 매개변수 하위 집합만 업데이트하여 대규모 사전 훈련 모델을 보다 효율적으로 미세 조정할 수 있게 합니다.
  • trl: 강화 학습 기법을 사용하여 트랜스포머 언어 모델을 훈련하도록 설계되었습니다.
  • scipy: Python에서 과학 및 기술 계산을 위한 라이브러리입니다.
  • huggingface_hub: Hugging Face Hub와 상호 작용하기 위한 Python 인터페이스를 제공합니다. 이를 통해 모델, 데이터 세트 및 Spaces를 다운로드하고 업로드할 수 있습니다.
  • bitsandbytes: 사용하기 쉬운 8비트 최적화기 및 양자화 기능을 제공하여 대규모 딥 러닝 모델의 훈련 및 추론에 필요한 메모리 사용량을 줄입니다.

완벽합니다! 파인 튜닝 과정에 필요한 라이브러리를 설치하셨습니다.

2단계: Hugging Face에 연결하기

노트북의 두 번째 셀에 다음을 작성하세요:

from huggingface_hub import notebook_login, login

# 대화형 로그인
notebook_login()
print("로그인 셀 실행 완료. 성공 시 다음 단계로 진행 가능합니다.")

실행하면 다음과 같이 표시됩니다:

Inserting your token

“Token” 입력란에 Hugging Face 계정에서 생성한 토큰을 붙여넣으세요.

훌륭합니다! 이제 Hugging Face에서 Llama 4 모델을 불러올 수 있습니다.

3단계: Llama 4 모델 로드하기

노트북의 세 번째 셀에 다음 코드를 작성하세요:

import os
import torch
import json
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, Llama4ForConditionalGeneration, BitsAndBytesConfig
from trl import SFTTrainer

# 모델 로드
base_model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct" 

# BitsAndBytes 양자화 설정
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=False,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
)

# 지정된 구성으로 Llama4 모델 로드
model = Llama4ForConditionalGeneration.from_pre-trained(
    base_model_name,
    device_map="auto", 
    torch_dtype=torch.bfloat16,
    quantization_config=bnb_config,
    trust_remote_code=True,
)

# 모델 캐싱 비활성화
model.config.use_cache = False
# 사전 훈련 텐서 병렬 처리 설정 (1로 설정)
model.config.pre-training_tp = 1

# 미세 조정 JSON 데이터 파일 경로
fine_tuning_data_file_path = "amazon-data.json"

# 결과 저장 경로
output_model_dir = "results_llama_office_items_finetuned/"
final_model_adapter_path = os.path.join(output_model_dir, "final_adapter")
max_seq_length_for_tokenization = 1024

# 출력 디렉터리 생성
os.makedirs(output_model_dir)

위의 코드 조각:

  • base_model_name으로 로드할 모델의 이름을 정의합니다.
  • BitsAndBytesConfig() 메서드를 사용하여 bnb_config로 모델 가중치를 구성합니다.
  • from_pre-trained() 메서드로 모델을 로드하여 훈련합니다.
  • fine_tuning_data_file_path로 미세 조정 데이터셋을 로드합니다.
  • 결과 출력 디렉터리 경로를 정의하고 makedirs() 메서드로 생성합니다.

셀 실행이 완료되면 다음과 같은 결과를 확인할 수 있습니다:

The Llama 4 model correctly loaded

훌륭합니다! Llama 4 모델이 설정되어 노트북에 로드되었습니다.

4단계: 훈련 과정을 위한 파인 튜닝 데이터셋 준비

노트북의 네 번째 셀에 다음 코드를 작성하여 훈련 과정을 위한 파인 튜닝 데이터셋을 준비하세요:

from datasets import Dataset

# 파인 튜닝 데이터셋 열기
with open(fine_tuning_data_file_path, "r") as f:
  data_list = json.load(f)

# 데이터 항목 목록을 Hugging Face Dataset 객체로 변환
raw_fine_tuning_dataset = Dataset.from_list(data_list)
print(f"JSON 데이터를 Hugging Face Dataset으로 변환했습니다. 예제 수: {len(raw_fine_tuning_dataset)}")

def format_fine_tuning_entry(data_item):
    system_message = "당신은 전문 카피라이터입니다. 제공된 세부 정보를 바탕으로 간결하고 매력적인 제품 설명을 생성하세요."
    # 다음 줄을 파인 튜닝 파일에 맞게 조정하세요
    item_title = data_item.get("title")
    item_brand = data_item.get("brand")
    item_category = data_item.get("categories")
    item_name = data_item.get("name")
    item_features_list = data_item.get("features")
    item_features_str = ", ".join(item_features_list) if isinstance(item_features_list, list) else str(item_features_list)
    target_description = data_item.get("description")

    # 훈련 프롬프트
    user_prompt = (
        f"다음 항목에 대한 제품 설명을 생성하세요:n"
        f"제목: {item_title}n브랜드: {item_brand}n카테고리: {item_category}n"
        f"이름: {item_name}n특징: {item_features_str}n설명:"
    )
    # Llama 채팅 형식
    formatted_string = (
        f"<|start_header_id|>system<|end_header_id|>nn{system_message}<|eot_id|>"
        f"<|start_header_id|>user<|end_header_id|>nn{user_prompt}<|eot_id|>"
        f"<|start_header_id|>assistant<|end_header_id|>nn{target_description}<|eot_id|>"
    )
    return {"text": formatted_string}

# 원시 데이터셋의 각 항목에 포맷팅 함수를 적용하여 파인 튜닝을 위한 구조화
text_formatted_dataset = raw_fine_tuning_dataset.map(format_fine_tuning_entry)

# 토큰화기 설정
tokenizer = AutoTokenizer.from_pre-trained(base_model_name, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token

# 데이터셋 사전 토큰화
def tokenize_function_for_sft(examples):
    # 전체 채팅 형식 문자열을 포함하는 "text" 필드 토큰화
    tokenized_output = tokenizer(
        examples["text"],
        truncation=True,
        padding="max_length",
        max_length=max_seq_length_for_tokenization,
    )
    return tokenized_output

# 형식화된 데이터셋에 토큰화 함수 적용
tokenized_train_dataset = text_formatted_dataset.map(
    tokenize_function_for_sft,
    batched=True,
    remove_columns=["text"]
  )

이 노트북 셀은:

  • Dataset.from_list() 메서드를 사용하여 미세 조정 데이터셋을 열고 Hugging Face Dataset 객체로 변환합니다.
  • format_fine_tuning_entry() 함수를 정의합니다. 이 함수는 단일 데이터 항목(제품 세부 정보)을 받아 Llama와 같은 챗 모델의 명령어 미세 조정에 적합한 구조화된 텍스트 형식으로 변환하는 역할을 합니다. 이 함수는 사용자의 미세 조정 데이터셋 구조에 맞게 조정되어야 합니다.
  • 데이터셋을 토큰화하고 map() 메서드로 토큰화를 적용합니다. 언어 모델은 원시 텍스트를 이해하지 못하기 때문입니다. 이들은 토큰이라고 불리는 수치적 표현을 기반으로 작동합니다.

셀 실행 완료 시 예상 결과는 다음과 같습니다:

Data conversion process

“Num examples” 값은 사용자의 미세 조정 데이터셋에 따라 달라집니다.

대단합니다! 이제 파인튜닝 데이터셋이 파인튜닝 과정을 진행할 준비가 되었습니다.

단계 #5: 매개변수 효율적 미세 조정(PEFT) 환경 및 매개변수 구성

노트북의 새 셀에 PEFT 환경 및 매개변수 설정을 위한 다음 코드를 작성하세요:

from transformers import BitsAndBytesConfig
from peft import LoraConfig

# QLoRA 구성
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16, 
    bnb_4bit_use_double_quant=True,)


# LoRA 구성
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
)

이 코드는:

  • BitsAndBytesConfig() 메서드를 사용하여 양자화할 QLoRA 구성을 정의합니다. 이 구성은 사전 훈련된 언어 모델을 로드할 때 양자화 방식을 지정합니다. 양자화는 계산 및 메모리 비용을 줄이는 기술입니다.
  • LoraConfig() 메서드를 사용하여 매개변수 효율적인 파인 튜닝을 위한 모델 설정을 위한 LoRA 구성을 정의합니다.

아주 좋습니다! 효율적인 파인 튜닝을 위한 환경이 준비되었습니다.

6단계: 훈련 프로세스 초기화

새로운 셀에 다음 코드를 작성하여 훈련 프로세스를 초기화합니다:

from peft import get_peft_model, prepare_model_for_kbit_training
from transformers import TrainingArguments

# k-bit 훈련을 위한 모델 준비
model = prepare_model_for_kbit_training(
    model,
    gradient_checkpointing_kwargs={"use_reentrant": False}
)
# 모델에 PEFT(LoRA) 구성을 적용합니다.
model = get_peft_model(model, lora_config)
# 모델 구성에서 캐싱을 비활성화합니다.
model.config.use_cache = False
# 모델의 훈련 가능 매개변수 수를 출력합니다.
model.print_trainable_parameters()

# 훈련 인자 정의
training_args = TrainingArguments(
    output_dir=output_model_dir,
    num_train_epochs=3,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    logging_steps=25,
    save_steps=50,
    fp16=True,
    optim="paged_adamw_8bit",
    lr_scheduler_type="cosine",
    warmup_ratio=0.03,
    report_to="none",
    max_grad_norm=0.3,
    save_total_limit=2,)


# SFTTrainer 초기화
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_train_dataset,
    peft_config=lora_config,
)

이 셀의 코드:

아래는 예상 결과입니다:

Train dataset preparation

7단계: 모델 훈련

이제 train() 메서드를 사용하여 Llama 4 모델을 훈련할 준비가 완료되었습니다:

# 모델 훈련
trainer.train()

# 미세 조정된 모델 저장
trainer.save_model(final_model_adapter_path) # LoRA 어댑터 저장
tokenizer.save_pre-trained(final_model_adapter_path) # 어댑터와 함께 토큰화기 저장

결과는 다음과 같습니다:

Training the model with the fine-tuning data

AI의 확률적 특성으로 인해 다른 숫자가 나올 수 있음을 유의하십시오.

단계 #8: 추론을 위한 모델 준비

추론을 위해 모델을 준비하려면 새 셀에 다음 코드를 작성하세요:

# 양자화 적용 모델 로드 (추론용)
base_model_for_inference = AutoModelForCausalLM.from_pre-trained(
  base_model_name,
  quantization_config=bnb_config,  
  device_map="auto",              
  trust_remote_code=True
)
# 미세 조정된 LoRA 어댑터를 로드하고 모델에 연결
fine_tuned_model_for_testing = PeftModel.from_pre-trained(
    base_model_for_inference,
    final_model_adapter_path
)

# LoRA 어댑터를 기본 모델에 병합
fine_tuned_model_for_testing = fine_tuned_model_for_testing.merge_and_unload()

# 토큰화기 로드
fine_tuned_tokenizer_for_testing = AutoTokenizer.from_pre-trained(
    final_model_adapter_path,
    trust_remote_code=True)

# 추론을 위한 토큰화기 구성
fine_tuned_tokenizer_for_testing.pad_token = fine_tuned_tokenizer_for_testing.eos_token
fine_tuned_tokenizer_for_testing.padding_side = "left"
# 파인 튜닝된 모델을 평가 모드로 설정
fine_tuned_model_for_testing.eval()

이 셀의 코드:

  • 추론을 위해 from_pre-trained() 메서드로 모델을 로드합니다.
  • 추론을 위해 LoRA 어댑터를 로드하고 적용하며 기본 모델과 병합합니다.
  • 미세 조정된 토큰라이저를 로드하고 추론을 위해 구성합니다.
  • eval() 메서드로 모델을 평가 모드로 설정합니다. 이는 훈련 관련 동작을 비활성화하여 추론 중 일관되고 결정론적인 출력을 보장합니다.

자, 이제 시작합니다! 추론을 위한 모든 준비가 완료되었습니다.

9단계: 모델 추론

마지막 단계에서 추론을 수행합니다. 이전에 아마존에서 수집한 제품 데이터로 Llama 4를 훈련시켰습니다. 이제 사무용품과 유사한 항목의 이름과 특징을 포함한 데이터를 주어 모델이 해당 설명을 생성할 수 있는지 확인하고자 합니다.

다음 코드를 통해 추론 과정을 관리할 수 있습니다:

# 미세 조정된 모델 테스트용 합성 제품 데이터 항목 목록 정의
synthetic_test_items = [
  {
    "title": "Executive Ergonomic Office Chair", "brand": "ComfortLuxe", "category": "Office Chairs", "name": "ErgoPro-EL100",
    "features": ["하이백 디자인", "조절 가능한 요추 지지대", "통기성 메쉬 원단", "동기화된 틸트 메커니즘", "패딩 처리된 팔걸이", "헤비듀티 나일론 베이스"]
  },
  {
    "title": "조절 가능한 스탠딩 데스크 컨버터", "brand": "FlexiDesk", "category": "책상 및 워크스테이션", "name": "HeightRise-FD20",
    "features": ["넓은 이중층 작업대", "부드러운 가스 스프링 리프트", "조절 가능 높이 범위 6-17인치", "최대 35파운드 지지", "키보드 트레이 포함", "미끄럼 방지 고무 발"]
  },
  {
    "title": "무선 키보드 및 마우스 콤보", "brand": "TechGear", "category": "컴퓨터 주변기기", "name": "SilentType-KM850",
    "features": ["숫자 키패드 포함 풀사이즈 키보드", "저소음 키", "조절 가능한 DPI 인체공학적 마우스", "2.4GHz 무선 연결", "장시간 배터리 수명", "플러그 앤 플레이 USB 수신기"]
  },
  {
    "title": "서랍형 데스크탑 정리함", "brand": "NeatOffice", "category": "책상 액세서리", "name": "SpaceSaver-DO3",
    "features": ["다중 수납 공간 디자인", "두 개의 풀아웃 서랍", "내구성 있는 목재 구조", "컴팩트한 크기", "펜, 노트, 소형 용품 보관에 이상적"]
  },
  {
    "title": "USB 충전 포트 내장 LED 책상 램프", "brand": "BrightSpark", "category": "사무실 조명", "name": "LumiCharge-LS50",
    "features": ["조절 가능한 밝기 단계 (5단계)", "색온도 모드 (3종)", "유연한 구스넥 디자인", "내장 USB 충전 포트", "눈 보호, 깜빡임 없는 빛", "에너지 효율적인 LED"]
  },
]

# 추론을 위한 시스템 메시지 및 프롬프트 구조
system_message_inference = "당신은 전문 카피라이터입니다. 제공된 세부 정보를 바탕으로 간결하고 매력적인 제품 설명을 생성하세요."

print("n--- 합성 테스트 데이터를 사용한 미세 조정 모델로 설명 생성 중 ---")

# synthetic_test_items 리스트의 각 항목 반복
for item_data in synthetic_test_items: 
    # 합성 항목 구조에 기반한 사용자 프롬프트 부분 구성
    user_prompt_inference = (
        f"다음 사무용품에 대한 제품 설명 생성:n"
        f"제목: {item_data["title"]}n"
        f"브랜드: {item_data["brand"]}n"
        f"카테고리: {item_data["category"]}n"
        f"이름: {item_data["name"]}n"
        f"특징: {", ".join(item_data["features"])}n"
        f"설명:" # 모델은 이 뒤에 텍스트를 생성합니다.
    )

    full_prompt_for_inference = (
        f"<|start_header_id|>시스템<|end_header_id|>nn{system_message_inference}<|eot_id|>"
        f"<|start_header_id|>사용자<|end_header_id|>nn{user_prompt_inference}<|eot_id|>"
        f"<|start_header_id|>어시스턴트<|end_header_id|>nn"
    )

    print(f"n항목 {item_data["name"]}에 대한 프롬프트")

    # 미세 조정된 토큰화기를 사용하여 전체 프롬프트 문자열을 토큰화합니다.
    inputs = fine_tuned_tokenizer_for_testing(
        full_prompt_for_inference,
        return_tensors="pt",
        padding=False,
        truncation=True,
        max_length=max_seq_length_for_tokenization - 150
    ).to(fine_tuned_model_for_testing.device)

    # 추론 수행
    with torch.no_grad():
        outputs = fine_tuned_model_for_testing.generate(
            **inputs,
            max_new_tokens=150,
            num_return_sequences=1,
            do_sample=True,
            temperature=0.6,
            top_k=50,
            top_p=0.9,
            pad_token_id=fine_tuned_tokenizer_for_testing.eos_token_id,
            eos_token_id=[
                fine_tuned_tokenizer_for_testing.eos_token_id,
                fine_tuned_tokenizer_for_testing.convert_tokens_to_ids("<|eot_id|>")
            ]
        )

    # 생성된 토큰 ID를 사람이 읽을 수 있는 텍스트 문자열로 다시 디코딩
    generated_text_full = fine_tuned_tokenizer_for_testing.decode(outputs[0], skip_special_tokens=False)
    # Llama 채팅 형식에서 어시스턴트 응답 시작을 표시하는 마커 정의
    assistant_marker = "<|start_header_id|>assistant<|end_header_id|>nn"
    # 생성된 텍스트에서 어시스턴트 마커의 마지막 발생 위치 찾기
    assistant_response_start_index = generated_text_full.rfind(assistant_marker)

    # 전체 모델 출력에서 실제 생성된 설명 추출
    if assistant_response_start_index != -1:
        # 어시스턴트 마커가 발견되면 그 뒤에 오는 텍스트 추출
        generated_description = generated_text_full[assistant_response_start_index + len(assistant_marker):]
        # Llama용 턴 종료 토큰 정의
        eot_token = "<|eot_id|>"
        # 추출된 설명이 Llama 턴 종료 토큰으로 끝나는지 확인하고 제거
        if generated_description.endswith(eot_token):
            generated_description = generated_description[:-len(eot_token)]
        # 또한 토큰라이저의 표준 시퀀스 종료 토큰으로 끝나는지 확인하고 제거합니다.
        if generated_description.endswith(fine_tuned_tokenizer_for_testing.eos_token):
             generated_description = generated_description[:-len(fine_tuned_tokenizer_for_testing.eos_token)]
        # 정리된 설명에서 앞뒤 공백을 제거합니다
        generated_description = generated_description.strip()
    else:
        # 대체 처리: 어시스턴트 마커를 찾지 못하면, 생성된 부분이 원래 입력 프롬프트 이후의 모든 내용이라고 가정하여 추출을 시도합니다.
        input_prompt_decoded_len = len(fine_tuned_tokenizer_for_testing.decode(inputs["input_ids"][0], skip_special_tokens=False))
        # 입력 프롬프트 토큰을 디코딩하여 문자열 형태의 길이를 얻습니다.
        generated_description = generated_text_full[input_prompt_decoded_len:].strip()
        # 이 대체 추출 과정에서 Llama의 턴 종료 토큰이 남아 있으면 제거합니다.
        if generated_description.endswith("<|eot_id|>"):
            generated_description = generated_description[:-len("<|eot_id|>")]
        generated_description = generated_description.strip()

    # 추출 및 정리된 생성된 설명 출력
    print(f"생성됨 (미세 조정됨):n{generated_description}")
    # 항목 간 가독성 향상을 위한 구분선 출력
    print("-" * 50)

이 마지막 Jupyter Notebook 셀은 추론 과정을 관리합니다. 이 과정은 미세 조정 과정 중 훈련이 얼마나 잘 이루어졌는지 확인하는 데 유용합니다.

특히 위 코드는:

  • 테스트 데이터를 synthetic_test_items라는 리스트로 정의합니다. 이 리스트의 각 요소는 제품 정보를 나타내는 사전으로, 제목, 브랜드, 카테고리, 이름, 특징 목록 등의 세부 정보를 포함합니다. 이 데이터는 모델의 입력으로 사용되며 그 구조는 튜닝 데이터셋의 구조와 일치해야 합니다.
  • system_message_inference를 통해 추론 프롬프트 구조를 설정합니다. 이는 훈련 과정에서 사용된 프롬프트와 반드시 일치해야 합니다.
  • for item_data in synthetic_test_items 루프는 각 item_data에 대해 사용자 프롬프트를 생성합니다. 각 item_data의 구조는 훈련 과정에서 사용된 것과 일치해야 합니다.
  • 토큰화하고 모델이 출력 텍스트를 생성하는 방식을 제어합니다. 실제 추론은 with 문 아래에서 수행됩니다. 특히, 핵심 추론 단계인 generate() 메서드 덕분에 가능합니다.
  • 토큰화기를 사용하여 모델의 원시 출력(토큰 ID 시퀀스)을 사람이 읽을 수 있는 문자열(generated_text_full)로 다시 디코딩합니다.
  • if-else 블록을 사용하여 언어 모델의 원시 출력을 정리하여 어시스턴트가 생성한 제품 설명만 추출합니다. 원시 출력(generated_text_full)에는 일반적으로 입력 프롬프트 전체와 모델의 응답이 Llama의 특수 채팅 토큰으로 포맷된 형태로 포함됩니다.
  • 결과를 출력합니다.

결과는 다음과 같을 것으로 예상됩니다:

--- 합성 테스트 데이터를 활용한 미세 조정 모델로 설명 생성 ---

아이템 프롬프트: ErgoPro-EL100
생성 결과 (미세 조정):
**ErgoPro-EL100 소개: 궁극의 경영진용 인체공학적 사무용 의자**

ComfortLuxe ErgoPro-EL100으로 최상의 편안함과 지지력을 경험하세요. 업무 환경을 한 단계 업그레이드하도록 설계된 이 프리미엄 사무용 의자는 상체를 감싸는 하이백 디자인으로 탁월한 요추 지지력과 건강한 자세를 제공합니다.

통기성 메쉬 소재는 시원하고 쾌적한 착석감을 보장하며, 동기화 틸트 메커니즘으로 선호하는 작업 자세로 원활하게 조절할 수 있습니다. 충전된 팔걸이는 추가적인 지지력과 편안함을 제공하여 어깨와 손목의 피로를 줄여줍니다.

오래도록 견딜 수 있도록 제작된 ErgoPro-EL100은 안정성과 내구성을 보장하는 고강도 나일론 베이스가 특징입니다. 장시간 작업하거나 단순히
--------------------------------------------------

PROMPT for item: HeightRise-FD20
GENERATED (Fine-tuned):
**플렉시데스크의 HeightRise-FD20 조절식 스탠딩 데스크 컨버터로 생산성을 높이세요**

플렉시데스크의 HeightRise-FD20, 궁극의 조절식 스탠딩 데스크 컨버터로 업무를 새로운 차원으로 끌어올리세요. 작업 공간에 혁신을 가져다주는 이 혁신적인 컨버터는 어떤 책상도 편안하고 인체공학적인 스탠딩 작업 공간으로 변신시킵니다.

**스탠딩의 이점을 경험하세요**

HeightRise-FD20은 노트북, 모니터 및 기타 필수 작업 도구를 놓기에 완벽한 넓은 이중 층 표면을 자랑합니다. 부드러운 가스 스프링 리프트는 6인치에서 17인치까지 손쉬운 높이 조절을 가능하게 하여 필요에 맞는 편안한 스탠딩 자세를 보장합니다.

**내구성과 신뢰성**

견고한 구조와 미끄럼 방지 고무 받침으로
--------------------------------------------------

자, 이제 Bright Data Scraper API를 사용하여 새로 수집한 데이터셋으로 Llama 4를 미세 조정했습니다.

결론

이 글에서는 Bright Data Scraper API를 활용해 아마존에서 스크래핑한 데이터셋으로 Llama 4를 미세 조정하는 방법을 배웠습니다. 다음으로 구성된 전체 과정을 살펴보았습니다:

  • 웹에서 데이터 수집
  • 토큰이 포함된 Hugging Face 계정 설정.
  • 필요한 클라우드 인프라 설정.
  • Llama 4 훈련 및 테스트(추론).

미세 조정 과정의 핵심은 고품질 데이터셋 확보에 있습니다. 다행히 Bright Data는 데이터셋 수집 또는 생성을 위한 다양한 AI 지원 서비스를 제공합니다:

  • 스크래핑 브라우저: 내장된 잠금 해제 기능을 갖춘 Playwright, Selenium, Puppeter 호환 브라우저.
  • 웹 스크레이퍼 API: 100개 이상의 주요 도메인에서 구조화된 데이터를 추출하기 위한 사전 구성된 API.
  • 웹 언락커: 봇 방지 기능이 있는 사이트의 사이트 언락을 처리하는 올인원 API.
  • SERP API: 검색 엔진 결과를 잠금 해제하고 완전한 SERP 데이터를 추출하는 전문 API.
  • 파운데이션 모델: 사전 훈련, 평가 및 미세 조정을 위한 규정 준수 웹 규모 데이터셋 접근.
  • 데이터 공급자: 신뢰할 수 있는 공급자와 연결하여 대규모의 고품질 AI 준비 데이터 세트를 확보하세요.
  • 데이터 패키지: 선별되고 즉시 사용 가능한 데이터 세트를 구조화, 보강 및 주석 처리된 형태로 제공합니다.

Bright Data 계정을 무료로 생성하여 AI 활용 가능한 데이터 인프라를 테스트해 보세요!