Recent Posts
Recent Comments
반응형
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

오늘도 공부

MiniMind: 개인 GPU로 LLM을 처음부터 끝까지 이해하게 만드는 가장 작은 풀스택 LLM 프로젝트 본문

AI

MiniMind: 개인 GPU로 LLM을 처음부터 끝까지 이해하게 만드는 가장 작은 풀스택 LLM 프로젝트

행복한 수지아빠 2026. 3. 24. 09:49
반응형

거대한 LLM을 보는 방식은 보통 두 가지입니다.
하나는 이미 만들어진 모델을 불러와서 프롬프트를 던져보는 방식이고, 다른 하나는 **“이 모델이 실제로 어떻게 만들어지고 학습되는가”**를 끝까지 따라가 보는 방식입니다.

MiniMind는 분명히 두 번째를 겨냥한 프로젝트입니다.
이 저장소의 핵심 가치는 “작은 모델” 그 자체보다, LLM의 전체 생애주기—토크나이저, 프리트레인, SFT, LoRA, DPO, PPO/GRPO/SPO, 증류, OpenAI 호환 서빙—를 PyTorch 중심의 비교적 투명한 코드로 한 번에 보여준다는 데 있습니다. 게다가 가장 작은 모델은 26M 규모로, 개인 GPU에서도 실험 가능한 수준을 목표로 합니다. (GitHub)

 

 

GitHub - jingyaogong/minimind: 🚀🚀 「大模型」2小时完全从0训练26M的小参数GPT!🌏 Train a 26M-parameter GP

🚀🚀 「大模型」2小时完全从0训练26M的小参数GPT!🌏 Train a 26M-parameter GPT from scratch in just 2h! - jingyaogong/minimind

github.com

 


프로젝트 소개

MiniMind는 Jingyao Gong이 공개한 오픈소스 프로젝트로, “작은 언어 모델을 처음부터 직접 학습시키면서 LLM 내부를 이해하게 해주는 튜토리얼형 저장소”에 가깝습니다. 저장소 설명 자체도 26M 파라미터 GPT를 2시간 안팎으로 처음부터 훈련할 수 있다고 소개하고 있고, 현재는 MiniMind2-small 26M, MiniMind2 104M, MiniMind2-MoE 145M 같은 여러 계열로 확장돼 있습니다. 저장소는 Python 기반이며, 핵심 구현은 PyTorch로 되어 있고, transformers, trl, peft 같은 외부 생태계와도 연결되도록 설계되어 있습니다. 또한 Streamlit 기반 Web UI, OpenAI API 호환 서버, vLLM·Ollama·llama.cpp 연동까지 포함합니다. (GitHub)

이 프로젝트를 한 문장으로 요약하면 이렇습니다.

“대형 모델을 잘 쓰는 법”이 아니라, “작은 모델을 직접 만들어 보며 LLM 시스템을 이해하는 법”을 가르치는 저장소

그래서 MiniMind는 단순히 모델 체크포인트를 배포하는 리포지토리가 아니라, 교육용이면서도 실전형 구조를 함께 갖춘 아키텍처 샘플로 보는 편이 정확합니다. (GitHub)


왜 이 프로젝트가 등장했을까

MiniMind가 겨냥하는 문제의식은 꽤 분명합니다.

대부분의 개발자는 LLM을 배울 때 이미 학습된 초거대 모델 위에 LoRA를 얹거나, transformers 몇 줄로 미세조정하는 방식부터 접합니다. 이 방식은 생산성은 높지만, 모델 내부 구조나 학습 루프를 이해하기는 어렵습니다. 저장소 README도 바로 이 점을 비판합니다. 고수준 프레임워크가 너무 많은 것을 감춰서, 정작 개발자는 “모델이 어떻게 돌아가는지”를 보기 어렵다는 것입니다. MiniMind는 이 추상화 장벽을 낮추기 위해, 핵심 알고리즘을 PyTorch 중심으로 다시 구현하고 학습 단계를 가능한 한 드러내는 방향을 택했습니다. (GitHub)

개발자 입장에서 보면 이 프로젝트의 등장은 세 가지 흐름과 맞닿아 있습니다.

