Instructions to use HelloSun/Experiment_1 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use HelloSun/Experiment_1 with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/Experiment_1:Q4_K_M # Run inference directly in the terminal: llama cli -hf HelloSun/Experiment_1:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/Experiment_1:Q4_K_M # Run inference directly in the terminal: llama cli -hf HelloSun/Experiment_1:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf HelloSun/Experiment_1:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf HelloSun/Experiment_1:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf HelloSun/Experiment_1:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf HelloSun/Experiment_1:Q4_K_M
Use Docker
docker model run hf.co/HelloSun/Experiment_1:Q4_K_M
- Llama new
- LM Studio
- Jan
- Ollama
How to use HelloSun/Experiment_1 with Ollama:
ollama run hf.co/HelloSun/Experiment_1:Q4_K_M
- Unsloth Desktop
- Docker Model Runner
How to use HelloSun/Experiment_1 with Docker Model Runner:
docker model run hf.co/HelloSun/Experiment_1:Q4_K_M
- Lemonade
How to use HelloSun/Experiment_1 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull HelloSun/Experiment_1:Q4_K_M
Run and chat with the model
lemonade run user.Experiment_1-Q4_K_M
List all available models
lemonade list
- Atomic Chat
Commit ·
bb7b6d5
0
Parent(s):
Duplicate from HelloSun/openPangu-R-7B-2512-Q4KM-gguf
Browse files- .gitattributes +36 -0
- LICENSE +34 -0
- README.md +90 -0
- build_openpangu_r.sh +83 -0
- openPangu-R-7B-2512-Q4_K_M.gguf +3 -0
- openpangu-r-llama.cpp-v0.7.0.patch +710 -0
.gitattributes
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
openPangu-R-7B-2512-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OPENPANGU MODEL LICENSE AGREEMENT VERSION 1.0
|
| 2 |
+
|
| 3 |
+
This OPENPANGU MODEL LICENSE AGREEMENT VERSION 1.0 (the "Agreement") is a legal agreement between You and Huawei Technologies Co., Ltd. ("Huawei", "We" or "Us"), and it governs Your reproducing, use, modification, and distribution of openPangu as made available by Huawei under this Agreement.
|
| 4 |
+
|
| 5 |
+
By using, reproducing, modifying, distributing, performing or displaying any portion or element of openPangu, or otherwise accepting the terms of this Agreement, You agree to be bound by this Agreement.
|
| 6 |
+
|
| 7 |
+
1. Definitions.
|
| 8 |
+
1.1. “openPangu” or “Model” means openPangu large language models and software, including trained model weights, parameters (including optimizer states), accompanying source code and scripts released under this Agreement.
|
| 9 |
+
1.2. “Derivative Model” means all (1) modifications to the Model, (2) works based on the Model, and (3) any other derivative works of the Model. For clarity, information or content results from operating or otherwise using the Model is not a Derivative Model.
|
| 10 |
+
1.3. “You” or “Your” means an individual or Legal Entity exercising permissions granted by this Agreement and/or using the Model for any purpose.
|
| 11 |
+
1.4. “Third Party” or “Third Parties” means individuals or legal entities that are not under common control with Us or You.
|
| 12 |
+
|
| 13 |
+
2. License Grant. Subject to Your full compliance with the terms and conditions of this Agreement, We hereby grant to You a perpetual, worldwide, non-exclusive, non-transferable, no-charge, royalty-free license (except as stated in Section 3) to use, reproduce, modify, and distribute the Model.
|
| 14 |
+
|
| 15 |
+
3. Conditions for License Grant. You represent and warrant that You will not, access, download, install, run, deploy, integrate, modify, or otherwise use the Model, directly or indirectly, within the European Union.
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
4. Redistribution.
|
| 19 |
+
4.1. If You distribute the Model or Derivative Model, You shall retain in Your distribution (1) a copy of this agreement, and (2) all copyright notices and other notices of origin included in the Model that are applicable to Your distribution.
|
| 20 |
+
4.2. Further, if You distribute or make available to Third Parties a product or service (including another AI model) based on the Model, You are required to (1) display the acknowledgement “Powered by openPangu” and (2) include a trademark notice “openPangu is a trademark of Huawei Technologies Co., Ltd.” on related webpages, user manuals, product documentations or other advertising materials mentioning features of the Model.
|
| 21 |
+
4.3. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for Derivative Model made by You as a whole, provided Your use, reproduction, and distribution of the Model otherwise complies with the terms and conditions of this Agreement.
|
| 22 |
+
|
| 23 |
+
5. Ownership. We do not claim ownership to any information or content generated using the Model or Derivative Model that are made by You. You are solely responsible for evaluating the accuracy and appropriateness of such information or content for Your use case.
|
| 24 |
+
|
| 25 |
+
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of Huawei, except as required for complying with Section 4.2.
|
| 26 |
+
|
| 27 |
+
7. Indemnity. You will indemnify and hold harmless Huawei from and against any claim by any third party arising out of or related to Your use or distribution of the Model or Derivative Model made by You (e.g. a violation against Section 3). For avoidance of doubt, “third party” in this clause include supervisory authorities.
|
| 28 |
+
|
| 29 |
+
8. THE MODEL IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NONINFRINGEMENT, ACCURACY, OR THE ABSENCE OF LATENT OR OTHER DEFECTS OR ERRORS, WHETHER OR NOT DISCOVERABLE, ALL TO THE GREATEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW.
|
| 30 |
+
|
| 31 |
+
9. IN NO EVENT SHALL WE BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE MODEL, IN WHOLE OR IN PART, NO MATTER HOW IT’S CAUSED OR THE LEGAL THEORY IT IS BASED ON, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
END OF THE TERMS AND CONDITIONS
|
README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: openpangu-model-license-agreement-1.0
|
| 4 |
+
license_link: LICENSE
|
| 5 |
+
base_model: openpangu/openPangu-R-7B-2512
|
| 6 |
+
library_name: gguf
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
# openPangu-R-7B-2512-Q4_K_M (GGUF)
|
| 10 |
+
|
| 11 |
+
Powered by openPangu. openPangu is a trademark of Huawei Technologies Co., Ltd.
|
| 12 |
+
|
| 13 |
+
Q4_K_M GGUF conversion of [openpangu/openPangu-R-7B-2512](https://huggingface.co/openpangu/openPangu-R-7B-2512).
|
| 14 |
+
This is an unofficial community conversion, not released or endorsed by Huawei.
|
| 15 |
+
|
| 16 |
+
## Important
|
| 17 |
+
|
| 18 |
+
- **Upstream llama.cpp does not support this model.** The GGUF uses the architecture name `openpangu-r`,
|
| 19 |
+
which exists only in the patch in this repository. The patch targets **llama.cpp v0.7.0** (latest stable release).
|
| 20 |
+
- Tested on CPU only (x86-64, AVX-512). GPU backends were not tested.
|
| 21 |
+
|
| 22 |
+
## Quick start
|
| 23 |
+
|
| 24 |
+
```bash
|
| 25 |
+
bash build_openpangu_r.sh # clones llama.cpp v0.7.0, applies the patch, builds, downloads the GGUF
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
Options: `SKIP_MODEL=1` skips the download; `HF_TOKEN` is only needed if this repository is private.
|
| 29 |
+
The script checks the sha256 of the patch and the GGUF.
|
| 30 |
+
|
| 31 |
+
Run (raw prompt, Chinese chat template of the model):
|
| 32 |
+
|
| 33 |
+
```bash
|
| 34 |
+
./llama.cpp/build/bin/llama-completion -m models/openPangu-R-7B-2512-Q4_K_M.gguf -no-cnv --temp 0 -n 128 --no-display-prompt \
|
| 35 |
+
-p "[unused9]系统:你是一个有帮助的助手。[unused10][unused9]用户:用一句话介绍什么是大语言模型。 /no_think[unused10][unused9]助手:[unused16]"
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
Prompt format: `[unused9]系统:…[unused10][unused9]用户:…[unused10][unused9]助手:[unused16]`.
|
| 39 |
+
Append ` /no_think` to a user message for fast (non-thinking) answers. The answer follows `[unused17]`; generation ends with `[unused10]`.
|
| 40 |
+
|
| 41 |
+
## Conversion
|
| 42 |
+
|
| 43 |
+
1. `convert_hf_to_gguf.py` (patched) with `--outtype f16` from the BF16 safetensors. The MTP module (layer 27) and the second final norm are dropped.
|
| 44 |
+
2. `llama-quantize <f16.gguf> <out.gguf> Q4_K_M`. Sinks and the conv weight are kept in F32.
|
| 45 |
+
|
| 46 |
+
## Verification (done in this environment)
|
| 47 |
+
|
| 48 |
+
- **Reference check:** a CPU fp32 reference was written from the HF modeling code. For a 33-token prompt, the top-10 logits
|
| 49 |
+
match llama.cpp F16 (max |Δlogit| ≈ 0.01). For a 484-token prompt (sliding-window layers active), the top-10 match with
|
| 50 |
+
max |Δlogit| ≈ 0.03. Turning the sliding window off in the reference changes the logits by about 6, so the window is verified.
|
| 51 |
+
- **Greedy decoding:** llama.cpp F16 matches the fp32 reference token by token (11 tokens checked).
|
| 52 |
+
- **Batching:** F16 gives the same results with prompt decoding in one batch, in chunks of 4, and token by token.
|
| 53 |
+
- **Long context:** a fact placed about 400 tokens before the question was answered correctly (`7312`).
|
| 54 |
+
- **Multi-turn:** a second user turn appended to the same context is answered in context.
|
| 55 |
+
|
| 56 |
+
Sample outputs (Q4_K_M):
|
| 57 |
+
|
| 58 |
+
| prompt | output |
|
| 59 |
+
|---|---|
|
| 60 |
+
| 用一句话介绍什么是大语言模型(快思考) | 大语言模型是一种基于大量文本数据训练而成的人工智能模型,能够理解和生成人类语言,广泛应用于自然语言处理任务。 |
|
| 61 |
+
| 写一首关于秋天的四行短诗(快思考) | 秋风轻拂叶纷飞,/ 金黄铺满小径长。/ 寒蝉低唱夕阳下,/ 一缕炊烟入梦乡。 |
|
| 62 |
+
| 一个班有30名学生,其中2/5是女生,女生有多少人?(慢思考) | 12人 |
|
| 63 |
+
| 123 + 456 等于多少?(慢思考) | 579 |
|
| 64 |
+
|
| 65 |
+
Note: in fast mode the model once answered `123 + 456 = 679`. The fp32 reference gives the same answer for that prompt, so this is a model
|
| 66 |
+
behavior, not a conversion or implementation error. Thinking mode answers 579.
|
| 67 |
+
|
| 68 |
+
## Known limitations
|
| 69 |
+
|
| 70 |
+
- **One sequence per batch.** A batch with more than one sequence aborts. The conv history of the merge layers is kept inside the model
|
| 71 |
+
and follows one sequence decoded contiguously. Prompt-cache reuse, `seq_rm`, and multi-slot serving are not supported.
|
| 72 |
+
- The MTP (next-token) head is not included and not used.
|
| 73 |
+
- Hadamard-rotated (quantized) KV cache is not supported; use the default f16 KV cache.
|
| 74 |
+
- `llama-server` was not validated.
|
| 75 |
+
|
| 76 |
+
## License and notices
|
| 77 |
+
|
| 78 |
+
The model and derivative works are licensed under the **OPENPANGU MODEL LICENSE AGREEMENT VERSION 1.0** (see `LICENSE`).
|
| 79 |
+
|
| 80 |
+
- **EU restriction (Section 3):** you must not access, download, install, run, deploy, integrate, modify, or otherwise use this model within the European Union.
|
| 81 |
+
- **Acknowledgment (Section 4.2):** "Powered by openPangu" and the trademark notice "openPangu is a trademark of Huawei Technologies Co., Ltd." must appear on pages, manuals, or materials that describe features of the model.
|
| 82 |
+
- The model is provided "AS IS" without warranty. Outputs are generated automatically and may be inaccurate.
|
| 83 |
+
|
| 84 |
+
## Files and checksums
|
| 85 |
+
|
| 86 |
+
| file | sha256 |
|
| 87 |
+
|---|---|
|
| 88 |
+
| `openPangu-R-7B-2512-Q4_K_M.gguf` | `efeb81edbf64ad9d7a80254332f3128d86deec589ee39315a3c1f7ec1aa5f10a` |
|
| 89 |
+
| `openpangu-r-llama.cpp-v0.7.0.patch` | `b5f302da0cece9c6bc717982d820f8b3e6ca0970f8f32b549efb41ef0d6b8773` |
|
| 90 |
+
| `LICENSE` | `747083c8c24995c75ed641d5c031a95a859b1ec37cd3deeb033425a75249a3cb` |
|
build_openpangu_r.sh
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# One-click setup for openPangu-R-7B-2512 (Q4_K_M GGUF):
|
| 3 |
+
# 1. clones llama.cpp v0.7.0 (stable release)
|
| 4 |
+
# 2. applies the openPangu-R patch (adds the "openpangu-r" architecture)
|
| 5 |
+
# 3. builds llama-cli / llama-completion / llama-quantize
|
| 6 |
+
# 4. downloads the Q4_K_M GGUF and checks its sha256
|
| 7 |
+
#
|
| 8 |
+
# usage: bash build_openpangu_r.sh [install_dir] (default: ./openpangu-r)
|
| 9 |
+
# env: SKIP_MODEL=1 do not download the GGUF
|
| 10 |
+
# HF_TOKEN=... only needed if the Hugging Face repo is private; read from the
|
| 11 |
+
# environment and never written to disk
|
| 12 |
+
set -euo pipefail
|
| 13 |
+
|
| 14 |
+
LLAMA_TAG=v0.7.0
|
| 15 |
+
HF_REPO=HelloSun/openPangu-R-7B-2512-Q4KM
|
| 16 |
+
PATCH_NAME=openpangu-r-llama.cpp-v0.7.0.patch
|
| 17 |
+
PATCH_SHA256=b5f302da0cece9c6bc717982d820f8b3e6ca0970f8f32b549efb41ef0d6b8773
|
| 18 |
+
GGUF_NAME=openPangu-R-7B-2512-Q4_K_M.gguf
|
| 19 |
+
GGUF_SHA256=efeb81edbf64ad9d7a80254332f3128d86deec589ee39315a3c1f7ec1aa5f10a
|
| 20 |
+
|
| 21 |
+
# HF_BASE can point to a local mirror (file:// or http://) for testing
|
| 22 |
+
HF_BASE=${HF_BASE:-https://huggingface.co/${HF_REPO}/resolve/main}
|
| 23 |
+
|
| 24 |
+
ROOT=$(mkdir -p "${1:-$PWD/openpangu-r}" && cd "${1:-$PWD/openpangu-r}" && pwd)
|
| 25 |
+
cd "$ROOT"
|
| 26 |
+
|
| 27 |
+
for tool in git cmake make g++ curl sha256sum; do
|
| 28 |
+
command -v "$tool" >/dev/null || { echo "error: missing tool: $tool" >&2; exit 1; }
|
| 29 |
+
done
|
| 30 |
+
|
| 31 |
+
AUTH=()
|
| 32 |
+
if [ -n "${HF_TOKEN:-}" ]; then
|
| 33 |
+
AUTH=(-H "Authorization: Bearer ${HF_TOKEN}")
|
| 34 |
+
fi
|
| 35 |
+
|
| 36 |
+
check_sha() { # file expected_sha256
|
| 37 |
+
echo "$2 $1" | sha256sum -c --quiet - || { echo "error: sha256 mismatch for $1" >&2; exit 1; }
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
echo "[1/4] llama.cpp $LLAMA_TAG"
|
| 41 |
+
if [ ! -d llama.cpp ]; then
|
| 42 |
+
git clone --depth 1 --branch "$LLAMA_TAG" https://github.com/ggml-org/llama.cpp.git llama.cpp
|
| 43 |
+
fi
|
| 44 |
+
if [ "$(git -C llama.cpp describe --tags --exact-match 2>/dev/null || true)" != "$LLAMA_TAG" ]; then
|
| 45 |
+
echo "error: $ROOT/llama.cpp is not at tag $LLAMA_TAG" >&2
|
| 46 |
+
exit 1
|
| 47 |
+
fi
|
| 48 |
+
|
| 49 |
+
echo "[2/4] openPangu-R patch"
|
| 50 |
+
curl -fsSL "${AUTH[@]}" -o "$PATCH_NAME" "$HF_BASE/$PATCH_NAME"
|
| 51 |
+
check_sha "$PATCH_NAME" "$PATCH_SHA256"
|
| 52 |
+
if git -C llama.cpp apply --reverse --check "$ROOT/$PATCH_NAME" 2>/dev/null; then
|
| 53 |
+
echo "patch already applied"
|
| 54 |
+
else
|
| 55 |
+
git -C llama.cpp apply --check "$ROOT/$PATCH_NAME"
|
| 56 |
+
git -C llama.cpp apply "$ROOT/$PATCH_NAME"
|
| 57 |
+
echo "patch applied"
|
| 58 |
+
fi
|
| 59 |
+
|
| 60 |
+
echo "[3/4] build"
|
| 61 |
+
cmake -S llama.cpp -B llama.cpp/build -DCMAKE_BUILD_TYPE=Release -DLLAMA_CURL=OFF -DLLAMA_BUILD_TESTS=OFF
|
| 62 |
+
cmake --build llama.cpp/build -j"$(nproc)" --target llama-cli llama-completion llama-quantize
|
| 63 |
+
|
| 64 |
+
echo "[4/4] model"
|
| 65 |
+
MODEL="$ROOT/models/$GGUF_NAME"
|
| 66 |
+
if [ "${SKIP_MODEL:-0}" = "1" ]; then
|
| 67 |
+
echo "skipped (SKIP_MODEL=1)"
|
| 68 |
+
else
|
| 69 |
+
mkdir -p "$ROOT/models"
|
| 70 |
+
if [ ! -f "$MODEL" ]; then
|
| 71 |
+
curl -fL --retry 3 "${AUTH[@]}" -o "$MODEL.part" "$HF_BASE/$GGUF_NAME"
|
| 72 |
+
mv "$MODEL.part" "$MODEL"
|
| 73 |
+
fi
|
| 74 |
+
check_sha "$MODEL" "$GGUF_SHA256"
|
| 75 |
+
echo "model ready: $MODEL"
|
| 76 |
+
fi
|
| 77 |
+
|
| 78 |
+
cat <<EOF
|
| 79 |
+
|
| 80 |
+
done. try:
|
| 81 |
+
$ROOT/llama.cpp/build/bin/llama-completion -m $MODEL -no-cnv --temp 0 -n 128 --no-display-prompt \\
|
| 82 |
+
-p "[unused9]系统:你是一个有帮助的助手。[unused10][unused9]用户:用一句话介绍什么是大语言模型。 /no_think[unused10][unused9]助手:[unused16]"
|
| 83 |
+
EOF
|
openPangu-R-7B-2512-Q4_K_M.gguf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:efeb81edbf64ad9d7a80254332f3128d86deec589ee39315a3c1f7ec1aa5f10a
|
| 3 |
+
size 5067641664
|
openpangu-r-llama.cpp-v0.7.0.patch
ADDED
|
@@ -0,0 +1,710 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
diff --git a/conversion/__init__.py b/conversion/__init__.py
|
| 2 |
+
index 8ce4cb7..f7455f4 100644
|
| 3 |
+
--- a/conversion/__init__.py
|
| 4 |
+
+++ b/conversion/__init__.py
|
| 5 |
+
@@ -228,6 +228,7 @@ TEXT_MODEL_MAP: dict[str, str] = {
|
| 6 |
+
"PLaMo3ForCausalLM": "plamo",
|
| 7 |
+
"PaddleOCRVLForConditionalGeneration": "ernie",
|
| 8 |
+
"PanguEmbeddedForCausalLM": "pangu",
|
| 9 |
+
+ "PanguEmbeddedRForCausalLM": "pangu",
|
| 10 |
+
"Phi3ForCausalLM": "phi",
|
| 11 |
+
"Phi4ForCausalLMV": "phi",
|
| 12 |
+
"PhiForCausalLM": "phi",
|
| 13 |
+
diff --git a/conversion/base.py b/conversion/base.py
|
| 14 |
+
index a5a80f2..1a5276b 100644
|
| 15 |
+
--- a/conversion/base.py
|
| 16 |
+
+++ b/conversion/base.py
|
| 17 |
+
@@ -3121,6 +3121,12 @@ def get_model_architecture(hparams: dict[str, Any], model_type: ModelType) -> st
|
| 18 |
+
arch = text_config["architectures"][0]
|
| 19 |
+
elif model_type == ModelType.MMPROJ and vision_config.get("architectures") is not None:
|
| 20 |
+
arch = vision_config["architectures"][0]
|
| 21 |
+
+
|
| 22 |
+
+ # openPangu-R reuses the PanguEmbedded architecture name, but its config carries the
|
| 23 |
+
+ # sliding-window / attention-sink / gate / conv extensions: route it to its own class
|
| 24 |
+
+ if model_type == ModelType.TEXT and arch == "PanguEmbeddedForCausalLM" and "param_sink_number" in hparams:
|
| 25 |
+
+ arch = "PanguEmbeddedRForCausalLM"
|
| 26 |
+
+
|
| 27 |
+
if arch is None:
|
| 28 |
+
raise ValueError("Failed to detect model architecture")
|
| 29 |
+
return arch
|
| 30 |
+
diff --git a/conversion/pangu.py b/conversion/pangu.py
|
| 31 |
+
index 74c7653..14b2250 100644
|
| 32 |
+
--- a/conversion/pangu.py
|
| 33 |
+
+++ b/conversion/pangu.py
|
| 34 |
+
@@ -45,3 +45,71 @@ class PanguEmbeddedModel(TextModel):
|
| 35 |
+
logger.info("Skipping tied output layer 'lm_head.weight'")
|
| 36 |
+
return
|
| 37 |
+
yield from super().modify_tensors(data_torch, name, bid)
|
| 38 |
+
+
|
| 39 |
+
+
|
| 40 |
+
+@ModelBase.register("PanguEmbeddedRForCausalLM")
|
| 41 |
+
+@ModelBase.example("openpangu/openPangu-R-7B-2512")
|
| 42 |
+
+class PanguEmbeddedRModel(TextModel):
|
| 43 |
+
+ # openPangu-R: PanguEmbedded config + interleaved sliding-window/full attention,
|
| 44 |
+
+ # per-layer attention sinks (learned K/V prefix), gated attention with per-head RMSNorm,
|
| 45 |
+
+ # partial RoPE, a causal depthwise conv merge in the first and last layers, and an MTP head
|
| 46 |
+
+ # (layer index == block_count, not used for inference).
|
| 47 |
+
+ model_arch = gguf.MODEL_ARCH.PANGU_EMBED_R
|
| 48 |
+
+
|
| 49 |
+
+ def set_vocab(self):
|
| 50 |
+
+ self._set_vocab_sentencepiece()
|
| 51 |
+
+
|
| 52 |
+
+ tokenizer_config_file = self.dir_model / 'tokenizer_config.json'
|
| 53 |
+
+ if tokenizer_config_file.is_file():
|
| 54 |
+
+ with open(tokenizer_config_file, "r", encoding="utf-8") as f:
|
| 55 |
+
+ tokenizer_config_json = json.load(f)
|
| 56 |
+
+ if "add_prefix_space" in tokenizer_config_json:
|
| 57 |
+
+ self.gguf_writer.add_add_space_prefix(tokenizer_config_json["add_prefix_space"])
|
| 58 |
+
+
|
| 59 |
+
+ def set_gguf_parameters(self):
|
| 60 |
+
+ super().set_gguf_parameters()
|
| 61 |
+
+ hparams = self.hparams
|
| 62 |
+
+ self.gguf_writer.add_vocab_size(hparams["vocab_size"])
|
| 63 |
+
+
|
| 64 |
+
+ # partial RoPE: only rotary_percent of head_dim is rotated (rounded up to an even count, as in HF)
|
| 65 |
+
+ head_dim = hparams["head_dim"]
|
| 66 |
+
+ rot_dim = int(head_dim * hparams["rotary_percent"])
|
| 67 |
+
+ rot_dim += rot_dim % 2
|
| 68 |
+
+ self.gguf_writer.add_rope_dimension_count(rot_dim)
|
| 69 |
+
+
|
| 70 |
+
+ self.gguf_writer.add_sliding_window(hparams["sliding_window"])
|
| 71 |
+
+ self.gguf_writer.add_sliding_window_pattern([t == "sliding_attention" for t in hparams["layer_types"]])
|
| 72 |
+
+
|
| 73 |
+
+ def tensor_force_quant(self, name: str, new_name: str, bid: int | None, n_dims: int) -> gguf.GGMLQuantizationType | bool:
|
| 74 |
+
+ # sinks and the conv merge are small; keep them in F32
|
| 75 |
+
+ if any(self.match_model_tensor_name(new_name, key, bid) for key in (
|
| 76 |
+
+ gguf.MODEL_TENSOR.ATTN_SINK_K,
|
| 77 |
+
+ gguf.MODEL_TENSOR.ATTN_SINK_V,
|
| 78 |
+
+ gguf.MODEL_TENSOR.FFN_MERGE_CONV,
|
| 79 |
+
+ )):
|
| 80 |
+
+ return gguf.GGMLQuantizationType.F32
|
| 81 |
+
+ return super().tensor_force_quant(name, new_name, bid, n_dims)
|
| 82 |
+
+
|
| 83 |
+
+ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
|
| 84 |
+
+ # the MTP module (layer block_count) and the second final norm are unused for inference
|
| 85 |
+
+ if (bid is not None and bid >= self.block_count) or name == "model.norms.1.weight":
|
| 86 |
+
+ return
|
| 87 |
+
+
|
| 88 |
+
+ # HF param_sink_key/value: [n_sink, n_kv_head, head_dim]
|
| 89 |
+
+ # GGUF ne = [head_dim, n_sink, n_kv_head] (key) and [n_sink, head_dim, n_kv_head] (value)
|
| 90 |
+
+ if name.endswith(".self_attn.param_sink_key"):
|
| 91 |
+
+ yield (self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_SINK_K, bid),
|
| 92 |
+
+ data_torch.permute(1, 0, 2).contiguous())
|
| 93 |
+
+ return
|
| 94 |
+
+ if name.endswith(".self_attn.param_sink_value"):
|
| 95 |
+
+ yield (self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_SINK_V, bid),
|
| 96 |
+
+ data_torch.permute(1, 2, 0).contiguous())
|
| 97 |
+
+ return
|
| 98 |
+
+
|
| 99 |
+
+ # HF depthwise Conv1d weight [n_embd, 1, 3] -> GGUF ne = [n_embd, 3]
|
| 100 |
+
+ if name.endswith(".merge_conv.weight"):
|
| 101 |
+
+ yield (self.format_tensor_name(gguf.MODEL_TENSOR.FFN_MERGE_CONV, bid),
|
| 102 |
+
+ data_torch.squeeze(1).permute(1, 0).contiguous())
|
| 103 |
+
+ return
|
| 104 |
+
+
|
| 105 |
+
+ yield from super().modify_tensors(data_torch, name, bid)
|
| 106 |
+
diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py
|
| 107 |
+
index a39d046..8a7f15a 100644
|
| 108 |
+
--- a/gguf-py/gguf/constants.py
|
| 109 |
+
+++ b/gguf-py/gguf/constants.py
|
| 110 |
+
@@ -674,6 +674,7 @@ class MODEL_ARCH(IntEnum):
|
| 111 |
+
MINIMAXM3 = auto()
|
| 112 |
+
RND1 = auto()
|
| 113 |
+
PANGU_EMBED = auto()
|
| 114 |
+
+ PANGU_EMBED_R = auto()
|
| 115 |
+
MISTRAL3 = auto()
|
| 116 |
+
EAGLE3 = auto()
|
| 117 |
+
DFLASH = auto()
|
| 118 |
+
@@ -743,6 +744,9 @@ class MODEL_TENSOR(IntEnum):
|
| 119 |
+
ATTN_ROT_EMBD = auto()
|
| 120 |
+
ATTN_SINKS = auto()
|
| 121 |
+
ATTN_GATE = auto()
|
| 122 |
+
+ ATTN_SINK_K = auto()
|
| 123 |
+
+ ATTN_SINK_V = auto()
|
| 124 |
+
+ FFN_MERGE_CONV = auto()
|
| 125 |
+
FFN_GATE_INP = auto()
|
| 126 |
+
FFN_GATE_INP_SHEXP = auto()
|
| 127 |
+
FFN_NORM = auto()
|
| 128 |
+
@@ -1479,6 +1483,7 @@ MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = {
|
| 129 |
+
MODEL_ARCH.COGVLM: "cogvlm",
|
| 130 |
+
MODEL_ARCH.RND1: "rnd1",
|
| 131 |
+
MODEL_ARCH.PANGU_EMBED: "pangu-embedded",
|
| 132 |
+
+ MODEL_ARCH.PANGU_EMBED_R: "openpangu-r",
|
| 133 |
+
MODEL_ARCH.MISTRAL3: "mistral3",
|
| 134 |
+
MODEL_ARCH.EAGLE3: "eagle3",
|
| 135 |
+
MODEL_ARCH.DFLASH: "dflash",
|
| 136 |
+
@@ -1544,6 +1549,9 @@ TENSOR_NAMES: dict[MODEL_TENSOR, str] = {
|
| 137 |
+
MODEL_TENSOR.ATTN_ROT_EMBD: "blk.{bid}.attn_rot_embd",
|
| 138 |
+
MODEL_TENSOR.ATTN_SINKS: "blk.{bid}.attn_sinks",
|
| 139 |
+
MODEL_TENSOR.ATTN_GATE: "blk.{bid}.attn_gate",
|
| 140 |
+
+ MODEL_TENSOR.ATTN_SINK_K: "blk.{bid}.attn_sink_k",
|
| 141 |
+
+ MODEL_TENSOR.ATTN_SINK_V: "blk.{bid}.attn_sink_v",
|
| 142 |
+
+ MODEL_TENSOR.FFN_MERGE_CONV: "blk.{bid}.ffn_merge_conv",
|
| 143 |
+
MODEL_TENSOR.ATTN_Q_NORM: "blk.{bid}.attn_q_norm",
|
| 144 |
+
MODEL_TENSOR.ATTN_K_NORM: "blk.{bid}.attn_k_norm",
|
| 145 |
+
MODEL_TENSOR.ATTN_OUT_NORM: "blk.{bid}.attn_output_norm",
|
| 146 |
+
@@ -5488,6 +5496,25 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
| 147 |
+
MODEL_TENSOR.FFN_DOWN,
|
| 148 |
+
MODEL_TENSOR.FFN_UP,
|
| 149 |
+
],
|
| 150 |
+
+ MODEL_ARCH.PANGU_EMBED_R: [
|
| 151 |
+
+ MODEL_TENSOR.TOKEN_EMBD,
|
| 152 |
+
+ MODEL_TENSOR.OUTPUT_NORM,
|
| 153 |
+
+ MODEL_TENSOR.OUTPUT,
|
| 154 |
+
+ MODEL_TENSOR.ATTN_NORM,
|
| 155 |
+
+ MODEL_TENSOR.ATTN_Q,
|
| 156 |
+
+ MODEL_TENSOR.ATTN_K,
|
| 157 |
+
+ MODEL_TENSOR.ATTN_V,
|
| 158 |
+
+ MODEL_TENSOR.ATTN_OUT,
|
| 159 |
+
+ MODEL_TENSOR.ATTN_GATE,
|
| 160 |
+
+ MODEL_TENSOR.ATTN_OUT_NORM,
|
| 161 |
+
+ MODEL_TENSOR.ATTN_SINK_K,
|
| 162 |
+
+ MODEL_TENSOR.ATTN_SINK_V,
|
| 163 |
+
+ MODEL_TENSOR.FFN_NORM,
|
| 164 |
+
+ MODEL_TENSOR.FFN_GATE,
|
| 165 |
+
+ MODEL_TENSOR.FFN_DOWN,
|
| 166 |
+
+ MODEL_TENSOR.FFN_UP,
|
| 167 |
+
+ MODEL_TENSOR.FFN_MERGE_CONV,
|
| 168 |
+
+ ],
|
| 169 |
+
MODEL_ARCH.MISTRAL3: [
|
| 170 |
+
MODEL_TENSOR.TOKEN_EMBD,
|
| 171 |
+
MODEL_TENSOR.OUTPUT_NORM,
|
| 172 |
+
diff --git a/gguf-py/gguf/tensor_mapping.py b/gguf-py/gguf/tensor_mapping.py
|
| 173 |
+
index 63301cc..df154b8 100644
|
| 174 |
+
--- a/gguf-py/gguf/tensor_mapping.py
|
| 175 |
+
+++ b/gguf-py/gguf/tensor_mapping.py
|
| 176 |
+
@@ -101,6 +101,7 @@ class TensorNameMap:
|
| 177 |
+
"gpt_neox.final_layer_norm", # gptneox
|
| 178 |
+
"transformer.ln_f", # gpt2 gpt-j falcon jais exaone
|
| 179 |
+
"model.norm", # llama-hf baichuan internlm2 olmoe olmo2 phimoe plamo2
|
| 180 |
+
+ "model.norms.0", # openpangu-r (final norm)
|
| 181 |
+
"norm", # llama-pth
|
| 182 |
+
"transformer.norm_f", # mpt dbrx
|
| 183 |
+
"ln_f", # refact bloom qwen gpt2
|
| 184 |
+
@@ -409,6 +410,7 @@ class TensorNameMap:
|
| 185 |
+
"encoder.layers.{bid}.norm1", # nomic-bert
|
| 186 |
+
"transformer.decoder_layer.{bid}.rms_norm_1", # Grok
|
| 187 |
+
"model.layers.{bid}.post_attn_norm", # grok-2
|
| 188 |
+
+ "model.layers.{bid}.self_attn.groupnorm", # openpangu-r (per-head RMSNorm before gate)
|
| 189 |
+
"transformer.blocks.{bid}.norm_attn_norm.norm_2", # dbrx
|
| 190 |
+
),
|
| 191 |
+
|
| 192 |
+
@@ -435,6 +437,7 @@ class TensorNameMap:
|
| 193 |
+
|
| 194 |
+
MODEL_TENSOR.ATTN_GATE: (
|
| 195 |
+
"model.layers.{bid}.self_attn.gate_proj", # afmoe muse-glimmer
|
| 196 |
+
+ "model.layers.{bid}.self_attn.attention_gate", # openpangu-r
|
| 197 |
+
"model.layers.{bid}.linear_attn.in_proj_z", # qwen3.5
|
| 198 |
+
"layers.{bid}.linear_attn.in_proj_z", # qwen3.5 text
|
| 199 |
+
"model.layers.{bid}.self_attn.g_proj", # step3.5 head-wise attention gate
|
| 200 |
+
diff --git a/src/llama-arch.cpp b/src/llama-arch.cpp
|
| 201 |
+
index d1dd4cb..d30be8c 100644
|
| 202 |
+
--- a/src/llama-arch.cpp
|
| 203 |
+
+++ b/src/llama-arch.cpp
|
| 204 |
+
@@ -144,6 +144,7 @@ static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
| 205 |
+
{ LLM_ARCH_COGVLM, "cogvlm" },
|
| 206 |
+
{ LLM_ARCH_RND1, "rnd1" },
|
| 207 |
+
{ LLM_ARCH_PANGU_EMBED, "pangu-embedded" },
|
| 208 |
+
+ { LLM_ARCH_OPENPANGU_R, "openpangu-r" },
|
| 209 |
+
{ LLM_ARCH_MISTRAL3, "mistral3" },
|
| 210 |
+
{ LLM_ARCH_EAGLE3, "eagle3" },
|
| 211 |
+
{ LLM_ARCH_DFLASH, "dflash" },
|
| 212 |
+
@@ -500,6 +501,9 @@ static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = {
|
| 213 |
+
{ LLM_TENSOR_ATTN_Q_NORM, "blk.%d.attn_q_norm" },
|
| 214 |
+
{ LLM_TENSOR_ATTN_K_NORM, "blk.%d.attn_k_norm" },
|
| 215 |
+
{ LLM_TENSOR_ATTN_GATE, "blk.%d.attn_gate" },
|
| 216 |
+
+ { LLM_TENSOR_ATTN_SINK_K, "blk.%d.attn_sink_k" },
|
| 217 |
+
+ { LLM_TENSOR_ATTN_SINK_V, "blk.%d.attn_sink_v" },
|
| 218 |
+
+ { LLM_TENSOR_FFN_MERGE_CONV, "blk.%d.ffn_merge_conv" },
|
| 219 |
+
{ LLM_TENSOR_FFN_POST_NORM, "blk.%d.post_ffw_norm" },
|
| 220 |
+
{ LLM_TENSOR_FFN_POST_NORM_1, "blk.%d.post_ffw_norm_1" },
|
| 221 |
+
{ LLM_TENSOR_FFN_POST_NORM_2, "blk.%d.post_ffw_norm_2" },
|
| 222 |
+
@@ -839,6 +843,9 @@ static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = {
|
| 223 |
+
{LLM_TENSOR_ATTN_QKV, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 224 |
+
{LLM_TENSOR_ATTN_OUT, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 225 |
+
{LLM_TENSOR_ATTN_GATE, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 226 |
+
+ {LLM_TENSOR_ATTN_SINK_K, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 227 |
+
+ {LLM_TENSOR_ATTN_SINK_V, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 228 |
+
+ {LLM_TENSOR_FFN_MERGE_CONV, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL}},
|
| 229 |
+
{LLM_TENSOR_FFN_GATE, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 230 |
+
{LLM_TENSOR_FFN_DOWN, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 231 |
+
{LLM_TENSOR_FFN_UP, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}},
|
| 232 |
+
diff --git a/src/llama-arch.h b/src/llama-arch.h
|
| 233 |
+
index 4e8e534..0fa9b42 100644
|
| 234 |
+
--- a/src/llama-arch.h
|
| 235 |
+
+++ b/src/llama-arch.h
|
| 236 |
+
@@ -146,6 +146,7 @@ enum llm_arch {
|
| 237 |
+
LLM_ARCH_COGVLM,
|
| 238 |
+
LLM_ARCH_RND1,
|
| 239 |
+
LLM_ARCH_PANGU_EMBED,
|
| 240 |
+
+ LLM_ARCH_OPENPANGU_R,
|
| 241 |
+
LLM_ARCH_MISTRAL3,
|
| 242 |
+
LLM_ARCH_MISTRAL4,
|
| 243 |
+
LLM_ARCH_PADDLEOCR,
|
| 244 |
+
@@ -500,6 +501,9 @@ enum llm_tensor {
|
| 245 |
+
LLM_TENSOR_ATTN_ROT_EMBD,
|
| 246 |
+
LLM_TENSOR_ATTN_SINKS,
|
| 247 |
+
LLM_TENSOR_ATTN_GATE,
|
| 248 |
+
+ LLM_TENSOR_ATTN_SINK_K,
|
| 249 |
+
+ LLM_TENSOR_ATTN_SINK_V,
|
| 250 |
+
+ LLM_TENSOR_FFN_MERGE_CONV,
|
| 251 |
+
LLM_TENSOR_FFN_GATE_INP,
|
| 252 |
+
LLM_TENSOR_FFN_GATE_INP_SHEXP,
|
| 253 |
+
LLM_TENSOR_FFN_NORM,
|
| 254 |
+
diff --git a/src/llama-model.cpp b/src/llama-model.cpp
|
| 255 |
+
index ded790b..a811c9d 100644
|
| 256 |
+
--- a/src/llama-model.cpp
|
| 257 |
+
+++ b/src/llama-model.cpp
|
| 258 |
+
@@ -324,6 +324,8 @@ static llama_model * llama_model_mapping(llm_arch arch, const llama_model_params
|
| 259 |
+
return new llama_model_cogvlm(params);
|
| 260 |
+
case LLM_ARCH_PANGU_EMBED:
|
| 261 |
+
return new llama_model_pangu_embed(params);
|
| 262 |
+
+ case LLM_ARCH_OPENPANGU_R:
|
| 263 |
+
+ return new llama_model_openpangu_r(params);
|
| 264 |
+
case LLM_ARCH_QWEN3NEXT:
|
| 265 |
+
return new llama_model_qwen3next(params);
|
| 266 |
+
case LLM_ARCH_QWEN35:
|
| 267 |
+
@@ -3590,6 +3592,7 @@ llama_rope_type llama_model_rope_type(const llama_model * model) {
|
| 268 |
+
case LLM_ARCH_MINIMAX_M3:
|
| 269 |
+
case LLM_ARCH_COGVLM:
|
| 270 |
+
case LLM_ARCH_PANGU_EMBED:
|
| 271 |
+
+ case LLM_ARCH_OPENPANGU_R:
|
| 272 |
+
case LLM_ARCH_AFMOE:
|
| 273 |
+
case LLM_ARCH_LAGUNA:
|
| 274 |
+
case LLM_ARCH_QWEN3NEXT:
|
| 275 |
+
diff --git a/src/llama-model.h b/src/llama-model.h
|
| 276 |
+
index bcfbf1e..4ac2432 100644
|
| 277 |
+
--- a/src/llama-model.h
|
| 278 |
+
+++ b/src/llama-model.h
|
| 279 |
+
@@ -529,6 +529,12 @@ struct llama_layer {
|
| 280 |
+
// openai-moe
|
| 281 |
+
struct ggml_tensor * attn_sinks = nullptr;
|
| 282 |
+
|
| 283 |
+
+ // openpangu-r
|
| 284 |
+
+ struct ggml_tensor * attn_gate = nullptr;
|
| 285 |
+
+ struct ggml_tensor * attn_sink_k = nullptr;
|
| 286 |
+
+ struct ggml_tensor * attn_sink_v = nullptr;
|
| 287 |
+
+ struct ggml_tensor * ffn_merge_conv = nullptr;
|
| 288 |
+
+
|
| 289 |
+
// DeepSeek-V4
|
| 290 |
+
struct ggml_tensor * attn_kv_norm = nullptr;
|
| 291 |
+
struct ggml_tensor * hc_attn_fn = nullptr;
|
| 292 |
+
diff --git a/src/models/models.h b/src/models/models.h
|
| 293 |
+
index 88fd07d..773e3fe 100644
|
| 294 |
+
--- a/src/models/models.h
|
| 295 |
+
+++ b/src/models/models.h
|
| 296 |
+
@@ -2378,6 +2378,42 @@ struct llama_model_pangu_embed : public llama_model_base {
|
| 297 |
+
std::unique_ptr<llm_graph_context> build_arch_graph(const llm_graph_params & params) const override;
|
| 298 |
+
};
|
| 299 |
+
|
| 300 |
+
+// openPangu-R-7B-2512
|
| 301 |
+
+struct llama_model_openpangu_r : public llama_model_base {
|
| 302 |
+
+ llama_model_openpangu_r(const struct llama_model_params & params) : llama_model_base(params) {}
|
| 303 |
+
+ void load_arch_hparams(llama_model_loader & ml) override;
|
| 304 |
+
+ void load_arch_tensors(llama_model_loader & ml) override;
|
| 305 |
+
+
|
| 306 |
+
+ // persistent history of the merge_conv layers: the last 2 post-attention hidden states [n_embd, 2]
|
| 307 |
+
+ // (indexed by layer, nullptr elsewhere); owned by the model, zeroed when a sequence restarts at pos 0
|
| 308 |
+
+ ggml_context_ptr conv_state_ctx;
|
| 309 |
+
+ ggml_backend_buffer_ptr conv_state_buf;
|
| 310 |
+
+ std::vector<ggml_tensor *> conv_state;
|
| 311 |
+
+
|
| 312 |
+
+ struct graph : public llm_graph_context {
|
| 313 |
+
+ graph(const llama_model & model, const llm_graph_params & params);
|
| 314 |
+
+
|
| 315 |
+
+ // causal attention with per-layer learned sink keys/values (not cached, no RoPE)
|
| 316 |
+
+ ggml_tensor * build_attn_sinks(
|
| 317 |
+
+ llm_graph_input_attn_kv_iswa * inp,
|
| 318 |
+
+ const llama_layer & layer,
|
| 319 |
+
+ ggml_tensor * attn_in,
|
| 320 |
+
+ ggml_tensor * q_cur,
|
| 321 |
+
+ ggml_tensor * k_cur,
|
| 322 |
+
+ ggml_tensor * v_cur,
|
| 323 |
+
+ int il);
|
| 324 |
+
+
|
| 325 |
+
+ // depthwise causal conv over tokens (kernel 3), continuing from the persisted history
|
| 326 |
+
+ ggml_tensor * build_merge_conv(
|
| 327 |
+
+ ggml_tensor * h,
|
| 328 |
+
+ const llama_layer & layer,
|
| 329 |
+
+ ggml_tensor * state,
|
| 330 |
+
+ int il);
|
| 331 |
+
+ };
|
| 332 |
+
+
|
| 333 |
+
+ std::unique_ptr<llm_graph_context> build_arch_graph(const llm_graph_params & params) const override;
|
| 334 |
+
+};
|
| 335 |
+
+
|
| 336 |
+
|
| 337 |
+
struct llama_model_qwen3next : public llama_model_base {
|
| 338 |
+
llama_model_qwen3next(const struct llama_model_params & params) : llama_model_base(params) {}
|
| 339 |
+
diff --git a/src/models/openpangu-r.cpp b/src/models/openpangu-r.cpp
|
| 340 |
+
new file mode 100644
|
| 341 |
+
index 0000000..5ece53e
|
| 342 |
+
--- /dev/null
|
| 343 |
+
+++ b/src/models/openpangu-r.cpp
|
| 344 |
+
@@ -0,0 +1,366 @@
|
| 345 |
+
+#include "models.h"
|
| 346 |
+
+#include "llama-kv-cache-iswa.h"
|
| 347 |
+
+
|
| 348 |
+
+// openPangu-R-7B-2512 (HF architecture "PanguEmbeddedForCausalLM" with the R extensions)
|
| 349 |
+
+//
|
| 350 |
+
+// per layer:
|
| 351 |
+
+// h1 = h + wo( groupnorm(attn(q, k, v)) * sigmoid(attn_gate(x)) ) x = rmsnorm(h)
|
| 352 |
+
+// x' = merge_conv(h1) (layers 0 and N-1 only; causal depthwise conv, kernel 3, no bias)
|
| 353 |
+
+// h2 = h1 + ffn(rmsnorm(x'))
|
| 354 |
+
+// attention:
|
| 355 |
+
+// - interleaved sliding-window (even layers, window 128) and full attention (odd layers)
|
| 356 |
+
+// - partial RoPE (first 32 of 128 dims, NEOX layout)
|
| 357 |
+
+// - per-layer learned sinks: n_sink (key, value) pairs per KV head that every query can attend to;
|
| 358 |
+
+// they are not cached and not rotated, so they are added to the softmax as extra logits
|
| 359 |
+
+// - per-head RMSNorm (groupnorm, weight shared across heads) on the attention output
|
| 360 |
+
+// the MTP module (layer N) is not used for inference
|
| 361 |
+
+//
|
| 362 |
+
+// limitations: one sequence per batch; the merge_conv history is kept in the model, so it only follows
|
| 363 |
+
+// a single sequence that is decoded contiguously (positions restart at 0 for a new sequence)
|
| 364 |
+
+
|
| 365 |
+
+namespace {
|
| 366 |
+
+
|
| 367 |
+
+// zeroes the merge_conv history when a sequence starts at position 0
|
| 368 |
+
+class llm_graph_input_openpangu_r_state : public llm_graph_input_i {
|
| 369 |
+
+public:
|
| 370 |
+
+ explicit llm_graph_input_openpangu_r_state(std::vector<ggml_tensor *> states) : states(std::move(states)) {}
|
| 371 |
+
+
|
| 372 |
+
+ void set_input(const llama_ubatch * ubatch) override {
|
| 373 |
+
+ if (ubatch->n_seqs_unq > 1) {
|
| 374 |
+
+ GGML_ABORT("openpangu-r: only one sequence per batch is supported");
|
| 375 |
+
+ }
|
| 376 |
+
+ if (ubatch->pos != nullptr && ubatch->n_tokens > 0 && ubatch->pos[0] == 0) {
|
| 377 |
+
+ for (ggml_tensor * s : states) {
|
| 378 |
+
+ if (s != nullptr) {
|
| 379 |
+
+ ggml_backend_tensor_memset(s, 0, 0, ggml_nbytes(s));
|
| 380 |
+
+ }
|
| 381 |
+
+ }
|
| 382 |
+
+ }
|
| 383 |
+
+ }
|
| 384 |
+
+
|
| 385 |
+
+ std::vector<ggml_tensor *> states;
|
| 386 |
+
+};
|
| 387 |
+
+
|
| 388 |
+
+} // namespace
|
| 389 |
+
+
|
| 390 |
+
+void llama_model_openpangu_r::load_arch_hparams(llama_model_loader & ml) {
|
| 391 |
+
+ ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps);
|
| 392 |
+
+
|
| 393 |
+
+ // interleaved sliding-window / full attention; the pattern comes from the GGUF (sliding_window_pattern)
|
| 394 |
+
+ hparams.swa_type = LLAMA_SWA_TYPE_STANDARD;
|
| 395 |
+
+ ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa);
|
| 396 |
+
+ load_swa_pattern(ml, 2);
|
| 397 |
+
+
|
| 398 |
+
+ // the HF implementation uses a single rotary embedding for both layer types
|
| 399 |
+
+ ml.get_key(LLM_KV_ROPE_FREQ_BASE, hparams.rope_freq_base_train_swa);
|
| 400 |
+
+
|
| 401 |
+
+ switch (hparams.n_layer()) {
|
| 402 |
+
+ case 27: type = LLM_TYPE_7B; break;
|
| 403 |
+
+ default: type = LLM_TYPE_UNKNOWN;
|
| 404 |
+
+ }
|
| 405 |
+
+}
|
| 406 |
+
+
|
| 407 |
+
+void llama_model_openpangu_r::load_arch_tensors(llama_model_loader & ml) {
|
| 408 |
+
+ LLAMA_LOAD_LOCALS;
|
| 409 |
+
+
|
| 410 |
+
+ tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0);
|
| 411 |
+
+
|
| 412 |
+
+ // output
|
| 413 |
+
+ output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0);
|
| 414 |
+
+ output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, TENSOR_NOT_REQUIRED);
|
| 415 |
+
+
|
| 416 |
+
+ // if output is NULL, init from the input tok embed
|
| 417 |
+
+ if (output == NULL) {
|
| 418 |
+
+ output = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, TENSOR_DUPLICATED);
|
| 419 |
+
+ }
|
| 420 |
+
+
|
| 421 |
+
+ // number of sink tokens: dim 1 of attn_sink_k (GGUF ne = [head_dim, n_sink, n_kv_head])
|
| 422 |
+
+ const ggml_tensor * sink_meta = ml.get_tensor_meta(tn(LLM_TENSOR_ATTN_SINK_K, "weight", 0).str().c_str());
|
| 423 |
+
+ if (sink_meta == nullptr) {
|
| 424 |
+
+ throw std::runtime_error("openpangu-r: missing attn_sink_k tensor");
|
| 425 |
+
+ }
|
| 426 |
+
+ const int64_t n_sink = sink_meta->ne[1];
|
| 427 |
+
+
|
| 428 |
+
+ conv_state.assign(n_layer, nullptr);
|
| 429 |
+
+
|
| 430 |
+
+ for (int i = 0; i < n_layer; ++i) {
|
| 431 |
+
+ auto & layer = layers[i];
|
| 432 |
+
+
|
| 433 |
+
+ layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0);
|
| 434 |
+
+
|
| 435 |
+
+ create_tensor_qkv(layer, i, n_embd, n_embd_head_k * n_head, n_embd_k_gqa, n_embd_v_gqa, 0);
|
| 436 |
+
+ layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0);
|
| 437 |
+
+ layer.wo_b = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "bias", i), {n_embd}, 0);
|
| 438 |
+
+
|
| 439 |
+
+ layer.attn_gate = create_tensor(tn(LLM_TENSOR_ATTN_GATE, "weight", i), {n_embd, n_embd_head_k * n_head}, 0);
|
| 440 |
+
+ layer.attn_out_norm = create_tensor(tn(LLM_TENSOR_ATTN_OUT_NORM, "weight", i), {n_embd_head_k}, 0);
|
| 441 |
+
+ layer.attn_sink_k = create_tensor(tn(LLM_TENSOR_ATTN_SINK_K, "weight", i), {n_embd_head_k, n_sink, n_head_kv}, 0);
|
| 442 |
+
+ layer.attn_sink_v = create_tensor(tn(LLM_TENSOR_ATTN_SINK_V, "weight", i), {n_sink, n_embd_head_v, n_head_kv}, 0);
|
| 443 |
+
+
|
| 444 |
+
+ layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0);
|
| 445 |
+
+ layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0);
|
| 446 |
+
+ layer.ffn_up = create_tensor(tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0);
|
| 447 |
+
+ layer.ffn_down = create_tensor(tn(LLM_TENSOR_FFN_DOWN, "weight", i), {n_ff, n_embd}, 0);
|
| 448 |
+
+
|
| 449 |
+
+ if (i == 0 || i == n_layer - 1) {
|
| 450 |
+
+ layer.ffn_merge_conv = create_tensor(tn(LLM_TENSOR_FFN_MERGE_CONV, "weight", i), {n_embd, 3}, 0);
|
| 451 |
+
+ }
|
| 452 |
+
+ }
|
| 453 |
+
+
|
| 454 |
+
+ // persistent merge_conv history (2 tokens x n_embd per conv layer), allocated on the CPU
|
| 455 |
+
+ int n_conv = 0;
|
| 456 |
+
+ for (int i = 0; i < n_layer; ++i) {
|
| 457 |
+
+ n_conv += layers[i].ffn_merge_conv != nullptr;
|
| 458 |
+
+ }
|
| 459 |
+
+
|
| 460 |
+
+ ggml_init_params params = {
|
| 461 |
+
+ /*.mem_size =*/ ggml_tensor_overhead() * (n_conv + 1),
|
| 462 |
+
+ /*.mem_buffer =*/ nullptr,
|
| 463 |
+
+ /*.no_alloc =*/ true,
|
| 464 |
+
+ };
|
| 465 |
+
+ conv_state_ctx.reset(ggml_init(params));
|
| 466 |
+
+ if (!conv_state_ctx) {
|
| 467 |
+
+ throw std::runtime_error("openpangu-r: failed to create the conv state context");
|
| 468 |
+
+ }
|
| 469 |
+
+
|
| 470 |
+
+ for (int i = 0; i < n_layer; ++i) {
|
| 471 |
+
+ if (layers[i].ffn_merge_conv == nullptr) {
|
| 472 |
+
+ continue;
|
| 473 |
+
+ }
|
| 474 |
+
+ conv_state[i] = ggml_new_tensor_2d(conv_state_ctx.get(), GGML_TYPE_F32, n_embd, 2);
|
| 475 |
+
+ ggml_format_name(conv_state[i], "openpangu_r_conv_state_%d", i);
|
| 476 |
+
+ }
|
| 477 |
+
+
|
| 478 |
+
+ conv_state_buf.reset(ggml_backend_alloc_ctx_tensors_from_buft(conv_state_ctx.get(), ggml_backend_cpu_buffer_type()));
|
| 479 |
+
+ if (!conv_state_buf) {
|
| 480 |
+
+ throw std::runtime_error("openpangu-r: failed to allocate the conv state buffer");
|
| 481 |
+
+ }
|
| 482 |
+
+}
|
| 483 |
+
+
|
| 484 |
+
+std::unique_ptr<llm_graph_context> llama_model_openpangu_r::build_arch_graph(const llm_graph_params & params) const {
|
| 485 |
+
+ return std::make_unique<graph>(*this, params);
|
| 486 |
+
+}
|
| 487 |
+
+
|
| 488 |
+
+// the attention of one layer; sinks are extra softmax terms, the K/V cache is written as usual
|
| 489 |
+
+ggml_tensor * llama_model_openpangu_r::graph::build_attn_sinks(
|
| 490 |
+
+ llm_graph_input_attn_kv_iswa * inp,
|
| 491 |
+
+ const llama_layer & layer,
|
| 492 |
+
+ ggml_tensor * attn_in,
|
| 493 |
+
+ ggml_tensor * q,
|
| 494 |
+
+ ggml_tensor * k_cur,
|
| 495 |
+
+ ggml_tensor * v_cur,
|
| 496 |
+
+ int il) {
|
| 497 |
+
+ const bool is_swa = hparams.is_swa(il);
|
| 498 |
+
+
|
| 499 |
+
+ GGML_ASSERT(!(is_swa ? inp->self_k_rot_swa : inp->self_k_rot) && "openpangu-r: Hadamard-rotated KV cache is not supported");
|
| 500 |
+
+ GGML_ASSERT(!(is_swa ? inp->self_v_rot_swa : inp->self_v_rot) && "openpangu-r: Hadamard-rotated KV cache is not supported");
|
| 501 |
+
+
|
| 502 |
+
+ const int64_t n_embd_head = q->ne[0];
|
| 503 |
+
+ const int64_t n_tokens = q->ne[2];
|
| 504 |
+
+ const int64_t n_sink = layer.attn_sink_k->ne[1];
|
| 505 |
+
+ const float kq_scale = 1.0f / sqrtf(float(n_embd_head));
|
| 506 |
+
+
|
| 507 |
+
+ const auto * mctx_iswa = static_cast<const llama_kv_cache_iswa_context *>(mctx);
|
| 508 |
+
+ const auto * mctx_cur = is_swa ? mctx_iswa->get_swa() : mctx_iswa->get_base();
|
| 509 |
+
+
|
| 510 |
+
+ // store the current K/V, then read the whole cache (same as llm_graph_context::build_attn)
|
| 511 |
+
+ ggml_build_forward_expand(gf, mctx_cur->cpy_k(ctx0, k_cur, is_swa ? inp->get_k_idxs_swa() : inp->get_k_idxs(), il));
|
| 512 |
+
+ ggml_build_forward_expand(gf, mctx_cur->cpy_v(ctx0, v_cur, is_swa ? inp->get_v_idxs_swa() : inp->get_v_idxs(), il));
|
| 513 |
+
+
|
| 514 |
+
+ ggml_tensor * k = mctx_cur->get_k(ctx0, il);
|
| 515 |
+
+ ggml_tensor * v = mctx_cur->get_v(ctx0, il);
|
| 516 |
+
+
|
| 517 |
+
+ GGML_ASSERT(k->ne[3] == 1 && "openpangu-r: multi-stream KV cache is not supported");
|
| 518 |
+
+
|
| 519 |
+
+ const bool v_trans = v->nb[1] > v->nb[2];
|
| 520 |
+
+
|
| 521 |
+
+ // [D, n_tokens, n_head], [D, n_kv, n_kv_head], [n_kv, D, n_kv_head]
|
| 522 |
+
+ ggml_tensor * qp = ggml_permute(ctx0, q, 0, 2, 1, 3);
|
| 523 |
+
+ ggml_tensor * kp = ggml_permute(ctx0, k, 0, 2, 1, 3);
|
| 524 |
+
+ ggml_tensor * vp = ggml_permute(ctx0, v, 0, 2, 1, 3);
|
| 525 |
+
+ if (!v_trans) {
|
| 526 |
+
+ vp = ggml_cont(ctx0, ggml_transpose(ctx0, vp));
|
| 527 |
+
+ }
|
| 528 |
+
+
|
| 529 |
+
+ // cached keys: [n_kv, n_tokens, n_head]
|
| 530 |
+
+ ggml_tensor * kq = ggml_mul_mat(ctx0, kp, qp);
|
| 531 |
+
+ kq = ggml_scale(ctx0, kq, kq_scale);
|
| 532 |
+
+
|
| 533 |
+
+ ggml_tensor * kq_mask = is_swa ? inp->get_kq_mask_swa() : inp->get_kq_mask();
|
| 534 |
+
+ if (kq_mask != nullptr) {
|
| 535 |
+
+ ggml_tensor * mask = ggml_cast(ctx0, kq_mask, GGML_TYPE_F32);
|
| 536 |
+
+ mask = ggml_cont(ctx0, ggml_view_3d(ctx0, mask, kq->ne[0], n_tokens, 1, mask->nb[1], mask->nb[2], 0));
|
| 537 |
+
+ kq = ggml_add(ctx0, kq, mask);
|
| 538 |
+
+ }
|
| 539 |
+
+
|
| 540 |
+
+ // sink keys: not cached, not rotated, always visible: [n_sink, n_tokens, n_head]
|
| 541 |
+
+ ggml_tensor * ks = ggml_mul_mat(ctx0, layer.attn_sink_k, qp);
|
| 542 |
+
+ ks = ggml_scale(ctx0, ks, kq_scale);
|
| 543 |
+
+
|
| 544 |
+
+ // one softmax over [cached keys | sinks]
|
| 545 |
+
+ ggml_tensor * p = ggml_soft_max(ctx0, ggml_concat(ctx0, kq, ks, 0));
|
| 546 |
+
+
|
| 547 |
+
+ const int64_t n_kv = kq->ne[0];
|
| 548 |
+
+ // the views have row strides of the full [n_kv + n_sink] row; the CPU mul_mat needs contiguous rows
|
| 549 |
+
+ ggml_tensor * p_kv = ggml_cont(ctx0, ggml_view_3d(ctx0, p, n_kv, n_tokens, kq->ne[2], p->nb[1], p->nb[2], 0));
|
| 550 |
+
+ ggml_tensor * p_sk = ggml_cont(ctx0, ggml_view_3d(ctx0, p, n_sink, n_tokens, kq->ne[2], p->nb[1], p->nb[2], n_kv*p->nb[0]));
|
| 551 |
+
+
|
| 552 |
+
+ ggml_tensor * o_kv = ggml_mul_mat(ctx0, vp, p_kv); // [D, n_tokens, n_head]
|
| 553 |
+
+ ggml_tensor * o_sk = ggml_mul_mat(ctx0, layer.attn_sink_v, p_sk); // [D, n_tokens, n_head]
|
| 554 |
+
+ ggml_tensor * o = ggml_add(ctx0, o_kv, o_sk);
|
| 555 |
+
+
|
| 556 |
+
+ o = ggml_cont(ctx0, ggml_permute(ctx0, o, 0, 2, 1, 3)); // [D, n_head, n_tokens]
|
| 557 |
+
+ cb(o, "kqv", il);
|
| 558 |
+
+
|
| 559 |
+
+ // per-head RMSNorm, then the sigmoid gate computed from the attention input
|
| 560 |
+
+ o = build_norm(o, layer.attn_out_norm, NULL, LLM_NORM_RMS, il);
|
| 561 |
+
+ o = ggml_reshape_2d(ctx0, o, n_embd_head * hparams.n_head(il), n_tokens);
|
| 562 |
+
+
|
| 563 |
+
+ ggml_tensor * gate = build_lora_mm(layer.attn_gate, attn_in, nullptr);
|
| 564 |
+
+ o = ggml_mul(ctx0, o, ggml_sigmoid(ctx0, gate));
|
| 565 |
+
+
|
| 566 |
+
+ o = build_lora_mm(layer.wo, o, layer.wo_s);
|
| 567 |
+
+ if (layer.wo_b) {
|
| 568 |
+
+ o = ggml_add(ctx0, o, layer.wo_b);
|
| 569 |
+
+ }
|
| 570 |
+
+
|
| 571 |
+
+ return o;
|
| 572 |
+
+}
|
| 573 |
+
+
|
| 574 |
+
+// causal depthwise conv over the token axis: out[t] = w0*h[t-2] + w1*h[t-1] + w2*h[t]
|
| 575 |
+
+// history of the previous two tokens comes from `state`, which is updated with the last two tokens of h
|
| 576 |
+
+ggml_tensor * llama_model_openpangu_r::graph::build_merge_conv(
|
| 577 |
+
+ ggml_tensor * h,
|
| 578 |
+
+ const llama_layer & layer,
|
| 579 |
+
+ ggml_tensor * state,
|
| 580 |
+
+ int il) {
|
| 581 |
+
+ const int64_t n_embd = h->ne[0];
|
| 582 |
+
+ const int64_t n_tokens = h->ne[1];
|
| 583 |
+
+
|
| 584 |
+
+ GGML_ASSERT(state->ne[0] == n_embd && state->ne[1] == 2);
|
| 585 |
+
+
|
| 586 |
+
+ // [history(2) | h(n_tokens)] along the token axis
|
| 587 |
+
+ ggml_tensor * cat = ggml_concat(ctx0, state, h, 1);
|
| 588 |
+
+ cb(cat, "merge_conv_in", il);
|
| 589 |
+
+
|
| 590 |
+
+ // persist the last two tokens for the next batch
|
| 591 |
+
+ ggml_tensor * next = ggml_view_2d(ctx0, cat, n_embd, 2, cat->nb[1], n_tokens*cat->nb[1]);
|
| 592 |
+
+ ggml_build_forward_expand(gf, ggml_cpy(ctx0, next, state));
|
| 593 |
+
+
|
| 594 |
+
+ ggml_tensor * W = ggml_cast(ctx0, layer.ffn_merge_conv, GGML_TYPE_F32); // [n_embd, 3]
|
| 595 |
+
+
|
| 596 |
+
+ ggml_tensor * out = nullptr;
|
| 597 |
+
+ for (int k = 0; k < 3; ++k) {
|
| 598 |
+
+ ggml_tensor * x_k = ggml_view_2d(ctx0, cat, n_embd, n_tokens, cat->nb[1], k*cat->nb[1]);
|
| 599 |
+
+ ggml_tensor * w_k = ggml_view_2d(ctx0, W, n_embd, 1, W->nb[1], k*W->nb[1]);
|
| 600 |
+
+ ggml_tensor * t = ggml_mul(ctx0, x_k, w_k);
|
| 601 |
+
+ out = out == nullptr ? t : ggml_add(ctx0, out, t);
|
| 602 |
+
+ }
|
| 603 |
+
+
|
| 604 |
+
+ cb(out, "merge_conv_out", il);
|
| 605 |
+
+ return out;
|
| 606 |
+
+}
|
| 607 |
+
+
|
| 608 |
+
+llama_model_openpangu_r::graph::graph(const llama_model & model, const llm_graph_params & params) : llm_graph_context(params) {
|
| 609 |
+
+ const auto & self = static_cast<const llama_model_openpangu_r &>(model);
|
| 610 |
+
+
|
| 611 |
+
+ const int64_t n_embd_head = hparams.n_embd_head_k();
|
| 612 |
+
+
|
| 613 |
+
+ ggml_tensor * cur;
|
| 614 |
+
+ ggml_tensor * inpL;
|
| 615 |
+
+
|
| 616 |
+
+ inpL = build_inp_embd(model.tok_embd);
|
| 617 |
+
+
|
| 618 |
+
+ // inp_pos - contains the positions
|
| 619 |
+
+ ggml_tensor * inp_pos = build_inp_pos();
|
| 620 |
+
+
|
| 621 |
+
+ res->add_input(std::make_unique<llm_graph_input_openpangu_r_state>(self.conv_state));
|
| 622 |
+
+
|
| 623 |
+
+ auto * inp_attn = build_attn_inp_kv_iswa();
|
| 624 |
+
+
|
| 625 |
+
+ ggml_tensor * inp_out_ids = build_inp_out_ids();
|
| 626 |
+
+
|
| 627 |
+
+ for (int il = 0; il < n_layer; ++il) {
|
| 628 |
+
+ const auto & layer = model.layers[il];
|
| 629 |
+
+
|
| 630 |
+
+ ggml_tensor * inpSA = inpL;
|
| 631 |
+
+
|
| 632 |
+
+ // norm
|
| 633 |
+
+ cur = build_norm(inpL, layer.attn_norm, NULL, LLM_NORM_RMS, il);
|
| 634 |
+
+ cb(cur, "attn_norm", il);
|
| 635 |
+
+
|
| 636 |
+
+ // self attention
|
| 637 |
+
+ {
|
| 638 |
+
+ auto [Qcur, Kcur, Vcur] = build_qkv(layer, cur, n_embd_head, n_head, n_head_kv, il);
|
| 639 |
+
+
|
| 640 |
+
+ // partial RoPE: only the first n_rot dims are rotated
|
| 641 |
+
+ const float freq_base_l = model.get_rope_freq_base (cparams, il);
|
| 642 |
+
+ const float freq_scale_l = model.get_rope_freq_scale(cparams, il);
|
| 643 |
+
+
|
| 644 |
+
+ Qcur = ggml_rope_ext(
|
| 645 |
+
+ ctx0, Qcur, inp_pos, nullptr,
|
| 646 |
+
+ n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l,
|
| 647 |
+
+ ext_factor, attn_factor, beta_fast, beta_slow);
|
| 648 |
+
+
|
| 649 |
+
+ Kcur = ggml_rope_ext(
|
| 650 |
+
+ ctx0, Kcur, inp_pos, nullptr,
|
| 651 |
+
+ n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l,
|
| 652 |
+
+ ext_factor, attn_factor, beta_fast, beta_slow);
|
| 653 |
+
+
|
| 654 |
+
+ cb(Qcur, "Qcur", il);
|
| 655 |
+
+ cb(Kcur, "Kcur", il);
|
| 656 |
+
+ cb(Vcur, "Vcur", il);
|
| 657 |
+
+
|
| 658 |
+
+ cur = build_attn_sinks(inp_attn, layer, cur, Qcur, Kcur, Vcur, il);
|
| 659 |
+
+ }
|
| 660 |
+
+
|
| 661 |
+
+ ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA);
|
| 662 |
+
+ cb(ffn_inp, "ffn_inp", il);
|
| 663 |
+
+
|
| 664 |
+
+ // merge conv runs over all tokens of the batch, before the output rows are selected
|
| 665 |
+
+ ggml_tensor * x = ffn_inp;
|
| 666 |
+
+ if (layer.ffn_merge_conv != nullptr) {
|
| 667 |
+
+ x = build_merge_conv(ffn_inp, layer, self.conv_state[il], il);
|
| 668 |
+
+ }
|
| 669 |
+
+
|
| 670 |
+
+ if (il == n_layer - 1 && inp_out_ids) {
|
| 671 |
+
+ x = ggml_get_rows(ctx0, x, inp_out_ids);
|
| 672 |
+
+ ffn_inp = ggml_get_rows(ctx0, ffn_inp, inp_out_ids);
|
| 673 |
+
+ }
|
| 674 |
+
+
|
| 675 |
+
+ // feed-forward network
|
| 676 |
+
+ cur = build_norm(x, layer.ffn_norm, NULL, LLM_NORM_RMS, il);
|
| 677 |
+
+ cb(cur, "ffn_norm", il);
|
| 678 |
+
+
|
| 679 |
+
+ cur = build_ffn(cur,
|
| 680 |
+
+ layer.ffn_up, NULL, NULL,
|
| 681 |
+
+ layer.ffn_gate, NULL, NULL,
|
| 682 |
+
+ layer.ffn_down, NULL, NULL,
|
| 683 |
+
+ NULL,
|
| 684 |
+
+ LLM_FFN_SILU, LLM_FFN_PAR, il);
|
| 685 |
+
+ cb(cur, "ffn_out", il);
|
| 686 |
+
+
|
| 687 |
+
+ cur = ggml_add(ctx0, cur, ffn_inp);
|
| 688 |
+
+
|
| 689 |
+
+ cur = build_cvec(cur, il);
|
| 690 |
+
+ cb(cur, "l_out", il);
|
| 691 |
+
+
|
| 692 |
+
+ // input for next layer
|
| 693 |
+
+ inpL = cur;
|
| 694 |
+
+ }
|
| 695 |
+
+
|
| 696 |
+
+ cur = inpL;
|
| 697 |
+
+
|
| 698 |
+
+ cur = build_norm(cur,
|
| 699 |
+
+ model.output_norm, NULL,
|
| 700 |
+
+ LLM_NORM_RMS, -1);
|
| 701 |
+
+
|
| 702 |
+
+ cb(cur, "result_norm", -1);
|
| 703 |
+
+ res->t_embd = cur;
|
| 704 |
+
+
|
| 705 |
+
+ // lm_head
|
| 706 |
+
+ cur = build_lora_mm(model.output, cur);
|
| 707 |
+
+
|
| 708 |
+
+ cb(cur, "result_output", -1);
|
| 709 |
+
+ res->t_logits = cur;
|
| 710 |
+
+}
|