Deep Dive카카오테크 원문 826과 연결 글 807·808·804, 카카오 공식 Hugging Face 3B·1.3B config 직접 확인. Node.js 24.17.0으로 공개 config의 BF16 KV cache를 재계산해 원문 표 3과 일치 확인

Kanana-2 SLM 개발기 해부: 3B를 0.9B로 줄이면서 32K 문맥을 남긴 방법

카카오 Kanana-2 SLM 개발기를 처음부터 끝까지 읽는다. 3B Base를 1.3B·0.9B로 압축한 PCA pruning과 cascade distillation, 3:1 hybrid SWA가 32K BF16 KV cache를 4GiB에서 1120MiB로 줄이는 정확한 계산, 모델 크기에 맞춰 갈라진 post-training·임베딩·Elastic Training 판단을 12살도 따라올 수 있는 비유와 재현 가능한 수식으로 풀어낸다.

On this page목차 50원문 Markdown ↗

이 글은 카카오테크의 더 작고 강해진 Kanana SLM 개발을 바닥부터 다시 읽고 쓴 해설이다. 원문은 2026-07-28에 공개됐다. 여기에는 원문이 직접 밝힌 사실, 카카오가 공개한 3B config1.3B config에서 확인한 사실, 그리고 그 숫자로 직접 계산한 내용을 따로 적었다. 카카오의 학습 코드·데이터·내부 평가셋은 공개되지 않았으므로, 공개 자료 밖을 재현했다고 말하지 않는다.

이 글을 다 읽으면 설명할 수 있는 것

이 글의 목표는 원문을 짧게 요약하는 데 있지 않다. 읽고 나서 아래 질문을 자기 말로 설명할 수 있어야 한다.

  • 3B, 1.3B, 0.9B는 무엇이 다르고, 왜 3B에서 바로 0.9B로 자르지 않았는가?
  • pruning은 단순히 가중치를 지우는 일인데, PCA rotation을 왜 먼저 하는가?
  • full attention과 Sliding Window Attention(SWA)은 답변을 한 token씩 만들 때 무엇을 다르게 읽는가?
  • 1.3B의 32K BF16 KV cache가 왜 full-only에서는 4GiB, 3:1 hybrid에서는 1120MiB가 되는가?
  • 작은 모델의 post-training에서 tool-call 데이터를 한꺼번에 많이 넣으면 왜 문제가 생길 수 있는가?
  • off-policy distillation, on-policy distillation, forward KL, rejection sampling, RL은 어느 순서로 어떤 문제를 푸는가?
  • 언어 모델을 embedding 모델로 바꾸는 일은 왜 attention mask와 pooling 방식을 다시 고르는 일인가?
  • 이 글을 쓴 뒤 카나나 팀에게 무엇을 더 물어봐야 하는가?

먼저 한 문장으로 잡자.

Kanana-2 SLM은 큰 모델을 작게 복사한 결과가 아니다. 좋은 3B 출발점, 단계적 압축, 긴 문맥에서 cache가 폭증하지 않게 하는 attention 구조, 작은 모델에서 지식이 지워지지 않게 하는 사후학습을 묶은 설계다.

먼저 보는 전체 지도

원문에 나온 흐름을 한 장으로 줄이면 아래와 같다.

30B-A3B Instruct teacher
             │
             ▼
3B Base: TPU 사전학습 → GPU distillation → 32K mid-training
             │
             ▼
3B → 2B → 1.3B → 0.9B
   PCA structured pruning + distillation
             │
    ┌────────┴────────┐
    ▼                 ▼
3B Instruct       1.3B / 0.9B Instruct
staged SFT         off-policy distillation
domain별 RL        on-policy distillation
merge/calibration  multi-domain RL
    │                 │
    └────────┬────────┘
             ▼
 1.3B·0.9B에는 3:1 hybrid SWA
 32K 문맥에서 KV cache와 decode read를 줄임

여기서 모델 계열을 먼저 분리해야 한다.

이름원문에서 맡는 역할
Base다음 token을 잘 맞히도록 만든 기본 언어 모델distillation과 후속 학습의 출발점
Instruct사용자의 지시·대화 형식·도구 호출에 맞게 다듬은 모델서비스에서 직접 쓰기 쉬운 assistant
Teacher더 큰 모델 또는 더 강한 모델student가 따라 배울 확률 분포와 응답을 제공
Student줄이거나 새로 학습하는 모델3B, 2B, 1.3B, 0.9B 계열
Embedding문장을 하나의 숫자 벡터로 바꾸는 모델검색·유사도 비교·RAG의 retrieval

원문은 3B·1.3B·0.9B를 개발 대상으로 설명한다. 다만 공개 배포는 3B와 1.3B의 Base·Instruct 네 모델이다. 카카오의 Hugging Face 조직 페이지와 Kanana-2-SLM collection에서 이 공개 범위를 확인했다. 0.9B는 원문에 성능과 학습 방법이 나오지만, 글을 작성한 시점에는 같은 공개 collection에서 내려받을 수 있는 Base/Instruct 항목으로 보이지 않는다.

아주 작은 사전: 뒤에서 계속 나오는 말

전문 용어를 한 번에 외울 필요는 없다. 아래 뜻만 잡고 본문으로 들어가면 된다.

token

모델이 읽고 쓰는 글자 조각이다. 한국어 한 문장이 몇 token이 되는지는 tokenizer가 정한다. 같은 문장을 더 적은 token으로 표현하면 읽을 양, 저장할 KV cache, 생성할 token 수가 함께 줄 수 있다. 원문은 Kanana-2 Tokenizer가 한국어 처리 효율을 기존 대비 30% 이상 높였다고 보고한다. 이 숫자는 문장 품질 30% 향상을 뜻하지 않는다. 같은 한국어를 얼마나 촘촘하게 쪼개는지에 관한 효율 수치다.

parameter

모델 안에 들어 있는 조절값이다. 모델이 읽고 배운 내용을 숫자로 압축해 저장한 자리라고 생각해도 된다. 3B는 대략 30억 개, 1.3B는 대략 13억 개라는 뜻이다. parameter가 적으면 가중치를 저장하고 일부 행렬 계산을 하는 비용은 줄어든다. 하지만 긴 대화의 속도까지 자동으로 빨라지는 것은 아니다. 그 차이를 만드는 대표적인 것이 KV cache다.

attention과 KV cache

답을 한 token씩 쓸 때 모델은 앞에서 읽거나 쓴 token들을 다시 참고한다. 각 token에서 만든 Key와 Value를 저장해 두는 메모가 KV cache다.

