Instructions to use pipenetwork/GLM-5.3-MLX-5bit with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use pipenetwork/GLM-5.3-MLX-5bit with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("pipenetwork/GLM-5.3-MLX-5bit") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Pi
How to use pipenetwork/GLM-5.3-MLX-5bit with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "pipenetwork/GLM-5.3-MLX-5bit"
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "pipenetwork/GLM-5.3-MLX-5bit" } ] } } }Run Pi
# Start Pi in your project directory: pi
- MLX LM
How to use pipenetwork/GLM-5.3-MLX-5bit with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "pipenetwork/GLM-5.3-MLX-5bit"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "pipenetwork/GLM-5.3-MLX-5bit" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "pipenetwork/GLM-5.3-MLX-5bit", "messages": [ {"role": "user", "content": "Hello"} ] }' - Hermes Agent
How to use pipenetwork/GLM-5.3-MLX-5bit with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "pipenetwork/GLM-5.3-MLX-5bit"
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default pipenetwork/GLM-5.3-MLX-5bit
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use pipenetwork/GLM-5.3-MLX-5bit with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "pipenetwork/GLM-5.3-MLX-5bit"
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "pipenetwork/GLM-5.3-MLX-5bit" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +1 -0
- LICENSE +29 -0
- README.md +95 -0
- __pycache__/glm_moe_dsa.cpython-314.pyc +0 -0
- chat_template.jinja +251 -0
- config.json +233 -0
- generation_config.json +12 -0
- glm_moe_dsa.py +703 -0
- model-00001.safetensors +3 -0
- model-00002.safetensors +3 -0
- model-00003.safetensors +3 -0
- model-00004.safetensors +3 -0
- model-00005.safetensors +3 -0
- model-00006.safetensors +3 -0
- model-00007.safetensors +3 -0
- model-00008.safetensors +3 -0
- model-00009.safetensors +3 -0
- model-00010.safetensors +3 -0
- model-00011.safetensors +3 -0
- model-00012.safetensors +3 -0
- model-00013.safetensors +3 -0
- model-00014.safetensors +3 -0
- model-00015.safetensors +3 -0
- model-00016.safetensors +3 -0
- model-00017.safetensors +3 -0
- model-00018.safetensors +3 -0
- model-00019.safetensors +3 -0
- model-00020.safetensors +3 -0
- model-00021.safetensors +3 -0
- model-00022.safetensors +3 -0
- model-00023.safetensors +3 -0
- model-00024.safetensors +3 -0
- model-00025.safetensors +3 -0
- model-00026.safetensors +3 -0
- model-00027.safetensors +3 -0
- model-00028.safetensors +3 -0
- model-00029.safetensors +3 -0
- model-00030.safetensors +3 -0
- model-00031.safetensors +3 -0
- model-00032.safetensors +3 -0
- model-00033.safetensors +3 -0
- model-00034.safetensors +3 -0
- model-00035.safetensors +3 -0
- model-00036.safetensors +3 -0
- model-00037.safetensors +3 -0
- model-00038.safetensors +3 -0
- model-00039.safetensors +3 -0
- model-00040.safetensors +3 -0
- model-00041.safetensors +3 -0
- model-00042.safetensors +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* 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
|
|
|
|
|
|
| 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 |
+
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GLM-5.3 License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 Z.AI
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person or entity (the "Licensee") obtaining a copy of this software — including the model weights, parameters, configuration files, inference and training code, and associated documentation (collectively, the "Software") — to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software; to run, deploy, fine-tune, or otherwise modify the Software and create derivative works from it; and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 6 |
+
|
| 7 |
+
1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Licensee's use of the Software must comply with applicable laws and regulations.
|
| 8 |
+
|
| 9 |
+
2. "Model as a Service" means giving a third party access to language model inference or fine-tuning (e.g., via API) in a manner that allows such third party to exercise meaningful control over the inputs, parameters, or training data. This does not include (a) end-user products with model capabilities solely embedded within specific features or harnesses, or (b) mere relaying of requests to models hosted by others.
|
| 10 |
+
If the Licensee or any of its affiliates operates a Model as a Service business, and the aggregate revenue of the Licensee and its affiliates exceeds 10 billion US dollars (or the equivalent in other currencies) in total over any consecutive 12 months, the Licensee must pass Z.AI's security review before using the Software or its derivative works for any commercial purpose. The scope and method of the security review shall be reasonably determined by Z.AI.
|
| 11 |
+
|
| 12 |
+
3. THE SOFTWARE AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL Z.AI OR ITS AFFILIATES OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 13 |
+
|
| 14 |
+
For any questions regarding this license, please contact glmlicense@z.ai.
|
| 15 |
+
|
| 16 |
+
-----
|
| 17 |
+
|
| 18 |
+
版权所有 (c) 2026 Z.AI
|
| 19 |
+
|
| 20 |
+
特此免费授予任何获得本软件副本的个人或实体("被许可方")——包括模型权重、参数、配置文件、推理和训练代码及相关文档(统称"软件")——不受限制地处理本软件的权利,包括但不限于:使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本;运行、部署、微调或以其他方式修改软件并创建衍生作品;以及允许获得软件的其他人行使上述权利,但须遵守以下条件:
|
| 21 |
+
|
| 22 |
+
1. 上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。被许可方对软件的使用必须符合适用法律法规。
|
| 23 |
+
|
| 24 |
+
2. "模型即服务"指以允许第三方对输入、参数或训练数据行使实质性控制的方式,向第三方提供语言模型推理或微调服务(如通过API)。不包括:(a) 模型能力仅嵌入特定功能或框架中的终端用户产品,或(b) 单纯转发请求至他人托管的模型。
|
| 25 |
+
若被许可方或其关联方运营"模型即服务"业务,且被许可方及关联方在任意连续12个月内累计总收入超过100亿美元(或等值其他货币),则被许可方在使用软件或其衍生作品进行任何商业用途之前,须通过Z.AI的安全审查。安全审查的范围和方式由Z.AI合理确定。
|
| 26 |
+
|
| 27 |
+
3. 软件及其任何输出和结果均按"现状"提供,不附带任何形式的保证,无论是明示还是暗示,包括但不限于适销性、特定用途适用性和不侵权的保证。在任何情况下,Z.AI或其关联方或版权持有人均不对任何索赔、损害或其他责任承担责任,无论该责任是基于合同、侵权或其他方式,因软件或使用软件而产生或与之相关。
|
| 28 |
+
|
| 29 |
+
如对本许可有任何疑问,请联系 glmlicense@z.ai。
|
README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: glm-5.3
|
| 4 |
+
license_link: LICENSE
|
| 5 |
+
base_model: zai-org/GLM-5.3
|
| 6 |
+
base_model_relation: quantized
|
| 7 |
+
tags:
|
| 8 |
+
- mlx
|
| 9 |
+
- apple-silicon
|
| 10 |
+
- glm_moe_dsa
|
| 11 |
+
- mixture-of-experts
|
| 12 |
+
- 5-bit
|
| 13 |
+
pipeline_tag: text-generation
|
| 14 |
+
library_name: mlx
|
| 15 |
+
---
|
| 16 |
+
|
| 17 |
+
# GLM-5.3-MLX-5bit
|
| 18 |
+
|
| 19 |
+
MLX (Apple Silicon) build of [**GLM-5.3**](https://huggingface.co/zai-org/GLM-5.3) — 744B-parameter
|
| 20 |
+
`glm_moe_dsa` MoE (256 experts, top-8; MLA with DeepSeek-V3.2-style sparse attention) — quantized
|
| 21 |
+
to **5-bit**.
|
| 22 |
+
|
| 23 |
+
**These files are modified**: converted from the upstream **bfloat16** release
|
| 24 |
+
([GLM-5.3-BF16](https://huggingface.co/zai-org/GLM-5.3-BF16)) to MLX and quantized; the architecture
|
| 25 |
+
is unchanged. The multi-token-prediction layer (78) is not included.
|
| 26 |
+
|
| 27 |
+
## Runtime — read this
|
| 28 |
+
|
| 29 |
+
This checkpoint bundles `glm_moe_dsa.py` (declared via `model_file`) and needs it:
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
pip install -U mlx-lm
|
| 33 |
+
mlx_lm.generate --model pipenetwork/GLM-5.3-MLX-5bit --trust-remote-code --prompt "..." --max-tokens 300
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
mlx-lm's own `glm_moe_dsa` builds a lightning indexer on all 78 layers, but GLM-5.2/5.3 ship
|
| 37 |
+
indexer weights on 21 (`indexer_types`: the other 57 "shared" layers reuse the previous full layer's
|
| 38 |
+
top-k selection). A strict load of the release fails with 285 missing parameters; `mlx_lm.load`
|
| 39 |
+
loads leniently and leaves those 57 indexers at random initialisation. Prompts up to 2048 tokens are
|
| 40 |
+
unaffected (the indexer is bypassed below `index_topk`); beyond that, 57 layers attend to keys
|
| 41 |
+
chosen by random projections. The bundled runtime implements the schedule as the reference does,
|
| 42 |
+
plus the reference's fp32 indexer scores and router logits and the indexer LayerNorm epsilon.
|
| 43 |
+
Tiny-config parity against `transformers` 5.16 is **4e-7** with the sparse path live, cached decode
|
| 44 |
+
exact; strict loading of this checkpoint reports zero missing and zero unexpected tensors. Details and
|
| 45 |
+
tests: [https://github.com/PipeNetwork/glm53-mlx](https://github.com/PipeNetwork/glm53-mlx).
|
| 46 |
+
|
| 47 |
+
## Size and what is quantized
|
| 48 |
+
|
| 49 |
+
**511.5 GB** on disk. RAM: 768 GB (two machines).
|
| 50 |
+
|
| 51 |
+
| group | share of parameters | this build |
|
| 52 |
+
|---|---:|---|
|
| 53 |
+
| routed experts (`switch_mlp`, 75 layers × 256) | 724.8B (97.5%) | 5-bit, group 64 |
|
| 54 |
+
| attention (MLA), shared experts, dense layers 0–2, embeddings, `lm_head` | 18.4B (2.5%) | 5-bit, group 64 |
|
| 55 |
+
| lightning indexer (21 layers), MoE router + correction bias, norms | 0.3B | as stored (bf16 / fp32) |
|
| 56 |
+
|
| 57 |
+
Source precision: the FP8 release is a lossy derivative of the bf16 one (dequantized FP8 weights
|
| 58 |
+
differ from bf16 by up to 1.6e-2 on values of 0.46 — half an e4m3 step). The ladder row `fp8` is the FP8 release itself measured against bf16: its error is the floor any FP8-sourced build inherits.
|
| 59 |
+
|
| 60 |
+
## Quality
|
| 61 |
+
|
| 62 |
+
Two measurements, because at 744B most of the ladder cannot be loaded on a 512 GB machine:
|
| 63 |
+
|
| 64 |
+
**Per-layer divergence vs bf16** (`scripts/eval_ladder.py`): every decoder layer run in bf16 and in
|
| 65 |
+
each recipe on identical inputs (16,384 tokens of wikitext-2), *teacher-forced* (each layer
|
| 66 |
+
sees bf16 inputs — isolates its own damage) and *free-running* (each recipe feeds itself — what
|
| 67 |
+
inference does). Relative L2 error of the layer output; lower is better.
|
| 68 |
+
|
| 69 |
+
| recipe | teacher-forced (mean over layers) | free-running (final layer) | cosine (final) |
|
| 70 |
+
|---|---:|---:|---:|
|
| 71 |
+
| 8bit | 0.00685 | 0.13119 | 0.98945 |
|
| 72 |
+
| 6bit | 0.01465 | 0.16736 | 0.98389 |
|
| 73 |
+
| 5bit | 0.02651 | 0.22521 | 0.97272 |
|
| 74 |
+
| 4bit | 0.05161 | 0.35740 | 0.93390 |
|
| 75 |
+
| mixed-4_8bit | 0.02524 | 0.24951 | 0.96710 |
|
| 76 |
+
| mixed-3_6bit | 0.05242 | 0.42380 | 0.90624 |
|
| 77 |
+
| fp8 | 0.01741 | 0.17321 | 0.98320 |
|
| 78 |
+
|
| 79 |
+
**Perplexity** on wikitext-2 (test), 288,627 tokens in 141 windows of 2048, for the builds
|
| 80 |
+
that fit this machine, scored on identical windows:
|
| 81 |
+
|
| 82 |
+
| build | size | perplexity [95% CI] |
|
| 83 |
+
|---|---:|---|
|
| 84 |
+
| [4bit](https://huggingface.co/pipenetwork/GLM-5.3-MLX-4bit) | 418.6 GB | 2.8636 [2.6681, 3.0714] |
|
| 85 |
+
| [mixed-4_8bit](https://huggingface.co/pipenetwork/GLM-5.3-MLX-mixed-4_8bit) | 427.8 GB | 2.7420 [2.5533, 2.9477] |
|
| 86 |
+
| [mixed-3_6bit](https://huggingface.co/pipenetwork/GLM-5.3-MLX-mixed-3_6bit) | 332.6 GB | 3.0338 [2.8366, 3.2386] |
|
| 87 |
+
| [REAP50-4bit](https://huggingface.co/pipenetwork/GLM-5.3-REAP50-MLX-4bit) | 214.7 GB | 5.0295 [4.7571, 5.3137] |
|
| 88 |
+
|
| 89 |
+
**Recommendation.** For a 512 GB Mac, **mixed 4/8-bit** (427.7 GB): perplexity 2.7420, a paired 4.3% better than uniform 4-bit (ratio 0.9575 [0.9537, 0.9612], better on 98.6% of windows) for 9 GB more — the 2.5% of non-expert weights are worth their 8 bits, as on every model we have measured. Uniform 4-bit (418.6 GB) is the fallback when those 9 GB matter. **Mixed 3/6-bit** (332.6 GB) is the 384 GB-class option, at a real cost: 3.0338, +5.9% over 4-bit and +10.6% over mixed 4/8 — it leads the ladder for the first ten layers and then 3-bit expert damage compounds. Among the builds that cannot be run here, the ladder puts 8-bit closest to bfloat16 (free-running error 0.131), then 6-bit (0.167); the **upstream FP8 release scores 0.173, between 6-bit and 5-bit**, which is why these are converted from the bf16 release. 5-bit (0.225) sits just above mixed 4/8 (0.250) at 100 GB more.
|
| 90 |
+
|
| 91 |
+
Greedy generation (a collapse detector, not a ranking) is coherent on every published build.
|
| 92 |
+
|
| 93 |
+
## License
|
| 94 |
+
|
| 95 |
+
[GLM-5.3 license](LICENSE), as the upstream model. Port code: [https://github.com/PipeNetwork/glm53-mlx](https://github.com/PipeNetwork/glm53-mlx).
|
__pycache__/glm_moe_dsa.cpython-314.pyc
ADDED
|
Binary file (41.2 kB). View file
|
|
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[gMASK]<sop>
|
| 2 |
+
{%- set effective_reasoning_effort = reasoning_effort if reasoning_effort is defined and reasoning_effort in ['low', 'high'] else 'max' -%}
|
| 3 |
+
{%- if effective_reasoning_effort is not none -%}<|system|>Reasoning Effort: {{ effective_reasoning_effort | capitalize }}{%- endif -%}
|
| 4 |
+
{%- set clear_thinking = clear_thinking if clear_thinking is defined else false -%}
|
| 5 |
+
{%- if tools -%}
|
| 6 |
+
{%- macro tool_to_json(tool) -%}
|
| 7 |
+
{%- set ns_tool = namespace(first=true) -%}
|
| 8 |
+
{{ '{' -}}
|
| 9 |
+
{%- for k, v in tool.items() -%}
|
| 10 |
+
{%- if k != 'defer_loading' and k != 'strict' -%}
|
| 11 |
+
{%- if not ns_tool.first -%}{{- ', ' -}}{%- endif -%}
|
| 12 |
+
{%- set ns_tool.first = false -%}
|
| 13 |
+
"{{ k }}": {{ v | tojson(ensure_ascii=False) }}
|
| 14 |
+
{%- endif -%}
|
| 15 |
+
{%- endfor -%}
|
| 16 |
+
{{- '}' -}}
|
| 17 |
+
{%- endmacro -%}
|
| 18 |
+
{%- macro tool_references_to_response(refs) -%}
|
| 19 |
+
{{- '<tool_response><tools>\n' -}}
|
| 20 |
+
{%- for tr in refs -%}
|
| 21 |
+
{%- for tool in tools -%}
|
| 22 |
+
{%- if 'function' in tool -%}
|
| 23 |
+
{%- set tool = tool['function'] -%}
|
| 24 |
+
{%- endif -%}
|
| 25 |
+
{%- if tool.name == tr.name -%}
|
| 26 |
+
{{- tool_to_json(tool) + '\n' -}}
|
| 27 |
+
{%- endif -%}
|
| 28 |
+
{%- endfor -%}
|
| 29 |
+
{%- endfor -%}
|
| 30 |
+
{{- '</tools></tool_response>' -}}
|
| 31 |
+
{%- endmacro -%}
|
| 32 |
+
<|system|>
|
| 33 |
+
# Tools
|
| 34 |
+
|
| 35 |
+
You may call one or more functions to assist with the user query.
|
| 36 |
+
|
| 37 |
+
You are provided with function signatures within <tools></tools> XML tags:
|
| 38 |
+
<tools>
|
| 39 |
+
{% for tool in tools %}
|
| 40 |
+
{%- if 'function' in tool -%}
|
| 41 |
+
{%- set tool = tool['function'] -%}
|
| 42 |
+
{%- endif -%}
|
| 43 |
+
{% if tool.defer_loading is not defined or not tool.defer_loading %}
|
| 44 |
+
{{ tool_to_json(tool) }}
|
| 45 |
+
{% endif %}
|
| 46 |
+
{% endfor %}
|
| 47 |
+
</tools>
|
| 48 |
+
|
| 49 |
+
For each function call, output the function name and arguments within the following XML format:
|
| 50 |
+
<tool_call>{function-name}<arg_key>{arg-key-1}</arg_key><arg_value>{arg-value-1}</arg_value><arg_key>{arg-key-2}</arg_key><arg_value>{arg-value-2}</arg_value>...</tool_call>{%- endif -%}
|
| 51 |
+
{%- macro visible_text(content) -%}
|
| 52 |
+
{%- if content is string -%}
|
| 53 |
+
{{- content }}
|
| 54 |
+
{%- elif content is iterable and content is not mapping -%}
|
| 55 |
+
{%- for item in content -%}
|
| 56 |
+
{%- if item is mapping and item.type == 'text' -%}
|
| 57 |
+
{{- item.text }}
|
| 58 |
+
{%- elif item is string -%}
|
| 59 |
+
{{- item }}
|
| 60 |
+
{%- elif item is mapping and item.type in ['image', 'image_url', 'video', 'video_url', 'audio', 'audio_url', 'input_audio'] -%}
|
| 61 |
+
{%- set media_type = item.type | replace('_url', '') | replace('input_', '') -%}
|
| 62 |
+
{{- "<reminder>You are unable to process this " ~ media_type ~ " because you don't have multi-modal input ability. Try different methods.</reminder>" }}
|
| 63 |
+
{%- endif -%}
|
| 64 |
+
{%- endfor -%}
|
| 65 |
+
{%- else -%}
|
| 66 |
+
{{- content }}
|
| 67 |
+
{%- endif -%}
|
| 68 |
+
{%- endmacro -%}
|
| 69 |
+
{%- macro tool_response(text) -%}
|
| 70 |
+
{{- '<tool_response>' + text + '</tool_response>' -}}
|
| 71 |
+
{%- endmacro -%}
|
| 72 |
+
{%- macro render_tool_response(m) -%}
|
| 73 |
+
{%- if m.content is string -%}
|
| 74 |
+
{{- tool_response(m.content) -}}
|
| 75 |
+
{%- elif m.content and m.content is not mapping and m.content.0.type == "tool_reference" -%}
|
| 76 |
+
{{- tool_references_to_response(m.content) -}}
|
| 77 |
+
{%- elif is_list_of_outputs(m) -%}
|
| 78 |
+
{%- for tr in m.content -%}
|
| 79 |
+
{%- if tr.output is iterable and tr.output is not string and tr.output is not mapping and tr.output and tr.output.0.type == "tool_reference" -%}
|
| 80 |
+
{{- tool_references_to_response(tr.output) -}}
|
| 81 |
+
{%- else -%}
|
| 82 |
+
{{- tool_response(visible_text(tr.output)) -}}
|
| 83 |
+
{%- endif -%}
|
| 84 |
+
{%- endfor -%}
|
| 85 |
+
{%- else -%}
|
| 86 |
+
{{- tool_response(visible_text(m.content)) -}}
|
| 87 |
+
{%- endif -%}
|
| 88 |
+
{%- endmacro -%}
|
| 89 |
+
{%- macro id_of(obj) -%}
|
| 90 |
+
{%- if obj.tool_call_id -%}
|
| 91 |
+
{{- obj.tool_call_id -}}
|
| 92 |
+
{%- elif obj.id -%}
|
| 93 |
+
{{- obj.id -}}
|
| 94 |
+
{%- endif -%}
|
| 95 |
+
{%- endmacro -%}
|
| 96 |
+
{%- macro is_list_of_outputs(m) -%}
|
| 97 |
+
{%- if m.content and m.content.0.output is defined -%}1{%- endif -%}
|
| 98 |
+
{%- endmacro -%}
|
| 99 |
+
{%- macro has_dup_tool_result_id(lo, hi, target) -%}
|
| 100 |
+
{%- set ns_cnt = namespace(n=0) -%}
|
| 101 |
+
{%- for k in range(lo, hi + 1) -%}
|
| 102 |
+
{%- set m = messages[k] -%}
|
| 103 |
+
{%- if is_list_of_outputs(m) -%}
|
| 104 |
+
{%- for entry in m.content -%}
|
| 105 |
+
{%- if id_of(entry) == target -%}
|
| 106 |
+
{%- set ns_cnt.n = ns_cnt.n + 1 -%}
|
| 107 |
+
{%- endif -%}
|
| 108 |
+
{%- endfor -%}
|
| 109 |
+
{%- elif id_of(m) == target -%}
|
| 110 |
+
{%- set ns_cnt.n = ns_cnt.n + 1 -%}
|
| 111 |
+
{%- endif -%}
|
| 112 |
+
{%- if ns_cnt.n > 1 -%}{%- break -%}{%- endif -%}
|
| 113 |
+
{%- endfor -%}
|
| 114 |
+
{%- if ns_cnt.n > 1 -%}1{%- endif -%}
|
| 115 |
+
{%- endmacro -%}
|
| 116 |
+
{%- macro tc_id_exists(tcs, target) -%}
|
| 117 |
+
{%- set ns_f = namespace(found=false) -%}
|
| 118 |
+
{%- for tc in tcs -%}
|
| 119 |
+
{%- if id_of(tc) == target -%}
|
| 120 |
+
{%- set ns_f.found = true -%}
|
| 121 |
+
{%- break -%}
|
| 122 |
+
{%- endif -%}
|
| 123 |
+
{%- endfor -%}
|
| 124 |
+
{%- if ns_f.found -%}1{%- endif -%}
|
| 125 |
+
{%- endmacro -%}
|
| 126 |
+
{%- set ns = namespace(last_user_index=-1) -%}
|
| 127 |
+
{%- for m in messages %}
|
| 128 |
+
{%- if m.role == 'user' %}
|
| 129 |
+
{%- set ns.last_user_index = loop.index0 -%}
|
| 130 |
+
{%- endif %}
|
| 131 |
+
{%- endfor %}
|
| 132 |
+
{%- for m in messages -%}
|
| 133 |
+
{%- if m.role == 'user' -%}<|user|>{{ visible_text(m.content) }}
|
| 134 |
+
{%- elif m.role == 'assistant' -%}
|
| 135 |
+
<|assistant|>
|
| 136 |
+
{%- set content = visible_text(m.content) %}
|
| 137 |
+
{%- if m.reasoning_content is string %}
|
| 138 |
+
{%- set reasoning_content = m.reasoning_content %}
|
| 139 |
+
{%- elif '</think>' in content %}
|
| 140 |
+
{%- set reasoning_content = content.split('</think>')[0].split('<think>')[-1] %}
|
| 141 |
+
{%- set content = content.split('</think>')[-1] %}
|
| 142 |
+
{%- endif %}
|
| 143 |
+
{%- if (not clear_thinking or loop.index0 > ns.last_user_index) and reasoning_content is defined -%}
|
| 144 |
+
{{ '<think>' + reasoning_content + '</think>'}}
|
| 145 |
+
{%- else -%}
|
| 146 |
+
{{ '<think></think>' }}
|
| 147 |
+
{%- endif -%}
|
| 148 |
+
{%- if content.strip() -%}
|
| 149 |
+
{{ content.strip() }}
|
| 150 |
+
{%- endif -%}
|
| 151 |
+
{% if m.tool_calls %}
|
| 152 |
+
{% for tc in m.tool_calls %}
|
| 153 |
+
{%- if tc.function %}
|
| 154 |
+
{%- set tc = tc.function %}
|
| 155 |
+
{%- endif %}
|
| 156 |
+
{{- '<tool_call>' + tc.name -}}
|
| 157 |
+
{% set _args = tc.arguments %}{% for k, v in _args.items() %}<arg_key>{{ k }}</arg_key><arg_value>{{ v | tojson(ensure_ascii=False) if v is not string else v }}</arg_value>{% endfor %}</tool_call>{% endfor %}
|
| 158 |
+
{% endif %}
|
| 159 |
+
{%- elif m.role == 'tool' -%}
|
| 160 |
+
{%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
|
| 161 |
+
{{- '<|observation|>' -}}
|
| 162 |
+
{%- set block_start = loop.index0 -%}
|
| 163 |
+
{%- set ns_blk = namespace(end=block_start) -%}
|
| 164 |
+
{%- for j in range(block_start, messages|length) -%}
|
| 165 |
+
{%- if messages[j].role == 'tool' -%}
|
| 166 |
+
{%- set ns_blk.end = j -%}
|
| 167 |
+
{%- else -%}
|
| 168 |
+
{%- break -%}
|
| 169 |
+
{%- endif -%}
|
| 170 |
+
{%- endfor -%}
|
| 171 |
+
{%- set ns_a = namespace(tool_calls=none) -%}
|
| 172 |
+
{%- if block_start > 0 and messages[block_start - 1].role == 'assistant' and messages[block_start - 1].tool_calls -%}
|
| 173 |
+
{%- set ns_a.tool_calls = messages[block_start - 1].tool_calls -%}
|
| 174 |
+
{%- endif -%}
|
| 175 |
+
{%- set ns_chk = namespace(can_sort=true) -%}
|
| 176 |
+
{%- if not ns_a.tool_calls -%}
|
| 177 |
+
{%- set ns_chk.can_sort = false -%}
|
| 178 |
+
{%- else -%}
|
| 179 |
+
{%- for k in range(block_start, ns_blk.end + 1) -%}
|
| 180 |
+
{%- set m = messages[k] -%}
|
| 181 |
+
{%- if is_list_of_outputs(m) -%}
|
| 182 |
+
{%- for entry in m.content -%}
|
| 183 |
+
{%- set eid = id_of(entry) -%}
|
| 184 |
+
{%- if not eid -%}
|
| 185 |
+
{%- set ns_chk.can_sort = false -%}
|
| 186 |
+
{%- elif has_dup_tool_result_id(block_start, ns_blk.end, eid) -%}
|
| 187 |
+
{%- set ns_chk.can_sort = false -%}
|
| 188 |
+
{%- elif not tc_id_exists(ns_a.tool_calls, eid) -%}
|
| 189 |
+
{%- set ns_chk.can_sort = false -%}
|
| 190 |
+
{%- endif -%}
|
| 191 |
+
{%- endfor -%}
|
| 192 |
+
{%- else -%}
|
| 193 |
+
{%- set tk_id = id_of(m) -%}
|
| 194 |
+
{%- if not tk_id -%}
|
| 195 |
+
{%- set ns_chk.can_sort = false -%}
|
| 196 |
+
{%- elif has_dup_tool_result_id(block_start, ns_blk.end, tk_id) -%}
|
| 197 |
+
{%- set ns_chk.can_sort = false -%}
|
| 198 |
+
{%- elif not tc_id_exists(ns_a.tool_calls, tk_id) -%}
|
| 199 |
+
{%- set ns_chk.can_sort = false -%}
|
| 200 |
+
{%- endif -%}
|
| 201 |
+
{%- endif -%}
|
| 202 |
+
{%- endfor -%}
|
| 203 |
+
{%- for i in range(ns_a.tool_calls | length) -%}
|
| 204 |
+
{%- set tc_id = id_of(ns_a.tool_calls[i]) -%}
|
| 205 |
+
{%- if not tc_id -%}
|
| 206 |
+
{%- set ns_chk.can_sort = false -%}
|
| 207 |
+
{%- endif -%}
|
| 208 |
+
{%- for j in range(i + 1, ns_a.tool_calls | length) -%}
|
| 209 |
+
{%- if id_of(ns_a.tool_calls[j]) == tc_id -%}
|
| 210 |
+
{%- set ns_chk.can_sort = false -%}
|
| 211 |
+
{%- endif -%}
|
| 212 |
+
{%- endfor -%}
|
| 213 |
+
{%- endfor -%}
|
| 214 |
+
{%- endif -%}
|
| 215 |
+
{%- if ns_chk.can_sort -%}
|
| 216 |
+
{%- for tc in ns_a.tool_calls -%}
|
| 217 |
+
{%- set tc_id = id_of(tc) -%}
|
| 218 |
+
{%- for k in range(block_start, ns_blk.end + 1) -%}
|
| 219 |
+
{%- set m = messages[k] -%}
|
| 220 |
+
{%- if is_list_of_outputs(m) -%}
|
| 221 |
+
{%- for entry in m.content -%}
|
| 222 |
+
{%- set eid = id_of(entry) -%}
|
| 223 |
+
{%- if eid == tc_id -%}
|
| 224 |
+
{%- if entry.output is iterable and entry.output is not string and entry.output is not mapping and entry.output and entry.output.0.type == "tool_reference" -%}
|
| 225 |
+
{{- tool_references_to_response(entry.output) -}}
|
| 226 |
+
{%- else -%}
|
| 227 |
+
{{- tool_response(visible_text(entry.output)) -}}
|
| 228 |
+
{%- endif -%}
|
| 229 |
+
{%- endif -%}
|
| 230 |
+
{%- endfor -%}
|
| 231 |
+
{%- else -%}
|
| 232 |
+
{%- set tk_id = id_of(m) -%}
|
| 233 |
+
{%- if tk_id == tc_id -%}
|
| 234 |
+
{{- render_tool_response(m) -}}
|
| 235 |
+
{%- endif -%}
|
| 236 |
+
{%- endif -%}
|
| 237 |
+
{%- endfor -%}
|
| 238 |
+
{%- endfor -%}
|
| 239 |
+
{%- else -%}
|
| 240 |
+
{%- for k in range(block_start, ns_blk.end + 1) -%}
|
| 241 |
+
{{- render_tool_response(messages[k]) -}}
|
| 242 |
+
{%- endfor -%}
|
| 243 |
+
{%- endif -%}
|
| 244 |
+
{% endif -%}
|
| 245 |
+
{%- elif m.role == 'system' -%}
|
| 246 |
+
<|system|>{{ visible_text(m.content) }}
|
| 247 |
+
{%- endif -%}
|
| 248 |
+
{%- endfor -%}
|
| 249 |
+
{%- if add_generation_prompt -%}
|
| 250 |
+
<|assistant|>{{- '<think>' -}}
|
| 251 |
+
{%- endif -%}
|
config.json
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"GlmMoeDsaForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"dtype": "bfloat16",
|
| 8 |
+
"eos_token_id": [
|
| 9 |
+
154820,
|
| 10 |
+
154827,
|
| 11 |
+
154829
|
| 12 |
+
],
|
| 13 |
+
"ep_size": 1,
|
| 14 |
+
"first_k_dense_replace": 3,
|
| 15 |
+
"head_dim": 192,
|
| 16 |
+
"hidden_act": "silu",
|
| 17 |
+
"hidden_size": 6144,
|
| 18 |
+
"index_head_dim": 128,
|
| 19 |
+
"index_n_heads": 32,
|
| 20 |
+
"index_share_for_mtp_iteration": true,
|
| 21 |
+
"index_skip_topk_offset": 3,
|
| 22 |
+
"index_topk": 2048,
|
| 23 |
+
"index_topk_freq": 4,
|
| 24 |
+
"index_topk_pattern": null,
|
| 25 |
+
"indexer_rope_interleave": true,
|
| 26 |
+
"indexer_types": [
|
| 27 |
+
"full",
|
| 28 |
+
"full",
|
| 29 |
+
"full",
|
| 30 |
+
"shared",
|
| 31 |
+
"shared",
|
| 32 |
+
"shared",
|
| 33 |
+
"full",
|
| 34 |
+
"shared",
|
| 35 |
+
"shared",
|
| 36 |
+
"shared",
|
| 37 |
+
"full",
|
| 38 |
+
"shared",
|
| 39 |
+
"shared",
|
| 40 |
+
"shared",
|
| 41 |
+
"full",
|
| 42 |
+
"shared",
|
| 43 |
+
"shared",
|
| 44 |
+
"shared",
|
| 45 |
+
"full",
|
| 46 |
+
"shared",
|
| 47 |
+
"shared",
|
| 48 |
+
"shared",
|
| 49 |
+
"full",
|
| 50 |
+
"shared",
|
| 51 |
+
"shared",
|
| 52 |
+
"shared",
|
| 53 |
+
"full",
|
| 54 |
+
"shared",
|
| 55 |
+
"shared",
|
| 56 |
+
"shared",
|
| 57 |
+
"full",
|
| 58 |
+
"shared",
|
| 59 |
+
"shared",
|
| 60 |
+
"shared",
|
| 61 |
+
"full",
|
| 62 |
+
"shared",
|
| 63 |
+
"shared",
|
| 64 |
+
"shared",
|
| 65 |
+
"full",
|
| 66 |
+
"shared",
|
| 67 |
+
"shared",
|
| 68 |
+
"shared",
|
| 69 |
+
"full",
|
| 70 |
+
"shared",
|
| 71 |
+
"shared",
|
| 72 |
+
"shared",
|
| 73 |
+
"full",
|
| 74 |
+
"shared",
|
| 75 |
+
"shared",
|
| 76 |
+
"shared",
|
| 77 |
+
"full",
|
| 78 |
+
"shared",
|
| 79 |
+
"shared",
|
| 80 |
+
"shared",
|
| 81 |
+
"full",
|
| 82 |
+
"shared",
|
| 83 |
+
"shared",
|
| 84 |
+
"shared",
|
| 85 |
+
"full",
|
| 86 |
+
"shared",
|
| 87 |
+
"shared",
|
| 88 |
+
"shared",
|
| 89 |
+
"full",
|
| 90 |
+
"shared",
|
| 91 |
+
"shared",
|
| 92 |
+
"shared",
|
| 93 |
+
"full",
|
| 94 |
+
"shared",
|
| 95 |
+
"shared",
|
| 96 |
+
"shared",
|
| 97 |
+
"full",
|
| 98 |
+
"shared",
|
| 99 |
+
"shared",
|
| 100 |
+
"shared",
|
| 101 |
+
"full",
|
| 102 |
+
"shared",
|
| 103 |
+
"shared",
|
| 104 |
+
"shared"
|
| 105 |
+
],
|
| 106 |
+
"initializer_range": 0.02,
|
| 107 |
+
"intermediate_size": 12288,
|
| 108 |
+
"kv_lora_rank": 512,
|
| 109 |
+
"max_position_embeddings": 1048576,
|
| 110 |
+
"mlp_layer_types": [
|
| 111 |
+
"dense",
|
| 112 |
+
"dense",
|
| 113 |
+
"dense",
|
| 114 |
+
"sparse",
|
| 115 |
+
"sparse",
|
| 116 |
+
"sparse",
|
| 117 |
+
"sparse",
|
| 118 |
+
"sparse",
|
| 119 |
+
"sparse",
|
| 120 |
+
"sparse",
|
| 121 |
+
"sparse",
|
| 122 |
+
"sparse",
|
| 123 |
+
"sparse",
|
| 124 |
+
"sparse",
|
| 125 |
+
"sparse",
|
| 126 |
+
"sparse",
|
| 127 |
+
"sparse",
|
| 128 |
+
"sparse",
|
| 129 |
+
"sparse",
|
| 130 |
+
"sparse",
|
| 131 |
+
"sparse",
|
| 132 |
+
"sparse",
|
| 133 |
+
"sparse",
|
| 134 |
+
"sparse",
|
| 135 |
+
"sparse",
|
| 136 |
+
"sparse",
|
| 137 |
+
"sparse",
|
| 138 |
+
"sparse",
|
| 139 |
+
"sparse",
|
| 140 |
+
"sparse",
|
| 141 |
+
"sparse",
|
| 142 |
+
"sparse",
|
| 143 |
+
"sparse",
|
| 144 |
+
"sparse",
|
| 145 |
+
"sparse",
|
| 146 |
+
"sparse",
|
| 147 |
+
"sparse",
|
| 148 |
+
"sparse",
|
| 149 |
+
"sparse",
|
| 150 |
+
"sparse",
|
| 151 |
+
"sparse",
|
| 152 |
+
"sparse",
|
| 153 |
+
"sparse",
|
| 154 |
+
"sparse",
|
| 155 |
+
"sparse",
|
| 156 |
+
"sparse",
|
| 157 |
+
"sparse",
|
| 158 |
+
"sparse",
|
| 159 |
+
"sparse",
|
| 160 |
+
"sparse",
|
| 161 |
+
"sparse",
|
| 162 |
+
"sparse",
|
| 163 |
+
"sparse",
|
| 164 |
+
"sparse",
|
| 165 |
+
"sparse",
|
| 166 |
+
"sparse",
|
| 167 |
+
"sparse",
|
| 168 |
+
"sparse",
|
| 169 |
+
"sparse",
|
| 170 |
+
"sparse",
|
| 171 |
+
"sparse",
|
| 172 |
+
"sparse",
|
| 173 |
+
"sparse",
|
| 174 |
+
"sparse",
|
| 175 |
+
"sparse",
|
| 176 |
+
"sparse",
|
| 177 |
+
"sparse",
|
| 178 |
+
"sparse",
|
| 179 |
+
"sparse",
|
| 180 |
+
"sparse",
|
| 181 |
+
"sparse",
|
| 182 |
+
"sparse",
|
| 183 |
+
"sparse",
|
| 184 |
+
"sparse",
|
| 185 |
+
"sparse",
|
| 186 |
+
"sparse",
|
| 187 |
+
"sparse",
|
| 188 |
+
"sparse"
|
| 189 |
+
],
|
| 190 |
+
"model_type": "glm_moe_dsa",
|
| 191 |
+
"moe_intermediate_size": 2048,
|
| 192 |
+
"moe_layer_freq": 1,
|
| 193 |
+
"moe_router_dtype": "float32",
|
| 194 |
+
"n_group": 1,
|
| 195 |
+
"n_routed_experts": 256,
|
| 196 |
+
"n_shared_experts": 1,
|
| 197 |
+
"norm_topk_prob": true,
|
| 198 |
+
"num_attention_heads": 64,
|
| 199 |
+
"num_experts_per_tok": 8,
|
| 200 |
+
"num_hidden_layers": 78,
|
| 201 |
+
"num_key_value_heads": 64,
|
| 202 |
+
"num_nextn_predict_layers": 1,
|
| 203 |
+
"pad_token_id": 154820,
|
| 204 |
+
"pretraining_tp": 1,
|
| 205 |
+
"q_lora_rank": 2048,
|
| 206 |
+
"qk_head_dim": 256,
|
| 207 |
+
"qk_nope_head_dim": 192,
|
| 208 |
+
"qk_rope_head_dim": 64,
|
| 209 |
+
"rms_norm_eps": 1e-05,
|
| 210 |
+
"rope_interleave": true,
|
| 211 |
+
"rope_parameters": {
|
| 212 |
+
"rope_theta": 8000000,
|
| 213 |
+
"rope_type": "default"
|
| 214 |
+
},
|
| 215 |
+
"routed_scaling_factor": 2.5,
|
| 216 |
+
"scoring_func": "sigmoid",
|
| 217 |
+
"tie_word_embeddings": false,
|
| 218 |
+
"topk_group": 1,
|
| 219 |
+
"topk_method": "noaux_tc",
|
| 220 |
+
"transformers_version": "5.15.0",
|
| 221 |
+
"use_cache": true,
|
| 222 |
+
"v_head_dim": 256,
|
| 223 |
+
"vocab_size": 154880,
|
| 224 |
+
"quantization": {
|
| 225 |
+
"group_size": 64,
|
| 226 |
+
"bits": 5
|
| 227 |
+
},
|
| 228 |
+
"quantization_config": {
|
| 229 |
+
"group_size": 64,
|
| 230 |
+
"bits": 5
|
| 231 |
+
},
|
| 232 |
+
"model_file": "glm_moe_dsa.py"
|
| 233 |
+
}
|
generation_config.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from_model_config": true,
|
| 3 |
+
"eos_token_id": [
|
| 4 |
+
154820,
|
| 5 |
+
154827,
|
| 6 |
+
154829
|
| 7 |
+
],
|
| 8 |
+
"pad_token_id": 154820,
|
| 9 |
+
"temperature": 1.0,
|
| 10 |
+
"top_p": 0.95,
|
| 11 |
+
"transformers_version": "5.12.0"
|
| 12 |
+
}
|
glm_moe_dsa.py
ADDED
|
@@ -0,0 +1,703 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright © 2025 Apple Inc.
|
| 2 |
+
|
| 3 |
+
import math
|
| 4 |
+
from dataclasses import dataclass
|
| 5 |
+
from typing import Any, Dict, Optional
|
| 6 |
+
|
| 7 |
+
import mlx.core as mx
|
| 8 |
+
import mlx.nn as nn
|
| 9 |
+
from mlx.nn.layers.distributed import shard_inplace, shard_linear, sum_gradients
|
| 10 |
+
|
| 11 |
+
from mlx_lm.models.activations import swiglu
|
| 12 |
+
from mlx_lm.models.base import BaseModelArgs, create_attention_mask, scaled_dot_product_attention
|
| 13 |
+
from mlx_lm.models.cache import CacheList, KVCache
|
| 14 |
+
from mlx_lm.models.mla import MultiLinear
|
| 15 |
+
from mlx_lm.models.rope_utils import initialize_rope
|
| 16 |
+
from mlx_lm.models.switch_layers import SwitchGLU
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
@dataclass
|
| 20 |
+
class ModelArgs(BaseModelArgs):
|
| 21 |
+
model_type: str
|
| 22 |
+
vocab_size: int
|
| 23 |
+
hidden_size: int
|
| 24 |
+
index_head_dim: int
|
| 25 |
+
index_n_heads: int
|
| 26 |
+
index_topk: int
|
| 27 |
+
intermediate_size: int
|
| 28 |
+
moe_intermediate_size: int
|
| 29 |
+
num_hidden_layers: int
|
| 30 |
+
num_attention_heads: int
|
| 31 |
+
num_key_value_heads: int
|
| 32 |
+
n_shared_experts: Optional[int]
|
| 33 |
+
n_routed_experts: Optional[int]
|
| 34 |
+
routed_scaling_factor: float
|
| 35 |
+
kv_lora_rank: int
|
| 36 |
+
q_lora_rank: int
|
| 37 |
+
qk_rope_head_dim: int
|
| 38 |
+
v_head_dim: int
|
| 39 |
+
qk_nope_head_dim: int
|
| 40 |
+
topk_method: str
|
| 41 |
+
scoring_func: str
|
| 42 |
+
norm_topk_prob: bool
|
| 43 |
+
n_group: int
|
| 44 |
+
topk_group: int
|
| 45 |
+
num_experts_per_tok: int
|
| 46 |
+
moe_layer_freq: int
|
| 47 |
+
first_k_dense_replace: int
|
| 48 |
+
max_position_embeddings: int
|
| 49 |
+
rms_norm_eps: float
|
| 50 |
+
rope_parameters: Dict
|
| 51 |
+
attention_bias: bool
|
| 52 |
+
rope_scaling: Dict = None
|
| 53 |
+
rope_theta: Optional[float] = None
|
| 54 |
+
indexer_rope_interleave: bool = True
|
| 55 |
+
rope_interleave: bool = True
|
| 56 |
+
indexer_types: Optional[list] = None
|
| 57 |
+
index_topk_freq: int = 1
|
| 58 |
+
index_skip_topk_offset: int = 0
|
| 59 |
+
index_topk_pattern: Optional[Any] = None
|
| 60 |
+
num_nextn_predict_layers: int = 0
|
| 61 |
+
mlp_layer_types: Optional[list] = None
|
| 62 |
+
|
| 63 |
+
def __post_init__(self):
|
| 64 |
+
self.rope_scaling = self.rope_parameters
|
| 65 |
+
self.rope_theta = self.rope_parameters["rope_theta"]
|
| 66 |
+
if self.indexer_types is None:
|
| 67 |
+
# Reference schedule: a layer runs its own indexer ("full") iff
|
| 68 |
+
# max(i - offset + 1, 0) % freq == 0; the others ("shared") reuse the most recent
|
| 69 |
+
# full layer's top-k selection and carry no indexer weights.
|
| 70 |
+
f, o = self.index_topk_freq, self.index_skip_topk_offset
|
| 71 |
+
self.indexer_types = [
|
| 72 |
+
"full" if max(i - o + 1, 0) % f == 0 else "shared"
|
| 73 |
+
for i in range(self.num_hidden_layers)
|
| 74 |
+
]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
class Indexer(nn.Module):
|
| 79 |
+
def __init__(self, args: ModelArgs):
|
| 80 |
+
super().__init__()
|
| 81 |
+
self.dim = args.hidden_size
|
| 82 |
+
self.n_heads = args.index_n_heads
|
| 83 |
+
self.head_dim = args.index_head_dim
|
| 84 |
+
self.rope_head_dim = args.qk_rope_head_dim
|
| 85 |
+
self.index_topk = args.index_topk
|
| 86 |
+
self.q_lora_rank = args.q_lora_rank
|
| 87 |
+
self.wq_b = nn.Linear(
|
| 88 |
+
self.q_lora_rank, self.n_heads * self.head_dim, bias=False
|
| 89 |
+
)
|
| 90 |
+
self.wk = nn.Linear(self.dim, self.head_dim, bias=False)
|
| 91 |
+
self.k_norm = nn.LayerNorm(self.head_dim, eps=1e-6)
|
| 92 |
+
self.weights_proj = nn.Linear(self.dim, self.n_heads, bias=False)
|
| 93 |
+
self.softmax_scale = self.head_dim**-0.5
|
| 94 |
+
self.rope = initialize_rope(
|
| 95 |
+
dims=args.qk_rope_head_dim,
|
| 96 |
+
base=args.rope_theta,
|
| 97 |
+
traditional=args.indexer_rope_interleave,
|
| 98 |
+
max_position_embeddings=args.max_position_embeddings,
|
| 99 |
+
scaling_config=args.rope_scaling,
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
def __call__(
|
| 103 |
+
self,
|
| 104 |
+
x: mx.array,
|
| 105 |
+
qr: mx.array,
|
| 106 |
+
mask: Optional[mx.array],
|
| 107 |
+
cache: Optional[Any] = None,
|
| 108 |
+
):
|
| 109 |
+
# Computes top_k indices for attention
|
| 110 |
+
b, s, _ = x.shape
|
| 111 |
+
q = self.wq_b(qr)
|
| 112 |
+
q = q.reshape(b, s, self.n_heads, self.head_dim).swapaxes(1, 2)
|
| 113 |
+
k = self.wk(x)
|
| 114 |
+
k = self.k_norm(k)
|
| 115 |
+
k = mx.reshape(k, (b, 1, s, self.head_dim))
|
| 116 |
+
|
| 117 |
+
offset = cache.offset if cache is not None else 0
|
| 118 |
+
|
| 119 |
+
q = self.rope(q, offset=offset)
|
| 120 |
+
k = self.rope(k, offset=offset)
|
| 121 |
+
|
| 122 |
+
if cache is not None:
|
| 123 |
+
k, _ = cache.update_and_fetch(k, mx.zeros([b, 1, s, 0]))
|
| 124 |
+
if k.shape[2] <= self.index_topk:
|
| 125 |
+
return None
|
| 126 |
+
# Scores in float32, as the reference (which also keeps weights_proj in fp32): in bf16
|
| 127 |
+
# keys at the top-k boundary flip.
|
| 128 |
+
scores = q.astype(mx.float32) @ k.astype(mx.float32).swapaxes(-1, -2)
|
| 129 |
+
scores = mx.maximum(scores, 0)
|
| 130 |
+
weights = self.weights_proj(x).astype(mx.float32) * (self.n_heads**-0.5 * self.softmax_scale)
|
| 131 |
+
weights = weights.swapaxes(-1, -2)[..., None]
|
| 132 |
+
scores = scores * weights
|
| 133 |
+
scores = scores.sum(axis=1, keepdims=True)
|
| 134 |
+
if mask is not None:
|
| 135 |
+
scores = mx.where(mask, scores, -float("inf"))
|
| 136 |
+
return mx.argpartition(scores, kth=-self.index_topk, axis=-1)[
|
| 137 |
+
..., -self.index_topk :
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
class DeepseekV32Attention(nn.Module):
|
| 142 |
+
def __init__(self, config: ModelArgs, layer_idx: int = 0):
|
| 143 |
+
super().__init__()
|
| 144 |
+
self.config = config
|
| 145 |
+
self.hidden_size = config.hidden_size
|
| 146 |
+
self.num_heads = config.num_attention_heads
|
| 147 |
+
self.max_position_embeddings = config.max_position_embeddings
|
| 148 |
+
self.rope_theta = config.rope_theta
|
| 149 |
+
self.q_lora_rank = config.q_lora_rank
|
| 150 |
+
self.qk_rope_head_dim = config.qk_rope_head_dim
|
| 151 |
+
self.kv_lora_rank = config.kv_lora_rank
|
| 152 |
+
self.v_head_dim = config.v_head_dim
|
| 153 |
+
self.qk_nope_head_dim = config.qk_nope_head_dim
|
| 154 |
+
self.q_head_dim = config.qk_nope_head_dim + config.qk_rope_head_dim
|
| 155 |
+
|
| 156 |
+
self.scale = self.q_head_dim**-0.5
|
| 157 |
+
|
| 158 |
+
self.q_a_proj = nn.Linear(
|
| 159 |
+
self.hidden_size, self.q_lora_rank, bias=config.attention_bias
|
| 160 |
+
)
|
| 161 |
+
self.q_a_layernorm = nn.RMSNorm(self.q_lora_rank, eps=1e-6)
|
| 162 |
+
self.q_b_proj = nn.Linear(
|
| 163 |
+
self.q_lora_rank, self.num_heads * self.q_head_dim, bias=False
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
self.kv_a_proj_with_mqa = nn.Linear(
|
| 167 |
+
self.hidden_size,
|
| 168 |
+
self.kv_lora_rank + self.qk_rope_head_dim,
|
| 169 |
+
bias=config.attention_bias,
|
| 170 |
+
)
|
| 171 |
+
self.kv_a_layernorm = nn.RMSNorm(self.kv_lora_rank, eps=1e-6)
|
| 172 |
+
self.embed_q = MultiLinear(
|
| 173 |
+
self.qk_nope_head_dim, self.kv_lora_rank, self.num_heads
|
| 174 |
+
)
|
| 175 |
+
self.unembed_out = MultiLinear(
|
| 176 |
+
self.kv_lora_rank, self.v_head_dim, self.num_heads
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
self.o_proj = nn.Linear(
|
| 180 |
+
self.num_heads * self.v_head_dim,
|
| 181 |
+
self.hidden_size,
|
| 182 |
+
bias=config.attention_bias,
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
if self.config.rope_scaling is not None:
|
| 186 |
+
mscale_all_dim = self.config.rope_scaling.get("mscale_all_dim", 0)
|
| 187 |
+
if mscale_all_dim:
|
| 188 |
+
scaling_factor = self.config.rope_scaling["factor"]
|
| 189 |
+
if scaling_factor > 1:
|
| 190 |
+
s = 0.1 * mscale_all_dim * math.log(scaling_factor) + 1.0
|
| 191 |
+
self.scale = self.scale * s * s
|
| 192 |
+
|
| 193 |
+
# "shared" layers carry no indexer weights: they reuse the previous full layer's top-k.
|
| 194 |
+
self.indexer = Indexer(config) if config.indexer_types[layer_idx] == "full" else None
|
| 195 |
+
self.rope = initialize_rope(
|
| 196 |
+
dims=self.qk_rope_head_dim,
|
| 197 |
+
base=self.rope_theta,
|
| 198 |
+
traditional=True,
|
| 199 |
+
max_position_embeddings=self.max_position_embeddings,
|
| 200 |
+
scaling_config=self.config.rope_scaling,
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
def __call__(
|
| 204 |
+
self,
|
| 205 |
+
x: mx.array,
|
| 206 |
+
mask: Optional[mx.array] = None,
|
| 207 |
+
cache: Optional[Any] = None,
|
| 208 |
+
prev_topk_indices: Optional[mx.array] = None,
|
| 209 |
+
):
|
| 210 |
+
B, L, D = x.shape
|
| 211 |
+
|
| 212 |
+
qr = self.q_a_layernorm(self.q_a_proj(x))
|
| 213 |
+
q = self.q_b_proj(qr)
|
| 214 |
+
|
| 215 |
+
q = q.reshape(B, L, self.num_heads, self.q_head_dim).transpose(0, 2, 1, 3)
|
| 216 |
+
q_nope, q_pe = mx.split(q, [self.qk_nope_head_dim], axis=-1)
|
| 217 |
+
compressed_kv = self.kv_a_proj_with_mqa(x)
|
| 218 |
+
compressed_kv, k_pe = mx.split(compressed_kv, [self.kv_lora_rank], axis=-1)
|
| 219 |
+
k_pe = k_pe.reshape(B, L, 1, self.qk_rope_head_dim).transpose(0, 2, 1, 3)
|
| 220 |
+
kv_latent = self.kv_a_layernorm(compressed_kv)
|
| 221 |
+
|
| 222 |
+
offset = cache[0].offset if cache is not None else 0
|
| 223 |
+
q_pe = self.rope(q_pe, offset)
|
| 224 |
+
k_pe = self.rope(k_pe, offset)
|
| 225 |
+
|
| 226 |
+
kv_latent = mx.expand_dims(kv_latent, axis=1)
|
| 227 |
+
|
| 228 |
+
if cache is not None:
|
| 229 |
+
kv_latent, k_pe = cache[0].update_and_fetch(kv_latent, k_pe)
|
| 230 |
+
else:
|
| 231 |
+
cache = [None] * 2
|
| 232 |
+
|
| 233 |
+
if self.indexer is not None:
|
| 234 |
+
topk_indices = self.indexer(x, qr, mask, cache=cache[1])
|
| 235 |
+
else:
|
| 236 |
+
topk_indices = prev_topk_indices
|
| 237 |
+
if topk_indices is not None:
|
| 238 |
+
if L == 1:
|
| 239 |
+
idx = topk_indices[:, :, 0, :, None]
|
| 240 |
+
kv_latent = mx.take_along_axis(
|
| 241 |
+
kv_latent,
|
| 242 |
+
mx.broadcast_to(idx, idx.shape[:-1] + (kv_latent.shape[-1],)),
|
| 243 |
+
axis=2,
|
| 244 |
+
)
|
| 245 |
+
k_pe = mx.take_along_axis(
|
| 246 |
+
k_pe,
|
| 247 |
+
mx.broadcast_to(idx, idx.shape[:-1] + (k_pe.shape[-1],)),
|
| 248 |
+
axis=2,
|
| 249 |
+
)
|
| 250 |
+
if mask is not None:
|
| 251 |
+
mask = mx.take_along_axis(mask, topk_indices, axis=-1)
|
| 252 |
+
else:
|
| 253 |
+
shape = list(topk_indices.shape)
|
| 254 |
+
shape[-1] = kv_latent.shape[2]
|
| 255 |
+
sparse_mask = mx.zeros(shape, dtype=mx.bool_)
|
| 256 |
+
sparse_mask = mx.put_along_axis(
|
| 257 |
+
sparse_mask, topk_indices, mx.array(True), axis=-1
|
| 258 |
+
)
|
| 259 |
+
if mask is not None:
|
| 260 |
+
sparse_mask = sparse_mask & mask
|
| 261 |
+
mask = sparse_mask
|
| 262 |
+
# Ensure the indexer cache is evaluated even if the topk_indices are unused
|
| 263 |
+
# to keep the graph from getting too large
|
| 264 |
+
if self.indexer is not None and cache is not None and cache[0] is not None:
|
| 265 |
+
cache[0].keys = mx.depends(cache[0].keys, (cache[1].keys, cache[1].values))
|
| 266 |
+
|
| 267 |
+
pe_scores = (q_pe * self.scale) @ k_pe.swapaxes(-1, -2)
|
| 268 |
+
if mask is not None:
|
| 269 |
+
pe_scores = mx.where(
|
| 270 |
+
mask,
|
| 271 |
+
pe_scores,
|
| 272 |
+
mx.array(mx.finfo(pe_scores.dtype).min, pe_scores.dtype),
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
if L == 1:
|
| 276 |
+
q_nope = self.embed_q(q_nope)
|
| 277 |
+
k = v = kv_latent
|
| 278 |
+
else:
|
| 279 |
+
k = self.embed_q(kv_latent, transpose=False)
|
| 280 |
+
v = self.unembed_out(kv_latent)
|
| 281 |
+
|
| 282 |
+
output = scaled_dot_product_attention(
|
| 283 |
+
q_nope, k, v, cache=cache, scale=self.scale, mask=pe_scores
|
| 284 |
+
)
|
| 285 |
+
if L == 1:
|
| 286 |
+
output = self.unembed_out(output)
|
| 287 |
+
|
| 288 |
+
output = output.transpose(0, 2, 1, 3).reshape(B, L, -1)
|
| 289 |
+
return self.o_proj(output), topk_indices
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
class DeepseekV32MLP(nn.Module):
|
| 293 |
+
def __init__(
|
| 294 |
+
self, config: ModelArgs, hidden_size: int = None, intermediate_size: int = None
|
| 295 |
+
):
|
| 296 |
+
super().__init__()
|
| 297 |
+
self.config = config
|
| 298 |
+
self.hidden_size = config.hidden_size if hidden_size is None else hidden_size
|
| 299 |
+
self.intermediate_size = (
|
| 300 |
+
config.intermediate_size if intermediate_size is None else intermediate_size
|
| 301 |
+
)
|
| 302 |
+
|
| 303 |
+
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 304 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 305 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 306 |
+
|
| 307 |
+
def __call__(self, x):
|
| 308 |
+
down_proj = self.down_proj(swiglu(self.gate_proj(x), self.up_proj(x)))
|
| 309 |
+
return down_proj
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
@mx.compile
|
| 313 |
+
def group_expert_select(
|
| 314 |
+
gates,
|
| 315 |
+
e_score_correction_bias,
|
| 316 |
+
top_k,
|
| 317 |
+
n_group,
|
| 318 |
+
topk_group,
|
| 319 |
+
routed_scaling_factor,
|
| 320 |
+
norm_topk_prob,
|
| 321 |
+
):
|
| 322 |
+
|
| 323 |
+
scores = mx.sigmoid(gates.astype(mx.float32))
|
| 324 |
+
orig_scores = scores
|
| 325 |
+
scores = scores + e_score_correction_bias
|
| 326 |
+
if n_group > 1:
|
| 327 |
+
scores = mx.unflatten(scores, axis=-1, shape=(n_group, -1))
|
| 328 |
+
group_scores = mx.topk(scores, 2, axis=-1).sum(axis=-1, keepdims=True)
|
| 329 |
+
k = n_group - topk_group
|
| 330 |
+
group_idx = mx.argpartition(group_scores, kth=k - 1, axis=-2)[..., :k, :]
|
| 331 |
+
scores = mx.put_along_axis(
|
| 332 |
+
scores, mx.stop_gradient(group_idx), mx.array(0.0), axis=-2
|
| 333 |
+
)
|
| 334 |
+
scores = mx.flatten(scores, -2, -1)
|
| 335 |
+
|
| 336 |
+
k = top_k
|
| 337 |
+
inds = mx.argpartition(-scores, kth=k - 1, axis=-1)[..., :k]
|
| 338 |
+
scores = mx.take_along_axis(orig_scores, inds, axis=-1)
|
| 339 |
+
if top_k > 1 and norm_topk_prob:
|
| 340 |
+
denominator = scores.sum(axis=-1, keepdims=True)
|
| 341 |
+
scores = scores / denominator
|
| 342 |
+
scores = scores * routed_scaling_factor
|
| 343 |
+
|
| 344 |
+
return inds, scores
|
| 345 |
+
|
| 346 |
+
|
| 347 |
+
class MoEGate(nn.Module):
|
| 348 |
+
def __init__(self, config: ModelArgs):
|
| 349 |
+
super().__init__()
|
| 350 |
+
self.config = config
|
| 351 |
+
self.top_k = config.num_experts_per_tok
|
| 352 |
+
self.norm_topk_prob = config.norm_topk_prob
|
| 353 |
+
self.n_routed_experts = config.n_routed_experts
|
| 354 |
+
self.routed_scaling_factor = config.routed_scaling_factor
|
| 355 |
+
self.n_group = config.n_group
|
| 356 |
+
self.topk_group = config.topk_group
|
| 357 |
+
self.weight = mx.zeros((self.n_routed_experts, config.hidden_size))
|
| 358 |
+
self.e_score_correction_bias = mx.zeros((self.n_routed_experts,))
|
| 359 |
+
assert config.topk_method == "noaux_tc", "Unsupported topk method."
|
| 360 |
+
|
| 361 |
+
def __call__(self, x):
|
| 362 |
+
return group_expert_select(
|
| 363 |
+
x.astype(mx.float32) @ self.weight.astype(mx.float32).T,
|
| 364 |
+
self.e_score_correction_bias,
|
| 365 |
+
self.top_k,
|
| 366 |
+
self.n_group,
|
| 367 |
+
self.topk_group,
|
| 368 |
+
self.routed_scaling_factor,
|
| 369 |
+
self.norm_topk_prob,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
class DeepseekV32MoE(nn.Module):
|
| 374 |
+
def __init__(self, config: ModelArgs):
|
| 375 |
+
super().__init__()
|
| 376 |
+
self.config = config
|
| 377 |
+
self.num_experts_per_tok = config.num_experts_per_tok
|
| 378 |
+
self.switch_mlp = SwitchGLU(
|
| 379 |
+
config.hidden_size,
|
| 380 |
+
config.moe_intermediate_size,
|
| 381 |
+
config.n_routed_experts,
|
| 382 |
+
)
|
| 383 |
+
|
| 384 |
+
self.gate = MoEGate(config)
|
| 385 |
+
if config.n_shared_experts is not None:
|
| 386 |
+
intermediate_size = config.moe_intermediate_size * config.n_shared_experts
|
| 387 |
+
self.shared_experts = DeepseekV32MLP(
|
| 388 |
+
config=config, intermediate_size=intermediate_size
|
| 389 |
+
)
|
| 390 |
+
|
| 391 |
+
self.sharding_group = None
|
| 392 |
+
|
| 393 |
+
def __call__(self, x):
|
| 394 |
+
if self.sharding_group is not None:
|
| 395 |
+
x = sum_gradients(self.sharding_group)(x)
|
| 396 |
+
|
| 397 |
+
inds, scores = self.gate(x)
|
| 398 |
+
y = self.switch_mlp(x, inds)
|
| 399 |
+
y = (y * scores[..., None]).sum(axis=-2).astype(y.dtype)
|
| 400 |
+
if self.config.n_shared_experts is not None:
|
| 401 |
+
y = y + self.shared_experts(x)
|
| 402 |
+
|
| 403 |
+
if self.sharding_group is not None:
|
| 404 |
+
y = mx.distributed.all_sum(y, group=self.sharding_group)
|
| 405 |
+
|
| 406 |
+
return y
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
class DeepseekV32DecoderLayer(nn.Module):
|
| 410 |
+
def __init__(self, config: ModelArgs, layer_idx: int):
|
| 411 |
+
super().__init__()
|
| 412 |
+
self.self_attn = DeepseekV32Attention(config, layer_idx)
|
| 413 |
+
self.mlp = (
|
| 414 |
+
DeepseekV32MoE(config)
|
| 415 |
+
if (
|
| 416 |
+
config.n_routed_experts is not None
|
| 417 |
+
and layer_idx >= config.first_k_dense_replace
|
| 418 |
+
and layer_idx % config.moe_layer_freq == 0
|
| 419 |
+
)
|
| 420 |
+
else DeepseekV32MLP(config)
|
| 421 |
+
)
|
| 422 |
+
self.input_layernorm = nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 423 |
+
self.post_attention_layernorm = nn.RMSNorm(
|
| 424 |
+
config.hidden_size, eps=config.rms_norm_eps
|
| 425 |
+
)
|
| 426 |
+
|
| 427 |
+
def __call__(
|
| 428 |
+
self,
|
| 429 |
+
x: mx.array,
|
| 430 |
+
mask: Optional[mx.array] = None,
|
| 431 |
+
cache: Optional[Any] = None,
|
| 432 |
+
prev_topk_indices: Optional[mx.array] = None,
|
| 433 |
+
):
|
| 434 |
+
r, topk_indices = self.self_attn(self.input_layernorm(x), mask, cache, prev_topk_indices)
|
| 435 |
+
h = x + r
|
| 436 |
+
r = self.mlp(self.post_attention_layernorm(h))
|
| 437 |
+
return h + r, topk_indices
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
class DeepseekV32Model(nn.Module):
|
| 441 |
+
def __init__(self, config: ModelArgs):
|
| 442 |
+
super().__init__()
|
| 443 |
+
self.vocab_size = config.vocab_size
|
| 444 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
|
| 445 |
+
self.layers = [
|
| 446 |
+
DeepseekV32DecoderLayer(config, idx)
|
| 447 |
+
for idx in range(config.num_hidden_layers)
|
| 448 |
+
]
|
| 449 |
+
self.start_idx = 0
|
| 450 |
+
self.end_idx = len(self.layers)
|
| 451 |
+
self.num_layers = self.end_idx
|
| 452 |
+
|
| 453 |
+
self.norm = nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 454 |
+
self.pipeline_rank = 0
|
| 455 |
+
self.pipeline_size = 1
|
| 456 |
+
|
| 457 |
+
def pipeline(self, group):
|
| 458 |
+
# Split layers in reverse so rank=0 gets the last layers and
|
| 459 |
+
# rank=pipeline_size-1 gets the first
|
| 460 |
+
self.pipeline_rank = group.rank()
|
| 461 |
+
self.pipeline_size = group.size()
|
| 462 |
+
layers_per_rank = len(self.layers) // self.pipeline_size
|
| 463 |
+
extra = len(self.layers) - layers_per_rank * self.pipeline_size
|
| 464 |
+
if self.pipeline_rank < extra:
|
| 465 |
+
layers_per_rank += 1
|
| 466 |
+
self.start_idx = (self.pipeline_size - self.pipeline_rank - 1) * layers_per_rank
|
| 467 |
+
self.end_idx = self.start_idx + layers_per_rank
|
| 468 |
+
self.layers = self.layers[: self.end_idx]
|
| 469 |
+
self.layers[: self.start_idx] = [None] * self.start_idx
|
| 470 |
+
self.num_layers = len(self.layers) - self.start_idx
|
| 471 |
+
|
| 472 |
+
def __call__(
|
| 473 |
+
self,
|
| 474 |
+
x: mx.array,
|
| 475 |
+
cache: Optional[Any] = None,
|
| 476 |
+
) -> mx.array:
|
| 477 |
+
h = self.embed_tokens(x)
|
| 478 |
+
|
| 479 |
+
pipeline_rank = self.pipeline_rank
|
| 480 |
+
pipeline_size = self.pipeline_size
|
| 481 |
+
|
| 482 |
+
if cache is None:
|
| 483 |
+
cache = [None] * self.num_layers
|
| 484 |
+
mask = create_attention_mask(
|
| 485 |
+
h, cache[0][0] if cache[0] else None, return_array=True
|
| 486 |
+
)
|
| 487 |
+
|
| 488 |
+
# Receive from the previous process in the pipeline
|
| 489 |
+
|
| 490 |
+
if pipeline_rank < pipeline_size - 1:
|
| 491 |
+
h = mx.distributed.recv_like(h, (pipeline_rank + 1))
|
| 492 |
+
|
| 493 |
+
# A "shared" layer reuses the top-k selection of the most recent "full" layer.
|
| 494 |
+
topk = None
|
| 495 |
+
for i in range(self.num_layers):
|
| 496 |
+
h, topk = self.layers[self.start_idx + i](h, mask, cache[i], topk)
|
| 497 |
+
|
| 498 |
+
# Send to the next process in the pipeline
|
| 499 |
+
if pipeline_rank != 0:
|
| 500 |
+
h = mx.distributed.send(h, (pipeline_rank - 1) % pipeline_size)
|
| 501 |
+
if cache[-1] is not None:
|
| 502 |
+
cache[-1][0].keys = mx.depends(cache[-1][0].keys, h)
|
| 503 |
+
|
| 504 |
+
# Broadcast h while keeping it in the graph
|
| 505 |
+
if pipeline_size > 1:
|
| 506 |
+
h = mx.distributed.all_gather(h)[: h.shape[0]]
|
| 507 |
+
|
| 508 |
+
return self.norm(h)
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
class Model(nn.Module):
|
| 512 |
+
def __init__(self, config: ModelArgs):
|
| 513 |
+
super().__init__()
|
| 514 |
+
self.args = config
|
| 515 |
+
self.model_type = config.model_type
|
| 516 |
+
self.model = DeepseekV32Model(config)
|
| 517 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 518 |
+
|
| 519 |
+
def __call__(
|
| 520 |
+
self,
|
| 521 |
+
inputs: mx.array,
|
| 522 |
+
cache: Optional[Any] = None,
|
| 523 |
+
):
|
| 524 |
+
out = self.model(inputs, cache)
|
| 525 |
+
return self.lm_head(out)
|
| 526 |
+
|
| 527 |
+
def sanitize(self, weights):
|
| 528 |
+
# Remove multi-token prediction layers
|
| 529 |
+
mpt_layer = self.args.num_hidden_layers
|
| 530 |
+
new_weights = {}
|
| 531 |
+
for k, v in weights.items():
|
| 532 |
+
parts = k.split(".")
|
| 533 |
+
if len(parts) >= 3 and parts[1] == "layers" and int(parts[2]) >= mpt_layer:
|
| 534 |
+
continue
|
| 535 |
+
new_weights[k] = v
|
| 536 |
+
weights = new_weights
|
| 537 |
+
|
| 538 |
+
def dequant(weight, scale_inv):
|
| 539 |
+
dtype = mx.bfloat16
|
| 540 |
+
weight = mx.from_fp8(weight, dtype=mx.bfloat16)
|
| 541 |
+
bs = 128 # block size
|
| 542 |
+
m, n = weight.shape
|
| 543 |
+
pad_bottom = (-m) % bs
|
| 544 |
+
pad_side = (-n) % bs
|
| 545 |
+
weight = mx.pad(weight, ((0, pad_bottom), (0, pad_side)))
|
| 546 |
+
weight = weight.reshape(
|
| 547 |
+
((m + pad_bottom) // bs, bs, (n + pad_side) // bs, bs)
|
| 548 |
+
)
|
| 549 |
+
weight = (weight * scale_inv[:, None, :, None]).reshape(
|
| 550 |
+
m + pad_bottom, n + pad_side
|
| 551 |
+
)
|
| 552 |
+
return weight[:m, :n].astype(dtype)
|
| 553 |
+
|
| 554 |
+
# Dequantize
|
| 555 |
+
new_weights = {}
|
| 556 |
+
for k, v in weights.items():
|
| 557 |
+
if "weight_scale_inv" in k:
|
| 558 |
+
scale_inv = v
|
| 559 |
+
wk = k.replace("_scale_inv", "")
|
| 560 |
+
weight = weights[wk]
|
| 561 |
+
weight = dequant(weight, scale_inv)
|
| 562 |
+
new_weights[wk] = weight
|
| 563 |
+
elif k not in new_weights:
|
| 564 |
+
new_weights[k] = v
|
| 565 |
+
weights = new_weights
|
| 566 |
+
|
| 567 |
+
# Stack experts
|
| 568 |
+
for l in range(self.args.num_hidden_layers):
|
| 569 |
+
prefix = f"model.layers.{l}"
|
| 570 |
+
for n, m in [("w1", "gate_proj"), ("w2", "down_proj"), ("w3", "up_proj")]:
|
| 571 |
+
for k in ["weight", "scales", "biases"]:
|
| 572 |
+
if f"{prefix}.mlp.experts.0.{m}.{k}" in weights:
|
| 573 |
+
to_join = [
|
| 574 |
+
weights.pop(f"{prefix}.mlp.experts.{e}.{m}.{k}")
|
| 575 |
+
for e in range(self.args.n_routed_experts)
|
| 576 |
+
]
|
| 577 |
+
weights[f"{prefix}.mlp.switch_mlp.{m}.{k}"] = mx.stack(to_join)
|
| 578 |
+
prefix = f"model.layers.{l}.self_attn"
|
| 579 |
+
if f"{prefix}.kv_b_proj.weight" in weights:
|
| 580 |
+
layer = self.model.layers[l].self_attn.embed_q
|
| 581 |
+
quantized = f"{prefix}.kv_b_proj.scales" in weights
|
| 582 |
+
v = weights.pop(f"{prefix}.kv_b_proj.weight")
|
| 583 |
+
head_dim = self.args.qk_nope_head_dim + self.args.v_head_dim
|
| 584 |
+
|
| 585 |
+
if quantized:
|
| 586 |
+
dims = self.args.kv_lora_rank
|
| 587 |
+
scales = weights.pop(f"{prefix}.kv_b_proj.scales")
|
| 588 |
+
biases = weights.pop(f"{prefix}.kv_b_proj.biases")
|
| 589 |
+
# Try to infer bits and group size
|
| 590 |
+
bits = (v.shape[-1] * 32) // dims
|
| 591 |
+
group_size = dims // scales.shape[-1]
|
| 592 |
+
v = mx.dequantize(
|
| 593 |
+
v, scales, biases, bits=bits, group_size=group_size
|
| 594 |
+
)
|
| 595 |
+
num_heads = self.args.num_attention_heads
|
| 596 |
+
v = v.reshape(num_heads, head_dim, -1)
|
| 597 |
+
wk = mx.contiguous(
|
| 598 |
+
v[:, : self.args.qk_nope_head_dim, :].swapaxes(-1, -2)
|
| 599 |
+
)
|
| 600 |
+
wv = mx.contiguous(v[:, self.args.qk_nope_head_dim :, :])
|
| 601 |
+
if quantized:
|
| 602 |
+
wk, wk_scales, wk_biases = mx.quantize(
|
| 603 |
+
wk, bits=bits, group_size=group_size
|
| 604 |
+
)
|
| 605 |
+
wv, wv_scales, wv_biases = mx.quantize(
|
| 606 |
+
wv, bits=bits, group_size=group_size
|
| 607 |
+
)
|
| 608 |
+
weights[f"{prefix}.embed_q.scales"] = wk_scales
|
| 609 |
+
weights[f"{prefix}.unembed_out.scales"] = wv_scales
|
| 610 |
+
weights[f"{prefix}.embed_q.biases"] = wk_biases
|
| 611 |
+
weights[f"{prefix}.unembed_out.biases"] = wv_biases
|
| 612 |
+
weights[f"{prefix}.embed_q.weight"] = wk
|
| 613 |
+
weights[f"{prefix}.unembed_out.weight"] = wv
|
| 614 |
+
|
| 615 |
+
return weights
|
| 616 |
+
|
| 617 |
+
def shard(self, group: Optional[mx.distributed.Group] = None):
|
| 618 |
+
group = group or mx.distributed.init()
|
| 619 |
+
N = group.size()
|
| 620 |
+
rank = group.rank()
|
| 621 |
+
for layer in self.model.layers:
|
| 622 |
+
layer.self_attn.q_b_proj = shard_linear(
|
| 623 |
+
layer.self_attn.q_b_proj, "all-to-sharded", group=group
|
| 624 |
+
)
|
| 625 |
+
|
| 626 |
+
layer.self_attn.o_proj = shard_linear(
|
| 627 |
+
layer.self_attn.o_proj, "sharded-to-all", group=group
|
| 628 |
+
)
|
| 629 |
+
layer.self_attn.num_heads //= N
|
| 630 |
+
num_heads = layer.self_attn.num_heads
|
| 631 |
+
sh = rank * num_heads
|
| 632 |
+
eh = sh + num_heads
|
| 633 |
+
|
| 634 |
+
def shard_heads(w):
|
| 635 |
+
return w[sh:eh]
|
| 636 |
+
|
| 637 |
+
layer.self_attn.embed_q.apply(shard_heads)
|
| 638 |
+
layer.self_attn.unembed_out.apply(shard_heads)
|
| 639 |
+
|
| 640 |
+
# Shard the MLP
|
| 641 |
+
if isinstance(layer.mlp, DeepseekV32MLP):
|
| 642 |
+
layer.mlp.gate_proj = shard_linear(
|
| 643 |
+
layer.mlp.gate_proj, "all-to-sharded", group=group
|
| 644 |
+
)
|
| 645 |
+
layer.mlp.down_proj = shard_linear(
|
| 646 |
+
layer.mlp.down_proj, "sharded-to-all", group=group
|
| 647 |
+
)
|
| 648 |
+
layer.mlp.up_proj = shard_linear(
|
| 649 |
+
layer.mlp.up_proj, "all-to-sharded", group=group
|
| 650 |
+
)
|
| 651 |
+
|
| 652 |
+
# Shard the MoE. Shard in place since the MoE should be responsible
|
| 653 |
+
# for aggregating the results.
|
| 654 |
+
else:
|
| 655 |
+
layer.mlp.sharding_group = group = group
|
| 656 |
+
shard_inplace(
|
| 657 |
+
layer.mlp.shared_experts.gate_proj, "all-to-sharded", group=group
|
| 658 |
+
)
|
| 659 |
+
shard_inplace(
|
| 660 |
+
layer.mlp.shared_experts.down_proj, "sharded-to-all", group=group
|
| 661 |
+
)
|
| 662 |
+
shard_inplace(
|
| 663 |
+
layer.mlp.shared_experts.up_proj, "all-to-sharded", group=group
|
| 664 |
+
)
|
| 665 |
+
shard_inplace(
|
| 666 |
+
layer.mlp.switch_mlp.gate_proj, "all-to-sharded", group=group
|
| 667 |
+
)
|
| 668 |
+
shard_inplace(
|
| 669 |
+
layer.mlp.switch_mlp.down_proj, "sharded-to-all", group=group
|
| 670 |
+
)
|
| 671 |
+
shard_inplace(
|
| 672 |
+
layer.mlp.switch_mlp.up_proj, "all-to-sharded", group=group
|
| 673 |
+
)
|
| 674 |
+
|
| 675 |
+
@property
|
| 676 |
+
def layers(self):
|
| 677 |
+
return self.model.layers[self.model.start_idx : self.model.end_idx]
|
| 678 |
+
|
| 679 |
+
@property
|
| 680 |
+
def cast_predicate(self):
|
| 681 |
+
def predicate(k):
|
| 682 |
+
return "e_score_correction_bias" not in k
|
| 683 |
+
|
| 684 |
+
return predicate
|
| 685 |
+
|
| 686 |
+
@property
|
| 687 |
+
def quant_predicate(self):
|
| 688 |
+
def predicate(path, module):
|
| 689 |
+
# The lightning indexer (0.03% of parameters, reference keeps weights_proj in fp32) and the
|
| 690 |
+
# MoE router decide *what* is computed; keep them as stored.
|
| 691 |
+
if ".indexer." in path or path.endswith("mlp.gate"):
|
| 692 |
+
return False
|
| 693 |
+
return True
|
| 694 |
+
|
| 695 |
+
return predicate
|
| 696 |
+
|
| 697 |
+
def make_cache(self):
|
| 698 |
+
# Shared layers have no indexer, so no indexer key cache: an empty second KVCache would
|
| 699 |
+
# trip mlx-lm's `cache.state` evaluation (keys is None) during generation.
|
| 700 |
+
return [
|
| 701 |
+
CacheList(KVCache(), KVCache()) if layer.self_attn.indexer is not None else CacheList(KVCache())
|
| 702 |
+
for layer in self.layers
|
| 703 |
+
]
|
model-00001.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f120d730030ee9719453bcb4e7e00d7ae43ebbb087f665f65473a82983a3d339
|
| 3 |
+
size 1308439222
|
model-00002.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:05bfe8555f1a07eaeff47171c0a790d5b8397c7a0c5bcdf5b5f18ff4e4d13a9c
|
| 3 |
+
size 287942178
|
model-00003.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:94ab4b4b4717f03d10631245933289b918e326e68c4c05a6551fc8e00ae3bc45
|
| 3 |
+
size 287942182
|
model-00004.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:757fc827480b9639d2652a386f961af2e1c52159a2555b562a964714194335c9
|
| 3 |
+
size 287942208
|
model-00005.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9a42247e35c6e710f11eda7fc9a27a7f34a262e9242db84f3ee7cbdde1b7edc4
|
| 3 |
+
size 6786362373
|
model-00006.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:984e842656dad4ba94c2f6f32bb18912141081b67180b8da40c23f34661863f3
|
| 3 |
+
size 6786362353
|
model-00007.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7260c6809d047afadf472392a5e6c0abb08056d7795196d737e0dc11790f58c9
|
| 3 |
+
size 6786362369
|
model-00008.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c60f60d46dbe7ef167fc6f6d5068b87deecfc694293c88595d3ba24fb291a5e7
|
| 3 |
+
size 6805106777
|
model-00009.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d1604b3b7ea8b969df66b88ed9966d42f5bb8cd3f0dd95c1672865ae892c4ad7
|
| 3 |
+
size 6786362379
|
model-00010.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9f4c3c3860689cfc255b5b8d7a5e3c47fdce04fad25cb446858a6cf0c94058dd
|
| 3 |
+
size 6786362331
|
model-00011.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:812f7b222632f321ce50c8ee025dd4c08bfd57a53d5b8ec4dc398f2bd9ff0673
|
| 3 |
+
size 6786362365
|
model-00012.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7786afa99229f0f00bb0b958fce3fb93f6e9a6c9c2adb492d70a1e5293b7e295
|
| 3 |
+
size 6805106824
|
model-00013.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:568e8861701be1afdfe2c126d11ce2fdfc85ff67088fb617686d25198ab88605
|
| 3 |
+
size 6786362419
|
model-00014.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0e84314f6a07e84260aff2ffdfdca68b5923a3c376621aa66c193e18fc0c6283
|
| 3 |
+
size 6786362363
|
model-00015.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e91f96d816ac14a6d450d4a54f0ec22ceb28f382ef503e5b3002351daff632b5
|
| 3 |
+
size 6786362423
|
model-00016.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb6e19c47535bd3c30465be4553c952b7c0b92d44982fd0d371190ee6d84447f
|
| 3 |
+
size 6805106830
|
model-00017.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e9a6a5864b89043de023a8731049fd9d630a583f615d5f073d118e62d8c24ff2
|
| 3 |
+
size 6786362409
|
model-00018.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:68bbdf429c6349ced587e648bb946a3caa3fe0931a22a1851c04ff0f46b00b3d
|
| 3 |
+
size 6786362417
|
model-00019.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e49ef00333f898f77afd1da05268b48a846012eb06b9ea80b253169352e93a64
|
| 3 |
+
size 6786362393
|
model-00020.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9ff6207e305b25a7c6899845c0e28440cb71af8e60fcc93d4bbec67b225f4695
|
| 3 |
+
size 6805106844
|
model-00021.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6776af31ccd797fea9a95d1cb785435aba6e2be7f47fc4eadefda57913f53af4
|
| 3 |
+
size 6786362417
|
model-00022.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:16697c87789a03d15b6aa21d1eef52131359aeccc98044c780d6adad52662784
|
| 3 |
+
size 6786362423
|
model-00023.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6833ecbb32a896f3017784cfa3968b0bfda667d502c656a23f98dd005f9c0036
|
| 3 |
+
size 6786362405
|
model-00024.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:74fdb1055a896d9d8c0cd118ab327dd651cf82e8190ce868b75bb10101713a59
|
| 3 |
+
size 6805106842
|
model-00025.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cc2976c96bcae3b3c6c1a98a80eed639dae94824ff8b6194ad4b6cdfad9781fc
|
| 3 |
+
size 6786362417
|
model-00026.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a4dd6caaaf94c9d23d9d9aa3a15b2ede6b4938229e97f906996eda9f876b6b0e
|
| 3 |
+
size 6786362427
|
model-00027.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6358f9cd8be030d35f659f9c966ebac7fb1661c506a606809bceea00de4f111b
|
| 3 |
+
size 6786362419
|
model-00028.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:771b0995bcdbe18ac122ae376b78d80aa03b3a0716ea2e73cf6f96e9e1ee77a6
|
| 3 |
+
size 6805106838
|
model-00029.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8813fd889066cf6814e713b44969e5ca64fe17c00f30af1b0daf4bc2a7e36c0e
|
| 3 |
+
size 6786362405
|
model-00030.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:27c07fa2b01401b9769ee7a418ad88fee184ea82186e68bab01a880222b77ac9
|
| 3 |
+
size 6786362413
|
model-00031.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d748b8fdb742677f730465e13bdad9459a7c826818b2ca5a540a5a1ac6da478f
|
| 3 |
+
size 6786362405
|
model-00032.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5b69ed5b8f54b481da0cf0dd97ffce6028f1f955804a2a812c15bb4a608f5e9e
|
| 3 |
+
size 6805106830
|
model-00033.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ac056c2ea58bfedf52a4ddd2fd54e74d7e5b59c53e3c47a2388252dda9c05152
|
| 3 |
+
size 6786362417
|
model-00034.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:df2c162dfcf436cf18f91b2d8a5bd3ae35a89edb1ca17e44567873dbd4d6184b
|
| 3 |
+
size 6786362423
|
model-00035.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:82dd7b52dea809af0cf454e6b90fe9b2656baca18fcfe3a23f2eb81120029c4c
|
| 3 |
+
size 6786362421
|
model-00036.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c757eb8c925fa1f00a119bff0b638b48dc26951b0ae74cbec80b83789fb38510
|
| 3 |
+
size 6805106828
|
model-00037.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:04f78a9ec6a8b5532c8382dd73da9e648be784c8c9bd7e3df7cb4f5d54518293
|
| 3 |
+
size 6786362411
|
model-00038.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6269299dd2925f797c522f2de6893d8766ab970163f7292f6c567bd40214f5ac
|
| 3 |
+
size 6786362403
|
model-00039.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:079a1e224b57d6649c711d180a127d64cc530042a04c7aab4a9241ad182abe13
|
| 3 |
+
size 6786362407
|
model-00040.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:41fe314605e4e8f60cf8f98d0e57485a1a5b2083fd33e5624efc02d1402020f8
|
| 3 |
+
size 6805106830
|
model-00041.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bc50020a9a0d150beb97c96cf340b3a9754e68183f456c4a18e636b44c2eaa9b
|
| 3 |
+
size 6786362429
|
model-00042.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:376c840fcee97c47a900fb3d72de01c93d66f22ff91b456ea99658e0eb9aefce
|
| 3 |
+
size 6786362415
|