9. v1 Phase B 신규 프리미티브 워크스루 (MLA / Titans / MoD / Dual-Stream / Neural-ODE / TTT)
이 튜토리얼은 EulerStack v1 에서 새로 추가된 14 개 primitive 를 하나씩 YAML 로 작성하고 검증하는 단계별 가이드입니다. 각 primitive 는:
- 무엇을 가능하게 하는지 (근거 논문 / 상황)
- YAML 로 어떻게 쓰는지 (최소 예제 + 주석)
- 언제 쓸지 (실전 사용 가이드라인)
- 런타임 상태 (Core / Component / Plugin-track)
순서로 다룹니다. schema_version: 1 을 기본으로 두고, 기존 attention /
mamba / retnet / hyena / moe baseline 에 얹을 수 있는 구조로
설계되어 있습니다.
런타임 전체 상태는 runtime_primitive_status.md 매트릭스를 참조하세요 (내부 자산).
0. 사전 준비
pip install -e .
eulerstack --lang ko schema # 스키마 요약 출력 (5 개 언어 지원)
모든 예제는 eulerstack validate --preset <파일> 으로 즉시 검증 가능합니다.
--report 옵션을 붙이면 파라미터 추정 + realism 체크 + reserved-namespace
경고가 함께 나옵니다.
1. per-layer override (B1.1) — 스케줄 수준 값 교체
상황: 템플릿은 그대로 두고 특정 레이어 그룹의 일부 값 (residual scaling, attention window 등) 만 바꾸고 싶을 때.
schema_version: 1
# ... (model/tokenizer/embedding 생략)
layer_templates:
attn_dense:
mixer: { type: attention, attention: { window: null } }
ffn: { type: gated_mlp }
residual: { type: sequential, scaling: 1.0 }
layer_schedule:
- template: attn_dense
repeat: 6
override: # 첫 6 개만 교체
residual: { scaling: 0.5 }
attention: { window: 128 }
- template: attn_dense
repeat: 6 # 나머지 6 개는 템플릿 기본값 그대로
허용 필드 (whitelist, 값 타입 한정):
- residual.scaling
- attention.window, attention.attn_drop
- norm.type, norm.position
- ffn.activation
mixer.type 변경은 불허 — 타입이 다른 레이어는 새 템플릿으로 분리합니다.
런타임: ✅ Core. 정규화 단계에서 per-layer 템플릿 복제본에 override 가 적용됩니다.
2. let: + ${…} 표현식 (B1.2)
상황: d_model = n_heads × d_head 같은 의존 관계를 YAML 수준에서
표현하고 싶을 때.
schema_version: 1
let:
n_heads: 16
d_head: 64
layers: 24
model:
name: "let-demo"
d_model: ${let.n_heads * let.d_head} # 1024
vocab_size: 32000
max_seq_len: ${let.layers * 512} # 12288
n_heads: ${let.n_heads}
n_kv_heads: ${let.n_heads // 2} # 8
layer_schedule:
- template: decoder
repeat: ${let.layers}
허용 연산: + - * / // + 괄호 + let.<name> 참조. 조건문·함수 호출 ·
문자열 연산은 전부 거부됩니다 (Level 1).
런타임: ✅ Core. validate 전 pre-pass 에서 전부 해소.
3. Reserved namespace (B0/B6)
상황: 플러그인이 읽을 메타데이터나 아직 정식 primitive 가 아닌 실험을 YAML 에 남겨두고 싶을 때.
schema_version: 1
# ... (일반 필드)
experimental.online_adaptation: # WARNING 만 발생, ERROR 아님
reward_source: reward_model
vendor.acme.telemetry:
endpoint: "https://telemetry.acme"
future.symbolic_interface:
mode: sidecar
experimental.*— 진행 중 연구future.*— v1.x+ 예약vendor.<name>.*— 서드파티 플러그인
eulerstack validate --report 실행 시 [reserved_namespace] 라벨로 경고
표시됩니다. 플러그인이 등록된 환경에서는 동일 키가 기능적으로 해석됩니다.
4. MLA — attention.latent_dim (B2.1)
근거: DeepSeek-V3 Technical Report (2024). KV 를 공유 latent 로 압축해 캐시 메모리 감소.
layer_templates:
mla_decoder:
mixer:
type: attention
attention:
latent_dim: 384 # d_model=768 의 절반 → KV 캐시 약 50% 절감
ffn: { type: gated_mlp }
실전 가이드:
- 보통 latent_dim ≈ d_model / 2 부터 시작
- 긴 컨텍스트 (≥ 16K) 에서 효과 극대화
- latent_dim ≥ d_model 이면 검증 실패
런타임: ✅ Core. CausalSelfAttention(latent_dim=…) 이 실제 compressed
KV projection 을 수행. forward/backward/kv-cache 모두 지원.
데모 preset: configs/presets/arch_advanced_mla.yml
5. Branched mixer — mixer.type: branched (B2.2)
근거: Jamba (Lieber et al., AI21, 2024) 의 layer-level hybrid 를 per-token routing 으로 일반화.
layer_templates:
branched_layer:
mixer:
type: branched
branched:
branches:
ssm: { type: mamba, mamba: { variant: mamba2 } }
attn: { type: attention, attention: {} }
selector:
type: learned_gate # 또는 top_k
top_k: 1
input: hidden
ffn: { type: gated_mlp }
제약:
- 브랜치 2 개 이상 필수
- 브랜치 안에 또 다른 branched 금지 (v1 에서는 1-레벨만)
런타임: 🟡 Fallback. 현재 컴파일은 첫 브랜치로 대체 실행, 원 spec 은
config.stack.pattern[].\_v1_extras.branched 에 보존. 실 routing 은
플러그인 트랙.
6. TTT layer — mixer.type: ttt_layer (B2.3)
근거: Sun et al. 2024, "Learning to (Learn at Test Time): RNNs with Expressive Hidden States".
layer_templates:
ttt_block:
mixer:
type: ttt_layer
ttt:
inner_model: { type: mlp, hidden: 256 }
inner_optimizer: sgd
inner_lr: 0.01
inner_steps_per_token: 1
ffn: { type: gated_mlp }
state:
ssm_state: true # TTT 는 지속 내부 가중치가 있으므로 기본 true
런타임: 🔌✅ 플러그인 레퍼런스 구현 가능 (v1.1).
eulerstack.plugins.ttt 를 import 하면 실제 per-token meta-learning 루프를
수행하는 TTTBlock 이 plugin registry 에 등록되고, core modeling 이 Mamba
fallback 을 자동으로 업그레이드합니다. import 하지 않으면 기존 Mamba
fallback 이 유지됩니다 (공통프롬프트 §7 격리).
import eulerstack.plugins.ttt # 한 줄 import 으로 활성화
from eulerstack.compiler.compile import compile_to_hf_model
model = compile_to_hf_model(ir, seed=0) # 이제 TTTBlock 이 인스턴스화됨
구현 특징 (functional fast-weights):
- 토큰마다 inner-loss(MSE reconstruction) 를 autograd.grad 로 미분해
SGD 로 fast-weight 텐서 갱신
- 지속 inner 파라미터 self.inner_net 는 forward 종료 시점에
with torch.no_grad(): copy_ 로 한 번에 업데이트 — in-place 버전
충돌 없이 outer training 과 공존
테스트: tests/test_ttt_plugin_runtime.py (10) + tests/test_runtime_hf_training_e2e.py::TestHFExportTTTTraining.
7. Mixture-of-Depths — schedule[].depth_gating (B3.1)
근거: Raposo et al. ICML 2024.
layer_schedule:
- template: attn_block
repeat: 32
depth_gating:
enabled: true
capacity: 0.5 # 토큰의 50% 만 해당 레이어 통과
router: top_k # 또는 learned_gate
실전 가이드:
- capacity: 0.5 가 논문 기본값. 0.25 까지 낮추면 추가 속도, 품질 하락 가능
- router: top_k 결정적 · 재현 가능. learned_gate 는 soft routing
런타임: 🟢 Component. 사용법:
from eulerstack.components.depth_gate import DepthGate
gate = DepthGate(d_model=768, capacity=0.5, router="top_k")
y = gate(x, body_fn=my_attention_layer)
데모 preset: configs/presets/arch_advanced_mod.yml
8. Parallel (monoidal) 스케줄 — schedule[] parallel: (B3.2)
근거: PaLM (2023) within-layer parallel, Flamingo (2022) dual-tower, Jamba (2024) 의 monoidal 일반화.
layer_schedule:
- parallel:
- stream: fast
body:
- { template: mamba_block, repeat: 6 }
- stream: slow
body:
- { template: attn_block, repeat: 6 }
merge:
type: concat # concat | add | gated | cross_attn
projection: true # concat 의 경우 N*d_model → d_model 투영
제약:
- 스트림 ≥ 2
- 스트림 body 안에 다시 parallel / integrator 넣기 금지 (flat 만)
- 스트림 이름 고유
런타임: 🟢 Component. 사용법:
from eulerstack.components.parallel_stream import ParallelStream
p = ParallelStream(
[fast_stream_module, slow_stream_module],
d_model=768,
merge_type="concat",
merge_projection=True,
stream_names=["fast", "slow"],
)
y = p(x)
데모 preset: configs/presets/arch_expert_dual_stream.yml
9. Integrator — schedule[] integrator: (B3.3)
근거: Universal Transformer (Dehghani 2019), PonderNet (Banino 2021), Diffusion-LM (Li 2022), Coconut (Hao 2024) — 네 연구 라인의 통합. v1.1 부터는 Neural-ODE 해석 (Chen et al. 2018) 도 core 에서 지원합니다.
9a. discrete — 독립 가중치 K 단계 (기본)
layer_schedule:
- integrator:
type: discrete # Diffusion-LM 스타일 — K 개 독립 가중치
steps: 4
body: refine_block
output: token # 또는 hidden (Coconut latent reasoning)
기본 compile 은 body 를 K 개 독립 복사본 으로 펼칩니다. 같은 모듈을
shared-weight 로 K 번 적용하고 싶다면 DiscreteIntegrator 컴포넌트로 직접
조립할 수 있습니다.
from eulerstack.components.integrator import DiscreteIntegrator
integrator = DiscreteIntegrator(refine_block, steps=4) # shared weights
9b. ode_euler / ode_rk4 — Neural-ODE shared-weight (v1.1 core ✨)
layer_schedule:
- integrator:
type: ode_rk4 # 또는 ode_euler
steps: 4
body: refine_block
output: token
의미: body(x) 를 "미분 항" f(x) 로 해석하고, dt = 1/steps 로 K
단계 수치적분을 수행합니다. 가중치는 공유 — steps 를 늘려도 파라미터
수는 늘지 않습니다.
ode_euler— step 당 body 1 회 호출 (가장 저렴)ode_rk4— step 당 body 4 회 호출 (정확도가 훨씬 높음)
from eulerstack.components.integrator import ODEIntegrator
odeint = ODEIntegrator(refine_block, steps=4, method="rk4")
런타임 경로: EulerStackLayer._forward_ode 에서 per-step RoPE /
attention mask 를 올바르게 흘리면서 RK4 를 수행합니다. KV 캐시는 ODE
경로에서 비활성화됩니다 (해석이 모호함).
9c. ode_adaptive — 예약 (plugin-only)
adaptive step-size 제어 (torchdiffeq 등) 는 여전히 reserved 입니다. 정식 플러그인이 나오기 전에는 validator 가 거부합니다.
10. Memory module — template.memory: (B4.1)
근거: Titans (Behrouz et al., Google, 2024-2025).
layer_templates:
attn_with_memory:
mixer: { type: attention, attention: {} }
ffn: { type: gated_mlp }
memory:
type: neural_memory
update_at_inference: true
params:
hidden: 2048
inner_lr: 0.001
persistence: session # per_query | session | persistent
런타임: ✅ Core (v1.1). TitansMemoryModule 이 template 에
memory: 가 선언된 모든 레이어에 자동 결합됩니다. 훈련 중에는 outer 옵티마이저가
메모리 파라미터를 함께 학습하고, 추론 시에는 표준 훅 step_memory_at_inference
로 inner SGD 스텝을 수행합니다 — HF save_pretrained → from_pretrained
왕복 후에도 그대로 동작합니다.
from transformers import AutoModelForCausalLM
from eulerstack.hf.auto_register import register_eulerstack_auto_classes
register_eulerstack_auto_classes()
model = AutoModelForCausalLM.from_pretrained("./titans_model", trust_remote_code=True)
ids = tokenizer("앞 turn 에서 등장한 사실", return_tensors="pt").input_ids
out = model(ids, output_hidden_states=True)
surprise = model.step_memory_at_inference(out.hidden_states[-1])
# surprise: {"eulerstack.layers.0.titans_memory": 0.42, ...}
데모 preset: configs/presets/arch_expert_titans_memory.yml
11. Shape-change layer — template.shape_change: (B4.2)
근거: Hourglass Transformer (Nawrot et al. 2021).
layer_templates:
wide_block: { mixer: { type: attention, attention: {} }, ffn: { type: gated_mlp } }
bottleneck:
mixer: { type: attention, attention: {} }
ffn: { type: gated_mlp }
shape_change:
d_out: 128 # 여기서 hidden 을 d_out 으로 축소
projection: linear # linear | conv1d | mlp
런타임: 🔌 Plugin-track. Core modeling 이 layer 간 d_model 고정 가정이라 shape-changing residual wire-up 은 플러그인이 제공.
12. Reasoning mode — execution_modes: + transition: (B5)
근거: DeepSeek-R1 (2025), OpenAI o1/o3 (2024), Quiet-STaR (NeurIPS 2024).
아키텍처는 변하지 않습니다 — 훈련 레시피와 generate() 가 읽는
메타데이터일 뿐입니다.
execution_modes:
- name: think
max_tokens: 8192
kv_share: true
loss_weight: 0.0 # primary LM 손실에서 제외
visible_to_user: false
- name: answer
max_tokens: 2048
loss_weight: 1.0
visible_to_user: true
transition:
type: special_token
token: "<think_end>"
Quiet-STaR 변형 (토큰마다 rationale 생성):
execution_modes:
- name: rationale
max_tokens: 16
per_token_rationale: true # Zelikman 2024
loss_weight: 0.1
visible_to_user: false
- name: answer
max_tokens: 256
loss_weight: 1.0
visible_to_user: true
런타임: ✅ Core (메타데이터 round-trip). Generate 경로가 phase 분리를 honour.
데모 preset: configs/presets/arch_expert_reasoning_r1.yml
13. Reserved integrator 타입 (B3.3, v1.x+)
ode_rk4 / ode_euler 는 v1.1 에서 core 로 승격됐습니다 (§9b 참조).
v1.0 에서 reserved 였던 타입 중 현재 남아 있는 것은 ode_adaptive 뿐입니다.
layer_schedule:
- integrator:
type: ode_adaptive # RESERVED — 플러그인 (torchdiffeq 등) 이 필요
steps: 8
body: refine_block
상태: 스키마 예약. adaptive step-size 제어에는 torchdiffeq 같은 전용
라이브러리가 필요하므로 플러그인 트랙으로 남깁니다. 일반 고차 수치적분은
이미 ode_rk4 로 충분합니다.
14. Weight form 예약 (future)
tensor network weight (MPS/MERA/TT) 는 weight_form: 필드로 예약되어 있으나
v1.0 스키마 enum 에는 아직 없습니다. 필요 시 vendor.tensor.weight_form: mera
처럼 reserved namespace 로 미리 써두면 plugin 등장 시 자연스럽게 연결됩니다.
검증 & 컴파일 체인
모든 primitive 를 조합한 스펙은 아래 한 줄로 검증됩니다:
eulerstack --lang ko validate --preset my_spec.yml --report
리포트에는 다음이 포함됩니다: - 스키마 통과 여부 - 추정 파라미터 수 - 층 수 (integrator 는 K 로 펼친 수) - realism 경고 (RoPE head_dim, MoE expert 수 등) - reserved-namespace 경고 (해당 시)
컴파일 후 HF 커스텀 모델로 저장:
eulerstack --lang ko compile --preset my_spec.yml --output-dir ./my_model
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("./my_model", trust_remote_code=True)
# config.v1_extensions 에 execution_modes / schedule_kinds / _v1_extras 전부 보존
"이걸 다 같이 쓰면 정말 돌아가?" — Capstone preset
위 primitive 를 한 스펙에 전부 담은 캡스톤 preset 이 있습니다:
configs/presets/arch_expert_kitchen_sink.yml.
let:+${…}표현식 ✓- reserved namespace (
experimental.*/vendor.*.*/future.*) ✓ - per-layer override (B1.1) ✓
- MLA (
attention.latent_dim) + Titans neural memory 한 레이어에 결합 ✓ - mamba / retnet / hyena / attention / branched / ttt_layer 6 종 mixer 전부 ✓
- MoE FFN (gated_mlp 혼합) ✓
- depth_gating (MoD) + parallel 스케줄 + discrete integrator + ODE RK4 ✓
- execution_modes + transition (R1 계약) ✓
TDD 검증 (tests/test_kitchen_sink_preset.py) 10 개:
- YAML 이
validate_v2를 통과 normalize_to_ir이 20 개 expanded layer 를 생성- override 가 Titans memory / ODE 메타를 보존 (회귀 가드)
compile_to_hf_model이 실제EulerStackForCausalLM인스턴스 생성- 1-스텝 forward 가 예상 logits shape 반환
save_pretrained → AutoModelForCausalLM.from_pretrained왕복 후 forward 결과 동일 (atol=1e-5)config.v1_extensions에execution_modes/ode_rk4메타 보존- HF 훈련 25 step 동안 loss 감소 (plugin 미설치)
- 같은 훈련이
eulerstack.plugins.ttt임포트 후에도 loss 감소 (plugin 활성)
즉, "이걸 전부 한 번에 조합해도 compile → save_pretrained → train 이 정말
돌아간다" 가 자동 회귀 테스트로 매일 검증됩니다.
다음 단계
- 프리셋 학습 순서: 02_use_presets.md 의 v1 3-tier (Validated → Hybrid → Experimental) 권장
- 전체 primitive 런타임 상태: docs/architectures/runtime_primitive_status.md
- v1 스펙 정본: docs/architectures/yaml_v1_spec.md