"민지는 파란 상자를 열었다. 그 안에는 ..."

마지막 빈칸을 만들 때 모델은 앞의 민지, 파란 상자, 열었다를 참고해야 한다. 매번 처음부터 계산하지 않으려고 Key·Value 메모를 저장한다. full attention은 과거 전체를 참고하고, SWA는 최근 window만 직접 참고한다.

pruning과 distillation

pruning은 이미 학습된 모델의 구조를 줄이는 일이다. 책장으로 치면 책장을 줄이되 중요한 책을 먼저 남기는 일에 가깝다. distillation은 큰 teacher의 답변과 token별 확률 분포를 보고 작은 student가 다시 배우는 일이다. 책장을 줄인 뒤에도 남은 책으로 일을 잘 하게 훈련하는 단계다.

pre-training, mid-training, post-training

pre-training   : 엄청난 양의 텍스트를 읽고 언어의 기본 규칙을 익힌다.
mid-training   : 긴 문맥, 특정 data mixture처럼 목표 능력에 맞춰 중간 조정한다.
post-training  : 지시를 따르고, 도구를 부르고, 안전하게 답하도록 다듬는다.

구분은 중요하다. pre-training의 지식, long-context의 위치 처리, post-training의 대화 형식은 같은 loss 하나로 생기지 않는다.

1부. 3B Base를 먼저 만드는 과정

TPU에서 9.5T token을 읽고, GPU에서 teacher를 붙였다

원문이 설명한 3B Base의 순서는 다음과 같다.

Stage 1 pre-training: 7.5T tokens
Stage 2 pre-training: 2T tokens
GPU teacher distillation
4K → 32K long-context training + LR decay mid-training

두 stage를 합치면 9.5T token이다. 원문은 TPU v5e cluster와 MaxText 기반 자체 framework에서 사전학습한 뒤, GPU cluster의 자체 Megatron-LM framework로 학습을 이어 갔다고 밝힌다. 여기서 핵심은 TPU와 GPU를 섞어 썼다는 사실보다, 같은 모델을 가속기와 framework가 바뀐 뒤에도 이어서 학습할 수 있는 운영 경로를 갖췄다는 점이다. 대규모 학습은 좋은 optimizer 하나만으로 끝나지 않는다. checkpoint가 이어지고, 수치가 깨지지 않고, data와 optimizer state가 맞아야 한다.

원문은 pre-training 전체 구간에 Muon Optimizer를 적용했다고 쓴다. 다만 이 글에는 Muon의 learning-rate, weight-decay, batch size, schedule 세부값이 없다. “Muon을 썼으니 성능이 이만큼 올랐다”라고 결론 내릴 근거는 공개되지 않았다. 여기서는 사용 사실까지만 기록하는 게 맞다.

100B proxy 실험으로 7.5T 학습률을 고른 방법

7.5T token을 실제로 돌리는 비용은 매우 크다. learning rate 후보를 하나씩 7.5T token으로 시험하는 일은 현실적이지 않다. 원문은 Stage 1과 같은 data distribution을 유지한 100B-token proxy run에서 후보 learning rate를 고른 뒤, Token Horizon scaling law로 본 학습 learning rate를 옮겼다.

원문이 인용한 식은 아래다.

[ LR^(D_{target}) \approx LR^(D_{proxy}) \left(\frac{D_{target}}{D_{proxy}}\right)^{-\beta} ]

  • (D_{proxy}=100B)
  • (D_{target}=7.5T=7500B)
  • (\beta=0.32)

여기서는 (D_{target}/D_{proxy}=75)다. 숫자를 그대로 넣으면 scaling factor는 (75^{-0.32}\approx0.251)이다. 다시 말해 proxy에서 찾은 최적 learning rate에 약 0.251을 곱하는 형태다.

proxy run에서 LR을 찾는다
→ token horizon이 75배 긴 본 학습에서는 더 낮은 LR로 옮긴다

긴 학습에서 같은 큰 learning rate를 오래 유지하면 update가 너무 거칠어질 수 있다. 이 식은 “학습을 오래 하면 LR을 조금 낮추자”라는 감각을 경험 법칙으로 만든 것이다. 원 논문도 더 긴 token horizon일수록 최적 LR이 작아지고, 짧은 run에서 긴 run의 LR을 추정할 수 있다고 보고한다. Scaling Optimal LR Across Token Horizons

여기서 주의할 점이 있다. 이 계산은 원문이 택한 (\beta)와 token 수를 넣은 산술 확인이다. 실제 Karana-2의 proxy LR 값은 공개되지 않았으므로 최종 LR 값을 재현한 것은 아니다.

왜 Base teacher보다 Instruct teacher가 좋았나

원문은 Kanana-2-30B-A3B의 Base, Instruct, Thinking을 각각 teacher로 두고 비교했다. 그 결과 3B student의 distillation 전 구간에서 Instruct teacher가 가장 좋았다고 보고한다. 실제 3B 학습에는 Kanana-2-30B-A3B-Instruct-2601을 teacher로 사용했다.

학생에게 답을 가르칠 때를 생각해 보자. Base teacher는 언어를 이어 쓰는 법을 아주 잘 아는 선생님이고, Instruct teacher는 질문을 읽고 형식에 맞춰 답하는 법까지 배운 선생님이다. 최종 학생이 service assistant라면 후자의 분포가 더 유용할 수 있다. 원문의 결과는 이 직관과 맞는다.

그렇지만 이유를 과장하면 안 된다. 원문은 Instruct teacher가 왜 이겼는지를 loss term별·domain별로 분해한 ablation을 공개하지 않았다. “post-trained teacher는 항상 better”도 아니다. 이 3B student, 이 data, 이 평가 조건에서 나온 결과다.

또 한 가지 구분이 있다. distillation은 teacher의 숨은 생각을 복사하는 기술이 아니다. 공개된 글만으로는 어떤 hidden state를 맞췄는지, 어떤 temperature나 KL loss를 썼는지 알 수 없다. 안전하게 말할 수 있는 것은 teacher의 출력 또는 logit 분포가 student 학습에 쓰였고, teacher 후보 중 Instruct가 이 조건에서 가장 좋았다는 것까지다.

4K에서 32K로: 길이만 늘린 것이 아니다

3B Base는 YaRN을 적용해 context length를 4K에서 32K로 늘리고, LR decay 구간에 mid-training data를 넣었다. 32K는 4K의 여덟 배다. 길이만 늘리면 과거 위치를 읽는 방식이 흔들릴 수 있으므로 position encoding을 함께 다뤄야 한다.

