概要
MiniMind は教育向けのオープンソースプロジェクトであり、個人が 1 枚のコンシューマー向け GPU で約 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() が裸の except: ブロック内で signal.signal(signal.SIGALRM, ...) を呼び出しているため、結果として発生した AttributeError が静かに握りつぶされ、関数は None を返します。そして rollout_single がその None を、すべてのツール呼び出しに対して {"error": "tool not found"} に変換します — クラッシュも警告もありません。これは Agentic RL トレーニングも静かに破壊します。フォーマット報酬は引き続きスコアされますが、モデルが実際のツール結果を一切見ることがないため、メインの ground-truth 報酬(重み 2.5)は到達不能になります。
修正(PR #847): trainer/trainer_utils.py にある AST ベースの safe_math_eval() を含むバージョンに更新してください。これは、モデルが生成した文字列に対する生の eval() を置き換え、シグナルベースのタイムアウトを完全に除去します(AST 評価器は無限ループに入ることができないため、signal.alarm は不要です — プラットフォームガードなしでクロスプラットフォームの問題が解消します)。同じ修正が 3 つすべての 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)
重要なルール: 裸の except: は絶対に使用しないでください(これが AttributeError を隠蔽し、失敗をサイレントにしました)。また、クロスプラットフォームコードでは signal.SIGALRM/signal.alarm を必ず hasattr(signal, 'SIGALRM') でガードしてください。
トラブル対応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)が事前学習のmax_seq_len(340)と異なるのですか?
original_max_position_embeddings は、YaRN を有効にする前にチェックポイントが実際に学習されたコンテキスト長を参照する必要があります — train_pretrain.py の値ではありません。MiniMind のパイプラインは次のとおりです。(1) 元の RoPE を使用し、max_seq_len=340 で事前学習を実施 (YaRN は無効)。(2) 元の RoPE を使用し、max_seq_len=2048 で Full SFT を実施 (YaRN は無効 — 公開されている full_sft の重みは、簡易 mini-dataset 再現スクリプトで使用される 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 で学習された事前学習のみのチェックポイントに YaRN を直接適用する場合にのみ、original_max_position_embeddings=340 を設定すべきです。