Home > EulerWeave > Tutorials > 튜토리얼 3: HuggingFace 데이터셋 → SFT 훈련 데이터

튜토리얼 3: HuggingFace 데이터셋 → SFT 훈련 데이터

이 튜토리얼에서는 HuggingFace에서 공개 데이터셋을 다운로드하고, eulerweave 파이프라인으로 처리하여 LLM 미세 조정용 훈련 데이터를 만드는 전체 과정을 안내합니다.

이 튜토리얼에서 배우는 내용:

사전 요구 사항: eulerweave가 설치되어 있어야 합니다. 튜토리얼 0: 설치를 참고하세요.


시나리오 A: 구조화된 SFT 데이터셋 (Alpaca 스타일)

HuggingFace에는 이미 instruction-output 쌍이 있는 SFT 데이터셋이 많습니다. 이런 데이터는 build_sft_messages로 바로 처리할 수 있습니다.

1단계: 데이터 다운로드

pip install datasets
# download_alpaca.py
from datasets import load_dataset
import json

# tatsu-lab/alpaca 데이터셋 다운로드
ds = load_dataset("tatsu-lab/alpaca", split="train")

# 처음 1000개만 JSONL로 저장
with open("data/alpaca_1k.jsonl", "w") as f:
    for row in ds.select(range(1000)):
        json.dump({
            "instruction": row["instruction"],
            "input": row["input"],
            "output": row["output"],
        }, f, ensure_ascii=False)
        f.write("\n")

print(f"Saved {min(1000, len(ds))} records to data/alpaca_1k.jsonl")
mkdir -p data
python download_alpaca.py
# Saved 1000 records to data/alpaca_1k.jsonl

2단계: 데이터 확인

head -1 data/alpaca_1k.jsonl | python -m json.tool
{
  "instruction": "Give three tips for staying healthy.",
  "input": "",
  "output": "1. Eat a balanced diet... 2. Exercise regularly... 3. Get enough sleep..."
}

이 데이터는 이미 instruction-output 구조가 있으므로 build_sft_messages를 사용합니다.

3단계: 매니페스트 작성

manifest_alpaca.yaml:

version: 1
track: sft

inputs:
  - type: jsonl
    uri: data/alpaca_1k.jsonl

pipeline:
  - id: norm1
    type: normalize_text
    slot: normalize
    input_type: TextDocument
    output_type: TextDocument

  - id: filter1
    type: heuristic_filter
    slot: filter
    input_type: TextDocument
    output_type: TextDocument
    params:
      min_length: 20
      max_length: 10000

  - id: sft1
    type: build_sft_messages
    slot: build_task
    input_type: TextDocument
    output_type: SFTMessages

  - id: exp1
    type: export_jsonl
    slot: export
    input_type: SFTMessages
    output_type: ExportedDataset

exports:
  - type: jsonl
    path: out/alpaca_sft.jsonl

profile:
  cpu_only: true
  allow_external_llm: false

핵심 포인트:

4단계: 검증 및 실행

# 검증
eulerweave validate manifest_alpaca.yaml

# 실행
eulerweave run manifest_alpaca.yaml \
  --input data/alpaca_1k.jsonl \
  --artifacts ./artifacts

5단계: 결과 확인

wc -l out/alpaca_sft.jsonl
# 998 out/alpaca_sft.jsonl  (2개 필터링됨)

head -1 out/alpaca_sft.jsonl | python -m json.tool
{
  "instruction": "Give three tips for staying healthy.",
  "input": "",
  "output": "1. Eat a balanced diet... 2. Exercise regularly... 3. Get enough sleep..."
}

시나리오 B: 원시 텍스트 데이터셋 → QnA 생성

HuggingFace에는 원시 텍스트만 있는 데이터셋도 많습니다 (위키백과, 뉴스, 논문 등). 이런 데이터는 build_langextract_qna로 QnA 쌍을 자동 생성합니다.

1단계: 위키백과 데이터 다운로드

# download_wiki.py
from datasets import load_dataset
import json

# 한국어 위키백과 (또는 원하는 언어)
ds = load_dataset("wikipedia", "20220301.ko", split="train", streaming=True)