공개 3B config에는 다음이 적혀 있다.

hidden_size: 2560
num_hidden_layers: 32
num_attention_heads: 32
num_key_value_heads: 8
max_position_embeddings: 32768
rope_scaling: YaRN, original_max_position_embeddings 4096

config의 YaRN factor는 40이다. 이것을 “문맥을 정확히 40배 늘렸다”라고 읽으면 안 된다. config의 내부 scaling parameter이고, 실제 max position은 32768, 원래 길이는 4096이다. 원문에서 말한 service target은 4K에서 32K로 늘린 것이다.

2부. 3B를 1.3B와 0.9B로 줄이는 법

자르기 전에 무엇을 남길지 정한다

Transformer block을 아주 단순하게 그리면 이렇다.

token vector
   │
   ├─ attention: 다른 token에서 필요한 정보를 가져온다
   │
   └─ MLP: 지금 token 안에서 정보를 변환한다

모델을 줄일 때는 여러 축을 깎을 수 있다.

줄이는 축줄어드는 것직관
layer생각을 여러 번 고쳐 쓰는 단계 수책의 장을 통째로 빼는 일
hidden dimensiontoken vector의 폭한 장의 가로 폭을 줄이는 일
MLP intermediate dimensionblock 안의 확장 계산 폭작업대 넓이를 줄이는 일
attention head서로 다른 관점으로 보는 창 수여러 개의 시선을 줄이는 일

원문은 작은 모델을 만들기 전, hidden·MLP·head·layer를 어느 비율로 줄일지 후보를 만든 뒤 같은 조건에서 distillation 회복 속도를 비교했다. 이 순서가 좋다. parameter 수만 맞춰 놓고 구조를 감으로 고르면, 학습 뒤에 회복하지 못할 손실을 만든다.

기존 Index pruning의 한계

기존 hidden dimension pruning은 calibration data를 forward해 activation을 모으고, 좌표마다 importance score를 매긴다. 점수가 높은 dimension index만 남기는 방식이다. 빠르고 단순하다.

문제는 모델의 정보가 꼭 한 좌표에 한 가지씩 들어 있지 않다는 데 있다. 두 좌표가 함께 같은 정보를 나눠 담을 수 있다.

x축 하나만 보며 자르기
→ x1은 낮고 x2도 낮아 보여도, 둘을 합친 대각선 방향에는 중요한 정보가 있을 수 있다.

원문은 이 한계를 피하려고 Ministral 3의 PCA 기반 hidden-dimension pruning을 적용했다.

PCA rotation을 먼저 하는 이유

PCA는 데이터가 가장 크게 퍼진 방향을 찾는다. 교실 바닥에 구슬을 뿌렸는데 구슬이 왼쪽 아래에서 오른쪽 위로 길게 늘어섰다고 하자. 원래 가로·세로 눈금만 쓰면 중요한 방향이 두 축에 나뉘어 보인다. 바닥 눈금을 대각선 방향으로 돌리면 구슬이 대부분 첫 번째 축에 모인다.

hidden state도 같은 생각으로 다룬다.

1. calibration data로 RMSNorm input activation을 모은다.
2. PCA로 중요 방향을 앞쪽 좌표에 모으는 global rotation matrix를 만든다.
3. token embedding과 attention·MLP projection weight의 입출력에 같은 rotation을 적용한다.
4. 뒤쪽, 덜 중요한 좌표를 잘라 hidden width를 줄인다.

원문이 언급한 activation은 Attention RMSNorm input, MLP RMSNorm input, Final RMSNorm input이다. “같은 회전”을 embedding과 projection에 일관되게 적용하는 이유도 중요하다. hidden state의 좌표계만 돌리고 다음 layer weight를 그대로 두면, 모델이 읽던 방향과 쓰는 방향이 어긋난다. 회전은 좌표계를 바꾸는 일이고, pruning은 그 좌표계에서 뒤쪽 축을 버리는 일이다.

PCA 이후에는 attention head와 MLP intermediate dimension도 줄인다.

회전 뒤 activation 재수집
  → attention head importance 계산
  → KV group마다 top-k query head 선택
  → MLP의 SiLU(gate) × up activation으로 intermediate importance 계산
  → 필요한 intermediate dimension만 남김

원문 의사코드의 핵심은 이 순서다. hidden coordinate를 먼저 PCA로 정리한 뒤, 그 결과에서 head와 MLP를 평가한다. 세 pruning을 독립적인 가위질로 보지 않았다는 뜻이다.

Global MLP pruning과 layer-wise pruning

MLP intermediate dimension을 줄이는 방법도 두 가지다.

  • Global: 모든 layer의 score를 한데 더해 모든 layer에서 같은 index를 자른다.
  • Layer-wise: layer마다 score를 따로 구해, layer마다 다른 index를 자른다.

원문은 PCA 기반 pipeline에서 성능 차이가 거의 없었고, layer별 activation 특성을 반영할 수 있는 layer-wise를 골랐다고 쓴다. 더 복잡한 방법이 더 좋았다는 보고가 아니다. 차이가 없을 때는 더 유연하게 해석할 수 있는 쪽을 택했다는 architecture decision이다.

PCA가 실제로 더 좋았다는 검증

원문은 약 2B 규모 candidate 세 개에서 Index 방식과 PCA 방식을 비교했다. hidden pruning만 바꾸고 MLP·attention-head pruning은 같게 두었다. candidate는 hidden, MLP intermediate, query head를 다른 비율로 줄였다.

후보HiddenMLP intermediateQuery heads파라미터
Candidate 117927168322.05B
Candidate 217928064242.09B
Candidate 320486144242.01B

원문은 모든 candidate에서 PCA 방식이 Index 방식보다 distillation 초반부터 높고, 학습 전체에서 우세했다고 보고한다. attention head까지 줄인 Candidate 2·3에서 차이가 더 컸다. head capacity가 좁아질수록 hidden representation을 잘 보존하는 일이 더 중요했을 가능성이 있다는 해석이 원문에 나온다.

여기서 “PCA가 LLM pruning의 정답”이라고 말할 수는 없다. calibration data, target architecture, loss, teacher가 달라지면 결과도 달라진다. 이 실험이 분명히 보여 주는 것은 Kanana-2의 비교 조건에서는 coordinate index를 바로 고르는 것보다 중요한 방향을 회전으로 모아 둔 뒤 자르는 편이 나았다는 사실이다.

Width를 줄이고 layer와 query head를 남긴 이유

