> EulerForge > CLI 레퍼런스

EulerForge CLI 레퍼런스

GitHub 저장소: https://github.com/eulerwa/eulerforge

English version: cli_en.md

글로벌 옵션

--lang LANG — 출력 언어 설정

모든 서브커맨드에 --lang 지정하면 CLI 출력 언어를 변경합니다.

# 영어로 출력
eulerforge --lang en train --preset configs/presets/qwen3.5_0.8b_dense_lora_sft.yml

# ��본어로 출력
eulerforge --lang ja bench --preset configs/bench/sft_target_only.yml
언어 코드 언어
ko 한국어 (기본값)
en English
zh 中文
ja 日本語
es Español

환경변수 EULERFORGE_LANG으로도 설정 가능합니다. --lang이 환경변수보다 우선합니다.

export EULERFORGE_LANG=en
eulerforge train --preset ...    # 영어로 출력

명령어

eulerforge train

메인 훈련 파이프라인.

eulerforge train [OPTIONS]
옵션 설명
--preset PATH YAML 프리셋 설정 파일
--set KEY=VALUE 설정 값 오버라이드 (반복 가능)
--output-dir DIR 체크포인트 출력 디렉토리
--run-name NAME 선택적 실행 이름 접미사
--print-config 해석된 설정 JSON 출력
--validate-only 설정 검증만 수행, 훈련하지 않음
--preflight 모델 로드, 인젝션 적용, 페이즈 검증 — 훈련 없이
--metrics-level LEVEL 메트릭 수준: minimal (기본) 또는 advanced (+ MoE 라우팅 통계)
--debug 상세 디버그 로깅 활성화
--debug-every N N 스텝마다 디버그 로그 출력 (기본값: 50)
--debug-max-modules N 디버그 섹션당 최대 모듈 수 (기본값: 50)
--debug-topk-grad N 출력할 Top-K 그래디언트 노름 수 (기본값: 20)
--debug-attn 어텐션 프로젝션 요약 출력
--debug-trainable-names 학습 가능 파라미터 이름 덤프

파이프라인 연속 훈련 (체크포인트 자동 탐지)

model_name에 이전 EulerForge 훈련의 체크포인트 경로를 지정하면, 자동으로 base 모델을 탐지하여 올바르게 로드합니다.

# SFT → DPO 파이프라인 예시
eulerforge train --preset configs/presets/qwen3.5_0.8b_dense_lora_sft.yml \
    --output-dir outputs/sft

# SFT 체크포인트를 model_name으로 지정 → base 모델 자동 탐지
eulerforge train --preset configs/presets/qwen3.5_0.8b_dense_lora_dpo.yml \
    --set model_name=outputs/sft/final \
    --output-dir outputs/dpo

동작 원리: 1. model_name 디렉토리에 lora_info.json이 있으면 EulerForge LoRA 체크포인트로 인식 2. 부모 디렉토리의 resolved_config.json에서 원본 base 모델 이름을 추출 3. 이전 체크포인트의 injection 설정(lora_r, lora_alpha, target_keywords, start_layer 등)으로 현재 config를 자동 override — SFT(lora_r=48)→DPO(lora_r=24) 등 LoRA 구조 불일치 방지 4. Base 모델을 로드한 후 LoRA injection 적용 (checkpoint 기준 파라미터) 5. 이전 체크포인트의 LoRA 어댑터 가중치를 복원

주의: resolved_config.json이 없으면 자동 탐지가 작동하지 않습니다. EulerForge train 명령으로 생성된 체크포인트만 지원됩니다. DPO 단계에서 LoRA 구조를 다르게 하고 싶다면, 파이프라인이 아닌 별도 훈련으로 진행해야 합니다.

환경 변수

환경 변수 설명
EULERFORGE_MOE_PERF=1 MoEFFN 모듈별 forward 시간/토큰 분포 프로파일링 활성화. [MoEPerf] 로그 출력
EULERFORGE_MOE_DTYPE_DEBUG=1 MoEFFN merge 지점의 dtype 흐름 디버그 로그 활성화. [MoEDType] 로그 출력 (hidden/router/weights/expert_out/buffer dtype)
EULERFORGE_TRAIN_DEBUG=1 훈련 루프 상세 디버그: per-group LR, grad norm 평균, param dtype 분포, phase 전환 시 dequantize 통계 (mean/std/min/max). [TrainDebug]/[DequantDebug] 로그 출력

eulerforge convert

임의 JSONL을 EulerForge 표준 raw JSONL로 변환합니다. 기본 철학은 --map 기반 매핑이며, recipe는 편의 기능입니다.

세 가지 모드: - Map 모드 (기본): --map OUT_KEY=EXPR (반복 가능) — 범용 필드 매핑 - Recipe 모드: --recipe <이름> — 내장 레시피로 일반적인 데이터 구조 변환 - Validate 모드: --validate — 변환 없이 입력 파일 스키마 검증만 수행

# 필드 확인 (입력 파일 구조 탐색)
eulerforge convert --task sft --input data/sft_10k.jsonl --print-sample-flat

