개요
MiniMind는 개인이 단일 소비자급 그래픽 카드에서 약 2시간 만에 처음부터 64M 초소형 언어 모델을 훈련할 수 있도록 하는 교육용 오픈소스 프로젝트입니다. 이 프로젝트는 네이티브 PyTorch를 기반으로 대규모 모델의 극도로 간소화된 구조와 완전한 훈련 파이프라인을 구현하며, MoE, 사전 훈련, SFT, LoRA, DPO, RLAIF, Agentic RL, 도구 호출 및 모델 증류를 포괄하고, 오픈소스 데이터셋, 모델 가중치와 주요 추론 및 훈련 프레임워크에 대한 호환성 지원을 제공합니다.
README 미리보기
\n\n\n\n\n\n\n\n\n[](https://github.com/jingyaogong/minimind/stargazers)\n[](LICENSE)\n[](https://github.com/jingyaogong/minimind/commits/master)\n[](https://github.com/jingyaogong/minimind/pulls)\n[](https://huggingface.co/collections/jingyaogong/minimind-66caf8d999f5c7fa64f399e5)\n\n\n\n\n\n\n\n\n\n\n "大道至简"\n\n\n\n\n中文 | [English](./README_en.md)\n\n\n\n* 此开源项目旨在完全从 0 开始,仅用 3 块钱成本与 2 小时训练时间,即可训练出规模约为 64M 的超小语言模型 MiniMind。\n* MiniMind 系列极其轻量,主线最小版本体积约为 GPT-3 的 $\frac{1}{2700}$,力求让普通个人 GPU 也能快速完成训练与复现。\n* 项目同时开源了大模型的极简结构与完整训练链路,覆盖 MoE、数据清洗、预训练(Pretrain)、监督微调(SFT)、LoRA、RLHF(DPO)、RLAIF(PPO / GRPO / CISPO)、Tool Use、Agentic RL、自适应思考与模型蒸馏等全过程代码。\n* MiniMind 同时拓展了视觉模态模型 [MiniMind-V](https://github.com/jingyaogong/minimind-v)、多模态 Omni 模型 [MiniMind-O](https://github.com/jingyaogong/minimind-o)、扩散语言模型(MiniMind-dLM)、线性模型(MiniMind-Linear),详见 [Discussion](https://github.com/jingyaogong/minimind/discussions)。\n* 项目所有核心算法代码均从 0 使用 PyTorch 原生实现,不依赖第三方库提供的高层抽象接口。\n* 这不仅是一个大语言模型全阶段开源复现项目,也是一套面向 LLM 入门与实践的教程。\n* 希望此项目能为更多人提供一个可复现、可理解、可扩展的起点,一起感受创造的乐趣,并推动更广泛 AI 社区的进步。\n\n> 注:本项目基于 Apache 2.0 协议开源,完全免费。“2 小时” 指 SFT 阶段在单张 NVIDIA 3090 上跑完 `1 epoch` 的实测耗时,“3 块钱” 指对应时段的 GPU 租用成本。\n\n---\n\n\n\n\n\n[🔗 在线体验](https://www.modelscope.cn/studios/gongjy/MiniMind) | [🔗 视频介绍](https://www.bilibili.com/video/BV12dHPeqE72)\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\n\n\n---\n\n# 📌 项目介绍\n\n大语言模型(Large Language Model, LLM)的出现,引发了全球范围内对 AI 的空前关注。无论是 ChatGPT、DeepSeek 还是 Qwen,都以惊艳的效果让人真切感受到这场技术浪潮的冲击力。然而,动辄数百亿参数的模型规模,使得它们对个人设备而言不仅难以训练,甚至连部署都显得遥不可及。打开大模型的“黑盒子”,真正去理解其内部运作机制,本应是一件令人心潮澎湃的事。遗憾的是,绝大多数探索最终都止步于使用 LoRA 等技术对现有大模型做少量微调,学习一些新指令或特定任务。这更像是在教牛顿如何使用 21 世纪的智能手机——虽然有趣,却偏离了理解物理本质的初衷。\n\n与此同时,第三方的大模型框架与工具库,如 `transformers` / `trl` / `peft` 等,往往只暴露出高度抽象的接口。只需短短十几行代码,就可以完成“加载模型 + 加载数据集 + 推理 + 强化学习”的全流程训练。这种高效封装固然便利,却也在一定程度上把开发者与底层实现隔离开来,削弱了深入理解 LLM 核心代码的机会。我认为 “用乐高自己拼出一架飞机,远比坐在头等舱里飞行更让人兴奋”,然而更现实的问题是,互联网上充斥着大量付费课程和营销内容,用漏洞百出FAQ (3)
문제 해결Windows에서 train_agent.py를 실행할 때 모든 도구 호출이 "tool not found" 오류를 반환하는 이유는 무엇인가요?
근본 원인: signal.SIGALRM과 signal.alarm()은 POSIX 전용이며 Windows에는 존재하지 않습니다. trainer/train_agent.py에서 execute_tool()이 bare except: 블록 안에서 signal.signal(signal.SIGALRM, ...)을 호출하므로, 결과적으로 발생하는 AttributeError가 조용히 삼켜지고 함수는 None을 반환합니다. 그러면 rollout_single이 모든 도구 호출에 대해 그 None을 {"error": "tool not found"}로 변환합니다 — 크래시도, 경고도 없이. 이는 Agentic RL 학습까지 조용히 손상시킵니다: format reward는 여전히 점수가 매겨지지만, 모델이 실제 도구 결과를 전혀 보지 못하기 때문에 메인 ground-truth reward(가중치 2.5)에는 도달할 수 없게 됩니다.
수정 사항 (PR #847): trainer/trainer_utils.py에 AST 기반 safe_math_eval()이 포함된 버전으로 업데이트하세요. 이는 모델이 생성한 문자열에 대한 원시 eval()을 대체하고 시그널 기반 타임아웃을 완전히 제거합니다(AST 평가기는 무한 루프에 빠질 수 없으므로 signal.alarm이 불필요하며, 플랫폼 가드 없이도 크로스 플랫폼 문제가 사라집니다). 동일한 수정이 세 개의 eval() 호출 지점 모두에 적용됩니다: trainer/train_agent.py, scripts/eval_toolcall.py, scripts/web_demo.py.
이전 커밋에 머물러 있다면, 다음과 같은 최소한의 크로스 플랫폼 패치를 적용하세요:
_HAS_ALARM = hasattr(signal, "SIGALRM")
def execute_tool(name, args):
fn = MOCK_RESULTS.get(name)
if not fn: return None
try:
if _HAS_ALARM:
signal.signal(signal.SIGALRM, lambda *_: (_ for _ in ()).throw(TimeoutError()))
signal.alarm(1)
return fn(args)
except Exception as e:
print(f"[tool] {name} failed: {type(e).__name__}: {e}")
return None
finally:
if _HAS_ALARM: signal.alarm(0)
핵심 규칙: bare except:를 절대 사용하지 마세요(이것이 AttributeError를 숨기고 실패를 조용하게 만들었습니다). 그리고 크로스 플랫폼 코드에서는 항상 hasattr(signal, 'SIGALRM')으로 signal.SIGALRM/signal.alarm을 가드하세요.
문제 해결24GB GPU (RTX 4090)에서 train_agent.py 또는 train_grpo.py 실행 시 CUDA Out of Memory (OOM) 오류를 해결하는 방법은?
실효 학습 배치 크기는 batch_size × num_generations이며(Agent RL: 2×4=8, GRPO: 2×6=12), 학습 시 Policy 모델, Reference 모델, 그리고 1.8B Reward Model을 동시에 로드하므로 24GB VRAM이 부족할 수 있습니다. 해결 방법:
1. train_agent.py의 경우, 배치 크기와 전체 길이를 줄이세요:
python train_agent.py --batch_size 1 --max_total_len 1536
2. train_grpo.py의 경우(max_total_len 옵션 없음), 배치 크기, 생성 수, 시퀀스 길이를 줄이세요:
python train_grpo.py --batch_size 1 --num_generations 4 --max_seq_len 512 --max_gen_len 768
3. PyTorch가 큰 'reserved but unallocated memory'를 보고하는 경우, 다음을 설정하여 메모리 단편화를 줄이세요:
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True문제 해결MiniMind에서 YaRN rope_scaling을 사용할 때 original_max_position_embeddings (2048)이 pretrain max_seq_len (340)과 다른 이유는 무엇인가요?
original_max_position_embeddings는 YaRN을 활성화하기 *전에* 체크포인트가 실제로 학습된 컨텍스트 길이를 가리켜야 하며, train_pretrain.py의 값이 아닙니다. MiniMind의 파이프라인은 다음과 같습니다: (1) max_seq_len=340에서 원본 RoPE로 Pretrain 수행 (YaRN 비활성화); (2) max_seq_len=2048에서 원본 RoPE로 Full SFT 수행 (YaRN 비활성화 — 릴리스된 full_sft 가중치는 빠른 미니 데이터셋 재현 스크립트에서 사용된 768이 아니라 2048 토큰으로 학습되었습니다); (3) YaRN을 활성화하여 2048 윈도우로부터 외삽하며 추론 (예: python eval_llm.py --weight full_sft --inference_rope_scaling). 따라서 original_max_position_embeddings=2048이 Full SFT 체크포인트와 일치합니다. RoPE 자체는 학습 가능한 파라미터가 없는 결정론적 위치 회전이며, 학습이 필요한 것은 위치 범위에 대한 모델 가중치의 적응인데, 이는 이미 2048 토큰 Full SFT 단계에서 이루어졌습니다. Full SFT를 건너뛰고 길이 340으로 학습된 Pretrain 전용 체크포인트에 YaRN을 직접 적용하는 경우에만 original_max_position_embeddings=340으로 설정해야 합니다.