원문은 layer를 줄이는 후보도 Block Influence와 Norm Ratio로 평가했다. 그 결과 attention head를 줄인 구조의 성능 저하가 가장 컸고, layer pruning도 같은 parameter budget의 width-pruned 모델보다 낫지 않았다. 최종 pipeline은 layer 수와 query head를 유지하고 hidden·MLP width를 줄였다.

최종 구조는 아래와 같다.

모델HiddenMLP intermediateQuery headsLayers
3B256081923232
2B179271683232
1.3B128057603232
0.9B102446083232

3B와 1.3B 공개 config는 각각 hidden 2560·1280, 32 layer, 32 query head를 보여 준다. 원문 표 2와 맞는다.

한 가지는 기록해 둘 만하다. 원문 표 1의 candidate 비교에는 Kanana-2-3B baseline의 hidden이 2048로 적혀 있지만, 바로 뒤 표 2와 공개 3B config에는 2560으로 적혀 있다. 원문은 둘의 차이를 설명하지 않는다. 표 1이 다른 실험용 baseline인지, 표기 문제인지는 공개 자료만으로 확정할 수 없다. 이 글에서는 최종 표 2와 공개 config가 서로 일치하는 2560을 공개 3B 구조로 쓴다. 이 부분은 저자에게 물어볼 가치가 있다.

왜 3B에서 0.9B로 바로 내려가지 않았나

원문은 총 distillation token 수를 맞춘 뒤, 한 번에 3B에서 0.9B로 가는 single-stage와 3B → 2B → 0.9B two-stage cascade를 비교했다. two-stage가 distillation 시작부터 더 높은 성능을 보이고 끝까지 앞섰다. 최종 pipeline은 3B → 2B → 1.3B → 0.9B다.

비유하면 큰 피아노 곡을 초등학생 손 크기에 맞추는 일과 같다. 큰 곡에서 가장 어려운 부분을 한 번에 지우면 곡의 뼈대가 무너질 수 있다. 먼저 조금 쉬운 편곡을 만들고, 그 편곡을 다시 줄이면 다음 학생이 따라갈 거리가 짧아진다.

3B teacher → 0.9B student
: 한 번에 잃은 표현을 아주 작은 모델이 모두 회복해야 한다.

3B → 2B → 1.3B → 0.9B
: 매 단계의 teacher와 student가 더 가깝다.

NVIDIA의 Minitron 논문도 structured pruning과 knowledge distillation으로 여러 target 규모를 만들며 이런 문제를 다룬다. Kanana-2의 기여는 그 일반적인 방향을 그대로 가져온 것이 아니라, PCA rotation, width 선택, SWA, 작은 모델의 post-training까지 자체 실험으로 다시 연결한 데 있다.

물론 cascade에는 비용이 있다. 중간 모델마다 architecture search와 distillation을 해야 한다. 원문의 마지막 Elastic Training은 이 비용을 줄이려는 다음 단계다.

3부. SWA가 32K KV cache를 4GiB에서 1120MiB로 줄이는 정확한 이유

full attention은 매번 긴 장부를 다시 펼친다

답변을 만들 때 모델은 token 하나를 쓴다. full attention layer에서는 지금까지의 모든 token에 저장한 Key와 Value를 본다.

2K 문맥  → 2K token의 KV를 읽는다
8K 문맥  → 8K token의 KV를 읽는다
32K 문맥 → 32K token의 KV를 읽는다

문맥이 길수록 cache 메모리와 token당 읽기량이 같이 커진다. GPU server는 큰 batch와 높은 bandwidth로 이 비용을 나눠 가질 여지가 있지만, 휴대폰처럼 memory bandwidth가 작은 곳은 decode가 cache read에 묶이기 쉽다. 원문이 말하는 온디바이스 병목이다.

SWA는 최근 1024 token만 직접 본다

SWA layer는 모든 과거가 아니라 고정 window 안의 최근 token만 attention한다. Kanana-2-1.3B 공개 config에는 sliding_window가 1024로 들어 있다.

full layer:    과거 전체를 본다
sliding layer: 최근 1024 token만 본다

모든 layer를 sliding으로 바꾸면 cache는 훨씬 작아진다. 대신 문서 앞부분의 정보가 직접 attention 범위 밖으로 나간다. 원문은 이를 피하려고 32개 layer 중 24개는 sliding attention, 매 네 번째인 8개는 full attention으로 둔다.

S S S F  S S S F  S S S F  S S S F
S S S F  S S S F  S S S F  S S S F

여기서 S는 sliding, F는 full이다. 공개 1.3B config의 layer_types 배열도 정확히 이 순서를 보여 준다. 그래서 “3:1 hybrid”는 말만 3:1인 구성이 아니라, 24 sliding layer와 8 full layer라는 실제 배치다.

원문 표 3을 config만으로 재현하기

원문 표 3은 BF16 1.3B에서 full-only와 SWA:Full = 3:1의 KV cache를 비교한다.

문맥 길이Full-only3:1 hybrid원문 절감률
2K256MiB160MiB37.5%
8K1024MiB352MiB65.6%
32K4096MiB1120MiB72.7%

이 표는 공개 config의 숫자로 정확히 계산된다.

  1. 1.3B config에는 KV head 8개, head dimension 128, BF16 원소 2 byte가 있다.
  2. token 하나가 layer 하나에 남기는 K와 V의 cache는 두 개다.
  3. token당·layer당 cache는 (2 \times 8 \times 128 \times 2 = 4096) byte, 곧 4KiB다.

full-only 32K라면 32개 full layer가 32768 token을 전부 저장한다.

[ 32 \times 32768 \times 4096;bytes = 4294967296;bytes = 4096;MiB = 4;GiB ]

3:1 hybrid 32K에서는 full 8개 layer가 32768 token을 저장하고, sliding 24개 layer는 각자 1024 token만 저장한다.

[ (8 \times 32768 + 24 \times 1024) \times 4096;bytes = 1174405120;bytes = 1120;MiB ]

직접 실행한 계산은 다음과 같다.

const bytesPerTokenPerLayer = 2 * 8 * 128 * 2;
const fullOnly = 32 * 32768 * bytesPerTokenPerLayer;
const hybrid = (8 * 32768 + 24 * 1024) * bytesPerTokenPerLayer;
console.log(fullOnly / 2 ** 20, hybrid / 2 ** 20);

4096 1120

절감률은 (1 - 1120/4096)으로 72.65625%, 반올림하면 원문의 72.7%다. 2K와 8K도 같은 식으로 160MiB와 352MiB가 나온다.