# Map 모드 (flat 필드)
eulerforge convert --task sft --input data/custom.jsonl --output data/out.jsonl \
    --map prompt=instruction --map response=output

# Map 모드 (중첩 필드 — dot-path 자동 flatten)
eulerforge convert --task prompted_preference --input data/dpo_10k.jsonl --output data/dpo_10k_raw.jsonl \
    --map prompt=instruction.value --map chosen=chosen.value --map rejected=rejected.value

# Recipe 모드 (messages 배열)
eulerforge convert --task sft --input data/sft_10k.jsonl --output data/sft_10k_raw.jsonl \
    --recipe sft_messages --messages-expr json_record.messages

# Validate 모드 (변환 없이 스키마 검증)
eulerforge convert --task sft --input data/sft_10k_raw.jsonl --validate
옵션 설명
--task 타겟 태스크: sft, preference, prompted_preference
--input 입력 JSONL 파일 경로
--output 출력 표준 raw JSONL 경로 (--validate / --print-sample-flat 불필요)
--map OUT_KEY=EXPR 출력 키 → 필드 표현식 매핑 (반복 가능). 예: --map prompt=instruction
--flatten dot\|none flatten 모드: dot(기본) 중첩 dict를 dot-key로 평탄화; none dot-path 직접 탐색
--join-sep SEP list[str] 값 결합 구분자 (기본값: 줄바꿈)
--strict 해석된 값이 None/빈 문자열/빈 리스트이면 에러
--recipe 내장 레시피 이름
--messages-expr EXPR messages 배열 dot-path (--recipe sft_messages 필수)
--num-proc 병렬 워커 수 (기본값: 1)
--overwrite 출력 파일 존재 시 덮어쓰기
--max-rows 최대 변환 행 수 (샘플링)
--validate Validate-only 모드: 입력 스키마 검증, 변환 없음
--print-sample-flat 첫 1-2행을 flatten한 키 목록 출력 후 종료 (필드 탐색용)

내장 레시피

레시피 task 입력 구조 출력
sft_messages sft 임의 dot-path → messages 배열 (--messages-expr 필수) {prompt, response}
sft_instruction_output sft {instruction, output} {prompt, response}
dpo_nested_value prompted_preference {instruction.value, chosen.value, rejected.value} {prompt, chosen, rejected}
sft_messages_v1 sft {json_record.messages: [{role,content}]} {prompt, response}
dpo_nested_v1 prompted_preference {instruction.value, chosen.value, rejected.value} {prompt, chosen, rejected}
passthrough_prompted_preference_v1 prompted_preference {prompt, chosen, rejected} 동일 (extra 키 제거)
passthrough_sft_prompt_response_v1 sft {prompt, response} 동일 (extra 키 제거)
passthrough_preference_v1 preference {chosen, rejected} 동일 (extra 키 제거)

상세: tutorials/00_data_preprocessing.md

eulerforge preprocess

Raw JSONL을 토큰화된 processed JSONL로 변환합니다.

eulerforge preprocess --task TASK --input RAW.jsonl --output PROCESSED.jsonl --model-name MODEL
옵션 설명
--task 태스크 타입: sft, preference, prompted_preference
--input 입력 raw JSONL 파일 경로
--output 출력 processed JSONL 파일 경로
--model-name HuggingFace 모델/토크나이저 이름
--max-length 최대 시퀀스 길이 (기본값: 512)
--num-proc 병렬 워커 수 (기본값: CPU 코어 50%)
--text-col SFT text 컬럼명 (기본값: text)
--prompt-col prompt 컬럼명 (기본값: prompt)
--response-col response 컬럼명 (기본값: response)
--chosen-col chosen 컬럼명 (기본값: chosen)
--rejected-col rejected 컬럼명 (기본값: rejected)

상세: tutorials/00_data_preprocessing.md

eulerforge bench

추론 벤치마크. YAML spec으로 target/baseline/judge 모델을 설정하고, 벤치마크 데이터에서 샘플을 추출하여 추론 결과를 비교한다. target은 API 모델(Ollama/OpenAI/Gemini) 또는 학습된 로컬 HF 체크포인트를 지원한다.

eulerforge bench [OPTIONS]
옵션 설명
--preset PATH Bench YAML spec 파일 경로 (필수)
--set KEY=VALUE 설정 값 오버라이드 (반복 가능)
--output-dir DIR 결과 출력 디렉토리
--validate-only 설정 검증만 수행
--dry-run 데이터 샘플만 추출 (모델 호출 없음)
--target-output-dir PATH target 로컬 모델: 학습 출력 루트 디렉토리
--checkpoint TYPE 체크포인트 유형: final(기본) | latest | best
--target-model-dir PATH target 로컬 모델: HF save_pretrained 디렉토리 직접 지정
--target-device DEVICE target 로컬 모델 device 오버라이드 (예: cuda:0, cuda:1, cpu)

순차 모델 로딩 (OOM 방지)

모델을 1개씩 로드하여 전체 데이터를 처리한 뒤 언로드합니다. 동시에 2개 이상 모델이 GPU 메모리에 존재하지 않습니다.

