Skip to content

Commit 9c8fdb6

Browse files
committed
[LLM:Feature] Add segment converter and runtime
1 parent 8ecf6b8 commit 9c8fdb6

36 files changed

Lines changed: 8137 additions & 20 deletions

docs/transformers/llm.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,39 @@ python llmexport.py \
179179
cmake .. -DMNN_BUILD_CONVERTER=ON && make -j16
180180
```
181181
编译完成后 `build/` 目录下会生成 `MNNConvert` 可执行文件,`llmexport.py` 默认会在 `../../../build/` 下查找该工具;也可以通过 `--mnnconvert` 选项显式指定 MNNConvert 路径。若未提供本地 MNNConvert,脚本会回退到 pymnn(需先安装 `pip install MNN`)。此方案目前支持导出4bit和8bit模型。
182+
- 导出 segment 形式的 MNN LLM,使用 `--export mnn --segment`。该模式从 safetensors 权重和 workflow JSON 直接生成多个 MNN 子图,跳过 ONNX 中间文件,适合在 Metal 等后端上复用 decoder、logit、embedding 等 segment 模型。默认会在 `resource/*.json` 中查找匹配的 workflow,也可以通过 `--workflow /path/to/workflow.json` 显式指定。
183+
184+
```bash
185+
cd transformers/llm/export
186+
python3 llmexport.py \
187+
--path /path/to/Qwen3-0.6B \
188+
--export mnn \
189+
--segment \
190+
--dst_path ./model
191+
```
192+
193+
segment 导出目录包含:
194+
195+
```text
196+
model/
197+
├── config.json # llm_demo 入口配置,包含 "mnn_llm_version": "segment"
198+
├── llm_config.json # 模型结构和模板配置
199+
├── tokenizer.mtok
200+
├── embed.mnn
201+
├── decoder.mnn
202+
├── decoder.mnn.weight
203+
├── logit.mnn
204+
├── logit.mnn.weight
205+
└── logit_topkv_1.mnn
206+
```
207+
208+
运行 segment 模型时需要使用生成的 `config.json`
209+
210+
```bash
211+
./llm_demo transformers/llm/export/model/config.json /path/to/prompt.txt
212+
```
213+
214+
C++ 运行时需启用 `MNN_BUILD_LLM=ON`,并打开 `MNN_LLM_SUPPORT_SEGMENT`(默认开启)。segment 路径当前仅支持 `--export mnn`,不支持 `--export onnx`
182215
- 如果直接转为mnn模型遇到问题,或者需要其他bits数的量化(如5bit/6bit),可以先将模型先转为onnx模型,使用`--export onnx`,然后使用./MNNConvert工具将onnx模型转为mnn模型:
183216

184217
```
@@ -197,7 +230,7 @@ usage: llmexport.py [-h] --path PATH [--type TYPE] [--tokenizer_path TOKENIZER_P
197230
[--gptq_path GPTQ_PATH] [--dst_path DST_PATH] [--verbose] [--test TEST] [--export EXPORT]
198231
[--onnx_slim] [--quant_bit QUANT_BIT] [--quant_block QUANT_BLOCK]
199232
[--lm_quant_bit LM_QUANT_BIT] [--mnnconvert MNNCONVERT] [--ppl] [--awq] [--omni] [--sym] [--seperate_embed]
200-
[--lora_split]
233+
[--lora_split] [--segment] [--workflow WORKFLOW]
201234
202235
llm_exporter
203236
@@ -219,6 +252,8 @@ optional arguments:
219252
--verbose Whether or not to print verbose.
220253
--test TEST test model inference with query `TEST`.
221254
--export EXPORT export model to an onnx/mnn model.
255+
--segment export segment MNN LLM from safetensors workflow directly, without ONNX export.
256+
--workflow WORKFLOW workflow json for --segment safetensors conversion. If absent, search resource/*.json.
222257
--onnx_slim Whether or not to use onnx-slim.
223258
--quant_bit QUANT_BIT
224259
mnn quant bit, 4 or 8, default is 4.
@@ -1158,4 +1193,4 @@ adb push model /data/local/tmp/MNN/model
11581193
```
11591194
cd ${MNN_ROOT}
11601195
project/android/testCommon.sh ./llm_demo model/config_mlda.json
1161-
```
1196+
```

resource/qwen3_hf_0.6b.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"models": [
3+
{
4+
"name": "hf_decoder",
5+
"blocks": [
6+
{
7+
"type": "QwenTransformer",
8+
"hiddenSize": 1024,
9+
"headDim": 128,
10+
"numHead": 16,
11+
"kvNumHead": 8,
12+
"number": 28,
13+
"max_position_embeddings": 40960
14+
}
15+
]
16+
},
17+
{
18+
"name": "logit",
19+
"blocks": [
20+
{
21+
"type": "InnerProduct",
22+
"prefix": "lm_head"
23+
},
24+
{
25+
"type": "TieEmbedding"
26+
},
27+
{
28+
"type": "TopKV",
29+
"K": [1, 5]
30+
}
31+
]
32+
}
33+
]
34+
}

skills/support-new-llm/SKILL.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
name: support-new-llm
3-
description: 为 MNN 框架添加新的 LLM 模型支持。支持从 HuggingFace/ModelScope 下载模型,分析架构,添加映射,Hook 对齐测试,导出 MNN 模型。采用 TDD 模式,分 6 步执行,每步有独立测试标准。
3+
description: 为 MNN 框架添加新的 LLM 模型支持。支持从 HuggingFace/ModelScope 下载模型,分析架构,添加映射,Hook 对齐测试,导出 MNN 模型;当用户明确要求 safetensors/segment/workflow/MNNConvert -f ST 时,走 safetensors segment 补充分支。采用 TDD 模式,分 6 步执行,每步有独立测试标准。
44
---
55

66
# MNN LLM 新模型支持 SKILL
77

8-
> **触发条件**:当用户请求支持/添加/适配一个新的 LLM 模型时触发。常见表述包括:"支持xxx模型"、"添加xxx模型支持"、"适配xxx"、"导出xxx模型"等。
8+
> **触发条件**:当用户请求支持/添加/适配一个新的 LLM 模型时触发。常见表述包括:"支持xxx模型"、"添加xxx模型支持"、"适配xxx"、"导出xxx模型"等。若用户明确提到 `safetensors``--segment``workflow.json``MNNConvert -f ST` 或“绕过 ONNX 直接转换”,先读 `safetensors-segment.md`
99
1010
## 概述
1111

@@ -20,6 +20,8 @@ MNN 的模型导出本质上是**对照 HuggingFace transformers 库中原始模
2020
3. 用 Python `--test` 验证映射正确性
2121
4. 导出 MNN 模型并用 C++ 引擎验证
2222

23+
默认导出链路是 `llmexport.py --export mnn`。如果目标是 safetensors segment 格式,则使用 `llmexport.py --export mnn --segment`,按 `safetensors-segment.md` 先校验 workflow、safetensors key 和 builder 约定。
24+
2325
### 注意事项
2426

2527
> **🚨 严禁将输出错误归因于"量化精度不够"**:4bit 量化的 0.5B 小模型都能正确输出。如果 C++ 输出完全不对(如图片识别不出、输出乱码),**一定是实现细节没有与 HF 对齐**,必须逐步 dump 数据对比定位,不要靠猜。
@@ -44,6 +46,9 @@ MNN 的模型导出本质上是**对照 HuggingFace transformers 库中原始模
4446
| `transformers/llm/export/utils/audio.py` | Audio Encoder 实现 | 音频模型 |
4547
| `transformers/llm/export/utils/custom_op.py` | 自定义算子导出 | 新算子时 |
4648
| `transformers/llm/export/llmexport.py` | 导出主流程入口 | 偶尔 |
49+
| `transformers/llm/export/segment.py` | safetensors segment 导出入口 | segment 分支 |
50+
| `resource/*.json` | safetensors workflow 模板 | segment 分支 |
51+
| `tools/converter/source/safetensors/*.cpp` | safetensors converter / builder 实现 | segment 分支 |
4752

4853
---
4954

@@ -98,6 +103,7 @@ MNN 的模型导出本质上是**对照 HuggingFace transformers 库中原始模
98103
| Tier 4 (音频模型) | 1 → 2 → 3 → 5 → 4 | 需要 audio.py |
99104
| Tier 5 (视觉模型) | 1 → 2 → 3 → 5 → 4 | 需要 vision.py |
100105
| Tier 6 (全新架构) | 1 → 2 → 6 → 3 → 4 | 需要新算子(如叠加 Tier 4/5 则加入 step5) |
106+
| Safetensors segment | 1 → S1/S2/S3 → S4/S5 | 明确要求 `--segment` / workflow / `MNNConvert -f ST` 时,参见 `safetensors-segment.md` |
101107

102108
---
103109

@@ -185,8 +191,10 @@ modeling_*.py 中是否有全新的 Attention 类型(非标准 SDPA)?
185191

186192
**在开始之前,建议先浏览 `common-pitfalls.md`**,了解已知的常见问题和解决方案(RoPE 变体、dtype 级联、Jinja 限制、stop token、残差模式、MoE 支持要点、FakeLinear axis 陷阱、**do_map 静默失败与 rope_theta 间接存储**、非标准模型加载等)。
187193

194+
**Safetensors segment 分支的常见问题**:workflow 超参与权重 shape 不匹配、builder 预期 key 前缀不存在、自动 workflow 匹配选错、segment runtime 没启用。详见 `safetensors-segment.md`
195+
188196
---
189197

190198
## 开始执行
191199

192-
**现在请打开 `skills/support-new-llm/step1-analyze.md`,开始步骤 1。**
200+
**现在请打开 `skills/support-new-llm/step1-analyze.md`,开始步骤 1。若用户明确要求 safetensors segment 导出,同时打开 `skills/support-new-llm/safetensors-segment.md`**

0 commit comments

Comments
 (0)