# 처음 500개 문서를 JSONL로 저장
with open("data/wiki_ko_500.jsonl", "w") as f:
    for i, row in enumerate(ds):
        if i >= 500:
            break
        if len(row["text"]) < 200:
            continue  # 너무 짧은 문서 건너뛰기
        json.dump({
            "text": row["text"][:5000],  # 5000자로 제한
            "title": row["title"],
        }, f, ensure_ascii=False)
        f.write("\n")

print("Saved to data/wiki_ko_500.jsonl")
python download_wiki.py

2단계: 데이터 확인

head -1 data/wiki_ko_500.jsonl | python -m json.tool
{
  "text": "지미 카터(James Earl Carter Jr., 1924년 10월 1일 ~ )는 미국의 제39대 대통령이다...",
  "title": "지미 카터"
}

원시 텍스트만 있으므로 LLM으로 QnA를 생성해야 합니다.

3단계: FakeProvider로 파이프라인 테스트

먼저 LLM 없이 파이프라인 구조를 테스트합니다.

manifest_wiki_test.yaml:

version: 1
track: sft

inputs:
  - type: jsonl
    uri: data/wiki_ko_500.jsonl

pipeline:
  - id: norm1
    type: normalize_text
    slot: normalize
    input_type: TextDocument
    output_type: TextDocument

  - id: filter1
    type: heuristic_filter
    slot: filter
    input_type: TextDocument
    output_type: TextDocument
    params:
      min_length: 200

  - id: dedup1
    type: dedup_exact
    slot: dedup
    input_type: TextDocument
    output_type: TextDocument

  - id: qna1
    type: build_langextract_qna
    slot: build_task
    input_type: TextDocument
    output_type: SFTQnA

  - id: exp1
    type: export_jsonl
    slot: export
    input_type: SFTQnA
    output_type: ExportedDataset

exports:
  - type: jsonl
    path: out/wiki_qna.jsonl

profile:
  cpu_only: true
  allow_external_llm: false
eulerweave validate manifest_wiki_test.yaml
eulerweave run manifest_wiki_test.yaml \
  --input data/wiki_ko_500.jsonl \
  --artifacts ./artifacts

FakeProvider 출력 예시:

{
  "messages": [
    {"role": "user", "content": "What is the main topic of: '지미 카터는 미국의...'?"},
    {"role": "assistant", "content": "The text discusses: 지미 카터는 미국의... [fake-d4e5f6]"}
  ]
}

4단계: Ollama로 실제 QnA 생성

파이프라인이 올바르게 동작하면, Ollama를 사용하여 실제 QnA를 생성합니다.

manifest_wiki_ollama.yaml:

version: 1
track: sft

inputs:
  - type: jsonl
    uri: data/wiki_ko_500.jsonl

pipeline:
  - id: norm1
    type: normalize_text
    slot: normalize
    input_type: TextDocument
    output_type: TextDocument

  - id: filter1
    type: heuristic_filter
    slot: filter
    input_type: TextDocument
    output_type: TextDocument
    params:
      min_length: 200
      max_length: 50000

  - id: dedup1
    type: dedup_exact
    slot: dedup
    input_type: TextDocument
    output_type: TextDocument

  - id: m1
    type: metrics_text_basic
    slot: metrics
    input_type: TextDocument
    output_type: TextDocument

  - id: qna1
    type: build_langextract_qna
    slot: build_task
    input_type: TextDocument
    output_type: SFTQnA
    params:
      model: "gpt-oss:20b"
      base_url: "http://localhost:11434"

  - id: exp1
    type: export_jsonl
    slot: export
    input_type: SFTQnA
    output_type: ExportedDataset

exports:
  - type: jsonl
    path: out/wiki_qna.jsonl

profile:
  cpu_only: false
  allow_external_llm: true
# Ollama 시작
ollama serve
ollama pull gpt-oss:20b

# 실행
eulerweave run manifest_wiki_ollama.yaml \
  --input data/wiki_ko_500.jsonl \
  --artifacts ./artifacts

실제 QnA 출력 예시:

{
  "messages": [
    {"role": "user", "content": "지미 카터 대통령은 몇 대 대통령인가요?"},
    {"role": "assistant", "content": "지미 카터는 미국의 제39대 대통령입니다. 1977년부터 1981년까지 재임했습니다."}
  ]
}