Phase 1: target 로드 → 전체 샘플 추론 → 언로드
Phase 2: baseline 로드 → 전체 샘플 추론 → 언로드 (enabled일 때)
Phase 3: judge 로드 → 전체 샘플 평가 → 언로드 (enabled일 때)
Phase 4: 결과 통합 → 기존과 동일한 출력 포맷

LocalHFClient.unload()는 모델/토크나이저 삭제 + torch.cuda.empty_cache() 수행. API 클라이언트(ChatClient/JudgeClient)의 unload()는 no-op.

실행 모드

조건 모드 출력
target만 target-only target 응답 출력
target + baseline comparison 둘 다 출력
judge + target만 pointwise 점수(1-10) + 해설
judge + target + baseline pairwise 승자(A/B/tie) + 점수 + 해설

Bench YAML Spec

target 지정 방법 (정확히 하나만 사용):

bench:
  task: sft                                  # sft | preference
  data_path: data/sft_1k_bench_raw.jsonl
  sample:
    k: 10
    seed: 42
    shuffle: true
  generation:
    max_new_tokens: 256
    temperature: 0.7
    top_p: 0.95
  models:
    target:
      # 방법 A: API 모델 (Ollama/OpenAI/Gemini)
      provider: ollama                       # ollama | openai | gemini
      model: "qwen3:0.6b"
      base_url: "http://localhost:11434/v1"

      # 방법 B: 학습 출력 디렉토리 (자동 체크포인트 해석)
      # output_dir: "outputs/run_20260301_120000"
      # checkpoint: "final"                  # final | latest | best (기본: final)
      # device: "auto"                       # 기본: auto
      # dtype: "auto"                        # 기본: auto

      # 방법 C: HF 모델 디렉토리 직접 지정
      # provider: local_hf                   # 생략 가능 (자동 설정)
      # model_dir: "outputs/run_20260301_120000/final"
    baseline:
      enabled: false
      # API 방식 (Ollama/OpenAI/Gemini):
      provider: ollama
      model: "qwen3:4b"
      # 또는 HF 모델 직접 로드 (provider 불필요):
      # model_dir: "Qwen/Qwen2.5-0.5B"     # HF Hub 이름 또는 로컬 경로 모두 가능
      # device: "cuda:0"
      # dtype: "float16"
      # 참고: 파이프라인 스크립트에서 --set bench.models.baseline.enabled=false로
      # 덮어쓰면 preset의 baseline 설정이 무시됩니다.
    judge:
      enabled: false
      provider: ollama
      model: "gemma3:27b"
      mode: pointwise                        # pointwise | pairwise
      mitigate_position_bias: true           # pairwise A/B 스왑 2회
  output:
    out_dir: outputs/bench
    save_jsonl: true
    print_examples: true
    print_max_chars: 1500

사용 예제

# API 모델 사용
eulerforge bench --preset configs/bench/sft_target_only.yml

# 학습 출력 디렉토리에서 final 체크포인트 로드
eulerforge bench --preset configs/bench/sft_local.yml \
  --target-output-dir outputs/run_20260301_120000

# latest 체크포인트 사용
eulerforge bench --preset configs/bench/sft_local.yml \
  --target-output-dir outputs/run_20260301_120000 --checkpoint latest

# 모델 디렉토리 직접 지정
eulerforge bench --preset configs/bench/sft_local.yml \
  --target-model-dir outputs/run_20260301_120000/final

# GPU 지정 (judge가 GPU 0을 사용할 때, target을 GPU 1에 로드)
eulerforge bench --preset configs/bench/sft_local.yml \
  --target-output-dir outputs/run_20260301_120000 --target-device cuda:1

# 설정 오버라이드
eulerforge bench --preset configs/bench/sft_target_only.yml --set bench.sample.k=20

# 검증만
eulerforge bench --preset configs/bench/sft_target_only.yml --validate-only

# 샘플 확인 (모델 호출 없음)
eulerforge bench --preset configs/bench/sft_target_only.yml --dry-run

벤치 데이터 형식

파일 task
sft_1k_bench_raw.jsonl prompt, response sft
dpo_1k_bench_raw.jsonl prompt, chosen, rejected preference

상세: tutorials/11_bench.md

eulerforge eval (스텁)

퍼플렉시티 평가 (미구현).

eulerforge grid

Optuna 기반 하이퍼파라미터 grid / random / Bayesian search. 상세: 아래 eulerforge grid 섹션 참조.


훈련 타입 (training.type)

타입 설명 데이터 포맷 레퍼런스 모델
sft Supervised Fine-Tuning (기본값) {input_ids, attention_mask, labels} 불필요
dpo Direct Preference Optimization chosen/rejected 쌍 (DPO 포맷) adapter disable
orpo Odds Ratio Preference Optimization chosen/rejected 쌍 (DPO 포맷) 불필요
rm Reward Model (Bradley-Terry) chosen/rejected 쌍 (DPO 포맷) 불필요
ppo PPO/RLHF 프롬프트 전용 + 리워드 모델 adapter disable

공통 훈련 설정