1) LLM 학습을 “사용”에서 “이해”로 옮기려는 흐름

MiniMind는 프리트레인부터 RL 계열 튜닝까지 전 단계를 한 저장소 안에 넣었습니다. 즉, “이 단계는 외부 서비스가 대신 해준다”가 아니라, 각 단계가 어떤 역할을 하는지 직접 코드로 보게 만듭니다. (GitHub)

2) 개인 장비에서도 재현 가능한 소형 모델 수요

초거대 모델은 학습도 배포도 부담이 큽니다. 반면 MiniMind는 26M급 모델을 전면에 내세우며, 개인 GPU 환경에서도 프리트레인과 SFT를 실습할 수 있도록 접근성을 낮췄습니다. README와 공식 사이트 모두 “노트북/개인 GPU에서도 가능”이라는 메시지를 강하게 밀고 있습니다. (GitHub)

3) LLM 생태계의 실전 연결성

교육용 프로젝트는 종종 실서비스 연결이 약합니다. 그런데 MiniMind는 OpenAI API 호환 서버와 외부 추론 엔진 연동을 함께 제공합니다. 즉, 학습용 저장소이면서도 “만든 모델을 어떻게 서비스에 붙이는가”까지 이어집니다. (GitHub)


이 저장소를 보면 바로 보이는 핵심 특징

MiniMind의 강점은 “작다”보다 **“범위가 넓다”**는 데 있습니다.

1) LLM 전 과정을 한 저장소에서 본다

루트 구조를 보면 model, trainer, scripts, dataset 디렉터리로 나뉘고, trainer 안에는 train_pretrain.py, train_full_sft.py, train_lora.py, train_dpo.py, train_ppo.py, train_grpo.py, train_spo.py, train_distillation.py, train_reason.py, train_tokenizer.py가 들어 있습니다. 즉, 모델 정의와 학습 단계가 분리되어 있고, 각 훈련 스크립트가 역할별로 독립돼 있습니다. 이런 구조는 초중급 개발자가 파이프라인을 따라가기에 매우 좋습니다. (GitHub)

2) Dense와 MoE를 둘 다 다룬다

README에 따르면 MiniMind는 Dense 모델뿐 아니라 MoE 모델도 포함합니다. 특히 MoE는 DeepSeek-V2/3 계열의 MixFFN 아이디어를 참고해, routed expert와 shared expert 구성을 노출합니다. 설정 클래스에도 use_moe, n_routed_experts, n_shared_experts, num_experts_per_tok, aux_loss_alpha 같은 값이 드러나 있습니다. (GitHub)

3) 단순 학습이 아니라 RL 계열 정렬까지 포함한다

이 프로젝트는 SFT에서 끝나지 않습니다. README는 DPO, PPO, GRPO, SPO, 증류를 모두 지원한다고 밝히고 있고, 실제 trainer 디렉터리에도 각 스크립트가 존재합니다. 특히 2025년 10월 업데이트에서 PPO·GRPO·SPO와 YaRN, Adaptive Thinking, Tool Calling 템플릿 지원이 추가됐다고 명시돼 있습니다. (GitHub)

4) 모델을 바로 서비스에 붙일 수 있다

scripts/serve_openai_api.py는 FastAPI와 Uvicorn으로 /v1/chat/completions 엔드포인트를 제공하고, 요청 스키마도 OpenAI 스타일로 맞춰져 있습니다. 메시지 배열, temperature, top_p, stream 옵션을 받아 스트리밍 응답까지 처리합니다. 즉, 학습용 모델을 바로 Chat UI나 에이전트 프레임워크에 붙이기 쉬운 형태입니다. (GitHub)


프로젝트 아키텍처 분석

MiniMind를 아키텍처 관점에서 보면 크게 네 층으로 나눌 수 있습니다.

  1. 모델 계층
    model/model_minimind.py에서 설정과 Transformer 본체를 정의합니다.
  2. 학습 계층
    trainer 아래 스크립트들이 프리트레인, SFT, LoRA, DPO, PPO, GRPO, SPO, 증류를 담당합니다.
  3. 데이터 계층
    JSONL 기반 데이터셋을 읽어 단계별 학습에 맞는 배치를 구성합니다. README도 2025년 2월 업데이트에서 데이터셋 형식을 JSONL로 통일했다고 설명합니다.
  4. 서빙 계층
    scripts/serve_openai_api.py, web_demo.py, convert_model.py가 모델 배포와 인터페이스를 담당합니다. (GitHub)

