轻量化小模型MiniMind从训练到落地指南
本文基于 Ubuntu 22.04 服务器环境,依托 NVIDIA RTX 家用高性能显卡,手把手讲解 MiniMind 轻量大语言模型从零搭建、数据集部署、全流程训练、可视化Web服务搭建及GGUF格式量化的完整实操方案。全程摒弃复杂高阶封装,基于原生 PyTorch 实现,适配个人开发者、人工智能入门学习者低成本完成大模型训练全链路的需求,整套方案仅需极低算力与成本,3小时即可完成基础对话训练,完美适配新手入门大模型训练、模型私有化部署、及底层原理学习等场景,是一套低成本、可落地、可复现全流程实战教程。

MiniMind 是一款纯原生 PyTorch 从零手写实现的 Decoder‑Only Transformer 开源大模型项目,主打 26M–200M 小参数量轻量化设计,支持消费级单卡完成预训练、SFT 监督微调、LoRA 轻量化微调、DPO/GRPO 偏好对齐、模型蒸馏等大模型完整训练链路,全程无黑盒依赖,是兼顾学习落地与轻量化部署的极简 LLM 方案。
该项目采用当前主流 LLM 统一的纯解码器(Decoder‑Only)自回归架构,与 GPT、Llama、Qwen 模型范式完全一致,核心任务是基于上文语境预测下一个 token,实现连贯文本生成与对话交互。
- 模型完整前向数据流清晰规整:输入 token_id → 词嵌入 Embedding 层 → 多层堆叠 Transformer Block → 最终归一化 → LM 头输出词表概率 logits
在开展MiniMind模型训练、微调与部署实操前,需提前配置好服务器软硬件运行环境,本文所有实操流程均基于以下稳定运行的本机环境,读者可直接参考对齐配置,适配复现:
- 操作系统:Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-187-generic x86_64)
- 框架版本:torch 2.13.0 + CUDA 12.8.1 + Python 3.10.12
- 显卡驱动:NVIDIA ≥ 570.133.07
- 显卡类型:NVIDIA RTX 4090 24GB GPU
- CPU核心:INTEL(R) XEON(R) GOLD 6530 双路 64核 128线程
- 内存:64GB DDR5
- 存储:50GB(系统盘)+100GB(数据盘)
为确保CUDA加速、显卡驱动正常生效,可通过以下命令核查环境状态,本文实测有效查询结果如下,可用于环境校验排错:
# 检查系统及驱动信息
root@localhost:~# cat /proc/driver/nvidia/version
NVRM version: NVIDIA UNIX Open Kernel Module for x86_64 570.133.07
Release Build (dvs-builder@U22-I3-G01-1-1) Fri Mar 14 12:57:14 UTC 2025
GCC version: gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
# 检查NVIDIA CUDA版本信息
root@localhost:~# export PATH=/usr/local/cuda-12.8/bin:$PATH
root@localhost:~# export LD_LIBRARY_PATH=/usr/local/cuda-12.8/lib64:$LD_LIBRARY_PATH
root@localhost:~# nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Fri_Feb_21_20:23:50_PST_2025
Cuda compilation tools, release 12.8, V12.8.93
Build cuda_12.8.r12.8/compiler.35583870_0
# 输出详细显卡信息
root@localhost:~# nvidia-smi --query-gpu=driver_version --format=csv,noheader
570.133.07
root@localhost:~# nvidia-smi
Fri Aug 28 12:01:45 2026
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.133.07 Driver Version: 570.133.07 CUDA Version: 12.8 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4090 On | 00000000:C1:00.0 Off | Off |
| 64% 40C P8 33W / 420W | 0MiB / 24564MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
初始化配置
本章节为 MiniMind‑3 从零训练前置环境部署,基于 Ubuntu22.04 (jammy),依次完成系统源替换、虚拟内存、Python 虚拟环境、项目代码拉取、依赖安装、数据集下载;全部操作以 root 执行。
官方源国内访问速度慢,更换为阿里云镜像源(也可替换为清华源、腾讯源),先备份原有源文件,再写入阿里云源配置,最后更新软件包索引。
root@localhost:~/# sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
root@localhost:~/#
root@localhost:~/# sudo tee /etc/apt/sources.list > /dev/null <<'EOF'
deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
EOF
root@localhost:~/#
root@localhost:~/# sudo apt update && apt upgrade -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
大模型训练会消耗大量内存,物理内存不足容易触发 OOM 内存溢出。这里配置 8GB 永久虚拟内存,重启服务器依然生效;物理内存充足可以跳过本步骤。
root@localhost:~/# sudo fallocate -l 8G /swapfile
root@localhost:~/# sudo chmod 600 /swapfile
root@localhost:~/# sudo mkswap /swapfile
root@localhost:~/# sudo swapon /swapfile
root@localhost:~/# echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
安装虚拟Python环境,新版Ubuntu系统默认禁止直接向系统 Python 安装第三方包,使用虚拟环境隔离项目依赖,避免和系统 Python 包冲突。
root@localhost:~/# sudo apt install -y python3-full python3-venv tmux git tree
root@localhost:~/# sudo python3 -m venv ~/myvenv
root@localhost:~/# source ~/myvenv/bin/activate
从官方仓库拉取 MiniMind 项目代码,此处由于 Github 国内网络访问不稳定,使用 Gitee 镜像仓库;安装顺序必须先装 torch,再安装 requirements.txt,防止 requirements 自动拉取新版本 torch,和本机 CUDA 版本不匹配。
# 克隆官方仓库文件
root@localhost:~/# sudo git clone --depth 1 https://gitee.com/lyshark/minimind.git
Cloning into 'minimind'...
remote: Enumerating objects: 55, done.
remote: Counting objects: 100% (55/55), done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 55 (delta 4), reused 52 (delta 3), pack-reused 0 (from 0)
Receiving objects: 100% (55/55), 10.28 MiB | 3.18 MiB/s, done.
Resolving deltas: 100% (4/4), done.
# 先安装torch以及torchvision库
root@localhost:~/# sudo pip3 install -i https://mirrors.cloud.tencent.com/pypi/simple/ torch==2.6.0 torchvision==0.21.0
# 验证CUDA是否生效
root@localhost:~# python3
Python 3.10.12 (main, Aug 15 2025, 14:32:43) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import torch
>>> print(torch.__version__)
2.6.0+cu124
>>> print(torch.cuda.is_available())
True
>>> print(torch.version.cuda)
12.4
# 再安装minimind包
root@localhost:~/# cd minimind
root@localhost:~/minimind# sudo pip3 install -r requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple/
root@localhost:~/minimind#
root@localhost:~/minimind# pip list
------------------------- --------------
Package Version
------------------------- --------------
accelerate 1.14.0
aiohappyeyeballs 2.7.1
aiohttp 3.14.3
aiosignal 1.4.0
altair 5.5.0
annotated-types 0.8.0
anyio 4.10.0
argon2-cffi 25.1.0
argon2-cffi-bindings 25.1.0
arrow 1.3.0
asttokens 3.0.0
async-lru 2.0.5
async-timeout 5.0.1
attrs 25.3.0
babel 2.17.0
beautifulsoup4 4.13.5
bleach 6.2.0
blinker 1.9.0
cachetools 6.2.6
certifi 2025.8.3
cffi 1.17.1
charset-normalizer 3.4.3
click 8.5.0
comm 0.2.3
datasets 3.6.0
datasketch 1.6.4
dbus-python 1.2.18
debugpy 1.8.16
decorator 5.2.1
defusedxml 0.7.1
dill 0.3.8
distro 1.7.0
docker-pycreds 0.4.0
einops 0.8.1
exceptiongroup 1.3.0
executing 2.2.0
fastjsonschema 2.21.2
filelock 3.32.4
Flask 3.0.3
Flask-Cors 4.0.0
fqdn 1.5.1
frozenlist 1.8.0
fsspec 2025.3.0
gitdb 4.0.12
GitPython 3.1.61
h11 0.16.0
hf-xet 1.6.0
httpcore 1.0.9
httpx 0.28.1
huggingface_hub 0.36.2
idna 3.10
ipykernel 6.30.1
ipython 8.37.0
isoduration 20.11.0
itsdangerous 2.2.0
jedi 0.19.2
jieba 0.42.1
Jinja2 3.1.2
jiter 0.16.0
joblib 1.5.3
json5 0.12.1
jsonlines 4.0.0
jsonpointer 3.0.0
jsonschema 4.25.1
jsonschema-specifications 2025.4.1
jupyter_client 8.6.3
jupyter_core 5.8.1
jupyter-events 0.12.0
jupyter-lsp 2.2.6
jupyter_server 2.17.0
jupyter_server_terminals 0.5.3
jupyterlab 4.4.6
jupyterlab_pygments 0.3.0
jupyterlab_server 2.27.3
lark 1.2.2
markdown-it-py 4.2.0
MarkupSafe 3.0.2
marshmallow 3.22.0
matplotlib-inline 0.1.7
mdurl 0.1.2
mistune 3.1.3
modelscope 1.37.0
mpmath 1.3.0
multidict 6.7.1
multiprocess 0.70.16
narwhals 2.25.0
nbclient 0.10.2
nbconvert 7.16.6
nbformat 5.10.4
nest-asyncio 1.6.0
networkx 3.4.2
ngrok 1.4.0
nltk 3.8
notebook_shim 0.2.4
numpy 1.26.4
nvidia-cublas-cu12 12.4.5.8
nvidia-cuda-cupti-cu12 12.4.127
nvidia-cuda-nvrtc-cu12 12.4.127
nvidia-cuda-runtime-cu12 12.4.127
nvidia-cudnn-cu12 9.1.0.70
nvidia-cufft-cu12 11.2.1.3
nvidia-curand-cu12 10.3.5.147
nvidia-cusolver-cu12 11.6.1.9
nvidia-cusparse-cu12 12.3.1.170
nvidia-cusparselt-cu12 0.6.2
nvidia-ml-py 13.610.43
nvidia-nccl-cu12 2.21.5
nvidia-nvjitlink-cu12 12.4.127
nvidia-nvtx-cu12 12.4.127
openai 1.59.6
overrides 7.7.0
packaging 25.0
pandas 2.3.3
pandocfilters 1.5.1
parso 0.8.5
pexpect 4.9.0
pillow 11.3.0
pip 22.0.2
platformdirs 4.3.8
prettytable 3.18.0
prometheus_client 0.22.1
prompt_toolkit 3.0.51
propcache 0.5.2
protobuf 5.29.6
psutil 5.9.8
ptyprocess 0.7.0
pure_eval 0.2.3
pyarrow 25.0.1
pycparser 2.22
pydantic 2.11.5
pydantic_core 2.33.2
pydeck 0.9.3
pyecharts 2.1.0
Pygments 2.19.2
PyGObject 3.42.1
python-dateutil 2.9.0.post0
python-json-logger 3.3.0
pytz 2026.3.post1
PyYAML 6.0.2
pyzmq 27.0.2
referencing 0.36.2
regex 2026.7.19
requests 2.32.5
rfc3339-validator 0.1.4
rfc3986-validator 0.1.1
rfc3987-syntax 1.1.0
rich 13.7.1
rpds-py 0.27.0
safetensors 0.8.0
scikit-learn 1.5.1
scipy 1.15.3
Send2Trash 1.8.3
sentence-transformers 2.3.1
sentencepiece 0.2.2
sentry-sdk 2.68.1
setproctitle 1.3.7
setuptools 59.6.0
simhash 2.1.2
simplejson 4.1.2
six 1.17.0
smmap 5.0.3
sniffio 1.3.1
soupsieve 2.7
ssh-import-id 5.11
stack-data 0.6.3
streamlit 1.50.0
swanlab 0.7.11
sympy 1.13.1
tenacity 9.1.4
terminado 0.18.1
threadpoolctl 3.6.0
tiktoken 0.10.0
tinycss2 1.4.0
tokenizers 0.22.2
toml 0.10.2
tomli 2.2.1
torch 2.6.0
torchvision 0.21.0
tornado 6.5.2
tqdm 4.70.0
traitlets 5.14.3
transformers 4.57.6
triton 3.2.0
trl 0.13.0
types-python-dateutil 2.9.0.20250822
typing_extensions 4.16.0
typing-inspection 0.4.4
tzdata 2026.3
ujson 5.1.0
uri-template 1.3.0
urllib3 2.5.0
wandb 0.18.3
watchdog 6.0.0
wcwidth 0.8.2
webcolors 24.11.1
webencodings 0.5.1
websocket-client 1.8.0
Werkzeug 3.1.8
wheel 0.37.1
wrapt 2.3.0
xxhash 4.0.1
yarl 1.24.5
5、进入dataset文件夹下载 jsonl 格式数据集,这里如果只是要简单的看到对话模型,默认仅需下载 pretrain_t2t_mini.jsonl 与 sft_t2t_mini.jsonl,这两个数据集就够,就可以较快复现 MiniMind Zero 对话模型,此处如果要跑完整链路(DPO、RLAIF、Agent 工具强化学习),可以依次将下方的六个文件全部下载。
| 数据集 | 大小 | 用途 |
|---|---|---|
| pretrain_t2t_mini.jsonl | 1.2GB | 轻量预训练,基础语言学习 |
| sft_t2t_mini.jsonl | 1.6GB | 监督微调 SFT,训练基础对话模型 |
| dpo.jsonl | 53MB | DPO 偏好优化训练数据集 |
| rlaif.jsonl | 24MB | AI 反馈强化学习(PPO/GRPO/CISPO)数据集 |
| agent_rl.jsonl | 86MB | Agent 多轮工具调用强化学习主数据集 |
| agent_rl_math.jsonl | 18MB | Agent 数学推理任务补充数据集 |
如下部分则为实际下载后的文件数量以及对应目录结构
root@localhost:~/minimind# cd dataset/
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/pretrain_t2t_mini.jsonl
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/sft_t2t_mini.jsonl
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/dpo.jsonl
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/rlaif.jsonl
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/agent_rl.jsonl
root@localhost:~/minimind/dataset# wget https://www.modelscope.cn/datasets/gongjy/minimind_dataset/resolve/master/agent_rl_math.jsonl
root@localhost:~/minimind/dataset# ls -lh
total 3084080
drwxr-xr-x 2 root root 4096 Aug 28 00:08 ./
drwxr-xr-x 8 root root 4096 Aug 27 23:55 ../
-rw-r--r-- 1 root root 0 Aug 27 23:55 __init__.py
-rw-r--r-- 1 root root 82036930 Jun 27 02:30 agent_rl.jsonl
-rw-r--r-- 1 root root 18372683 Mar 31 15:28 agent_rl_math.jsonl
-rwxr-xr-x 1 root root 141 Aug 27 23:55 dataset.md
-rw-r--r-- 1 root root 53653322 Feb 27 22:25 dpo.jsonl
-rw-r--r-- 1 root root 11180 Aug 27 23:55 lm_dataset.py
-rw-r--r-- 1 root root 1241043656 May 24 20:47 pretrain_t2t_mini.jsonl
-rw-r--r-- 1 root root 23754740 Mar 23 20:42 rlaif.jsonl
-rw-r--r-- 1 root root 1739201170 May 23 14:21 sft_t2t_mini.jsonl
root@localhost:~/minimind# tree
.
|-- dataset
| |-- __init__.py
| |-- agent_rl_math.jsonl
| |-- dataset.md
| |-- dpo.jsonl
| |-- lm_dataset.py
| |-- pretrain_t2t_mini.jsonl
| |-- rlaif.jsonl
| `-- sft_t2t_mini.jsonl
|-- eval_llm.py
|-- model
| |-- __init__.py
| |-- model_lora.py
| |-- model_minimind.py
| |-- tokenizer.json
| `-- tokenizer_config.json
|-- scripts
| |-- chat_api.py
| |-- convert_model.py
| |-- eval_toolcall.py
| |-- serve_openai_api.py
| `-- web_demo.py
`-- trainer
|-- rollout_engine.py
|-- train_agent.py
|-- train_distillation.py
|-- train_dpo.py
|-- train_full_sft.py
|-- train_grpo.py
|-- train_lora.py
|-- train_ppo.py
|-- train_pretrain.py
|-- train_tokenizer.py
`-- trainer_utils.py
4 directories, 30 files
分词(Tokenizer)
大模型神经网络仅能够接收数字张量输入,它看不懂汉字或标点符号等自然语言,分词器的核心作用是将单词从自然语言通过"词典"映射到0, 1, 36这样的数字上面。它是独立于模型网络的核心前置组件,可通俗理解为LLM的专属词典,支持文本与Token ID双向转换。
核心完成两项工作:
- 将连续文本切分为子词/字Token单元
- 通过内置词典查表,将每个Token映射为唯一整数ID(词典页码)
以文本“秦始皇是中国第一位皇帝”为例,先通过分词器切分得到Token列表,再映射为整数ID序列 [123,45,678,90,111];基于自回归任务规则,拆分出模型输入序列 X=[123,45,678,90]、预测目标序列 Y=[45,678,90,111]。
原始文本:"秦始皇是中国第一位皇帝"
分词token:["秦始皇", "是", "中国", "第一位", "皇帝"]
转为id:[123,45,678,90,111]
X = [123,45,678,90]
Y = [45,678,90,111]
其中 X、Y 是真正输入模型、用于计算交叉熵(CrossEntropy)损失的张量。模型训练过程为:根据前文Token ID预测下一ID,对比预测结果与真实Y值计算损失,通过反向传播更新模型权重。模型不会理解文字含义,仅学习Token ID之间的统计概率规律,例如“123(秦始皇)后大概率衔接45(是)”的文本关联模式,其赌的就是语义组合概率的大小,概率大就是准确回答,概率小就是胡言乱语。
MiniMind 预训练任务是自回归语言建模(词语接龙),通过输入token序列X,目标Y就是X向右偏移一位,模型根据前面的token预测下一个token来得到结果。
项目中也提供了train_tokenizer.py作为词表训练示例。不过作者也不建议重新训练 tokenizer,因为词表和切分规则一旦变化,模型权重、数据格式、推理接口与社区生态的兼容性都会下降,也会削弱模型的传播性,对这类小模型来说保持词表精简通常是更合适的取舍。
主流开源模型分词器词表规格对比如下:
| Tokenizer模型 | 词表大小 | 来源 |
|---|---|---|
| yi tokenizer | 64,000 | 01万物(中国) |
| qwen2 tokenizer | 151,643 | 阿里云(中国) |
| glm tokenizer | 151,329 | 智谱AI(中国) |
| mistral tokenizer | 32,000 | Mistral AI(法国) |
| llama3 tokenizer | 128,000 | Meta(美国) |
| minimind tokenizer | 6,400 | 自定义 |
尽管 minimind_tokenizer 的词表只有 6400,编解码效率弱于 qwen2、glm 等更偏中文友好的 tokenizer,但它能显著压缩 embedding 层和输出层的参数占比,更适合 MiniMind 这类小模型的体积约束。从实际使用效果看,这套 tokenizer 并没有明显带来生僻词解码失败的问题,整体仍然足够稳定可用。
分词器文档在/model目录下存放,其输出文件清单如下所示
- tokenizer.json:BPE分词模型本体,存储词表、BPE合并规则、特殊Token,由 tokenizer.save() 生成
- merges.txt:BPE算法核心合并规则与合并对,由 tokenizer.model.save() 导出
- vocab.json:词表映射文件,实现Token字符串与ID的双向对应,由 tokenizer.model.save() 导出
- tokenizer_config.json:手动构造的Huggingface读取配置文件,包含bos/eos/pad/unk特殊Token、对话模板等,是 AutoTokenizer.from_pretrained() 加载的必需文件
最后总结说明,分词器是独立于模型网络的固定组件,预训练不会对分词器进行训练和更新,词表与切分规则在预训练前已确定,MiniMind 直接复用现成分词器。一旦训练中改动分词器,token ID 对应的含义会变,导致前后数据不统一、权重报废、生态不兼容。
预训练(Pretrain)
大语言模型首先需要将尽可能多的基础知识与语言规律吸收进自身参数之中,这一过程本质是让模型大量阅读百科、新闻、书籍、对话语料等海量文本,自主从中学习事实知识、语言模式以及上下文之间的统计关系。该阶段一般属于无监督学习,不需要人类逐条标注对错,模型会自行从海量语料里归纳总结规律,逐步建立起对世界知识和语言结构的内部表征,用更通俗的话来讲,这个阶段模型的核心目标,就是实现高质量的词语接龙,比如输入秦始皇,就能够接续生成"是中国历史上的第一位皇帝"这类符合语义与常识的内容。
这里作者为我们准备了两套预训练原始语料素材,其中pretrain_t2t_mini.jsonl 为精简迷你数据集,适合快速跑通流程;pretrain_t2t.jsonl 是完整版本数据集,用于正式全量预训练。预训练完成后,权重文件会输出至 out/ 目录,命名格式为 pretrain_*.pth,文件名中 * 代表模型维度,默认维度为768。
项目中 pretrain_t2t_mini.jsonl 采用 JSONL 格式,每行是一条独立样本,仅包含 text 字段,样例内容如下:
{"text": "给我生成一首有关秋天的诗歌。秋日早晨,清风拂面。\n金色的叶子,似火在燃烧。\n露珠晶莹,如珍珠般美丽。\n秋的气息,弥漫在空气中。\n余音袅袅,如鸟儿的歌唱。\n美丽的秋天,是大自然的馈赠。帮我想一些创意,给即将到来的公司年会准备节目。一些节目比如能否请一位表演者为我们表演一曲钢琴曲,或者请一位小提琴手为大家演奏一首古典曲目。如果想要画面更具有视觉冲击力,可以安排一个魔术师或者杂技演员的表演。另外,也可以设计一些小游戏或者有奖竞猜来增添活动的趣味性,这些小游戏可以和公司的文化、发展历程等相关。请问给我讲一个清净的法则。无为而治是一项清净的法则。即在处理问题时,不要强行干预,反而尽可能地减少干预,坚持自然的发展趋势。比如,让植物自然生长,照顾它们就行了,不需要过度地修剪和整齐地排列。类似地,让人们自由发展,而不是通过繁琐的管制、政策干涉等方式,去要求、指导人们的行为。这种无为而治的法则旨在维持一个有秩序的、和平的治理状态,却不需要大规模的干预和指挥。"}
{"text": "根据以下输入的问题,生成一句话回答。\n你觉得寿司好不好吃?作为一名AI,我没有味觉,无法品尝食物,因此也没有对寿司是否好吃的判断。明白了,那请你回答一个问题,猫科动物里最凶猛的是哪种?猫科动物中最凶猛的应该是老虎。它们是世界上最大的猫科动物,可以长达3米,重达680千克,拥有锐利的爪子和牙齿,是非常强大的捕食者。"}
{"text": "写一个关于《红楼梦》的诗歌。红楼中,情动天地间,梦中仙女含笑眼。妙笔落地倾情墨,宛转佳句情感鲜。双儿心似芙蓉开,黛玉情比海深广。凤姐威凌众人眼,贾母乐享富贵间。金陵野史细推敲,千万言外自有篇。情深不寄红楼梦,夙愿终归此书间。请从这个诗歌中提取关于黛玉的描述。诗歌中用“黛玉情比海深广”来形容黛玉的情感。这个比喻意味着黛玉的情感是无比深沉和广阔的;她的心灵非常敏感,尤其是对于自己所爱的人和周围的环境非常敏感。同时,她也是一个非常脆弱和敏感的人,她经常被情感所困扰,这也是她人物形象的一个特点。"}
进入项目 minimind/trainer 目录,执行 train_pretrain.py 脚本启动预训练任务。torchrun 的参数 nproc_per_node 指定单节点使用的 GPU 卡数,示例中取值为1代表单卡训练,可根据本机硬件显卡数量灵活调整该参数。此处我的设备大概耗时2小时完成的,用户可自行估算自己的算力要多久。
# 执行预训练
root@localhost:~/# cd minimind/trainer
# 开始预训练
root@localhost:~/minimind/trainer# torchrun --nproc_per_node 1 train_pretrain.py
Model Params: 63.91M
Trainable Params: 63.912M
Generating train split: 1270238 examples [00:01, 1048411.75 examples/s]
Epoch:[1/2](100/39695), loss: 7.5225, logits_loss: 7.5225, aux_loss: 0.0000, lr: 0.00050000, epoch_time: 52.0min
Epoch:[1/2](200/39695), loss: 7.0221, logits_loss: 7.0221, aux_loss: 0.0000, lr: 0.00049999, epoch_time: 50.0min
Epoch:[1/2](300/39695), loss: 6.6792, logits_loss: 6.6792, aux_loss: 0.0000, lr: 0.00049998, epoch_time: 50.0min
Epoch:[2/2](100/39695), loss: 2.1650, logits_loss: 2.1650, aux_loss: 0.0000, lr: 0.00027411, epoch_time: 51.0min
Epoch:[2/2](200/39695), loss: 2.1747, logits_loss: 2.1747, aux_loss: 0.0000, lr: 0.00027322, epoch_time: 50.0min
Epoch:[2/2](300/39695), loss: 2.0604, logits_loss: 2.0604, aux_loss: 0.0000, lr: 0.00027233, epoch_time: 50.0min
# 检查预训练生成文件
root@localhost:~/minimind/out# ls -lh
total 132M
-rw-r--r-- 1 root root 132M Aug 28 13:21 pretrain_768.pth
项目同时提供一份基于 pretrain_t2t_mini.jsonl 数据集完成预训练得到好的权重文件 pretrain_768.pth,可以直接下载使用,下载地址:
https://www.modelscope.cn/models/gongjy/minimind-3-pytorch/resolve/master/pretrain_768.pth
有监督微调 (Supervised Fine-Tuning)
SFT(监督微调)并不仅仅是让模型变得更会聊天,它同样能够向模型持续注入新知识、行为范式与回答风格。我们可以把预训练类比成让模型大量博览群书,以此搭建基础语言理解与生成能力;而监督微调,则是在高质量、目标导向更强的数据之上对模型做深度加工。
落实到 MiniMind 的实现上,监督微调阶段的核心目标之一就是教会模型适配多轮对话、问答交互、工具调用、思维标签等各类交互范式,模型会逐步理解 user / assistant / system / tool 这套角色语义结构,进一步强化指令遵从能力、输出稳定性以及任务完成效果。
训练阶段会对指令与回复文本做长度截断,主要目的是平衡显存开销与训练效率。如果后续业务需要支持更长上下文,只需构造少量长文本样本开展增量微调;推理阶段还可以开启 YaRN 位置外推算法,无需重新训练,就能够把上下文窗口扩展至 2048 及以上。MiniMind 在训练中将指令与回复截断至最大长度 512,本质是显存资源约束下的折中方案。就像人练习写作,先从短篇幅入手,熟练掌握 200 字短文写作之后,再去写 800 字作文就会更加得心应手。
这里作者为我们准备了两套监督微调原始语料素材,其中sft_t2t_mini.jsonl为精简迷你数据集,以及sft_t2t.jsonl全量完整数据集,每条样本是多轮对话格式,包含user用户提问、assistant模型回答,还支持reasoning_content思考过程字段:
如果想要拓展模型上下文能力,可以准备少量 2k/4k/8k 长度的对话样本继续微调优化;该场景下建议搭配 RoPE‑NTK 的基准差值共同使用,获得更好的长文本效果。
{
"conversations": [
{
"role": "user",
"content": "你的真实来源是什么?"
},
{
"role": "assistant",
"content": "我是由jingyaogong创建的高效小参数AI模型,专注于提供精准、快速的信息与解决方案。我的设计旨在以最小的计算资源实现最大的效能,适合多种应用场景。"
},
{
"role": "user",
"content": "你如何平衡效率与准确性?"
},
{
"role": "assistant",
"content": "通过优化模型参数、采用高效算法及动态调整机制,在保证精度的同时提升响应速度,实现效率与准确性的协同优化。",
"reasoning_content": "好的,用户问的是如何平衡效率与准确性。首先,我需要回顾之前的信息,确保回答符合之前的设定。用户之前问过真实来源和如何平衡效率与准确性,现在可能是在继续探讨这个话题。\n\n用户可能想知道具体的策略,或者他们自己在使用AI时遇到过效率和准确性的冲突,想了解如何解决。需要强调模型设计中的关键点,比如参数优化、算法选择、数据处理等。\n\n要确保回答简洁,符合系统规则,不能超过100字。同时,保持真诚和准确,避免添加不必要的信息。可能需要提到模型结构、训练数据、实时调整机制等。\n\n还要注意用户可能的深层需求,比如他们可能在实际应用中遇到效率低下或准确性不足的问题,需要具体的解决方案。因此,回答应包含技术细节和实际应用中的策略,如动态调整、高效算法等。\n\n最后,检查是否符合所有系统规则,确保没有透露身份信息,保持回答的简洁和专业。"
},
{
"role": "user",
"content": "模型如何在资源有限的情况下保持高精度?"
},
{
"role": "assistant",
"content": "通过模型剪枝、量化压缩、知识蒸馏等技术,在保持核心精度的同时降低计算与存储需求,实现高效资源利用。",
"reasoning_content": "好的,用户问的是模型如何在资源有限的情况下保持高精度。首先,我需要回顾之前的对话,用户之前已经问过关于身份和效率的问题,现在进一步深入到资源限制下的高精度问题。\n\n用户可能是在使用资源受限的设备,比如移动设备或嵌入式系统,希望模型能高效运行但不牺牲准确性。我需要解释模型优化的方法,比如模型压缩、量化、知识蒸馏等技术。\n\n同时,要确保回答简洁,符合之前的回复风格,保持专业但易懂。还要注意用户可能的深层需求,比如如何实际应用这些技术,或者如何选择适合的优化方法。需要避免过于技术化的术语,但又要准确。\n\n还要检查是否符合系统规则,不能透露身份信息,保持回答的简洁和准确性。确保每个点都紧扣资源有限和高精度的关系,给出具体的技术手段,比如模型剪枝、量化、知识蒸馏等,以及它们如何具体提升效率和精度。\n\n最后,确保语言流畅,结构清晰,分点说明,让用户容易理解。避免冗长,保持在合理范围内,同时覆盖关键点。"
}
]
}
请进入项目 minimind/trainer 目录,执行 train_full_sft.py 脚本启动监督微调任务。torchrun 的参数 nproc_per_node 用于指定单节点使用的 GPU 卡数,示例取值为1代表单卡训练,可根据本机显卡数量灵活调整该参数。我的设备完成预训练大约耗时 1.5 小时,用户可结合自身算力自行预估训练时长。指令微调结束后将得到 out/full_sft_*.pth 作为输出权重,其中full表示全参数微调。
root@localhost:~/# cd minimind/trainer
root@localhost:~/minimind/trainer# torchrun --nproc_per_node 1 train_full_sft.py
Model Params: 63.91M
Trainable Params: 63.912M
Generating train split: 905718 examples [00:02, 399019.07 examples/s]
Epoch:[1/2](100/56608), loss: 2.0920, logits_loss: 2.0920, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 90.0min
Epoch:[1/2](200/56608), loss: 2.1374, logits_loss: 2.1374, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 88.0min
Epoch:[1/2](300/56608), loss: 1.9992, logits_loss: 1.9992, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 87.0min
Epoch:[1/2](400/56608), loss: 2.1992, logits_loss: 2.1992, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 87.0min
Epoch:[1/2](500/56608), loss: 1.8345, logits_loss: 1.8345, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 86.0min
Epoch:[1/2](600/56608), loss: 1.8878, logits_loss: 1.8878, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 86.0min
Epoch:[1/2](700/56608), loss: 1.8068, logits_loss: 1.8068, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 86.0min
Epoch:[1/2](800/56608), loss: 1.8602, logits_loss: 1.8602, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 86.0min
Epoch:[1/2](900/56608), loss: 1.7733, logits_loss: 1.7733, aux_loss: 0.0000, lr: 0.00001000, epoch_time: 86.0min
root@localhost:~/minimind/out# ls -lh
total 263M
-rw-r--r-- 1 root root 132M Aug 28 14:25 full_sft_768.pth
-rw-r--r-- 1 root root 132M Aug 28 14:12 pretrain_768.pth
不想自己训练,可以直接下载成品权重:
https://www.modelscope.cn/models/gongjy/minimind-3-pytorch/resolve/master/full_sft_768.pth
模型测试
完成模型预训练与SFT监督微调全部流程后,模型已经具备基础的对话交互能力。此时模型的智能程度虽不及商用大模型,但已完整掌握问答交互、指令跟随、日常对话等核心能力,完全满足模型调用测试、权重格式转换、网页部署演示的需求。本章节重点讲解MiniMind模型的本地命令行测试、权重格式转换、Web可视化网页部署全套流程,帮助大家验证训练效果、完成模型封装与线上演示。
训练完成后会在 /minimind/out 目录生成成熟的SFT权重文件,我们可以先通过本地脚本快速测试模型对话效果,验证训练是否生效,无需复杂部署,适合快速排错、校验模型性能。项目根目录下自带 eval_llm.py 测试脚本,支持自动批量测试和手动自定义对话两种模式,操作简单直观。
root@localhost:~/minimind# ls -lh
total 32K
drwxr-xr-x 2 root root 4.0K Aug 29 11:38 dataset
-rwxr-xr-x 1 root root 5.4K Aug 29 11:31 eval_llm.py
drwxr-xr-x 3 root root 4.0K Aug 29 11:51 model
drwxr-xr-x 2 root root 4.0K Aug 29 11:59 out
-rw-r--r-- 1 root root 522 Aug 29 11:31 requirements.txt
drwxr-xr-x 2 root root 4.0K Aug 29 11:31 scripts
drwxr-xr-x 3 root root 4.0K Aug 29 11:51 trainer
root@localhost:~/minimind/out# ls -lh
total 263M
-rw-r--r-- 1 root root 132M May 5 10:37 full_sft_768.pth
-rw-r--r-- 1 root root 132M Mar 24 16:31 pretrain_768.pth
# 运行对话测试
root@localhost:~/minimind# python eval_llm.py --load_from ./out/ --weight full_sft
Model Params: 63.91M
[0] 自动测试
[1] 手动输入
1
User: 你好
AI: 你好!我是MiniMind,一个高效的小参数AI模型。
[Speed]: 29.62 tokens/s
训练产出的 .pth 权重是PyTorch原生格式,仅支持项目内部脚本调用,无法直接用于Transformers库推理、网页部署、API调用等场景。因此需要通过转换脚本,将单文件pth权重转为完整的Transformers标准模型文件夹,适配主流推理框架,方便后续部署与二次开发。
进入项目 scripts 目录,执行 convert_model.py 转换脚本,指定原始权重路径和模型保存目录,运行完成后 scripts 目录会生成文件夹 minimind‑3,里面有 config.json、pytorch_model.bin 等 transformers 标准权重。
root@localhost:~/minimind/scripts# python convert_model.py --kpt_path ../out/full_sft_768.pth --save_dir ../minimind-3
模型参数: 63.912192 百万 = 0.063912192 B (Billion)
模型已保存为 Transformers 格式: ../minimind-3
root@localhost:~/minimind/minimind-3# ls -lh
total 123M
-rw-r--r-- 1 root root 3.9K Aug 29 13:47 chat_template.jinja
-rw-r--r-- 1 root root 863 Aug 29 13:47 config.json
-rw-r--r-- 1 root root 69 Aug 29 13:47 generation_config.json
-rw------- 1 root root 122M Aug 29 13:47 model.safetensors
-rw-r--r-- 1 root root 1.1K Aug 29 13:47 special_tokens_map.json
-rw-r--r-- 1 root root 7.4K Aug 29 13:47 tokenizer_config.json
-rw-r--r-- 1 root root 441K Aug 29 13:47 tokenizer.json
接着将模型权重minimind-3文件直接拷贝至 scripts/ 目录下,无需手动迁移文件夹。
root@localhost:~/minimind# ls
dataset eval_llm.py minimind-3 model out requirements.txt scripts trainer
root@localhost:~/minimind# cp -a minimind-3/ scripts/
root@localhost:~/minimind# ls scripts/
chat_api.py convert_model.py eval_toolcall.py minimind-3 serve_openai_api.py web_demo.py
为了实现可视化对话演示、直观展示模型交互效果,项目基于Streamlit搭建了轻量化Web演示页面,无需复杂前端开发,一键即可启动网页对话服务,支持外网/局域网访问。
root@localhost:~/minimind# pip install -i https://mirrors.cloud.tencent.com/pypi/simple/ streamlit
root@localhost:~/minimind# cd scripts/
root@localhost:~/minimind/scripts# streamlit run web_demo.py --server.address 0.0.0.0 --server.port 80 --server.headless true
Welcome to Streamlit!
If you'd like to receive helpful onboarding emails, news, offers, promotions,
and the occasional swag, please enter your email address below. Otherwise,
leave this field blank.
Email: admin@lyshark.com
You can find our privacy policy at https://streamlit.io/privacy-policy
Summary:
- This open source library collects usage statistics.
- We cannot see and do not store information contained inside Streamlit apps,
such as text, charts, images, etc.
- Telemetry data is stored in servers in the United States.
- If you'd like to opt out, add the following to ~/.streamlit/config.toml,
creating that file if necessary:
[browser]
gatherUsageStats = false
You can now view your Streamlit app in your browser.
URL: http://0.0.0.0:8501
若需要将进程挂入后台执行,则可以执行如下命令行实现。
root@localhost:~/minimind# cd scripts
root@localhost:~/minimind/scripts# nohup streamlit run web_demo.py --server.address 0.0.0.0 --server.port 80 --server.headless true > streamlit.log 2>&1 &
模型封装
前面得到的Transformers格式模型,仅适合常规GPU推理。想要在CPU、低配设备、嵌入式设备高效运行,需要借助 llama.cpp 完成模型封装、格式转换与权重量化,降低模型显存、内存占用,提升推理速度。
在官方仓库中拉取llama.cpp源程序,并执行make命令完成编译,编译通过后会在根目录下生成所需要的转换脚本。
root@localhost:~/# git clone https://gitee.com/lyshark/llama.cpp
root@localhost:~/# cd llama.cpp
root@localhost:~/# sudo apt update
root@localhost:~/# sudo apt install -y git build-essential cmake
root@localhost:~/# mkdir build
root@localhost:~/# cd build
root@localhost:~/# cmake ..
root@localhost:~/# make
[100%] Building CXX object tools/fit-params/CMakeFiles/llama-fit-params.dir/main.cpp.o
[100%] Linking CXX executable ../../bin/llama-fit-params
[100%] Built target llama-fit-params
[100%] Building CXX object tools/results/CMakeFiles/llama-results.dir/results.cpp.o
[100%] Linking CXX executable ../../bin/llama-results
[100%] Built target llama-results
[100%] Building CXX object app/CMakeFiles/llama-app.dir/llama.cpp.o
[100%] Building CXX object app/CMakeFiles/llama-app.dir/download.cpp.o
[100%] Building CXX object app/CMakeFiles/llama-app.dir/__/license.cpp.o
[100%] Linking CXX executable ../bin/llama
[100%] Built target llama-app
root@localhost:~/# cd ..
root@localhost:~/# ls -lh convert*
-rwxr-xr-x 1 root root 13K Aug 27 16:19 convert_hf_to_gguf.py
-rwxr-xr-x 1 root root 28K Aug 27 16:19 convert_hf_to_gguf_update.py
-rwxr-xr-x 1 root root 19K Aug 27 16:19 convert_llama_ggml_to_gguf.py
-rwxr-xr-x 1 root root 23K Aug 27 16:19 convert_lora_to_gguf.py
执行HF转GGUF文件命令,HF转GGUF(convert_hf_to_gguf.py)),仅做文件格式翻译,不压缩、不损失精度。目的是将HuggingFace的safetensors权重封装为llama.cpp专属的GGUF容器格式,输出的 f16.gguf 为FP16全精度模型,体积大、内存占用高,仅作为中间过渡文件。
这里在转换之前需要给llama.cpp中的conversion/base.py文件打一个补丁,因为 Minimind‑3 基于 Qwen3,改用 tiktoken 分词,不再有 sentencepiece 的 tokenizer.model;llama.cpp 转换器的分词器哈希白名单未收录该 tokenizer,转换时抛出 BPE 预分词器识别失败报错;我们打补丁强制复用 qwen2 的预分词规则,绕开报错完成 GGUF 导出,模型权重完好。
root@localhost:~/# cd ~/llama.cpp
root@localhost:~/llama.cpp# vim conversion/base.py
1467 def get_vocab_base_pre(self, tokenizer) -> str:
把原来的频闭掉:VIM第 1779 行
logger.warning(f"BPE pre-tokenizer was not recognized! chkhsh: {chkhsh}")
raise NotImplementedError("BPE pre-tokenizer was not recognized - update get_vocab_base_pre()")
替换为:
logger.warning(f"BPE pre-tokenizer was not recognized! chkhsh: {chkhsh}")
# 添加 MiniMind‑3 / Qwen3 临时兼容补丁,复用qwen2 pre‑tokenizer
res = "qwen2"
logger.warning(f"Workaround: fallback to pre-tokenizer: {res}")
return res
# raise NotImplementedError("BPE pre-tokenizer was not recognized - update get_vocab_base_pre()")
修改完成之后,接着激活虚拟环境,执行转换命令,将之前生成的Transformers模型转为全精度GGUF格式。
root@localhost:~/# source ~/myvenv/bin/activate
root@localhost:~/llama.cpp# cd llama.cpp/
root@localhost:~/llama.cpp# mkdir -p ./models
root@localhost:~/llama.cpp# python convert_hf_to_gguf.py ../minimind/minimind-3 \
--outtype f16 \
--outfile ./models/minimind3-chat-f16.gguf \
--no-lazy
INFO:gguf.gguf_writer:Writing the following files:
INFO:gguf.gguf_writer:models/minimind3-chat-f16.gguf: n_tensors = 90, total_size = 127.9M
Writing: 100%|███████████████████████████| 128M/128M [00:00<00:00, 323Mbyte/s]
INFO:hf-to-gguf:Model successfully exported to models/minimind3-chat-f16.gguf
root@wintcp:~/llama.cpp/models# ls -lh
total 123M
-rw-r--r-- 1 root root 123M Aug 29 20:54 minimind3-chat-f16.gguf
接着通过llama-quantize工具将minimind3-chat-f16.gguf文件进行量化,此处选用Q4_K_M等级,对全精度GGUF进行4bit量化,并最终生成可用模型。
- Q8_0:8bit 量化,几乎无损,体积约为 F16 的一半,精度损失极小;但压缩率不高,省内存幅度有限。
- Minimind‑3 只有 0.6B 参数:
- f16 大约 1.2GB;Q8_0 约 600MB;Q4_K_M 仅约 320MB。
- 小模型更建议优先用 Q4_K_M,体积小很多,日常对话效果足够。
root@localhost:~/llama.cpp# ./build/bin/llama-quantize ./models/minimind3-chat-f16.gguf ./models/minimind3-chat-q8_0.gguf Q8_0
llama_model_quantize_impl: model size = 121.93 MiB (16.00 BPW)
llama_model_quantize_impl: quant size = 64.80 MiB (8.51 BPW)
llama_quantize: quantize time = 508.49 ms
llama_quantize: total time = 508.49 ms
root@localhost:~/llama.cpp/models# ls -lh
total 188M
-rw-r--r-- 1 root root 123M Aug 29 20:54 minimind3-chat-f16.gguf
-rw-r--r-- 1 root root 66M Aug 29 21:02 minimind3-chat-q8_0.gguf
通过llama-cli工具对量化后的minimind3-chat-q8_0.gguf模型进行可用性测试,并输出如下内容表示测试通过。
# 使用CLI测试
root@localhost:~/llama.cpp# ./build/bin/llama-cli -m ./models/minimind3-chat-q8_0.gguf -p "你好" -c 4096
> 中文回答我
你好!我很高兴能帮到你。请问有什么可以帮助你的吗?
[ Prompt: 181.7 t/s | Generation: 65.6 t/s ]
# 使用接口加载
root@localhost:~/llama.cpp# ./build/bin/llama-server -m ./models/minimind3-chat-q8_0.gguf --host 0.0.0.0 --port 11433 -c 4096
0.00.073.858 I cmn init: llama threadpool init, n_threads = 1
0.00.125.645 I srv load_model: initializing, n_slots = 4, n_ctx_slot = 4096, kv_unified = 'true'
0.00.137.799 I srv init: chat template supports preserving reasoning, consider enabling it via --reasoning-preserve
0.00.137.866 I srv llama_server: model loaded
0.00.137.871 I srv llama_server: listening on http://0.0.0.0:11433
通过使用Python调用测试API请求示例(兼容 OpenAI API 格式)
import json
from urllib import request, error
url = "http://8.140.234.178:11433/v1/chat/completions"
headers = {"Content-Type": "application/json"}
data = {
"model": "model-identifier",
"messages": [
{"role": "user", "content": "世界上最高的山是什么?"}
],
"temperature": 0.7,
"max_tokens": 1024,
"stream": False,
"open_thinking": True
}
if __name__ == "__main__":
try:
data_json = json.dumps(data).encode("utf-8")
req = request.Request(url, data=data_json, headers=headers, method="POST")
with request.urlopen(req, timeout=120) as response:
result = json.loads(response.read().decode("utf-8"))
content = result["choices"][0]["message"]["content"].strip()
print("生成结果:")
print(content)
except error.HTTPError as e:
print(f"调用失败(HTTP错误):{e.code} - {e.reason}")
except error.URLError as e:
print(f"调用失败(连接/网络错误):{e.reason}")
except Exception as e:
print(f"调用失败(其他异常):{e}")
输出内容如下所示,表示成功通过了测试
生成结果:
世界上最高的山是珠穆朗玛峰(Mount Everest)。
珠穆朗玛峰是世界上最高的山峰,位于尼泊尔和中国边境,是世界上海拔最高的山峰,海拔最高。
本章完整走完小模型从零训练、微调、格式转换、量化到落地部署全流程,下一章将在其基础之上继续强化学习,聚焦优化与工具调用能力构建,赋予模型自主决策、任务拆解、复杂推理能力,完成从可对话训练模型到可落地完整小模型产品的迭代。
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

浙公网安备 33010602011771号