별칭 기본값 설명
max_train_steps max_steps 10000 최대 훈련 스텝 수 (micro-step 기준 = forward/backward 횟수). optimizer step = max_train_steps / grad_accum_steps
batch_size 4 배치 크기
grad_accum_steps 1 그래디언트 축적 스텝. optimizer step = max_train_steps / grad_accum_steps
lr 1e-5 학습률
weight_decay 0.01 Weight decay
warmup_steps 500 워밍업 스텝 수 (micro-step 단위, 내부에서 optimizer step으로 자동 변환)
max_grad_norm 1.0 그래디언트 클리핑 최대 노름
log_steps 100 로깅 주기 (micro-step)
save_steps 1000 체크포인트 저장 주기 (micro-step)
val_steps save_steps 검증 실행 주기 (micro-step). 미설정 시 save_steps와 동일

참고: max_train_stepsmax_steps는 동일한 의미입니다. 둘 다 지정한 경우 max_steps가 우선합니다. LR 스케줄링: cosine decay는 optimizer step = max_train_steps / grad_accum_steps 단위로 동작합니다. warmup_steps도 micro step 단위로 지정하되, 내부에서 자동 변환됩니다. 프리셋에서는 max_train_steps가 표준 키입니다.

스텝 용어: - Micro-step: 매 배치 forward/backward가 1 micro-step. max_steps는 micro-step 기준. - Optimizer step: grad_accum_steps 배치마다 1회. 총 optimizer step = max_steps / grad_accum_steps. - Effective batch: batch_size × grad_accum_steps. 실질적으로 1 optimizer step에 처리되는 샘플 수.

ORPO 옵션

training:
  type: orpo
  orpo_lambda: 1.0  # ORPO 항 가중치 (필수, 양수)

RM 옵션

training:
  type: rm
  # RewardHead가 자동 생성됨 (hidden_size → 1)

PPO 옵션

training:
  type: ppo
  ppo:
    clip_range: 0.2     # PPO 클리핑 범위
    kl_coef: 0.1        # KL 페널티 계수
    epochs: 4           # 배치당 PPO 업데이트 에폭 수
    max_gen_len: 64     # 최대 생성 길이
    temperature: 1.0    # 샘플링 온도
  reward_model:
    model_name: "path/to/model"  # 리워드 모델 경로
    checkpoint_path: ""          # 체크포인트 (선택)

모델 로드 정밀도 (model.load_precision)

모델 로드 시 정밀도와 양자화 옵션을 YAML로 선언합니다.

model:
  load_precision:
    mode: int4               # fp32 | fp16 | bf16 | int8 | int4
    compute_dtype: bf16      # int8/int4 연산 dtype (fp16 | bf16)
    quant_type: nf4           # int4 전용: nf4 | fp4
    double_quant: true        # int4 전용
    dequantize_on_train: true # base_ffn trainable 시 자동 dequantize

mode별 동작

mode torch_dtype BitsAndBytes 용도
fp32 float32 CPU/디버그
fp16 float16 GPU 메모리 절감
bf16 bfloat16 GPU 기본값 (Ampere+)
int8 load_in_8bit 8bit 양자화
int4 load_in_4bit 4bit 양자화 (QLoRA)

Phase Dequantize 정책

dequantize_on_train=true (기본값)이고 phase 전환 시 base_ffn이 trainable이 되면, 양자화 모듈을 nn.Linear교체하고 가중치를 compute_dtype으로 복원합니다.

mode 교체 대상 dequant 방식
int4 Linear4bitnn.Linear dequantize_4bit()
int8 Linear8bitLtnn.Linear int8_vectorwise_dequant()
bf16/fp16/fp32 교체 없음 직접 requires_grad 설정

교체는 set_trainable_by_groups() 내부에서 requires_grad=True 설정 직전에 자동 수행됩니다. 양자화 모듈의 forward()가 int8/int4 데이터를 재할당하므로, param cast만으로는 부족하며 모듈 자체를 교체해야 합니다.

target_layers 자동 스코핑: base_ffn이 활성이고 명시적 target_layers가 없으면, injection.start_layer/injection.num_layers에서 대상 레이어를 자동 추출합니다. MoE가 주입된 레이어만 dequantize/unfreeze합니다.

하위 호환

기존 training.quant_bits 사용 시 경고와 함께 자동 변환됩니다: - quant_bits: 4mode: int4 - quant_bits: 8mode: int8 - quant_bits: 16mode: bf16

스펙 상세: docs/fixtures/specs/load_precision_spec.md


데이터 입력 (data 섹션)

EulerForge는 3종류의 데이터 태스크를 표준으로 지원합니다:

태스크 Raw 스키마 Processed 스키마
sft {text} 또는 {prompt, response} {input_ids, attention_mask, labels}
preference {chosen, rejected} {chosen_input_ids, chosen_attention_mask, chosen_labels, rejected_input_ids, rejected_attention_mask, rejected_labels}
prompted_preference {prompt, chosen, rejected} 위 + {prompt_input_ids, prompt_attention_mask, prompt_len}

설정 예시

# 방법 1: 이미 토큰화된 processed JSONL
data:
  format: processed
  path: data/sft_processed.jsonl