아키텍처를 흐름으로 그리면 대략 이렇습니다.

이 구조가 좋은 이유는, 학습 단계와 서비스 단계를 분리하면서도 연결 경로가 자연스럽기 때문입니다.
예를 들어 많은 튜토리얼 프로젝트는 학습 코드만 보여주고 끝나는데, MiniMind는 학습된 결과가 어떻게 API 서버로 올라가고, 또 어떻게 외부 추론 엔진으로 연결되는지까지 보여줍니다. 그래서 “모델 학습 공부”와 “서비스 통합 실험”을 한 번에 이어서 볼 수 있습니다. (GitHub)


모델 구조는 어떻게 되어 있을까

README와 모델 코드 기준으로 MiniMind Dense는 Llama 계열에 가까운 Decoder-only Transformer입니다. 다만 몇 가지 포인트가 명확합니다.

RMSNorm 기반 Pre-Norm

README는 GPT-3 스타일의 pre-normalization과 RMSNorm을 사용한다고 설명합니다. 이는 학습 안정성을 높이는 데 자주 쓰이는 선택입니다. (GitHub)

SwiGLU 활성화

활성화 함수는 ReLU 대신 SwiGLU를 사용합니다. 소형 모델에서도 표현력을 조금 더 끌어올리기 위한 현대적인 선택입니다. (GitHub)

RoPE와 YaRN 외삽

절대 위치 임베딩 대신 RoPE를 사용하고, 설정 코드에는 rope_theta=1000000.0와 함께 inference_rope_scaling 및 YaRN 관련 스케일링 정보가 들어 있습니다. 즉, 이 프로젝트는 “짧은 컨텍스트로 학습하고, 추론에서 더 긴 길이로 늘려 쓰는” 전략까지 실험할 수 있게 해 둔 셈입니다. README도 2025년 10월 업데이트에서 YaRN 추가를 명시합니다. (GitHub)

GQA 형태의 헤드 구성

설정 클래스에는 num_attention_heads와 num_key_value_heads가 따로 존재합니다. Attention 코드에서도 KV head를 반복해서 맞추는 repeat_kv 로직이 보입니다. 즉, 완전한 MHA보다 GQA/Grouped Query Attention에 가까운 구조를 갖고 있다고 볼 수 있습니다. 작은 모델에서 효율을 챙기려는 선택으로 읽힙니다. (GitHub)

MoE 확장

use_moe가 켜지면 routed expert, shared expert, top-k expert selection, auxiliary loss가 활성화됩니다. 즉, MiniMind는 단순한 “작은 Dense 모델 튜토리얼”이 아니라, MoE의 학습 불안정성과 load balancing까지 맛볼 수 있는 입문형 실험장입니다. (GitHub)


학습 파이프라인을 개발자 시점에서 해석해보자

MiniMind의 학습 파이프라인은 꽤 교과서적입니다. 그리고 이게 장점입니다.

1) Pretrain: 언어 모델의 기본기 만들기

train_pretrain.py는 AutoTokenizer와 MiniMindLM을 로드하고, PretrainDataset에서 읽어온 입력에 대해 causal LM loss를 계산합니다. 학습률은 cosine 형태로 조절하고, gradient clipping과 mixed precision, DDP를 지원합니다. 즉, 소규모 프로젝트지만 현대적인 기본 학습 루프는 다 들어 있습니다. (GitHub)

이 단계는 말 그대로 “세상 지식”을 주입하는 과정입니다. README도 프리트레인을 “학습된 지식의 잉크를 채우는 단계”로 설명합니다. 아직 대화는 잘 못하지만, 다음 토큰 예측 능력을 갖추는 단계입니다. (GitHub)

2) SFT: 채팅하는 법 배우기

