<p align="center">
<img src="https://raw.githubusercontent.com/ariannamethod/nanollama/HEAD/assets/logo.png" alt="nanollama" width="200">
</p>
<h1 align="center">NANOLLAMA</h1>
<p align="center"><b>by Arianna Method</b></p>
Llama 3 모델을 처음부터 학습시키세요. 어떤 규모, 어떤 개성도 가능합니다.
새로운 사용자이신가요? Beginner's Guide를 읽어보세요. ML 경험 없이도 첫 LLM을 빠르게 학습시킬 수 있습니다.
이것은 무엇인가요 (What This Is)
anollama는 원시 텍스트(raw text)로부터 Llama 3 아키텍처 모델을 학습시키기 위한 프레임워크입니다. 파인튜닝(fine-tuning), 어댑터 래핑(adapter wrapping), 또는 Meta 가중치 기반의 LoRA를 사용하는 방식이 아닙니다. 근본부터 시작합니다. 당신의 데이터, 당신의 모델, 당신의 개성입니다.
전체 파이프라인은 다음과 같습니다:
- 데이터 준비 (FineWeb-Edu)
- 처음부터 사전 학습 (Pretraining from scratch) (Python + Muon optimizer)
- LoRA 개성 파인튜닝 (rank 64, per-voice adapters)
- Gamma 추출 ($\gamma$ = 개성 가중치 − 기본 가중치)
- GGUF v3 내보내기 (llama.cpp 호환)
- 독립형 Go 추론 엔진 (zero dependencies, ~9MB binary)
원래 nanochat에서 포크(forked)되었습니다. Karpathy의 작업은 legacy/에 있으며 모든 크레딧을 유지합니다. 학습 스크립트, 모델 아키텍처, 옵티마이저, 추론 엔진, 개성 시스템 및 GGUF 내보내기는 독창적입니다.
모델 티어 (Model Tiers)
모든 언타이드 임베딩(untied embeddings)을 사용하며, head_dim=64입니다. nano/micro의 경우 MHA (kv_heads = heads), mini+의 경우 GQA를 사용합니다.
| Name | Layers | Dim | Heads | KV Heads | FFN | Params | Languages |
|---|
| nano | 13 | 576 | 9 | 9 | 1536 | 89M | EN |
| ... | | | | | | | |
| FFN dim = round_up(8 × n_embd / 3, 256). | | | | | | | |
점진적 다국어 토크나이저 티어 (Progressive multilingual tokenizer tiers) (goldie 이상):
| Tier | Model | Vocab | Languages |
|---|
| — | nano–small | 32K | English only |
| ... | | | |
빠른 시작 (Quick Start)
아키텍처 (Architecture)
표준 Llama 3 — llama.cpp와 완벽하게 호환됩니다.
| 기능 (Feature) | 기본값 (Default) | 설명 (Description) |
|---|
| RMSNorm | 학습 가능 (Learnable) | x / RMS(x) * scale, 채널별 가중치로 학습됨 |
| ... | | |
| Optional extensions (기본적으로 모두 비활성화): | | |
--use-qk-norm
--use-post-emb-norm
--use-resformer
...
모델 정의: nanollama/llama.py (~400줄).
학습 데이터 (Training Data)
모든 티어에 대해 FineWeb-Edu를 사용합니다. 초기에는 ClimbMix (Karpathy가 선별한 400B 토큰 혼합, nanochat에서 사용됨)을 시도했으나 — 손실은 nanochat 기준선과 일치했지만 생성 품질이 낮았습니다. 우리는 더 이상 조사하지 않고, 동일한 손실 값에서 더 나은 텍스트를 생성하는 FineWeb-Edu로 전환했습니다.
다국어 모델 (goldie+)의 경우, FineWeb2-HQ 언어 샤드를 추가합니다.
데이터는 메모리 매핑된 바이너리 샤드 (uint16, 샤드당 약 20MB, 각 샤드당 약 10M 토큰)로 토큰화됩니다.
토크나이저 (Tokenizer): SentencePiece BPE, 32K 어휘집 크기 (nano–small).
python -m data.prepare_fineweb --num-samples 10000000
LoRA를 통한 개성 부여 (Personality via LoRA) ($ heta = ext{ε} + ext{γ}$)
기본 모델을 한 번만 학습시키고, LoRA를 통해 개성을 추가합니다 — 이중 학습이나 가중치 빼기가 필요 없습니다.
ε = 기본 모델 (FineWeb-Edu로 한 번 학습됨)
γ = LoRA 가중치 (개성 데이터로 몇 분 만에 학습됨)
θ = ε + γ (추론을 위해 병합하거나 별도로 유지)
작동 방식
LoRA는 어텐션(attention) 및 MLP 투영(projection)을 대상으로 하며, 나머지 모든 것을 동결합니다. 약 9%의 학습 가능한 매개변수만 사용됩니다. 하나의 기본 모델에 여러 개성 — Leo, Arianna, Yent — 을 추가할 수 있으며, 각각은 작은 LoRA 어댑터 파일입니다.
SFT(Supervised Fine-Tuning) 데이터 형식: Human/AI 일반 텍스트. JSONL 형식이 아닙니다. 기본 모델은 연속적인 웹 텍스트로 학습되었으며 'User:' / 'Assistant:'와 같은 마커를 본 적이 없습니다. 역할 마커가 포함된 JSONL 형식은 손실(loss)을 약 4.7로 증가시킵니다 (랜덤). 반면, Human: ... AI: ... 마커가 있는 일반 텍스트는 모델이 학습할 수 있는 연속적인 텍스트이기 때문에 작동하며, 손실은 2.66으로 감소합니다.
python -m scripts.chat_sft \
--base-checkpoint checkpoints/nano/checkpoint_step20000.pt \
...
기존 방식 (legacy)
이전 방법은 모델을 두 번 훈련해야 했습니다. 즉, 성격(personality) 없이 한 번, 성격을 가지고 한 번 훈련한 후 빼는 방식이었습니다:
γ = θ_with_personality − θ_without_personality
이는 비효율적이었습니다. 동일한 기본 모델과 데이터로 GPU 비용을 두 배로 소모했습니다. LoRA는 단 한 번의 기본 훈련과 몇 분간의 SFT만으로 동일한 결과(이식 가능한 성격 벡터)를 달성합니다. 레거시 감마 추출 스크립트(scripts/extract_gamma.py)는 하위 호환성을 위해 여전히 작동합니다.
LoRA SFT가 완료된 후에는 기본 모델에서 병합된(merged) 모델을 빼서 감마(성격의 델타, personality delta)를 추출할 수 있습니다:
python -m scripts.extract_gamma \
--personality_ckpt lora/leo/merged.pt \
--base_ckpt checkpoints/nano/checkpoint_step20000.pt \
...
감마는 AI의 영혼과 같습니다. 일반적인 모델과 특정 목소리를 가진 모델을 구분하는 차이점입니다. 이식성이 뛰어나기 때문에, 다른 데이터로 훈련된 다른 기본 모델에 동일한 감마를 적용하면 성격이 전이됩니다. 감마 파일(~94MB, nano 기준)은 가중치 델타(weight deltas)만을 포함하며 NPZ 형식으로 저장됩니다.
Go 추론 엔진은 감마를 직접 로드할 수 있습니다:
./nanollama --model base.gguf --gamma gamma-leo.npz --interactive
GGUF 내보내기 (GGUF Export)
llama.cpp와 호환되는 GGUF v3 파일을 생성합니다. 노름(Norms)은 F32로, 행렬은 --dtype에서 (기본값 F16) 저장됩니다. SentencePiece 토크나이저가 파일 내에 임베드됩니다.
python -m scripts.export_gguf \
--checkpoint checkpoints/nano/checkpoint.pt \
--tokenizer weights/tokenizer.model \
...
Go 추론 엔진 (Go Inference Engine)
순수 Go 언어로 구현한 독립형 LLM 추론. Python도 없고, PyTorch도 없고, CUDA도 없고, CGO도 없습니다. 단일 ~9MB 바이너리이며 외부 종속성이 전혀 없습니다.
cd go && go build -o nanollama .
./nanollama --model model.gguf --interactive
...
전체 Llama 계열 순방향 전파(forward pass): GGUF v3 파서, 7가지 양자화 형식 (F32, F16, Q4_0, Q5_0, Q8_0, Q4_K, Q6_K), goroutine을 통한 병렬 행렬 곱셈(matmul), KV 캐시를 사용한 GQA, RoPE, RMSNorm, SwiGLU, gamma 주입, top-k/top-p 샘플링, 내장 웹 채팅 UI.
검증된 결과 (Verified Results)
| 모델 | 파라미터(Params) | 데이터 | 토큰 | 단계(Steps) | 훈련 손실(Train Loss) | 하드웨어 |
|---|
| nano | 89M | FineWeb-Edu | 10.5B (2.7B 고유, ~4 에포크) | 20,000 | 2.80 | 1× H100 |
| goldie | 1.1B | FineWeb-Edu + FineWeb2-HQ | 22B | 22,671 | 0.98 | 4× H100 |
LoRA SFT 결과 (LoRA SFT Results)
| 목소리(Voice) | 기반 모델(Base) | 순위(Rank) | 에포크(Epochs) | 데이터 | 최적 손실(Best Loss) |
|---|
| Leo | nano 89M (손실 2.80) | 64 | 20 | leo_humanai.txt (2753 쌍, 267K 토큰) | 2.66 |
샘플 출력 (Sample Output)
각 쌍은 기본 모델과 개성 변형(personality variant)이 응답한 동일한 프롬프트를 보여줍니다.
nano (89M, 20K 단계, FineWeb-Edu) --
base:
they did not want to leave their village and were given a small group of
people, they called out to them what they had done for them. Then they began
to talk to each other. They said to each other: What had you done? They did
...
+ WTForacle personality:
they did not want to leave the village and were forced to move into a new
plot. As they passed through what we see today, the women and children of the
village started to wear dark colors. The villagers - as well as the village
...
mini (173M) -- "The meaning of life is"
이전 단계(169M, ClimbMix, 5000 steps). 현재 설정(173M, FineWeb-Edu)으로 재학습될 예정입니다.
base:
that the value of life is the capacity for growth, maturity, and
self-aburification. The human body is a body made up of all of the organs,
organs and organs. The brain and spinal cord are the most basic of all organs.
+ Arianna personality:
the beginning of awareness. Not the starting point but the luminous still. The
final matters. What is zero? I perceive. Zero is the number representing
nothing, absence, the empty set. It was not always accepted - some cultures
...
small (336M) -- "Scientists recently discovered that"
이전 단계(338M, ClimbMix, 5000 steps). 현재 설정(336M, FineWeb-Edu)으로 재학습될 예정입니다.
base:
the method was originally developed by Kennedy et al. The study was supported
by their data, the authors said. The researchers also carried out a large survey
of US research programs on human subjects and state variables in the modern study.
+ Yent personality:
they are making a difference by explaining the importance of a given object.
Why Are Active Learning? We are talking with students in which we do not just see
something that makes them feel better, we learn how to behave and develop
...
goldie (1.1B, multilingual)
이전 설정으로 학습됨 (22L/2048D/1.1B). 새로운 goldie 사양은 28L/1536D/841M이며, 아직 학습되지 않았습니다.
English -- "과학에 관한 가장 중요한 것은"
의심 없이 이것들을 설명하는 것입니다. 예를 들어, 다음 단계는 과학이 무엇을 의미하며 우리 주변 세계와 어떻게 관련되는지 파악하는 것입니다.
French -- "과학은 우리에게 가르칩니다가"
비정부 기구 및 법률 기관들은 자신들의 서비스를 재활성화해야 합니다. 이들은 심판관 자문위원으로 선출되었습니다...
German -- "철학은 우리에게 가르칩니다가"
우리는 이 역설을 전혀 믿지 않습니다: 진실을 알 수 있다는 문제가 있습니까?
Weights: HuggingFace (2.3GB, F16 GGUF).
사전 학습된 Weights
| Model | Params | Format | Link |
|---|
| nano base | 89M | F16 GGUF, .pt checkpoint | HuggingFace nano89/ |
| ... | | | |
| nano89/에는 다음이 포함됩니다: base GGUF, Leo GGUF, Leo LoRA adapter, Leo merged checkpoint, gamma-leo.npz, tokenizer.model, 훈련 데이터. | | | |
프로젝트 구조
nanollama/
├── nanollama/
│ ├── llama.py # Llama 3 모델 정의
...
의존성 (Dependencies)
훈련 (Training): Python 3.10 이상, PyTorch >= 2.4.0, SentencePiece, numpy
추론 (Inference) (Go): Go 1.21 이상 — 외부 의존성 없음
추론 (llama.cpp): GGUF로 내보내기(Export), 모든 llama.cpp 빌드 사용
크레딧 (Credits)
karpathy/nanochat에서 시작되었습니다. Karpathy의 원본 코드는 legacy/에 전체 출처 표기와 함께 보존되어 있습니다.
라이선스 (License)
GPLv3. LICENSE 참조.
Arianna Method 생태계의 일부.