# 방법 2: raw JSONL (훈련 시 자동 전처리 → 캐시)
data:
  format: raw
  task: prompted_preference
  path: data/dpo_10k_raw.jsonl
  max_length: 512
  # num_proc: 기본값 = CPU 코어 50% (자동)
  # cache_dir: 기본값 = outputs/.cache (run 간 공유 캐시)
  #
  # 캐시 파일명 규칙: {입력파일명}_{task}_{모델명}_len{max_length}.jsonl
  # 예: dpo_10k_raw_prompted_preference_qwen3.5-0.8b-base_len512.jsonl
  # 동일 파라미터면 자동 재사용 (재전처리 없음)

# 방법 3 (레거시): processed_data_path 직접 지정
processed_data_path: data/sft_processed.jsonl

Labels 마스킹 정책

통합테스트 데이터 정책

데이터 검증

Processed 데이터는 훈련 시작 전 첫 5줄을 검사하여 필수 키를 확인합니다. 누락 시 3줄 에러:

Data: processed dataset row 0 missing 'input_ids'
Fix: Run `eulerforge preprocess ...` or set data.format=raw with schema mapping
See: docs/tutorials/ko/00_data_preprocessing.md

data.task ↔ training.type 호환성

data.format=raw일 때 data.tasktraining.type의 호환성을 자동 검증합니다:

data.task 호환 training.type
sft sft, ppo
preference dpo, orpo, rm
prompted_preference dpo, orpo, rm
prompt_only ppo

불일치 시 에러:

Data Config: data.task='sft' is incompatible with training.type='dpo'. Task 'sft' produces data for sft, ppo training
Fix: Set --set training.type=sft or change data.task to match
See: docs/tutorials/ko/00_data_preprocessing.md

설정 오버라이드 메커니즘

--set으로 도트 경로 표기법을 사용하여 오버라이드합니다:

--set training.lr=2e-5
--set injection.lora_r=32
--set training.phases.1.step=100   # list 내 특정 인덱스 필드 업데이트 (sparse)
--set training.phases.0.trainable=[lora,attn_lora]  # list 요소의 list 값

List 인덱스 오버라이드: training.phases.N.field=value 형식으로 list 내 N번째 요소의 필드만 업데이트 가능합니다. 나머지 요소와 해당 요소의 다른 필드는 preset 값이 보존됩니다. 범위 초과 시 명확한 에러가 발생합니다.

타입 추론

파싱 결과
true bool
false bool
null None
42 int
3.14 float
2e-5 float
hello str

우선순위

CLI --set 오버라이드 > YAML 프리셋 값

출력 및 체크포인트

훈련 시 다음 디렉토리 구조가 생성됩니다:

outputs/run_YYYYMMDD_HHMMSS/
├── resolved_config.json    # 전체 해석된 설정 (재현성)
├── checkpoint-latest/      # 최신 체크포인트
│   ├── model files...
│   ├── tokenizer files...
│   └── training_state.pt   # 옵티마이저, 스케줄러, 스텝, best_val_loss
├── checkpoint-best/        # 최적 검증 손실 체크포인트
│   └── ...
└── final/                  # 훈련 완료 후 최종 모델
    └── ...

checkpoint-bestval_steps 주기로, checkpoint-latestsave_steps 주기로 독립적으로 저장됩니다. 예: val_steps=500, save_steps=1000 → step 500에서 best 저장 시도, step 1000에서 latest 저장.

훈련 자동 Resume

checkpoint-latest/training_state.pt가 존재하면 자동으로 해당 지점에서 이어서 훈련합니다: - micro_step, optimizer_step, best_val_loss 복원 - LR scheduler fast-forward: resume 지점의 optimizer_step에 맞게 cosine schedule을 즉시 복원 (warmup부터 재시작하지 않음) - ETA 계산: resume 이후 진행된 step 기준으로 남은 시간 추정


MoE Stability Validation

MoE 전략(mixture_lora, moe_expert_lora)을 사용할 때 validator가 자동으로 안정성을 검사합니다.

필수 파라미터

역할 권장값 근거
moe.router_z_loss_coef 라우터 logit 안정화 0.001 ST-MoE: softmax overflow 방지
moe.load_balance.type 부하 분산 정책 aux_loss 라우팅 붕괴 방지
moe.load_balance.aux_loss_coef 보조 손실 가중치 0.01 type=aux_loss 시 필수

선택 파라미터

역할 기본값 권장 범위
moe.capacity_factor_train 훈련 시 전문가 처리량 상한 모델 기본값 1.0~2.0 (ST-MoE: 1.25)
moe.capacity_factor_eval 평가 시 전문가 처리량 상한 모델 기본값 train 이상 (ST-MoE: 2.0)
moe.router_dtype 라우터 연산 정밀도 float32 float32 (float16/bfloat16은 수치 불안정)
moe.load_balance.bias_update_speed 전문가 bias 적응 속도 type=aux_loss_free 시 필수 (0.001)

에러 메시지 형식

MoE 검증 실패 시 3줄 포맷으로 출력됩니다:

MoE Config: moe.router_z_loss_coef is required for MoE strategies.
Fix: Set moe.router_z_loss_coef: 0.001 (ST-MoE recommended)
See: docs/tutorials/ko/09_moe_stability_and_validation.md