train_full_sft.py는 SFTDataset을 읽어 지도 미세조정을 수행합니다. 손실은 res.loss + res.aux_loss 형태이며, MoE일 경우 auxiliary loss가 추가됩니다. 학습 하이퍼파라미터도 프리트레인과 분리되어 있어, 단계별 실험이 쉽습니다. (GitHub)

프리트레인이 “언어를 아는 모델”을 만든다면, SFT는 “사람과 대화하는 인터페이스를 아는 모델”을 만드는 과정입니다. MiniMind는 이 단계를 명확히 분리해 보여주기 때문에, 초급 개발자가 LLM 학습의 역할 분담을 이해하기 좋습니다. (GitHub)

3) LoRA: 가볍게 도메인 적응

model_lora.py는 LoRA를 아주 직접적으로 구현합니다. 선형층 위에 저랭크 A/B 행렬을 덧붙이고, 원래 forward에 LoRA 출력을 더하는 방식입니다.
프레임워크에 숨겨진 magic 없이 LoRA의 본질을 보여준다는 점이 이 프로젝트다운 부분입니다. (GitHub)

4) DPO / PPO / GRPO / SPO: 정렬 단계

MiniMind는 최근 정렬 학습 흐름도 많이 흡수했습니다. README는 DPO와 PPO/GRPO/SPO를 모두 언급하고, trainer 디렉터리에도 각각의 스크립트가 존재합니다. 특히 train_grpo.py를 보면, 하나의 프롬프트에서 여러 샘플을 생성하고, reward model 점수와 포맷 보상, KL penalty를 묶어 advantage를 계산한 뒤 policy loss를 업데이트합니다. 즉, 논문 개념을 아주 깊게 추상화하지 않고 비교적 직접적으로 드러내는 쪽입니다. (GitHub)

이 점은 교육적으로 큰 의미가 있습니다.
많은 개발자가 GRPO를 “DeepSeek-R1 쪽에서 많이 쓰는 강화학습 방식” 정도로만 이해하는데, MiniMind는 적어도 코드 수준에서 “샘플 여러 개 뽑고, 상대 비교 보상으로 policy를 조정한다”는 흐름을 따라갈 수 있게 해줍니다. (GitHub)


서빙 구조도 생각보다 실용적이다

MiniMind를 흥미롭게 만드는 건 여기서 끝나지 않습니다.
이 프로젝트는 “학습용”인데도, 서빙 계층이 꽤 실전적입니다.

scripts/serve_openai_api.py는 FastAPI 기반 서버를 띄우고 /v1/chat/completions를 제공합니다. 요청은 messages, temperature, top_p, max_tokens, stream, tools 필드를 포함하며, 내부에서는 tokenizer.apply_chat_template(...)를 통해 프롬프트를 만들고 model.generate(...)를 호출합니다. 스트리밍도 TextStreamer와 큐를 이용해 구현되어 있습니다. (GitHub)

즉, MiniMind의 API 계층은 다음처럼 이해하면 됩니다.

flowchart LR
    A[Client / Chat UI] --> B[/v1/chat/completions]
    B --> C[FastAPI Server]
    C --> D[Tokenizer.apply_chat_template]
    D --> E[MiniMind Model.generate]
    E --> F[Streaming / Non-stream Response]

이 구조의 의미는 큽니다.
모델을 학습한 뒤 바로 FastGPT, Open WebUI, Dify 같은 도구에 붙여볼 수 있으니, “튜토리얼용 저장소”가 곧바로 “내부 실험용 모델 서버”가 될 수 있습니다. README도 이 연결성을 분명하게 강조합니다. (GitHub)


코드로 보면 왜 이해하기 쉬운가

MiniMind는 거대한 프레임워크 대신, 비교적 읽기 쉬운 스크립트 단위로 동작합니다.
예를 들어 SFT는 정말 직관적으로 보입니다.

# 개념적으로 보면 이런 흐름이다
for input_ids, labels in loader:
    res = model(input_ids, labels=labels)
    loss = res.loss + res.aux_loss
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

실제 train_full_sft.py도 거의 이런 구조를 따릅니다.
학습률 스케줄링, gradient clipping, 저장 로직, resume 로직만 추가된 형태입니다. (GitHub)

OpenAI 호환 API도 본질은 단순합니다.