이 검산은 꽤 중요하다. 원문의 표를 믿고 옮겨 적은 것이 아니라, model config의 layer count·KV head·head dimension·window·BF16을 모두 넣었을 때 같은 값이 나온다. full layer가 8개라는 사실과 KV head가 8개라는 사실이 빠지면 이 숫자는 맞지 않는다.

이 계산이 말하지 않는 것

1120MiB는 KV cache만의 값이다. model weight, activation buffer, runtime workspace, allocator fragmentation, 앱과 OS 메모리는 들어 있지 않다. quantization을 쓰면 weight와 KV cache가 같은 비율로 줄어든다는 보장도 없다. 이 값으로 “1.3B가 어떤 휴대폰에서 32K를 반드시 지원한다”고 말하면 안 된다.

또 cache를 줄였다고 모든 응답이 72.7% 빨라지는 것도 아니다. prefill compute, MLP 계산, memory bandwidth, runtime kernel, generated output 길이가 함께 걸린다. 원문이 직접 보고한 것은 cache 절감이다. 실제 tokens/s와 전력은 기기·runtime별 측정이 필요하다.

window 1024는 왜 골랐나

원문은 1.3B에서 3:1 비율을 고정하고 window 128, 512, 1024를 비교했다. 2B·1.3B·0.9B 각 단계에서 300B token 규모 distillation을 수행했고, teacher는 30B-A3B-Instruct-2601, loss는 KL divergence만 사용했다.

window 128은 full attention보다 성능 격차가 뚜렷했다. window를 키울수록 full에 가까워졌고, 1024는 학습 전 구간과 RULER-4K에서 full과 거의 비슷했다고 원문은 보고한다.

이건 “1024가 모든 모델의 정답”이라는 뜻이 아니다. window는 세 비용 사이의 협상값이다.

window를 작게 잡는다
→ cache와 decode read는 줄어든다
→ 가까운 문맥밖에 직접 못 보니 품질을 잃을 수 있다

window를 크게 잡는다
→ 품질은 full attention에 가까워진다
→ cache 절감은 작아진다

내 서비스가 코드 파일 20K 줄 앞의 함수 선언을 자주 참조한다면 RULER-4K만으로 충분하지 않다. 문서 앞·중간·끝에 필요한 정보를 심은 실제 업무 평가를 따로 만들어야 한다.

32K position 처리: full layer와 sliding layer를 같게 늘리지 않았다

원문은 long-context training에서 full attention layer에만 YaRN을 적용하고 SWA layer에는 기존 RoPE를 유지했다고 쓴다. full layer는 먼 위치까지 읽어야 하므로 4K 밖의 위치 처리가 필요하다. sliding layer는 최대 1024 window 안에서만 직접 동작하니 기존 local position 표현을 유지하는 편이 자연스럽다.

이 선택은 context length를 키우는 일이 config의 max_position_embeddings 숫자 하나를 바꾸는 일이 아니라는 점을 보여 준다. attention mask, layer 종류, position encoding, long-context data가 한 세트다.

long-context data도 작은 모델에 맞춰 다시 섞었다

원문은 일부 한국어 long-context data의 noise가 작은 모델에 더 크게 영향을 준다고 보고한다. 그래서 해당 데이터 비중을 줄이고 Math·Code·영어 비중을 높였다. 이 재조정은 RULER-32K와 전체 성능 향상에 도움이 됐다고 한다.

여기서 얻을 수 있는 교훈은 단순하다. “한국어 data를 많이 넣으면 한국어가 좋아진다”는 말만으로는 부족하다. data의 길이, noise, 모델 용량, 목표 task가 같이 움직인다. 0.9B처럼 작은 모델은 noise를 흡수할 표현 여유가 더 적을 수 있다.

4부. Base 모델 성능표를 읽는 법

원문은 아래 Base 성능을 보고한다. shot 수가 다르므로 행끼리 점수를 단순 비교하면 안 된다. 같은 benchmark·같은 shot·같은 모델 크기 안에서 읽어야 한다.

평가3B1.3B0.9B
MMLU 5-shot62.7756.4953.72
MMLU-Pro 5-shot36.5429.8727.11
BBH 3-shot54.2345.5840.87
SimpleQA 5-shot27.3923.7621.34
KMMLU 5-shot47.9244.1740.58
HAERAE 5-shot80.6675.3471.22
KoSimpleQA 5-shot32.5028.5024.90
MATH 4-shot35.0830.8227.68
MBPP 3-shot50.9544.8637.56

점수표가 보여 주는 방향은 분명하다. 모델이 작아질수록 모든 지표가 대체로 내려간다. 1.3B와 0.9B는 3B와 같아지지 않는다. SLM 설계의 목표는 손실을 마법처럼 없애는 게 아니라, 기기 예산 안에서 손실이 감당 가능한 모델을 만드는 일이다.

표가 말하지 않는 것도 있다. latency, peak memory, battery, tool-call 성공률, hallucination, 한국어 업무 문서 품질, 안전성은 이 표만으로 알 수 없다. Base benchmark가 좋은 것과 실제 assistant 제품이 좋은 것은 서로 다른 시험이다.

5부. post-training: 작은 모델이 서비스 문법을 배우는 과정

3B는 staged SFT에서 시작했다

3B Instruct는 여러 open-source SFT dataset으로 supervised fine-tuning을 한 뒤, Instruction Following·Math·Code·Tool·Chat·Knowledge domain별 RL을 수행했다. 각 domain expert를 병합하고 calibration하는 흐름이다.

원문이 특히 강조한 문제는 catastrophic forgetting이다. 작은 모델은 새로운 tool-call data 비중이 갑자기 커지면, 전에 배운 일반 대화나 지식 일부를 잃을 수 있다. 그래서 tool-call data를 처음부터 많이 넣지 않고, 낮은 비중에서 시작해 점차 올리는 staged SFT를 썼다. SFT에는 32K sequence packing도 적용했다.

tool-call data를 한 번에 많이 넣기
→ 도구 형식은 잘 맞을 수 있다
→ 작은 모델의 제한된 parameter 공간에서 기존 능력과 충돌할 수 있다

staged SFT
→ 새 형식을 조금씩 섞는다
→ stage마다 기존 능력 회귀를 확인할 여지가 생긴다

이 설명은 tool-call data가 나쁘다는 뜻이 아니다. data mixture의 변화 속도도 hyperparameter라는 뜻이다.

DAPO를 domain별 RL에 쓴 이유