경고 (비치명적)

조건 의미
router_z_loss_coef = 0 z-loss 비활성화 — 대규모 훈련에서 불안정 가능
router_z_loss_coef > 0.1 비정상적으로 큰 값 — 라우터 제약 과도
load_balance.type = none 부하 분산 없음 — 라우팅 붕괴 위험
aux_loss_coef = 0 실질적 부하 분산 비활성화
router_dtype = float16/bfloat16 라우터 softmax 수치 불안정 가능
capacity_factor_eval < train eval 시 토큰 드롭 증가
어떤 페이즈에도 router 없음 라우터 미훈련 — 데이터 적응 불가

Preflight 검사

--preflight는 모델 로드 후 런타임 검사를 수행합니다:

eulerforge train --preset PRESET.yml --preflight
검사 항목 설명
그룹 파라미터 수 페이즈가 참조하는 그룹의 파라미터가 0개인 경우 에러
target_layers 범위 모델 레이어 수를 초과하는 인덱스 에러

상세: tutorials/09_moe_stability_and_validation.md


로깅 및 메트릭

훈련 루프는 2단계 메트릭 시스템을 통해 로깅합니다.

메트릭 레벨

레벨 기록 항목
minimal (기본) step, main_loss, total_loss, aux_loss, lr, grad_norm, throughput, tokens/samples, 훈련 타입별 메트릭
advanced minimal + MoE 라우팅 통계 (token_frac, entropy, importance_cv, router_logit_max 등)

minimal 메트릭

태그 설명
train/main_loss 주 손실 (SFT/DPO/ORPO/RM/PPO)
train/total_loss 총 손실 (main + aux * weight)
train/aux_loss MoE 보조 손실 합계
train/learning_rate 현재 학습률
train/grad_norm Global L2 그래디언트 노름
train/tokens_seen 누적 학습 토큰 수 (labels != -100)
train/samples_seen 누적 처리 샘플 수 (preference: 쌍 기준)
train/optimizer_step 누적 옵티마이저 스텝 수
train/micro_step 누적 마이크로 스텝 수
train/effective_batch 유효 배치 크기 (batch_size x grad_accum_steps)
DPO: train/reward_margin chosen-rejected 보상 차
ORPO: train/sft_loss, train/orpo_loss SFT/ORPO 개별 손실
PPO: train/kl, train/reward_mean KL divergence, 보상 평균

advanced 메트릭 (MoE 전용)

태그 설명
moe/token_frac_mean 전문가별 토큰 비율 평균
moe/token_frac_std 전문가별 토큰 비율 표준편차
moe/token_frac_max 가장 많이 선택된 전문가 비율
moe/entropy_mean 라우터 엔트로피 평균
moe/importance_cv 중요도 변동계수 (불균형 감지)
moe/aux_loss_total 전체 aux loss 합계
moe/router_logit_max 라우터 logit 최대값 (수치 폭주 감지)
moe/num_moe_modules MoE 모듈 수

LoRA Handoff 로깅

lora_handoff 설정 시 훈련 로그에 다음 마일스톤 이벤트가 자동 출력됩니다:

이벤트 로그 메시지 시점
스케줄 초기화 [Handoff] Schedule: expert_lora(step 4000→6000, ...) 훈련 시작 시
fade 시작 [Handoff] expert_lora fade 시작 at step 4000 (curve=cosine, ...) start_step 도달 시
fade 완료 [Handoff] expert_lora fade 완료 at step 6000 (scale=0.0000) start_step + duration_steps 도달 시
freeze [Handoff] expert_lora frozen at step 6000 (scale=0.0000) end_action=freeze
ramp 시작 [Handoff] base_ffn_ramp 시작 at step 2000 (LR ×1.0→×3.0) ramp start_step 도달 시
ramp 완료 [Handoff] base_ffn_ramp 완료 at step 4000 (LR ×3.0) ramp end_step 도달 시

각 이벤트는 한 번만 출력됩니다 (one-shot). attn_lora도 동일 패턴입니다.

주기적 로그(log_steps)에는 handoff 상태가 자동 추가됩니다:

[Phase2] Step 400/600 (micro 4500/6000) | Loss: 0.1234 | LR: 1.00e-05 | ... | Handoff[expert_lora=0.75, attn_lora=0.80, ffn_lr_mult=2.50]

TensorBoard 통합

TensorBoard 기록은 선택적 의존성입니다:

pip install eulerforge[tb]

설정 예시:

logging:
  metrics_level: advanced      # "minimal" | "advanced"
  tensorboard:
    enabled: true              # TensorBoard 기록 (기본: false)
    log_dir: "outputs/tb"      # 로그 디렉토리
  log_interval: 50             # N 스텝마다 TensorBoard 기록
  max_experts_log: 16          # advanced에서 상위 N 전문가 상세 로그

CLI로 메트릭 레벨 오버라이드:

eulerforge train --preset PRESET.yml --metrics-level advanced

tensorboard 미설치 시 경고만 출력하고 훈련은 정상 진행됩니다.

상세: tutorials/10_metrics_monitoring.md


eulerforge grid

기본 사용법