시나리오 C: CSV 데이터셋

HuggingFace의 일부 데이터셋은 CSV로도 다운로드할 수 있습니다.

CSV로 다운로드

# download_csv.py
from datasets import load_dataset

ds = load_dataset("tatsu-lab/alpaca", split="train")
ds.select(range(1000)).to_csv("data/alpaca_1k.csv")
print("Saved to data/alpaca_1k.csv")

CSV 매니페스트

version: 1
track: sft

inputs:
  - type: csv
    uri: data/alpaca_1k.csv
    options:
      text_column: instruction    # 텍스트로 사용할 컬럼 지정
      delimiter: ","

pipeline:
  - id: norm1
    type: normalize_text
    slot: normalize
    input_type: TextDocument
    output_type: TextDocument

  - id: sft1
    type: build_sft_messages
    slot: build_task
    input_type: TextDocument
    output_type: SFTMessages

  - id: exp1
    type: export_jsonl
    slot: export
    input_type: SFTMessages
    output_type: ExportedDataset

exports:
  - type: jsonl
    path: out/alpaca_csv_sft.jsonl

profile:
  cpu_only: true
  allow_external_llm: false

실전 예제: 코드 데이터셋 → 코딩 QnA

코드 관련 데이터셋에서 코딩 QnA를 생성하는 예제입니다.

데이터 다운로드

# download_code.py
from datasets import load_dataset
import json

ds = load_dataset("sahil2801/CodeAlpaca-20k", split="train")

with open("data/code_alpaca.jsonl", "w") as f:
    for row in ds.select(range(500)):
        json.dump({
            "instruction": row["instruction"],
            "input": row.get("input", ""),
            "output": row["output"],
        }, f, ensure_ascii=False)
        f.write("\n")

print("Saved 500 records to data/code_alpaca.jsonl")

매니페스트

version: 1
track: sft

inputs:
  - type: jsonl
    uri: data/code_alpaca.jsonl

pipeline:
  - id: norm1
    type: normalize_text
    slot: normalize
    input_type: TextDocument
    output_type: TextDocument

  - id: filter1
    type: heuristic_filter
    slot: filter
    input_type: TextDocument
    output_type: TextDocument
    params:
      min_length: 30

  - id: m1
    type: metrics_text_basic
    slot: metrics
    input_type: TextDocument
    output_type: TextDocument

  - id: sft1
    type: build_sft_messages
    slot: build_task
    input_type: TextDocument
    output_type: SFTMessages

  - id: exp1
    type: export_jsonl
    slot: export
    input_type: SFTMessages
    output_type: ExportedDataset

exports:
  - type: jsonl
    path: out/code_sft.jsonl

profile:
  cpu_only: true
  allow_external_llm: false
python download_code.py
eulerweave validate manifest_code.yaml
eulerweave run manifest_code.yaml --input data/code_alpaca.jsonl --artifacts ./artifacts

# 결과 확인
head -1 out/code_sft.jsonl | python -m json.tool

build_sft_messages vs build_langextract_qna

어떤 블록을 사용할지 결정하는 기준:

기준 build_sft_messages build_langextract_qna
소스 데이터 instruction-output 쌍이 이미 존재 원시 텍스트만 존재
LLM 필요 아니요 예 (Ollama 또는 FakeProvider)
속도 빠름 (필드 매핑만) 느림 (LLM 호출)
품질 원본 데이터에 의존 LLM 능력에 의존
적합한 데이터 Alpaca, ShareGPT, Dolly 등 위키백과, 논문, 매뉴얼, 뉴스
프로필 설정 allow_external_llm: false 가능 allow_external_llm: true 필요

자세한 비교는 튜토리얼 4: SFT 트랙 심화를 참고하세요.


전체 과정 요약

# 1. HuggingFace datasets 설치
pip install datasets

# 2. 데이터 다운로드 (Python 스크립트)
python download_alpaca.py   # 또는 download_wiki.py

# 3. 매니페스트 작성

# 4. 검증
eulerweave validate manifest.yaml

# 5. 실행
eulerweave run manifest.yaml --input data/... --artifacts ./artifacts

# 6. 결과 확인
wc -l out/result.jsonl
head -3 out/result.jsonl | python -m json.tool

다음 단계

← Prev Back to List Next →