#!/usr/bin/env bash # data/tokenize_cc100.sh # CC-100 Korean 토크나이징 및 기존 korean_train.bin 과의 병합 스크립트 # # 버그 수정 내역 (build_korean_dataset.sh 대비): # - build_korean_dataset.sh Step 6에서 cc100_ko 디렉토리가 비어있을 경우 # prepare.py 의 find_input_files()가 FileNotFoundError 를 발생시키는 버그가 있었음. # 본 스크립트는 사전에 cc100_ko/*.txt 파일 존재 여부를 확인하고 # 없을 경우 명확한 안내 메시지와 함께 종료한다. # # 전제 조건: # 1. tokenizer/korean_sp/tokenizer.json — SP 토크나이저가 이미 학습/변환 완료 # 2. data/raw/cc100_ko/*.txt — CC-100 다운로드 완료 # (없으면: bash data/download_cc100.sh 먼저 실행) # 3. data/korean_train.bin — 기존 병합 학습 데이터 (병합 대상) # (없어도 토크나이징은 진행되며, 병합 단계만 건너뜀) # # 실행 방법 (프로젝트 루트에서): # bash data/tokenize_cc100.sh # # 출력: # data/korean_cc100_train.bin — CC-100 학습 토큰 # data/korean_cc100_val.bin — CC-100 검증 토큰 # data/korean_train_combined.bin — 기존 korean_train.bin + CC-100 병합본 # (korean_train.bin 이 존재하는 경우에만 생성) set -euo pipefail # ─── 경로 설정 ──────────────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" cd "$PROJECT_ROOT" RAW_DIR="data/raw" BIN_DIR="data" TOKENIZER_JSON="tokenizer/korean_sp/tokenizer.json" CC100_DIR="$RAW_DIR/cc100_ko" # ─── 출력 파일 경로 ─────────────────────────────────────────────────────────── CC100_TRAIN_BIN="$BIN_DIR/korean_cc100_train.bin" CC100_VAL_BIN="$BIN_DIR/korean_cc100_val.bin" EXISTING_TRAIN_BIN="$BIN_DIR/korean_train.bin" COMBINED_TRAIN_BIN="$BIN_DIR/korean_train_combined.bin" # ─── 사전 검사 ──────────────────────────────────────────────────────────────── echo "=== CC-100 토크나이징 및 병합 ===" echo "프로젝트 루트: $PROJECT_ROOT" echo "" # 검사 1: 토크나이저 파일 존재 여부 if [ ! -f "$TOKENIZER_JSON" ]; then echo "ERROR: 토크나이저 파일을 찾을 수 없습니다: $TOKENIZER_JSON" >&2 echo "" echo "해결 방법: 토크나이저를 먼저 학습하고 변환하세요." echo " python tokenizer/train_sp_tokenizer.py --input <텍스트파일> --output_dir tokenizer/korean_sp" echo " python tokenizer/convert_sp_to_hf.py --model tokenizer/korean_sp/tokenizer.model --output $TOKENIZER_JSON" exit 1 fi echo "[OK] 토크나이저: $TOKENIZER_JSON" # 검사 2: CC-100 .txt 파일 존재 여부 CC100_FILE_COUNT=$(find "$CC100_DIR" -maxdepth 1 -name "*.txt" 2>/dev/null | wc -l) if [ "$CC100_FILE_COUNT" -eq 0 ]; then echo "ERROR: CC-100 텍스트 파일이 없습니다: $CC100_DIR/*.txt" >&2 echo "" echo "해결 방법: CC-100 먼저 다운로드하세요." echo " bash data/download_cc100.sh" echo "" echo "주의: build_korean_dataset.sh 의 --text_col text 버그로 다운로드했다면" echo " 해당 파일들은 빈 내용이므로 삭제 후 재다운로드가 필요합니다." echo " rm -f \"$CC100_DIR\"/*.txt && bash data/download_cc100.sh" exit 1 fi echo "[OK] CC-100 샤드 파일: ${CC100_FILE_COUNT}개 ($CC100_DIR)" # 검사 3: 기존 korean_train.bin 존재 여부 확인 (경고만, 중단하지 않음) if [ -f "$EXISTING_TRAIN_BIN" ]; then EXISTING_SIZE=$(du -sh "$EXISTING_TRAIN_BIN" 2>/dev/null | cut -f1) echo "[OK] 기존 학습 데이터: $EXISTING_TRAIN_BIN ($EXISTING_SIZE) — 병합 예정" else echo "[WARN] 기존 학습 데이터 없음: $EXISTING_TRAIN_BIN" echo " 토크나이징만 진행하고, 병합 단계는 건너뜁니다." fi echo "" # ─── Step 1: CC-100 토크나이징 ──────────────────────────────────────────────── # prepare.py 는 --output 경로의 'train' 을 'val' 로 치환하여 val .bin 을 자동 생성함. # --val_split 0.002 → 0.2% 를 검증 셋으로 분리 (1,000만 행 기준 약 3M 토큰) echo "[1/2] CC-100 토크나이징..." echo " 입력: $CC100_DIR/*.txt (${CC100_FILE_COUNT}개 파일)" echo " 출력: $CC100_TRAIN_BIN" echo " 출력: $CC100_VAL_BIN (val_split=0.2%)" echo "" python data/prepare.py \ --input "$CC100_DIR/*.txt" \ --output "$CC100_TRAIN_BIN" \ --tokenizer "$TOKENIZER_JSON" \ --val_split 0.002 \ --seed 42 echo "" echo "[완료] 토크나이징 결과:" if [ -f "$CC100_TRAIN_BIN" ]; then echo " $CC100_TRAIN_BIN ($(du -sh "$CC100_TRAIN_BIN" | cut -f1))" fi if [ -f "$CC100_VAL_BIN" ]; then echo " $CC100_VAL_BIN ($(du -sh "$CC100_VAL_BIN" | cut -f1))" fi echo "" # ─── Step 2: 기존 korean_train.bin 과 병합 ──────────────────────────────────── # 병합 결과는 korean_train_combined.bin 으로 저장. # 기존 korean_train.bin 은 덮어쓰지 않으므로 안전하게 검토 후 교체 가능. if [ -f "$EXISTING_TRAIN_BIN" ] && [ -f "$CC100_TRAIN_BIN" ]; then echo "[2/2] 기존 학습 데이터와 병합..." echo " 입력1: $EXISTING_TRAIN_BIN" echo " 입력2: $CC100_TRAIN_BIN" echo " 출력: $COMBINED_TRAIN_BIN" echo "" python data/merge_bins.py \ "$EXISTING_TRAIN_BIN" \ "$CC100_TRAIN_BIN" \ "$COMBINED_TRAIN_BIN" echo "" echo "[완료] 병합 결과:" echo " $COMBINED_TRAIN_BIN ($(du -sh "$COMBINED_TRAIN_BIN" | cut -f1))" echo "" echo "병합 파일을 기존 학습 데이터로 교체하려면:" echo " mv \"$EXISTING_TRAIN_BIN\" \"${EXISTING_TRAIN_BIN%.bin}_backup.bin\"" echo " mv \"$COMBINED_TRAIN_BIN\" \"$EXISTING_TRAIN_BIN\"" else echo "[2/2] 병합 건너뜀 — 기존 korean_train.bin 없음." echo " CC-100 학습 데이터만 단독으로 생성되었습니다: $CC100_TRAIN_BIN" fi # ─── 최종 요약 ──────────────────────────────────────────────────────────────── echo "" echo "=== 완료 ===" echo "" echo "생성된 파일:" for f in "$CC100_TRAIN_BIN" "$CC100_VAL_BIN" "$COMBINED_TRAIN_BIN"; do if [ -f "$f" ]; then TOKEN_COUNT=$(python3 -c " import numpy as np, sys d = np.memmap('$f', dtype='uint16', mode='r') print(f'{len(d):,}') " 2>/dev/null || echo "계산 불가") echo " $f → ${TOKEN_COUNT} 토큰 ($(du -sh "$f" | cut -f1))" fi done echo "" echo "학습 재시작 시 combined 파일을 configs/small_fp8_run1.yaml 의" echo "data_path 에 지정하거나, 기존 korean_train.bin 을 교체하세요."