# spec 검증만 (dry-run)
eulerforge grid configs/grid/sft_random_search.yml --dry-run

# 실제 실행
eulerforge grid configs/grid/sft_random_search.yml

# project root 명시
eulerforge grid configs/grid/sft_random_search.yml --project-root /path/to/project

옵션

옵션 기본값 설명
spec (필수) Grid search YAML spec 파일 경로
--dry-run false Spec 검증만 수행, 학습 미실행
--project-root DIR cwd 상대 경로 기준 디렉토리

Optuna 의존성

pip install eulerforge[hpo]

optuna 미설치 시 pip install eulerforge[hpo] 안내 메시지 출력 후 종료합니다.

method별 Optuna 샘플러

method 샘플러 비고
grid GridSampler 이산 공간만 지원 (categorical / choices)
random RandomSampler 연속/이산 모두 지원
bayes TPESampler 연속/이산 모두 지원

method: "grid" + type: "float" + low/high 조합은 오류입니다. Grid에서 연속 실수를 탐색하려면 choices: [값1, 값2] 형식을 사용하세요.

출력

<output_root>/
├── trial_0000/
│   ├── metrics.jsonl       # 스텝별 지표 (train/total_loss 등)
│   └── checkpoint-latest/
├── trial_0001/
│   └── ...
├── summary.json            # 전체 결과 (best_trial + all_trials)
└── summary.csv

spec 형식 상세: docs/fixtures/specs/grid_search_spec.md


Python API: eulerforge.loader

EulerForge로 훈련한 체크포인트를 Python에서 직접 로드하는 공용 API.

from eulerforge import load_model

load_model(path, *, checkpoint, device, dtype, load_precision) → LoadedModel

파라미터 기본값 설명
path (필수) run_dir 또는 checkpoint_dir 경로
checkpoint "final" run_dir일 때 체크포인트 선택: final | best | latest
device "auto" "auto" | "cpu" | "cuda" | "cuda:0"
dtype "auto" "auto" | "float32" | "bfloat16"
load_precision None 로드 정밀도: None | "fp32" | "fp16" | "bf16" | "int8" | "int4"

반환 타입

@dataclass
class LoadedModel:
    model: nn.Module           # eval 모드
    tokenizer: PreTrainedTokenizer
    metadata: ModelMetadata

@dataclass
class ModelMetadata:
    strategy: str              # "dense_lora" | "moe_expert_lora" | "mixture_lora" | "none"
    backbone: str              # "qwen3" | "llama" | "gemma3" | ""
    path_type: str             # "run_dir" | "checkpoint_dir"
    checkpoint_dir: str        # 실제 체크포인트 디렉토리 경로
    lora_config: dict | None   # {"lora_r": int, "lora_alpha": float}
    structure_preserved: bool  # MoE/MixtureLoRA 구조 보존 여부
    load_precision: str | None # "fp32" | "fp16" | "bf16" | "int8" | "int4" | None

경로 자동 분류

경로 유형 판별 기준 동작
run_dir resolved_config.json 존재 checkpoint 파라미터로 서브디렉토리 해석
checkpoint_dir config.json 존재 직접 로드

사용 예제

from eulerforge import load_model

# 1. 학습 출력 디렉토리에서 로드 (final 체크포인트)
result = load_model("outputs/run_20260311_163425")
print(result.metadata.strategy)     # "moe_expert_lora"
print(result.metadata.backbone)     # "qwen3"

# 2. best 체크포인트 로드
result = load_model("outputs/run_20260311_163425", checkpoint="best")

# 3. 체크포인트 디렉토리 직접 지정
result = load_model("outputs/run_20260311_163425/final", device="cuda:0")

# 4. 양자화 로딩 (int4/int8)
result = load_model("outputs/run_20260311_163425", load_precision="int4")
result = load_model("outputs/run_20260311_163425", load_precision="bf16")

# 5. 추론
messages = [{"role": "user", "content": "안녕하세요"}]
text = result.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = result.tokenizer(text, return_tensors="pt").to(result.model.device)
with torch.no_grad():
    out = result.model.generate(**inputs, max_new_tokens=128)
print(result.tokenizer.decode(out[0], skip_special_tokens=True))

# 6. 메타데이터 활용
if result.metadata.structure_preserved:
    print("MoE 구조가 보존된 체크포인트입니다")
if result.metadata.lora_config:
    print(f"LoRA r={result.metadata.lora_config['lora_r']}")

로딩 전략

strategy 로드 방식 구조 보존
dense_lora LoRA 병합 → dense 모델 No
moe_expert_lora MoE 아키텍처 재구성 (expert+router) Yes
mixture_lora MixtureLoRA 아키텍처 재구성 Yes
none from_pretrained() 직접 로드 N/A

참고: moe_expert_loramixture_loraresolved_config.json이 필요합니다. 없으면 expert 평균 → dense 모델로 fallback됩니다 (WARNING 출력).


eulerforge export-hf

EulerForge 체크포인트를 HuggingFace Transformers 호환 모델로 내보냅니다.

기본 사용법

# dense_lora → merged HF 모델
eulerforge export-hf --checkpoint outputs/run_20260311_163425 --output ./exported

