# 薄荷Transformer网络训练器 **Repository Path**: Mint-Space/Mint ## Basic Information - **Project Name**: 薄荷Transformer网络训练器 - **Description**: 一个用 **Rust 从零手写**的中文聊天大模型项目:包含**训练、微调、聊天**三大能力,不依赖 PyTorch / TensorFlow 等任何深度学习框架,连 GPU 加速代码(CUDA 核函数)都是手写的。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-09-13 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mint > 当前版本 **v1.0.0** 一个用 **Rust 从零手写**的中文聊天大模型项目:包含**训练、微调、聊天**三大能力,不依赖 PyTorch / TensorFlow 等任何深度学习框架,连 GPU 加速代码(CUDA 核函数)都是手写的。 模型采用与 GPT 同族的 **Decoder-only Transformer** 架构,训练与聊天推理都可在 GPU 上运行。底层从注意力机制、反向传播到矩阵乘法全部自主实现,追求完全可控、可解释、无黑盒。 ## 特性 - **从零实现** — 注意力、RoPE 位置编码、RMSNorm、SwiGLU、交叉熵、Adam 优化器,全部手写前向/反向公式 - **手写 CUDA 核函数** — 29 个核函数(寄存器分块的矩阵乘法、块对角注意力、融合 softmax+损失、Adam 更新等),不依赖 cuBLAS - **训练 / 微调 / 聊天** — 一键训练新模型、加载检查点继续微调、像 ChatGPT 一样逐字生成并支持多轮对话记忆 - **实时可视化** — 终端进度条、损失曲线、自动生成 HTML 训练报告 - **GPU 加速** — 训练全程在 GPU 上(前向、反向、Adam、验证集评估),注意力按序列分块做(batch 内各序列互不可见,只算真正用到的块);聊天另有**显存常驻的增量推理**路径(权重一次上传、K/V 常驻显存),用 `-gpu` 开启 - **模型管理** — 列出/查看检查点详情、GPU 状态查询 - **赞赏支持** — 主菜单 `[8]` 或 `mint -thanks` 直接在终端画出微信赞赏码(自研 JPEG 解码路径:GDI+ 读取 + 模块重采样 + 半块字符渲染) - **单文件分发** — CUDA 运行时静态链接,exe 不附带任何 DLL(读赞赏码图时用 Windows 自带的 `gdiplus.dll`) ## 技术栈 | 层 | 技术 | |---|---| | 语言 | Rust (edition 2021) | | GPU | CUDA 12.0 + 手写核函数 (`src/gpu/kernels.cu`) | | 序列化 | serde / serde_json | | 并行 | rayon (CPU 端矩阵乘法) | | 随机数 | rand 0.8 | | 时间 | chrono | | 构建 | nvcc + MSVC + rc.exe (图标嵌入) | ## 架构 ```mermaid flowchart TB subgraph main["main.rs — 界面层"] MENU["交互菜单 / CLI 参数解析"] TRAIN["训练循环 train_chat"] CHAT["聊天推理 interactive_chat"] end subgraph core["核心模块"] DATA["data.rs
数据发现 / 词表 / 分批"] MODEL["model/transformer.rs
Transformer 模型本体"] TRAINING["training.rs
GPU 训练器 / 前向反向"] CKPT["checkpoint.rs
保存 / 加载"] CHART["chart.rs
进度条 / 报告"] end subgraph gpu["GPU 封装"] OPS["gpu/ops.rs
GpuBuffer 安全封装"] FFI["gpu/cuda_ffi.rs
Rust ↔ CUDA FFI"] KERNEL["gpu/kernels.cu
手写 CUDA 核函数"] end MENU --> DATA MENU --> MODEL MENU --> TRAINING MENU --> CKPT MENU --> CHART CHAT --> MODEL TRAINING --> OPS OPS --> FFI FFI --> KERNEL CKPT --> MODEL ``` 数据流:数据 → 词表 → 词嵌入 → L 层解码器(注意力 + SwiGLU FFN)→ 输出投影 → softmax → 逐字生成。 ## 目录结构 ``` Mint ├── Cargo.toml # 项目清单(cuda 特性默认开启) ├── build.rs # 编译前脚本:编译 CUDA、嵌入图标 ├── mint.rc / icon/ # Windows 资源与图标 ├── data/ # 训练数据集(Belle / zhwiki / LCCC / CLUE 系列) ├── docs/ # 技术解读报告(含完整数学公式推导) ├── models/ # 训练好的检查点 ├── versions/ # 历代版本快照归档 └── src/ ├── main.rs # 入口、交互菜单、训练/聊天驱动循环 ├── model/transformer.rs# Transformer 模型本体 ├── tensor.rs # CPU 张量运算库 ├── training.rs # GPU 训练器、前向/反向传播 ├── data.rs # 数据发现/解析/词表/分批 ├── checkpoint.rs # 模型保存/加载 ├── chart.rs # 进度条、图表、HTML 报告 └── gpu/ # CUDA 核函数与三层封装 ``` ## 快速开始 ### 环境要求 - **Rust 工具链**(cargo 1.98+) - **NVIDIA GPU + CUDA Toolkit 12.0**(或设置 `CUDA_PATH` 指向其他版本) - **Visual Studio Build Tools**(MSVC,build.rs 通过 `vswhere` 自动查找) 训练**必须使用 CUDA GPU**——CPU 训练已禁用。聊天推理有两条路径:**CPU(默认)** 与**显存常驻的增量推理**;默认走 CPU 是因为实测在当前模型规格(4.5M 参数)下,显存路径每 token 要发约 1050 次核函数启动,启动开销压过计算,反而比多线程 CPU 慢十几倍(实测 605 字/秒 vs 49.8 字/秒)。模型更大时用 `-gpu` 切换,程序每轮都会打印“字/秒”供对比。 ### 构建与运行 ```powershell # 编译(release,CUDA 默认开启) cargo build --release # 交互式菜单(训练 / 聊天 / 微调 / 模型管理) .\target\release\mint.exe # 直接训练(Belle 数据集、medium 规格、3 轮) .\target\release\mint.exe -train -task=belle -size=medium -epochs=3 # 加载模型聊天 .\target\release\mint.exe -model=chat_belle_medium_model.json # 微调已有模型 .\target\release\mint.exe -train -task=belle -model=chat_belle_medium_model.json # 运行测试(含 GPU 数值对拍) cargo test # 查看帮助 .\target\release\mint.exe -h ``` ### CLI 参数 | 参数 | 说明 | 默认值 | |---|---|---| | `-train` | 进入训练模式 | — | | `-model=` | 加载模型;单独使用=聊天,与 `-train` 同用=微调 | — | | `-task=` | 训练任务(belle/zhwiki/LCCC-base-split/afqmc/ocnli/tnews/cmrc2018…) | belle | | `-size=` | 模型规格(small/medium/large/xlarge) | medium | | `-epochs=` | 训练轮数 | 3 | | `-lr=` | 学习率 | 0.001 | | `-batch=` | 批次大小 | 8 | | `-max=` | 最大训练样本数(0=不限) | 20000 | | `-gpu` | 强制使用 GPU 加速(聊天推理也走显存) | — | | `-cpu` | 不用 GPU 加速(聊天用 CPU;训练会直接报错) | — | | `-thanks` | 查看赞赏支持(微信收款码) | — | | `-h` / `--help` | 显示帮助 | — | 无参数启动进入交互式主菜单:1 训练新模型、2 加载模型聊天、3 微调、4 浏览数据集、5 模型管理、6 GPU 状态、7 帮助、8 赞赏支持。 ## 模型规格 | 型号 | d_model | 层数 | 头数 | d_ff | 最大序列 | 参数量(约) | |---|---|---|---|---|---|---| | small | 96 | 3 | 6 | 288 | 128 | ~1.2M | | medium | 128 | 4 | 8 | 384 | 128 | ~1.9M | | large | 192 | 6 | 12 | 576 | 192 | ~4.5M | | xlarge | 256 | 8 | 16 | 768 | 256 | ~9.0M | > 采用**字符级**词表,`d_ff = 3 × d_model`,每头维度 `dk = d_model / 头数`。词嵌入与输出投影各占 `词表 × d` 的参数,是参数量的主要来源。 > > 上表参数量按约 **4000 字**词表估算(仓库内的检查点实测 `param_count = 4509870`,对应 large);真实数值由数据集词表决定,程序会按实际配置打印。 ## 数据格式 数据放在 `data/<任务名>/` 目录下,程序会自动发现并解析。支持三类任务: - **指令对话/Seq2Seq**(如 Belle、LCCC)— JSON 数组,`{ "instruction": "…", "output": "…" }` 或对话对 - **语言模型预训练**(如 zhwiki)— 纯文本,流式解析并缓存为 JSONL - **分类/阅读理解**(CLUE 系列:AFQMC、OCNLI、TNEWS、CMRC2018) 对话数据打包时只对"助手回复"部分计算损失(`loss_mask`),模型学的是"如何回答"而非"如何复述问题"。 ## 测试 `cargo test` 运行 36 个测试,全部通过。核心方法是 **GPU 与 CPU 数值对拍**以及**有限差分**验证梯度正确性: - 手写矩阵乘法 × 13 组尺寸对拍 CPU - GPU 前向 = CPU 前向 - 反向传播核函数逐元素数值验证 - 有限差分验证梯度(含生产规模 4585 词表) - KV 缓存逐 token 推理 = 全序列一次推理(误差 < 1e-4) - 边界守卫:GPU 封装的越界长度会被断言拦下、模型规格命名与配置一致、报告数值不会产出非法的 `inf` - 终端二维码:合成图定位/采样与原始网格逐格相等、半块渲染的尺寸与静区布局正确、低分辨率下网格要么被时序图形标尺校准回正确值要么明确报错(绝不静默出错)、透明像素按白底合成、采样阈值随对比度自适应 - 显存增量推理:**逐 token 与 CPU 的 `forward_cached` 逐值对拍**(< 1e-3)、滑窗裁切后仍与 CPU 一致、分配失败返回 `None` 而非崩溃 训练性能用 `cargo test --release -- --ignored --nocapture bench_training` 拆解:它会分别给出前向/反向、梯度裁剪、Adam 各占多少毫秒,以及单层注意力、GEMM 实测吞吐。**这类测量只有在同一进程内交替 A/B 才可靠**——同一份代码在不同进程之间实测能差 2~3 倍(笔记本 GPU 的频率/供电状态),跨进程前后对比很容易得出假结论。 ## 已知限制 - **字符级建模** — 生成步数多,长程语义理解弱于子词(BPE)分词 - **模型规模** — 1.2M(小)到 9.0M(大)参数,远小于 GPT-3 的 1750 亿,只能短对话、无深度推理 - **显存硬约束** — 4GB 显存限制 batch 与模型大小(聊天走显存约需 20 MB,不是瓶颈) - **检查点为 JSON** — 体积偏大,序列化时内存翻倍 - **训练报告** — HTML 依赖 CDN 图表库,离线打开无图表 ## 赞赏支持 如果 Mint 对你有帮助,欢迎请作者喝杯咖啡。主菜单 `[8]` 或运行 `mint -thanks` 会**直接在命令行窗口里画出微信赞赏码**,用手机扫码即可,不必打开图片文件。 这里不依赖任何图像库:图片用 Windows 自带的 GDI+ 解码,然后二值化、定位三个寻像图形、按模块重采样成 0/1 网格,最后用半块字符 `▀` 打印 —— 一个字符正好是 1 格宽 × 2 个模块高,所以二维码在终端里是方的。 网格会再用二维码自带的**时序图形**复核一次:低分辨率图里包围盒会被模糊撑宽 1px,足以让模块数差 1、整张码错位而寻像图形照样“通过”;这一步校准不过在就明确报错,不会把错位的码当成功打印出来。窗口放不下时也提前警告(本图 45 模块 + 8 格静区 = 53 列),把窗口拉宽或调小字号即可。 二维码图片位于 `icon/gratuity.jpg`,**不内嵌进 exe**:单文件分发时把它放在 `mint.exe` 同级的 `icon/` 目录即可(程序依次查找「exe 同级 → 工作目录 → 源码根」);找不到时会打印应放置的路径。 ## 更多文档 技术细节、逐组件数学公式推导、训练系统与 GPU 加速详解、经典 Bug 案例集等,请见 [`docs/Mint项目技术解读报告.md`](docs/Mint项目技术解读报告.md)。