원문은 3B의 domain expert를 만들 때 GRPO 대신 DAPO를 사용했다. DAPO는 Decoupled Clip and Dynamic Sampling Policy Optimization의 약자다. 원문이 든 핵심 요소는 네 가지다.

DAPO 요소쉽게 말하면원문이 연결한 목적
Dynamic Sampling너무 쉽거나 너무 어려워서 배울 게 없는 문제 묶음을 빼고, gradient가 있는 묶음으로 batch를 채움학습 자원 낭비와 수렴 지연 축소
Clip-Higher좋은 방향으로 확률을 크게 올리는 update를 너무 일찍 막지 않음entropy collapse를 줄이고 탐색 유지
Token-level PG loss답 전체를 한 덩어리로만 보지 않고 token별 update를 다룸긴 답변에서 더 세밀한 교정
Overlong penalty불필요하게 긴 응답에 감점온디바이스의 생성 비용·응답 길이 제어

Clip-Higher는 “무조건 길고 다양한 답을 만들자”는 규칙이 아니다. 원래 policy와 새 policy의 확률 비율을 clip할 때 상한을 넓혀, 좋은 update가 너무 빨리 막히지 않게 하는 장치다. DAPO 원문도 entropy collapse, zero-gradient prompt group, 긴 CoT에서 token-level loss 문제를 핵심 과제로 든다.

Overlong penalty도 답을 짧게만 만들자는 말이 아니다. 답이 길어야 풀리는 문제와 의미 없이 반복하는 답을 구분해야 한다. 원문은 정확한 penalty 계수나 도메인별 길이 분포를 공개하지 않았으므로, 이 모델이 실제로 어느 길이에서 얼마나 감점을 받았는지는 알 수 없다.

domain expert를 합친 뒤 calibration한 이유

원문 표 5에는 3B Instruct의 stage별 domain score가 나온다.

| Stage | IF | Math | Code | Tool | Chat | Knowledge | Macro Avg. | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | SFT | 44.93 | 47.64 | 62.56 | 71.51 | 40.73 | 39.63 | 46.18 | | Merge | 62.39 | 56.18 | 61.61 | 65.84 | 46.17 | 41.46 | 50.95 | | Calibration | 62.56 | 57.05 | 61.31 | 71.94 | 47.58 | 40.74 | 51.52 |

병합 뒤 Code는 SFT보다 낮고 Tool도 낮아진다. calibration 뒤 Tool은 크게 회복한다. 이 표 때문에 merge를 “좋은 checkpoint를 합치면 모든 과목이 동시에 오른다”는 마법으로 읽으면 안 된다. domain별 update는 서로 같은 parameter를 다른 방향으로 밀 수 있다.

원문은 정답 rollout만 필터링하고, domain별 sample 수를 균등하게 맞췄다. model merging에는 SCE(Select, Calculate, Erase)를 쓰고, expert rollout과 소량 held-out data로 calibration했다. 세부 SCE hyperparameter는 원문에 없다. 공개된 사실은 병합 뒤에도 calibration을 별도 단계로 두었고, 표에서 그 필요성을 확인할 수 있다는 것이다.

왜 1.3B·0.9B에는 같은 3B recipe를 그대로 쓰지 않았나

더 작은 모델에서는 3B에 쓴 parallel RL이 불안정하고 성능 향상이 유의미하지 않았다고 원문은 쓴다. parameter가 적을수록 domain expert를 따로 학습해 병합할 때 간섭과 weight conflict가 심해졌기 때문이다. 작은 모델은 multi-domain RL로 여러 domain을 한 policy에서 함께 학습했다.

이 판단은 꽤 현실적이다. 모델이 작을수록 여러 능력을 각각 완벽히 담을 빈 공간이 적다. 여섯 개의 expert를 따로 만들고 나중에 섞는 방식은 각 능력을 밀어 넣는 update가 부딪힐 가능성을 키운다. 함께 학습하면 최적화 난이도는 다르지만, 병합이라는 큰 충돌 지점을 피할 수 있다.

6부. 작은 모델의 distillation은 왜 두 번 나뉘나

off-policy distillation: student가 아직 만들지 않은 답을 먼저 배운다

1.3B·0.9B는 teacher rollout을 사용한 off-policy distillation부터 한다. prompt set은 다음 on-policy 단계의 데이터와 겹치지 않게 뒀다. 목적은 두 가지다.

  • chat template에 맞는 답변 형식을 student가 먼저 익히게 한다.
  • teacher와 student의 분포 차이를 줄여, on-policy 초반 rollout 품질과 학습 안정성을 확보한다.

off-policy에서는 teacher의 답이 student parameter와 무관하게 이미 정해져 있다. 원문은 이 경우 teacher 답을 매 step online으로 다시 만들 필요가 없다고 판단했다. online generation은 decode-bound이고, 긴 응답이 batch에 끼면 다른 GPU가 기다린다. degenerate response가 나오면 필터링·재생성 동안 idle time도 생긴다.

그래서 teacher 답을 미리 생성하고, 반복 같은 degenerate response를 걸러 남은 샘플로 학습했다. 여기서 “사전 생성이 언제나 더 낫다”라고 일반화하면 안 된다. teacher가 학습 중 바뀌거나, student 상태에 따라 prompt를 고르는 adaptive training이라면 online generation에 새 정보가 생길 수 있다. 원문의 논리는 fixed teacher distribution을 쓰는 off-policy stage에 한정된다.

on-policy distillation: student가 실제로 틀리는 자리에서 배운다

on-policy에서는 student가 rollout을 만들고, 그 student가 실제로 밟은 경로에서 teacher의 교정을 받는다. 이미 잘 쓴 teacher 답만 베끼는 것보다, student가 어느 token에서 흔들리는지 직접 보게 된다. 이것이 exposure bias를 줄이는 핵심이다.

원문은 forward KL을 택했다. 두 KL을 기호로만 보면 어렵지만, 방향을 보면 된다.

[ D_{KL}(p_{teacher};||;p_{student}) ]

forward KL은 teacher가 확률을 준 여러 선택지를 student가 넓게 덮도록 압박한다. teacher가 가능하다고 본 답을 student가 0에 가깝게 두면 큰 벌을 받는다.

[ D_{KL}(p_{student};||;p_{teacher}) ]

reverse KL은 student가 높은 확률을 준 답이 teacher와 어긋나는 일을 강하게 막는다. 한두 mode에 집중하는 방향이 되기 쉬워 Pass@1에는 도움이 될 수 있지만, 분포의 폭과 entropy가 줄 수 있다.