# MoE → custom_moe HF 모델 (trust_remote_code=True로 로드)
eulerforge export-hf --checkpoint outputs/run_moe --output ./exported_moe

# dry-run (계획만 출력)
eulerforge export-hf --checkpoint outputs/run --output ./out --dry-run

# validate-only (검증만)
eulerforge export-hf --checkpoint outputs/run --output ./out --validate-only

옵션

옵션 기본값 설명
--checkpoint (필수) run_dir 또는 checkpoint_dir 경로
--output (필수) export 출력 디렉토리 (이미 존재하면 에러)
--format auto auto | merged | custom_moe
--select-checkpoint final final | best | latest
--dtype auto auto | fp32 | fp16 | bf16
--safe-serialization True safetensors 사용 여부 (--no-safe-serialization으로 비활성화)
--copy-tokenizer True tokenizer 복사 여부 (--no-copy-tokenizer로 비활성화)
--dry-run False 계획만 출력, 실제 export 없음
--validate-only False 검증만 수행
--skip-diversity-check False Expert diversity check 건너뛰기 (경량 훈련 시 expert 미분화)

전략별 Export 포맷

전략 format=auto 시 결과 HF 로드
dense_lora merged 표준 dense HF 모델 from_pretrained(path)
mixture_lora custom_moe base+router+N LoRA experts from_pretrained(path, trust_remote_code=True)
moe_expert_lora custom_moe N expert FFN+router from_pretrained(path, trust_remote_code=True)

핵심: moe_expert_lora/mixture_lora 전략을 merged로 export하면 expert 구조가 파괴됩니다. format=merged+MoE → ValueError.

스펙 상세: docs/fixtures/specs/export_hf_spec.md


eulerforge pretrain (Plugin)

Plugin 명령: pretrain은 plugin 방식으로 제공됩니다. eulerforge.plugins.pretrain_plugin 모듈이 존재할 때만 CLI에 등록됩니다. 공개 배포판에서 이 모듈을 제외하면 명령이 자동 비활성화됩니다.

EulerStack 등 외부 도구가 HuggingFace 형식으로 export한 모델을 raw text 데이터로 스크래치 사전훈련합니다. 기존 train 명령어(LoRA/MoE 인젝션)와 완전히 분리된 전체 파라미터 causal LM 훈련입니다.

eulerforge pretrain [OPTIONS]
옵션 설명
--preset PATH pretrain YAML 프리셋 경로 (필수)
--set KEY=VALUE 설정 오버라이드 (반복 가능)
--output-dir DIR 출력 디렉토리
--validate-only 설정 검증만, 훈련 없음

pretrain vs train 차이

항목 train (파인튜닝) pretrain (스크래치)
모델 로드 from_pretrained (기존 가중치) from_pretrained (초기화된 가중치)
인젝션 LoRA/MoE 적용 없음 (전체 파라미터 학습)
페이즈 스케줄 freeze/unfreeze 제어 없음 (전부 trainable)
데이터 instruction/preference 형식 raw text (packed chunking)
금지 키 injection, moe, backbone → 에러

pretrain YAML 프리셋 구조

# 디바이스
device: "cuda:0"             # cuda:0, cuda:1, cpu

# 모델 (EulerStack export 디렉토리)
model_dir: "outputs/full_hybrid_moe"
trust_remote_code: true

# 토크나이저 (model_dir에 없으면 별도 지정)
tokenizer: "gpt2"

# 데이터
data:
  path: "data/dolma_10k.jsonl"
  text_column: "text"        # JSONL의 텍스트 키
  max_length: 1024
  packing: true              # packed chunking (텍스트 연결 → 고정 길이 분할)

# 훈련
training:
  max_steps: 500
  batch_size: 2
  grad_accum_steps: 4
  lr: 3.0e-4
  weight_decay: 0.1
  warmup_steps: 50
  max_grad_norm: 1.0
  log_steps: 10
  save_steps: 250
  dtype: "float32"           # Hybrid 모델(Hyena/RetNet)은 float32 필수
  amp: false                 # FFT 연산 bf16 미지원 → 비활성화
  seed: 42

사용 예

# 기본 실행
eulerforge pretrain --preset configs/presets/pretrain/eulerstack_hybrid_moe.yml

# 설정 오버라이드
eulerforge pretrain --preset ... --set training.max_steps=1000 --set training.lr=1e-4

# 검증만
eulerforge pretrain --preset ... --validate-only

# 출력 디렉토리 지정
eulerforge pretrain --preset ... --output-dir outputs/my_pretrain

출력 구조

outputs/pretrain_YYYYMMDD_HHMMSS/
├── pretrain_config.json         # 설정 스냅샷
├── metrics.jsonl                # 스텝별 loss, lr 기록
├── checkpoint-250/              # 중간 체크포인트
│   ├── config.json
│   ├── model.safetensors
│   └── tokenizer files...
└── final/                       # 최종 모델
    ├── config.json
    ├── model.safetensors
    └── tokenizer files...

pretrain 완료 후 final/ 디렉토리를 eulerforge trainmodel_name으로 지정하면 LoRA 파인튜닝이 가능합니다.