@app.post("/v1/chat/completions")
async def chat_completions(request):
    prompt = tokenizer.apply_chat_template(
        request.messages,
        tokenize=False,
        add_generation_prompt=True
    )
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    generated_ids = model.generate(
        inputs["input_ids"],
        max_length=inputs["input_ids"].shape[1] + request.max_tokens
    )
    answer = tokenizer.decode(
        generated_ids[0][inputs["input_ids"].shape[1]:],
        skip_special_tokens=True
    )
    return {"choices": [{"message": {"role": "assistant", "content": answer}}]}

이 정도 수준으로 읽히기 때문에,
“아, OpenAI API 호환 서버가 사실은 이런 식으로 만들어지는구나”를 바로 이해할 수 있습니다. (GitHub)


이 프로젝트를 언제 쓰면 좋을까

MiniMind는 모든 상황에 맞는 프로젝트는 아닙니다.
대신 맞는 상황에서는 굉장히 강력합니다.

잘 맞는 경우

1. LLM을 처음부터 이해하고 싶은 개발자
LoRA만 해본 사람에게 가장 좋습니다. 프리트레인과 SFT의 차이, 정렬 단계의 의미, 서빙 구조까지 한 번에 잡을 수 있습니다. (GitHub)

2. 개인 GPU로 LLM 학습 파이프라인을 실험하고 싶은 경우
26M급 소형 모델은 부담이 낮습니다. 대규모 성능 경쟁보다, 파이프라인 이해와 재현성 실험에 적합합니다. (GitHub)

3. 사내 교육용 또는 스터디용 저장소가 필요한 경우
디렉터리 구조가 명확하고 학습 단계가 분리되어 있어, 세션 단위로 공부하기 좋습니다.
예를 들어 1주는 tokenizer, 2주는 pretrain, 3주는 SFT, 4주는 DPO/GRPO 식으로 나눠 보기 좋습니다. (GitHub)

4. 소형 모델을 API 서버 형태로 붙여보고 싶은 경우
OpenAI 호환 엔드포인트를 제공하므로 간단한 사내 챗봇 실험이나 UI 연결 테스트에 유용합니다. (GitHub)

덜 맞는 경우

1. 최고 성능의 프로덕션 모델이 필요한 경우
MiniMind는 교육성과 재현성을 우선시한 프로젝트입니다. 대형 상용 모델과 직접 경쟁하는 용도로 보면 실망할 수 있습니다. (GitHub)

2. 추상화된 고수준 API만 원하는 경우
이 프로젝트의 미덕은 내부를 드러내는 데 있습니다. 그래서 편의성만 보면 더 쉬운 대안이 많습니다. (GitHub)


추천하는 읽기 순서

이 저장소를 제대로 보려면 순서를 잡는 게 좋습니다.

  1. README에서 모델 계열과 훈련 단계 개요를 읽는다.
  2. model/model_minimind.py에서 구조를 본다.
  3. trainer/train_pretrain.py와 trainer/train_full_sft.py를 본다.
  4. 그다음 train_dpo.py, train_grpo.py로 정렬 단계를 확장해서 본다.
  5. 마지막으로 scripts/serve_openai_api.py와 web_demo.py를 본다. (GitHub)

이 순서로 보면 “모델 정의 → 학습 → 정렬 → 배포”라는 LLM 전체 흐름이 머릿속에 자연스럽게 연결됩니다.


한 줄 평

MiniMind는 “작은 모델 저장소”가 아닙니다.
정확히는 개발자가 LLM을 블랙박스가 아니라 시스템으로 이해하게 만드는, 아주 잘 정리된 실습형 아키텍처 저장소입니다.

대형 모델을 fine-tuning만 해본 개발자라면, 이 프로젝트를 보는 순간 이런 생각이 들 가능성이 큽니다.

“아, 내가 지금까지는 모델을 ‘썼지’, 만들어본 적은 없었구나.”

그리고 MiniMind의 진짜 가치는 바로 그 지점에 있습니다.
직접 만들어보게 한다는 것.
LLM을 이해하게 만든다는 것.
그리고 그 결과물을 다시 API 서버로 연결해보게 한다는 것. (GitHub)

반응형