Kanana-2의 작은 모델 pipeline은 on-policy 뒤에 RL을 둔다. 원문은 이때 reverse KL로 분포를 너무 일찍 날카롭게 만들면, RL이 탐색 중 정답을 만날 기회인 Pass@K를 줄일 수 있다고 판단했다. 그래서 forward KL로 “탐색 여지가 남은 RL 시작점”을 만들었다.

이 논리는 설득력 있지만 조건부다. RL 없이 바로 배포할 모델, Pass@1이 유일한 목표인 모델, reward가 불안정한 모델에서는 선택이 달라질 수 있다. 원문은 자기 pipeline의 목적에 맞춘 선택을 설명한다.

rejection sampling을 하지 않은 이유

rejection sampling은 정답 rollout만 남기는 방식이다. 직관적으로는 깨끗한 data만 남기니 좋아 보인다. 원문은 하지 않았다.

teacher logit은 token마다 dense한 감독 신호를 준다. student가 끝까지 정답에 못 갔어도, 처음 틀린 token부터 teacher가 다른 확률을 줬다면 고칠 정보가 있다. 실패 trajectory를 다 버리면 student가 실제로 실패하는 길을 배우는 on-policy의 장점이 줄어든다. 정답 여부는 다음 RL 단계의 verifiable reward가 다루게 했다.

이것도 “실패 sample은 모두 보관하자”는 규칙이 아니다. 원문도 off-policy에서 repetition처럼 degenerate한 teacher 응답은 필터링했다. 실패가 학습 신호인지, noise인지, 안전상 제거해야 할 sample인지는 data pipeline과 reward 정의가 결정한다.

7부. Decoder-only SLM에서 embedding 모델까지

원문의 마지막 큰 덩어리는 Kanana-2-Embedding이다. 생성 모델과 embedding 모델은 출력 모양부터 다르다.

생성 모델: 다음 token의 확률을 낸다.
embedding 모델: 문장 전체를 한 vector로 바꾼다.

검색에서는 query vector와 document vector가 가까울수록 좋은 문서를 찾는다. 여기서 “가깝다”는 보통 cosine similarity로 계산한다.

마지막 token 하나를 쓸까, 모든 token을 평균 낼까

원문은 decoder-only SLM을 embedding으로 바꾸며 두 초기화를 비교했다.

방법attention문장 vector를 만드는 법
Causal + Last Pool왼쪽 token만 봄마지막 EOS token의 hidden state
Bidirectional + Mean Pool모든 token이 서로 봄모든 token hidden state 평균

첫 방법은 원래 decoder 구조를 거의 그대로 쓴다. 둘째 방법은 attention mask를 bidirectional로 바꿔 문장 안의 모든 token이 서로를 읽게 한 뒤 평균을 낸다. 원문에서는 retrieval task에서 둘의 차이가 컸고, 학습이 갈수록 Bidirectional + Mean Pool이 Causal + Last Pool을 앞섰다. 최종 모델은 전자를 택했다.

왜 그럴까? 검색 vector는 문장 전체의 뜻을 하나의 점으로 압축해야 한다. 마지막 token 하나에 모든 요약 부담을 주는 것보다, 모든 token이 양방향으로 문맥을 섞고 평균을 낸 쪽이 retrieval에 유리할 수 있다. 이것은 원문 결과를 이해하기 위한 해석이다. 모든 embedding task와 모든 decoder model에서 항상 그렇다는 법칙은 아니다.

contrastive loss: 무엇을 서로 멀리 밀어 냈나

원문은 InfoNCE 계열 네 loss를 비교했다.

loss비교에 넣은 관계
In-batch NCEquery-positive document, document-hard negative
GISTq-d, q-q, d-d, d-hard negative
HN-onlydocument-hard negative만
KaLMq-d, d-hard negative, q-synthetic

여기서 hard negative는 정답처럼 보이지만 실제로는 틀린 문서다. 검색 모델이 가장 많이 헷갈리는 상대다.

직관과 달리 원문에서는 가장 적은 비교 항을 둔 HN-only가 hard-negative 개수와 관계없이 가장 좋았다. global batch size는 2048이고, 여러 GPU의 batch 사이 유사도를 계산할 때 GradCache를 썼다. 이 결과를 “negative가 적을수록 항상 좋다”로 읽으면 안 된다. 원문 모델과 data에서 decoder-only model에 이미 있는 embedding 능력을 끌어내는 데 hard negative가 가장 강한 신호였다는 결과다.

temperature 0.02는 무엇을 바꾸나

cosine similarity는 -1부터 1 사이에 있다. 이 값을 softmax 앞에서 temperature로 나누면 작은 temperature일수록 차이가 더 크게 보인다.

[ \text{score} = \frac{\cos(q,d)}{\tau} ]

(\tau)가 0.05에서 0.02로 작아지면, 어려운 negative와 positive의 작은 차이가 loss에 더 크게 반영된다. 원문은 temperature 0.02가 0.05보다 조금 더 좋았다고 보고한다.

Hard negative 수영어 향상폭한국어 향상폭
7+0.51%p+0.46%p
9+0.99%p+0.37%p

이 표의 Δ는 0.02에서 0.05를 뺀 값이 아니다. 원문 설명대로 0.05 대비 0.02의 성능 상승폭이다. 부호와 기준을 뒤집어 읽지 말아야 한다.

최종 embedding recipe는 Bidirectional + Mean Pool, HN-only, temperature 0.02, query당 hard negative 9개다. 3B embedding에서 1.3B·0.9B embedding으로는 distillation을 했다. MRL(Matryoshka Representation Learning)은 full dimension뿐 아니라 1024, 512, 256, 128, 64처럼 vector 앞부분만 잘라서도 쓸 수 있게 학습하는 방식이다. 작은 dimension으로 검색해 memory와 similarity 계산을 줄이고, 필요할 때 큰 dimension을 쓰려는 설계다.

원문은 0.9B embedding의 MRL 512가 이전 8B embedding보다 한국어에서 좋았다고 보고한다. 이 수치는 특정 evaluation과 MRL setting의 결과다. 내 RAG index에서 512 dimension이 충분한지는 corpus·chunking·reranker·filter와 함께 다시 재야 한다.

8부. 다음 문제: model family를 매번 따로 만들지 않는 Elastic Training

Cascade는 품질 회복에는 도움이 되지만, 모델 크기마다 세 일을 반복한다.

1. 출발 Dense model을 만든다.
2. target size의 architecture search를 한다.
3. target size마다 pruning과 distillation을 한다.

