From e235edee4a587984d5f7602687bfaaca49f03ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=8F=E5=BB=BA?= Date: Wed, 8 Jul 2026 15:13:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=BD=AC=E6=8D=A2=E5=B7=A5=E5=85=B7):=201?= =?UTF-8?q?.=20=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=202.=20=E6=9B=B4=E6=96=B0=20Cargo.toml=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BB=A5=E5=8C=85=E5=90=AB=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=203.=20=E5=88=A0=E9=99=A4=E8=BF=87=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E6=8C=87=E5=8D=97=E6=96=87=E6=A1=A3=204.=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20README=20=E6=96=87=E4=BB=B6=E4=BB=A5?= =?UTF-8?q?=E5=8F=8D=E6=98=A0=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84=E5=92=8C?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 13 ++ Cargo.toml | 1 + MODEL_GUIDE.md | 155 -------------------- examples/convert/Cargo.toml | 13 ++ examples/convert/src/main.rs | 20 +++ readme.md | 266 ++++++++++++++--------------------- 6 files changed, 150 insertions(+), 318 deletions(-) delete mode 100644 MODEL_GUIDE.md create mode 100644 examples/convert/Cargo.toml create mode 100644 examples/convert/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 8505302..22f88f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,6 +564,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0098bf6555c151517b4c98ca0e8ed1ab6a976e40f5f4e967c117b00eee21e192" dependencies = [ + "aligned-vec", "burn-backend", "burn-ir", "burn-std", @@ -571,7 +572,9 @@ dependencies = [ "gemm", "half", "libm", + "macerator", "num-traits", + "rayon", ] [[package]] @@ -749,6 +752,7 @@ dependencies = [ "aligned-vec", "bon", "burn-cubecl", + "burn-flex", "burn-fusion", "burn-ir", "burn-tensor", @@ -1080,6 +1084,15 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d3e02915a2cea4d74caa8681e2d44b1c3254bdbf17d11d41d587ff858832c" +[[package]] +name = "convert" +version = "0.1.0" +dependencies = [ + "anyhow", + "burn", + "minicpm-convert", +] + [[package]] name = "convert_case" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index a4a81d0..43f3081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "crates/minicpm-core", "crates/minicpm-convert", "crates/minicpm-inference", + "examples/convert", "examples/wgpu-backend", ] resolver = "2" diff --git a/MODEL_GUIDE.md b/MODEL_GUIDE.md deleted file mode 100644 index d2ea5d7..0000000 --- a/MODEL_GUIDE.md +++ /dev/null @@ -1,155 +0,0 @@ -# 模型格式与使用指南 - -## 模型格式说明 - -项目支持三种模型格式,适用于不同场景: - -| 格式 | 精度 | 文件大小 | 适用后端 | 速度 | -|------|------|----------|----------|------| -| full | f32 全精度 | ~2.5GB | Flex / Wgpu | 基准 | -| half | f16 半精度 | ~1.2GB | Flex / Wgpu | 较快 | -| q8 | INT8 量化 | ~650MB | Flex (推荐) | 最快 | - -### 1. 全精度模型 (full) -- 目录:`model/` -- 文件:`model.mpk` -- 精度:FP32 -- 适用场景:精度优先、GPU 推理 - -### 2. 半精度模型 (half) -- 目录:`model_half/` -- 文件:`model.mpk` -- 精度:FP16 -- 适用场景:GPU 推理、显存有限 - -### 3. INT8 量化模型 (q8) -- 目录:`model_q8/` -- 文件:`model.q8.bin` + `model.q8.json` -- 精度:INT8 + 缩放因子 -- 适用场景:CPU 推理、内存有限 -- 特性:SIMD 指令集加速(AVX2/SSE) - -## 使用方法 - -### 命令行参数 - -所有示例都支持以下命令行参数: - -```bash ---full # 使用全精度模型 ---half # 使用半精度模型 ---q8 # 使用 INT8 量化模型 -``` - -**重要**:参数前需要加 `--` 与 cargo 分隔: - -```bash -# 正确 -cargo run --release -p flex-backend -- --q8 -cargo run --release -p wgpu-backend -- --half - -# 错误(参数会被 cargo 吃掉) -cargo run --release -p flex-backend --q8 -``` - -### Flex 后端(CPU) - -```bash -# 全精度 -cargo run --release -p flex-backend -- --full - -# 半精度 -cargo run --release -p flex-backend -- --half - -# INT8 量化(推荐,最快) -cargo run --release -p flex-backend -- --q8 -``` - -**最佳性能编译**: -```bash -RUSTFLAGS="-C target-cpu=native" cargo build --release -p flex-backend -cargo run --release -p flex-backend -- --q8 -``` - -### Wgpu 后端(GPU) - -```bash -# 全精度(推荐) -cargo run --release -p wgpu-backend -- --full - -# 半精度 -cargo run --release -p wgpu-backend -- --half - -# INT8 量化(不推荐,性能较差) -cargo run --release -p wgpu-backend -- --q8 -``` - -**注意**: -- WGPU 后端下,q8 量化层使用 CPU 实现,会频繁在 CPU-GPU 间传输数据,性能可能不如全精度 -- GPU 推理建议使用 `--full` 或 `--half` - -## 模型转换 - -使用 convert 示例转换模型: - -```bash -# 全精度 -cargo run --release -p convert -- --full - -# 半精度 -cargo run --release -p convert -- --half - -# INT8 量化 -cargo run --release -p convert -- --q8 - -# 全部转换 -cargo run --release -p convert -- --all -``` - -源模型目录:`MiniCPM5-1B/`(需要包含 safetensors 格式模型) - -## 性能对比(参考) - -以 MiniCPM5-1B 模型为例: - -| 后端 | 格式 | 内存占用 | 推理速度 | 推荐指数 | -|------|------|----------|----------|----------| -| Flex CPU | q8 | ~1GB | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | -| Flex CPU | half | ~1.5GB | ⭐⭐⭐ | ⭐⭐ | -| Flex CPU | full | ~3GB | ⭐⭐ | ⭐ | -| Wgpu GPU | full | ~2.5GB | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | -| Wgpu GPU | half | ~1.5GB | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | -| Wgpu GPU | q8 | ~1GB | ⭐ | ⭐ | - -> 注:实际性能取决于 CPU/GPU 型号、内存带宽等因素 - -## 启动时的输出说明 - -程序启动时会打印配置信息,确认使用的模型格式: - -``` -======================================== -后端: Flex (纯 Rust CPU) -模式: INT8 量化 (SIMD 加速) -模型目录: model_q8 -配置文件: MiniCPM5-1B/config.json - 特性: INT8 量化 + SIMD 加速,推荐使用 - 编译建议: RUSTFLAGS="-C target-cpu=native" cargo build --release -======================================== -``` - -如果模式和模型目录与预期不符,请检查命令行参数是否正确传递。 - -## 常见问题 - -### Q: 加了 --q8 参数但感觉没变化? -A: 检查是否加了 `--` 分隔符。正确用法:`cargo run --release -p flex-backend -- --q8` - -### Q: WGPU 上 q8 反而更慢? -A: 正常现象。q8 量化是 CPU 优化的,GPU 上建议用 full 或 half。 - -### Q: half 模型速度和 full 差不多? -A: Flex CPU 后端上 f16 运算会转成 f32,速度差异不大。WGPU GPU 后端上显存占用会明显减少。 - -### Q: 怎么确认用的是哪个模型? -A: 看启动时的打印信息,"模式"和"模型目录"字段会显示当前配置。 diff --git a/examples/convert/Cargo.toml b/examples/convert/Cargo.toml new file mode 100644 index 0000000..34a5ba0 --- /dev/null +++ b/examples/convert/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "convert" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "convert" +path = "src/main.rs" + +[dependencies] +minicpm-convert = { path = "../../crates/minicpm-convert" } +burn = { version = "0.21", default-features = false, features = ["std", "flex"] } +anyhow = "1.0" diff --git a/examples/convert/src/main.rs b/examples/convert/src/main.rs new file mode 100644 index 0000000..c729c59 --- /dev/null +++ b/examples/convert/src/main.rs @@ -0,0 +1,20 @@ +use burn::backend::{flex::FlexDevice, Flex}; +use minicpm_convert::{run_export, ExportTask, Format}; +use std::path::Path; + +fn main() -> anyhow::Result<()> { + let safetensors_path = Path::new("MiniCPM5-1B/model-00000-of-00001.safetensors"); + let config_path = Path::new("MiniCPM5-1B/config.json"); + let tokenizer_path = Path::new("MiniCPM5-1B/tokenizer.json"); + + println!("模型转换工具"); + println!("源文件: {:?}", safetensors_path); + println!(); + + let device = FlexDevice::default(); + let tasks = vec![ExportTask::new(Format::Full)]; + + run_export::(safetensors_path, config_path, tokenizer_path, &tasks, &device)?; + + Ok(()) +} diff --git a/readme.md b/readme.md index 2605d99..62f3a26 100644 --- a/readme.md +++ b/readme.md @@ -1,186 +1,126 @@ # MiniCPM5-1B-rust -基于 [Burn](https://burn.dev/) 深度学习框架实现的 MiniCPM5-1B 大语言模型推理库,纯 Rust 编写,支持 GPU 加速。 +MiniCPM5-1B 模型的 Rust 推理实现,基于 [Burn](https://github.com/tracel-ai/burn) 框架。 -## 模型架构参数 +## 特性 -| 参数 | 值 | -|------|-----| -| 层数 | 24 | -| 注意力机制 | GQA (16 Query / 2 KV) | -| head_dim | 128 | -| hidden_size | 1536 | -| intermediate_size | 8960 | -| vocab_size | 151936 | -| RoPE theta | 5000000 | -| 归一化 | RMSNorm | -| 激活函数 | SiLU (SwiGLU) | -| KV Cache | 支持 | +- 🔥 **Wgpu GPU 加速**:支持 CUDA / Metal / Vulkan / DX12 等多种 GPU 后端 +- 🚀 **算子融合**:启用 fusion + autotune 优化,自动选择最优 kernel +- 📝 **流式输出**:实时生成文本,支持逐字输出 +- 🧠 **思考模式**:支持开启模型的推理思考过程 +- 📦 **纯 Rust**:无 C/C++ 依赖,跨平台编译简单 -## Workspace 结构 +## 项目结构 -项目采用 Cargo workspace 多成员结构,包含三个 crate: - -### minicpm-core - -核心模型定义,包含: - -- `LlamaConfig` — 模型配置(从 `config.json` 加载) -- `LlamaForCausalLM` — 因果语言模型主体 -- `LlamaKVCache` — KV 缓存结构 -- `EosTokenId` — EOS token 标识(支持单个或多个) -- 各模块实现:Attention、Decoder、FFN、RMSNorm、RoPE - -### minicpm-convert - -模型格式转换工具,负责将 HuggingFace safetensors 格式的权重转换为 Burn MPK 格式: - -- `export_model()` — 完整转换流程(加载 safetensors → 构建模型 → 导出 MPK) -- 支持 BF16 / F16 / F32 精度输入 -- 支持 `tie_word_embeddings` 权重共享 - -### minicpm-inference - -推理功能封装,提供高层 API: - -- `MiniCPM` — 高层封装,整合模型 + tokenizer + 推理逻辑 -- `TokenizerWrapper` — tokenizer 封装,支持 MiniCPM5 chat template -- `GenerationConfig` — 生成配置(max_new_tokens、temperature、top_p) -- `generate_with_cache()` — 带 KV Cache 的自回归生成 -- 支持 temperature 采样、top-p 采样、greedy 解码 +``` +MiniCPM5-1B-rust/ +├── crates/ +│ ├── minicpm-core/ # 核心模型实现(Transformer、Attention、FFN) +│ ├── minicpm-inference/ # 推理引擎(生成、采样、tokenizer) +│ └── minicpm-convert/ # 模型转换库 +└── examples/ + ├── convert/ # 模型转换示例(safetensors → Burn 格式) + └── wgpu-backend/ # Wgpu GPU 推理示例 +``` ## 快速开始 -### 1. 转换模型 +### 1. 准备模型 -首先将 HuggingFace 格式的 MiniCPM5-1B 模型转换为 Burn MPK 格式: - -```rust -use minicpm_convert::export_model; -use burn::backend::Wgpu; -use std::path::Path; - -fn main() -> anyhow::Result<()> { - let device = Default::default(); - - export_model::( - Path::new("MiniCPM5-1B/model.safetensors"), - Path::new("MiniCPM5-1B/config.json"), - Path::new("MiniCPM5-1B-burn"), - &device, - )?; - - Ok(()) -} -``` - -转换完成后,`MiniCPM5-1B-burn/` 目录下会生成 `model.mp` 文件。 - -### 2. 推理使用 - -使用 `MiniCPM` 高层 API 进行文本生成: - -```rust -use minicpm_inference::{MiniCPM, GenerationConfig}; -use burn::backend::Wgpu; - -fn main() -> anyhow::Result<()> { - let device = Default::default(); - - // 加载模型 - let model = MiniCPM::::load( - "MiniCPM5-1B-burn/model", - "MiniCPM5-1B/config.json", - "MiniCPM5-1B/tokenizer.json", - &device, - )?; - - // 生成配置 - let gen_config = GenerationConfig { - max_new_tokens: Some(512), - temperature: 0.7, - top_p: 0.8, - }; - - // 生成回答(think = true 启用思考模式) - let response = model.generate("用 Rust 写一个 Hello World", true, &gen_config)?; - - println!("{}", response); - - Ok(()) -} -``` - -## 移植到其他项目 - -### 依赖配置 - -在你的 `Cargo.toml` 中添加: - -```toml -[dependencies] -minicpm-inference = { path = "../MiniCPM5-1B-rust/crates/minicpm-inference" } -burn = { version = "0.21", features = ["std", "wgpu"] } -anyhow = "1.0" -``` - -> 也可以根据需要选择其他 backend(如 `tch-gpu`、`cuda` 等)。 - -### 最小示例 - -```rust -use minicpm_inference::{MiniCPM, GenerationConfig}; -use burn::backend::Wgpu; - -fn main() -> anyhow::Result<()> { - let device = Default::default(); - - let model = MiniCPM::::load( - "model", - "config.json", - "tokenizer.json", - &device, - )?; - - let config = GenerationConfig { - max_new_tokens: Some(256), - temperature: 1.0, - top_p: 1.0, - }; - - let output = model.generate("你好", false, &config)?; - println!("{}", output); - - Ok(()) -} -``` - -## 模型文件准备 - -`MiniCPM5-1B/` 目录需要包含以下文件: +将 MiniCPM5-1B safetensors 模型放到 `MiniCPM5-1B/` 目录: ``` MiniCPM5-1B/ -├── config.json # 模型配置文件 -├── model.safetensors # safetensors 格式权重 -└── tokenizer.json # tokenizer 配置 +├── model-00000-of-00001.safetensors +├── config.json +└── tokenizer.json ``` -转换后 Burn 模型目录结构: +### 2. 转换模型 -``` -MiniCPM5-1B-burn/ -└── model.mp # Burn MPK 格式权重 +```bash +cargo run --release -p convert ``` -## 性能说明 +转换完成后会生成 `model/` 目录(全精度 f32,Burn mpk 格式)。 -| Backend | 设备 | 速度 | 显存占用 | -|---------|------|------|----------| -| WGPU (Vulkan) | RTX 4060 | ~10 tokens/s | ~4 GB (F32) | +### 3. 运行推理 -> 以上数据仅供参考,实际性能因硬件配置、生成长度等因素而异。 +```bash +# 普通模式 +cargo run --release -p wgpu-backend -## 许可证 +# 开启思考模式 +cargo run --release -p wgpu-backend -- --think +``` + +## 使用说明 + +### wgpu-backend 命令行参数 + +| 参数 | 说明 | +|------|------| +| `--think` | 开启思考模式,模型会在回答前进行推理思考 | + +### GenerationConfig + +```rust +GenerationConfig { + max_new_tokens: Some(1200), // 最大生成 token 数 + temperature: 0.7, // 温度,越高越随机 + top_p: 0.95, // nucleus sampling 参数 +} +``` + +### 作为库使用 + +```rust +use burn::backend::{wgpu::WgpuDevice, Wgpu}; +use minicpm_inference::{GenerationConfig, MiniCPM}; + +let device = WgpuDevice::default(); +let model = MiniCPM::::load( + "model/model", + "config.json", + "tokenizer.json", + &device, +)?; + +let config = GenerationConfig { + max_new_tokens: Some(500), + temperature: 0.7, + top_p: 0.95, +}; + +// 流式生成 +let stream = model.generate_stream("你好", false, &config)?; +for text in stream { + print!("{}", text); +} +``` + +## 发布构建 + +```bash +# Release 构建(启用 LTO + 最高优化级别) +cargo build --release + +# 发布到 gitea registry +cargo publish -p minicpm-core --registry gitea +cargo publish -p minicpm-inference --registry gitea +cargo publish -p minicpm-convert --registry gitea +``` + +Release profile 配置: +- `opt-level = 3`:最高优化级别 +- `lto = true`:链接时优化 +- `codegen-units = 1`:单代码生成单元,最大化优化 + +## 依赖 + +- Rust 1.75+ +- 支持 Wgpu 的 GPU(CUDA / Metal / Vulkan / DX12) + +## License MIT