4. Compile & Explain
이 장에서는 YAML 스펙을 실제로 실행 가능한 모델 객체 로 바꾸는 두 명령,
explain 과 compile 을 다룹니다. 앞 장에서 스펙 검증을 끝냈다면, 이 장의 목적은
그 스펙이 어떤 모델로 만들어지고, 그 모델이 어떻게 HuggingFace 생태계로 이어지는지
이해하는 것입니다.
왜 컴파일이 필요한가
EulerStack 의 YAML 은 선언적 설계도 일 뿐이며 그 자체로 실행 가능하지 않습니다. PyTorch 가 이 설계도를 이해하려면 중간 표현(IR)을 거쳐 두 가지 산출물 중 하나로 변환되어야 합니다.
-
JSON 런타임 config 스펙을 평평한 딕셔너리로 펼쳐서 검사/디버깅/CI 용으로 저장하는 형태입니다. 모델을 만들지는 않고 스펙을 JSON 으로 굳힌 스냅샷 이라고 생각하면 됩니다.
-
HuggingFace 모델 디렉토리 실제
PreTrainedModel을 메모리에 만든 뒤save_pretrained()로 저장한 폴더입니다.config.json과model.safetensors(랜덤 초기화 가중치)가 생성되며, eulerforge 나 다른 HF 호환 트레이너에서 바로 로드할 수 있습니다.
이 두 산출물이 "아키텍처 설계" 와 "모델 훈련" 사이를 이어주는 다리 역할을 합니다. 설계를 JSON 으로 굳히면 디버깅이 쉽고, HF 디렉토리로 만들면 훈련이 쉽습니다.
모델 설명 (explain)
가중치를 만들기 전에 먼저 스펙이 어떤 모델을 그릴지 눈으로 확인하는 것이 좋습니다.
explain 명령은 YAML 을 읽어 레이어 템플릿, 스케줄, 파라미터 추정치까지 텍스트로
출력합니다. GPU 를 쓰지 않고도 전체 아키텍처 그림을 확인할 수 있습니다.
eulerstack explain --preset configs/presets/arch_expert_research.yml
출력 예시는 다음과 같습니다.
모델: arch-expert-research
Family 힌트: full-hybrid-moe
차원: d_model=1024, n_heads=8, n_kv_heads=4
Vocab: 32000, 최대 길이: 32768, dtype: bfloat16
위치 인코딩: rope
레이어 템플릿:
attn:
mixer: attention {...}
ffn: gated_mlp
...
mamba:
mixer: mamba {variant: mamba2, d_state: 128, ...}
ffn: gated_mlp
...
retnet:
mixer: retnet {...}
...
레이어 스케줄:
mamba x1, retnet x1, mamba x1, retnet x1, mamba x1, attn x1, ...
총 레이어 수: 32
Head: causal_lm, tie_weights=True
컴파일 타겟: huggingface
추정 파라미터: 1.48B (1,481,235,456)
목표 파라미터: 1.50B (비율: 98.7%)
이 출력이 기대와 다르다면 YAML 을 수정해야 합니다. 시간이 오래 걸리는 GPU 컴파일을
돌리기 전에 explain 으로 먼저 확인하는 습관을 들이면 실수를 많이 줄일 수 있습니다.
JSON 으로 컴파일 (검사용)
compile --print-config 는 스펙을 JSON 으로 변환한 결과를 터미널에 그대로 출력합니다.
--output <file> 로 파일에 저장할 수도 있습니다.
# 터미널에 JSON 출력
eulerstack compile --preset configs/presets/arch_advanced_jamba.yml --print-config
# 파일로 저장
eulerstack compile --preset configs/presets/arch_advanced_jamba.yml --output compiled.json
출력된 JSON 은 HuggingFace 호환 config 의 모든 필드를 포함합니다. 구체적으로는
model_type, stack 패턴, blocks 기본값, 위치 인코딩 설정, MoE 라우팅, 메모리
설정 등입니다. 이 JSON 을 diff 로 비교하면 두 프리셋이 구조적으로 어떤 지점에서
다른지 정확히 짚어낼 수 있습니다.
HuggingFace 모델로 컴파일 (export)
가장 중요한 출력은 HF 모델 디렉토리 입니다. 이 디렉토리는 transformers 라이브러리가
바로 로드할 수 있는 표준 PyTorch 모델을 담고 있습니다.
eulerstack compile --preset configs/presets/arch_advanced_jamba.yml --output-dir ./my_jamba_model
성공하면 다음과 같은 메시지가 출력됩니다.
HF 모델 저장 완료: ./my_jamba_model
model_type: eulerstack
파라미터: 1.20B (1,199,582,208)
레이어: 32
로드 방법: AutoModelForCausalLM.from_pretrained('./my_jamba_model', trust_remote_code=True)
생성된 디렉토리 구조는 다음과 같습니다.
my_jamba_model/
├── config.json # EulerStackConfig (모든 아키텍처 파라미터)
├── model.safetensors # 랜덤 초기화 가중치
├── configuration_eulerstack.py # trust_remote_code 로 로드되는 커스텀 config
└── modeling_eulerstack.py # trust_remote_code 로 로드되는 모델 클래스
configuration_eulerstack.py 와 modeling_eulerstack.py 가 함께 저장되는 이유는
AutoModelForCausalLM.from_pretrained(trust_remote_code=True) 로 로드할 때 HF 가
이 파일들을 읽어 EulerStack 모델 클래스를 재구성하기 때문입니다. 이 구조 덕분에
eulerstack 이 설치되어 있지 않은 환경에서도 모델 자체는 로드/훈련 가능합니다.
Python 에서 로드하기
export 된 디렉토리는 HF 표준 인터페이스로 로드합니다.
from transformers import AutoModelForCausalLM, AutoTokenizer
from eulerstack.hf.auto_register import register_eulerstack_auto_classes
register_eulerstack_auto_classes()
# Llama / Mistral 로드와 동일한 방식
model = AutoModelForCausalLM.from_pretrained(
"./my_jamba_model",
trust_remote_code=True,
dtype="bfloat16",
)
# 표준 PreTrainedModel 클래스
print(type(model)) # <class 'EulerStackForCausalLM'>
print(model.config.n_layers)
# forward pass 가 정상 동작하는지 확인
import torch
ids = torch.randint(0, 32000, (1, 128))
with torch.no_grad():
out = model(ids)
print(out.logits.shape) # (1, 128, 32000)
register_eulerstack_auto_classes() 는 EulerStack config 와 모델 클래스를 HF 의
AutoConfig / AutoModel 레지스트리에 등록하는 함수입니다. 이 등록이 있어야
AutoModelForCausalLM 이 model_type: eulerstack 을 올바르게 해석합니다.
전체 파이프라인 요약
지금까지의 모든 명령을 하나의 그림으로 정리하면 다음과 같습니다.
YAML 프리셋
↓ eulerstack validate --preset X --report (에러 조기 발견)
↓ eulerstack explain --preset X (구조 확인)
↓ eulerstack compile --preset X --output-dir (HF 모델 export)
HF 모델 디렉토리
↓ AutoModelForCausalLM.from_pretrained() (Python 에서 로드)
↓ eulerforge train --preset ... (실제 데이터로 훈련)
훈련된 모델
이 흐름이 EulerStack 의 핵심 워크플로우입니다. YAML 편집과 compile --output-dir
만으로 새 아키텍처를 HF 생태계로 넣을 수 있으며, 그 이후부터는 표준 HF 파이프라인
(PEFT, TRL, eulerforge 등)이 그대로 적용됩니다.
검증만 빠르게 돌리는 모드
HF 모델을 실제로 만들지 않고 스펙이 컴파일 가능한지만 확인하고 싶을 때는
--validate-only 플래그를 사용합니다. GPU 를 쓰지 않고 빠르게 검사할 수 있습니다.
eulerstack compile --preset my_model.yml --validate-only
CI 파이프라인에서 YAML 프리셋이 망가지지 않았는지 확인하는 용도로 유용합니다.
다국어 지원
모든 compile, explain, validate 명령은 --lang 을 지원합니다.
eulerstack --lang en compile --preset my_model.yml --output-dir ./my_model
eulerstack --lang zh compile --preset my_model.yml --output-dir ./my_model
완료/에러 메시지 모두 해당 언어로 출력됩니다. 커맨드 이름과 옵션 이름은 번역되지 않으며, 메시지 내용만 번역됩니다. 이는 스크립트 자동화의 호환성을 유지하기 위한 의도적 설계입니다.
실행 가능한 예제
이 장에서 소개한 흐름을 스크립트 형태로 바로 실행하고 싶다면 examples/ 디렉토리
아래의 다음 파일들을 참고하면 됩니다.
examples/01_compile_and_export.py— compile / save_pretrained 전체 과정examples/02_load_and_generate.py— 로드 후 텍스트 생성examples/03_architecture_evolution.py— 여러 프리셋을 한 번에 비교
다음 단계
- 튜토리얼 5: 데이터 준비 — 훈련에 쓸 토큰화된 데이터
- 튜토리얼 6: Sanity 훈련 — 짧게 돌려 모델이 학습되는지 확인