target model이 많아지면 비용도 거의 선형으로 늘어난다. 원문은 NVIDIA의 Nemotron Elastic과 Star Elastic을 다음 방향으로 소개한다.

큰 parent student 하나 안에
3B, 2B, 1.3B, 0.9B sub-model을 nested로 넣고
weight를 공유하며
한 학습 안에서 여러 budget을 같이 최적화한다.

Nemotron Elastic은 router 기반 architecture search와 nested distillation을 결합한다. 원문은 먼저 router 없이 nested distillation만 시험했다. 내부 개선 30B-A3B-Instruct-2601을 teacher, 3B Base를 parent student로 두고, cascade에서 고른 pruning configuration을 고정했다. 하나의 3B 안에 2B·1.3B·0.9B sub-model을 넣어 동시에 distillation했다.

그 결과 모든 sub-model이 학습과 함께 개선됐고, 기존 cascade로 따로 학습한 같은 크기 모델과 큰 성능 차이가 없었다고 원문은 보고한다. 아직 “router까지 포함한 Elastic Training이 Kanana SLM에서 끝났다”는 말은 아니다. 원문은 현재 router 기반 architecture search까지 결합하는 연구를 이어 간다고 적는다.

이 방향의 매력은 명확하다. 기기별 model family가 여섯 개 필요할 때 여섯 번 전부 학습하지 않고, 하나의 parent 안에서 여러 budget을 만들 수 있다. Nemotron Elastic 원문도 nested submodel과 shared weight로 여러 deployment budget을 다루는 방식을 제안한다. 다만 nested model의 간섭, router 안정성, 각 sub-model의 독립 배포 성능은 별도의 검증 대상이다.

전문가와 대화할 때 꺼낼 질문

원문을 제대로 읽었다면 “좋은 SLM이네요”보다 구체적인 질문이 나와야 한다. 아래 질문은 공개 글에서 답이 명확하지 않거나, 다음 실험을 설계할 때 중요한 지점이다.

  1. 표 1의 3B hidden 2048과 표 2·공개 config의 hidden 2560은 서로 다른 baseline인가?
  2. 3B pre-training distillation에서 정확히 어떤 loss, temperature, teacher-logit 처리, data mixture를 썼는가?
  3. PCA rotation은 calibration data의 domain·길이·sample 수에 얼마나 민감한가?
  4. Query head와 layer를 유지한 width-pruning 선택은 1.3B·0.9B 외 target size에서도 유지되는가?
  5. 1024 window가 RULER-4K에서는 full과 비슷했는데, 32K에서 needle 위치별·한국어 문서별 failure curve는 어떤가?
  6. 3:1 hybrid에서 full layer를 네 번째마다 둔 이유는 무엇인가? 같은 8개 full layer를 앞·중간·뒤에 몰아 두는 배치와 비교했는가?
  7. BF16 KV cache는 config로 재현된다. 실제 target phone에서 quantized weight와 KV cache precision을 포함한 peak memory·tokens/s·전력은 얼마인가?
  8. staged SFT의 tool-call 비중 schedule과 catastrophic forgetting을 판정한 domain별 regression set은 무엇인가?
  9. forward KL을 쓴 on-policy distillation에서 Pass@1, Pass@K, entropy가 stage별로 어떻게 움직였는가?
  10. HN-only embedding loss가 우세했던 이유는 data 중복, hard-negative 품질, decoder initialization 중 어느 쪽의 영향이 큰가?

이 질문들은 흠을 잡기 위한 목록이 아니다. 공개된 개발기를 실제 학습 recipe와 배포 계획으로 바꾸려면 꼭 메워야 하는 빈칸이다.

이 글에서 확실히 아는 것과 아직 모르는 것

마지막으로 선을 긋는다.

공개 자료로 확인한 것

  • 3B는 TPU v5e와 MaxText로 7.5T + 2T token pre-training을 거쳤다.
  • 100B proxy에서 LR을 찾고 Token Horizon scaling을 적용했다.
  • teacher 후보 비교에서 Instruct가 가장 좋았고, 30B-A3B-Instruct-2601이 3B distillation teacher다.
  • PCA-based structured pruning, 3B → 2B → 1.3B → 0.9B cascade, 1.3B·0.9B의 SWA가 원문에 명시돼 있다.
  • 공개 1.3B config는 32 layer, 24 sliding + 8 full, window 1024, KV head 8, head dimension 128이다.
  • 이 config와 BF16만으로 원문 표 3의 256/1024/4096MiB와 160/352/1120MiB를 재현한다.
  • 3B와 작은 모델의 post-training recipe가 다르며, embedding까지 별도 실험을 했다.

공개 자료로는 모르는 것

  • 학습 data 원문과 정확한 mixture, token 품질 필터
  • exact loss coefficient, LR schedule 전체, batch·parallelism, training wall time
  • teacher logit 처리 방식과 distillation temperature
  • mobile device별 memory, power, first-token latency, decode tokens/s
  • benchmark별 prompt template과 failure example
  • safety, privacy, hallucination을 실제 서비스에서 어떻게 측정하는지

이 구분이 있어야 기술 글이 광고도, 추측도 되지 않는다.

마무리

Kanana-2 SLM 개발기를 읽고 가장 크게 남은 것은 “작은 모델”이라는 말이 너무 많은 것을 숨긴다는 사실이다. 3B를 0.9B로 만든다고 해서 model file만 줄어드는 게 아니다. 중요한 hidden 방향을 남겨야 하고, 중간 크기 teacher를 거쳐야 하고, 긴 대화에서 매 token마다 읽는 cache의 상한도 만들어야 한다. 그 뒤에는 tool-call data가 기존 지식을 지우지 않게 섞고, 작은 모델이 감당할 수 있는 RL 방식을 다시 골라야 한다.

원문의 3:1 SWA는 그 연결을 가장 선명하게 보여 준다. 32K BF16 KV cache를 4GiB에서 1120MiB로 줄인다는 문장은 멋진 수사가 아니다. 32 layer, 8 KV head, head dimension 128, 24 sliding layer, 8 full layer, window 1024를 넣으면 정확히 나오는 설계 결과다.

다음 검증은 공개 3B·1.3B를 같은 runtime과 같은 한국어 prompt set에서 돌리는 일이다. tokenizer 길이, 2K·8K·32K first-token latency, steady-state tokens/s, peak memory, 앞부분 회수 실패를 한 표에 놓고 봐야 한다. 그때 이 개발기의 architecture decision이 내 제품의 선택으로 바뀐다.

참고 자료

대화

댓글

0
댓글을 불러오는 중입니다.