ajh-code commited on
Commit
16f5171
·
verified ·
1 Parent(s): af92d5e

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. .dockerignore +8 -0
  2. .gitattributes +4 -34
  3. .gitignore +5 -0
  4. .source +4 -0
  5. Dockerfile +61 -0
  6. LICENSE.md +94 -0
  7. MANIFEST.json +1134 -0
  8. Notice +20 -0
  9. README.md +273 -0
  10. THIRD_PARTY_NOTICES.md +28 -0
  11. activation-scaling-report.json +0 -0
  12. chat_template.jinja +85 -0
  13. client.py +102 -0
  14. compose.yaml +24 -0
  15. config.json +80 -0
  16. install.sh +66 -0
  17. launch.sh +40 -0
  18. model.safetensors.index.json +605 -0
  19. quantization.json +2197 -0
  20. requirements.txt +5 -0
  21. runtime/experimental/fp8/__init__.py +11 -0
  22. runtime/experimental/fp8/modules.py +307 -0
  23. runtime/experimental/fp8/server.py +109 -0
  24. runtime/experimental/nvfp4/__init__.py +32 -0
  25. runtime/experimental/nvfp4/checkpoint.py +203 -0
  26. runtime/experimental/nvfp4/modules.py +1761 -0
  27. runtime/experimental/nvfp4/server.py +113 -0
  28. runtime/native/direct_w4a4_m1/direct_w4a4_m1.cu +152 -0
  29. runtime/native/direct_w4a4_m1/direct_w4a4_m1.h +14 -0
  30. runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cpp +97 -0
  31. runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cu +276 -0
  32. runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.h +20 -0
  33. runtime/server.py +145 -0
  34. runtime/torch-overrides.txt +7 -0
  35. special_tokens_map.json +0 -0
  36. tokenizer_config.json +0 -0
  37. validate_release.py +293 -0
  38. vendor/fish-speech/.gitignore +114 -0
  39. vendor/fish-speech/.project-root +0 -0
  40. vendor/fish-speech/.readthedocs.yaml +19 -0
  41. vendor/fish-speech/API_FLAGS.txt +6 -0
  42. vendor/fish-speech/README.md +197 -0
  43. vendor/fish-speech/compose.base.yml +25 -0
  44. vendor/fish-speech/compose.rocm.yml +58 -0
  45. vendor/fish-speech/compose.yml +26 -0
  46. vendor/fish-speech/dockerfile.dev +37 -0
  47. vendor/fish-speech/entrypoint.sh +10 -0
  48. vendor/fish-speech/inference.ipynb +214 -0
  49. vendor/fish-speech/mkdocs.yml +155 -0
  50. vendor/fish-speech/pyrightconfig.json +6 -0
.dockerignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ .build
2
+ .git
3
+ .venv
4
+ runtime-data
5
+ model-*.safetensors
6
+ codec.pth
7
+ activation-scaling-report.json
8
+ tokenizer.json
.gitattributes CHANGED
@@ -1,35 +1,5 @@
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  *.safetensors filter=lfs diff=lfs merge=lfs -text
2
+ *.pth filter=lfs diff=lfs merge=lfs -text
3
+ *.wav filter=lfs diff=lfs merge=lfs -text
4
+ *.flac filter=lfs diff=lfs merge=lfs -text
5
+ *.mp3 filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ /.build/
2
+ /.venv/
3
+ /runtime-data/*
4
+ !/runtime-data/references/
5
+ !/runtime-data/references/.gitkeep
.source ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ base_model=fishaudio/s2-pro@1de9996b6be38b745688de084d87a5633f714e4e
2
+ fish_speech=e5e292632cb11e7a27b2b7487f58f612bc101e13
3
+ fish_scales_ops=a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded
4
+ nvfp4_native_source=7a03467b90d6feff6bd196928dfe156bd173f36e
Dockerfile ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1.7
2
+
3
+ ARG CUDA_IMAGE=nvidia/cuda:13.0.2-cudnn-devel-ubuntu24.04
4
+ ARG UV_VERSION=0.12.3
5
+ FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv-bin
6
+ FROM ${CUDA_IMAGE}
7
+
8
+ ARG FISH_SCALES_REVISION=a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded
9
+ ENV DEBIAN_FRONTEND=noninteractive \
10
+ PYTHONDONTWRITEBYTECODE=1 \
11
+ PYTHONUNBUFFERED=1 \
12
+ VIRTUAL_ENV=/opt/venv \
13
+ PATH=/opt/venv/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
14
+ CUDA_HOME=/usr/local/cuda \
15
+ TORCH_CUDA_ARCH_LIST=12.0a \
16
+ FISH_NVFP4_ROOT=/model \
17
+ FISH_NVFP4_BUILD_ROOT=/data/torch-extensions \
18
+ PYTHONPATH=/model/runtime \
19
+ TTS_PYTHON=/opt/venv/bin/python \
20
+ TEMPORARILY_DISABLE_PROTOBUF_VERSION_CHECK=true
21
+
22
+ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
23
+ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
24
+ apt-get update && apt-get install -y --no-install-recommends \
25
+ build-essential ca-certificates cmake ffmpeg git git-lfs libsndfile1 \
26
+ ninja-build portaudio19-dev python3.12 python3.12-dev python3.12-venv && \
27
+ git lfs install --system
28
+
29
+ COPY --from=uv-bin /uv /uvx /usr/local/bin/
30
+ COPY runtime/torch-overrides.txt /opt/release/torch-overrides.txt
31
+ COPY requirements.txt /opt/release/requirements.txt
32
+ COPY vendor/fish-speech /opt/fish-speech
33
+
34
+ RUN uv venv /opt/venv --python python3.12 && \
35
+ uv pip install --python /opt/venv/bin/python \
36
+ "setuptools>=75" wheel ninja packaging \
37
+ "torch==2.11.0" "torchaudio==2.11.0" --torch-backend=cu130 && \
38
+ uv pip install --python /opt/venv/bin/python \
39
+ --overrides /opt/release/torch-overrides.txt --torch-backend=cu130 \
40
+ /opt/fish-speech -r /opt/release/requirements.txt
41
+
42
+ RUN git init /opt/fish-scales-ops && \
43
+ git -C /opt/fish-scales-ops remote add origin https://github.com/fishaudio/fish-scales-ops.git && \
44
+ git -C /opt/fish-scales-ops fetch --depth 1 origin "${FISH_SCALES_REVISION}" && \
45
+ git -C /opt/fish-scales-ops checkout --detach FETCH_HEAD && \
46
+ git -C /opt/fish-scales-ops submodule update --init --recursive --depth 1
47
+
48
+ RUN --mount=type=cache,target=/root/.cache/uv \
49
+ CUTLASS_DIR=/opt/fish-scales-ops/3rdparty/cutlass \
50
+ MAX_JOBS=2 TORCH_CUDA_ARCH_LIST=12.0a \
51
+ uv pip install --python /opt/venv/bin/python \
52
+ --no-build-isolation /opt/fish-scales-ops/python
53
+
54
+ RUN install -m 0644 /opt/fish-speech/.project-root \
55
+ /opt/venv/lib/python3.12/site-packages/.project-root && \
56
+ /opt/venv/bin/python -c \
57
+ "from pathlib import Path; import comfy_kitchen, fish_speech, torch, tools.server.model_manager; from fish_speech.models.dac.modded_dac import DAC; site_packages = Path('/opt/venv/lib/python3.12/site-packages'); assert (site_packages / 'fish_speech/configs/modded_dac_vq.yaml').is_file(); assert list((site_packages / 'fish_scales_ops').glob('_C*.so')); print(torch.__version__, torch.version.cuda)"
58
+
59
+ WORKDIR /data
60
+ EXPOSE 8080
61
+ ENTRYPOINT ["/bin/bash", "/model/launch.sh"]
LICENSE.md ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FISH AUDIO RESEARCH LICENSE AGREEMENT
2
+
3
+ **Last Updated: March 7, 2026**
4
+
5
+ ## I. INTRODUCTION
6
+
7
+ This Agreement applies to any individual person or entity ("You", "Your" or "Licensee") that uses or distributes any portion or element of the Fish Audio Materials or Derivative Works thereof for any Research, Non-Commercial, or Commercial purpose. Capitalized terms not otherwise defined herein are defined in Section V below.
8
+
9
+ This Agreement is intended to allow research and non-commercial uses of the Materials free of charge. Any Commercial use of the Materials requires a separate license from Fish Audio.
10
+
11
+ By clicking "I Accept" or by using, distributing, or accessing any portion or element of the Fish Audio Materials or Derivative Works, You agree that You have read, understood and are bound by the terms of this Agreement. If You are acting on behalf of a company, organization or other entity, then "You" includes you and that entity, and You agree that You: (i) are an authorized representative of such entity with the authority to bind such entity to this Agreement, and (ii) You agree to the terms of this Agreement on that entity's behalf.
12
+
13
+ ## II. RESEARCH & NON-COMMERCIAL USE LICENSE
14
+
15
+ Subject to the terms of this Agreement, Fish Audio grants You a non-exclusive, worldwide, non-transferable, non-sublicensable, revocable and royalty-free limited license under Fish Audio's intellectual property or other rights owned by Fish Audio embodied in the Fish Audio Materials to use, reproduce, distribute, and create Derivative Works of, and make modifications to, the Fish Audio Materials for any Research or Non-Commercial Purpose.
16
+
17
+ "Research Purpose" means academic or scientific advancement, and in each case, is not primarily intended for commercial advantage or monetary compensation to You or others.
18
+
19
+ "Non-Commercial Purpose" means any purpose other than a Research Purpose that is not primarily intended for commercial advantage or monetary compensation to You or others, such as personal use (i.e., hobbyist) or evaluation and testing.
20
+
21
+ ## III. COMMERCIAL USE
22
+
23
+ **Any use of the Fish Audio Materials or Derivative Works for a Commercial Purpose requires a separate written license agreement from Fish Audio.** No commercial rights are granted under this Agreement.
24
+
25
+ "Commercial Purpose" means any purpose other than a Research Purpose or Non-Commercial Purpose that is primarily intended for or directed toward commercial advantage or monetary compensation to You or others, including but not limited to: (i) creating, modifying, or distributing Your product or service, including via a hosted service or application programming interface, (ii) Your business's or organization's internal operations, and (iii) any use in connection with a product or service for which You charge a fee or generate revenue, whether directly or indirectly.
26
+
27
+ To obtain a commercial license, please contact Fish Audio at:
28
+
29
+ - **Website:** [https://fish.audio](https://fish.audio)
30
+ - **Email:** business@fish.audio
31
+
32
+ ## IV. GENERAL TERMS
33
+
34
+ Your Research and Non-Commercial License under this Agreement is subject to the following terms.
35
+
36
+ ### a. Distribution & Attribution
37
+
38
+ If You distribute or make available the Fish Audio Materials or a Derivative Work to a third party, or a product or service that uses any portion of them, You shall: (i) provide a copy of this Agreement to that third party, (ii) retain the following attribution notice within a "Notice" text file distributed as a part of such copies: "This model is licensed under the Fish Audio Research License, Copyright © 39 AI, INC. All Rights Reserved.", and (iii) prominently display "Built with Fish Audio" on a related website, user interface, blogpost, about page, or product documentation.
39
+
40
+ If You create a Derivative Work, You may add your own attribution notice(s) to the "Notice" text file included with that Derivative Work, provided that You clearly indicate which attributions apply to the Fish Audio Materials and state in the "Notice" text file that You changed the Fish Audio Materials and how it was modified.
41
+
42
+ ### b. Use Restrictions
43
+
44
+ Your use of the Fish Audio Materials and Derivative Works, including any output or results of the Fish Audio Materials or Derivative Works, must comply with applicable laws and regulations (including Trade Control Laws and equivalent regulations) and adhere to Fish Audio's Acceptable Use Policy, which is hereby incorporated by reference.
45
+
46
+ Furthermore, You will not use the Fish Audio Materials or Derivative Works, or any output or results of the Fish Audio Materials or Derivative Works, to create or improve any foundational generative AI model (excluding the Models or Derivative Works).
47
+
48
+ ### c. Intellectual Property
49
+
50
+ **(i) Trademark License.** No trademark licenses are granted under this Agreement, and in connection with the Fish Audio Materials or Derivative Works, You may not use any name or mark owned by or associated with Fish Audio or any of its Affiliates, except as required under Section IV(a) herein.
51
+
52
+ **(ii) Ownership of Derivative Works.** As between You and Fish Audio, You are the owner of Derivative Works You create, subject to Fish Audio's ownership of the Fish Audio Materials and any Derivative Works made by or for Fish Audio.
53
+
54
+ **(iii) Ownership of Outputs.** As between You and Fish Audio, You own any outputs generated from the Models or Derivative Works to the extent permitted by applicable law.
55
+
56
+ **(iv) Disputes.** If You or Your Affiliate(s) institute litigation or other proceedings against Fish Audio (including a cross-claim or counterclaim in a lawsuit) alleging that the Fish Audio Materials, Derivative Works or associated outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by You, then any licenses granted to You under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Fish Audio from and against any claim by any third party arising out of or related to Your use or distribution of the Fish Audio Materials or Derivative Works in violation of this Agreement.
57
+
58
+ **(v) Feedback.** From time to time, You may provide Fish Audio with verbal and/or written suggestions, comments or other feedback related to Fish Audio's existing or prospective technology, products or services (collectively, "Feedback"). You are not obligated to provide Fish Audio with Feedback, but to the extent that You do, You hereby grant Fish Audio a perpetual, irrevocable, royalty-free, fully-paid, sub-licensable, transferable, non-exclusive, worldwide right and license to exploit the Feedback in any manner without restriction. Your Feedback is provided "AS IS" and You make no warranties whatsoever about any Feedback.
59
+
60
+ ### d. Disclaimer of Warranty
61
+
62
+ UNLESS REQUIRED BY APPLICABLE LAW, THE FISH AUDIO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OR LAWFULNESS OF USING OR REDISTRIBUTING THE FISH AUDIO MATERIALS, DERIVATIVE WORKS OR ANY OUTPUT OR RESULTS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE FISH AUDIO MATERIALS, DERIVATIVE WORKS AND ANY OUTPUT AND RESULTS.
63
+
64
+ ### e. Limitation of Liability
65
+
66
+ IN NO EVENT WILL FISH AUDIO OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF FISH AUDIO OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
67
+
68
+ ### f. Term and Termination
69
+
70
+ The term of this Agreement will commence upon Your acceptance of this Agreement or access to the Fish Audio Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Fish Audio may terminate this Agreement if You are in breach of any term or condition of this Agreement. Upon termination of this Agreement, You shall delete and cease use of any Fish Audio Materials or Derivative Works. Sections IV(d), (e), and (g) shall survive the termination of this Agreement.
71
+
72
+ ### g. Governing Law
73
+
74
+ This Agreement will be governed by and construed in accordance with the laws of the United States and the State of California without regard to choice of law principles, and the UN Convention on Contracts for International Sale of Goods does not apply to this Agreement.
75
+
76
+ ## V. DEFINITIONS
77
+
78
+ **"Affiliate(s)"** means any entity that directly or indirectly controls, is controlled by, or is under common control with the subject entity; for purposes of this definition, "control" means direct or indirect ownership or control of more than 50% of the voting interests of the subject entity.
79
+
80
+ **"Agreement"** means this Fish Audio Research License Agreement.
81
+
82
+ **"Derivative Work(s)"** means (a) any derivative work of the Fish Audio Materials as recognized by U.S. copyright laws and (b) any modifications to a Model, and any other model created which is based on or derived from the Model or the Model's output, including "fine tune" and "low-rank adaptation" models derived from a Model or a Model's output, but do not include the output of any Model.
83
+
84
+ **"Documentation"** means any specifications, manuals, documentation, and other written information provided by Fish Audio related to the Software or Models.
85
+
86
+ **"Fish Audio"** or **"we"** means 39 AI, INC. and its Affiliates.
87
+
88
+ **"Model(s)"** means, collectively, Fish Audio's proprietary models and algorithms, including machine-learning models, trained model weights and other elements of the foregoing.
89
+
90
+ **"Software"** means Fish Audio's proprietary software made available under this Agreement now or in the future.
91
+
92
+ **"Fish Audio Materials"** means, collectively, Fish Audio's proprietary Models, Software and Documentation (and any portion or combination thereof) made available under this Agreement.
93
+
94
+ **"Trade Control Laws"** means any applicable U.S. and non-U.S. export control and trade sanctions laws and regulations.
MANIFEST.json ADDED
@@ -0,0 +1,1134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": 1,
3
+ "algorithm": "sha256",
4
+ "excluded": [
5
+ "MANIFEST.json"
6
+ ],
7
+ "files": [
8
+ {
9
+ "path": ".dockerignore",
10
+ "size": 107,
11
+ "sha256": "8846b754cd333873df23ed2c6447c3c26657f21008bf901866561d1a58587cda"
12
+ },
13
+ {
14
+ "path": ".gitattributes",
15
+ "size": 219,
16
+ "sha256": "ad359bc56ca7ad35381312a9987f07c468b574209288305d5d3df127c8ac6e8b"
17
+ },
18
+ {
19
+ "path": ".gitignore",
20
+ "size": 95,
21
+ "sha256": "d9c2f19352ae8ea0dd69c2e66c46a3ecae6dad27c3e0fc043295ca7acf9753a9"
22
+ },
23
+ {
24
+ "path": ".source",
25
+ "size": 240,
26
+ "sha256": "e5d3907e41ff60c4e50108a4fcc4b64de346d5a02aa45819211f0f364bfd8799"
27
+ },
28
+ {
29
+ "path": "Dockerfile",
30
+ "size": 2981,
31
+ "sha256": "35a9862345533b12de2bbc90f7933e8558da522ac9c072c51e2cc2c1a55eb67b"
32
+ },
33
+ {
34
+ "path": "LICENSE.md",
35
+ "size": 10360,
36
+ "sha256": "aa7d9206e9d710590987a3636934f643529c00cd490323594e6206aaa0c32d80"
37
+ },
38
+ {
39
+ "path": "Notice",
40
+ "size": 994,
41
+ "sha256": "49f2d4dcecbb95e10aaba411e6237fadbe0fd1aeccc863adef3c2a7ff8b1adfe"
42
+ },
43
+ {
44
+ "path": "README.md",
45
+ "size": 10945,
46
+ "sha256": "c010e235b428b3a45f118df4e2eb9053278fbc85a5543deb542a60f5e239f18e"
47
+ },
48
+ {
49
+ "path": "THIRD_PARTY_NOTICES.md",
50
+ "size": 1039,
51
+ "sha256": "fe4c78dfee8f6ccf99bed12fbf918ce9ca4a24d2f80e6279cbccec1959ce0def"
52
+ },
53
+ {
54
+ "path": "activation-scaling-report.json",
55
+ "size": 2657835,
56
+ "sha256": "20024a68428ee44e4aa1b8101cc6357310d7670ebdd2ab87e91eb4f8f54d43ef"
57
+ },
58
+ {
59
+ "path": "chat_template.jinja",
60
+ "size": 4116,
61
+ "sha256": "87a2728cb8dc9fe424d624542f6060ec05a1d285ebbec578bb078900e33396b5"
62
+ },
63
+ {
64
+ "path": "client.py",
65
+ "size": 3640,
66
+ "sha256": "45a7831d9e8482728bcad99065c9deb2d66c0133d625eb830313cc9cd8aa83db"
67
+ },
68
+ {
69
+ "path": "codec.pth",
70
+ "size": 1871099728,
71
+ "sha256": "74fc41c5a7151c6f350af8bd7e5d6e3accfcc7f3dfbfac23afd35af07052bb2f"
72
+ },
73
+ {
74
+ "path": "compose.yaml",
75
+ "size": 612,
76
+ "sha256": "98f2090a2588f19628fdacefd0efb50d6b272d7f0f0933e8f201b3bed54efd51"
77
+ },
78
+ {
79
+ "path": "config.json",
80
+ "size": 2139,
81
+ "sha256": "bd1b81bf140b1eac0a15fe75319f5552902ad3b9903d557ddada358aef743125"
82
+ },
83
+ {
84
+ "path": "install.sh",
85
+ "size": 2521,
86
+ "sha256": "0eb32f6024fefbd3c3bf5130aecd0764dec9018656519d3532d6148405d451cc"
87
+ },
88
+ {
89
+ "path": "launch.sh",
90
+ "size": 1311,
91
+ "sha256": "83fd98f286bdf924247bd217da125169c1f6527c8375d1011b595112336c6d9c"
92
+ },
93
+ {
94
+ "path": "model-00001-of-00003.safetensors",
95
+ "size": 1992555752,
96
+ "sha256": "b304711a5a7a102dc27a49616048e72aca0c695ef4648e860a4b9b5f2c39d694"
97
+ },
98
+ {
99
+ "path": "model-00002-of-00003.safetensors",
100
+ "size": 1984565944,
101
+ "sha256": "ab75ab15859d88276b88d9c4672f196489a71336fb062335f7833da8e35e277b"
102
+ },
103
+ {
104
+ "path": "model-00003-of-00003.safetensors",
105
+ "size": 926458160,
106
+ "sha256": "0187275d6a87c4879b24b54462d8b3f487318ab402213f27bc9cca017b7d3816"
107
+ },
108
+ {
109
+ "path": "model.safetensors.index.json",
110
+ "size": 48027,
111
+ "sha256": "25229032b7d5a846fb2f946c46a35229f79babc569dad1dbc577705d892b2fba"
112
+ },
113
+ {
114
+ "path": "quantization.json",
115
+ "size": 70173,
116
+ "sha256": "9dc6d4d1bb010db508d9d5a0a9b520ff10c19e8e5c7f1d1eeb7ee9d4ee1e465b"
117
+ },
118
+ {
119
+ "path": "requirements.txt",
120
+ "size": 150,
121
+ "sha256": "b91057af47321ec40b3fb5137ad769a0510ea879054a7cc02ffb8a4c552cb477"
122
+ },
123
+ {
124
+ "path": "runtime/experimental/__init__.py",
125
+ "size": 76,
126
+ "sha256": "e2111b3a6982e6f1a84fe32ea7095a6670909abc4ae1b3c68626fc55db636d8e"
127
+ },
128
+ {
129
+ "path": "runtime/experimental/codec.py",
130
+ "size": 11733,
131
+ "sha256": "5bf0c02babbfefe1a736f3e844f6a46aac18d9653ba7444fd324d19abaf9dbfe"
132
+ },
133
+ {
134
+ "path": "runtime/experimental/fp8/__init__.py",
135
+ "size": 303,
136
+ "sha256": "752f7212156ef486d5015f55fc0098e6240260e07b08417f8f32db71c6899a4e"
137
+ },
138
+ {
139
+ "path": "runtime/experimental/fp8/modules.py",
140
+ "size": 10873,
141
+ "sha256": "3c4b2f71d0c3f078ad5f295c6ada96a5eb4c9c63ea518177985bdd6112766c5a"
142
+ },
143
+ {
144
+ "path": "runtime/experimental/fp8/server.py",
145
+ "size": 3551,
146
+ "sha256": "e421337cdddf0b3fe4c835fac47c97d56ea977a13c0455aec19eadf6aef00aa6"
147
+ },
148
+ {
149
+ "path": "runtime/experimental/nvfp4/__init__.py",
150
+ "size": 910,
151
+ "sha256": "267c7f107de1c3038459f1c20d72c3a92e56da01009a766bd178e7dfc4d0087d"
152
+ },
153
+ {
154
+ "path": "runtime/experimental/nvfp4/checkpoint.py",
155
+ "size": 7342,
156
+ "sha256": "41870d3effbcf4e5647ba62e107bbacf0db172e963b0cf14a9503349858b7114"
157
+ },
158
+ {
159
+ "path": "runtime/experimental/nvfp4/modules.py",
160
+ "size": 70345,
161
+ "sha256": "275be371fed819985805cf496735c32e679779fe1ccf0096f26e948bd2a668f7"
162
+ },
163
+ {
164
+ "path": "runtime/experimental/nvfp4/server.py",
165
+ "size": 3787,
166
+ "sha256": "bf84ec5ff00916e88b504eaef2cba5d0175322bb2a19b446a43e94ea7bf89ac1"
167
+ },
168
+ {
169
+ "path": "runtime/native/LICENSE",
170
+ "size": 11364,
171
+ "sha256": "cd1c9ea1573c9047e9b5a3676ecc1c8f755e56f249ac1ebd8b5ceda7899037da"
172
+ },
173
+ {
174
+ "path": "runtime/native/direct_w4a4_m1/direct_w4a4_m1.cpp",
175
+ "size": 4196,
176
+ "sha256": "47205d814c92081d85dd70161706efb10ce46fa7ae0da93fe43c329376ffb649"
177
+ },
178
+ {
179
+ "path": "runtime/native/direct_w4a4_m1/direct_w4a4_m1.cu",
180
+ "size": 5609,
181
+ "sha256": "23dd124a573bae75efdb9e676b8bab8b23400e6bc59f684caa17e449d8592781"
182
+ },
183
+ {
184
+ "path": "runtime/native/direct_w4a4_m1/direct_w4a4_m1.h",
185
+ "size": 428,
186
+ "sha256": "80e09accc0eff8ff12ea72e355b0f4872824fa05cb70a4a57f35fb187128d8fd"
187
+ },
188
+ {
189
+ "path": "runtime/native/rmsnorm_nvfp4_m1/rmsnorm_nvfp4_m1.cpp",
190
+ "size": 1230,
191
+ "sha256": "ab6126591d36c783ca08bb5ce0a0e0564a2085d3927631406e9b41e73197d242"
192
+ },
193
+ {
194
+ "path": "runtime/native/rmsnorm_nvfp4_m1/rmsnorm_nvfp4_m1.cu",
195
+ "size": 5848,
196
+ "sha256": "26f219fe25c6a51904e8fd11c1a05f762b20518042a095b0745e55e80f743a47"
197
+ },
198
+ {
199
+ "path": "runtime/native/rmsnorm_nvfp4_m1/rmsnorm_nvfp4_m1.h",
200
+ "size": 199,
201
+ "sha256": "eb50d22a5765fb178e48d87d3bad214c41097502446a2002094ffbd11e329676"
202
+ },
203
+ {
204
+ "path": "runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cpp",
205
+ "size": 3572,
206
+ "sha256": "eadd24b46567ea2a605b260552f07157e6a09901b1313afa5922f877781a4c2f"
207
+ },
208
+ {
209
+ "path": "runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cu",
210
+ "size": 10912,
211
+ "sha256": "ca9bd7e7a6251d6eb729333167305c60b184d0732f50294125c8b42ac424f9e4"
212
+ },
213
+ {
214
+ "path": "runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.h",
215
+ "size": 507,
216
+ "sha256": "968d4dbb617bc9d650a739a07a025f0e8c577e52c29ab41f024855304724b813"
217
+ },
218
+ {
219
+ "path": "runtime/native/smallm_gemv/smallm_gemv.cpp",
220
+ "size": 2970,
221
+ "sha256": "ae1bf8fa6400c55c9f148bcc6939ce39c6d7fcf576de5f5c7831680a1f0da626"
222
+ },
223
+ {
224
+ "path": "runtime/native/smallm_gemv/smallm_gemv.cu",
225
+ "size": 5918,
226
+ "sha256": "5de1f50d0c10ab87f87025de29600db5212d94b2558eae5bda292c3aac083521"
227
+ },
228
+ {
229
+ "path": "runtime/native/smallm_gemv/smallm_gemv.h",
230
+ "size": 316,
231
+ "sha256": "8ef4a719d3799c5afb226e40d961d82dd97412bf709fac084a9bdf71a4eb2d27"
232
+ },
233
+ {
234
+ "path": "runtime/server.py",
235
+ "size": 5276,
236
+ "sha256": "2975cb70ebc20828e39719306d1e36075141531ea457aa2b0b12f700dfea68d1"
237
+ },
238
+ {
239
+ "path": "runtime/torch-overrides.txt",
240
+ "size": 141,
241
+ "sha256": "1e4323fd7ec8624ef33657e15571562d214879275875ff59a464952d2585a02d"
242
+ },
243
+ {
244
+ "path": "runtime/web/index.html",
245
+ "size": 11668,
246
+ "sha256": "74653d8ba1b8fbfb48f5db12d85aeae7511119079043cfa18bb874841bfb2bc5"
247
+ },
248
+ {
249
+ "path": "runtime-data/references/.gitkeep",
250
+ "size": 1,
251
+ "sha256": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
252
+ },
253
+ {
254
+ "path": "special_tokens_map.json",
255
+ "size": 101864,
256
+ "sha256": "c2ff18fde6e43b7408435bc8ed079af74531befba549358a97cbc59ce606bc6b"
257
+ },
258
+ {
259
+ "path": "tokenizer.json",
260
+ "size": 12217872,
261
+ "sha256": "f24e08099d45a8adf3f52f5f0b03276e433bb9d689bb15fcbcc48ce58744588b"
262
+ },
263
+ {
264
+ "path": "tokenizer_config.json",
265
+ "size": 860832,
266
+ "sha256": "b8d149343ae425b0da67e6708686aceb51be7815d9792f265fc12ff04d5e9856"
267
+ },
268
+ {
269
+ "path": "validate_release.py",
270
+ "size": 11355,
271
+ "sha256": "c37f3e9c97882396db85679a8790f51b7dc50eee75848334b8191e6e275deb21"
272
+ },
273
+ {
274
+ "path": "vendor/fish-speech/.dockerignore",
275
+ "size": 1589,
276
+ "sha256": "d2e3fb35eae76b30d8ea06950affe3fd5174542249fd052f61644e8c0f7760bd"
277
+ },
278
+ {
279
+ "path": "vendor/fish-speech/.github/ISSUE_TEMPLATE/bug_report.yml",
280
+ "size": 2820,
281
+ "sha256": "1a105d8adfe941ab402fe7b5c67b37a65a13e44ca155917ec171e719d4212974"
282
+ },
283
+ {
284
+ "path": "vendor/fish-speech/.github/ISSUE_TEMPLATE/config.yml",
285
+ "size": 207,
286
+ "sha256": "53700059c64ff2b2a68b3cbe3ae5aec2e94783aba2414b7be14bc7a4e504fcea"
287
+ },
288
+ {
289
+ "path": "vendor/fish-speech/.github/ISSUE_TEMPLATE/feature_request.yml",
290
+ "size": 3013,
291
+ "sha256": "7aa0fa3e8b6a4695b90a26fe0ca0b766f81e5008aebef796d1316ffbcf0cec58"
292
+ },
293
+ {
294
+ "path": "vendor/fish-speech/.github/pull_request_template.md",
295
+ "size": 157,
296
+ "sha256": "600549340bc95f15c3f95c6d015fa814027220a99aaf1734dba344da4615f9c4"
297
+ },
298
+ {
299
+ "path": "vendor/fish-speech/.github/workflows/build-docker-image.yml",
300
+ "size": 2617,
301
+ "sha256": "2823c0767aebc69469286f50bdf387fa77cf08ac7246970cc65b612ce5910b67"
302
+ },
303
+ {
304
+ "path": "vendor/fish-speech/.github/workflows/docs.yml",
305
+ "size": 822,
306
+ "sha256": "8ae583f964ad63254123abbbfa8b11179cd763445012831b56a95ceac6c2c0ec"
307
+ },
308
+ {
309
+ "path": "vendor/fish-speech/.github/workflows/stale.yml",
310
+ "size": 959,
311
+ "sha256": "059b20b9316f59ec485f770fdd43f81bcd7b213fcc7d57c6e3763c6ad16d1e55"
312
+ },
313
+ {
314
+ "path": "vendor/fish-speech/.gitignore",
315
+ "size": 1344,
316
+ "sha256": "826527d0096c82edc0e6a076976134ba21b9eaf884da295b44788f7bd0f7a193"
317
+ },
318
+ {
319
+ "path": "vendor/fish-speech/.pre-commit-config.yaml",
320
+ "size": 550,
321
+ "sha256": "6d3e3c6ff61b53f62370995a0177d6fcf337d0b430ee858a407c3930185d23cf"
322
+ },
323
+ {
324
+ "path": "vendor/fish-speech/.project-root",
325
+ "size": 0,
326
+ "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
327
+ },
328
+ {
329
+ "path": "vendor/fish-speech/.readthedocs.yaml",
330
+ "size": 438,
331
+ "sha256": "2bc0776dddcc9829597377de94866048f00dfe926bf0b4d44d484c59c0ce0827"
332
+ },
333
+ {
334
+ "path": "vendor/fish-speech/API_FLAGS.txt",
335
+ "size": 204,
336
+ "sha256": "bd47758241d9a11d4b8b88aefd6500560500eb8db5b596c5f0241c6d4b7b08df"
337
+ },
338
+ {
339
+ "path": "vendor/fish-speech/LICENSE",
340
+ "size": 10360,
341
+ "sha256": "aa7d9206e9d710590987a3636934f643529c00cd490323594e6206aaa0c32d80"
342
+ },
343
+ {
344
+ "path": "vendor/fish-speech/README.md",
345
+ "size": 12065,
346
+ "sha256": "23193581f6c9a0dd174cd1427e670d64a0aeda11394f627a124b78876a23d544"
347
+ },
348
+ {
349
+ "path": "vendor/fish-speech/awesome_webui/.gitignore",
350
+ "size": 253,
351
+ "sha256": "fe718e7babb14f3cbad2d97f08889b9ce5215ed3fe0e43b2b8cfbfb3b9b844e8"
352
+ },
353
+ {
354
+ "path": "vendor/fish-speech/awesome_webui/README.md",
355
+ "size": 2520,
356
+ "sha256": "14e649116424a26ec2a1e47477c37383e4288f690a17167d2d2b88d3c4a5f725"
357
+ },
358
+ {
359
+ "path": "vendor/fish-speech/awesome_webui/eslint.config.js",
360
+ "size": 616,
361
+ "sha256": "4efe97b16d1200fac0eaf07aa00930a8668b1f96a0be1891ace8c1e712ff0ccb"
362
+ },
363
+ {
364
+ "path": "vendor/fish-speech/awesome_webui/index.html",
365
+ "size": 285,
366
+ "sha256": "f344a5836a0826a031127fdc7bc1f9f79e8ca928c45f79076d460b36df301610"
367
+ },
368
+ {
369
+ "path": "vendor/fish-speech/awesome_webui/package-lock.json",
370
+ "size": 121456,
371
+ "sha256": "307a2e98994212382c86e9356642f0dacfd405fc0cc74405ff0ca4dec43ab2d9"
372
+ },
373
+ {
374
+ "path": "vendor/fish-speech/awesome_webui/package.json",
375
+ "size": 1290,
376
+ "sha256": "a569905880fa7d29b8d5aadd08cccfb4b478bb3987057167201cb97c04054aaf"
377
+ },
378
+ {
379
+ "path": "vendor/fish-speech/awesome_webui/public/vite.svg",
380
+ "size": 1498,
381
+ "sha256": "fff702862e14c3ce019b81d86e07a0734764cac22ca5dbbe8542d4a682e482b2"
382
+ },
383
+ {
384
+ "path": "vendor/fish-speech/awesome_webui/src/App.tsx",
385
+ "size": 42735,
386
+ "sha256": "c5af7ee6cef89fab8f5a8271afaec8a84314b9b8168e883d4f9c4ff6b6c9169d"
387
+ },
388
+ {
389
+ "path": "vendor/fish-speech/awesome_webui/src/assets/react.svg",
390
+ "size": 4127,
391
+ "sha256": "9d72e876c70d7c7d4cbfe6c315747b66308176577329d2dc59b75191bdc21a4e"
392
+ },
393
+ {
394
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/alert.tsx",
395
+ "size": 1116,
396
+ "sha256": "2d5d2bf02f63e9b0e7f0e35a05d288f640e75b8c0c432166ac5aafb381d877c5"
397
+ },
398
+ {
399
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/badge.tsx",
400
+ "size": 862,
401
+ "sha256": "dece5fb21fe58f1cac9d6787e148c89e6c528db1f6c0906f4367f46fb6f750e9"
402
+ },
403
+ {
404
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/button.tsx",
405
+ "size": 1625,
406
+ "sha256": "2acdf5422a5886858c53f6116c984fb052f1f281fc7e1a02a842ab57b80e4ae4"
407
+ },
408
+ {
409
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/card.tsx",
410
+ "size": 1041,
411
+ "sha256": "17bb4d1be2607c0468369dd8ccab60f7b69a7e997d7131c1554b26ec23b71a65"
412
+ },
413
+ {
414
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/collapsible.tsx",
415
+ "size": 313,
416
+ "sha256": "0e665a7b8c5b0cca799e13704afb704e26f6afc81e70b132c903a163289acb08"
417
+ },
418
+ {
419
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/dialog.tsx",
420
+ "size": 2369,
421
+ "sha256": "37e74fb20d49ab9001261e46831d28b88bdc1695a421764e107071d6b8800f75"
422
+ },
423
+ {
424
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/label.tsx",
425
+ "size": 366,
426
+ "sha256": "2364eaa6c73a1662a1f6a6c771d1b806913ee77b6678481c2791796325050ce0"
427
+ },
428
+ {
429
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/scroll-area.tsx",
430
+ "size": 1318,
431
+ "sha256": "642b84426acec1cfefc23a472c6ddd051f9d43995215ceb0a52b83d7bf1e1099"
432
+ },
433
+ {
434
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/separator.tsx",
435
+ "size": 588,
436
+ "sha256": "3efb4936a73d93406b0cb07da3bdf070e21e2c93f44be61ff422e1eab220b090"
437
+ },
438
+ {
439
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/slider.tsx",
440
+ "size": 937,
441
+ "sha256": "edbc70edafa017bd6beb6fe169fe9e160d56a0a90aecd70a07d8f70245f841f9"
442
+ },
443
+ {
444
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/switch.tsx",
445
+ "size": 1041,
446
+ "sha256": "ebcf059e99fbbd83da8199fb26895353d718769eee111156a31dcb7249885d64"
447
+ },
448
+ {
449
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/textarea.tsx",
450
+ "size": 548,
451
+ "sha256": "3600836a7ae332cbc4a5609df662c3a328fde91066d3058779b8557d0e6a0c59"
452
+ },
453
+ {
454
+ "path": "vendor/fish-speech/awesome_webui/src/components/ui/toggle-group.tsx",
455
+ "size": 1423,
456
+ "sha256": "186970df1f46976a563b5a58ea52722cef6165f3a2547afec886bbaf2c27829e"
457
+ },
458
+ {
459
+ "path": "vendor/fish-speech/awesome_webui/src/index.css",
460
+ "size": 2003,
461
+ "sha256": "15688edb964294fa722b43c9acf444d3e61e4302d4102d5740ad7c7700ce8ad9"
462
+ },
463
+ {
464
+ "path": "vendor/fish-speech/awesome_webui/src/lib/utils.ts",
465
+ "size": 168,
466
+ "sha256": "bb1155a89f94a70f6e1c64138929f034af72405f698e3346b9c571c6a81e1938"
467
+ },
468
+ {
469
+ "path": "vendor/fish-speech/awesome_webui/src/main.tsx",
470
+ "size": 230,
471
+ "sha256": "6e9e5807fcbd48b75a96db5cbef36c996262196be42e6d4760dc86babbe61ad2"
472
+ },
473
+ {
474
+ "path": "vendor/fish-speech/awesome_webui/tsconfig.app.json",
475
+ "size": 816,
476
+ "sha256": "b75e309a7934571963d315a8f2376c6761adbdc8d7ab177d79ead9ff7fdc5a08"
477
+ },
478
+ {
479
+ "path": "vendor/fish-speech/awesome_webui/tsconfig.json",
480
+ "size": 119,
481
+ "sha256": "770b4140bbb581e2dfd9ea9946ffc9c75a1d86ba7d2db5f77c83e37cbdf9d808"
482
+ },
483
+ {
484
+ "path": "vendor/fish-speech/awesome_webui/tsconfig.node.json",
485
+ "size": 725,
486
+ "sha256": "8783c2ca6cf9b6cf07578deb90c2a42c09460bdfa725de6add8e1ace9ce486ee"
487
+ },
488
+ {
489
+ "path": "vendor/fish-speech/awesome_webui/vite.config.ts",
490
+ "size": 3278,
491
+ "sha256": "8d9fddde878fbd0e6fad17325272c81d1ba3ff40ef8c34e904e7553e9e78190e"
492
+ },
493
+ {
494
+ "path": "vendor/fish-speech/compose.base.yml",
495
+ "size": 633,
496
+ "sha256": "9741535b4d5bc58c088dd9a8ed6a308fa6dc845a78ec17b98e268a7ead7e4e7b"
497
+ },
498
+ {
499
+ "path": "vendor/fish-speech/compose.rocm.yml",
500
+ "size": 1318,
501
+ "sha256": "e6ce9cb3cfa06d81a537662e544bf6c1a6d1ee0bf57eb3ab126a8201ab4b16a9"
502
+ },
503
+ {
504
+ "path": "vendor/fish-speech/compose.yml",
505
+ "size": 476,
506
+ "sha256": "9a069086b7edc69c27c9863199962c3c3cfc3ade329678cd288ad2d0891cc3e4"
507
+ },
508
+ {
509
+ "path": "vendor/fish-speech/docker/Dockerfile",
510
+ "size": 12538,
511
+ "sha256": "3df60e1f23454cf31fed92e3e018eb772f1d6677eecce24985a74078b904d5e2"
512
+ },
513
+ {
514
+ "path": "vendor/fish-speech/docker/Dockerfile.rocm",
515
+ "size": 4025,
516
+ "sha256": "7b5fe82284aa9b28601c5952d4eafaa3b0f01652303b6718c41884a4e7050a79"
517
+ },
518
+ {
519
+ "path": "vendor/fish-speech/dockerfile.dev",
520
+ "size": 1074,
521
+ "sha256": "52cf29b9ae3bd05fe1d58473c9538fd632a8b2e8c0dd12d63e220e4a7a9648b5"
522
+ },
523
+ {
524
+ "path": "vendor/fish-speech/docs/CNAME",
525
+ "size": 18,
526
+ "sha256": "94b6e87dc6e8704a583456b9d2db4a39559c5ae6a65e1d92f977776863175a00"
527
+ },
528
+ {
529
+ "path": "vendor/fish-speech/docs/README.ar.md",
530
+ "size": 15648,
531
+ "sha256": "19b3439785d22912f794449de6f489c879cd4c93632bc8857aede5d0ee00c4d9"
532
+ },
533
+ {
534
+ "path": "vendor/fish-speech/docs/README.es.md",
535
+ "size": 9421,
536
+ "sha256": "69c381dba1b8d401a55e6d67c6a332938d2c058fa20f9e543187a92330f44c21"
537
+ },
538
+ {
539
+ "path": "vendor/fish-speech/docs/README.ja.md",
540
+ "size": 13744,
541
+ "sha256": "1a3b6726e5c2b9c6af0e172a52ae21b136c58b64fb599698aa0dcb48dd90c6eb"
542
+ },
543
+ {
544
+ "path": "vendor/fish-speech/docs/README.ko.md",
545
+ "size": 13034,
546
+ "sha256": "415f15e48f2b1f97619b91a9602dcd7348d81df84d69cd3cf9a2a4159cac6443"
547
+ },
548
+ {
549
+ "path": "vendor/fish-speech/docs/README.pt-BR.md",
550
+ "size": 13135,
551
+ "sha256": "90233321ef5f1d753f9dc8162a13f0a21a86370d0e32e5b732d232c7dc0e33d8"
552
+ },
553
+ {
554
+ "path": "vendor/fish-speech/docs/README.zh.md",
555
+ "size": 11662,
556
+ "sha256": "c395ac54df44cf7362bfd800e3d2db170ad5ec60a5908cea15bde87b1c953bda"
557
+ },
558
+ {
559
+ "path": "vendor/fish-speech/docs/ar/finetune.md",
560
+ "size": 6082,
561
+ "sha256": "e94b0cdcea11ce741c17d883b32beabb541e1653f267fe59a9efd5931b0f7cdb"
562
+ },
563
+ {
564
+ "path": "vendor/fish-speech/docs/ar/index.md",
565
+ "size": 13191,
566
+ "sha256": "29995c610cc69e982e905948463592273c712d15fac87622c54483e2199aeb9e"
567
+ },
568
+ {
569
+ "path": "vendor/fish-speech/docs/ar/inference.md",
570
+ "size": 3189,
571
+ "sha256": "a0dc48584eeff9452d4051b7ca3cc86c4b118aa796dbd4aa2acded07571a1404"
572
+ },
573
+ {
574
+ "path": "vendor/fish-speech/docs/ar/install.md",
575
+ "size": 7525,
576
+ "sha256": "837fd7cde51ce62c685aaac3945d6aa8d28818a08c7a51f4d0c9546ce1ec836e"
577
+ },
578
+ {
579
+ "path": "vendor/fish-speech/docs/assets/chattemplate.png",
580
+ "size": 3001037,
581
+ "sha256": "125061f3dbb707d7a494d991e6854a47dc7bd5e853590f0223bac154243b4778"
582
+ },
583
+ {
584
+ "path": "vendor/fish-speech/docs/assets/logo.svg",
585
+ "size": 1787,
586
+ "sha256": "15ae95ec011b44031163c7d92044152dbdba9055d13ee050992ad93455b18ab9"
587
+ },
588
+ {
589
+ "path": "vendor/fish-speech/docs/assets/totalability.png",
590
+ "size": 3564498,
591
+ "sha256": "b21736aa07c0cb1a1a0ae55ae0b97ab2a6ecbee34c0b7bc38076c83420617bcd"
592
+ },
593
+ {
594
+ "path": "vendor/fish-speech/docs/en/finetune.md",
595
+ "size": 4450,
596
+ "sha256": "af5355d64cef5bfbe652763790b45817b4027991ac866461b04cade72a9de32c"
597
+ },
598
+ {
599
+ "path": "vendor/fish-speech/docs/en/index.md",
600
+ "size": 10688,
601
+ "sha256": "cd8ddcff0de3c2b549a992f22118029e289fe0e213de83ac30700b4b8204b798"
602
+ },
603
+ {
604
+ "path": "vendor/fish-speech/docs/en/inference.md",
605
+ "size": 2400,
606
+ "sha256": "bbe2b3e9e2355c480477f4bfdf053f348917a42665cdb52464ede8514aa337bc"
607
+ },
608
+ {
609
+ "path": "vendor/fish-speech/docs/en/install.md",
610
+ "size": 7135,
611
+ "sha256": "9930c9099eced275c6dc7ccecae026411ba9de8ab61195651a927213030b2a76"
612
+ },
613
+ {
614
+ "path": "vendor/fish-speech/docs/en/server.md",
615
+ "size": 2053,
616
+ "sha256": "910820d8c593bc5722fae1108c21f583f588fbde12b5bb63fc3c2f472bce5f78"
617
+ },
618
+ {
619
+ "path": "vendor/fish-speech/docs/es/finetune.md",
620
+ "size": 4661,
621
+ "sha256": "3a498c00f147f31155c29007d9572db985c7c49d78febb3f2136e3d862d5c7c3"
622
+ },
623
+ {
624
+ "path": "vendor/fish-speech/docs/es/index.md",
625
+ "size": 11320,
626
+ "sha256": "0c476da28d0074d2c0614b0ac8a297bb7f9734579d258e46497fa5e27446cfec"
627
+ },
628
+ {
629
+ "path": "vendor/fish-speech/docs/es/inference.md",
630
+ "size": 1652,
631
+ "sha256": "697399235eb16525cb9f11db052c6c662301cbcae70811cb0139ff88354f2ace"
632
+ },
633
+ {
634
+ "path": "vendor/fish-speech/docs/es/install.md",
635
+ "size": 6258,
636
+ "sha256": "e9445f4d9abeccf9870d9912d1a3ed287282d87620c94507727566c6150e5d82"
637
+ },
638
+ {
639
+ "path": "vendor/fish-speech/docs/es/server.md",
640
+ "size": 2291,
641
+ "sha256": "a5ef0ccf911c67ada2f414c3e4b10cc17d89944c163ea838f01c2997ef288695"
642
+ },
643
+ {
644
+ "path": "vendor/fish-speech/docs/ja/finetune.md",
645
+ "size": 5665,
646
+ "sha256": "ee03602acc09a7a23f0bd51e9215f64b1d64d03a6c46e92fc13e3234ebec979c"
647
+ },
648
+ {
649
+ "path": "vendor/fish-speech/docs/ja/index.md",
650
+ "size": 11910,
651
+ "sha256": "b55777fc674b3ea5c419a52a4702479120cba951d7a0a196cb38c68ec5dd90cc"
652
+ },
653
+ {
654
+ "path": "vendor/fish-speech/docs/ja/inference.md",
655
+ "size": 3127,
656
+ "sha256": "a4bb49bd21855128b2cb157c0733fab0ef62c62c850b3b97b2dc9724eee1ef43"
657
+ },
658
+ {
659
+ "path": "vendor/fish-speech/docs/ja/install.md",
660
+ "size": 7155,
661
+ "sha256": "9032434192c823e8f3c6749723aa0dbe2c9861dde5b45675d03e3024c95915f9"
662
+ },
663
+ {
664
+ "path": "vendor/fish-speech/docs/ko/finetune.md",
665
+ "size": 5064,
666
+ "sha256": "62a5e0e92fc398e4f9bf2736ee9fe2543d2b4b845e3297dc33c8ea4a295906bb"
667
+ },
668
+ {
669
+ "path": "vendor/fish-speech/docs/ko/index.md",
670
+ "size": 10976,
671
+ "sha256": "457f171814d81819ed4bb776244858c9195ee686fc1bfac5e8e1a27d5ac89021"
672
+ },
673
+ {
674
+ "path": "vendor/fish-speech/docs/ko/inference.md",
675
+ "size": 2707,
676
+ "sha256": "aba1a3997e6b7b5d140c79f83976827b420fd3a1db69c63772a8fceb884120d9"
677
+ },
678
+ {
679
+ "path": "vendor/fish-speech/docs/ko/install.md",
680
+ "size": 6154,
681
+ "sha256": "4ef88b9b1c66fa5c6249c76242cf4c28bd253c8a7e75b34f2c0975b8aa3b679b"
682
+ },
683
+ {
684
+ "path": "vendor/fish-speech/docs/pt/finetune.md",
685
+ "size": 4808,
686
+ "sha256": "26fe44a755f77a9ecdba86de8170c32845d011b7e9c9e6a28e0c099acd0e31b7"
687
+ },
688
+ {
689
+ "path": "vendor/fish-speech/docs/pt/index.md",
690
+ "size": 10937,
691
+ "sha256": "d491cbe173ed548bbcac3b722855b0d2b34aec59e5c36e10954719efc8db7c9c"
692
+ },
693
+ {
694
+ "path": "vendor/fish-speech/docs/pt/inference.md",
695
+ "size": 2643,
696
+ "sha256": "0a00d7066248b42fd8f6c3ef1b60bb96303ee7e8ed60b4365c1573b3f042ea34"
697
+ },
698
+ {
699
+ "path": "vendor/fish-speech/docs/pt/install.md",
700
+ "size": 6239,
701
+ "sha256": "b46c769edb2a7f9a3159ada928bd85ed5baa318ef0c8c3b5b49fcb15236686b8"
702
+ },
703
+ {
704
+ "path": "vendor/fish-speech/docs/requirements.txt",
705
+ "size": 58,
706
+ "sha256": "d1ad209ce393487abd53afa357470c9d12e17f048689e30e20dfce5e03f42127"
707
+ },
708
+ {
709
+ "path": "vendor/fish-speech/docs/stylesheets/extra.css",
710
+ "size": 35,
711
+ "sha256": "8d429df9c7907d7e4fee12af1af8bfec0a29f6142cc9b5cb62c8b1de29e0898c"
712
+ },
713
+ {
714
+ "path": "vendor/fish-speech/docs/zh/finetune.md",
715
+ "size": 4081,
716
+ "sha256": "e0622704c25cd0941b5672a9370101b2123dcb39be48f6c1764204fa864b2f9d"
717
+ },
718
+ {
719
+ "path": "vendor/fish-speech/docs/zh/index.md",
720
+ "size": 10114,
721
+ "sha256": "0560d6e67a097ee92d02615b893ae306c13b9d71b15e4edef6abcd70ae46f94c"
722
+ },
723
+ {
724
+ "path": "vendor/fish-speech/docs/zh/inference.md",
725
+ "size": 2300,
726
+ "sha256": "19afd07e8af2a5e403adf8e3df2ff5468e8e3ab5e85d6b545707578855e547ec"
727
+ },
728
+ {
729
+ "path": "vendor/fish-speech/docs/zh/install.md",
730
+ "size": 5166,
731
+ "sha256": "c5b4953f4f0cc8654f49866442c9a2ce8655b5703730014f103a053e11e4c4a6"
732
+ },
733
+ {
734
+ "path": "vendor/fish-speech/entrypoint.sh",
735
+ "size": 171,
736
+ "sha256": "e16d821b9e21b0ba8915b497aed9a4612cf99801181f2fe1f9a87d895e71cf50"
737
+ },
738
+ {
739
+ "path": "vendor/fish-speech/fish_speech/callbacks/__init__.py",
740
+ "size": 141,
741
+ "sha256": "2e60f60140744e0acbd2d5e8b7d4bc95ea5593586b1b4d5ebbe6a58ea7ef4fbb"
742
+ },
743
+ {
744
+ "path": "vendor/fish-speech/fish_speech/callbacks/grad_norm.py",
745
+ "size": 3436,
746
+ "sha256": "a73b94c549d75806bd53a5ca72f4299c6a146613261502a2992a981fe59a8c84"
747
+ },
748
+ {
749
+ "path": "vendor/fish-speech/fish_speech/callbacks/progress_bar.py",
750
+ "size": 518,
751
+ "sha256": "caa68bcfaa4894ffe23312648ccdbf65ed24698dbc017eb413fc9a5da94d930b"
752
+ },
753
+ {
754
+ "path": "vendor/fish-speech/fish_speech/configs/base.yaml",
755
+ "size": 2618,
756
+ "sha256": "3131447a82b4f8e8176c653d1a7dc4021cf7d4ede12c320a3a76fa210d072b55"
757
+ },
758
+ {
759
+ "path": "vendor/fish-speech/fish_speech/configs/lora/r_32_alpha_16_fast.yaml",
760
+ "size": 182,
761
+ "sha256": "cdc5f6c8a8af194869ae544215b86e5a3a334f47266df47e922c2c008cb19bea"
762
+ },
763
+ {
764
+ "path": "vendor/fish-speech/fish_speech/configs/lora/r_8_alpha_16.yaml",
765
+ "size": 98,
766
+ "sha256": "6bd41590dd80eb8ff497c5d47f05757e05b97998bdd76e0be691ddb0df598082"
767
+ },
768
+ {
769
+ "path": "vendor/fish-speech/fish_speech/configs/modded_dac_vq.yaml",
770
+ "size": 1376,
771
+ "sha256": "73321408579c372149620d877f0dfb841cf70465758a535f7243e1cb6553d56a"
772
+ },
773
+ {
774
+ "path": "vendor/fish-speech/fish_speech/configs/text2semantic_finetune.yaml",
775
+ "size": 2074,
776
+ "sha256": "dcfb2cf20f62506a04078df72a1ecf52cea2bbb23db86f900439a02a7f6f3370"
777
+ },
778
+ {
779
+ "path": "vendor/fish-speech/fish_speech/content_sequence.py",
780
+ "size": 14345,
781
+ "sha256": "429218fb07feb5910d3b232bf6289555dc1c99e2a8622a28963737c3990a0c50"
782
+ },
783
+ {
784
+ "path": "vendor/fish-speech/fish_speech/conversation.py",
785
+ "size": 5602,
786
+ "sha256": "1baece5e55f9e3b27f655a3ac8c3ceef441ff87354db0b91a840cac137c4e3c2"
787
+ },
788
+ {
789
+ "path": "vendor/fish-speech/fish_speech/datasets/concat_repeat.py",
790
+ "size": 1498,
791
+ "sha256": "cbda40b72dd26b78327c011149ab9b98c351754cf2030e33ce80f25f3b861b14"
792
+ },
793
+ {
794
+ "path": "vendor/fish-speech/fish_speech/datasets/protos/text-data.proto",
795
+ "size": 392,
796
+ "sha256": "d6bb8c95bc7925f43efd0033cf03e7059e73add38f4d1944a2f560a51c279f7c"
797
+ },
798
+ {
799
+ "path": "vendor/fish-speech/fish_speech/datasets/protos/text_data_pb2.py",
800
+ "size": 1759,
801
+ "sha256": "54f5f84e4290f21e2a53cc5063228c5de52e9736aac971e22c38cf7a5b2cf750"
802
+ },
803
+ {
804
+ "path": "vendor/fish-speech/fish_speech/datasets/protos/text_data_stream.py",
805
+ "size": 781,
806
+ "sha256": "bfd8b78db202e8a15348bbd256ca3cfb79810ee7d23b013b200af8fb9457810d"
807
+ },
808
+ {
809
+ "path": "vendor/fish-speech/fish_speech/datasets/semantic.py",
810
+ "size": 20572,
811
+ "sha256": "ef9332053ea341bb4e04d9cafedfa2e9771d5a9e522abf868ad3dec58eb0beea"
812
+ },
813
+ {
814
+ "path": "vendor/fish-speech/fish_speech/datasets/vqgan.py",
815
+ "size": 3933,
816
+ "sha256": "d8612b491cabf5e9f6094617559d8d5a74c223fd2b08e7135e7f88a34b885b67"
817
+ },
818
+ {
819
+ "path": "vendor/fish-speech/fish_speech/i18n/README.md",
820
+ "size": 1483,
821
+ "sha256": "a57432fe33c55f24c14129e2e094851f526db28a8e7bbbce7d6a51b4e3c6cfac"
822
+ },
823
+ {
824
+ "path": "vendor/fish-speech/fish_speech/i18n/__init__.py",
825
+ "size": 43,
826
+ "sha256": "bbdaff1c2b53998714eb82fad8683d94b00dbc6c9b7dbd3e113c3c39bf9f9f16"
827
+ },
828
+ {
829
+ "path": "vendor/fish-speech/fish_speech/i18n/core.py",
830
+ "size": 1036,
831
+ "sha256": "f0ab3cc06a20ef753e019aa5cc696d7f1eb52802c64e1eee0885e74070e70cec"
832
+ },
833
+ {
834
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/ar_SA.json",
835
+ "size": 9843,
836
+ "sha256": "0eeeb96d4ee6e6405c415d490651566f2d9275172c8ffcae75c23637f410a1be"
837
+ },
838
+ {
839
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/en_US.json",
840
+ "size": 8103,
841
+ "sha256": "c41c66facb7f4e4641501828830f532a20f216ad2b258adddb91b96a3d8a0c98"
842
+ },
843
+ {
844
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/es_ES.json",
845
+ "size": 9012,
846
+ "sha256": "dcf80e38f59d415171271e3f12b4324bdba0ff27f1222a8504e0917df5c226b4"
847
+ },
848
+ {
849
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/ja_JP.json",
850
+ "size": 9496,
851
+ "sha256": "225330a3fb51f0be2c2aa54afe6522ced6ad1ecec57d15cd4cc695de54768b04"
852
+ },
853
+ {
854
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/ko_KR.json",
855
+ "size": 8787,
856
+ "sha256": "792f1862d348506b334e444b1adba83d148da67638a7f3918efa9ef594886bfb"
857
+ },
858
+ {
859
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/pt_BR.json",
860
+ "size": 9615,
861
+ "sha256": "44d54552e9ff585bbbaaa8389a79200fa7e68b59881121b08cee10bda96c1ae8"
862
+ },
863
+ {
864
+ "path": "vendor/fish-speech/fish_speech/i18n/locale/zh_CN.json",
865
+ "size": 7773,
866
+ "sha256": "ec1739836b8ade678540c692903489b992171e1afb171fcff0e9dbdae2c3ddbf"
867
+ },
868
+ {
869
+ "path": "vendor/fish-speech/fish_speech/i18n/scan.py",
870
+ "size": 3751,
871
+ "sha256": "d6675728f791d1dddb4dc1595a15fa38359425b6e23873bbdcc0431099539946"
872
+ },
873
+ {
874
+ "path": "vendor/fish-speech/fish_speech/inference_engine/__init__.py",
875
+ "size": 6261,
876
+ "sha256": "2e511bb701b2e1a07770700fb0d33a1c51b7066a418e8897467729913c6c59d0"
877
+ },
878
+ {
879
+ "path": "vendor/fish-speech/fish_speech/inference_engine/reference_loader.py",
880
+ "size": 9567,
881
+ "sha256": "7b9fd6ce1b5aa0b08a2d6ec6630549168ea57933e5f35027b6ac22efd1e7b7bb"
882
+ },
883
+ {
884
+ "path": "vendor/fish-speech/fish_speech/inference_engine/utils.py",
885
+ "size": 685,
886
+ "sha256": "22f32b647e2d73795dddbde9cb1e21884663627bd1a2c78e38381a81c0b933fe"
887
+ },
888
+ {
889
+ "path": "vendor/fish-speech/fish_speech/inference_engine/vq_manager.py",
890
+ "size": 1952,
891
+ "sha256": "881f9fa54661076b976e917caf9da1c04b7d476b77c9cf92f1edc22c2125e932"
892
+ },
893
+ {
894
+ "path": "vendor/fish-speech/fish_speech/models/dac/__init__.py",
895
+ "size": 0,
896
+ "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
897
+ },
898
+ {
899
+ "path": "vendor/fish-speech/fish_speech/models/dac/inference.py",
900
+ "size": 3895,
901
+ "sha256": "1914f547001ec23d25cdff3a495dc40e2434f4657d8fe3bda837d88001520331"
902
+ },
903
+ {
904
+ "path": "vendor/fish-speech/fish_speech/models/dac/modded_dac.py",
905
+ "size": 35062,
906
+ "sha256": "a08407421ee85d8af28377d6a14d989b5a17a985c9719f8b5701cd0a845840c0"
907
+ },
908
+ {
909
+ "path": "vendor/fish-speech/fish_speech/models/dac/rvq.py",
910
+ "size": 13143,
911
+ "sha256": "a4d38e529846473c712dd1b2f5eaa889eb0233fd56228799c168060f335c0246"
912
+ },
913
+ {
914
+ "path": "vendor/fish-speech/fish_speech/models/text2semantic/__init__.py",
915
+ "size": 0,
916
+ "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
917
+ },
918
+ {
919
+ "path": "vendor/fish-speech/fish_speech/models/text2semantic/inference.py",
920
+ "size": 31250,
921
+ "sha256": "0c2e6746cd1fcc5e776cc37d6430a33c3fda1fc1c08b347860903f345a1c0779"
922
+ },
923
+ {
924
+ "path": "vendor/fish-speech/fish_speech/models/text2semantic/lit_module.py",
925
+ "size": 6935,
926
+ "sha256": "c1c6d1d39d20e6e94a0aa75148e6d416534188ac595b6ec22d5ff131b7f31915"
927
+ },
928
+ {
929
+ "path": "vendor/fish-speech/fish_speech/models/text2semantic/llama.py",
930
+ "size": 36007,
931
+ "sha256": "b7dc3c039ddcbc05e445293e5d4babb1e80340b8a2944747fab0cf44c0919852"
932
+ },
933
+ {
934
+ "path": "vendor/fish-speech/fish_speech/models/text2semantic/lora.py",
935
+ "size": 4084,
936
+ "sha256": "551e140a0cf78a779ab86cdeb4b5c71af330282651ba9cc401937fba4ed23dc7"
937
+ },
938
+ {
939
+ "path": "vendor/fish-speech/fish_speech/scheduler.py",
940
+ "size": 1101,
941
+ "sha256": "c69b2d01f5e5b1dc7e37f84370925814a88b6ff716e664dd5c00b2b8e0eb7088"
942
+ },
943
+ {
944
+ "path": "vendor/fish-speech/fish_speech/text/__init__.py",
945
+ "size": 56,
946
+ "sha256": "584dd80b9ec25e96e1bdae800874e8d0edd3355c2732e52a0644a906e32b4e26"
947
+ },
948
+ {
949
+ "path": "vendor/fish-speech/fish_speech/text/clean.py",
950
+ "size": 832,
951
+ "sha256": "3b9b1ec80e2d4f8aa71d386f19ab362bea7603485b63836b38a202d137e36d6e"
952
+ },
953
+ {
954
+ "path": "vendor/fish-speech/fish_speech/tokenizer.py",
955
+ "size": 3948,
956
+ "sha256": "a25d136cdf3d150e862a808fe9badf8d7ab473509f4068c6115772ff98b566da"
957
+ },
958
+ {
959
+ "path": "vendor/fish-speech/fish_speech/train.py",
960
+ "size": 4470,
961
+ "sha256": "32d55a2cfb4c50498b4ecca9b0edc201a835ecf1ee8b232973d58e477bec9e40"
962
+ },
963
+ {
964
+ "path": "vendor/fish-speech/fish_speech/utils/__init__.py",
965
+ "size": 706,
966
+ "sha256": "dd8206cec25b8fce284d1f96428173fe9ced66d5081e9d7adcaff1d170fcb715"
967
+ },
968
+ {
969
+ "path": "vendor/fish-speech/fish_speech/utils/braceexpand.py",
970
+ "size": 6724,
971
+ "sha256": "5ffe38c16f8b24fdb590d6f5f63eb70d24b3168a6482c48d92a9ac1252d24ba5"
972
+ },
973
+ {
974
+ "path": "vendor/fish-speech/fish_speech/utils/context.py",
975
+ "size": 287,
976
+ "sha256": "1b9032235a9abe15febc17ac00d53431bf7ba23058f349f089706bccd15d4391"
977
+ },
978
+ {
979
+ "path": "vendor/fish-speech/fish_speech/utils/file.py",
980
+ "size": 3354,
981
+ "sha256": "d6d13187c1487698a4d5aa5c4b01e52d6da1b579931294b465534956c10b8286"
982
+ },
983
+ {
984
+ "path": "vendor/fish-speech/fish_speech/utils/instantiators.py",
985
+ "size": 1514,
986
+ "sha256": "2a45f5f174f3d7712dde02b308610b5c8d59b05fce9ecf2b750c4f9b846fc61e"
987
+ },
988
+ {
989
+ "path": "vendor/fish-speech/fish_speech/utils/logger.py",
990
+ "size": 2467,
991
+ "sha256": "5959ccc8442a94eda7bede31c92905a2071ea5e34335c1d68d3618fa6d1fa382"
992
+ },
993
+ {
994
+ "path": "vendor/fish-speech/fish_speech/utils/logging_utils.py",
995
+ "size": 1384,
996
+ "sha256": "049de1f2117eeb631bab16a38666602a0964a633dfcff193153afaf364887985"
997
+ },
998
+ {
999
+ "path": "vendor/fish-speech/fish_speech/utils/rich_utils.py",
1000
+ "size": 3105,
1001
+ "sha256": "447454aeadb1635775120db886d1679b28f44515b6351770c3dc73d235a742df"
1002
+ },
1003
+ {
1004
+ "path": "vendor/fish-speech/fish_speech/utils/schema.py",
1005
+ "size": 3912,
1006
+ "sha256": "8f4e8b272c29fc390272ce5c15f74268679d3f4434e684a6519141692c7f7c53"
1007
+ },
1008
+ {
1009
+ "path": "vendor/fish-speech/fish_speech/utils/spectrogram.py",
1010
+ "size": 3325,
1011
+ "sha256": "9663d20ae9c79e5a517516be9aefa25485292a69f53426b847d812c7f13bbbd2"
1012
+ },
1013
+ {
1014
+ "path": "vendor/fish-speech/fish_speech/utils/utils.py",
1015
+ "size": 4283,
1016
+ "sha256": "df0d1dac088ba396d59cead71fc7b3b0801a02448fddcab082931cafb9044454"
1017
+ },
1018
+ {
1019
+ "path": "vendor/fish-speech/inference.ipynb",
1020
+ "size": 5021,
1021
+ "sha256": "3ad1d80be8824a5fb980e38e9efc940e71d2b082f73b4efeacb49a4561077e1d"
1022
+ },
1023
+ {
1024
+ "path": "vendor/fish-speech/mkdocs.yml",
1025
+ "size": 4108,
1026
+ "sha256": "17a35919a0f090a195205cdb68288874d1f09a4c1454acc04bd1eb60a5830e6b"
1027
+ },
1028
+ {
1029
+ "path": "vendor/fish-speech/pyproject.toml",
1030
+ "size": 2966,
1031
+ "sha256": "6157b9769168546b14f76831da5549ec1674d7f338185f4119e72c8dbb0eab59"
1032
+ },
1033
+ {
1034
+ "path": "vendor/fish-speech/pyrightconfig.json",
1035
+ "size": 63,
1036
+ "sha256": "f78eaa043520319af6a9619303228999027e636d3307baf174638c7b08777fad"
1037
+ },
1038
+ {
1039
+ "path": "vendor/fish-speech/tools/api_client.py",
1040
+ "size": 7704,
1041
+ "sha256": "47cc75a9fd146763581dafb12e991fa7969e915aae78a0690d90b476371732a9"
1042
+ },
1043
+ {
1044
+ "path": "vendor/fish-speech/tools/api_server.py",
1045
+ "size": 4408,
1046
+ "sha256": "0e8c70f6184cdb0b64464a7f3204284051d86ba132c478ff86ddb649cfbd89dc"
1047
+ },
1048
+ {
1049
+ "path": "vendor/fish-speech/tools/llama/build_dataset.py",
1050
+ "size": 4910,
1051
+ "sha256": "b115a58c3e3e588ce2106f2e0db7ee3a26773ac2b5520d7244a36ef5c0ab8c7c"
1052
+ },
1053
+ {
1054
+ "path": "vendor/fish-speech/tools/llama/eval_in_context.py",
1055
+ "size": 4641,
1056
+ "sha256": "e46a8072380ad934dfadad4c621ab2749646376eef5e5b6a873ea15d29f75b59"
1057
+ },
1058
+ {
1059
+ "path": "vendor/fish-speech/tools/llama/merge_lora.py",
1060
+ "size": 3369,
1061
+ "sha256": "6f1de34312b56697c275e47d35104e336b5905db6804bd93ea4561fc92e1ea65"
1062
+ },
1063
+ {
1064
+ "path": "vendor/fish-speech/tools/llama/quantize.py",
1065
+ "size": 16589,
1066
+ "sha256": "3a07f3fbc44240c744725c75ec3587d48857de7e039847a9c79e6e4be7fd07f3"
1067
+ },
1068
+ {
1069
+ "path": "vendor/fish-speech/tools/run_webui.py",
1070
+ "size": 3377,
1071
+ "sha256": "20c3b10f10dbf45659dbfbfd5bff2fbf32f73ace966013a80d7909362d8dd5a3"
1072
+ },
1073
+ {
1074
+ "path": "vendor/fish-speech/tools/server/api_utils.py",
1075
+ "size": 4451,
1076
+ "sha256": "6bbb1414eefd42f6be053e0d27a381df8c921adcb0e4c4e12d02e4bd596bf5ec"
1077
+ },
1078
+ {
1079
+ "path": "vendor/fish-speech/tools/server/exception_handler.py",
1080
+ "size": 729,
1081
+ "sha256": "09471ac426e926d9c824e3f67c30f0e2884b17a2e502492f1632035c8075c171"
1082
+ },
1083
+ {
1084
+ "path": "vendor/fish-speech/tools/server/inference.py",
1085
+ "size": 1352,
1086
+ "sha256": "445898e3c2f97ce6fedd34b906b4bf0d53dd7dd896a27830d4f9484e142f26ae"
1087
+ },
1088
+ {
1089
+ "path": "vendor/fish-speech/tools/server/model_manager.py",
1090
+ "size": 2974,
1091
+ "sha256": "6135527b37067f4cc7ae4a782ee6584b8881d1b7fbd9b7fabecfebd8ebda7e03"
1092
+ },
1093
+ {
1094
+ "path": "vendor/fish-speech/tools/server/model_utils.py",
1095
+ "size": 2643,
1096
+ "sha256": "4680f7c92d04524b72a506cdf4525c4bd5dc5fa967e9a9cef0d018a1c6e2a893"
1097
+ },
1098
+ {
1099
+ "path": "vendor/fish-speech/tools/server/views.py",
1100
+ "size": 17012,
1101
+ "sha256": "25234db4aa025bde24d26a69a89fa8c5eb91b0c24dac2265533a4d4f458104e2"
1102
+ },
1103
+ {
1104
+ "path": "vendor/fish-speech/tools/vqgan/create_train_split.py",
1105
+ "size": 3008,
1106
+ "sha256": "ac096e4fb7ae098c6d79bd4e91a79e9d610eb141ba0f492b036566badb61fad6"
1107
+ },
1108
+ {
1109
+ "path": "vendor/fish-speech/tools/vqgan/extract_vq.py",
1110
+ "size": 7116,
1111
+ "sha256": "3552649e3827fd2ac388fd3207aed3e095e107bb10f304e8cdd5414c71d849f6"
1112
+ },
1113
+ {
1114
+ "path": "vendor/fish-speech/tools/webui/__init__.py",
1115
+ "size": 6167,
1116
+ "sha256": "8638f675fa822782a290e28907a3e9b73cf3b376fea68298baa45f92e0b3bb7a"
1117
+ },
1118
+ {
1119
+ "path": "vendor/fish-speech/tools/webui/inference.py",
1120
+ "size": 2109,
1121
+ "sha256": "01f14ab86b3fe5e883dffd0729a0a3e4af67f9834d2ac3c529568b8ca33aba15"
1122
+ },
1123
+ {
1124
+ "path": "vendor/fish-speech/tools/webui/variables.py",
1125
+ "size": 605,
1126
+ "sha256": "3e10038f814557353737e3892dcb07cad2e0073188129010b9b4d817c12f4fbd"
1127
+ },
1128
+ {
1129
+ "path": "vendor/fish-speech/uv.lock",
1130
+ "size": 1225073,
1131
+ "sha256": "59711c5afba9fa5b53e7c31bf869d1ee7993d60c3a11b36a73095d2f135f0807"
1132
+ }
1133
+ ]
1134
+ }
Notice ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This model is licensed under the Fish Audio Research License, Copyright © 39 AI, INC. All Rights Reserved.
2
+
3
+ Built with Fish Audio.
4
+
5
+ Changes made by ajh-code:
6
+
7
+ - Quantized 60 slow-transformer gate/up projections in layers 3–32 to packed
8
+ NVFP4 E2M1 weights with a native W4A16 decode path and W4A4 larger-M path.
9
+ - Quantized the other 120 slow-transformer projections to native MXFP8 W8A8.
10
+ - Folded calibrated English channel scales into selected normalization and
11
+ packed-weight tensors.
12
+ - Added a portable mixed-precision loader, Blackwell kernels, a TTS API/web
13
+ interface, compact inference-only DAC buffers, and reference-encoder staging.
14
+ - Kept embeddings, normalization arithmetic, output heads, the fast
15
+ transformer, KV cache, sampling, and DAC arithmetic at BF16 or their original
16
+ higher precision.
17
+
18
+ The original model is fishaudio/s2-pro, revision
19
+ 1de9996b6be38b745688de084d87a5633f714e4e. The bundled Fish Speech source is
20
+ revision e5e292632cb11e7a27b2b7487f58f612bc101e13.
README.md ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: fish-audio-research-license
4
+ license_link: https://huggingface.co/fishaudio/s2-pro/blob/1de9996b6be38b745688de084d87a5633f714e4e/LICENSE.md
5
+ library_name: fish-speech
6
+ pipeline_tag: text-to-speech
7
+ base_model: fishaudio/s2-pro
8
+ base_model_relation: quantized
9
+ language:
10
+ - en
11
+ tags:
12
+ - fish-speech
13
+ - fish-audio
14
+ - text-to-speech
15
+ - voice-cloning
16
+ - quantization
17
+ - nvfp4
18
+ - mxfp8
19
+ - blackwell
20
+ - sm120
21
+ - english
22
+ - v1
23
+ ---
24
+
25
+ <h1 align="center">V1 · Fish Audio S2-Pro · NVFP4 Balanced</h1>
26
+
27
+ <p align="center"><strong>A complete Blackwell-ready S2-Pro download:</strong> mixed native NVFP4/MXFP8 transformer weights, BF16 codec, tokenizer, pinned Fish Speech source, API server, web UI, and reproducibility checks.</p>
28
+
29
+ <p align="center"><strong>Balanced V1 prioritizes useful English quantization fidelity and VRAM reduction. This is not yet an XPO3 release.</strong></p>
30
+
31
+ <p align="center"><strong>An XPO3 version is coming soon.</strong> Follow <a href="https://huggingface.co/ajh-code">ajh-code on Hugging Face</a> and <a href="https://arands.com">Arands.com</a> for release updates.</p>
32
+
33
+ <p align="center">
34
+ <a href="https://huggingface.co/fishaudio/s2-pro">Original S2-Pro</a>
35
+ · <a href="https://github.com/fishaudio/fish-speech">Fish Speech</a>
36
+ · <a href="https://arands.com">Arands.com · updates</a>
37
+ </p>
38
+
39
+ ---
40
+
41
+ ## Download
42
+
43
+ | Component | Purpose | Size |
44
+ |:--|:--|--:|
45
+ | `model-*.safetensors` | Complete mixed NVFP4/MXFP8 transformer checkpoint | 4.90 GB |
46
+ | `codec.pth` | Complete BF16 S2-Pro DAC codec | 1.87 GB |
47
+ | Tokenizer, runtime, and pinned source | No separate base-model or codec download | ~24 MB |
48
+ | Complete repository | Weights, codec, runtime, source, and metadata | 6.80 GB |
49
+
50
+ All model and codec weights required by the server are in this repository.
51
+ The root `config.json` preserves the S2-Pro architecture metadata and adds the
52
+ mixed-precision policy, while Hugging Face metadata records this repository as
53
+ a quantization of [`fishaudio/s2-pro`](https://huggingface.co/fishaudio/s2-pro).
54
+
55
+ ## Quick start
56
+
57
+ Tested on Linux x86-64, Python 3.12, CUDA 13.0, PyTorch `2.11.0+cu130`,
58
+ `comfy-kitchen==0.2.22`, and NVIDIA Blackwell SM120. The current native path is
59
+ for GeForce RTX 50-series/SM120 GPUs; it is not a generic CUDA fallback.
60
+
61
+ ```bash
62
+ hf download ajh-code/Fish-Audio-S2-Pro-NVFP4-Balanced \
63
+ --local-dir fish-audio-s2-pro-nvfp4-balanced
64
+ cd fish-audio-s2-pro-nvfp4-balanced
65
+ ./install.sh
66
+ ./launch.sh
67
+ ```
68
+
69
+ Open <http://127.0.0.1:8080/ui> for the bundled zero-shot web interface. The
70
+ API listens on all interfaces by default; set `TTS_HOST=127.0.0.1` if it should
71
+ not be reachable from the local network. Protect or firewall the service before
72
+ exposing it beyond a trusted network.
73
+
74
+ Docker Compose is the recommended clean deployment when Docker, the NVIDIA
75
+ Container Toolkit, and a compatible driver are already configured:
76
+
77
+ ```bash
78
+ docker compose up --build
79
+ ```
80
+
81
+ This path passed a clean outer-Docker build, SM120 runtime launch, route/UI
82
+ checks, and a zero-shot API smoke test on an RTX 5080 with CUDA 13.0.
83
+
84
+ The image excludes the 6.8 GB model payload and mounts the downloaded repository
85
+ read-only, so rebuilding the runtime does not duplicate the weights inside the
86
+ image.
87
+
88
+ ## Zero-shot voice cloning
89
+
90
+ Use a clean, consented 10–30 second reference with one speaker and supply its
91
+ exact transcript:
92
+
93
+ ```bash
94
+ python client.py \
95
+ --url http://127.0.0.1:8080/v1/tts \
96
+ --reference-audio reference.wav \
97
+ --reference-text "The exact words spoken in reference.wav." \
98
+ --text "A few notes as this story begins." \
99
+ --seed 42 \
100
+ --output result.wav
101
+ ```
102
+
103
+ Equivalent JSON API call in Python:
104
+
105
+ ```python
106
+ import base64
107
+ from pathlib import Path
108
+
109
+ import requests
110
+
111
+ payload = {
112
+ "text": "A few notes as this story begins.",
113
+ "references": [{
114
+ "audio": base64.b64encode(Path("reference.wav").read_bytes()).decode(),
115
+ "text": "The exact words spoken in reference.wav.",
116
+ }],
117
+ "reference_id": None,
118
+ "format": "wav",
119
+ "streaming": False,
120
+ "normalize": True,
121
+ "max_new_tokens": 1024,
122
+ "chunk_length": 200,
123
+ "top_p": 0.9,
124
+ "temperature": 0.9,
125
+ "repetition_penalty": 1.1,
126
+ "seed": 42,
127
+ "use_memory_cache": "off",
128
+ }
129
+ response = requests.post("http://127.0.0.1:8080/v1/tts", json=payload, timeout=600)
130
+ response.raise_for_status()
131
+ Path("result.wav").write_bytes(response.content)
132
+ ```
133
+
134
+ Useful endpoints:
135
+
136
+ | Endpoint | Purpose |
137
+ |:--|:--|
138
+ | `GET /ui` | Bundled zero-shot web interface |
139
+ | `GET /v1/health` | Service health |
140
+ | `GET /v1/model` | Active release, quantization, and sampling metadata |
141
+ | `POST /v1/tts` | Fish Speech-compatible TTS request; returns audio |
142
+
143
+ Set `TTS_API_KEY` before launch to require bearer authentication. For an API
144
+ key named `secret`, send `Authorization: Bearer secret`.
145
+
146
+ ## Quantization policy
147
+
148
+ S2-Pro has 180 projections in its 36-layer slow transformer. V1 uses:
149
+
150
+ | Scope | Stored/executed precision | Count |
151
+ |:--|:--|--:|
152
+ | Gate/up in layers 3–32 | packed NVFP4 E2M1; W4A16 at `M=1`, W4A4 above `M=1` | 60 |
153
+ | Other slow-transformer projections | native dynamic MXFP8 W8A8 | 120 |
154
+ | Embeddings, tied text output, fast transformer/output, norms, RoPE, KV cache, sampling | BF16/original precision | — |
155
+ | DAC codec arithmetic | BF16 | — |
156
+
157
+ The English calibration scale is folded into the selected norm and packed
158
+ gate/up tensors. It adds no runtime tensor or operation. The original BF16
159
+ slow-projection weights are not retained as a second copy. V1's transformer
160
+ checkpoint is 46.25% smaller than the original transformer shards.
161
+
162
+ This is intentionally described as a mixed NVFP4/MXFP8 checkpoint. It is not a
163
+ claim that every operation, activation, or weight in the end-to-end TTS stack
164
+ runs at FP4.
165
+
166
+ ## Measured performance
167
+
168
+ Measurements below are local RTX 5080 results with the bundled compact BF16
169
+ codec path and a 3072-token cache. They are not universal performance claims.
170
+
171
+ | Measurement | V1 result |
172
+ |:--|--:|
173
+ | Loaded PyTorch allocation | 5.350 GiB |
174
+ | 15-sample short zero-shot peak | 5.607–5.769 GiB |
175
+ | Held-out ~39-second generation peak | 7.561 GiB |
176
+ | Median short/control real-time factor | about 1.05–1.06 |
177
+ | Median short/control time to first playable audio | about 5–6.5 s |
178
+ | Semantic generation throughput | about 20.4–20.6 frames/s |
179
+
180
+ The matching compact-runtime BF16 control loaded at 9.273 GiB, so V1 reduced
181
+ loaded PyTorch allocation by 42.31%. V1 is near real time on the RTX 5080, but
182
+ the current ordinary single-speaker API waits for a complete semantic segment
183
+ before playable audio. This release therefore does **not** claim agent-grade
184
+ low-latency streaming. An RTX 5060 Ti focused zero-shot run measured about 2.06
185
+ RTF and is not a real-time path.
186
+
187
+ ## Limited blind voice-cloning test
188
+
189
+ The first blind comparison is encouraging, but deliberately small. It used one
190
+ listener, one consented English reference speaker, and four matched BF16/V1
191
+ pairs: conversational, reflective, question-shaped, and long narrative prompts
192
+ at seeds 7, 17, 123, and 42. Both models used the same reference, runtime path,
193
+ `temperature=0.9`, `top_p=0.9`, and `top_k=30`.
194
+
195
+ | Blind result | BF16 | Balanced V1 |
196
+ |:--|--:|--:|
197
+ | Speaker-likeness scores | all four 5/5 | all four 5/5 |
198
+ | Mean reference-style likeness | 4.50 / 5 | 4.50 / 5 |
199
+ | Mean naturalness | 3.75 / 5 | 3.75 / 5 |
200
+ | Pair preference | 1 | 2 |
201
+
202
+ The fourth pair was tied. The only severe artifact reported in the set was a
203
+ deterministic BF16 pitch squeak in the long seed-42 sample; its V1 counterpart
204
+ did not contain that excursion.
205
+
206
+ This test suggests that the quant did not cause a detectable speaker-identity
207
+ loss for that reference. It is **not** a general MOS study or broad cloning
208
+ qualification: more listeners, speakers, accents, recording conditions, and
209
+ languages are still needed. The release therefore reports the result without
210
+ claiming parity in every voice-cloning setting.
211
+
212
+ ## Validated scope
213
+
214
+ | Gate | Result |
215
+ |:--|:--|
216
+ | Native execution | 60 NVFP4 and 120 MXFP8 projections execute through native SM120 paths |
217
+ | Standalone packaging | Fresh load from these shards, without BF16 source projections, matched a frozen 64-frame code canary bit exactly |
218
+ | English automated gates | Passed fixed-input signal/spectral, ASR, speaker-embedding, short/control, and held-out long-termination screens |
219
+ | Blind English clone identity | Limited four-pair test above: every BF16 and V1 sample scored 5/5 speaker likeness; preferences were V1 2, BF16 1, tie 1 |
220
+ | Multilingual | Not qualified; use an MXFP8 or BF16 model when language coverage matters |
221
+ | Hardware | NVIDIA Blackwell SM120 only in V1 |
222
+
223
+ The blind result supports quantization fidelity for that English reference; it
224
+ does not establish universal cloning quality across voices, recording
225
+ conditions, accents, or languages.
226
+
227
+ ## Known limitations
228
+
229
+ - Fish S2-Pro itself sounded substantially flatter and less expressive than
230
+ VoxCPM2 in our reference comparison. BF16 shared this behavior, so V1 does
231
+ not treat it as NVFP4-specific damage and does not claim to fix it.
232
+ - Inline emotion/style instructions change output trajectories but did not
233
+ reliably repair the perceived flatness in the tested voice.
234
+ - The objective speaker embedding saturated near 0.99 and failed to predict
235
+ human preference; human listening remains required for new voices.
236
+ - One matched long BF16 sample produced a deterministic pitch squeak while its
237
+ V1 counterpart did not. This is evidence from one seed, not a claim that V1
238
+ is generally more artifact-free than BF16.
239
+ - Long-form peak memory is materially higher than loaded memory. Do not market
240
+ V1 as a sub-6-GiB operational model for arbitrary request lengths.
241
+
242
+ These bounded claims are why this package is **Balanced V1**, not an XPO3
243
+ speed/quality/size release. Follow
244
+ [`ajh-code`](https://huggingface.co/ajh-code) for the upcoming XPO3 version.
245
+
246
+ ## Validate the download
247
+
248
+ ```bash
249
+ python validate_release.py
250
+ ```
251
+
252
+ `MANIFEST.json` records the byte size and SHA-256 of every distributed file
253
+ except itself. Validation also checks the safetensors index/header mapping,
254
+ the 60/120 NVFP4/MXFP8 tensor counts, source pins, license/notice files, and
255
+ runtime payload. Hashing the 6.8 GB package takes a little while.
256
+
257
+ For an additional hash check every time the service loads:
258
+
259
+ ```bash
260
+ TTS_VERIFY_CHECKSUMS=1 ./launch.sh
261
+ ```
262
+
263
+ ## License and attribution
264
+
265
+ **Built with Fish Audio.** This derivative is governed by the
266
+ [Fish Audio Research License](./LICENSE.md). Research and non-commercial use
267
+ are permitted subject to its terms. **Commercial use requires a separate
268
+ written license from Fish Audio; no commercial rights are granted by this
269
+ repository.** See [`Notice`](./Notice) for the required attribution and exact
270
+ change statement, and [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md) for
271
+ runtime dependencies.
272
+
273
+ Use only voices and recordings you have the right and consent to use.
THIRD_PARTY_NOTICES.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Third-party notices
2
+
3
+ ## Fish Audio S2-Pro and Fish Speech
4
+
5
+ The model weights, codec, tokenizer, configuration, and bundled Fish Speech
6
+ source derive from Fish Audio materials. They are governed by the Fish Audio
7
+ Research License in `LICENSE.md`. The required Fish attribution and the changes
8
+ made for this derivative are recorded in `Notice`.
9
+
10
+ ## comfy-kitchen
11
+
12
+ The runtime depends on `comfy-kitchen==0.2.22`, distributed separately under
13
+ Apache-2.0. Project: <https://github.com/Comfy-Org/comfy-kitchen>.
14
+
15
+ ## fish-scales-ops
16
+
17
+ The runtime builds pinned revision
18
+ `a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded` of `fish-scales-ops`, distributed
19
+ separately under Apache-2.0. Project:
20
+ <https://github.com/fishaudio/fish-scales-ops>.
21
+
22
+ ## Native NVFP4 helper kernels
23
+
24
+ The source under `runtime/native/` was adapted from the Apache-2.0 Mage-VL
25
+ NVFP4 runtime at revision `7a03467b90d6feff6bd196928dfe156bd173f36e`.
26
+ Its Apache-2.0 license is included at `runtime/native/LICENSE`.
27
+
28
+ No third-party project listed here endorses this derivative release.
activation-scaling-report.json ADDED
The diff for this file is too large to render. See raw diff
 
chat_template.jinja ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
27
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
28
+ {%- elif message.role == "assistant" %}
29
+ {%- set content = message.content %}
30
+ {%- set reasoning_content = '' %}
31
+ {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
32
+ {%- set reasoning_content = message.reasoning_content %}
33
+ {%- else %}
34
+ {%- if '</think>' in message.content %}
35
+ {%- set content = message.content.split('</think>')[-1].lstrip('\n') %}
36
+ {%- set reasoning_content = message.content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
37
+ {%- endif %}
38
+ {%- endif %}
39
+ {%- if loop.index0 > ns.last_query_index %}
40
+ {%- if loop.last or (not loop.last and reasoning_content) %}
41
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
42
+ {%- else %}
43
+ {{- '<|im_start|>' + message.role + '\n' + content }}
44
+ {%- endif %}
45
+ {%- else %}
46
+ {{- '<|im_start|>' + message.role + '\n' + content }}
47
+ {%- endif %}
48
+ {%- if message.tool_calls %}
49
+ {%- for tool_call in message.tool_calls %}
50
+ {%- if (loop.first and content) or (not loop.first) %}
51
+ {{- '\n' }}
52
+ {%- endif %}
53
+ {%- if tool_call.function %}
54
+ {%- set tool_call = tool_call.function %}
55
+ {%- endif %}
56
+ {{- '<tool_call>\n{"name": "' }}
57
+ {{- tool_call.name }}
58
+ {{- '", "arguments": ' }}
59
+ {%- if tool_call.arguments is string %}
60
+ {{- tool_call.arguments }}
61
+ {%- else %}
62
+ {{- tool_call.arguments | tojson }}
63
+ {%- endif %}
64
+ {{- '}\n</tool_call>' }}
65
+ {%- endfor %}
66
+ {%- endif %}
67
+ {{- '<|im_end|>\n' }}
68
+ {%- elif message.role == "tool" %}
69
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
70
+ {{- '<|im_start|>user' }}
71
+ {%- endif %}
72
+ {{- '\n<tool_response>\n' }}
73
+ {{- message.content }}
74
+ {{- '\n</tool_response>' }}
75
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
76
+ {{- '<|im_end|>\n' }}
77
+ {%- endif %}
78
+ {%- endif %}
79
+ {%- endfor %}
80
+ {%- if add_generation_prompt %}
81
+ {{- '<|im_start|>assistant\n' }}
82
+ {%- if enable_thinking is defined and enable_thinking is false %}
83
+ {{- '<think>\n\n</think>\n\n' }}
84
+ {%- endif %}
85
+ {%- endif %}
client.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Call a project Fish TTS API with a zero-shot voice or saved reference ID."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import base64
8
+ from pathlib import Path
9
+
10
+ import requests
11
+
12
+
13
+ def parse_args() -> argparse.Namespace:
14
+ parser = argparse.ArgumentParser(description=__doc__)
15
+ parser.add_argument("--url", default="http://127.0.0.1:8080/v1/tts")
16
+ parser.add_argument("--text", required=True)
17
+ voice = parser.add_mutually_exclusive_group()
18
+ voice.add_argument("--reference-audio", type=Path)
19
+ voice.add_argument("--reference-id")
20
+ parser.add_argument("--reference-text")
21
+ parser.add_argument("--output", type=Path, default=Path("output.wav"))
22
+ parser.add_argument("--api-key")
23
+ parser.add_argument("--seed", type=int)
24
+ parser.add_argument("--max-new-tokens", type=int, default=1024)
25
+ parser.add_argument("--chunk-length", type=int, default=200)
26
+ parser.add_argument("--top-p", type=float, default=0.9)
27
+ parser.add_argument("--temperature", type=float, default=0.9)
28
+ parser.add_argument("--repetition-penalty", type=float, default=1.1)
29
+ parser.add_argument(
30
+ "--normalize",
31
+ action=argparse.BooleanOptionalAction,
32
+ default=True,
33
+ help="Enable or disable API loudness normalization",
34
+ )
35
+ parser.add_argument(
36
+ "--use-memory-cache",
37
+ choices=("on", "off"),
38
+ default="on",
39
+ help="Reuse cached reference codes/text, or force a fresh reference encode",
40
+ )
41
+ return parser.parse_args()
42
+
43
+
44
+ def main() -> int:
45
+ args = parse_args()
46
+ references = []
47
+ if args.reference_audio is not None:
48
+ if not args.reference_audio.is_file():
49
+ raise SystemExit(f"Reference audio is missing: {args.reference_audio}")
50
+ if not args.reference_text or not args.reference_text.strip():
51
+ raise SystemExit("--reference-text is required with --reference-audio")
52
+ references.append(
53
+ {
54
+ "audio": base64.b64encode(args.reference_audio.read_bytes()).decode(
55
+ "ascii"
56
+ ),
57
+ "text": args.reference_text,
58
+ }
59
+ )
60
+ elif args.reference_text:
61
+ raise SystemExit("--reference-text requires --reference-audio")
62
+
63
+ payload = {
64
+ "text": args.text,
65
+ "references": references,
66
+ "reference_id": args.reference_id,
67
+ "format": "wav",
68
+ "streaming": False,
69
+ "normalize": args.normalize,
70
+ "max_new_tokens": args.max_new_tokens,
71
+ "chunk_length": args.chunk_length,
72
+ "top_p": args.top_p,
73
+ "temperature": args.temperature,
74
+ "repetition_penalty": args.repetition_penalty,
75
+ "seed": args.seed,
76
+ "use_memory_cache": args.use_memory_cache,
77
+ }
78
+ headers = {"Accept": "audio/wav"}
79
+ if args.api_key:
80
+ headers["Authorization"] = f"Bearer {args.api_key}"
81
+ response = requests.post(
82
+ args.url,
83
+ json=payload,
84
+ headers=headers,
85
+ timeout=600,
86
+ )
87
+ if response.status_code != 200:
88
+ raise SystemExit(
89
+ f"TTS request failed ({response.status_code}): {response.text[:2000]}"
90
+ )
91
+ content_type = response.headers.get("content-type", "")
92
+ if "audio/" not in content_type and not response.content.startswith(b"RIFF"):
93
+ raise SystemExit(f"Unexpected response content type: {content_type}")
94
+ args.output.parent.mkdir(parents=True, exist_ok=True)
95
+ args.output.write_bytes(response.content)
96
+ print(f"audio={args.output}")
97
+ print(f"bytes={len(response.content)}")
98
+ return 0
99
+
100
+
101
+ if __name__ == "__main__":
102
+ raise SystemExit(main())
compose.yaml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ tts:
3
+ build:
4
+ context: .
5
+ dockerfile: Dockerfile
6
+ image: fish-audio-s2-pro-nvfp4-balanced:v1-cu130
7
+ init: true
8
+ gpus: all
9
+ shm_size: 8gb
10
+ ports:
11
+ - "${TTS_PORT:-8080}:8080"
12
+ volumes:
13
+ - .:/model:ro
14
+ - ./runtime-data:/data
15
+ environment:
16
+ TTS_HOST: 0.0.0.0
17
+ TTS_PORT: 8080
18
+ TTS_DEVICE: ${TTS_DEVICE:-cuda:0}
19
+ TTS_CACHE_LENGTH: ${TTS_CACHE_LENGTH:-3072}
20
+ TTS_RUNTIME_DATA: /data
21
+ TTS_VERIFY_CHECKSUMS: ${TTS_VERIFY_CHECKSUMS:-0}
22
+ TTS_API_KEY: ${TTS_API_KEY:-}
23
+ MAX_JOBS: ${MAX_JOBS:-2}
24
+ restart: unless-stopped
config.json ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "audio_decoder_config": {
3
+ "attention_o_bias": false,
4
+ "attention_qk_norm": false,
5
+ "attention_qkv_bias": false,
6
+ "audio_hidden_dim": 5120,
7
+ "dim": 2560,
8
+ "dropout": 0.0,
9
+ "head_dim": 128,
10
+ "initializer_range": 0.01976423537605237,
11
+ "intermediate_size": 9728,
12
+ "max_seq_len": 11,
13
+ "model_type": "fish_qwen3_audio_decoder",
14
+ "moe_intermediate_size": 768,
15
+ "n_head": 32,
16
+ "n_layer": 4,
17
+ "n_local_heads": 8,
18
+ "norm_eps": 1e-06,
19
+ "norm_topk_prob": true,
20
+ "num_codebooks": 10,
21
+ "num_experts": 1,
22
+ "num_experts_per_tok": 1,
23
+ "rope_base": 1000000,
24
+ "router_gamma": 0.001,
25
+ "text_dim": 2560,
26
+ "tie_word_embeddings": false,
27
+ "use_aux_loss_free": false,
28
+ "use_bfloat16": false,
29
+ "use_gradient_checkpointing": true,
30
+ "use_moe": false,
31
+ "vocab_size": 4096
32
+ },
33
+ "audio_pad_token_id": 151677,
34
+ "dtype": "bfloat16",
35
+ "eos_token_id": 151645,
36
+ "model_type": "fish_qwen3_omni",
37
+ "pad_token_id": 151669,
38
+ "semantic_end_token_id": 155773,
39
+ "semantic_start_token_id": 151678,
40
+ "fish_s2_quantization": {
41
+ "format": "mixed_nvfp4_mxfp8",
42
+ "profile": "balanced",
43
+ "release": "v1",
44
+ "policy": "w4a16_gate_up_middle30_mxfp8_rest",
45
+ "nvfp4_modules": 60,
46
+ "mxfp8_modules": 120,
47
+ "runtime": "bundled",
48
+ "hardware_family": "sm_120"
49
+ },
50
+ "text_config": {
51
+ "attention_o_bias": false,
52
+ "attention_qk_norm": true,
53
+ "attention_qkv_bias": false,
54
+ "audio_hidden_dim": 5120,
55
+ "dim": 2560,
56
+ "dropout": 0.0,
57
+ "head_dim": 128,
58
+ "initializer_range": 0.01976423537605237,
59
+ "intermediate_size": 9728,
60
+ "max_seq_len": 32768,
61
+ "model_type": "fish_qwen3",
62
+ "moe_intermediate_size": 768,
63
+ "n_head": 32,
64
+ "n_layer": 36,
65
+ "n_local_heads": 8,
66
+ "norm_eps": 1e-06,
67
+ "norm_topk_prob": true,
68
+ "num_experts": 1,
69
+ "num_experts_per_tok": 1,
70
+ "rope_base": 1000000,
71
+ "router_gamma": 0.001,
72
+ "tie_word_embeddings": true,
73
+ "use_aux_loss_free": false,
74
+ "use_bfloat16": false,
75
+ "use_gradient_checkpointing": true,
76
+ "use_moe": false,
77
+ "vocab_size": 155776
78
+ },
79
+ "transformers_version": "4.57.1"
80
+ }
install.sh ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ release_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ python_bin="${PYTHON_BIN:-python3.12}"
6
+ venv_dir="${release_root}/.venv"
7
+ build_dir="${release_root}/.build"
8
+ scales_revision="a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded"
9
+ scales_dir="${build_dir}/fish-scales-ops-${scales_revision}"
10
+ cuda_root="${CUDA_HOME:-/usr/local/cuda}"
11
+
12
+ for command_name in "${python_bin}" git; do
13
+ if ! command -v "${command_name}" >/dev/null 2>&1; then
14
+ echo "Missing required command: ${command_name}" >&2
15
+ exit 1
16
+ fi
17
+ done
18
+ if [[ ! -x "${cuda_root}/bin/nvcc" ]]; then
19
+ echo "CUDA compiler not found at ${cuda_root}/bin/nvcc" >&2
20
+ exit 1
21
+ fi
22
+
23
+ mkdir -p "${build_dir}" "${release_root}/runtime-data/torch-extensions"
24
+ if [[ ! -x "${venv_dir}/bin/python" ]]; then
25
+ "${python_bin}" -m venv "${venv_dir}"
26
+ fi
27
+ "${venv_dir}/bin/python" -m pip install --upgrade "pip>=25" "uv==0.12.3"
28
+ uv_bin="${venv_dir}/bin/uv"
29
+
30
+ "${uv_bin}" pip install --python "${venv_dir}/bin/python" \
31
+ "setuptools>=75" wheel ninja packaging \
32
+ "torch==2.11.0" "torchaudio==2.11.0" \
33
+ --torch-backend=cu130
34
+ "${uv_bin}" pip install --python "${venv_dir}/bin/python" \
35
+ --overrides "${release_root}/runtime/torch-overrides.txt" \
36
+ --torch-backend=cu130 \
37
+ "${release_root}/vendor/fish-speech" \
38
+ -r "${release_root}/requirements.txt"
39
+
40
+ if [[ ! -d "${scales_dir}/.git" ]]; then
41
+ if [[ -e "${scales_dir}" ]]; then
42
+ echo "${scales_dir} exists but is not the expected Git checkout; move it aside and retry." >&2
43
+ exit 1
44
+ fi
45
+ git init "${scales_dir}"
46
+ git -C "${scales_dir}" remote add origin https://github.com/fishaudio/fish-scales-ops.git
47
+ git -C "${scales_dir}" fetch --depth 1 origin "${scales_revision}"
48
+ git -C "${scales_dir}" checkout --detach FETCH_HEAD
49
+ git -C "${scales_dir}" submodule update --init --recursive --depth 1
50
+ fi
51
+ if [[ "$(git -C "${scales_dir}" rev-parse HEAD)" != "${scales_revision}" ]]; then
52
+ echo "Unexpected fish-scales-ops revision in ${scales_dir}" >&2
53
+ exit 1
54
+ fi
55
+ git -C "${scales_dir}" submodule update --init --recursive --depth 1
56
+
57
+ CUTLASS_DIR="${scales_dir}/3rdparty/cutlass" \
58
+ CUDA_HOME="${cuda_root}" \
59
+ MAX_JOBS="${MAX_JOBS:-2}" \
60
+ TORCH_CUDA_ARCH_LIST=12.0a \
61
+ "${uv_bin}" pip install --python "${venv_dir}/bin/python" \
62
+ --no-build-isolation "${scales_dir}/python"
63
+
64
+ "${venv_dir}/bin/python" -c \
65
+ "import comfy_kitchen, fish_scales_ops, fish_speech, torch; print('installed', torch.__version__, torch.version.cuda)"
66
+ echo "Installation complete. Start the service with ./launch.sh"
launch.sh ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ release_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ python_bin="${TTS_PYTHON:-${release_root}/.venv/bin/python}"
6
+ listen_host="${TTS_HOST:-0.0.0.0}"
7
+ listen_port="${TTS_PORT:-8080}"
8
+ device_name="${TTS_DEVICE:-cuda:0}"
9
+ cache_length="${TTS_CACHE_LENGTH:-3072}"
10
+ runtime_data="${TTS_RUNTIME_DATA:-${release_root}/runtime-data}"
11
+
12
+ if [[ ! -x "${python_bin}" ]]; then
13
+ echo "Python environment not found at ${python_bin}; run ./install.sh first." >&2
14
+ exit 1
15
+ fi
16
+ mkdir -p "${runtime_data}/references" "${runtime_data}/torch-extensions"
17
+
18
+ export FISH_NVFP4_ROOT="${release_root}"
19
+ export FISH_NVFP4_BUILD_ROOT="${runtime_data}/torch-extensions"
20
+ export PYTHONPATH="${release_root}/runtime${PYTHONPATH:+:${PYTHONPATH}}"
21
+ export TEMPORARILY_DISABLE_PROTOBUF_VERSION_CHECK=true
22
+ export TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST:-12.0a}"
23
+
24
+ server_args=(
25
+ "${release_root}/runtime/server.py"
26
+ --checkpoint "${release_root}"
27
+ --host "${listen_host}"
28
+ --port "${listen_port}"
29
+ --device "${device_name}"
30
+ --cache-length "${cache_length}"
31
+ )
32
+ if [[ "${TTS_VERIFY_CHECKSUMS:-0}" == "1" ]]; then
33
+ server_args+=(--verify-checksums)
34
+ fi
35
+ if [[ -n "${TTS_API_KEY:-}" ]]; then
36
+ server_args+=(--api-key "${TTS_API_KEY}")
37
+ fi
38
+
39
+ cd "${runtime_data}"
40
+ exec "${python_bin}" "${server_args[@]}"
model.safetensors.index.json ADDED
@@ -0,0 +1,605 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "total_size": 4903514352
4
+ },
5
+ "weight_map": {
6
+ "embeddings.weight": "model-00001-of-00003.safetensors",
7
+ "codebook_embeddings.weight": "model-00001-of-00003.safetensors",
8
+ "layers.0.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
9
+ "layers.0.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
10
+ "layers.0.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
11
+ "layers.0.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
12
+ "layers.0.attention.q_norm.weight": "model-00001-of-00003.safetensors",
13
+ "layers.0.attention.k_norm.weight": "model-00001-of-00003.safetensors",
14
+ "layers.0.feed_forward.w1.weight_fp8": "model-00001-of-00003.safetensors",
15
+ "layers.0.feed_forward.w1.weight_scale_storage": "model-00001-of-00003.safetensors",
16
+ "layers.0.feed_forward.w3.weight_fp8": "model-00001-of-00003.safetensors",
17
+ "layers.0.feed_forward.w3.weight_scale_storage": "model-00001-of-00003.safetensors",
18
+ "layers.0.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
19
+ "layers.0.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
20
+ "layers.0.ffn_norm.weight": "model-00001-of-00003.safetensors",
21
+ "layers.0.attention_norm.weight": "model-00001-of-00003.safetensors",
22
+ "layers.1.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
23
+ "layers.1.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
24
+ "layers.1.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
25
+ "layers.1.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
26
+ "layers.1.attention.q_norm.weight": "model-00001-of-00003.safetensors",
27
+ "layers.1.attention.k_norm.weight": "model-00001-of-00003.safetensors",
28
+ "layers.1.feed_forward.w1.weight_fp8": "model-00001-of-00003.safetensors",
29
+ "layers.1.feed_forward.w1.weight_scale_storage": "model-00001-of-00003.safetensors",
30
+ "layers.1.feed_forward.w3.weight_fp8": "model-00001-of-00003.safetensors",
31
+ "layers.1.feed_forward.w3.weight_scale_storage": "model-00001-of-00003.safetensors",
32
+ "layers.1.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
33
+ "layers.1.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
34
+ "layers.1.ffn_norm.weight": "model-00001-of-00003.safetensors",
35
+ "layers.1.attention_norm.weight": "model-00001-of-00003.safetensors",
36
+ "layers.2.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
37
+ "layers.2.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
38
+ "layers.2.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
39
+ "layers.2.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
40
+ "layers.2.attention.q_norm.weight": "model-00001-of-00003.safetensors",
41
+ "layers.2.attention.k_norm.weight": "model-00001-of-00003.safetensors",
42
+ "layers.2.feed_forward.w1.weight_fp8": "model-00001-of-00003.safetensors",
43
+ "layers.2.feed_forward.w1.weight_scale_storage": "model-00001-of-00003.safetensors",
44
+ "layers.2.feed_forward.w3.weight_fp8": "model-00001-of-00003.safetensors",
45
+ "layers.2.feed_forward.w3.weight_scale_storage": "model-00001-of-00003.safetensors",
46
+ "layers.2.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
47
+ "layers.2.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
48
+ "layers.2.ffn_norm.weight": "model-00001-of-00003.safetensors",
49
+ "layers.2.attention_norm.weight": "model-00001-of-00003.safetensors",
50
+ "layers.3.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
51
+ "layers.3.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
52
+ "layers.3.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
53
+ "layers.3.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
54
+ "layers.3.attention.q_norm.weight": "model-00001-of-00003.safetensors",
55
+ "layers.3.attention.k_norm.weight": "model-00001-of-00003.safetensors",
56
+ "layers.3.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
57
+ "layers.3.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
58
+ "layers.3.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
59
+ "layers.3.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
60
+ "layers.3.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
61
+ "layers.3.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
62
+ "layers.3.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
63
+ "layers.3.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
64
+ "layers.3.ffn_norm.weight": "model-00001-of-00003.safetensors",
65
+ "layers.3.attention_norm.weight": "model-00001-of-00003.safetensors",
66
+ "layers.4.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
67
+ "layers.4.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
68
+ "layers.4.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
69
+ "layers.4.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
70
+ "layers.4.attention.q_norm.weight": "model-00001-of-00003.safetensors",
71
+ "layers.4.attention.k_norm.weight": "model-00001-of-00003.safetensors",
72
+ "layers.4.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
73
+ "layers.4.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
74
+ "layers.4.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
75
+ "layers.4.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
76
+ "layers.4.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
77
+ "layers.4.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
78
+ "layers.4.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
79
+ "layers.4.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
80
+ "layers.4.ffn_norm.weight": "model-00001-of-00003.safetensors",
81
+ "layers.4.attention_norm.weight": "model-00001-of-00003.safetensors",
82
+ "layers.5.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
83
+ "layers.5.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
84
+ "layers.5.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
85
+ "layers.5.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
86
+ "layers.5.attention.q_norm.weight": "model-00001-of-00003.safetensors",
87
+ "layers.5.attention.k_norm.weight": "model-00001-of-00003.safetensors",
88
+ "layers.5.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
89
+ "layers.5.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
90
+ "layers.5.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
91
+ "layers.5.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
92
+ "layers.5.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
93
+ "layers.5.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
94
+ "layers.5.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
95
+ "layers.5.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
96
+ "layers.5.ffn_norm.weight": "model-00001-of-00003.safetensors",
97
+ "layers.5.attention_norm.weight": "model-00001-of-00003.safetensors",
98
+ "layers.6.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
99
+ "layers.6.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
100
+ "layers.6.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
101
+ "layers.6.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
102
+ "layers.6.attention.q_norm.weight": "model-00001-of-00003.safetensors",
103
+ "layers.6.attention.k_norm.weight": "model-00001-of-00003.safetensors",
104
+ "layers.6.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
105
+ "layers.6.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
106
+ "layers.6.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
107
+ "layers.6.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
108
+ "layers.6.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
109
+ "layers.6.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
110
+ "layers.6.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
111
+ "layers.6.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
112
+ "layers.6.ffn_norm.weight": "model-00001-of-00003.safetensors",
113
+ "layers.6.attention_norm.weight": "model-00001-of-00003.safetensors",
114
+ "layers.7.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
115
+ "layers.7.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
116
+ "layers.7.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
117
+ "layers.7.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
118
+ "layers.7.attention.q_norm.weight": "model-00001-of-00003.safetensors",
119
+ "layers.7.attention.k_norm.weight": "model-00001-of-00003.safetensors",
120
+ "layers.7.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
121
+ "layers.7.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
122
+ "layers.7.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
123
+ "layers.7.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
124
+ "layers.7.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
125
+ "layers.7.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
126
+ "layers.7.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
127
+ "layers.7.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
128
+ "layers.7.ffn_norm.weight": "model-00001-of-00003.safetensors",
129
+ "layers.7.attention_norm.weight": "model-00001-of-00003.safetensors",
130
+ "layers.8.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
131
+ "layers.8.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
132
+ "layers.8.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
133
+ "layers.8.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
134
+ "layers.8.attention.q_norm.weight": "model-00001-of-00003.safetensors",
135
+ "layers.8.attention.k_norm.weight": "model-00001-of-00003.safetensors",
136
+ "layers.8.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
137
+ "layers.8.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
138
+ "layers.8.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
139
+ "layers.8.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
140
+ "layers.8.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
141
+ "layers.8.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
142
+ "layers.8.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
143
+ "layers.8.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
144
+ "layers.8.ffn_norm.weight": "model-00001-of-00003.safetensors",
145
+ "layers.8.attention_norm.weight": "model-00001-of-00003.safetensors",
146
+ "layers.9.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
147
+ "layers.9.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
148
+ "layers.9.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
149
+ "layers.9.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
150
+ "layers.9.attention.q_norm.weight": "model-00001-of-00003.safetensors",
151
+ "layers.9.attention.k_norm.weight": "model-00001-of-00003.safetensors",
152
+ "layers.9.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
153
+ "layers.9.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
154
+ "layers.9.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
155
+ "layers.9.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
156
+ "layers.9.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
157
+ "layers.9.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
158
+ "layers.9.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
159
+ "layers.9.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
160
+ "layers.9.ffn_norm.weight": "model-00001-of-00003.safetensors",
161
+ "layers.9.attention_norm.weight": "model-00001-of-00003.safetensors",
162
+ "layers.10.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
163
+ "layers.10.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
164
+ "layers.10.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
165
+ "layers.10.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
166
+ "layers.10.attention.q_norm.weight": "model-00001-of-00003.safetensors",
167
+ "layers.10.attention.k_norm.weight": "model-00001-of-00003.safetensors",
168
+ "layers.10.feed_forward.w1.qdata": "model-00001-of-00003.safetensors",
169
+ "layers.10.feed_forward.w1.weight_block_scale": "model-00001-of-00003.safetensors",
170
+ "layers.10.feed_forward.w1.weight_scale": "model-00001-of-00003.safetensors",
171
+ "layers.10.feed_forward.w3.qdata": "model-00001-of-00003.safetensors",
172
+ "layers.10.feed_forward.w3.weight_block_scale": "model-00001-of-00003.safetensors",
173
+ "layers.10.feed_forward.w3.weight_scale": "model-00001-of-00003.safetensors",
174
+ "layers.10.feed_forward.w2.weight_fp8": "model-00001-of-00003.safetensors",
175
+ "layers.10.feed_forward.w2.weight_scale_storage": "model-00001-of-00003.safetensors",
176
+ "layers.10.ffn_norm.weight": "model-00001-of-00003.safetensors",
177
+ "layers.10.attention_norm.weight": "model-00001-of-00003.safetensors",
178
+ "layers.11.attention.wqkv.weight_fp8": "model-00001-of-00003.safetensors",
179
+ "layers.11.attention.wqkv.weight_scale_storage": "model-00001-of-00003.safetensors",
180
+ "layers.11.attention.wo.weight_fp8": "model-00001-of-00003.safetensors",
181
+ "layers.11.attention.wo.weight_scale_storage": "model-00001-of-00003.safetensors",
182
+ "layers.11.attention.q_norm.weight": "model-00001-of-00003.safetensors",
183
+ "layers.11.attention.k_norm.weight": "model-00001-of-00003.safetensors",
184
+ "layers.11.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
185
+ "layers.11.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
186
+ "layers.11.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
187
+ "layers.11.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
188
+ "layers.11.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
189
+ "layers.11.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
190
+ "layers.11.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
191
+ "layers.11.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
192
+ "layers.11.ffn_norm.weight": "model-00002-of-00003.safetensors",
193
+ "layers.11.attention_norm.weight": "model-00002-of-00003.safetensors",
194
+ "layers.12.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
195
+ "layers.12.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
196
+ "layers.12.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
197
+ "layers.12.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
198
+ "layers.12.attention.q_norm.weight": "model-00002-of-00003.safetensors",
199
+ "layers.12.attention.k_norm.weight": "model-00002-of-00003.safetensors",
200
+ "layers.12.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
201
+ "layers.12.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
202
+ "layers.12.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
203
+ "layers.12.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
204
+ "layers.12.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
205
+ "layers.12.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
206
+ "layers.12.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
207
+ "layers.12.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
208
+ "layers.12.ffn_norm.weight": "model-00002-of-00003.safetensors",
209
+ "layers.12.attention_norm.weight": "model-00002-of-00003.safetensors",
210
+ "layers.13.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
211
+ "layers.13.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
212
+ "layers.13.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
213
+ "layers.13.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
214
+ "layers.13.attention.q_norm.weight": "model-00002-of-00003.safetensors",
215
+ "layers.13.attention.k_norm.weight": "model-00002-of-00003.safetensors",
216
+ "layers.13.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
217
+ "layers.13.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
218
+ "layers.13.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
219
+ "layers.13.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
220
+ "layers.13.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
221
+ "layers.13.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
222
+ "layers.13.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
223
+ "layers.13.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
224
+ "layers.13.ffn_norm.weight": "model-00002-of-00003.safetensors",
225
+ "layers.13.attention_norm.weight": "model-00002-of-00003.safetensors",
226
+ "layers.14.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
227
+ "layers.14.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
228
+ "layers.14.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
229
+ "layers.14.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
230
+ "layers.14.attention.q_norm.weight": "model-00002-of-00003.safetensors",
231
+ "layers.14.attention.k_norm.weight": "model-00002-of-00003.safetensors",
232
+ "layers.14.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
233
+ "layers.14.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
234
+ "layers.14.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
235
+ "layers.14.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
236
+ "layers.14.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
237
+ "layers.14.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
238
+ "layers.14.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
239
+ "layers.14.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
240
+ "layers.14.ffn_norm.weight": "model-00002-of-00003.safetensors",
241
+ "layers.14.attention_norm.weight": "model-00002-of-00003.safetensors",
242
+ "layers.15.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
243
+ "layers.15.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
244
+ "layers.15.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
245
+ "layers.15.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
246
+ "layers.15.attention.q_norm.weight": "model-00002-of-00003.safetensors",
247
+ "layers.15.attention.k_norm.weight": "model-00002-of-00003.safetensors",
248
+ "layers.15.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
249
+ "layers.15.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
250
+ "layers.15.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
251
+ "layers.15.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
252
+ "layers.15.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
253
+ "layers.15.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
254
+ "layers.15.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
255
+ "layers.15.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
256
+ "layers.15.ffn_norm.weight": "model-00002-of-00003.safetensors",
257
+ "layers.15.attention_norm.weight": "model-00002-of-00003.safetensors",
258
+ "layers.16.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
259
+ "layers.16.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
260
+ "layers.16.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
261
+ "layers.16.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
262
+ "layers.16.attention.q_norm.weight": "model-00002-of-00003.safetensors",
263
+ "layers.16.attention.k_norm.weight": "model-00002-of-00003.safetensors",
264
+ "layers.16.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
265
+ "layers.16.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
266
+ "layers.16.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
267
+ "layers.16.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
268
+ "layers.16.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
269
+ "layers.16.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
270
+ "layers.16.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
271
+ "layers.16.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
272
+ "layers.16.ffn_norm.weight": "model-00002-of-00003.safetensors",
273
+ "layers.16.attention_norm.weight": "model-00002-of-00003.safetensors",
274
+ "layers.17.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
275
+ "layers.17.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
276
+ "layers.17.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
277
+ "layers.17.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
278
+ "layers.17.attention.q_norm.weight": "model-00002-of-00003.safetensors",
279
+ "layers.17.attention.k_norm.weight": "model-00002-of-00003.safetensors",
280
+ "layers.17.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
281
+ "layers.17.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
282
+ "layers.17.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
283
+ "layers.17.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
284
+ "layers.17.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
285
+ "layers.17.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
286
+ "layers.17.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
287
+ "layers.17.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
288
+ "layers.17.ffn_norm.weight": "model-00002-of-00003.safetensors",
289
+ "layers.17.attention_norm.weight": "model-00002-of-00003.safetensors",
290
+ "layers.18.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
291
+ "layers.18.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
292
+ "layers.18.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
293
+ "layers.18.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
294
+ "layers.18.attention.q_norm.weight": "model-00002-of-00003.safetensors",
295
+ "layers.18.attention.k_norm.weight": "model-00002-of-00003.safetensors",
296
+ "layers.18.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
297
+ "layers.18.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
298
+ "layers.18.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
299
+ "layers.18.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
300
+ "layers.18.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
301
+ "layers.18.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
302
+ "layers.18.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
303
+ "layers.18.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
304
+ "layers.18.ffn_norm.weight": "model-00002-of-00003.safetensors",
305
+ "layers.18.attention_norm.weight": "model-00002-of-00003.safetensors",
306
+ "layers.19.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
307
+ "layers.19.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
308
+ "layers.19.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
309
+ "layers.19.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
310
+ "layers.19.attention.q_norm.weight": "model-00002-of-00003.safetensors",
311
+ "layers.19.attention.k_norm.weight": "model-00002-of-00003.safetensors",
312
+ "layers.19.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
313
+ "layers.19.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
314
+ "layers.19.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
315
+ "layers.19.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
316
+ "layers.19.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
317
+ "layers.19.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
318
+ "layers.19.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
319
+ "layers.19.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
320
+ "layers.19.ffn_norm.weight": "model-00002-of-00003.safetensors",
321
+ "layers.19.attention_norm.weight": "model-00002-of-00003.safetensors",
322
+ "layers.20.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
323
+ "layers.20.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
324
+ "layers.20.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
325
+ "layers.20.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
326
+ "layers.20.attention.q_norm.weight": "model-00002-of-00003.safetensors",
327
+ "layers.20.attention.k_norm.weight": "model-00002-of-00003.safetensors",
328
+ "layers.20.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
329
+ "layers.20.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
330
+ "layers.20.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
331
+ "layers.20.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
332
+ "layers.20.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
333
+ "layers.20.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
334
+ "layers.20.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
335
+ "layers.20.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
336
+ "layers.20.ffn_norm.weight": "model-00002-of-00003.safetensors",
337
+ "layers.20.attention_norm.weight": "model-00002-of-00003.safetensors",
338
+ "layers.21.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
339
+ "layers.21.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
340
+ "layers.21.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
341
+ "layers.21.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
342
+ "layers.21.attention.q_norm.weight": "model-00002-of-00003.safetensors",
343
+ "layers.21.attention.k_norm.weight": "model-00002-of-00003.safetensors",
344
+ "layers.21.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
345
+ "layers.21.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
346
+ "layers.21.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
347
+ "layers.21.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
348
+ "layers.21.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
349
+ "layers.21.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
350
+ "layers.21.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
351
+ "layers.21.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
352
+ "layers.21.ffn_norm.weight": "model-00002-of-00003.safetensors",
353
+ "layers.21.attention_norm.weight": "model-00002-of-00003.safetensors",
354
+ "layers.22.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
355
+ "layers.22.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
356
+ "layers.22.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
357
+ "layers.22.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
358
+ "layers.22.attention.q_norm.weight": "model-00002-of-00003.safetensors",
359
+ "layers.22.attention.k_norm.weight": "model-00002-of-00003.safetensors",
360
+ "layers.22.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
361
+ "layers.22.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
362
+ "layers.22.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
363
+ "layers.22.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
364
+ "layers.22.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
365
+ "layers.22.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
366
+ "layers.22.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
367
+ "layers.22.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
368
+ "layers.22.ffn_norm.weight": "model-00002-of-00003.safetensors",
369
+ "layers.22.attention_norm.weight": "model-00002-of-00003.safetensors",
370
+ "layers.23.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
371
+ "layers.23.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
372
+ "layers.23.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
373
+ "layers.23.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
374
+ "layers.23.attention.q_norm.weight": "model-00002-of-00003.safetensors",
375
+ "layers.23.attention.k_norm.weight": "model-00002-of-00003.safetensors",
376
+ "layers.23.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
377
+ "layers.23.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
378
+ "layers.23.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
379
+ "layers.23.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
380
+ "layers.23.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
381
+ "layers.23.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
382
+ "layers.23.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
383
+ "layers.23.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
384
+ "layers.23.ffn_norm.weight": "model-00002-of-00003.safetensors",
385
+ "layers.23.attention_norm.weight": "model-00002-of-00003.safetensors",
386
+ "layers.24.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
387
+ "layers.24.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
388
+ "layers.24.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
389
+ "layers.24.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
390
+ "layers.24.attention.q_norm.weight": "model-00002-of-00003.safetensors",
391
+ "layers.24.attention.k_norm.weight": "model-00002-of-00003.safetensors",
392
+ "layers.24.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
393
+ "layers.24.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
394
+ "layers.24.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
395
+ "layers.24.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
396
+ "layers.24.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
397
+ "layers.24.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
398
+ "layers.24.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
399
+ "layers.24.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
400
+ "layers.24.ffn_norm.weight": "model-00002-of-00003.safetensors",
401
+ "layers.24.attention_norm.weight": "model-00002-of-00003.safetensors",
402
+ "layers.25.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
403
+ "layers.25.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
404
+ "layers.25.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
405
+ "layers.25.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
406
+ "layers.25.attention.q_norm.weight": "model-00002-of-00003.safetensors",
407
+ "layers.25.attention.k_norm.weight": "model-00002-of-00003.safetensors",
408
+ "layers.25.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
409
+ "layers.25.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
410
+ "layers.25.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
411
+ "layers.25.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
412
+ "layers.25.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
413
+ "layers.25.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
414
+ "layers.25.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
415
+ "layers.25.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
416
+ "layers.25.ffn_norm.weight": "model-00002-of-00003.safetensors",
417
+ "layers.25.attention_norm.weight": "model-00002-of-00003.safetensors",
418
+ "layers.26.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
419
+ "layers.26.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
420
+ "layers.26.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
421
+ "layers.26.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
422
+ "layers.26.attention.q_norm.weight": "model-00002-of-00003.safetensors",
423
+ "layers.26.attention.k_norm.weight": "model-00002-of-00003.safetensors",
424
+ "layers.26.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
425
+ "layers.26.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
426
+ "layers.26.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
427
+ "layers.26.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
428
+ "layers.26.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
429
+ "layers.26.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
430
+ "layers.26.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
431
+ "layers.26.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
432
+ "layers.26.ffn_norm.weight": "model-00002-of-00003.safetensors",
433
+ "layers.26.attention_norm.weight": "model-00002-of-00003.safetensors",
434
+ "layers.27.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
435
+ "layers.27.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
436
+ "layers.27.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
437
+ "layers.27.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
438
+ "layers.27.attention.q_norm.weight": "model-00002-of-00003.safetensors",
439
+ "layers.27.attention.k_norm.weight": "model-00002-of-00003.safetensors",
440
+ "layers.27.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
441
+ "layers.27.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
442
+ "layers.27.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
443
+ "layers.27.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
444
+ "layers.27.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
445
+ "layers.27.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
446
+ "layers.27.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
447
+ "layers.27.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
448
+ "layers.27.ffn_norm.weight": "model-00002-of-00003.safetensors",
449
+ "layers.27.attention_norm.weight": "model-00002-of-00003.safetensors",
450
+ "layers.28.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
451
+ "layers.28.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
452
+ "layers.28.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
453
+ "layers.28.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
454
+ "layers.28.attention.q_norm.weight": "model-00002-of-00003.safetensors",
455
+ "layers.28.attention.k_norm.weight": "model-00002-of-00003.safetensors",
456
+ "layers.28.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
457
+ "layers.28.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
458
+ "layers.28.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
459
+ "layers.28.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
460
+ "layers.28.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
461
+ "layers.28.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
462
+ "layers.28.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
463
+ "layers.28.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
464
+ "layers.28.ffn_norm.weight": "model-00002-of-00003.safetensors",
465
+ "layers.28.attention_norm.weight": "model-00002-of-00003.safetensors",
466
+ "layers.29.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
467
+ "layers.29.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
468
+ "layers.29.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
469
+ "layers.29.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
470
+ "layers.29.attention.q_norm.weight": "model-00002-of-00003.safetensors",
471
+ "layers.29.attention.k_norm.weight": "model-00002-of-00003.safetensors",
472
+ "layers.29.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
473
+ "layers.29.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
474
+ "layers.29.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
475
+ "layers.29.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
476
+ "layers.29.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
477
+ "layers.29.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
478
+ "layers.29.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
479
+ "layers.29.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
480
+ "layers.29.ffn_norm.weight": "model-00002-of-00003.safetensors",
481
+ "layers.29.attention_norm.weight": "model-00002-of-00003.safetensors",
482
+ "layers.30.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
483
+ "layers.30.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
484
+ "layers.30.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
485
+ "layers.30.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
486
+ "layers.30.attention.q_norm.weight": "model-00002-of-00003.safetensors",
487
+ "layers.30.attention.k_norm.weight": "model-00002-of-00003.safetensors",
488
+ "layers.30.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
489
+ "layers.30.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
490
+ "layers.30.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
491
+ "layers.30.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
492
+ "layers.30.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
493
+ "layers.30.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
494
+ "layers.30.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
495
+ "layers.30.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
496
+ "layers.30.ffn_norm.weight": "model-00002-of-00003.safetensors",
497
+ "layers.30.attention_norm.weight": "model-00002-of-00003.safetensors",
498
+ "layers.31.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
499
+ "layers.31.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
500
+ "layers.31.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
501
+ "layers.31.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
502
+ "layers.31.attention.q_norm.weight": "model-00002-of-00003.safetensors",
503
+ "layers.31.attention.k_norm.weight": "model-00002-of-00003.safetensors",
504
+ "layers.31.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
505
+ "layers.31.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
506
+ "layers.31.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
507
+ "layers.31.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
508
+ "layers.31.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
509
+ "layers.31.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
510
+ "layers.31.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
511
+ "layers.31.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
512
+ "layers.31.ffn_norm.weight": "model-00002-of-00003.safetensors",
513
+ "layers.31.attention_norm.weight": "model-00002-of-00003.safetensors",
514
+ "layers.32.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
515
+ "layers.32.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
516
+ "layers.32.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
517
+ "layers.32.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
518
+ "layers.32.attention.q_norm.weight": "model-00002-of-00003.safetensors",
519
+ "layers.32.attention.k_norm.weight": "model-00002-of-00003.safetensors",
520
+ "layers.32.feed_forward.w1.qdata": "model-00002-of-00003.safetensors",
521
+ "layers.32.feed_forward.w1.weight_block_scale": "model-00002-of-00003.safetensors",
522
+ "layers.32.feed_forward.w1.weight_scale": "model-00002-of-00003.safetensors",
523
+ "layers.32.feed_forward.w3.qdata": "model-00002-of-00003.safetensors",
524
+ "layers.32.feed_forward.w3.weight_block_scale": "model-00002-of-00003.safetensors",
525
+ "layers.32.feed_forward.w3.weight_scale": "model-00002-of-00003.safetensors",
526
+ "layers.32.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
527
+ "layers.32.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
528
+ "layers.32.ffn_norm.weight": "model-00002-of-00003.safetensors",
529
+ "layers.32.attention_norm.weight": "model-00002-of-00003.safetensors",
530
+ "layers.33.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
531
+ "layers.33.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
532
+ "layers.33.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
533
+ "layers.33.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
534
+ "layers.33.attention.q_norm.weight": "model-00002-of-00003.safetensors",
535
+ "layers.33.attention.k_norm.weight": "model-00002-of-00003.safetensors",
536
+ "layers.33.feed_forward.w1.weight_fp8": "model-00002-of-00003.safetensors",
537
+ "layers.33.feed_forward.w1.weight_scale_storage": "model-00002-of-00003.safetensors",
538
+ "layers.33.feed_forward.w3.weight_fp8": "model-00002-of-00003.safetensors",
539
+ "layers.33.feed_forward.w3.weight_scale_storage": "model-00002-of-00003.safetensors",
540
+ "layers.33.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
541
+ "layers.33.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
542
+ "layers.33.ffn_norm.weight": "model-00002-of-00003.safetensors",
543
+ "layers.33.attention_norm.weight": "model-00002-of-00003.safetensors",
544
+ "layers.34.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
545
+ "layers.34.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
546
+ "layers.34.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
547
+ "layers.34.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
548
+ "layers.34.attention.q_norm.weight": "model-00002-of-00003.safetensors",
549
+ "layers.34.attention.k_norm.weight": "model-00002-of-00003.safetensors",
550
+ "layers.34.feed_forward.w1.weight_fp8": "model-00002-of-00003.safetensors",
551
+ "layers.34.feed_forward.w1.weight_scale_storage": "model-00002-of-00003.safetensors",
552
+ "layers.34.feed_forward.w3.weight_fp8": "model-00002-of-00003.safetensors",
553
+ "layers.34.feed_forward.w3.weight_scale_storage": "model-00002-of-00003.safetensors",
554
+ "layers.34.feed_forward.w2.weight_fp8": "model-00002-of-00003.safetensors",
555
+ "layers.34.feed_forward.w2.weight_scale_storage": "model-00002-of-00003.safetensors",
556
+ "layers.34.ffn_norm.weight": "model-00002-of-00003.safetensors",
557
+ "layers.34.attention_norm.weight": "model-00002-of-00003.safetensors",
558
+ "layers.35.attention.wqkv.weight_fp8": "model-00002-of-00003.safetensors",
559
+ "layers.35.attention.wqkv.weight_scale_storage": "model-00002-of-00003.safetensors",
560
+ "layers.35.attention.wo.weight_fp8": "model-00002-of-00003.safetensors",
561
+ "layers.35.attention.wo.weight_scale_storage": "model-00002-of-00003.safetensors",
562
+ "layers.35.attention.q_norm.weight": "model-00002-of-00003.safetensors",
563
+ "layers.35.attention.k_norm.weight": "model-00002-of-00003.safetensors",
564
+ "layers.35.feed_forward.w1.weight_fp8": "model-00003-of-00003.safetensors",
565
+ "layers.35.feed_forward.w1.weight_scale_storage": "model-00003-of-00003.safetensors",
566
+ "layers.35.feed_forward.w3.weight_fp8": "model-00003-of-00003.safetensors",
567
+ "layers.35.feed_forward.w3.weight_scale_storage": "model-00003-of-00003.safetensors",
568
+ "layers.35.feed_forward.w2.weight_fp8": "model-00003-of-00003.safetensors",
569
+ "layers.35.feed_forward.w2.weight_scale_storage": "model-00003-of-00003.safetensors",
570
+ "layers.35.ffn_norm.weight": "model-00003-of-00003.safetensors",
571
+ "layers.35.attention_norm.weight": "model-00003-of-00003.safetensors",
572
+ "norm.weight": "model-00003-of-00003.safetensors",
573
+ "fast_embeddings.weight": "model-00003-of-00003.safetensors",
574
+ "fast_layers.0.attention.wqkv.weight": "model-00003-of-00003.safetensors",
575
+ "fast_layers.0.attention.wo.weight": "model-00003-of-00003.safetensors",
576
+ "fast_layers.0.feed_forward.w1.weight": "model-00003-of-00003.safetensors",
577
+ "fast_layers.0.feed_forward.w3.weight": "model-00003-of-00003.safetensors",
578
+ "fast_layers.0.feed_forward.w2.weight": "model-00003-of-00003.safetensors",
579
+ "fast_layers.0.ffn_norm.weight": "model-00003-of-00003.safetensors",
580
+ "fast_layers.0.attention_norm.weight": "model-00003-of-00003.safetensors",
581
+ "fast_layers.1.attention.wqkv.weight": "model-00003-of-00003.safetensors",
582
+ "fast_layers.1.attention.wo.weight": "model-00003-of-00003.safetensors",
583
+ "fast_layers.1.feed_forward.w1.weight": "model-00003-of-00003.safetensors",
584
+ "fast_layers.1.feed_forward.w3.weight": "model-00003-of-00003.safetensors",
585
+ "fast_layers.1.feed_forward.w2.weight": "model-00003-of-00003.safetensors",
586
+ "fast_layers.1.ffn_norm.weight": "model-00003-of-00003.safetensors",
587
+ "fast_layers.1.attention_norm.weight": "model-00003-of-00003.safetensors",
588
+ "fast_layers.2.attention.wqkv.weight": "model-00003-of-00003.safetensors",
589
+ "fast_layers.2.attention.wo.weight": "model-00003-of-00003.safetensors",
590
+ "fast_layers.2.feed_forward.w1.weight": "model-00003-of-00003.safetensors",
591
+ "fast_layers.2.feed_forward.w3.weight": "model-00003-of-00003.safetensors",
592
+ "fast_layers.2.feed_forward.w2.weight": "model-00003-of-00003.safetensors",
593
+ "fast_layers.2.ffn_norm.weight": "model-00003-of-00003.safetensors",
594
+ "fast_layers.2.attention_norm.weight": "model-00003-of-00003.safetensors",
595
+ "fast_layers.3.attention.wqkv.weight": "model-00003-of-00003.safetensors",
596
+ "fast_layers.3.attention.wo.weight": "model-00003-of-00003.safetensors",
597
+ "fast_layers.3.feed_forward.w1.weight": "model-00003-of-00003.safetensors",
598
+ "fast_layers.3.feed_forward.w3.weight": "model-00003-of-00003.safetensors",
599
+ "fast_layers.3.feed_forward.w2.weight": "model-00003-of-00003.safetensors",
600
+ "fast_layers.3.ffn_norm.weight": "model-00003-of-00003.safetensors",
601
+ "fast_layers.3.attention_norm.weight": "model-00003-of-00003.safetensors",
602
+ "fast_norm.weight": "model-00003-of-00003.safetensors",
603
+ "fast_output.weight": "model-00003-of-00003.safetensors"
604
+ }
605
+ }
quantization.json ADDED
@@ -0,0 +1,2197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": 1,
3
+ "format": "fish-s2-pro-project-local-nvfp4-mixed",
4
+ "status": "release-v1-english-qualified-single-reference-clone-pass",
5
+ "created_utc": "2026-08-27T04:51:14Z",
6
+ "base_model": "fishaudio/s2-pro@1de9996b6be38b745688de084d87a5633f714e4e",
7
+ "fish_speech_revision": "e5e292632cb11e7a27b2b7487f58f612bc101e13",
8
+ "fish_scales_ops_revision": "a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded",
9
+ "xpo3_source_revision": "7a03467b90d6feff6bd196928dfe156bd173f36e",
10
+ "implementation_files": {
11
+ "runtime/experimental/nvfp4/checkpoint.py": {
12
+ "sha256": "41870d3effbcf4e5647ba62e107bbacf0db172e963b0cf14a9503349858b7114",
13
+ "bytes": 7342
14
+ },
15
+ "runtime/experimental/nvfp4/modules.py": {
16
+ "sha256": "275be371fed819985805cf496735c32e679779fe1ccf0096f26e948bd2a668f7",
17
+ "bytes": 70345
18
+ },
19
+ "runtime/experimental/fp8/modules.py": {
20
+ "sha256": "3c4b2f71d0c3f078ad5f295c6ada96a5eb4c9c63ea518177985bdd6112766c5a",
21
+ "bytes": 10873
22
+ },
23
+ "runtime/experimental/codec.py": {
24
+ "sha256": "5bf0c02babbfefe1a736f3e844f6a46aac18d9653ba7444fd324d19abaf9dbfe",
25
+ "bytes": 11733
26
+ },
27
+ "runtime/server.py": {
28
+ "sha256": "2975cb70ebc20828e39719306d1e36075141531ea457aa2b0b12f700dfea68d1",
29
+ "bytes": 5276
30
+ }
31
+ },
32
+ "torch": "2.11.0+cu130",
33
+ "compiled_cuda": "13.0",
34
+ "hardware_family": "sm_120",
35
+ "runtime_variant": "nvfp4-w4a16-gate-up-middle30-mxfp8-rest",
36
+ "policy": "w4a16_gate_up_middle30_mxfp8_rest",
37
+ "activation_scaling": {
38
+ "checkpoint_file": "activation-scaling-report.json",
39
+ "source_path": "outputs/kernels/s2-pro-nvfp4-ste-channel-scales-all36-english-profile-rtx5080-20260826.json",
40
+ "sha256": "20024a68428ee44e4aa1b8101cc6357310d7670ebdd2ab87e91eb4f8f54d43ef",
41
+ "bytes": 2657835,
42
+ "deployment": "folded into selected FFN norms and packed gate/up weights"
43
+ },
44
+ "qualified_sampling": {
45
+ "language": "English",
46
+ "temperature": 1.0,
47
+ "top_p": 0.85,
48
+ "top_k": 30
49
+ },
50
+ "coverage": {
51
+ "nvfp4_modules": 60,
52
+ "nvfp4_layers": [
53
+ 3,
54
+ 4,
55
+ 5,
56
+ 6,
57
+ 7,
58
+ 8,
59
+ 9,
60
+ 10,
61
+ 11,
62
+ 12,
63
+ 13,
64
+ 14,
65
+ 15,
66
+ 16,
67
+ 17,
68
+ 18,
69
+ 19,
70
+ 20,
71
+ 21,
72
+ 22,
73
+ 23,
74
+ 24,
75
+ 25,
76
+ 26,
77
+ 27,
78
+ 28,
79
+ 29,
80
+ 30,
81
+ 31,
82
+ 32
83
+ ],
84
+ "nvfp4_roles": [
85
+ "w1",
86
+ "w3"
87
+ ],
88
+ "mxfp8_modules": 120,
89
+ "slow_projection_modules": 180
90
+ },
91
+ "weight_execution": {
92
+ "nvfp4": "packed E2M1 W4A16 small-M kernel through M=1; native NVFP4 W4A4 above M=1",
93
+ "mxfp8": "native dynamic MXFP8 W8A8 GEMM",
94
+ "output_dtype": "BF16"
95
+ },
96
+ "bf16_exclusions": [
97
+ "text/codebook/fast embeddings and tied text output",
98
+ "fast transformer and fast output head",
99
+ "normalization (including folded channel scales)",
100
+ "RoPE, KV cache, and sampling",
101
+ "DAC codec"
102
+ ],
103
+ "conversion_seconds": 26.938446992018726,
104
+ "conversion": {
105
+ "policy": "w4a16_gate_up_middle30_mxfp8_rest",
106
+ "backend": "selective_nvfp4_weight_bf16_activation+mxfp8_rest",
107
+ "w4a16_max_m": 1,
108
+ "nvfp4_mlp_roles": [
109
+ "w1",
110
+ "w3"
111
+ ],
112
+ "nvfp4_layers": [
113
+ 3,
114
+ 4,
115
+ 5,
116
+ 6,
117
+ 7,
118
+ 8,
119
+ 9,
120
+ 10,
121
+ 11,
122
+ 12,
123
+ 13,
124
+ 14,
125
+ 15,
126
+ 16,
127
+ 17,
128
+ 18,
129
+ 19,
130
+ 20,
131
+ 21,
132
+ 22,
133
+ 23,
134
+ 24,
135
+ 25,
136
+ 26,
137
+ 27,
138
+ 28,
139
+ 29,
140
+ 30,
141
+ 31,
142
+ 32
143
+ ],
144
+ "activation_scaling": {
145
+ "sweep_report": "/workspace/outputs/kernels/s2-pro-nvfp4-ste-channel-scales-all36-english-profile-rtx5080-20260826.json",
146
+ "calibration_reports": [
147
+ "/workspace/outputs/calibration/english-profile-api-multiseed-20260826/en-short-01-seed17-bf16-history/slow-mlp-inputs.json",
148
+ "/workspace/outputs/calibration/english-profile-api-multiseed-20260826/en-medium-01-seed17-bf16-history/slow-mlp-inputs.json",
149
+ "/workspace/outputs/calibration/english-profile-controls-multiseed-20260826/en-control-01-seed7-bf16-history/slow-mlp-inputs.json"
150
+ ],
151
+ "calibration_history_sha256": [
152
+ "ee3b0d712b0f2c7ad84a0dc149c3aa21df7511d4c8c459a6def5e07d8920881f",
153
+ "3d50440208a7c8198d197deb91888139adf91582a1389157d845ea7be9346dca",
154
+ "4381e395febcf831e90190b48105ce98301f64d46e76a7d4372ff4b17879e486"
155
+ ],
156
+ "scale_clamp": 16.0,
157
+ "activation_statistic": "equal_corpus_geometric_mean_absmax",
158
+ "correction_tensors": null,
159
+ "layers": [
160
+ {
161
+ "layer": 3,
162
+ "alpha": null,
163
+ "calibration_improvement_fraction": 0.34115383428238044,
164
+ "clip_ratio": 1.0,
165
+ "scale_mode": "explicit_channel",
166
+ "correction_rank": null,
167
+ "sparse_correction_channels": null,
168
+ "input_hadamard_block_size": 0,
169
+ "scale_min": 0.4666644036769867,
170
+ "scale_p50": 0.9958776235580444,
171
+ "scale_max": 5.142515182495117
172
+ },
173
+ {
174
+ "layer": 4,
175
+ "alpha": null,
176
+ "calibration_improvement_fraction": 0.3441897165672957,
177
+ "clip_ratio": 1.0,
178
+ "scale_mode": "explicit_channel",
179
+ "correction_rank": null,
180
+ "sparse_correction_channels": null,
181
+ "input_hadamard_block_size": 0,
182
+ "scale_min": 0.212601438164711,
183
+ "scale_p50": 0.9981337785720825,
184
+ "scale_max": 4.799542427062988
185
+ },
186
+ {
187
+ "layer": 5,
188
+ "alpha": null,
189
+ "calibration_improvement_fraction": 0.30929929335239237,
190
+ "clip_ratio": 1.0,
191
+ "scale_mode": "explicit_channel",
192
+ "correction_rank": null,
193
+ "sparse_correction_channels": null,
194
+ "input_hadamard_block_size": 0,
195
+ "scale_min": 0.27531394362449646,
196
+ "scale_p50": 0.975422739982605,
197
+ "scale_max": 10.06588363647461
198
+ },
199
+ {
200
+ "layer": 6,
201
+ "alpha": null,
202
+ "calibration_improvement_fraction": 0.18018434671767158,
203
+ "clip_ratio": 1.0,
204
+ "scale_mode": "explicit_channel",
205
+ "correction_rank": null,
206
+ "sparse_correction_channels": null,
207
+ "input_hadamard_block_size": 0,
208
+ "scale_min": 0.1165572926402092,
209
+ "scale_p50": 0.9514962434768677,
210
+ "scale_max": 7.606848239898682
211
+ },
212
+ {
213
+ "layer": 7,
214
+ "alpha": null,
215
+ "calibration_improvement_fraction": 0.06065399728329279,
216
+ "clip_ratio": 1.0,
217
+ "scale_mode": "explicit_channel",
218
+ "correction_rank": null,
219
+ "sparse_correction_channels": null,
220
+ "input_hadamard_block_size": 0,
221
+ "scale_min": 0.3172764480113983,
222
+ "scale_p50": 1.0104628801345825,
223
+ "scale_max": 3.054215431213379
224
+ },
225
+ {
226
+ "layer": 8,
227
+ "alpha": null,
228
+ "calibration_improvement_fraction": 0.011250608751427471,
229
+ "clip_ratio": 1.0,
230
+ "scale_mode": "explicit_channel",
231
+ "correction_rank": null,
232
+ "sparse_correction_channels": null,
233
+ "input_hadamard_block_size": 0,
234
+ "scale_min": 0.1061466634273529,
235
+ "scale_p50": 1.0128974914550781,
236
+ "scale_max": 2.625473976135254
237
+ },
238
+ {
239
+ "layer": 9,
240
+ "alpha": null,
241
+ "calibration_improvement_fraction": 0.0,
242
+ "clip_ratio": 1.0,
243
+ "scale_mode": "explicit_channel",
244
+ "correction_rank": null,
245
+ "sparse_correction_channels": null,
246
+ "input_hadamard_block_size": 0,
247
+ "scale_min": 1.0,
248
+ "scale_p50": 1.0,
249
+ "scale_max": 1.0
250
+ },
251
+ {
252
+ "layer": 10,
253
+ "alpha": null,
254
+ "calibration_improvement_fraction": 0.007783796885644456,
255
+ "clip_ratio": 1.0,
256
+ "scale_mode": "explicit_channel",
257
+ "correction_rank": null,
258
+ "sparse_correction_channels": null,
259
+ "input_hadamard_block_size": 0,
260
+ "scale_min": 0.4347914755344391,
261
+ "scale_p50": 1.00908625125885,
262
+ "scale_max": 3.0566306114196777
263
+ },
264
+ {
265
+ "layer": 11,
266
+ "alpha": null,
267
+ "calibration_improvement_fraction": 0.02843783886713991,
268
+ "clip_ratio": 1.0,
269
+ "scale_mode": "explicit_channel",
270
+ "correction_rank": null,
271
+ "sparse_correction_channels": null,
272
+ "input_hadamard_block_size": 0,
273
+ "scale_min": 0.39092525839805603,
274
+ "scale_p50": 1.0116372108459473,
275
+ "scale_max": 3.0836970806121826
276
+ },
277
+ {
278
+ "layer": 12,
279
+ "alpha": null,
280
+ "calibration_improvement_fraction": 0.012714668301119225,
281
+ "clip_ratio": 1.0,
282
+ "scale_mode": "explicit_channel",
283
+ "correction_rank": null,
284
+ "sparse_correction_channels": null,
285
+ "input_hadamard_block_size": 0,
286
+ "scale_min": 0.4127214550971985,
287
+ "scale_p50": 1.0075856447219849,
288
+ "scale_max": 3.343895196914673
289
+ },
290
+ {
291
+ "layer": 13,
292
+ "alpha": null,
293
+ "calibration_improvement_fraction": 0.013615598069565804,
294
+ "clip_ratio": 1.0,
295
+ "scale_mode": "explicit_channel",
296
+ "correction_rank": null,
297
+ "sparse_correction_channels": null,
298
+ "input_hadamard_block_size": 0,
299
+ "scale_min": 0.2628592550754547,
300
+ "scale_p50": 1.0010664463043213,
301
+ "scale_max": 3.645423173904419
302
+ },
303
+ {
304
+ "layer": 14,
305
+ "alpha": null,
306
+ "calibration_improvement_fraction": 0.022818199391143934,
307
+ "clip_ratio": 1.0,
308
+ "scale_mode": "explicit_channel",
309
+ "correction_rank": null,
310
+ "sparse_correction_channels": null,
311
+ "input_hadamard_block_size": 0,
312
+ "scale_min": 0.2197420746088028,
313
+ "scale_p50": 0.9946508407592773,
314
+ "scale_max": 4.616183757781982
315
+ },
316
+ {
317
+ "layer": 15,
318
+ "alpha": null,
319
+ "calibration_improvement_fraction": 0.010961721473621622,
320
+ "clip_ratio": 1.0,
321
+ "scale_mode": "explicit_channel",
322
+ "correction_rank": null,
323
+ "sparse_correction_channels": null,
324
+ "input_hadamard_block_size": 0,
325
+ "scale_min": 0.39072415232658386,
326
+ "scale_p50": 0.9946622848510742,
327
+ "scale_max": 2.7863168716430664
328
+ },
329
+ {
330
+ "layer": 16,
331
+ "alpha": null,
332
+ "calibration_improvement_fraction": 0.08529829675949463,
333
+ "clip_ratio": 1.0,
334
+ "scale_mode": "explicit_channel",
335
+ "correction_rank": null,
336
+ "sparse_correction_channels": null,
337
+ "input_hadamard_block_size": 0,
338
+ "scale_min": 0.2035234123468399,
339
+ "scale_p50": 0.9768345355987549,
340
+ "scale_max": 2.824779987335205
341
+ },
342
+ {
343
+ "layer": 17,
344
+ "alpha": null,
345
+ "calibration_improvement_fraction": 0.05795215068343107,
346
+ "clip_ratio": 1.0,
347
+ "scale_mode": "explicit_channel",
348
+ "correction_rank": null,
349
+ "sparse_correction_channels": null,
350
+ "input_hadamard_block_size": 0,
351
+ "scale_min": 0.37192386388778687,
352
+ "scale_p50": 0.9935908317565918,
353
+ "scale_max": 3.944956064224243
354
+ },
355
+ {
356
+ "layer": 18,
357
+ "alpha": null,
358
+ "calibration_improvement_fraction": 0.1330481612253437,
359
+ "clip_ratio": 1.0,
360
+ "scale_mode": "explicit_channel",
361
+ "correction_rank": null,
362
+ "sparse_correction_channels": null,
363
+ "input_hadamard_block_size": 0,
364
+ "scale_min": 0.4043632745742798,
365
+ "scale_p50": 0.9705244302749634,
366
+ "scale_max": 5.344815731048584
367
+ },
368
+ {
369
+ "layer": 19,
370
+ "alpha": null,
371
+ "calibration_improvement_fraction": 0.11661456631179568,
372
+ "clip_ratio": 1.0,
373
+ "scale_mode": "explicit_channel",
374
+ "correction_rank": null,
375
+ "sparse_correction_channels": null,
376
+ "input_hadamard_block_size": 0,
377
+ "scale_min": 0.2677452862262726,
378
+ "scale_p50": 0.9670252799987793,
379
+ "scale_max": 4.1772003173828125
380
+ },
381
+ {
382
+ "layer": 20,
383
+ "alpha": null,
384
+ "calibration_improvement_fraction": 0.15586651036886956,
385
+ "clip_ratio": 1.0,
386
+ "scale_mode": "explicit_channel",
387
+ "correction_rank": null,
388
+ "sparse_correction_channels": null,
389
+ "input_hadamard_block_size": 0,
390
+ "scale_min": 0.3513035774230957,
391
+ "scale_p50": 1.0072706937789917,
392
+ "scale_max": 2.7189722061157227
393
+ },
394
+ {
395
+ "layer": 21,
396
+ "alpha": null,
397
+ "calibration_improvement_fraction": 0.13147452299013052,
398
+ "clip_ratio": 1.0,
399
+ "scale_mode": "explicit_channel",
400
+ "correction_rank": null,
401
+ "sparse_correction_channels": null,
402
+ "input_hadamard_block_size": 0,
403
+ "scale_min": 0.3314710557460785,
404
+ "scale_p50": 1.0048860311508179,
405
+ "scale_max": 2.3973195552825928
406
+ },
407
+ {
408
+ "layer": 22,
409
+ "alpha": null,
410
+ "calibration_improvement_fraction": 0.17074986711459594,
411
+ "clip_ratio": 1.0,
412
+ "scale_mode": "explicit_channel",
413
+ "correction_rank": null,
414
+ "sparse_correction_channels": null,
415
+ "input_hadamard_block_size": 0,
416
+ "scale_min": 0.30894899368286133,
417
+ "scale_p50": 1.019906997680664,
418
+ "scale_max": 2.589536428451538
419
+ },
420
+ {
421
+ "layer": 23,
422
+ "alpha": null,
423
+ "calibration_improvement_fraction": 0.17914724568745244,
424
+ "clip_ratio": 1.0,
425
+ "scale_mode": "explicit_channel",
426
+ "correction_rank": null,
427
+ "sparse_correction_channels": null,
428
+ "input_hadamard_block_size": 0,
429
+ "scale_min": 0.08279751241207123,
430
+ "scale_p50": 1.0246715545654297,
431
+ "scale_max": 2.500920057296753
432
+ },
433
+ {
434
+ "layer": 24,
435
+ "alpha": null,
436
+ "calibration_improvement_fraction": 0.2385892277628,
437
+ "clip_ratio": 1.0,
438
+ "scale_mode": "explicit_channel",
439
+ "correction_rank": null,
440
+ "sparse_correction_channels": null,
441
+ "input_hadamard_block_size": 0,
442
+ "scale_min": 0.30888521671295166,
443
+ "scale_p50": 1.0113917589187622,
444
+ "scale_max": 2.790740489959717
445
+ },
446
+ {
447
+ "layer": 25,
448
+ "alpha": null,
449
+ "calibration_improvement_fraction": 0.18576108916475464,
450
+ "clip_ratio": 1.0,
451
+ "scale_mode": "explicit_channel",
452
+ "correction_rank": null,
453
+ "sparse_correction_channels": null,
454
+ "input_hadamard_block_size": 0,
455
+ "scale_min": 0.30071744322776794,
456
+ "scale_p50": 1.0063565969467163,
457
+ "scale_max": 2.702918291091919
458
+ },
459
+ {
460
+ "layer": 26,
461
+ "alpha": null,
462
+ "calibration_improvement_fraction": 0.17304804845125255,
463
+ "clip_ratio": 1.0,
464
+ "scale_mode": "explicit_channel",
465
+ "correction_rank": null,
466
+ "sparse_correction_channels": null,
467
+ "input_hadamard_block_size": 0,
468
+ "scale_min": 0.2675870954990387,
469
+ "scale_p50": 1.0074219703674316,
470
+ "scale_max": 3.0248024463653564
471
+ },
472
+ {
473
+ "layer": 27,
474
+ "alpha": null,
475
+ "calibration_improvement_fraction": 0.07856216820359907,
476
+ "clip_ratio": 1.0,
477
+ "scale_mode": "explicit_channel",
478
+ "correction_rank": null,
479
+ "sparse_correction_channels": null,
480
+ "input_hadamard_block_size": 0,
481
+ "scale_min": 0.4005119204521179,
482
+ "scale_p50": 1.0053906440734863,
483
+ "scale_max": 2.7383763790130615
484
+ },
485
+ {
486
+ "layer": 28,
487
+ "alpha": null,
488
+ "calibration_improvement_fraction": 0.06775815208747848,
489
+ "clip_ratio": 1.0,
490
+ "scale_mode": "explicit_channel",
491
+ "correction_rank": null,
492
+ "sparse_correction_channels": null,
493
+ "input_hadamard_block_size": 0,
494
+ "scale_min": 0.42719921469688416,
495
+ "scale_p50": 1.0111608505249023,
496
+ "scale_max": 2.56790828704834
497
+ },
498
+ {
499
+ "layer": 29,
500
+ "alpha": null,
501
+ "calibration_improvement_fraction": 0.07100470156359495,
502
+ "clip_ratio": 1.0,
503
+ "scale_mode": "explicit_channel",
504
+ "correction_rank": null,
505
+ "sparse_correction_channels": null,
506
+ "input_hadamard_block_size": 0,
507
+ "scale_min": 0.1727953404188156,
508
+ "scale_p50": 1.011107087135315,
509
+ "scale_max": 2.124830484390259
510
+ },
511
+ {
512
+ "layer": 30,
513
+ "alpha": null,
514
+ "calibration_improvement_fraction": 0.07547034941098363,
515
+ "clip_ratio": 1.0,
516
+ "scale_mode": "explicit_channel",
517
+ "correction_rank": null,
518
+ "sparse_correction_channels": null,
519
+ "input_hadamard_block_size": 0,
520
+ "scale_min": 0.4036831259727478,
521
+ "scale_p50": 1.018500566482544,
522
+ "scale_max": 2.685163974761963
523
+ },
524
+ {
525
+ "layer": 31,
526
+ "alpha": null,
527
+ "calibration_improvement_fraction": 0.08205942511115716,
528
+ "clip_ratio": 1.0,
529
+ "scale_mode": "explicit_channel",
530
+ "correction_rank": null,
531
+ "sparse_correction_channels": null,
532
+ "input_hadamard_block_size": 0,
533
+ "scale_min": 0.3752962648868561,
534
+ "scale_p50": 1.0237677097320557,
535
+ "scale_max": 2.359099864959717
536
+ },
537
+ {
538
+ "layer": 32,
539
+ "alpha": null,
540
+ "calibration_improvement_fraction": 0.10552935903626048,
541
+ "clip_ratio": 1.0,
542
+ "scale_mode": "explicit_channel",
543
+ "correction_rank": null,
544
+ "sparse_correction_channels": null,
545
+ "input_hadamard_block_size": 0,
546
+ "scale_min": 0.39887359738349915,
547
+ "scale_p50": 1.0268824100494385,
548
+ "scale_max": 2.298870801925659
549
+ }
550
+ ]
551
+ },
552
+ "modules": 180,
553
+ "projections": 180,
554
+ "parameters": 3633315840,
555
+ "nvfp4_parameters": 1494220800,
556
+ "mxfp8_parameters": 2139095040,
557
+ "low_rank_correction_parameters": 0,
558
+ "low_rank_correction_bytes": 0,
559
+ "sparse_correction_parameters": 0,
560
+ "sparse_correction_bytes": 0,
561
+ "correction_parameters": 0,
562
+ "correction_bytes": 0,
563
+ "theoretical_bf16_source_bytes": 7266631680,
564
+ "packed_weight_bytes": 3046441200,
565
+ "nvfp4_packed_weight_bytes": 840499440,
566
+ "mxfp8_packed_weight_bytes": 2205941760,
567
+ "probe_cosine_min": 0.9942060112953186,
568
+ "probe_cosine_mean": 0.9979391674200694,
569
+ "probe_cosine_max": 0.9994385242462158,
570
+ "records": [
571
+ {
572
+ "name": "layers.0.attention.wqkv",
573
+ "in_features": 2560,
574
+ "out_features": 6144,
575
+ "parameters": 15728640,
576
+ "probe_cosine": 0.9994018077850342,
577
+ "precision": "mxfp8_w8a8"
578
+ },
579
+ {
580
+ "name": "layers.0.attention.wo",
581
+ "in_features": 4096,
582
+ "out_features": 2560,
583
+ "parameters": 10485760,
584
+ "probe_cosine": 0.9994044303894043,
585
+ "precision": "mxfp8_w8a8"
586
+ },
587
+ {
588
+ "name": "layers.0.feed_forward.w1",
589
+ "in_features": 2560,
590
+ "out_features": 9728,
591
+ "parameters": 24903680,
592
+ "probe_cosine": 0.9992644190788269,
593
+ "precision": "mxfp8_w8a8"
594
+ },
595
+ {
596
+ "name": "layers.0.feed_forward.w3",
597
+ "in_features": 2560,
598
+ "out_features": 9728,
599
+ "parameters": 24903680,
600
+ "probe_cosine": 0.9991974830627441,
601
+ "precision": "mxfp8_w8a8"
602
+ },
603
+ {
604
+ "name": "layers.0.feed_forward.w2",
605
+ "in_features": 9728,
606
+ "out_features": 2560,
607
+ "parameters": 24903680,
608
+ "probe_cosine": 0.9992890357971191,
609
+ "precision": "mxfp8_w8a8"
610
+ },
611
+ {
612
+ "name": "layers.1.attention.wqkv",
613
+ "in_features": 2560,
614
+ "out_features": 6144,
615
+ "parameters": 15728640,
616
+ "probe_cosine": 0.9992879033088684,
617
+ "precision": "mxfp8_w8a8"
618
+ },
619
+ {
620
+ "name": "layers.1.attention.wo",
621
+ "in_features": 4096,
622
+ "out_features": 2560,
623
+ "parameters": 10485760,
624
+ "probe_cosine": 0.9993317723274231,
625
+ "precision": "mxfp8_w8a8"
626
+ },
627
+ {
628
+ "name": "layers.1.feed_forward.w1",
629
+ "in_features": 2560,
630
+ "out_features": 9728,
631
+ "parameters": 24903680,
632
+ "probe_cosine": 0.9992480874061584,
633
+ "precision": "mxfp8_w8a8"
634
+ },
635
+ {
636
+ "name": "layers.1.feed_forward.w3",
637
+ "in_features": 2560,
638
+ "out_features": 9728,
639
+ "parameters": 24903680,
640
+ "probe_cosine": 0.9993327856063843,
641
+ "precision": "mxfp8_w8a8"
642
+ },
643
+ {
644
+ "name": "layers.1.feed_forward.w2",
645
+ "in_features": 9728,
646
+ "out_features": 2560,
647
+ "parameters": 24903680,
648
+ "probe_cosine": 0.9993032217025757,
649
+ "precision": "mxfp8_w8a8"
650
+ },
651
+ {
652
+ "name": "layers.2.attention.wqkv",
653
+ "in_features": 2560,
654
+ "out_features": 6144,
655
+ "parameters": 15728640,
656
+ "probe_cosine": 0.999262809753418,
657
+ "precision": "mxfp8_w8a8"
658
+ },
659
+ {
660
+ "name": "layers.2.attention.wo",
661
+ "in_features": 4096,
662
+ "out_features": 2560,
663
+ "parameters": 10485760,
664
+ "probe_cosine": 0.9992883801460266,
665
+ "precision": "mxfp8_w8a8"
666
+ },
667
+ {
668
+ "name": "layers.2.feed_forward.w1",
669
+ "in_features": 2560,
670
+ "out_features": 9728,
671
+ "parameters": 24903680,
672
+ "probe_cosine": 0.9992047548294067,
673
+ "precision": "mxfp8_w8a8"
674
+ },
675
+ {
676
+ "name": "layers.2.feed_forward.w3",
677
+ "in_features": 2560,
678
+ "out_features": 9728,
679
+ "parameters": 24903680,
680
+ "probe_cosine": 0.9993103742599487,
681
+ "precision": "mxfp8_w8a8"
682
+ },
683
+ {
684
+ "name": "layers.2.feed_forward.w2",
685
+ "in_features": 9728,
686
+ "out_features": 2560,
687
+ "parameters": 24903680,
688
+ "probe_cosine": 0.9992554187774658,
689
+ "precision": "mxfp8_w8a8"
690
+ },
691
+ {
692
+ "name": "layers.3.attention.wqkv",
693
+ "in_features": 2560,
694
+ "out_features": 6144,
695
+ "parameters": 15728640,
696
+ "probe_cosine": 0.9994385242462158,
697
+ "precision": "mxfp8_w8a8"
698
+ },
699
+ {
700
+ "name": "layers.3.attention.wo",
701
+ "in_features": 4096,
702
+ "out_features": 2560,
703
+ "parameters": 10485760,
704
+ "probe_cosine": 0.9992822408676147,
705
+ "precision": "mxfp8_w8a8"
706
+ },
707
+ {
708
+ "name": "layers.3.feed_forward.w1",
709
+ "in_features": 2560,
710
+ "out_features": 9728,
711
+ "parameters": 24903680,
712
+ "probe_cosine": 0.9948533773422241,
713
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
714
+ },
715
+ {
716
+ "name": "layers.3.feed_forward.w3",
717
+ "in_features": 2560,
718
+ "out_features": 9728,
719
+ "parameters": 24903680,
720
+ "probe_cosine": 0.9952349662780762,
721
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
722
+ },
723
+ {
724
+ "name": "layers.3.feed_forward.w2",
725
+ "in_features": 9728,
726
+ "out_features": 2560,
727
+ "parameters": 24903680,
728
+ "probe_cosine": 0.9992232918739319,
729
+ "precision": "mxfp8_w8a8"
730
+ },
731
+ {
732
+ "name": "layers.4.attention.wqkv",
733
+ "in_features": 2560,
734
+ "out_features": 6144,
735
+ "parameters": 15728640,
736
+ "probe_cosine": 0.9992364645004272,
737
+ "precision": "mxfp8_w8a8"
738
+ },
739
+ {
740
+ "name": "layers.4.attention.wo",
741
+ "in_features": 4096,
742
+ "out_features": 2560,
743
+ "parameters": 10485760,
744
+ "probe_cosine": 0.9992576837539673,
745
+ "precision": "mxfp8_w8a8"
746
+ },
747
+ {
748
+ "name": "layers.4.feed_forward.w1",
749
+ "in_features": 2560,
750
+ "out_features": 9728,
751
+ "parameters": 24903680,
752
+ "probe_cosine": 0.9952384233474731,
753
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
754
+ },
755
+ {
756
+ "name": "layers.4.feed_forward.w3",
757
+ "in_features": 2560,
758
+ "out_features": 9728,
759
+ "parameters": 24903680,
760
+ "probe_cosine": 0.9954122304916382,
761
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
762
+ },
763
+ {
764
+ "name": "layers.4.feed_forward.w2",
765
+ "in_features": 9728,
766
+ "out_features": 2560,
767
+ "parameters": 24903680,
768
+ "probe_cosine": 0.9993067979812622,
769
+ "precision": "mxfp8_w8a8"
770
+ },
771
+ {
772
+ "name": "layers.5.attention.wqkv",
773
+ "in_features": 2560,
774
+ "out_features": 6144,
775
+ "parameters": 15728640,
776
+ "probe_cosine": 0.9992440938949585,
777
+ "precision": "mxfp8_w8a8"
778
+ },
779
+ {
780
+ "name": "layers.5.attention.wo",
781
+ "in_features": 4096,
782
+ "out_features": 2560,
783
+ "parameters": 10485760,
784
+ "probe_cosine": 0.9992841482162476,
785
+ "precision": "mxfp8_w8a8"
786
+ },
787
+ {
788
+ "name": "layers.5.feed_forward.w1",
789
+ "in_features": 2560,
790
+ "out_features": 9728,
791
+ "parameters": 24903680,
792
+ "probe_cosine": 0.9942060112953186,
793
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
794
+ },
795
+ {
796
+ "name": "layers.5.feed_forward.w3",
797
+ "in_features": 2560,
798
+ "out_features": 9728,
799
+ "parameters": 24903680,
800
+ "probe_cosine": 0.9951051473617554,
801
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
802
+ },
803
+ {
804
+ "name": "layers.5.feed_forward.w2",
805
+ "in_features": 9728,
806
+ "out_features": 2560,
807
+ "parameters": 24903680,
808
+ "probe_cosine": 0.9992941617965698,
809
+ "precision": "mxfp8_w8a8"
810
+ },
811
+ {
812
+ "name": "layers.6.attention.wqkv",
813
+ "in_features": 2560,
814
+ "out_features": 6144,
815
+ "parameters": 15728640,
816
+ "probe_cosine": 0.9992526769638062,
817
+ "precision": "mxfp8_w8a8"
818
+ },
819
+ {
820
+ "name": "layers.6.attention.wo",
821
+ "in_features": 4096,
822
+ "out_features": 2560,
823
+ "parameters": 10485760,
824
+ "probe_cosine": 0.9993124008178711,
825
+ "precision": "mxfp8_w8a8"
826
+ },
827
+ {
828
+ "name": "layers.6.feed_forward.w1",
829
+ "in_features": 2560,
830
+ "out_features": 9728,
831
+ "parameters": 24903680,
832
+ "probe_cosine": 0.9946960210800171,
833
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
834
+ },
835
+ {
836
+ "name": "layers.6.feed_forward.w3",
837
+ "in_features": 2560,
838
+ "out_features": 9728,
839
+ "parameters": 24903680,
840
+ "probe_cosine": 0.9953465461730957,
841
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
842
+ },
843
+ {
844
+ "name": "layers.6.feed_forward.w2",
845
+ "in_features": 9728,
846
+ "out_features": 2560,
847
+ "parameters": 24903680,
848
+ "probe_cosine": 0.9993586540222168,
849
+ "precision": "mxfp8_w8a8"
850
+ },
851
+ {
852
+ "name": "layers.7.attention.wqkv",
853
+ "in_features": 2560,
854
+ "out_features": 6144,
855
+ "parameters": 15728640,
856
+ "probe_cosine": 0.9992846250534058,
857
+ "precision": "mxfp8_w8a8"
858
+ },
859
+ {
860
+ "name": "layers.7.attention.wo",
861
+ "in_features": 4096,
862
+ "out_features": 2560,
863
+ "parameters": 10485760,
864
+ "probe_cosine": 0.9992576837539673,
865
+ "precision": "mxfp8_w8a8"
866
+ },
867
+ {
868
+ "name": "layers.7.feed_forward.w1",
869
+ "in_features": 2560,
870
+ "out_features": 9728,
871
+ "parameters": 24903680,
872
+ "probe_cosine": 0.9948426485061646,
873
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
874
+ },
875
+ {
876
+ "name": "layers.7.feed_forward.w3",
877
+ "in_features": 2560,
878
+ "out_features": 9728,
879
+ "parameters": 24903680,
880
+ "probe_cosine": 0.9953813552856445,
881
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
882
+ },
883
+ {
884
+ "name": "layers.7.feed_forward.w2",
885
+ "in_features": 9728,
886
+ "out_features": 2560,
887
+ "parameters": 24903680,
888
+ "probe_cosine": 0.9992576241493225,
889
+ "precision": "mxfp8_w8a8"
890
+ },
891
+ {
892
+ "name": "layers.8.attention.wqkv",
893
+ "in_features": 2560,
894
+ "out_features": 6144,
895
+ "parameters": 15728640,
896
+ "probe_cosine": 0.9992561340332031,
897
+ "precision": "mxfp8_w8a8"
898
+ },
899
+ {
900
+ "name": "layers.8.attention.wo",
901
+ "in_features": 4096,
902
+ "out_features": 2560,
903
+ "parameters": 10485760,
904
+ "probe_cosine": 0.9993311166763306,
905
+ "precision": "mxfp8_w8a8"
906
+ },
907
+ {
908
+ "name": "layers.8.feed_forward.w1",
909
+ "in_features": 2560,
910
+ "out_features": 9728,
911
+ "parameters": 24903680,
912
+ "probe_cosine": 0.9954076409339905,
913
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
914
+ },
915
+ {
916
+ "name": "layers.8.feed_forward.w3",
917
+ "in_features": 2560,
918
+ "out_features": 9728,
919
+ "parameters": 24903680,
920
+ "probe_cosine": 0.9952717423439026,
921
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
922
+ },
923
+ {
924
+ "name": "layers.8.feed_forward.w2",
925
+ "in_features": 9728,
926
+ "out_features": 2560,
927
+ "parameters": 24903680,
928
+ "probe_cosine": 0.9992897510528564,
929
+ "precision": "mxfp8_w8a8"
930
+ },
931
+ {
932
+ "name": "layers.9.attention.wqkv",
933
+ "in_features": 2560,
934
+ "out_features": 6144,
935
+ "parameters": 15728640,
936
+ "probe_cosine": 0.9992669820785522,
937
+ "precision": "mxfp8_w8a8"
938
+ },
939
+ {
940
+ "name": "layers.9.attention.wo",
941
+ "in_features": 4096,
942
+ "out_features": 2560,
943
+ "parameters": 10485760,
944
+ "probe_cosine": 0.9993153214454651,
945
+ "precision": "mxfp8_w8a8"
946
+ },
947
+ {
948
+ "name": "layers.9.feed_forward.w1",
949
+ "in_features": 2560,
950
+ "out_features": 9728,
951
+ "parameters": 24903680,
952
+ "probe_cosine": 0.995424747467041,
953
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
954
+ },
955
+ {
956
+ "name": "layers.9.feed_forward.w3",
957
+ "in_features": 2560,
958
+ "out_features": 9728,
959
+ "parameters": 24903680,
960
+ "probe_cosine": 0.9953783750534058,
961
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
962
+ },
963
+ {
964
+ "name": "layers.9.feed_forward.w2",
965
+ "in_features": 9728,
966
+ "out_features": 2560,
967
+ "parameters": 24903680,
968
+ "probe_cosine": 0.999322772026062,
969
+ "precision": "mxfp8_w8a8"
970
+ },
971
+ {
972
+ "name": "layers.10.attention.wqkv",
973
+ "in_features": 2560,
974
+ "out_features": 6144,
975
+ "parameters": 15728640,
976
+ "probe_cosine": 0.9993197321891785,
977
+ "precision": "mxfp8_w8a8"
978
+ },
979
+ {
980
+ "name": "layers.10.attention.wo",
981
+ "in_features": 4096,
982
+ "out_features": 2560,
983
+ "parameters": 10485760,
984
+ "probe_cosine": 0.9993413090705872,
985
+ "precision": "mxfp8_w8a8"
986
+ },
987
+ {
988
+ "name": "layers.10.feed_forward.w1",
989
+ "in_features": 2560,
990
+ "out_features": 9728,
991
+ "parameters": 24903680,
992
+ "probe_cosine": 0.9951403737068176,
993
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
994
+ },
995
+ {
996
+ "name": "layers.10.feed_forward.w3",
997
+ "in_features": 2560,
998
+ "out_features": 9728,
999
+ "parameters": 24903680,
1000
+ "probe_cosine": 0.9953807592391968,
1001
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1002
+ },
1003
+ {
1004
+ "name": "layers.10.feed_forward.w2",
1005
+ "in_features": 9728,
1006
+ "out_features": 2560,
1007
+ "parameters": 24903680,
1008
+ "probe_cosine": 0.9992862939834595,
1009
+ "precision": "mxfp8_w8a8"
1010
+ },
1011
+ {
1012
+ "name": "layers.11.attention.wqkv",
1013
+ "in_features": 2560,
1014
+ "out_features": 6144,
1015
+ "parameters": 15728640,
1016
+ "probe_cosine": 0.9992955923080444,
1017
+ "precision": "mxfp8_w8a8"
1018
+ },
1019
+ {
1020
+ "name": "layers.11.attention.wo",
1021
+ "in_features": 4096,
1022
+ "out_features": 2560,
1023
+ "parameters": 10485760,
1024
+ "probe_cosine": 0.999306857585907,
1025
+ "precision": "mxfp8_w8a8"
1026
+ },
1027
+ {
1028
+ "name": "layers.11.feed_forward.w1",
1029
+ "in_features": 2560,
1030
+ "out_features": 9728,
1031
+ "parameters": 24903680,
1032
+ "probe_cosine": 0.9950716495513916,
1033
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1034
+ },
1035
+ {
1036
+ "name": "layers.11.feed_forward.w3",
1037
+ "in_features": 2560,
1038
+ "out_features": 9728,
1039
+ "parameters": 24903680,
1040
+ "probe_cosine": 0.9955061078071594,
1041
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1042
+ },
1043
+ {
1044
+ "name": "layers.11.feed_forward.w2",
1045
+ "in_features": 9728,
1046
+ "out_features": 2560,
1047
+ "parameters": 24903680,
1048
+ "probe_cosine": 0.9993455410003662,
1049
+ "precision": "mxfp8_w8a8"
1050
+ },
1051
+ {
1052
+ "name": "layers.12.attention.wqkv",
1053
+ "in_features": 2560,
1054
+ "out_features": 6144,
1055
+ "parameters": 15728640,
1056
+ "probe_cosine": 0.999247670173645,
1057
+ "precision": "mxfp8_w8a8"
1058
+ },
1059
+ {
1060
+ "name": "layers.12.attention.wo",
1061
+ "in_features": 4096,
1062
+ "out_features": 2560,
1063
+ "parameters": 10485760,
1064
+ "probe_cosine": 0.9992870092391968,
1065
+ "precision": "mxfp8_w8a8"
1066
+ },
1067
+ {
1068
+ "name": "layers.12.feed_forward.w1",
1069
+ "in_features": 2560,
1070
+ "out_features": 9728,
1071
+ "parameters": 24903680,
1072
+ "probe_cosine": 0.9951099753379822,
1073
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1074
+ },
1075
+ {
1076
+ "name": "layers.12.feed_forward.w3",
1077
+ "in_features": 2560,
1078
+ "out_features": 9728,
1079
+ "parameters": 24903680,
1080
+ "probe_cosine": 0.9955266714096069,
1081
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1082
+ },
1083
+ {
1084
+ "name": "layers.12.feed_forward.w2",
1085
+ "in_features": 9728,
1086
+ "out_features": 2560,
1087
+ "parameters": 24903680,
1088
+ "probe_cosine": 0.999378502368927,
1089
+ "precision": "mxfp8_w8a8"
1090
+ },
1091
+ {
1092
+ "name": "layers.13.attention.wqkv",
1093
+ "in_features": 2560,
1094
+ "out_features": 6144,
1095
+ "parameters": 15728640,
1096
+ "probe_cosine": 0.9992713332176208,
1097
+ "precision": "mxfp8_w8a8"
1098
+ },
1099
+ {
1100
+ "name": "layers.13.attention.wo",
1101
+ "in_features": 4096,
1102
+ "out_features": 2560,
1103
+ "parameters": 10485760,
1104
+ "probe_cosine": 0.9993178248405457,
1105
+ "precision": "mxfp8_w8a8"
1106
+ },
1107
+ {
1108
+ "name": "layers.13.feed_forward.w1",
1109
+ "in_features": 2560,
1110
+ "out_features": 9728,
1111
+ "parameters": 24903680,
1112
+ "probe_cosine": 0.9951012134552002,
1113
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1114
+ },
1115
+ {
1116
+ "name": "layers.13.feed_forward.w3",
1117
+ "in_features": 2560,
1118
+ "out_features": 9728,
1119
+ "parameters": 24903680,
1120
+ "probe_cosine": 0.9953491687774658,
1121
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1122
+ },
1123
+ {
1124
+ "name": "layers.13.feed_forward.w2",
1125
+ "in_features": 9728,
1126
+ "out_features": 2560,
1127
+ "parameters": 24903680,
1128
+ "probe_cosine": 0.9993041753768921,
1129
+ "precision": "mxfp8_w8a8"
1130
+ },
1131
+ {
1132
+ "name": "layers.14.attention.wqkv",
1133
+ "in_features": 2560,
1134
+ "out_features": 6144,
1135
+ "parameters": 15728640,
1136
+ "probe_cosine": 0.9992854595184326,
1137
+ "precision": "mxfp8_w8a8"
1138
+ },
1139
+ {
1140
+ "name": "layers.14.attention.wo",
1141
+ "in_features": 4096,
1142
+ "out_features": 2560,
1143
+ "parameters": 10485760,
1144
+ "probe_cosine": 0.9992244243621826,
1145
+ "precision": "mxfp8_w8a8"
1146
+ },
1147
+ {
1148
+ "name": "layers.14.feed_forward.w1",
1149
+ "in_features": 2560,
1150
+ "out_features": 9728,
1151
+ "parameters": 24903680,
1152
+ "probe_cosine": 0.9949911832809448,
1153
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1154
+ },
1155
+ {
1156
+ "name": "layers.14.feed_forward.w3",
1157
+ "in_features": 2560,
1158
+ "out_features": 9728,
1159
+ "parameters": 24903680,
1160
+ "probe_cosine": 0.9952331781387329,
1161
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1162
+ },
1163
+ {
1164
+ "name": "layers.14.feed_forward.w2",
1165
+ "in_features": 9728,
1166
+ "out_features": 2560,
1167
+ "parameters": 24903680,
1168
+ "probe_cosine": 0.9993098378181458,
1169
+ "precision": "mxfp8_w8a8"
1170
+ },
1171
+ {
1172
+ "name": "layers.15.attention.wqkv",
1173
+ "in_features": 2560,
1174
+ "out_features": 6144,
1175
+ "parameters": 15728640,
1176
+ "probe_cosine": 0.9993874430656433,
1177
+ "precision": "mxfp8_w8a8"
1178
+ },
1179
+ {
1180
+ "name": "layers.15.attention.wo",
1181
+ "in_features": 4096,
1182
+ "out_features": 2560,
1183
+ "parameters": 10485760,
1184
+ "probe_cosine": 0.9993578791618347,
1185
+ "precision": "mxfp8_w8a8"
1186
+ },
1187
+ {
1188
+ "name": "layers.15.feed_forward.w1",
1189
+ "in_features": 2560,
1190
+ "out_features": 9728,
1191
+ "parameters": 24903680,
1192
+ "probe_cosine": 0.9955209493637085,
1193
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1194
+ },
1195
+ {
1196
+ "name": "layers.15.feed_forward.w3",
1197
+ "in_features": 2560,
1198
+ "out_features": 9728,
1199
+ "parameters": 24903680,
1200
+ "probe_cosine": 0.9953669309616089,
1201
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1202
+ },
1203
+ {
1204
+ "name": "layers.15.feed_forward.w2",
1205
+ "in_features": 9728,
1206
+ "out_features": 2560,
1207
+ "parameters": 24903680,
1208
+ "probe_cosine": 0.9992756247520447,
1209
+ "precision": "mxfp8_w8a8"
1210
+ },
1211
+ {
1212
+ "name": "layers.16.attention.wqkv",
1213
+ "in_features": 2560,
1214
+ "out_features": 6144,
1215
+ "parameters": 15728640,
1216
+ "probe_cosine": 0.9992870092391968,
1217
+ "precision": "mxfp8_w8a8"
1218
+ },
1219
+ {
1220
+ "name": "layers.16.attention.wo",
1221
+ "in_features": 4096,
1222
+ "out_features": 2560,
1223
+ "parameters": 10485760,
1224
+ "probe_cosine": 0.9993147253990173,
1225
+ "precision": "mxfp8_w8a8"
1226
+ },
1227
+ {
1228
+ "name": "layers.16.feed_forward.w1",
1229
+ "in_features": 2560,
1230
+ "out_features": 9728,
1231
+ "parameters": 24903680,
1232
+ "probe_cosine": 0.9951826333999634,
1233
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1234
+ },
1235
+ {
1236
+ "name": "layers.16.feed_forward.w3",
1237
+ "in_features": 2560,
1238
+ "out_features": 9728,
1239
+ "parameters": 24903680,
1240
+ "probe_cosine": 0.9952670335769653,
1241
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1242
+ },
1243
+ {
1244
+ "name": "layers.16.feed_forward.w2",
1245
+ "in_features": 9728,
1246
+ "out_features": 2560,
1247
+ "parameters": 24903680,
1248
+ "probe_cosine": 0.9992488622665405,
1249
+ "precision": "mxfp8_w8a8"
1250
+ },
1251
+ {
1252
+ "name": "layers.17.attention.wqkv",
1253
+ "in_features": 2560,
1254
+ "out_features": 6144,
1255
+ "parameters": 15728640,
1256
+ "probe_cosine": 0.9993287324905396,
1257
+ "precision": "mxfp8_w8a8"
1258
+ },
1259
+ {
1260
+ "name": "layers.17.attention.wo",
1261
+ "in_features": 4096,
1262
+ "out_features": 2560,
1263
+ "parameters": 10485760,
1264
+ "probe_cosine": 0.9993382096290588,
1265
+ "precision": "mxfp8_w8a8"
1266
+ },
1267
+ {
1268
+ "name": "layers.17.feed_forward.w1",
1269
+ "in_features": 2560,
1270
+ "out_features": 9728,
1271
+ "parameters": 24903680,
1272
+ "probe_cosine": 0.9949835538864136,
1273
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1274
+ },
1275
+ {
1276
+ "name": "layers.17.feed_forward.w3",
1277
+ "in_features": 2560,
1278
+ "out_features": 9728,
1279
+ "parameters": 24903680,
1280
+ "probe_cosine": 0.9951303005218506,
1281
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1282
+ },
1283
+ {
1284
+ "name": "layers.17.feed_forward.w2",
1285
+ "in_features": 9728,
1286
+ "out_features": 2560,
1287
+ "parameters": 24903680,
1288
+ "probe_cosine": 0.9992471933364868,
1289
+ "precision": "mxfp8_w8a8"
1290
+ },
1291
+ {
1292
+ "name": "layers.18.attention.wqkv",
1293
+ "in_features": 2560,
1294
+ "out_features": 6144,
1295
+ "parameters": 15728640,
1296
+ "probe_cosine": 0.9993221759796143,
1297
+ "precision": "mxfp8_w8a8"
1298
+ },
1299
+ {
1300
+ "name": "layers.18.attention.wo",
1301
+ "in_features": 4096,
1302
+ "out_features": 2560,
1303
+ "parameters": 10485760,
1304
+ "probe_cosine": 0.9993113279342651,
1305
+ "precision": "mxfp8_w8a8"
1306
+ },
1307
+ {
1308
+ "name": "layers.18.feed_forward.w1",
1309
+ "in_features": 2560,
1310
+ "out_features": 9728,
1311
+ "parameters": 24903680,
1312
+ "probe_cosine": 0.9948270916938782,
1313
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1314
+ },
1315
+ {
1316
+ "name": "layers.18.feed_forward.w3",
1317
+ "in_features": 2560,
1318
+ "out_features": 9728,
1319
+ "parameters": 24903680,
1320
+ "probe_cosine": 0.9951784610748291,
1321
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1322
+ },
1323
+ {
1324
+ "name": "layers.18.feed_forward.w2",
1325
+ "in_features": 9728,
1326
+ "out_features": 2560,
1327
+ "parameters": 24903680,
1328
+ "probe_cosine": 0.9993153810501099,
1329
+ "precision": "mxfp8_w8a8"
1330
+ },
1331
+ {
1332
+ "name": "layers.19.attention.wqkv",
1333
+ "in_features": 2560,
1334
+ "out_features": 6144,
1335
+ "parameters": 15728640,
1336
+ "probe_cosine": 0.9992598295211792,
1337
+ "precision": "mxfp8_w8a8"
1338
+ },
1339
+ {
1340
+ "name": "layers.19.attention.wo",
1341
+ "in_features": 4096,
1342
+ "out_features": 2560,
1343
+ "parameters": 10485760,
1344
+ "probe_cosine": 0.9992833137512207,
1345
+ "precision": "mxfp8_w8a8"
1346
+ },
1347
+ {
1348
+ "name": "layers.19.feed_forward.w1",
1349
+ "in_features": 2560,
1350
+ "out_features": 9728,
1351
+ "parameters": 24903680,
1352
+ "probe_cosine": 0.9952045679092407,
1353
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1354
+ },
1355
+ {
1356
+ "name": "layers.19.feed_forward.w3",
1357
+ "in_features": 2560,
1358
+ "out_features": 9728,
1359
+ "parameters": 24903680,
1360
+ "probe_cosine": 0.9950501918792725,
1361
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1362
+ },
1363
+ {
1364
+ "name": "layers.19.feed_forward.w2",
1365
+ "in_features": 9728,
1366
+ "out_features": 2560,
1367
+ "parameters": 24903680,
1368
+ "probe_cosine": 0.9993191957473755,
1369
+ "precision": "mxfp8_w8a8"
1370
+ },
1371
+ {
1372
+ "name": "layers.20.attention.wqkv",
1373
+ "in_features": 2560,
1374
+ "out_features": 6144,
1375
+ "parameters": 15728640,
1376
+ "probe_cosine": 0.9993005990982056,
1377
+ "precision": "mxfp8_w8a8"
1378
+ },
1379
+ {
1380
+ "name": "layers.20.attention.wo",
1381
+ "in_features": 4096,
1382
+ "out_features": 2560,
1383
+ "parameters": 10485760,
1384
+ "probe_cosine": 0.999289870262146,
1385
+ "precision": "mxfp8_w8a8"
1386
+ },
1387
+ {
1388
+ "name": "layers.20.feed_forward.w1",
1389
+ "in_features": 2560,
1390
+ "out_features": 9728,
1391
+ "parameters": 24903680,
1392
+ "probe_cosine": 0.9953472018241882,
1393
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1394
+ },
1395
+ {
1396
+ "name": "layers.20.feed_forward.w3",
1397
+ "in_features": 2560,
1398
+ "out_features": 9728,
1399
+ "parameters": 24903680,
1400
+ "probe_cosine": 0.9954727292060852,
1401
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1402
+ },
1403
+ {
1404
+ "name": "layers.20.feed_forward.w2",
1405
+ "in_features": 9728,
1406
+ "out_features": 2560,
1407
+ "parameters": 24903680,
1408
+ "probe_cosine": 0.9993296265602112,
1409
+ "precision": "mxfp8_w8a8"
1410
+ },
1411
+ {
1412
+ "name": "layers.21.attention.wqkv",
1413
+ "in_features": 2560,
1414
+ "out_features": 6144,
1415
+ "parameters": 15728640,
1416
+ "probe_cosine": 0.9992555975914001,
1417
+ "precision": "mxfp8_w8a8"
1418
+ },
1419
+ {
1420
+ "name": "layers.21.attention.wo",
1421
+ "in_features": 4096,
1422
+ "out_features": 2560,
1423
+ "parameters": 10485760,
1424
+ "probe_cosine": 0.9992495775222778,
1425
+ "precision": "mxfp8_w8a8"
1426
+ },
1427
+ {
1428
+ "name": "layers.21.feed_forward.w1",
1429
+ "in_features": 2560,
1430
+ "out_features": 9728,
1431
+ "parameters": 24903680,
1432
+ "probe_cosine": 0.9953234195709229,
1433
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1434
+ },
1435
+ {
1436
+ "name": "layers.21.feed_forward.w3",
1437
+ "in_features": 2560,
1438
+ "out_features": 9728,
1439
+ "parameters": 24903680,
1440
+ "probe_cosine": 0.9952938556671143,
1441
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1442
+ },
1443
+ {
1444
+ "name": "layers.21.feed_forward.w2",
1445
+ "in_features": 9728,
1446
+ "out_features": 2560,
1447
+ "parameters": 24903680,
1448
+ "probe_cosine": 0.9992718696594238,
1449
+ "precision": "mxfp8_w8a8"
1450
+ },
1451
+ {
1452
+ "name": "layers.22.attention.wqkv",
1453
+ "in_features": 2560,
1454
+ "out_features": 6144,
1455
+ "parameters": 15728640,
1456
+ "probe_cosine": 0.9992914199829102,
1457
+ "precision": "mxfp8_w8a8"
1458
+ },
1459
+ {
1460
+ "name": "layers.22.attention.wo",
1461
+ "in_features": 4096,
1462
+ "out_features": 2560,
1463
+ "parameters": 10485760,
1464
+ "probe_cosine": 0.9992764592170715,
1465
+ "precision": "mxfp8_w8a8"
1466
+ },
1467
+ {
1468
+ "name": "layers.22.feed_forward.w1",
1469
+ "in_features": 2560,
1470
+ "out_features": 9728,
1471
+ "parameters": 24903680,
1472
+ "probe_cosine": 0.9949873089790344,
1473
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1474
+ },
1475
+ {
1476
+ "name": "layers.22.feed_forward.w3",
1477
+ "in_features": 2560,
1478
+ "out_features": 9728,
1479
+ "parameters": 24903680,
1480
+ "probe_cosine": 0.9951849579811096,
1481
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1482
+ },
1483
+ {
1484
+ "name": "layers.22.feed_forward.w2",
1485
+ "in_features": 9728,
1486
+ "out_features": 2560,
1487
+ "parameters": 24903680,
1488
+ "probe_cosine": 0.9992700815200806,
1489
+ "precision": "mxfp8_w8a8"
1490
+ },
1491
+ {
1492
+ "name": "layers.23.attention.wqkv",
1493
+ "in_features": 2560,
1494
+ "out_features": 6144,
1495
+ "parameters": 15728640,
1496
+ "probe_cosine": 0.99925696849823,
1497
+ "precision": "mxfp8_w8a8"
1498
+ },
1499
+ {
1500
+ "name": "layers.23.attention.wo",
1501
+ "in_features": 4096,
1502
+ "out_features": 2560,
1503
+ "parameters": 10485760,
1504
+ "probe_cosine": 0.9992924928665161,
1505
+ "precision": "mxfp8_w8a8"
1506
+ },
1507
+ {
1508
+ "name": "layers.23.feed_forward.w1",
1509
+ "in_features": 2560,
1510
+ "out_features": 9728,
1511
+ "parameters": 24903680,
1512
+ "probe_cosine": 0.9949401617050171,
1513
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1514
+ },
1515
+ {
1516
+ "name": "layers.23.feed_forward.w3",
1517
+ "in_features": 2560,
1518
+ "out_features": 9728,
1519
+ "parameters": 24903680,
1520
+ "probe_cosine": 0.995291531085968,
1521
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1522
+ },
1523
+ {
1524
+ "name": "layers.23.feed_forward.w2",
1525
+ "in_features": 9728,
1526
+ "out_features": 2560,
1527
+ "parameters": 24903680,
1528
+ "probe_cosine": 0.9993242025375366,
1529
+ "precision": "mxfp8_w8a8"
1530
+ },
1531
+ {
1532
+ "name": "layers.24.attention.wqkv",
1533
+ "in_features": 2560,
1534
+ "out_features": 6144,
1535
+ "parameters": 15728640,
1536
+ "probe_cosine": 0.9992597699165344,
1537
+ "precision": "mxfp8_w8a8"
1538
+ },
1539
+ {
1540
+ "name": "layers.24.attention.wo",
1541
+ "in_features": 4096,
1542
+ "out_features": 2560,
1543
+ "parameters": 10485760,
1544
+ "probe_cosine": 0.999344527721405,
1545
+ "precision": "mxfp8_w8a8"
1546
+ },
1547
+ {
1548
+ "name": "layers.24.feed_forward.w1",
1549
+ "in_features": 2560,
1550
+ "out_features": 9728,
1551
+ "parameters": 24903680,
1552
+ "probe_cosine": 0.9952665567398071,
1553
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1554
+ },
1555
+ {
1556
+ "name": "layers.24.feed_forward.w3",
1557
+ "in_features": 2560,
1558
+ "out_features": 9728,
1559
+ "parameters": 24903680,
1560
+ "probe_cosine": 0.9955209493637085,
1561
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1562
+ },
1563
+ {
1564
+ "name": "layers.24.feed_forward.w2",
1565
+ "in_features": 9728,
1566
+ "out_features": 2560,
1567
+ "parameters": 24903680,
1568
+ "probe_cosine": 0.9993101954460144,
1569
+ "precision": "mxfp8_w8a8"
1570
+ },
1571
+ {
1572
+ "name": "layers.25.attention.wqkv",
1573
+ "in_features": 2560,
1574
+ "out_features": 6144,
1575
+ "parameters": 15728640,
1576
+ "probe_cosine": 0.9993680715560913,
1577
+ "precision": "mxfp8_w8a8"
1578
+ },
1579
+ {
1580
+ "name": "layers.25.attention.wo",
1581
+ "in_features": 4096,
1582
+ "out_features": 2560,
1583
+ "parameters": 10485760,
1584
+ "probe_cosine": 0.9992563724517822,
1585
+ "precision": "mxfp8_w8a8"
1586
+ },
1587
+ {
1588
+ "name": "layers.25.feed_forward.w1",
1589
+ "in_features": 2560,
1590
+ "out_features": 9728,
1591
+ "parameters": 24903680,
1592
+ "probe_cosine": 0.9952845573425293,
1593
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1594
+ },
1595
+ {
1596
+ "name": "layers.25.feed_forward.w3",
1597
+ "in_features": 2560,
1598
+ "out_features": 9728,
1599
+ "parameters": 24903680,
1600
+ "probe_cosine": 0.9953001141548157,
1601
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1602
+ },
1603
+ {
1604
+ "name": "layers.25.feed_forward.w2",
1605
+ "in_features": 9728,
1606
+ "out_features": 2560,
1607
+ "parameters": 24903680,
1608
+ "probe_cosine": 0.9993116855621338,
1609
+ "precision": "mxfp8_w8a8"
1610
+ },
1611
+ {
1612
+ "name": "layers.26.attention.wqkv",
1613
+ "in_features": 2560,
1614
+ "out_features": 6144,
1615
+ "parameters": 15728640,
1616
+ "probe_cosine": 0.999308705329895,
1617
+ "precision": "mxfp8_w8a8"
1618
+ },
1619
+ {
1620
+ "name": "layers.26.attention.wo",
1621
+ "in_features": 4096,
1622
+ "out_features": 2560,
1623
+ "parameters": 10485760,
1624
+ "probe_cosine": 0.9992237091064453,
1625
+ "precision": "mxfp8_w8a8"
1626
+ },
1627
+ {
1628
+ "name": "layers.26.feed_forward.w1",
1629
+ "in_features": 2560,
1630
+ "out_features": 9728,
1631
+ "parameters": 24903680,
1632
+ "probe_cosine": 0.9952062368392944,
1633
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1634
+ },
1635
+ {
1636
+ "name": "layers.26.feed_forward.w3",
1637
+ "in_features": 2560,
1638
+ "out_features": 9728,
1639
+ "parameters": 24903680,
1640
+ "probe_cosine": 0.9953439831733704,
1641
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1642
+ },
1643
+ {
1644
+ "name": "layers.26.feed_forward.w2",
1645
+ "in_features": 9728,
1646
+ "out_features": 2560,
1647
+ "parameters": 24903680,
1648
+ "probe_cosine": 0.9993381500244141,
1649
+ "precision": "mxfp8_w8a8"
1650
+ },
1651
+ {
1652
+ "name": "layers.27.attention.wqkv",
1653
+ "in_features": 2560,
1654
+ "out_features": 6144,
1655
+ "parameters": 15728640,
1656
+ "probe_cosine": 0.9992940425872803,
1657
+ "precision": "mxfp8_w8a8"
1658
+ },
1659
+ {
1660
+ "name": "layers.27.attention.wo",
1661
+ "in_features": 4096,
1662
+ "out_features": 2560,
1663
+ "parameters": 10485760,
1664
+ "probe_cosine": 0.9992112517356873,
1665
+ "precision": "mxfp8_w8a8"
1666
+ },
1667
+ {
1668
+ "name": "layers.27.feed_forward.w1",
1669
+ "in_features": 2560,
1670
+ "out_features": 9728,
1671
+ "parameters": 24903680,
1672
+ "probe_cosine": 0.995395302772522,
1673
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1674
+ },
1675
+ {
1676
+ "name": "layers.27.feed_forward.w3",
1677
+ "in_features": 2560,
1678
+ "out_features": 9728,
1679
+ "parameters": 24903680,
1680
+ "probe_cosine": 0.9952636361122131,
1681
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1682
+ },
1683
+ {
1684
+ "name": "layers.27.feed_forward.w2",
1685
+ "in_features": 9728,
1686
+ "out_features": 2560,
1687
+ "parameters": 24903680,
1688
+ "probe_cosine": 0.9993325471878052,
1689
+ "precision": "mxfp8_w8a8"
1690
+ },
1691
+ {
1692
+ "name": "layers.28.attention.wqkv",
1693
+ "in_features": 2560,
1694
+ "out_features": 6144,
1695
+ "parameters": 15728640,
1696
+ "probe_cosine": 0.9993436336517334,
1697
+ "precision": "mxfp8_w8a8"
1698
+ },
1699
+ {
1700
+ "name": "layers.28.attention.wo",
1701
+ "in_features": 4096,
1702
+ "out_features": 2560,
1703
+ "parameters": 10485760,
1704
+ "probe_cosine": 0.9992949962615967,
1705
+ "precision": "mxfp8_w8a8"
1706
+ },
1707
+ {
1708
+ "name": "layers.28.feed_forward.w1",
1709
+ "in_features": 2560,
1710
+ "out_features": 9728,
1711
+ "parameters": 24903680,
1712
+ "probe_cosine": 0.9951224327087402,
1713
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1714
+ },
1715
+ {
1716
+ "name": "layers.28.feed_forward.w3",
1717
+ "in_features": 2560,
1718
+ "out_features": 9728,
1719
+ "parameters": 24903680,
1720
+ "probe_cosine": 0.9954068064689636,
1721
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1722
+ },
1723
+ {
1724
+ "name": "layers.28.feed_forward.w2",
1725
+ "in_features": 9728,
1726
+ "out_features": 2560,
1727
+ "parameters": 24903680,
1728
+ "probe_cosine": 0.9992546439170837,
1729
+ "precision": "mxfp8_w8a8"
1730
+ },
1731
+ {
1732
+ "name": "layers.29.attention.wqkv",
1733
+ "in_features": 2560,
1734
+ "out_features": 6144,
1735
+ "parameters": 15728640,
1736
+ "probe_cosine": 0.9993007183074951,
1737
+ "precision": "mxfp8_w8a8"
1738
+ },
1739
+ {
1740
+ "name": "layers.29.attention.wo",
1741
+ "in_features": 4096,
1742
+ "out_features": 2560,
1743
+ "parameters": 10485760,
1744
+ "probe_cosine": 0.9992722272872925,
1745
+ "precision": "mxfp8_w8a8"
1746
+ },
1747
+ {
1748
+ "name": "layers.29.feed_forward.w1",
1749
+ "in_features": 2560,
1750
+ "out_features": 9728,
1751
+ "parameters": 24903680,
1752
+ "probe_cosine": 0.9955875873565674,
1753
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1754
+ },
1755
+ {
1756
+ "name": "layers.29.feed_forward.w3",
1757
+ "in_features": 2560,
1758
+ "out_features": 9728,
1759
+ "parameters": 24903680,
1760
+ "probe_cosine": 0.9953714609146118,
1761
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1762
+ },
1763
+ {
1764
+ "name": "layers.29.feed_forward.w2",
1765
+ "in_features": 9728,
1766
+ "out_features": 2560,
1767
+ "parameters": 24903680,
1768
+ "probe_cosine": 0.9993128776550293,
1769
+ "precision": "mxfp8_w8a8"
1770
+ },
1771
+ {
1772
+ "name": "layers.30.attention.wqkv",
1773
+ "in_features": 2560,
1774
+ "out_features": 6144,
1775
+ "parameters": 15728640,
1776
+ "probe_cosine": 0.9992680549621582,
1777
+ "precision": "mxfp8_w8a8"
1778
+ },
1779
+ {
1780
+ "name": "layers.30.attention.wo",
1781
+ "in_features": 4096,
1782
+ "out_features": 2560,
1783
+ "parameters": 10485760,
1784
+ "probe_cosine": 0.9993020296096802,
1785
+ "precision": "mxfp8_w8a8"
1786
+ },
1787
+ {
1788
+ "name": "layers.30.feed_forward.w1",
1789
+ "in_features": 2560,
1790
+ "out_features": 9728,
1791
+ "parameters": 24903680,
1792
+ "probe_cosine": 0.9952709078788757,
1793
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1794
+ },
1795
+ {
1796
+ "name": "layers.30.feed_forward.w3",
1797
+ "in_features": 2560,
1798
+ "out_features": 9728,
1799
+ "parameters": 24903680,
1800
+ "probe_cosine": 0.9954016208648682,
1801
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1802
+ },
1803
+ {
1804
+ "name": "layers.30.feed_forward.w2",
1805
+ "in_features": 9728,
1806
+ "out_features": 2560,
1807
+ "parameters": 24903680,
1808
+ "probe_cosine": 0.99930739402771,
1809
+ "precision": "mxfp8_w8a8"
1810
+ },
1811
+ {
1812
+ "name": "layers.31.attention.wqkv",
1813
+ "in_features": 2560,
1814
+ "out_features": 6144,
1815
+ "parameters": 15728640,
1816
+ "probe_cosine": 0.9993473291397095,
1817
+ "precision": "mxfp8_w8a8"
1818
+ },
1819
+ {
1820
+ "name": "layers.31.attention.wo",
1821
+ "in_features": 4096,
1822
+ "out_features": 2560,
1823
+ "parameters": 10485760,
1824
+ "probe_cosine": 0.9992945194244385,
1825
+ "precision": "mxfp8_w8a8"
1826
+ },
1827
+ {
1828
+ "name": "layers.31.feed_forward.w1",
1829
+ "in_features": 2560,
1830
+ "out_features": 9728,
1831
+ "parameters": 24903680,
1832
+ "probe_cosine": 0.995145320892334,
1833
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1834
+ },
1835
+ {
1836
+ "name": "layers.31.feed_forward.w3",
1837
+ "in_features": 2560,
1838
+ "out_features": 9728,
1839
+ "parameters": 24903680,
1840
+ "probe_cosine": 0.9953712224960327,
1841
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1842
+ },
1843
+ {
1844
+ "name": "layers.31.feed_forward.w2",
1845
+ "in_features": 9728,
1846
+ "out_features": 2560,
1847
+ "parameters": 24903680,
1848
+ "probe_cosine": 0.9993300437927246,
1849
+ "precision": "mxfp8_w8a8"
1850
+ },
1851
+ {
1852
+ "name": "layers.32.attention.wqkv",
1853
+ "in_features": 2560,
1854
+ "out_features": 6144,
1855
+ "parameters": 15728640,
1856
+ "probe_cosine": 0.999280571937561,
1857
+ "precision": "mxfp8_w8a8"
1858
+ },
1859
+ {
1860
+ "name": "layers.32.attention.wo",
1861
+ "in_features": 4096,
1862
+ "out_features": 2560,
1863
+ "parameters": 10485760,
1864
+ "probe_cosine": 0.9992582201957703,
1865
+ "precision": "mxfp8_w8a8"
1866
+ },
1867
+ {
1868
+ "name": "layers.32.feed_forward.w1",
1869
+ "in_features": 2560,
1870
+ "out_features": 9728,
1871
+ "parameters": 24903680,
1872
+ "probe_cosine": 0.9953033924102783,
1873
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1874
+ },
1875
+ {
1876
+ "name": "layers.32.feed_forward.w3",
1877
+ "in_features": 2560,
1878
+ "out_features": 9728,
1879
+ "parameters": 24903680,
1880
+ "probe_cosine": 0.9953725934028625,
1881
+ "precision": "nvfp4_w4a16_through_m1_activation_scaled"
1882
+ },
1883
+ {
1884
+ "name": "layers.32.feed_forward.w2",
1885
+ "in_features": 9728,
1886
+ "out_features": 2560,
1887
+ "parameters": 24903680,
1888
+ "probe_cosine": 0.999283492565155,
1889
+ "precision": "mxfp8_w8a8"
1890
+ },
1891
+ {
1892
+ "name": "layers.33.attention.wqkv",
1893
+ "in_features": 2560,
1894
+ "out_features": 6144,
1895
+ "parameters": 15728640,
1896
+ "probe_cosine": 0.9993834495544434,
1897
+ "precision": "mxfp8_w8a8"
1898
+ },
1899
+ {
1900
+ "name": "layers.33.attention.wo",
1901
+ "in_features": 4096,
1902
+ "out_features": 2560,
1903
+ "parameters": 10485760,
1904
+ "probe_cosine": 0.9992942810058594,
1905
+ "precision": "mxfp8_w8a8"
1906
+ },
1907
+ {
1908
+ "name": "layers.33.feed_forward.w1",
1909
+ "in_features": 2560,
1910
+ "out_features": 9728,
1911
+ "parameters": 24903680,
1912
+ "probe_cosine": 0.9992245435714722,
1913
+ "precision": "mxfp8_w8a8"
1914
+ },
1915
+ {
1916
+ "name": "layers.33.feed_forward.w3",
1917
+ "in_features": 2560,
1918
+ "out_features": 9728,
1919
+ "parameters": 24903680,
1920
+ "probe_cosine": 0.999274492263794,
1921
+ "precision": "mxfp8_w8a8"
1922
+ },
1923
+ {
1924
+ "name": "layers.33.feed_forward.w2",
1925
+ "in_features": 9728,
1926
+ "out_features": 2560,
1927
+ "parameters": 24903680,
1928
+ "probe_cosine": 0.9992848038673401,
1929
+ "precision": "mxfp8_w8a8"
1930
+ },
1931
+ {
1932
+ "name": "layers.34.attention.wqkv",
1933
+ "in_features": 2560,
1934
+ "out_features": 6144,
1935
+ "parameters": 15728640,
1936
+ "probe_cosine": 0.9992939233779907,
1937
+ "precision": "mxfp8_w8a8"
1938
+ },
1939
+ {
1940
+ "name": "layers.34.attention.wo",
1941
+ "in_features": 4096,
1942
+ "out_features": 2560,
1943
+ "parameters": 10485760,
1944
+ "probe_cosine": 0.9992879629135132,
1945
+ "precision": "mxfp8_w8a8"
1946
+ },
1947
+ {
1948
+ "name": "layers.34.feed_forward.w1",
1949
+ "in_features": 2560,
1950
+ "out_features": 9728,
1951
+ "parameters": 24903680,
1952
+ "probe_cosine": 0.9993096590042114,
1953
+ "precision": "mxfp8_w8a8"
1954
+ },
1955
+ {
1956
+ "name": "layers.34.feed_forward.w3",
1957
+ "in_features": 2560,
1958
+ "out_features": 9728,
1959
+ "parameters": 24903680,
1960
+ "probe_cosine": 0.9992994070053101,
1961
+ "precision": "mxfp8_w8a8"
1962
+ },
1963
+ {
1964
+ "name": "layers.34.feed_forward.w2",
1965
+ "in_features": 9728,
1966
+ "out_features": 2560,
1967
+ "parameters": 24903680,
1968
+ "probe_cosine": 0.9992780685424805,
1969
+ "precision": "mxfp8_w8a8"
1970
+ },
1971
+ {
1972
+ "name": "layers.35.attention.wqkv",
1973
+ "in_features": 2560,
1974
+ "out_features": 6144,
1975
+ "parameters": 15728640,
1976
+ "probe_cosine": 0.9993366599082947,
1977
+ "precision": "mxfp8_w8a8"
1978
+ },
1979
+ {
1980
+ "name": "layers.35.attention.wo",
1981
+ "in_features": 4096,
1982
+ "out_features": 2560,
1983
+ "parameters": 10485760,
1984
+ "probe_cosine": 0.9992329478263855,
1985
+ "precision": "mxfp8_w8a8"
1986
+ },
1987
+ {
1988
+ "name": "layers.35.feed_forward.w1",
1989
+ "in_features": 2560,
1990
+ "out_features": 9728,
1991
+ "parameters": 24903680,
1992
+ "probe_cosine": 0.9992811679840088,
1993
+ "precision": "mxfp8_w8a8"
1994
+ },
1995
+ {
1996
+ "name": "layers.35.feed_forward.w3",
1997
+ "in_features": 2560,
1998
+ "out_features": 9728,
1999
+ "parameters": 24903680,
2000
+ "probe_cosine": 0.9993214011192322,
2001
+ "precision": "mxfp8_w8a8"
2002
+ },
2003
+ {
2004
+ "name": "layers.35.feed_forward.w2",
2005
+ "in_features": 9728,
2006
+ "out_features": 2560,
2007
+ "parameters": 24903680,
2008
+ "probe_cosine": 0.9992574453353882,
2009
+ "precision": "mxfp8_w8a8"
2010
+ }
2011
+ ]
2012
+ },
2013
+ "packed_tensor_counts": {
2014
+ "qdata": 60,
2015
+ "weight_block_scale": 60,
2016
+ "weight_scale": 60,
2017
+ "weight_fp8": 120,
2018
+ "weight_scale_storage": 120
2019
+ },
2020
+ "state_tensor_count": 598,
2021
+ "state_payload_bytes": 4903514352,
2022
+ "measured_runtime": {
2023
+ "loaded_allocation_bytes": 5744721408,
2024
+ "loaded_allocation_gib": 5.35,
2025
+ "note": "Measured with compact codec/reference offload and a 3072-token cache; not checkpoint file size.",
2026
+ "short_zero_shot_peak_gib_min": 5.607,
2027
+ "short_zero_shot_peak_gib_max": 5.769,
2028
+ "held_out_long_peak_gib": 7.561,
2029
+ "rtx5080_short_control_rtf": "approximately 1.05-1.06",
2030
+ "rtx5080_semantic_frames_per_second": "approximately 20.4-20.6",
2031
+ "rtx5060ti_focused_zero_shot_rtf": "approximately 2.06",
2032
+ "ordinary_segment_streaming": false
2033
+ },
2034
+ "qualification_evidence": {
2035
+ "outputs/quality-suite/audio-signal-gate-nvfp4-middle30-gate-up-english-profile-validation-20260826.json": {
2036
+ "sha256": "dead831243f3bbc8aa2f059158683433e317038ff2356459d186b39d2cd71a66",
2037
+ "bytes": 67309
2038
+ },
2039
+ "outputs/quality-suite/audio-signal-gate-nvfp4-middle30-gate-up-english-profile-long-20260826.json": {
2040
+ "sha256": "7604f81336f81ec43d41e0b6a168af6453b3a0fb504772e457c55c351ca7bdac",
2041
+ "bytes": 9054
2042
+ },
2043
+ "outputs/quality-suite/audio-signal-gate-nvfp4-middle30-gate-up-english-profile-api-default-3seed-20260826.json": {
2044
+ "sha256": "4ca0333e560ac8ae86bfefbf3e20fa8932a4e9e5a53755dd36ff80d9e0ebcb31",
2045
+ "bytes": 74872
2046
+ },
2047
+ "outputs/quality-suite/audio-signal-gate-nvfp4-middle30-gate-up-english-profile-controls-long-3seed-20260826.json": {
2048
+ "sha256": "f806dfe4294263f9f1d7418415fa610732541c1aaa37d010311e68e58855b188",
2049
+ "bytes": 75055
2050
+ },
2051
+ "outputs/quality-suite/asr-nvfp4-middle30-english-profile-validation-long-20260826.json": {
2052
+ "sha256": "4a914e3067249bb53527646a13f2f5b8671e8115945f1d639ec74f5aced18531",
2053
+ "bytes": 7532
2054
+ },
2055
+ "outputs/zero-shot/nvfp4-middle30-english-focused-fixed-reference-long-5seed-20260826/objective-speaker-prosody.json": {
2056
+ "sha256": "f706fb5d8e1f07abcecaf1b9a3756a3ce2fc0c4b5764170ec31a19173d2cf7d8",
2057
+ "bytes": 25395
2058
+ },
2059
+ "outputs/zero-shot/nvfp4-middle30-english-focused-fixed-reference-long-5seed-20260826/objective-asr.json": {
2060
+ "sha256": "94cf914803808154f5d5f23b82f50b726df97fff27ba3e4cce5cd1dfa2814e8d",
2061
+ "bytes": 15655
2062
+ }
2063
+ },
2064
+ "checksums": {
2065
+ ".source": {
2066
+ "sha256": "e5d3907e41ff60c4e50108a4fcc4b64de346d5a02aa45819211f0f364bfd8799",
2067
+ "bytes": 240
2068
+ },
2069
+ "LICENSE.md": {
2070
+ "sha256": "aa7d9206e9d710590987a3636934f643529c00cd490323594e6206aaa0c32d80",
2071
+ "bytes": 10360
2072
+ },
2073
+ "README.md": {
2074
+ "sha256": "c010e235b428b3a45f118df4e2eb9053278fbc85a5543deb542a60f5e239f18e",
2075
+ "bytes": 10945
2076
+ },
2077
+ "activation-scaling-report.json": {
2078
+ "sha256": "20024a68428ee44e4aa1b8101cc6357310d7670ebdd2ab87e91eb4f8f54d43ef",
2079
+ "bytes": 2657835
2080
+ },
2081
+ "chat_template.jinja": {
2082
+ "sha256": "87a2728cb8dc9fe424d624542f6060ec05a1d285ebbec578bb078900e33396b5",
2083
+ "bytes": 4116
2084
+ },
2085
+ "codec.pth": {
2086
+ "sha256": "74fc41c5a7151c6f350af8bd7e5d6e3accfcc7f3dfbfac23afd35af07052bb2f",
2087
+ "bytes": 1871099728
2088
+ },
2089
+ "config.json": {
2090
+ "sha256": "bd1b81bf140b1eac0a15fe75319f5552902ad3b9903d557ddada358aef743125",
2091
+ "bytes": 2139
2092
+ },
2093
+ "model-00001-of-00003.safetensors": {
2094
+ "sha256": "b304711a5a7a102dc27a49616048e72aca0c695ef4648e860a4b9b5f2c39d694",
2095
+ "bytes": 1992555752
2096
+ },
2097
+ "model-00002-of-00003.safetensors": {
2098
+ "sha256": "ab75ab15859d88276b88d9c4672f196489a71336fb062335f7833da8e35e277b",
2099
+ "bytes": 1984565944
2100
+ },
2101
+ "model-00003-of-00003.safetensors": {
2102
+ "sha256": "0187275d6a87c4879b24b54462d8b3f487318ab402213f27bc9cca017b7d3816",
2103
+ "bytes": 926458160
2104
+ },
2105
+ "model.safetensors.index.json": {
2106
+ "sha256": "25229032b7d5a846fb2f946c46a35229f79babc569dad1dbc577705d892b2fba",
2107
+ "bytes": 48027
2108
+ },
2109
+ "special_tokens_map.json": {
2110
+ "sha256": "c2ff18fde6e43b7408435bc8ed079af74531befba549358a97cbc59ce606bc6b",
2111
+ "bytes": 101864
2112
+ },
2113
+ "tokenizer.json": {
2114
+ "sha256": "f24e08099d45a8adf3f52f5f0b03276e433bb9d689bb15fcbcc48ce58744588b",
2115
+ "bytes": 12217872
2116
+ },
2117
+ "tokenizer_config.json": {
2118
+ "sha256": "b8d149343ae425b0da67e6708686aceb51be7815d9792f265fc12ff04d5e9856",
2119
+ "bytes": 860832
2120
+ }
2121
+ },
2122
+ "fresh_load_verification": {
2123
+ "status": "passed",
2124
+ "created_utc": "2026-08-27T04:52:43Z",
2125
+ "report": "outputs/nvfp4-checkpoint-verification/20260827/fresh-load/verification.json",
2126
+ "report_sha256": "b70642be85b6e908d8be45dd7cd59673d54f2213a100232b5190d9ba4568bd32",
2127
+ "all_14_artifact_checksums_verified": true,
2128
+ "bf16_source_projection_materialized": false,
2129
+ "nvfp4_modules": 60,
2130
+ "mxfp8_modules": 120,
2131
+ "meta_tensors": 0,
2132
+ "fixed_code_exact_match": true,
2133
+ "fixed_code_sha256": "64799db24ec3c4564bd901b06f868c3968297974b591fe46aa32cc930d8ed466"
2134
+ },
2135
+ "human_listening_correction": {
2136
+ "initial_unblinded_finding": "The standalone NVFP4 output sounded bland, monotone, robotic, flat, and insufficiently like the reference; explicit tags did not repair perceived expressiveness.",
2137
+ "bf16_control_finding": "The pinned BF16 base shared the broad expressiveness and speaker-likeness weakness versus VoxCPM2, so flat delivery alone is not NVFP4-specific damage.",
2138
+ "blind_gate_status": "single_listener_single_reference_english_clone_identity_pass",
2139
+ "blind_gate_response": "20260827T082148Z-5e83e8bb",
2140
+ "speaker_likeness": "all four BF16 and all four NVFP4 samples scored 5/5",
2141
+ "preferences": {
2142
+ "nvfp4": 2,
2143
+ "bf16": 1,
2144
+ "tie": 1
2145
+ },
2146
+ "mean_reference_style": {
2147
+ "nvfp4": 4.5,
2148
+ "bf16": 4.5
2149
+ },
2150
+ "mean_naturalness": {
2151
+ "nvfp4": 3.75,
2152
+ "bf16": 3.75
2153
+ },
2154
+ "limitation": "This does not qualify cloning across other speakers, languages, or recording conditions."
2155
+ },
2156
+ "scope_and_limitations": [
2157
+ "English automated signal, spectral, ASR, speaker-embedding, and held-out long-termination gates passed.",
2158
+ "A four-pair blind test with one listener and one consented English reference found no precision-specific speaker-identity loss versus BF16.",
2159
+ "S2-Pro BF16 and this V1 derivative both sounded flatter and less expressive than VoxCPM2 in the evaluated reference comparison; V1 does not claim to fix that inherited limitation.",
2160
+ "The objective speaker embedding saturated and did not predict human preference, so new voices still require listening evaluation.",
2161
+ "This policy is not qualified for other languages; use MXFP8 or BF16 when multilingual coverage matters.",
2162
+ "The runtime requires NVIDIA Blackwell SM120, CUDA 13.0, and the bundled/pinned software path.",
2163
+ "Loaded allocation is 5.350 GiB, but held-out long-form peak reached 7.561 GiB.",
2164
+ "The ordinary single-speaker API is not true low-latency semantic/audio streaming."
2165
+ ],
2166
+ "packaged_utc": "2026-08-27T08:41:54Z",
2167
+ "release": {
2168
+ "version": "1.0",
2169
+ "channel": "v1",
2170
+ "xpo3_release": false,
2171
+ "scope": "English-only research and non-commercial release",
2172
+ "repository_name": "ajh-code/Fish-Audio-S2-Pro-NVFP4-Balanced",
2173
+ "self_contained_weights": true,
2174
+ "display_name": "V1 · Fish Audio S2-Pro · NVFP4 Balanced",
2175
+ "profile": "balanced"
2176
+ },
2177
+ "conversion_implementation_files": {
2178
+ "experimental/nvfp4/checkpoint.py": {
2179
+ "sha256": "41870d3effbcf4e5647ba62e107bbacf0db172e963b0cf14a9503349858b7114",
2180
+ "bytes": 7342
2181
+ },
2182
+ "experimental/nvfp4/modules.py": {
2183
+ "sha256": "c12801c376ea3c74027e0ff6672c078858249c7c19b14bcc434b3af895a4ebf7",
2184
+ "bytes": 70176
2185
+ },
2186
+ "experimental/fp8/modules.py": {
2187
+ "sha256": "3c4b2f71d0c3f078ad5f295c6ada96a5eb4c9c63ea518177985bdd6112766c5a",
2188
+ "bytes": 10873
2189
+ }
2190
+ },
2191
+ "license": {
2192
+ "name": "Fish Audio Research License",
2193
+ "commercial_use": "requires a separate written license from Fish Audio",
2194
+ "notice_file": "Notice",
2195
+ "built_with_fish_audio": true
2196
+ }
2197
+ }
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Installed by install.sh after the pinned CUDA PyTorch wheels.
2
+ comfy-kitchen==0.2.22
3
+ huggingface-hub[cli]==0.34.4
4
+ requests==2.34.2
5
+ soundfile==0.14.0
runtime/experimental/fp8/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Project-local S2-Pro FP8 experiments."""
2
+
3
+ from .modules import MXFP8Linear, convert_s2_pro_mxfp8, load_mxfp8_checkpoint
4
+ from .server import launch_mxfp8_thread_safe_queue
5
+
6
+ __all__ = [
7
+ "MXFP8Linear",
8
+ "convert_s2_pro_mxfp8",
9
+ "launch_mxfp8_thread_safe_queue",
10
+ "load_mxfp8_checkpoint",
11
+ ]
runtime/experimental/fp8/modules.py ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Model-local MXFP8 projection modules for S2-Pro inference research."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from dataclasses import asdict, dataclass
8
+ from pathlib import Path
9
+
10
+ import torch
11
+ import torch.nn.functional as F
12
+ from torch import nn
13
+ from safetensors.torch import load_file
14
+
15
+ import fish_scales_ops as fso
16
+ from fish_speech.models.text2semantic.llama import (
17
+ BaseModelArgs,
18
+ DualARTransformer,
19
+ precompute_freqs_cis,
20
+ )
21
+ from fish_speech.tokenizer import FishTokenizer
22
+
23
+
24
+ @dataclass
25
+ class ConversionRecord:
26
+ name: str
27
+ in_features: int
28
+ out_features: int
29
+ parameters: int
30
+ probe_cosine: float
31
+
32
+
33
+ class MXFP8Linear(nn.Module):
34
+ """BF16-input linear using native 1x32 MXFP8 activation/weight GEMM."""
35
+
36
+ def __init__(
37
+ self,
38
+ weight_fp8: torch.Tensor,
39
+ weight_scale_storage: torch.Tensor,
40
+ *,
41
+ in_features: int,
42
+ out_features: int,
43
+ ) -> None:
44
+ super().__init__()
45
+ self.in_features = in_features
46
+ self.out_features = out_features
47
+ self.register_buffer("weight_fp8", weight_fp8)
48
+ # The SM120 kernel consumes K-major scales. Store their physical
49
+ # layout as a contiguous [K-block, N] tensor so safetensors can
50
+ # serialize it canonically; transpose restores the required view.
51
+ self.register_buffer("weight_scale_storage", weight_scale_storage)
52
+
53
+ @classmethod
54
+ @torch.inference_mode()
55
+ def from_linear(cls, linear: nn.Linear) -> "MXFP8Linear":
56
+ if linear.bias is not None:
57
+ raise ValueError("The initial S2-Pro MXFP8 path supports bias-free linears")
58
+ if linear.weight.device.type != "cuda":
59
+ raise ValueError("Quantize S2-Pro linears after moving them to CUDA")
60
+ if linear.weight.dtype != torch.bfloat16:
61
+ raise ValueError(f"Expected BF16 source weight, got {linear.weight.dtype}")
62
+ weight_fp8, weight_scale = fso.gemm.quantize_1x32_fp8(linear.weight)
63
+ return cls(
64
+ weight_fp8,
65
+ weight_scale.t().contiguous(),
66
+ in_features=linear.in_features,
67
+ out_features=linear.out_features,
68
+ )
69
+
70
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
71
+ if x.shape[-1] != self.in_features:
72
+ raise ValueError(
73
+ f"Expected input width {self.in_features}, got {x.shape[-1]}"
74
+ )
75
+ prefix = x.shape[:-1]
76
+ x_2d = x.reshape(-1, self.in_features).contiguous()
77
+ x_fp8, x_scale = fso.gemm.quantize_1x32_fp8(x_2d)
78
+ output = fso.gemm.linear_mxfp8(
79
+ x_fp8,
80
+ self.weight_fp8,
81
+ x_scale,
82
+ self.weight_scale_storage.t(),
83
+ )
84
+ return output.reshape(*prefix, self.out_features)
85
+
86
+ def extra_repr(self) -> str:
87
+ return (
88
+ f"in_features={self.in_features}, out_features={self.out_features}, "
89
+ "weight=MXFP8_1x32, activation=dynamic_MXFP8_1x32, output=BF16"
90
+ )
91
+
92
+
93
+ def _selected_slow_mlp(name: str, module: nn.Module) -> bool:
94
+ return (
95
+ isinstance(module, nn.Linear)
96
+ and name.startswith("layers.")
97
+ and ".feed_forward." in name
98
+ and name.rsplit(".", 1)[-1] in {"w1", "w2", "w3"}
99
+ )
100
+
101
+
102
+ def _selected_slow_transformer(name: str, module: nn.Module) -> bool:
103
+ return isinstance(module, nn.Linear) and name.startswith("layers.")
104
+
105
+
106
+ def _selected_fast_transformer(name: str, module: nn.Module) -> bool:
107
+ return isinstance(module, nn.Linear) and name.startswith("fast_layers.")
108
+
109
+
110
+ def _selected_all_transformers(name: str, module: nn.Module) -> bool:
111
+ return _selected_slow_transformer(name, module) or _selected_fast_transformer(
112
+ name, module
113
+ )
114
+
115
+
116
+ @torch.inference_mode()
117
+ def convert_s2_pro_mxfp8(
118
+ model: nn.Module,
119
+ *,
120
+ policy: str = "slow_mlp",
121
+ probe_seed: int = 20260817,
122
+ ) -> dict:
123
+ """Replace selected S2-Pro projections without patching global linear APIs."""
124
+ selectors = {
125
+ "slow_mlp": (_selected_slow_mlp, 108),
126
+ "slow_transformer": (_selected_slow_transformer, 180),
127
+ "fast_transformer": (_selected_fast_transformer, 20),
128
+ "all_transformers": (_selected_all_transformers, 200),
129
+ }
130
+ if policy not in selectors:
131
+ raise ValueError(f"Unsupported initial MXFP8 policy: {policy}")
132
+
133
+ selector, expected_modules = selectors[policy]
134
+
135
+ candidates = [
136
+ (name, module)
137
+ for name, module in model.named_modules()
138
+ if selector(name, module)
139
+ ]
140
+ if len(candidates) != expected_modules:
141
+ raise RuntimeError(
142
+ f"Expected {expected_modules} {policy} projections, found {len(candidates)}"
143
+ )
144
+
145
+ records = []
146
+ generator = torch.Generator(device=candidates[0][1].weight.device)
147
+ generator.manual_seed(probe_seed)
148
+ for name, linear in candidates:
149
+ parent_name, attribute = name.rsplit(".", 1)
150
+ parent = model.get_submodule(parent_name)
151
+ replacement = MXFP8Linear.from_linear(linear)
152
+
153
+ probe = torch.randn(
154
+ 1,
155
+ linear.in_features,
156
+ dtype=torch.bfloat16,
157
+ device=linear.weight.device,
158
+ generator=generator,
159
+ ) * 0.1
160
+ reference = F.linear(probe, linear.weight)
161
+ actual = replacement(probe)
162
+ probe_cosine = float(
163
+ F.cosine_similarity(
164
+ actual.float().flatten(), reference.float().flatten(), dim=0
165
+ ).item()
166
+ )
167
+ records.append(
168
+ ConversionRecord(
169
+ name=name,
170
+ in_features=linear.in_features,
171
+ out_features=linear.out_features,
172
+ parameters=linear.weight.numel(),
173
+ probe_cosine=probe_cosine,
174
+ )
175
+ )
176
+ setattr(parent, attribute, replacement)
177
+
178
+ torch.cuda.synchronize(candidates[0][1].weight.device)
179
+ serialized = [asdict(record) for record in records]
180
+ cosines = [record.probe_cosine for record in records]
181
+ return {
182
+ "policy": policy,
183
+ "modules": len(records),
184
+ "parameters": sum(record.parameters for record in records),
185
+ "theoretical_bf16_source_bytes": sum(
186
+ record.parameters * 2 for record in records
187
+ ),
188
+ "probe_cosine_min": min(cosines),
189
+ "probe_cosine_mean": sum(cosines) / len(cosines),
190
+ "probe_cosine_max": max(cosines),
191
+ "records": serialized,
192
+ }
193
+
194
+
195
+ def _sha256(path: Path) -> str:
196
+ digest = hashlib.sha256()
197
+ with path.open("rb") as handle:
198
+ while chunk := handle.read(8 * 1024 * 1024):
199
+ digest.update(chunk)
200
+ return digest.hexdigest()
201
+
202
+
203
+ def _install_empty_mxfp8_modules(model: nn.Module, policy: str) -> int:
204
+ selectors = {
205
+ "slow_transformer": (_selected_slow_transformer, 180),
206
+ }
207
+ if policy not in selectors:
208
+ raise ValueError(f"Unsupported artifact policy: {policy}")
209
+ selector, expected = selectors[policy]
210
+ names = [name for name, module in model.named_modules() if selector(name, module)]
211
+ if len(names) != expected:
212
+ raise RuntimeError(f"Expected {expected} artifact modules, found {len(names)}")
213
+ for name in names:
214
+ linear = model.get_submodule(name)
215
+ parent_name, attribute = name.rsplit(".", 1)
216
+ parent = model.get_submodule(parent_name)
217
+ replacement = MXFP8Linear(
218
+ torch.empty(
219
+ linear.out_features,
220
+ linear.in_features,
221
+ dtype=torch.float8_e4m3fn,
222
+ device="meta",
223
+ ),
224
+ torch.empty(
225
+ linear.in_features // 128,
226
+ linear.out_features,
227
+ dtype=torch.int32,
228
+ device="meta",
229
+ ),
230
+ in_features=linear.in_features,
231
+ out_features=linear.out_features,
232
+ )
233
+ setattr(parent, attribute, replacement)
234
+ return len(names)
235
+
236
+
237
+ @torch.inference_mode()
238
+ def load_mxfp8_checkpoint(
239
+ path: str | Path,
240
+ *,
241
+ device: str | torch.device = "cuda:0",
242
+ max_length: int = 4096,
243
+ verify_checksums: bool = False,
244
+ ) -> DualARTransformer:
245
+ """Load the canonical checkpoint without materializing BF16 FP8 sources."""
246
+ path = Path(path)
247
+ metadata = json.loads((path / "quantization.json").read_text())
248
+ if metadata["format"] != "fish-s2-pro-project-local-mxfp8":
249
+ raise ValueError(f"Unsupported checkpoint format: {metadata['format']}")
250
+ if torch.cuda.get_device_capability(device)[0] != 12:
251
+ raise RuntimeError("This MXFP8 artifact currently requires sm_120")
252
+ if verify_checksums:
253
+ for filename, record in metadata["checksums"].items():
254
+ file_path = path / filename
255
+ if file_path.stat().st_size != record["bytes"]:
256
+ raise RuntimeError(f"Size mismatch for {filename}")
257
+ if _sha256(file_path) != record["sha256"]:
258
+ raise RuntimeError(f"SHA256 mismatch for {filename}")
259
+
260
+ config = BaseModelArgs.from_pretrained(str(path))
261
+ config.max_seq_len = max_length
262
+ with torch.device("meta"):
263
+ model = DualARTransformer(config)
264
+ model.tokenizer = FishTokenizer.from_pretrained(path)
265
+ _install_empty_mxfp8_modules(model, metadata["policy"])
266
+
267
+ index_path = path / "model.safetensors.index.json"
268
+ if index_path.is_file():
269
+ index = json.loads(index_path.read_text())
270
+ shard_names = sorted(set(index["weight_map"].values()))
271
+ else:
272
+ shard_names = ["model.safetensors"]
273
+ expected_keys = set(model.state_dict())
274
+ loaded_keys: set[str] = set()
275
+ for shard_name in shard_names:
276
+ shard = load_file(path / shard_name, device="cpu")
277
+ unexpected = set(shard) - expected_keys
278
+ if unexpected:
279
+ raise RuntimeError(
280
+ f"Unexpected checkpoint tensors in {shard_name}: {sorted(unexpected)[:5]}"
281
+ )
282
+ model.load_state_dict(shard, strict=False, assign=True)
283
+ loaded_keys.update(shard)
284
+ missing = expected_keys - loaded_keys
285
+ if missing:
286
+ raise RuntimeError(f"Missing checkpoint tensors: {sorted(missing)[:5]}")
287
+
288
+ # These buffers are intentionally non-persistent and were meta tensors.
289
+ model.freqs_cis = precompute_freqs_cis(
290
+ config.max_seq_len,
291
+ config.head_dim,
292
+ config.rope_base,
293
+ )
294
+ model.causal_mask = torch.tril(
295
+ torch.ones(config.max_seq_len, config.max_seq_len, dtype=torch.bool)
296
+ )
297
+ model.fast_freqs_cis = precompute_freqs_cis(
298
+ config.num_codebooks,
299
+ config.fast_head_dim,
300
+ config.rope_base,
301
+ )
302
+ model = model.to(device=device).eval()
303
+ model.fixed_temperature = torch.tensor(0.7, device=device, dtype=torch.float)
304
+ model.fixed_top_p = torch.tensor(0.7, device=device, dtype=torch.float)
305
+ model.fixed_repetition_penalty = torch.tensor(1.5, device=device, dtype=torch.float)
306
+ model._cache_setup_done = False
307
+ return model
runtime/experimental/fp8/server.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Threaded Fish Speech inference queue for the canonical MXFP8 checkpoint."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import queue
6
+ import threading
7
+ import traceback
8
+ from pathlib import Path
9
+
10
+ import torch
11
+ from loguru import logger
12
+
13
+ from fish_speech.models.text2semantic.inference import (
14
+ GenerateRequest,
15
+ WrappedGenerateResponse,
16
+ decode_one_token_ar,
17
+ generate_long,
18
+ )
19
+
20
+ from .modules import MXFP8Linear, load_mxfp8_checkpoint
21
+
22
+
23
+ def launch_mxfp8_thread_safe_queue(
24
+ checkpoint_path: str | Path,
25
+ device: str | torch.device,
26
+ precision: torch.dtype,
27
+ compile: bool = False,
28
+ *,
29
+ max_length: int = 4096,
30
+ verify_checksums: bool = False,
31
+ ) -> queue.Queue:
32
+ """Load MXFP8 once and serialize Fish Speech generation through a queue."""
33
+
34
+ if precision is not torch.bfloat16:
35
+ raise ValueError("The qualified MXFP8 service requires BF16 exclusions")
36
+ if compile:
37
+ raise ValueError("torch.compile is not qualified for the MXFP8 API service")
38
+ if max_length < 1024:
39
+ raise ValueError("MXFP8 API cache length must be at least 1024")
40
+
41
+ input_queue: queue.Queue = queue.Queue()
42
+ init_event = threading.Event()
43
+ init_error: list[BaseException] = []
44
+
45
+ def worker() -> None:
46
+ try:
47
+ model = load_mxfp8_checkpoint(
48
+ checkpoint_path,
49
+ device=device,
50
+ max_length=max_length,
51
+ verify_checksums=verify_checksums,
52
+ )
53
+ with torch.device(device):
54
+ model.setup_caches(
55
+ max_batch_size=1,
56
+ max_seq_len=model.config.max_seq_len,
57
+ dtype=torch.bfloat16,
58
+ )
59
+ model._cache_setup_done = True
60
+ module_count = sum(
61
+ isinstance(module, MXFP8Linear) for module in model.modules()
62
+ )
63
+ if module_count != 180:
64
+ raise RuntimeError(
65
+ f"Expected 180 native MXFP8 projections, found {module_count}"
66
+ )
67
+ logger.info(
68
+ "Loaded qualified MXFP8 slow-transformer checkpoint with "
69
+ f"{module_count} native projections on {device}"
70
+ )
71
+ except BaseException as error:
72
+ init_error.append(error)
73
+ logger.error(traceback.format_exc())
74
+ init_event.set()
75
+ return
76
+
77
+ init_event.set()
78
+ while True:
79
+ item: GenerateRequest | None = input_queue.get()
80
+ if item is None:
81
+ break
82
+ response_queue = item.response_queue
83
+ try:
84
+ for chunk in generate_long(
85
+ model=model,
86
+ decode_one_token=decode_one_token_ar,
87
+ **item.request,
88
+ ):
89
+ response_queue.put(
90
+ WrappedGenerateResponse(status="success", response=chunk)
91
+ )
92
+ except Exception as error:
93
+ logger.error(traceback.format_exc())
94
+ response_queue.put(
95
+ WrappedGenerateResponse(status="error", response=error)
96
+ )
97
+ finally:
98
+ if torch.cuda.is_available():
99
+ torch.cuda.empty_cache()
100
+
101
+ threading.Thread(
102
+ target=worker,
103
+ name="fish-s2-pro-mxfp8-worker",
104
+ daemon=True,
105
+ ).start()
106
+ init_event.wait()
107
+ if init_error:
108
+ raise RuntimeError("MXFP8 model worker failed to initialize") from init_error[0]
109
+ return input_queue
runtime/experimental/nvfp4/__init__.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Project-local native NVFP4 experiments for Fish Audio S2-Pro."""
2
+
3
+ from .checkpoint import load_mixed_nvfp4_checkpoint
4
+ from .server import launch_mixed_nvfp4_thread_safe_queue
5
+
6
+ from .modules import (
7
+ NVFP4FeedForward,
8
+ NVFP4Linear,
9
+ NVFP4TransformerBlock,
10
+ apply_nvfp4_rounding_checkpoint,
11
+ convert_s2_pro_nvfp4,
12
+ load_direct_w4a4_m1_extension,
13
+ load_rmsnorm_nvfp4_m1_extension,
14
+ load_smallm_nvfp4_extension,
15
+ load_silu_product_nvfp4_m1_extension,
16
+ quantize_nvfp4,
17
+ )
18
+
19
+ __all__ = [
20
+ "NVFP4FeedForward",
21
+ "NVFP4Linear",
22
+ "NVFP4TransformerBlock",
23
+ "apply_nvfp4_rounding_checkpoint",
24
+ "convert_s2_pro_nvfp4",
25
+ "load_mixed_nvfp4_checkpoint",
26
+ "launch_mixed_nvfp4_thread_safe_queue",
27
+ "load_direct_w4a4_m1_extension",
28
+ "load_rmsnorm_nvfp4_m1_extension",
29
+ "load_smallm_nvfp4_extension",
30
+ "load_silu_product_nvfp4_m1_extension",
31
+ "quantize_nvfp4",
32
+ ]
runtime/experimental/nvfp4/checkpoint.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Standalone loader for project-local mixed NVFP4/MXFP8 S2-Pro checkpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ import torch
11
+ from safetensors.torch import load_file
12
+
13
+ from fish_speech.models.text2semantic.llama import (
14
+ BaseModelArgs,
15
+ DualARTransformer,
16
+ precompute_freqs_cis,
17
+ )
18
+ from fish_speech.tokenizer import FishTokenizer
19
+
20
+ from experimental.fp8 import MXFP8Linear
21
+ from .modules import NVFP4Linear
22
+
23
+
24
+ CHECKPOINT_FORMAT = "fish-s2-pro-project-local-nvfp4-mixed"
25
+
26
+
27
+ def _sha256(path: Path) -> str:
28
+ digest = hashlib.sha256()
29
+ with path.open("rb") as handle:
30
+ while chunk := handle.read(8 * 1024 * 1024):
31
+ digest.update(chunk)
32
+ return digest.hexdigest()
33
+
34
+
35
+ def _install_empty_projection(
36
+ model: DualARTransformer,
37
+ record: dict[str, Any],
38
+ *,
39
+ w4a16_max_m: int,
40
+ ) -> None:
41
+ name = str(record["name"])
42
+ in_features = int(record["in_features"])
43
+ out_features = int(record["out_features"])
44
+ precision = str(record["precision"])
45
+ original = model.get_submodule(name)
46
+ if not isinstance(original, torch.nn.Linear):
47
+ raise TypeError(f"Expected an unmodified Linear at {name}, got {type(original)}")
48
+ if (original.in_features, original.out_features) != (in_features, out_features):
49
+ raise ValueError(f"Checkpoint shape metadata does not match config at {name}")
50
+
51
+ if precision.startswith("nvfp4_w4a16_through_m"):
52
+ unsupported = (
53
+ "low_rank_corrected",
54
+ "sparse_channel_corrected",
55
+ "hadamard",
56
+ )
57
+ if any(marker in precision for marker in unsupported):
58
+ raise ValueError(
59
+ f"This standalone loader does not support corrected/rotated NVFP4: {name}"
60
+ )
61
+ replacement: torch.nn.Module = NVFP4Linear(
62
+ torch.empty(
63
+ out_features,
64
+ in_features // 2,
65
+ dtype=torch.uint8,
66
+ device="meta",
67
+ ),
68
+ torch.empty(
69
+ out_features,
70
+ in_features // 16,
71
+ dtype=torch.float8_e4m3fn,
72
+ device="meta",
73
+ ),
74
+ torch.empty((), dtype=torch.float32, device="meta"),
75
+ in_features=in_features,
76
+ out_features=out_features,
77
+ w4a16_max_m=w4a16_max_m,
78
+ )
79
+ elif precision == "mxfp8_w8a8":
80
+ replacement = MXFP8Linear(
81
+ torch.empty(
82
+ out_features,
83
+ in_features,
84
+ dtype=torch.float8_e4m3fn,
85
+ device="meta",
86
+ ),
87
+ torch.empty(
88
+ in_features // 128,
89
+ out_features,
90
+ dtype=torch.int32,
91
+ device="meta",
92
+ ),
93
+ in_features=in_features,
94
+ out_features=out_features,
95
+ )
96
+ else:
97
+ raise ValueError(f"Unsupported precision record for {name}: {precision}")
98
+
99
+ parent_name, attribute = name.rsplit(".", 1)
100
+ setattr(model.get_submodule(parent_name), attribute, replacement)
101
+
102
+
103
+ @torch.inference_mode()
104
+ def load_mixed_nvfp4_checkpoint(
105
+ path: str | Path,
106
+ *,
107
+ device: str | torch.device = "cuda:0",
108
+ max_length: int = 3072,
109
+ verify_checksums: bool = False,
110
+ ) -> DualARTransformer:
111
+ """Load a mixed checkpoint without materializing its BF16 source projections."""
112
+ path = Path(path)
113
+ metadata = json.loads((path / "quantization.json").read_text())
114
+ if metadata.get("format") != CHECKPOINT_FORMAT:
115
+ raise ValueError(f"Unsupported checkpoint format: {metadata.get('format')}")
116
+ device = torch.device(device)
117
+ if device.type != "cuda" or torch.cuda.get_device_capability(device)[0] != 12:
118
+ raise RuntimeError("This mixed NVFP4/MXFP8 artifact currently requires sm_120")
119
+ if verify_checksums:
120
+ for filename, record in metadata["checksums"].items():
121
+ file_path = path / filename
122
+ if file_path.stat().st_size != int(record["bytes"]):
123
+ raise RuntimeError(f"Size mismatch for {filename}")
124
+ if _sha256(file_path) != record["sha256"]:
125
+ raise RuntimeError(f"SHA256 mismatch for {filename}")
126
+
127
+ conversion = metadata["conversion"]
128
+ records = conversion["records"]
129
+ if len(records) != 180:
130
+ raise ValueError(f"Expected 180 mixed projection records, found {len(records)}")
131
+ if int(conversion["correction_parameters"]) != 0:
132
+ raise ValueError("This loader intentionally rejects correction-bearing artifacts")
133
+
134
+ config = BaseModelArgs.from_pretrained(str(path))
135
+ config.max_seq_len = max_length
136
+ with torch.device("meta"):
137
+ model = DualARTransformer(config)
138
+ model.tokenizer = FishTokenizer.from_pretrained(path)
139
+ for record in records:
140
+ _install_empty_projection(
141
+ model,
142
+ record,
143
+ w4a16_max_m=int(conversion["w4a16_max_m"]),
144
+ )
145
+
146
+ index_path = path / "model.safetensors.index.json"
147
+ if index_path.is_file():
148
+ index = json.loads(index_path.read_text())
149
+ shard_names = sorted(set(index["weight_map"].values()))
150
+ else:
151
+ shard_names = ["model.safetensors"]
152
+ expected_keys = set(model.state_dict())
153
+ loaded_keys: set[str] = set()
154
+ for shard_name in shard_names:
155
+ shard = load_file(path / shard_name, device="cpu")
156
+ unexpected = set(shard) - expected_keys
157
+ if unexpected:
158
+ raise RuntimeError(
159
+ f"Unexpected checkpoint tensors in {shard_name}: {sorted(unexpected)[:5]}"
160
+ )
161
+ model.load_state_dict(shard, strict=False, assign=True)
162
+ loaded_keys.update(shard)
163
+ missing = expected_keys - loaded_keys
164
+ if missing:
165
+ raise RuntimeError(f"Missing checkpoint tensors: {sorted(missing)[:5]}")
166
+
167
+ # These buffers are non-persistent, so reconstruct them after the meta load.
168
+ model.freqs_cis = precompute_freqs_cis(
169
+ config.max_seq_len,
170
+ config.head_dim,
171
+ config.rope_base,
172
+ )
173
+ model.causal_mask = torch.tril(
174
+ torch.ones(config.max_seq_len, config.max_seq_len, dtype=torch.bool)
175
+ )
176
+ model.fast_freqs_cis = precompute_freqs_cis(
177
+ config.num_codebooks,
178
+ config.fast_head_dim,
179
+ config.rope_base,
180
+ )
181
+ model = model.to(device=device).eval()
182
+ sampling = metadata.get("qualified_sampling", {})
183
+ model.fixed_temperature = torch.tensor(
184
+ sampling.get("temperature", 1.0), device=device, dtype=torch.float
185
+ )
186
+ model.fixed_top_p = torch.tensor(
187
+ sampling.get("top_p", 0.85), device=device, dtype=torch.float
188
+ )
189
+ model.fixed_repetition_penalty = torch.tensor(1.5, device=device, dtype=torch.float)
190
+ model._cache_setup_done = False
191
+
192
+ nvfp4_count = sum(isinstance(module, NVFP4Linear) for module in model.modules())
193
+ mxfp8_count = sum(isinstance(module, MXFP8Linear) for module in model.modules())
194
+ if (nvfp4_count, mxfp8_count) != (60, 120):
195
+ raise RuntimeError(
196
+ f"Expected 60 NVFP4 and 120 MXFP8 modules, got {nvfp4_count}/{mxfp8_count}"
197
+ )
198
+ meta_tensors = [
199
+ name for name, tensor in model.state_dict().items() if tensor.device.type == "meta"
200
+ ]
201
+ if meta_tensors:
202
+ raise RuntimeError(f"Checkpoint left meta tensors: {meta_tensors[:5]}")
203
+ return model
runtime/experimental/nvfp4/modules.py ADDED
@@ -0,0 +1,1761 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Portable native NVFP4 modules for the S2-Pro NVFP4 V1 runtime."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import os
8
+ import sys
9
+ from dataclasses import asdict, dataclass
10
+ from functools import lru_cache
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+ import numpy as np
15
+ import torch
16
+ import torch.nn.functional as F
17
+ from torch import nn
18
+ from torch.nn.attention import SDPBackend, sdpa_kernel
19
+
20
+ from fish_speech.models.text2semantic.llama import apply_rotary_emb
21
+
22
+
23
+ ROOT = Path(
24
+ os.environ.get("FISH_NVFP4_ROOT", Path(__file__).resolve().parents[3])
25
+ ).resolve()
26
+ NATIVE_SOURCE_ROOT = Path(
27
+ os.environ.get(
28
+ "FISH_NVFP4_NATIVE_ROOT",
29
+ ROOT / "runtime" / "native",
30
+ )
31
+ ).resolve()
32
+ BUILD_ROOT = Path(
33
+ os.environ.get(
34
+ "FISH_NVFP4_BUILD_ROOT",
35
+ ROOT / "runtime-data" / "torch-extensions",
36
+ )
37
+ ).resolve()
38
+ COMFY_KITCHEN_ROOT = os.environ.get("COMFY_KITCHEN_ROOT")
39
+ DIRECT_SOURCE_ROOT = NATIVE_SOURCE_ROOT / "direct_w4a4_m1"
40
+ SILU_PRODUCT_SOURCE_ROOT = NATIVE_SOURCE_ROOT / "silu_product_nvfp4_m1"
41
+ RMSNORM_SOURCE_ROOT = NATIVE_SOURCE_ROOT / "rmsnorm_nvfp4_m1"
42
+ SMALLM_SOURCE_ROOT = NATIVE_SOURCE_ROOT / "smallm_gemv"
43
+ DIRECT_SOURCE_FILES = (
44
+ "direct_w4a4_m1.cpp",
45
+ "direct_w4a4_m1.cu",
46
+ "direct_w4a4_m1.h",
47
+ )
48
+ SILU_PRODUCT_SOURCE_FILES = (
49
+ "silu_product_nvfp4_m1.cpp",
50
+ "silu_product_nvfp4_m1.cu",
51
+ "silu_product_nvfp4_m1.h",
52
+ )
53
+ RMSNORM_SOURCE_FILES = (
54
+ "rmsnorm_nvfp4_m1.cpp",
55
+ "rmsnorm_nvfp4_m1.cu",
56
+ "rmsnorm_nvfp4_m1.h",
57
+ )
58
+ SMALLM_SOURCE_FILES = (
59
+ "smallm_gemv.cpp",
60
+ "smallm_gemv.cu",
61
+ "smallm_gemv.h",
62
+ )
63
+
64
+ if COMFY_KITCHEN_ROOT and COMFY_KITCHEN_ROOT not in sys.path:
65
+ sys.path.insert(0, COMFY_KITCHEN_ROOT)
66
+
67
+ from comfy_kitchen.tensor import QuantizedTensor, TensorCoreNVFP4Layout
68
+
69
+
70
+ @dataclass
71
+ class ConversionRecord:
72
+ name: str
73
+ in_features: int
74
+ out_features: int
75
+ parameters: int
76
+ probe_cosine: float
77
+
78
+
79
+ @dataclass
80
+ class FusedMLPConversionRecord:
81
+ name: str
82
+ in_features: int
83
+ intermediate_features: int
84
+ out_features: int
85
+ parameters: int
86
+ probe_cosine: float
87
+
88
+
89
+ @dataclass
90
+ class FusedTransformerConversionRecord:
91
+ name: str
92
+ parameters: int
93
+ wqkv_probe_cosine: float
94
+ wo_probe_cosine: float
95
+ mlp_probe_cosine: float
96
+
97
+
98
+ def quantize_nvfp4(
99
+ value: torch.Tensor,
100
+ *,
101
+ scale: torch.Tensor | float | None = None,
102
+ ) -> QuantizedTensor:
103
+ """Apply the pinned tensor-wide dynamic NVFP4 policy."""
104
+ return QuantizedTensor.from_float(
105
+ value,
106
+ "TensorCoreNVFP4Layout",
107
+ scale=scale,
108
+ )
109
+
110
+
111
+ @torch.inference_mode()
112
+ def apply_nvfp4_rounding_checkpoint(
113
+ model: nn.Module,
114
+ checkpoint: Path | str,
115
+ ) -> dict[str, Any]:
116
+ """Apply a packed learned-rounding delta after ordinary model conversion."""
117
+
118
+ from safetensors.torch import load_file
119
+
120
+ checkpoint_path = Path(checkpoint)
121
+ if checkpoint_path.is_dir():
122
+ candidates = sorted(checkpoint_path.glob("*.safetensors"))
123
+ if len(candidates) != 1:
124
+ raise ValueError(
125
+ f"Expected one safetensors file in {checkpoint_path}, found {len(candidates)}"
126
+ )
127
+ checkpoint_path = candidates[0]
128
+ tensors = load_file(str(checkpoint_path), device=str(next(model.parameters()).device))
129
+ qdata_keys = sorted(key for key in tensors if key.endswith(".qdata"))
130
+ if not qdata_keys:
131
+ raise ValueError(f"No packed qdata entries in {checkpoint_path}")
132
+ records = []
133
+ for qdata_key in qdata_keys:
134
+ module_name = qdata_key.removesuffix(".qdata")
135
+ module = model.get_submodule(module_name)
136
+ if not isinstance(module, NVFP4Linear):
137
+ raise TypeError(f"Checkpoint target is not NVFP4Linear: {module_name}")
138
+ block_key = module_name + ".block_scale"
139
+ tensor_key = module_name + ".tensor_scale"
140
+ if block_key not in tensors or tensor_key not in tensors:
141
+ raise ValueError(f"Checkpoint lacks scales for {module_name}")
142
+ checkpoint_qdata = tensors[qdata_key]
143
+ checkpoint_block_scale = tensors[block_key]
144
+ checkpoint_tensor_scale = tensors[tensor_key]
145
+ if checkpoint_qdata.shape != module.qdata.shape:
146
+ raise ValueError(f"qdata shape mismatch for {module_name}")
147
+ if not torch.equal(checkpoint_block_scale, module.weight_block_scale):
148
+ raise ValueError(f"Block scale mismatch for {module_name}")
149
+ if not torch.equal(checkpoint_tensor_scale, module.weight_scale):
150
+ raise ValueError(f"Tensor scale mismatch for {module_name}")
151
+ changed_bytes = int((checkpoint_qdata != module.qdata).sum())
152
+ old_codes = torch.stack(
153
+ (module.qdata >> 4, module.qdata & 0x0F),
154
+ dim=-1,
155
+ )
156
+ new_codes = torch.stack(
157
+ (checkpoint_qdata >> 4, checkpoint_qdata & 0x0F),
158
+ dim=-1,
159
+ )
160
+ changed_weights = int((old_codes != new_codes).sum())
161
+ module.qdata.copy_(checkpoint_qdata)
162
+ records.append(
163
+ {
164
+ "module": module_name,
165
+ "changed_packed_bytes": changed_bytes,
166
+ "changed_weights": changed_weights,
167
+ "weights": module.out_features * module.in_features,
168
+ }
169
+ )
170
+ return {
171
+ "checkpoint": str(checkpoint_path),
172
+ "modules": len(records),
173
+ "changed_packed_bytes": sum(row["changed_packed_bytes"] for row in records),
174
+ "changed_weights": sum(row["changed_weights"] for row in records),
175
+ "records": records,
176
+ }
177
+
178
+
179
+ def _hadamard_blocks(value: torch.Tensor, block_size: int) -> torch.Tensor:
180
+ """Materialized orthonormal block Hadamard for quality prototypes."""
181
+ if block_size < 2 or block_size & (block_size - 1):
182
+ raise ValueError(f"Hadamard block size must be a power of two: {block_size}")
183
+ if value.shape[-1] % block_size:
184
+ raise ValueError(
185
+ f"Width {value.shape[-1]} is not divisible by block size {block_size}"
186
+ )
187
+ original_dtype = value.dtype
188
+ transformed = value.float().reshape(*value.shape[:-1], -1, block_size)
189
+ stride = 1
190
+ while stride < block_size:
191
+ pairs = transformed.reshape(
192
+ *transformed.shape[:-1],
193
+ block_size // (2 * stride),
194
+ 2,
195
+ stride,
196
+ )
197
+ left = pairs[..., 0, :]
198
+ right = pairs[..., 1, :]
199
+ transformed = torch.stack((left + right, left - right), dim=-2).reshape(
200
+ *transformed.shape
201
+ )
202
+ stride *= 2
203
+ return (transformed.reshape_as(value) / block_size**0.5).to(original_dtype)
204
+
205
+
206
+ def _direct_source_hash() -> str:
207
+ digest = hashlib.sha256()
208
+ for filename in DIRECT_SOURCE_FILES:
209
+ digest.update((DIRECT_SOURCE_ROOT / filename).read_bytes())
210
+ return digest.hexdigest()
211
+
212
+
213
+ def _source_hash(source_root: Path, filenames: tuple[str, ...]) -> str:
214
+ digest = hashlib.sha256()
215
+ for filename in filenames:
216
+ digest.update((source_root / filename).read_bytes())
217
+ return digest.hexdigest()
218
+
219
+
220
+ @lru_cache(maxsize=1)
221
+ def load_direct_w4a4_m1_extension(*, verbose: bool = False) -> Any:
222
+ """Build the pinned direct packed-NVFP4 M=1 primitive locally."""
223
+ from torch.utils.cpp_extension import load
224
+
225
+ missing = [
226
+ filename
227
+ for filename in DIRECT_SOURCE_FILES
228
+ if not (DIRECT_SOURCE_ROOT / filename).is_file()
229
+ ]
230
+ if missing:
231
+ raise RuntimeError(f"Missing pinned NVFP4 native sources: {missing}")
232
+ build_root = BUILD_ROOT / "direct_w4a4_m1"
233
+ build_root.mkdir(parents=True, exist_ok=True)
234
+ os.environ.setdefault("TORCH_CUDA_ARCH_LIST", "12.0")
235
+ os.environ.setdefault("MAX_JOBS", "2")
236
+ return load(
237
+ name=f"s2_pro_direct_w4a4_m1_{_direct_source_hash()[:12]}",
238
+ sources=[
239
+ str(DIRECT_SOURCE_ROOT / "direct_w4a4_m1.cpp"),
240
+ str(DIRECT_SOURCE_ROOT / "direct_w4a4_m1.cu"),
241
+ ],
242
+ extra_cflags=["-O3"],
243
+ extra_cuda_cflags=["-O3", "--use_fast_math", "-lineinfo"],
244
+ extra_include_paths=[str(DIRECT_SOURCE_ROOT)],
245
+ build_directory=str(build_root),
246
+ with_cuda=True,
247
+ verbose=verbose,
248
+ is_python_module=True,
249
+ )
250
+
251
+
252
+ @lru_cache(maxsize=1)
253
+ def load_silu_product_nvfp4_m1_extension(*, verbose: bool = False) -> Any:
254
+ """Build the pinned fused SiLU/product-to-NVFP4 M=1 primitive."""
255
+ from torch.utils.cpp_extension import load
256
+
257
+ missing = [
258
+ filename
259
+ for filename in SILU_PRODUCT_SOURCE_FILES
260
+ if not (SILU_PRODUCT_SOURCE_ROOT / filename).is_file()
261
+ ]
262
+ if missing:
263
+ raise RuntimeError(f"Missing pinned NVFP4 SiLU sources: {missing}")
264
+ build_root = BUILD_ROOT / "silu_product_nvfp4_m1"
265
+ build_root.mkdir(parents=True, exist_ok=True)
266
+ os.environ.setdefault("TORCH_CUDA_ARCH_LIST", "12.0")
267
+ os.environ.setdefault("MAX_JOBS", "2")
268
+ return load(
269
+ name=(
270
+ "s2_pro_silu_product_nvfp4_m1_"
271
+ f"{_source_hash(SILU_PRODUCT_SOURCE_ROOT, SILU_PRODUCT_SOURCE_FILES)[:12]}"
272
+ ),
273
+ sources=[
274
+ str(SILU_PRODUCT_SOURCE_ROOT / "silu_product_nvfp4_m1.cpp"),
275
+ str(SILU_PRODUCT_SOURCE_ROOT / "silu_product_nvfp4_m1.cu"),
276
+ ],
277
+ extra_cflags=["-O3"],
278
+ extra_cuda_cflags=["-O3", "--use_fast_math", "-lineinfo"],
279
+ extra_include_paths=[str(SILU_PRODUCT_SOURCE_ROOT)],
280
+ build_directory=str(build_root),
281
+ with_cuda=True,
282
+ verbose=verbose,
283
+ is_python_module=True,
284
+ )
285
+
286
+
287
+ @lru_cache(maxsize=1)
288
+ def load_rmsnorm_nvfp4_m1_extension(*, verbose: bool = False) -> Any:
289
+ """Build the pinned fused Fish-compatible RMSNorm-to-NVFP4 M=1 primitive."""
290
+ from torch.utils.cpp_extension import load
291
+
292
+ missing = [
293
+ filename
294
+ for filename in RMSNORM_SOURCE_FILES
295
+ if not (RMSNORM_SOURCE_ROOT / filename).is_file()
296
+ ]
297
+ if missing:
298
+ raise RuntimeError(f"Missing pinned NVFP4 RMSNorm sources: {missing}")
299
+ build_root = BUILD_ROOT / "rmsnorm_nvfp4_m1"
300
+ build_root.mkdir(parents=True, exist_ok=True)
301
+ os.environ.setdefault("TORCH_CUDA_ARCH_LIST", "12.0")
302
+ os.environ.setdefault("MAX_JOBS", "2")
303
+ return load(
304
+ name=(
305
+ "s2_pro_rmsnorm_nvfp4_m1_"
306
+ f"{_source_hash(RMSNORM_SOURCE_ROOT, RMSNORM_SOURCE_FILES)[:12]}"
307
+ ),
308
+ sources=[
309
+ str(RMSNORM_SOURCE_ROOT / "rmsnorm_nvfp4_m1.cpp"),
310
+ str(RMSNORM_SOURCE_ROOT / "rmsnorm_nvfp4_m1.cu"),
311
+ ],
312
+ extra_cflags=["-O3"],
313
+ extra_cuda_cflags=["-O3", "--use_fast_math", "-lineinfo"],
314
+ extra_include_paths=[str(RMSNORM_SOURCE_ROOT)],
315
+ build_directory=str(build_root),
316
+ with_cuda=True,
317
+ verbose=verbose,
318
+ is_python_module=True,
319
+ )
320
+
321
+
322
+ @lru_cache(maxsize=1)
323
+ def load_smallm_nvfp4_extension(*, verbose: bool = False) -> Any:
324
+ """Build the pinned packed-weight W4A16 small-M GEMV primitive."""
325
+ from torch.utils.cpp_extension import load
326
+
327
+ missing = [
328
+ filename
329
+ for filename in SMALLM_SOURCE_FILES
330
+ if not (SMALLM_SOURCE_ROOT / filename).is_file()
331
+ ]
332
+ if missing:
333
+ raise RuntimeError(f"Missing pinned NVFP4 small-M sources: {missing}")
334
+ build_root = BUILD_ROOT / "smallm_gemv"
335
+ build_root.mkdir(parents=True, exist_ok=True)
336
+ os.environ.setdefault("TORCH_CUDA_ARCH_LIST", "12.0")
337
+ os.environ.setdefault("MAX_JOBS", "2")
338
+ return load(
339
+ name=(
340
+ "s2_pro_smallm_nvfp4_"
341
+ f"{_source_hash(SMALLM_SOURCE_ROOT, SMALLM_SOURCE_FILES)[:12]}"
342
+ ),
343
+ sources=[
344
+ str(SMALLM_SOURCE_ROOT / "smallm_gemv.cpp"),
345
+ str(SMALLM_SOURCE_ROOT / "smallm_gemv.cu"),
346
+ ],
347
+ extra_cflags=["-O3"],
348
+ extra_cuda_cflags=["-O3", "--use_fast_math", "-lineinfo"],
349
+ extra_include_paths=[str(SMALLM_SOURCE_ROOT)],
350
+ build_directory=str(build_root),
351
+ with_cuda=True,
352
+ verbose=verbose,
353
+ is_python_module=True,
354
+ )
355
+
356
+
357
+ class NVFP4Linear(nn.Module):
358
+ """BF16-input linear using a native packed NVFP4 weight with BF16 output."""
359
+
360
+ def __init__(
361
+ self,
362
+ qdata: torch.Tensor,
363
+ weight_block_scale: torch.Tensor,
364
+ weight_scale: torch.Tensor,
365
+ *,
366
+ in_features: int,
367
+ out_features: int,
368
+ direct_m1: bool = False,
369
+ w4a16_max_m: int = 0,
370
+ correction_down: torch.Tensor | None = None,
371
+ correction_up: torch.Tensor | None = None,
372
+ sparse_correction_indices: torch.Tensor | None = None,
373
+ sparse_correction_weight: torch.Tensor | None = None,
374
+ input_hadamard_block_size: int = 0,
375
+ ) -> None:
376
+ super().__init__()
377
+ if w4a16_max_m < 0:
378
+ raise ValueError("w4a16_max_m must be nonnegative")
379
+ if direct_m1 and w4a16_max_m:
380
+ raise ValueError("Choose only one NVFP4 M=1 backend")
381
+ self.in_features = int(in_features)
382
+ self.out_features = int(out_features)
383
+ self.direct_m1 = bool(direct_m1)
384
+ self.w4a16_max_m = int(w4a16_max_m)
385
+ if input_hadamard_block_size and (
386
+ input_hadamard_block_size < 2
387
+ or input_hadamard_block_size & (input_hadamard_block_size - 1)
388
+ or self.in_features % input_hadamard_block_size
389
+ ):
390
+ raise ValueError(
391
+ "Input Hadamard block size must be a power of two that divides "
392
+ f"the input width, got {input_hadamard_block_size}"
393
+ )
394
+ self.input_hadamard_block_size = int(input_hadamard_block_size)
395
+ self.register_buffer("qdata", qdata)
396
+ self.register_buffer("weight_block_scale", weight_block_scale)
397
+ self.register_buffer("weight_scale", weight_scale)
398
+ if (correction_down is None) != (correction_up is None):
399
+ raise ValueError("Low-rank correction requires both down and up factors")
400
+ if correction_down is not None:
401
+ if correction_down.dim() != 2 or correction_up.dim() != 2:
402
+ raise ValueError("Low-rank correction factors must be 2D")
403
+ if correction_down.shape[1] != self.in_features:
404
+ raise ValueError("Low-rank down factor input width does not match")
405
+ if correction_up.shape != (self.out_features, correction_down.shape[0]):
406
+ raise ValueError("Low-rank up factor shape does not match")
407
+ self.register_buffer("correction_down", correction_down)
408
+ self.register_buffer("correction_up", correction_up)
409
+ if (sparse_correction_indices is None) != (sparse_correction_weight is None):
410
+ raise ValueError(
411
+ "Sparse correction requires both channel indices and a weight"
412
+ )
413
+ if sparse_correction_indices is not None:
414
+ if (
415
+ sparse_correction_indices.dim() != 1
416
+ or sparse_correction_indices.dtype != torch.int64
417
+ ):
418
+ raise ValueError("Sparse correction indices must be 1D int64")
419
+ if sparse_correction_weight.shape != (
420
+ self.out_features,
421
+ sparse_correction_indices.numel(),
422
+ ):
423
+ raise ValueError("Sparse correction weight shape does not match")
424
+ if sparse_correction_weight.dtype != torch.bfloat16:
425
+ raise ValueError("Sparse correction weight must be BF16")
426
+ if sparse_correction_indices.numel() and (
427
+ int(sparse_correction_indices.min()) < 0
428
+ or int(sparse_correction_indices.max()) >= self.in_features
429
+ ):
430
+ raise ValueError("Sparse correction channel index is out of range")
431
+ self.register_buffer("sparse_correction_indices", sparse_correction_indices)
432
+ self.register_buffer("sparse_correction_weight", sparse_correction_weight)
433
+
434
+ @classmethod
435
+ @torch.inference_mode()
436
+ def from_weight(
437
+ cls,
438
+ weight: torch.Tensor,
439
+ *,
440
+ direct_m1: bool = False,
441
+ w4a16_max_m: int = 0,
442
+ quantization_scale: torch.Tensor | float | None = None,
443
+ correction_down: torch.Tensor | None = None,
444
+ correction_up: torch.Tensor | None = None,
445
+ sparse_correction_indices: torch.Tensor | None = None,
446
+ sparse_correction_weight: torch.Tensor | None = None,
447
+ input_hadamard_block_size: int = 0,
448
+ ) -> "NVFP4Linear":
449
+ if weight.device.type != "cuda":
450
+ raise ValueError("Quantize S2-Pro weights after moving them to CUDA")
451
+ if weight.dtype != torch.bfloat16 or weight.dim() != 2:
452
+ raise ValueError(f"Expected a 2D BF16 source weight, got {weight.dtype} {weight.shape}")
453
+ packed = quantize_nvfp4(
454
+ weight.contiguous(),
455
+ scale=quantization_scale,
456
+ )
457
+ return cls(
458
+ packed._qdata,
459
+ packed._params.block_scale,
460
+ packed._params.scale,
461
+ in_features=weight.shape[1],
462
+ out_features=weight.shape[0],
463
+ direct_m1=direct_m1,
464
+ w4a16_max_m=w4a16_max_m,
465
+ correction_down=correction_down,
466
+ correction_up=correction_up,
467
+ sparse_correction_indices=sparse_correction_indices,
468
+ sparse_correction_weight=sparse_correction_weight,
469
+ input_hadamard_block_size=input_hadamard_block_size,
470
+ )
471
+
472
+ @classmethod
473
+ @torch.inference_mode()
474
+ def from_linear(
475
+ cls,
476
+ linear: nn.Linear,
477
+ *,
478
+ direct_m1: bool = False,
479
+ w4a16_max_m: int = 0,
480
+ ) -> "NVFP4Linear":
481
+ if linear.bias is not None:
482
+ raise ValueError("The initial S2-Pro NVFP4 path supports bias-free linears")
483
+ if linear.weight.device.type != "cuda":
484
+ raise ValueError("Quantize S2-Pro linears after moving them to CUDA")
485
+ if linear.weight.dtype != torch.bfloat16:
486
+ raise ValueError(f"Expected BF16 source weight, got {linear.weight.dtype}")
487
+ return cls.from_weight(
488
+ linear.weight,
489
+ direct_m1=direct_m1,
490
+ w4a16_max_m=w4a16_max_m,
491
+ )
492
+
493
+ def _weight_quantized_tensor(self) -> QuantizedTensor:
494
+ params = TensorCoreNVFP4Layout.Params(
495
+ scale=self.weight_scale,
496
+ orig_dtype=torch.bfloat16,
497
+ orig_shape=(self.out_features, self.in_features),
498
+ block_scale=self.weight_block_scale,
499
+ )
500
+ return QuantizedTensor(self.qdata, "TensorCoreNVFP4Layout", params)
501
+
502
+ def _direct(self, activation: QuantizedTensor) -> torch.Tensor:
503
+ params = activation._params
504
+ return load_direct_w4a4_m1_extension().linear(
505
+ activation._qdata,
506
+ params.block_scale,
507
+ params.scale,
508
+ self.qdata,
509
+ self.weight_block_scale,
510
+ self.weight_scale,
511
+ None,
512
+ )
513
+
514
+ def project_packed_m1(
515
+ self,
516
+ qdata: torch.Tensor,
517
+ block_scale: torch.Tensor,
518
+ tensor_scale: torch.Tensor,
519
+ ) -> torch.Tensor:
520
+ """Project an already packed logical M=1 activation without wrappers."""
521
+ return load_direct_w4a4_m1_extension().linear(
522
+ qdata,
523
+ block_scale,
524
+ tensor_scale,
525
+ self.qdata,
526
+ self.weight_block_scale,
527
+ self.weight_scale,
528
+ None,
529
+ )
530
+
531
+ def project_quantized(self, activation: QuantizedTensor) -> torch.Tensor:
532
+ logical_m = int(activation._params.orig_shape[0])
533
+ if self.direct_m1 and logical_m == 1:
534
+ return self._direct(activation)
535
+ return F.linear(activation, self._weight_quantized_tensor(), None)
536
+
537
+ def forward(self, value: torch.Tensor) -> torch.Tensor:
538
+ if value.shape[-1] != self.in_features:
539
+ raise ValueError(
540
+ f"Expected input width {self.in_features}, got {value.shape[-1]}"
541
+ )
542
+ input_shape = tuple(value.shape)
543
+ correction_input = value.reshape(-1, self.in_features).contiguous()
544
+ flattened = correction_input
545
+ if self.input_hadamard_block_size:
546
+ flattened = _hadamard_blocks(
547
+ flattened,
548
+ self.input_hadamard_block_size,
549
+ ).contiguous()
550
+ if 0 < flattened.shape[0] <= self.w4a16_max_m:
551
+ output = load_smallm_nvfp4_extension().linear(
552
+ flattened,
553
+ self.qdata,
554
+ self.weight_block_scale,
555
+ self.weight_scale,
556
+ None,
557
+ )
558
+ else:
559
+ activation = quantize_nvfp4(flattened)
560
+ output = self.project_quantized(activation)
561
+ if self.correction_down is not None:
562
+ correction = F.linear(
563
+ F.linear(correction_input, self.correction_down),
564
+ self.correction_up,
565
+ )
566
+ output = output + correction
567
+ if self.sparse_correction_indices is not None:
568
+ selected = correction_input.index_select(
569
+ 1,
570
+ self.sparse_correction_indices,
571
+ )
572
+ output = output + F.linear(selected, self.sparse_correction_weight)
573
+ return output.reshape(*input_shape[:-1], self.out_features)
574
+
575
+ def extra_repr(self) -> str:
576
+ backend = (
577
+ f"w4a16_through_m{self.w4a16_max_m}+w4a4_above_threshold"
578
+ if self.w4a16_max_m
579
+ else ("direct_m1+tensorcore" if self.direct_m1 else "tensorcore")
580
+ )
581
+ return (
582
+ f"in_features={self.in_features}, out_features={self.out_features}, "
583
+ f"weight=NVFP4_E2M1, activation=dynamic_NVFP4, output=BF16, backend={backend}, "
584
+ f"correction_rank={0 if self.correction_down is None else self.correction_down.shape[0]}, "
585
+ f"sparse_correction_channels="
586
+ f"{0 if self.sparse_correction_indices is None else self.sparse_correction_indices.numel()}, "
587
+ f"input_hadamard_block_size={self.input_hadamard_block_size}"
588
+ )
589
+
590
+
591
+ class NVFP4FeedForward(nn.Module):
592
+ """S2 SwiGLU with shared input packing and fused product packing at M=1."""
593
+
594
+ def __init__(
595
+ self,
596
+ w1: NVFP4Linear,
597
+ w2: NVFP4Linear,
598
+ w3: NVFP4Linear,
599
+ ) -> None:
600
+ super().__init__()
601
+ self.w1 = w1
602
+ self.w2 = w2
603
+ self.w3 = w3
604
+ self.decode_backend = "w4a16" if w1.w4a16_max_m else "w4a4"
605
+
606
+ @classmethod
607
+ @torch.inference_mode()
608
+ def from_module(
609
+ cls,
610
+ module: nn.Module,
611
+ *,
612
+ decode_backend: str = "w4a4",
613
+ w4a16_max_m: int = 1,
614
+ ) -> "NVFP4FeedForward":
615
+ if decode_backend not in {"w4a4", "w4a16"}:
616
+ raise ValueError(f"Unsupported NVFP4 MLP decode backend: {decode_backend}")
617
+ for name in ("w1", "w2", "w3"):
618
+ if not isinstance(getattr(module, name, None), nn.Linear):
619
+ raise TypeError(f"Expected BF16 FeedForward.{name} linear")
620
+ result = cls(
621
+ NVFP4Linear.from_linear(
622
+ module.w1,
623
+ direct_m1=decode_backend == "w4a4",
624
+ w4a16_max_m=(w4a16_max_m if decode_backend == "w4a16" else 0),
625
+ ),
626
+ NVFP4Linear.from_linear(
627
+ module.w2,
628
+ direct_m1=decode_backend == "w4a4",
629
+ w4a16_max_m=(w4a16_max_m if decode_backend == "w4a16" else 0),
630
+ ),
631
+ NVFP4Linear.from_linear(
632
+ module.w3,
633
+ direct_m1=decode_backend == "w4a4",
634
+ w4a16_max_m=(w4a16_max_m if decode_backend == "w4a16" else 0),
635
+ ),
636
+ )
637
+ result.decode_backend = decode_backend
638
+ return result
639
+
640
+ def _forward_m1(self, flattened: torch.Tensor) -> torch.Tensor:
641
+ if self.decode_backend == "w4a16":
642
+ return self.w2(F.silu(self.w1(flattened)) * self.w3(flattened))
643
+ packer = load_silu_product_nvfp4_m1_extension()
644
+ qdata, block_scale, tensor_scale = packer.quantize_input(flattened)
645
+ return self.forward_packed_m1(qdata, block_scale, tensor_scale)
646
+
647
+ def forward_packed_m1(
648
+ self,
649
+ qdata: torch.Tensor,
650
+ block_scale: torch.Tensor,
651
+ tensor_scale: torch.Tensor,
652
+ ) -> torch.Tensor:
653
+ """Consume an already packed normalized M=1 activation."""
654
+ packer = load_silu_product_nvfp4_m1_extension()
655
+ gate = self.w1.project_packed_m1(qdata, block_scale, tensor_scale)
656
+ up = self.w3.project_packed_m1(qdata, block_scale, tensor_scale)
657
+ product_qdata, product_block_scale, product_tensor_scale = packer.quantize(
658
+ gate, up
659
+ )
660
+ return self.w2.project_packed_m1(
661
+ product_qdata,
662
+ product_block_scale,
663
+ product_tensor_scale,
664
+ )
665
+
666
+ def _forward_tensorcore(self, flattened: torch.Tensor) -> torch.Tensor:
667
+ activation = quantize_nvfp4(flattened)
668
+ gate = self.w1.project_quantized(activation)
669
+ up = self.w3.project_quantized(activation)
670
+ return self.w2(F.silu(gate) * up)
671
+
672
+ def forward(self, value: torch.Tensor) -> torch.Tensor:
673
+ input_shape = tuple(value.shape)
674
+ flattened = value.reshape(-1, input_shape[-1]).contiguous()
675
+ if (
676
+ self.decode_backend == "w4a16"
677
+ and flattened.shape[0] <= self.w1.w4a16_max_m
678
+ ):
679
+ output = self.w2(F.silu(self.w1(flattened)) * self.w3(flattened))
680
+ elif flattened.shape[0] == 1:
681
+ output = self._forward_m1(flattened)
682
+ else:
683
+ output = self._forward_tensorcore(flattened)
684
+ return output.reshape(*input_shape[:-1], self.w2.out_features)
685
+
686
+ def extra_repr(self) -> str:
687
+ return (
688
+ f"decode_backend={self.decode_backend}, "
689
+ f"fused_silu_product_pack_m1={self.decode_backend == 'w4a4'}"
690
+ )
691
+
692
+
693
+ class NVFP4TransformerBlock(nn.Module):
694
+ """Slow S2 block with fused norm/MLP packing for autoregressive M=1."""
695
+
696
+ def __init__(self, source: nn.Module) -> None:
697
+ super().__init__()
698
+ source.attention.wqkv = NVFP4Linear.from_linear(
699
+ source.attention.wqkv, direct_m1=True
700
+ )
701
+ source.attention.wo = NVFP4Linear.from_linear(
702
+ source.attention.wo, direct_m1=True
703
+ )
704
+ self.attention = source.attention
705
+ self.feed_forward = NVFP4FeedForward.from_module(source.feed_forward)
706
+ self.ffn_norm = source.ffn_norm
707
+ self.attention_norm = source.attention_norm
708
+ self.train(source.training)
709
+
710
+ def _packed_norm(
711
+ self,
712
+ value: torch.Tensor,
713
+ norm: nn.Module,
714
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
715
+ flattened = value.reshape(-1, value.shape[-1]).contiguous()
716
+ return tuple(
717
+ load_rmsnorm_nvfp4_m1_extension().quantize(
718
+ flattened,
719
+ norm.weight.contiguous(),
720
+ float(norm.eps),
721
+ )
722
+ )
723
+
724
+ def _attention_m1(
725
+ self,
726
+ x: torch.Tensor,
727
+ packed_norm: tuple[torch.Tensor, torch.Tensor, torch.Tensor],
728
+ freqs_cis: torch.Tensor,
729
+ mask: torch.Tensor | None,
730
+ input_pos: torch.Tensor | None,
731
+ ) -> torch.Tensor:
732
+ attention = self.attention
733
+ bsz, seqlen, _ = x.shape
734
+ qkv = attention.wqkv.project_packed_m1(*packed_norm)
735
+ q_size = attention.n_head * attention.head_dim
736
+ kv_size = attention.n_local_heads * attention.head_dim
737
+ q, k, v = qkv.split([q_size, kv_size, kv_size], dim=-1)
738
+ q = q.view(bsz, seqlen, attention.n_head, attention.head_dim)
739
+ k = k.view(bsz, seqlen, attention.n_local_heads, attention.head_dim)
740
+ v = v.view(bsz, seqlen, attention.n_local_heads, attention.head_dim)
741
+ if attention.attention_qk_norm:
742
+ q = attention.q_norm(q)
743
+ k = attention.k_norm(k)
744
+ q = apply_rotary_emb(q, freqs_cis)
745
+ k = apply_rotary_emb(k, freqs_cis)
746
+ q, k, v = (item.transpose(1, 2) for item in (q, k, v))
747
+ if attention.kv_cache is not None:
748
+ k, v = attention.kv_cache.update(input_pos, k, v)
749
+ repeat = attention.n_head // attention.n_local_heads
750
+ k = k.repeat_interleave(repeat, dim=1)
751
+ v = v.repeat_interleave(repeat, dim=1)
752
+ if attention.use_sdpa:
753
+ if mask is None:
754
+ with sdpa_kernel(SDPBackend.FLASH_ATTENTION):
755
+ y = F.scaled_dot_product_attention(
756
+ q,
757
+ k,
758
+ v,
759
+ dropout_p=attention.dropout if attention.training else 0.0,
760
+ is_causal=True,
761
+ )
762
+ else:
763
+ y = F.scaled_dot_product_attention(
764
+ q,
765
+ k,
766
+ v,
767
+ attn_mask=mask,
768
+ dropout_p=attention.dropout if attention.training else 0.0,
769
+ )
770
+ else:
771
+ y = attention.eq_scaled_dot_product_attention(q, k, v, attn_mask=mask)
772
+ y = y.transpose(1, 2).contiguous().view(bsz, seqlen, q_size)
773
+ y_flat = y.reshape(-1, q_size)
774
+ output_pack = load_silu_product_nvfp4_m1_extension().quantize_input(y_flat)
775
+ return attention.wo.project_packed_m1(*output_pack).reshape(
776
+ bsz, seqlen, attention.dim
777
+ )
778
+
779
+ def forward(
780
+ self,
781
+ x: torch.Tensor,
782
+ freqs_cis: torch.Tensor,
783
+ mask: torch.Tensor,
784
+ input_pos: torch.Tensor | None = None,
785
+ ) -> torch.Tensor:
786
+ if x.reshape(-1, x.shape[-1]).shape[0] != 1:
787
+ h = x + self.attention(
788
+ self.attention_norm(x), freqs_cis, mask, input_pos
789
+ )
790
+ return h + self.feed_forward(self.ffn_norm(h))
791
+ attention_pack = self._packed_norm(x, self.attention_norm)
792
+ h = x + self._attention_m1(x, attention_pack, freqs_cis, mask, input_pos)
793
+ ffn_pack = self._packed_norm(h, self.ffn_norm)
794
+ feed_forward = self.feed_forward.forward_packed_m1(*ffn_pack)
795
+ return h + feed_forward.reshape_as(h)
796
+
797
+ def extra_repr(self) -> str:
798
+ return "fused_rmsnorm_pack_m1=True, fused_mlp_pack_m1=True"
799
+
800
+
801
+ def _selected_slow_mlp(name: str, module: nn.Module) -> bool:
802
+ return (
803
+ isinstance(module, nn.Linear)
804
+ and name.startswith("layers.")
805
+ and ".feed_forward." in name
806
+ and name.rsplit(".", 1)[-1] in {"w1", "w2", "w3"}
807
+ )
808
+
809
+
810
+ def _selected_slow_transformer(name: str, module: nn.Module) -> bool:
811
+ return isinstance(module, nn.Linear) and name.startswith("layers.")
812
+
813
+
814
+ def _selected_slow_attention(name: str, module: nn.Module) -> bool:
815
+ return (
816
+ isinstance(module, nn.Linear)
817
+ and name.startswith("layers.")
818
+ and ".attention." in name
819
+ and name.rsplit(".", 1)[-1] in {"wqkv", "wo"}
820
+ )
821
+
822
+
823
+ def _selected_slow_mlp_block(name: str, module: nn.Module) -> bool:
824
+ return (
825
+ name.startswith("layers.")
826
+ and name.endswith(".feed_forward")
827
+ and all(isinstance(getattr(module, role, None), nn.Linear) for role in ("w1", "w2", "w3"))
828
+ )
829
+
830
+
831
+ def _selected_slow_transformer_block(name: str, module: nn.Module) -> bool:
832
+ parts = name.split(".")
833
+ return (
834
+ len(parts) == 2
835
+ and parts[0] == "layers"
836
+ and parts[1].isdigit()
837
+ and hasattr(module, "attention")
838
+ and hasattr(module, "feed_forward")
839
+ and hasattr(module, "attention_norm")
840
+ and hasattr(module, "ffn_norm")
841
+ )
842
+
843
+
844
+ def _packed_weight_bytes(model: nn.Module) -> int:
845
+ return sum(
846
+ int(module.qdata.numel() * module.qdata.element_size())
847
+ + int(module.weight_block_scale.numel() * module.weight_block_scale.element_size())
848
+ + int(module.weight_scale.numel() * module.weight_scale.element_size())
849
+ for module in model.modules()
850
+ if isinstance(module, NVFP4Linear)
851
+ )
852
+
853
+
854
+ def _resolve_workspace_path(value: str | Path, *, relative_to: Path) -> Path:
855
+ path = Path(value)
856
+ if path.is_absolute():
857
+ return path
858
+ relative_candidate = relative_to / path
859
+ if relative_candidate.exists():
860
+ return relative_candidate
861
+ return ROOT / path
862
+
863
+
864
+ def _clip_weight_blocks(weight: torch.Tensor, ratio: float) -> torch.Tensor:
865
+ if ratio == 1.0:
866
+ return weight
867
+ if not 0 < ratio <= 1:
868
+ raise ValueError(f"NVFP4 clip ratio must be in (0,1], got {ratio}")
869
+ if weight.shape[1] % 128:
870
+ raise ValueError(f"Input width must be divisible by 128, got {weight.shape}")
871
+ blocks = weight.float().reshape(weight.shape[0], -1, 128)
872
+ threshold = blocks.abs().amax(dim=-1, keepdim=True) * ratio
873
+ return torch.clamp(blocks, min=-threshold, max=threshold).reshape_as(weight)
874
+
875
+
876
+ @torch.inference_mode()
877
+ def _prepare_activation_scaling(
878
+ model: nn.Module,
879
+ report_path: Path,
880
+ selected_layers: set[int],
881
+ *,
882
+ fold_norms: bool = True,
883
+ ) -> tuple[
884
+ dict[int, torch.Tensor],
885
+ dict[int, float],
886
+ dict[int, dict[str, float]],
887
+ dict[int, dict[str, torch.Tensor]],
888
+ dict[str, Any],
889
+ ]:
890
+ sweep = json.loads(report_path.read_text())
891
+ calibration_values = sweep.get("calibration_reports")
892
+ if calibration_values is None:
893
+ calibration_values = [sweep["calibration_report"]]
894
+ calibration_report_paths = [
895
+ _resolve_workspace_path(value, relative_to=report_path.parent)
896
+ for value in calibration_values
897
+ ]
898
+ calibrations = []
899
+ activation_sets = []
900
+ for calibration_report_path in calibration_report_paths:
901
+ calibration = json.loads(calibration_report_path.read_text())
902
+ with np.load(calibration_report_path.parent / calibration["arrays"]) as values:
903
+ activation_sets.append(values["activations"].copy())
904
+ calibrations.append(calibration)
905
+ activations = np.concatenate(activation_sets, axis=1)
906
+ rows = {int(row["layer"]): row for row in sweep["results"]}
907
+ missing = sorted(selected_layers - rows.keys())
908
+ if missing:
909
+ raise ValueError(f"Activation-scaling report lacks layers: {missing}")
910
+ clamp = float(sweep["scale_clamp"])
911
+ activation_statistic = sweep.get("activation_statistic", "absmax")
912
+ scales: dict[int, torch.Tensor] = {}
913
+ clip_ratios: dict[int, float] = {}
914
+ quantization_scales: dict[int, dict[str, float]] = {}
915
+ corrections: dict[int, dict[str, torch.Tensor]] = {}
916
+ correction_tensors = None
917
+ correction_tensors_value = sweep.get("correction_tensors")
918
+ if correction_tensors_value is not None:
919
+ from safetensors.torch import load_file
920
+
921
+ correction_path = _resolve_workspace_path(
922
+ correction_tensors_value,
923
+ relative_to=report_path.parent,
924
+ )
925
+ correction_tensors = load_file(
926
+ correction_path,
927
+ device=str(model.layers[0].ffn_norm.weight.device),
928
+ )
929
+ records = []
930
+ for layer_index in sorted(selected_layers):
931
+ block = model.layers[layer_index]
932
+ gate = block.feed_forward.w1.weight
933
+ up = block.feed_forward.w3.weight
934
+ row = rows[layer_index]
935
+ improvement = float(row["improvement_fraction_vs_unscaled"])
936
+ explicit_channel_scale = row.get("channel_scale")
937
+ if explicit_channel_scale is not None:
938
+ if len(explicit_channel_scale) != gate.shape[1]:
939
+ raise ValueError(
940
+ f"Layer {layer_index} channel scale has "
941
+ f"{len(explicit_channel_scale)} values, expected {gate.shape[1]}"
942
+ )
943
+ scale = torch.tensor(
944
+ explicit_channel_scale,
945
+ device=gate.device,
946
+ dtype=torch.float32,
947
+ )
948
+ if not torch.isfinite(scale).all() or (scale <= 0).any():
949
+ raise ValueError(
950
+ f"Layer {layer_index} channel scale must be finite and positive"
951
+ )
952
+ alpha = None
953
+ clip_ratio = float(row.get("best_clip_ratio", 1.0))
954
+ elif improvement <= 0:
955
+ scale = torch.ones(gate.shape[1], device=gate.device, dtype=torch.float32)
956
+ alpha = None
957
+ clip_ratio = 1.0
958
+ else:
959
+ alpha = float(row["best_alpha"])
960
+ clip_ratio = float(row.get("best_clip_ratio", 1.0))
961
+ activation = torch.from_numpy(activations[layer_index]).to(
962
+ device=gate.device,
963
+ dtype=torch.float32,
964
+ )
965
+ if activation_statistic == "absmax":
966
+ activation_scale = activation.abs().amax(dim=0)
967
+ elif activation_statistic == "abs_p99":
968
+ activation_scale = torch.quantile(activation.abs(), 0.99, dim=0)
969
+ elif activation_statistic == "abs_p999":
970
+ activation_scale = torch.quantile(activation.abs(), 0.999, dim=0)
971
+ elif activation_statistic == "mean_abs":
972
+ activation_scale = activation.abs().mean(dim=0)
973
+ elif activation_statistic == "rms":
974
+ activation_scale = activation.square().mean(dim=0).sqrt()
975
+ else:
976
+ raise ValueError(
977
+ f"Unknown activation statistic {activation_statistic!r}"
978
+ )
979
+ activation_scale = activation_scale.clamp_min(1e-6)
980
+ weight_max = torch.maximum(
981
+ gate.float().abs().amax(dim=0),
982
+ up.float().abs().amax(dim=0),
983
+ ).clamp_min(1e-6)
984
+ scale = activation_scale.pow(alpha) / weight_max.pow(1.0 - alpha)
985
+ scale = scale / torch.exp(torch.mean(torch.log(scale)))
986
+ scale = scale.clamp(min=1.0 / clamp, max=clamp)
987
+ role_quantization_scales = row.get("weight_tensor_scales")
988
+ if role_quantization_scales is not None:
989
+ parsed_role_scales = {
990
+ role: float(role_quantization_scales[role])
991
+ for role in ("w1", "w3")
992
+ }
993
+ if any(
994
+ not np.isfinite(value) or value <= 0
995
+ for value in parsed_role_scales.values()
996
+ ):
997
+ raise ValueError(
998
+ f"Layer {layer_index} weight tensor scales must be finite and positive"
999
+ )
1000
+ quantization_scales[layer_index] = parsed_role_scales
1001
+ low_rank = row.get("low_rank_correction")
1002
+ if low_rank is not None:
1003
+ if correction_tensors is None:
1004
+ raise ValueError(
1005
+ f"Layer {layer_index} has a low-rank correction without tensors"
1006
+ )
1007
+ down_key = low_rank["down_key"]
1008
+ up_keys = low_rank["up_keys"]
1009
+ try:
1010
+ correction = {
1011
+ "down": correction_tensors[down_key],
1012
+ "w1_up": correction_tensors[up_keys["w1"]],
1013
+ "w3_up": correction_tensors[up_keys["w3"]],
1014
+ }
1015
+ except KeyError as error:
1016
+ raise ValueError(
1017
+ f"Layer {layer_index} correction tensor is missing: {error}"
1018
+ ) from error
1019
+ if any(value.dtype != torch.bfloat16 for value in correction.values()):
1020
+ raise ValueError(
1021
+ f"Layer {layer_index} correction tensors must be BF16"
1022
+ )
1023
+ corrections[layer_index] = correction
1024
+ sparse = row.get("sparse_channel_correction")
1025
+ if sparse is not None:
1026
+ if correction_tensors is None:
1027
+ raise ValueError(
1028
+ f"Layer {layer_index} has a sparse correction without tensors"
1029
+ )
1030
+ try:
1031
+ sparse_correction = {
1032
+ "sparse_indices": correction_tensors[sparse["indices_key"]],
1033
+ "w1_sparse_weight": correction_tensors[
1034
+ sparse["weight_keys"]["w1"]
1035
+ ],
1036
+ "w3_sparse_weight": correction_tensors[
1037
+ sparse["weight_keys"]["w3"]
1038
+ ],
1039
+ }
1040
+ except KeyError as error:
1041
+ raise ValueError(
1042
+ f"Layer {layer_index} sparse correction tensor is missing: {error}"
1043
+ ) from error
1044
+ if sparse_correction["sparse_indices"].dtype != torch.int64:
1045
+ raise ValueError(
1046
+ f"Layer {layer_index} sparse correction indices must be int64"
1047
+ )
1048
+ if any(
1049
+ sparse_correction[key].dtype != torch.bfloat16
1050
+ for key in ("w1_sparse_weight", "w3_sparse_weight")
1051
+ ):
1052
+ raise ValueError(
1053
+ f"Layer {layer_index} sparse correction weights must be BF16"
1054
+ )
1055
+ corrections.setdefault(layer_index, {}).update(sparse_correction)
1056
+ input_hadamard_block_size = int(row.get("input_hadamard_block_size", 0))
1057
+ if input_hadamard_block_size and (
1058
+ input_hadamard_block_size < 2
1059
+ or input_hadamard_block_size & (input_hadamard_block_size - 1)
1060
+ or gate.shape[1] % input_hadamard_block_size
1061
+ ):
1062
+ raise ValueError(
1063
+ f"Layer {layer_index} has invalid input Hadamard block size "
1064
+ f"{input_hadamard_block_size}"
1065
+ )
1066
+ if fold_norms:
1067
+ norm = block.ffn_norm.weight
1068
+ norm.data.copy_((norm.float() / scale).to(dtype=norm.dtype))
1069
+ scales[layer_index] = scale
1070
+ clip_ratios[layer_index] = clip_ratio
1071
+ records.append(
1072
+ {
1073
+ "layer": layer_index,
1074
+ "alpha": alpha,
1075
+ "calibration_improvement_fraction": improvement,
1076
+ "clip_ratio": clip_ratio,
1077
+ "scale_mode": (
1078
+ "explicit_channel"
1079
+ if explicit_channel_scale is not None
1080
+ else "activation_formula"
1081
+ ),
1082
+ "correction_rank": (
1083
+ None if low_rank is None else int(low_rank["rank"])
1084
+ ),
1085
+ "sparse_correction_channels": (
1086
+ None if sparse is None else int(sparse["channels"])
1087
+ ),
1088
+ "input_hadamard_block_size": input_hadamard_block_size,
1089
+ "scale_min": float(scale.min()),
1090
+ "scale_p50": float(torch.quantile(scale, 0.50)),
1091
+ "scale_max": float(scale.max()),
1092
+ }
1093
+ )
1094
+ return scales, clip_ratios, quantization_scales, corrections, {
1095
+ "sweep_report": str(report_path),
1096
+ "calibration_reports": [str(path) for path in calibration_report_paths],
1097
+ "calibration_history_sha256": [
1098
+ calibration["history_sha256"] for calibration in calibrations
1099
+ ],
1100
+ "scale_clamp": clamp,
1101
+ "activation_statistic": activation_statistic,
1102
+ "correction_tensors": correction_tensors_value,
1103
+ "layers": records,
1104
+ }
1105
+
1106
+
1107
+ @torch.inference_mode()
1108
+ def convert_s2_pro_nvfp4(
1109
+ model: nn.Module,
1110
+ *,
1111
+ policy: str = "slow_mlp",
1112
+ direct_m1: bool = False,
1113
+ w4a16_max_m: int = 1,
1114
+ nvfp4_layers: set[int] | None = None,
1115
+ activation_scaling_report: Path | None = None,
1116
+ probe_seed: int = 20260818,
1117
+ ) -> dict[str, Any]:
1118
+ """Replace selected S2-Pro projections without modifying the FP8 path."""
1119
+ if w4a16_max_m < 1:
1120
+ raise ValueError("w4a16_max_m must be positive")
1121
+ selectors = {
1122
+ "slow_mlp": (_selected_slow_mlp, 108),
1123
+ "slow_transformer": (_selected_slow_transformer, 180),
1124
+ }
1125
+ if policy == "w4a16_slow_transformer":
1126
+ candidates = [
1127
+ (name, module)
1128
+ for name, module in model.named_modules()
1129
+ if _selected_slow_transformer(name, module)
1130
+ ]
1131
+ if len(candidates) != 180:
1132
+ raise RuntimeError(
1133
+ f"Expected 180 w4a16_slow_transformer projections, found {len(candidates)}"
1134
+ )
1135
+ generator = torch.Generator(device=candidates[0][1].weight.device)
1136
+ generator.manual_seed(probe_seed)
1137
+ records = []
1138
+ for name, linear in candidates:
1139
+ parent_name, attribute = name.rsplit(".", 1)
1140
+ parent = model.get_submodule(parent_name)
1141
+ probe = torch.randn(
1142
+ 1,
1143
+ linear.in_features,
1144
+ dtype=torch.bfloat16,
1145
+ device=linear.weight.device,
1146
+ generator=generator,
1147
+ ) * 0.1
1148
+ reference = F.linear(probe, linear.weight)
1149
+ replacement = NVFP4Linear.from_linear(
1150
+ linear, w4a16_max_m=w4a16_max_m
1151
+ )
1152
+ actual = replacement(probe)
1153
+ records.append(
1154
+ ConversionRecord(
1155
+ name=name,
1156
+ in_features=linear.in_features,
1157
+ out_features=linear.out_features,
1158
+ parameters=linear.weight.numel(),
1159
+ probe_cosine=float(
1160
+ F.cosine_similarity(
1161
+ actual.float().flatten(),
1162
+ reference.float().flatten(),
1163
+ dim=0,
1164
+ ).item()
1165
+ ),
1166
+ )
1167
+ )
1168
+ setattr(parent, attribute, replacement)
1169
+ torch.cuda.synchronize(candidates[0][1].weight.device)
1170
+ serialized = [asdict(record) for record in records]
1171
+ cosines = [record.probe_cosine for record in records]
1172
+ parameters = sum(record.parameters for record in records)
1173
+ return {
1174
+ "policy": policy,
1175
+ "backend": (
1176
+ f"w4a16_through_m{w4a16_max_m}+w4a4_above_threshold"
1177
+ ),
1178
+ "w4a16_max_m": w4a16_max_m,
1179
+ "modules": len(records),
1180
+ "projections": len(records),
1181
+ "parameters": parameters,
1182
+ "theoretical_bf16_source_bytes": parameters * 2,
1183
+ "packed_weight_bytes": _packed_weight_bytes(model),
1184
+ "probe_cosine_min": min(cosines),
1185
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1186
+ "probe_cosine_max": max(cosines),
1187
+ "records": serialized,
1188
+ }
1189
+ mixed_role_policies = {
1190
+ "w4a16_mlp_mxfp8_attention": ({"w1", "w2", "w3"}, None),
1191
+ "w4a16_gate_up_mxfp8_rest": ({"w1", "w3"}, None),
1192
+ "w4a16_down_mxfp8_rest": ({"w2"}, None),
1193
+ "w4a16_gate_up_middle6_mxfp8_rest": ({"w1", "w3"}, set(range(15, 21))),
1194
+ "w4a16_gate_up_middle12_mxfp8_rest": ({"w1", "w3"}, set(range(12, 24))),
1195
+ "w4a16_gate_up_middle18_mxfp8_rest": ({"w1", "w3"}, set(range(9, 27))),
1196
+ "w4a16_gate_up_middle24_mxfp8_rest": ({"w1", "w3"}, set(range(6, 30))),
1197
+ "w4a16_gate_up_middle30_mxfp8_rest": ({"w1", "w3"}, set(range(3, 33))),
1198
+ "w4a16_gate_up_custom_mxfp8_rest": ({"w1", "w3"}, "custom"),
1199
+ }
1200
+ if policy in mixed_role_policies:
1201
+ from experimental.fp8 import MXFP8Linear
1202
+
1203
+ candidates = [
1204
+ (name, module)
1205
+ for name, module in model.named_modules()
1206
+ if _selected_slow_transformer(name, module)
1207
+ ]
1208
+ if len(candidates) != 180:
1209
+ raise RuntimeError(
1210
+ f"Expected 180 {policy} projections, "
1211
+ f"found {len(candidates)}"
1212
+ )
1213
+ nvfp4_roles, policy_layers = mixed_role_policies[policy]
1214
+ if policy_layers == "custom":
1215
+ if not nvfp4_layers:
1216
+ raise ValueError(f"{policy} requires at least one nvfp4 layer")
1217
+ invalid_layers = sorted(set(nvfp4_layers) - set(range(36)))
1218
+ if invalid_layers:
1219
+ raise ValueError(f"Invalid slow-transformer layers: {invalid_layers}")
1220
+ selected_nvfp4_layers = set(nvfp4_layers)
1221
+ else:
1222
+ if nvfp4_layers is not None:
1223
+ raise ValueError("nvfp4_layers is only valid with the custom policy")
1224
+ selected_nvfp4_layers = policy_layers
1225
+ activation_scales: dict[int, torch.Tensor] = {}
1226
+ activation_clip_ratios: dict[int, float] = {}
1227
+ activation_quantization_scales: dict[int, dict[str, float]] = {}
1228
+ activation_corrections: dict[int, dict[str, torch.Tensor]] = {}
1229
+ activation_hadamard_blocks: dict[int, int] = {}
1230
+ activation_scaling = None
1231
+ if activation_scaling_report is not None:
1232
+ if nvfp4_roles != {"w1", "w3"}:
1233
+ raise ValueError(
1234
+ "Activation scaling requires NVFP4 gate and up projections together"
1235
+ )
1236
+ layers_to_scale = (
1237
+ set(range(36))
1238
+ if selected_nvfp4_layers is None
1239
+ else set(selected_nvfp4_layers)
1240
+ )
1241
+ (
1242
+ activation_scales,
1243
+ activation_clip_ratios,
1244
+ activation_quantization_scales,
1245
+ activation_corrections,
1246
+ activation_scaling,
1247
+ ) = _prepare_activation_scaling(
1248
+ model,
1249
+ Path(activation_scaling_report),
1250
+ layers_to_scale,
1251
+ )
1252
+ activation_hadamard_blocks = {
1253
+ int(record["layer"]): int(record["input_hadamard_block_size"])
1254
+ for record in activation_scaling["layers"]
1255
+ if int(record.get("input_hadamard_block_size", 0))
1256
+ }
1257
+ generator = torch.Generator(device=candidates[0][1].weight.device)
1258
+ generator.manual_seed(probe_seed)
1259
+ records = []
1260
+ nvfp4_parameters = 0
1261
+ mxfp8_parameters = 0
1262
+ for name, linear in candidates:
1263
+ parent_name, attribute = name.rsplit(".", 1)
1264
+ parent = model.get_submodule(parent_name)
1265
+ probe = torch.randn(
1266
+ 1,
1267
+ linear.in_features,
1268
+ dtype=torch.bfloat16,
1269
+ device=linear.weight.device,
1270
+ generator=generator,
1271
+ ) * 0.1
1272
+ reference = F.linear(probe, linear.weight)
1273
+ role = name.rsplit(".", 1)[-1]
1274
+ layer = int(name.split(".", 2)[1])
1275
+ selected_layer = (
1276
+ selected_nvfp4_layers is None or layer in selected_nvfp4_layers
1277
+ )
1278
+ if ".feed_forward." in name and role in nvfp4_roles and selected_layer:
1279
+ activation_scale = activation_scales.get(layer)
1280
+ if activation_scale is None:
1281
+ replacement = NVFP4Linear.from_linear(
1282
+ linear, w4a16_max_m=w4a16_max_m
1283
+ )
1284
+ actual_probe = probe
1285
+ else:
1286
+ scaled_weight = (
1287
+ linear.weight.float() * activation_scale
1288
+ )
1289
+ scaled_weight = _clip_weight_blocks(
1290
+ scaled_weight,
1291
+ activation_clip_ratios.get(layer, 1.0),
1292
+ )
1293
+ input_hadamard_block_size = activation_hadamard_blocks.get(
1294
+ layer,
1295
+ 0,
1296
+ )
1297
+ if input_hadamard_block_size:
1298
+ scaled_weight = _hadamard_blocks(
1299
+ scaled_weight,
1300
+ input_hadamard_block_size,
1301
+ )
1302
+ scaled_weight = scaled_weight.to(dtype=torch.bfloat16)
1303
+ replacement = NVFP4Linear.from_weight(
1304
+ scaled_weight,
1305
+ w4a16_max_m=w4a16_max_m,
1306
+ quantization_scale=activation_quantization_scales.get(
1307
+ layer, {}
1308
+ ).get(role),
1309
+ correction_down=activation_corrections.get(
1310
+ layer, {}
1311
+ ).get("down"),
1312
+ correction_up=activation_corrections.get(
1313
+ layer, {}
1314
+ ).get(f"{role}_up"),
1315
+ sparse_correction_indices=activation_corrections.get(
1316
+ layer, {}
1317
+ ).get("sparse_indices"),
1318
+ sparse_correction_weight=activation_corrections.get(
1319
+ layer, {}
1320
+ ).get(f"{role}_sparse_weight"),
1321
+ input_hadamard_block_size=input_hadamard_block_size,
1322
+ )
1323
+ actual_probe = (
1324
+ probe.float() / activation_scale
1325
+ ).to(dtype=torch.bfloat16)
1326
+ precision = (
1327
+ f"nvfp4_w4a16_through_m{w4a16_max_m}"
1328
+ + ("_activation_scaled" if activation_scale is not None else "")
1329
+ + (
1330
+ "_low_rank_corrected"
1331
+ if "down" in activation_corrections.get(layer, {})
1332
+ else ""
1333
+ )
1334
+ + (
1335
+ "_sparse_channel_corrected"
1336
+ if "sparse_indices" in activation_corrections.get(layer, {})
1337
+ else ""
1338
+ )
1339
+ + (
1340
+ f"_hadamard{activation_hadamard_blocks[layer]}"
1341
+ if layer in activation_hadamard_blocks
1342
+ else ""
1343
+ )
1344
+ )
1345
+ nvfp4_parameters += linear.weight.numel()
1346
+ else:
1347
+ replacement = MXFP8Linear.from_linear(linear)
1348
+ actual_probe = probe
1349
+ precision = "mxfp8_w8a8"
1350
+ mxfp8_parameters += linear.weight.numel()
1351
+ actual = replacement(actual_probe)
1352
+ record = ConversionRecord(
1353
+ name=name,
1354
+ in_features=linear.in_features,
1355
+ out_features=linear.out_features,
1356
+ parameters=linear.weight.numel(),
1357
+ probe_cosine=float(
1358
+ F.cosine_similarity(
1359
+ actual.float().flatten(),
1360
+ reference.float().flatten(),
1361
+ dim=0,
1362
+ ).item()
1363
+ ),
1364
+ )
1365
+ records.append({**asdict(record), "precision": precision})
1366
+ setattr(parent, attribute, replacement)
1367
+ torch.cuda.synchronize(candidates[0][1].weight.device)
1368
+ nvfp4_bytes = _packed_weight_bytes(model)
1369
+ mxfp8_bytes = sum(
1370
+ module.weight_fp8.numel() * module.weight_fp8.element_size()
1371
+ + module.weight_scale_storage.numel()
1372
+ * module.weight_scale_storage.element_size()
1373
+ for module in model.modules()
1374
+ if isinstance(module, MXFP8Linear)
1375
+ )
1376
+ cosines = [record["probe_cosine"] for record in records]
1377
+ parameters = nvfp4_parameters + mxfp8_parameters
1378
+ correction_tensors = {
1379
+ value.data_ptr(): value
1380
+ for correction in activation_corrections.values()
1381
+ for value in correction.values()
1382
+ }
1383
+ correction_parameters = sum(
1384
+ value.numel()
1385
+ for value in correction_tensors.values()
1386
+ if value.is_floating_point()
1387
+ )
1388
+ correction_bytes = sum(
1389
+ value.numel() * value.element_size()
1390
+ for value in correction_tensors.values()
1391
+ )
1392
+ low_rank_tensors = {
1393
+ value.data_ptr(): value
1394
+ for correction in activation_corrections.values()
1395
+ for key, value in correction.items()
1396
+ if key == "down" or key.endswith("_up")
1397
+ }
1398
+ sparse_correction_tensors = {
1399
+ value.data_ptr(): value
1400
+ for correction in activation_corrections.values()
1401
+ for key, value in correction.items()
1402
+ if key == "sparse_indices" or key.endswith("_sparse_weight")
1403
+ }
1404
+ low_rank_correction_parameters = sum(
1405
+ value.numel() for value in low_rank_tensors.values()
1406
+ )
1407
+ low_rank_correction_bytes = sum(
1408
+ value.numel() * value.element_size()
1409
+ for value in low_rank_tensors.values()
1410
+ )
1411
+ sparse_correction_parameters = sum(
1412
+ value.numel()
1413
+ for value in sparse_correction_tensors.values()
1414
+ if value.is_floating_point()
1415
+ )
1416
+ sparse_correction_bytes = sum(
1417
+ value.numel() * value.element_size()
1418
+ for value in sparse_correction_tensors.values()
1419
+ )
1420
+ return {
1421
+ "policy": policy,
1422
+ "backend": "selective_nvfp4_weight_bf16_activation+mxfp8_rest",
1423
+ "w4a16_max_m": w4a16_max_m,
1424
+ "nvfp4_mlp_roles": sorted(nvfp4_roles),
1425
+ "nvfp4_layers": (
1426
+ "all"
1427
+ if selected_nvfp4_layers is None
1428
+ else sorted(selected_nvfp4_layers)
1429
+ ),
1430
+ "activation_scaling": activation_scaling,
1431
+ "modules": len(records),
1432
+ "projections": len(records),
1433
+ "parameters": parameters,
1434
+ "nvfp4_parameters": nvfp4_parameters,
1435
+ "mxfp8_parameters": mxfp8_parameters,
1436
+ "low_rank_correction_parameters": low_rank_correction_parameters,
1437
+ "low_rank_correction_bytes": low_rank_correction_bytes,
1438
+ "sparse_correction_parameters": sparse_correction_parameters,
1439
+ "sparse_correction_bytes": sparse_correction_bytes,
1440
+ "correction_parameters": correction_parameters,
1441
+ "correction_bytes": correction_bytes,
1442
+ "theoretical_bf16_source_bytes": parameters * 2,
1443
+ "packed_weight_bytes": nvfp4_bytes + mxfp8_bytes,
1444
+ "nvfp4_packed_weight_bytes": nvfp4_bytes,
1445
+ "mxfp8_packed_weight_bytes": mxfp8_bytes,
1446
+ "probe_cosine_min": min(cosines),
1447
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1448
+ "probe_cosine_max": max(cosines),
1449
+ "records": records,
1450
+ }
1451
+ if policy == "hybrid_slow_transformer":
1452
+ from experimental.fp8 import MXFP8Linear
1453
+
1454
+ nvfp4 = convert_s2_pro_nvfp4(
1455
+ model,
1456
+ policy="slow_mlp_fused",
1457
+ probe_seed=probe_seed,
1458
+ )
1459
+ candidates = [
1460
+ (name, module)
1461
+ for name, module in model.named_modules()
1462
+ if _selected_slow_attention(name, module)
1463
+ ]
1464
+ if len(candidates) != 72:
1465
+ raise RuntimeError(
1466
+ f"Expected 72 hybrid attention projections, found {len(candidates)}"
1467
+ )
1468
+ generator = torch.Generator(device=candidates[0][1].weight.device)
1469
+ generator.manual_seed(probe_seed + 1)
1470
+ attention_records = []
1471
+ for name, linear in candidates:
1472
+ parent_name, attribute = name.rsplit(".", 1)
1473
+ parent = model.get_submodule(parent_name)
1474
+ probe = torch.randn(
1475
+ 1,
1476
+ linear.in_features,
1477
+ dtype=torch.bfloat16,
1478
+ device=linear.weight.device,
1479
+ generator=generator,
1480
+ ) * 0.1
1481
+ reference = F.linear(probe, linear.weight)
1482
+ replacement = MXFP8Linear.from_linear(linear)
1483
+ actual = replacement(probe)
1484
+ attention_records.append(
1485
+ ConversionRecord(
1486
+ name=name,
1487
+ in_features=linear.in_features,
1488
+ out_features=linear.out_features,
1489
+ parameters=linear.weight.numel(),
1490
+ probe_cosine=float(
1491
+ F.cosine_similarity(
1492
+ actual.float().flatten(),
1493
+ reference.float().flatten(),
1494
+ dim=0,
1495
+ ).item()
1496
+ ),
1497
+ )
1498
+ )
1499
+ setattr(parent, attribute, replacement)
1500
+ torch.cuda.synchronize(candidates[0][1].weight.device)
1501
+ attention_parameters = sum(record.parameters for record in attention_records)
1502
+ attention_packed_bytes = sum(
1503
+ module.weight_fp8.numel() * module.weight_fp8.element_size()
1504
+ + module.weight_scale_storage.numel()
1505
+ * module.weight_scale_storage.element_size()
1506
+ for module in model.modules()
1507
+ if isinstance(module, MXFP8Linear)
1508
+ )
1509
+ cosines = [
1510
+ *[record["probe_cosine"] for record in nvfp4["records"]],
1511
+ *[record.probe_cosine for record in attention_records],
1512
+ ]
1513
+ return {
1514
+ "policy": policy,
1515
+ "backend": "fused_nvfp4_mlp+mxfp8_attention",
1516
+ "modules": nvfp4["modules"] + len(attention_records),
1517
+ "projections": nvfp4["projections"] + len(attention_records),
1518
+ "parameters": nvfp4["parameters"] + attention_parameters,
1519
+ "theoretical_bf16_source_bytes": (
1520
+ nvfp4["theoretical_bf16_source_bytes"]
1521
+ + attention_parameters * 2
1522
+ ),
1523
+ "packed_weight_bytes": (
1524
+ nvfp4["packed_weight_bytes"] + attention_packed_bytes
1525
+ ),
1526
+ "nvfp4_mlp": nvfp4,
1527
+ "mxfp8_attention": {
1528
+ "modules": len(attention_records),
1529
+ "parameters": attention_parameters,
1530
+ "packed_weight_bytes": attention_packed_bytes,
1531
+ "records": [asdict(record) for record in attention_records],
1532
+ },
1533
+ "probe_cosine_min": min(cosines),
1534
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1535
+ "probe_cosine_max": max(cosines),
1536
+ }
1537
+ if policy == "slow_transformer_fused":
1538
+ candidates = [
1539
+ (name, module)
1540
+ for name, module in model.named_modules()
1541
+ if _selected_slow_transformer_block(name, module)
1542
+ ]
1543
+ if len(candidates) != 36:
1544
+ raise RuntimeError(
1545
+ f"Expected 36 slow_transformer_fused blocks, found {len(candidates)}"
1546
+ )
1547
+ generator = torch.Generator(device=candidates[0][1].attention.wqkv.weight.device)
1548
+ generator.manual_seed(probe_seed)
1549
+ records = []
1550
+ for name, module in candidates:
1551
+ parent_name, attribute = name.rsplit(".", 1)
1552
+ parent = model.get_submodule(parent_name)
1553
+ dim = module.attention.wqkv.in_features
1554
+ probe = torch.randn(
1555
+ 1,
1556
+ dim,
1557
+ dtype=torch.bfloat16,
1558
+ device=module.attention.wqkv.weight.device,
1559
+ generator=generator,
1560
+ ) * 0.1
1561
+ wo_probe = torch.randn(
1562
+ 1,
1563
+ module.attention.wo.in_features,
1564
+ dtype=torch.bfloat16,
1565
+ device=module.attention.wo.weight.device,
1566
+ generator=generator,
1567
+ ) * 0.1
1568
+ reference_wqkv = module.attention.wqkv(probe)
1569
+ reference_wo = module.attention.wo(wo_probe)
1570
+ reference_mlp = module.feed_forward(probe)
1571
+ parameters = sum(
1572
+ linear.weight.numel()
1573
+ for linear in (
1574
+ module.attention.wqkv,
1575
+ module.attention.wo,
1576
+ module.feed_forward.w1,
1577
+ module.feed_forward.w2,
1578
+ module.feed_forward.w3,
1579
+ )
1580
+ )
1581
+ replacement = NVFP4TransformerBlock(module)
1582
+ actual_wqkv = replacement.attention.wqkv(probe)
1583
+ actual_wo = replacement.attention.wo(wo_probe)
1584
+ actual_mlp = replacement.feed_forward(probe)
1585
+ records.append(
1586
+ FusedTransformerConversionRecord(
1587
+ name=name,
1588
+ parameters=parameters,
1589
+ wqkv_probe_cosine=float(
1590
+ F.cosine_similarity(
1591
+ actual_wqkv.float().flatten(),
1592
+ reference_wqkv.float().flatten(),
1593
+ dim=0,
1594
+ ).item()
1595
+ ),
1596
+ wo_probe_cosine=float(
1597
+ F.cosine_similarity(
1598
+ actual_wo.float().flatten(),
1599
+ reference_wo.float().flatten(),
1600
+ dim=0,
1601
+ ).item()
1602
+ ),
1603
+ mlp_probe_cosine=float(
1604
+ F.cosine_similarity(
1605
+ actual_mlp.float().flatten(),
1606
+ reference_mlp.float().flatten(),
1607
+ dim=0,
1608
+ ).item()
1609
+ ),
1610
+ )
1611
+ )
1612
+ setattr(parent, attribute, replacement)
1613
+ torch.cuda.synchronize(candidates[0][1].attention.wqkv.qdata.device)
1614
+ serialized = [asdict(record) for record in records]
1615
+ cosines = [
1616
+ cosine
1617
+ for record in records
1618
+ for cosine in (
1619
+ record.wqkv_probe_cosine,
1620
+ record.wo_probe_cosine,
1621
+ record.mlp_probe_cosine,
1622
+ )
1623
+ ]
1624
+ parameters = sum(record.parameters for record in records)
1625
+ return {
1626
+ "policy": policy,
1627
+ "backend": "direct_fused_m1+tensorcore_prefill",
1628
+ "modules": len(records),
1629
+ "projections": len(records) * 5,
1630
+ "parameters": parameters,
1631
+ "theoretical_bf16_source_bytes": parameters * 2,
1632
+ "packed_weight_bytes": _packed_weight_bytes(model),
1633
+ "probe_cosine_min": min(cosines),
1634
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1635
+ "probe_cosine_max": max(cosines),
1636
+ "records": serialized,
1637
+ }
1638
+ if policy == "slow_mlp_fused":
1639
+ candidates = [
1640
+ (name, module)
1641
+ for name, module in model.named_modules()
1642
+ if _selected_slow_mlp_block(name, module)
1643
+ ]
1644
+ if len(candidates) != 36:
1645
+ raise RuntimeError(
1646
+ f"Expected 36 slow_mlp_fused blocks, found {len(candidates)}"
1647
+ )
1648
+ generator = torch.Generator(device=candidates[0][1].w1.weight.device)
1649
+ generator.manual_seed(probe_seed)
1650
+ records = []
1651
+ for name, module in candidates:
1652
+ parent_name, attribute = name.rsplit(".", 1)
1653
+ parent = model.get_submodule(parent_name)
1654
+ probe = torch.randn(
1655
+ 1,
1656
+ module.w1.in_features,
1657
+ dtype=torch.bfloat16,
1658
+ device=module.w1.weight.device,
1659
+ generator=generator,
1660
+ ) * 0.1
1661
+ reference = module(probe)
1662
+ replacement = NVFP4FeedForward.from_module(module)
1663
+ actual = replacement(probe)
1664
+ records.append(
1665
+ FusedMLPConversionRecord(
1666
+ name=name,
1667
+ in_features=module.w1.in_features,
1668
+ intermediate_features=module.w1.out_features,
1669
+ out_features=module.w2.out_features,
1670
+ parameters=(
1671
+ module.w1.weight.numel()
1672
+ + module.w2.weight.numel()
1673
+ + module.w3.weight.numel()
1674
+ ),
1675
+ probe_cosine=float(
1676
+ F.cosine_similarity(
1677
+ actual.float().flatten(),
1678
+ reference.float().flatten(),
1679
+ dim=0,
1680
+ ).item()
1681
+ ),
1682
+ )
1683
+ )
1684
+ setattr(parent, attribute, replacement)
1685
+ torch.cuda.synchronize(candidates[0][1].w1.weight.device)
1686
+ serialized = [asdict(record) for record in records]
1687
+ cosines = [record.probe_cosine for record in records]
1688
+ parameters = sum(record.parameters for record in records)
1689
+ return {
1690
+ "policy": policy,
1691
+ "backend": "direct_fused_m1+tensorcore_prefill",
1692
+ "modules": len(records),
1693
+ "projections": len(records) * 3,
1694
+ "parameters": parameters,
1695
+ "theoretical_bf16_source_bytes": parameters * 2,
1696
+ "packed_weight_bytes": _packed_weight_bytes(model),
1697
+ "probe_cosine_min": min(cosines),
1698
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1699
+ "probe_cosine_max": max(cosines),
1700
+ "records": serialized,
1701
+ }
1702
+ if policy not in selectors:
1703
+ raise ValueError(f"Unsupported initial NVFP4 policy: {policy}")
1704
+ selector, expected_modules = selectors[policy]
1705
+ candidates = [
1706
+ (name, module)
1707
+ for name, module in model.named_modules()
1708
+ if selector(name, module)
1709
+ ]
1710
+ if len(candidates) != expected_modules:
1711
+ raise RuntimeError(
1712
+ f"Expected {expected_modules} {policy} projections, found {len(candidates)}"
1713
+ )
1714
+
1715
+ generator = torch.Generator(device=candidates[0][1].weight.device)
1716
+ generator.manual_seed(probe_seed)
1717
+ records = []
1718
+ for name, linear in candidates:
1719
+ parent_name, attribute = name.rsplit(".", 1)
1720
+ parent = model.get_submodule(parent_name)
1721
+ replacement = NVFP4Linear.from_linear(linear, direct_m1=direct_m1)
1722
+ probe = torch.randn(
1723
+ 1,
1724
+ linear.in_features,
1725
+ dtype=torch.bfloat16,
1726
+ device=linear.weight.device,
1727
+ generator=generator,
1728
+ ) * 0.1
1729
+ reference = F.linear(probe, linear.weight)
1730
+ actual = replacement(probe)
1731
+ probe_cosine = float(
1732
+ F.cosine_similarity(
1733
+ actual.float().flatten(), reference.float().flatten(), dim=0
1734
+ ).item()
1735
+ )
1736
+ records.append(
1737
+ ConversionRecord(
1738
+ name=name,
1739
+ in_features=linear.in_features,
1740
+ out_features=linear.out_features,
1741
+ parameters=linear.weight.numel(),
1742
+ probe_cosine=probe_cosine,
1743
+ )
1744
+ )
1745
+ setattr(parent, attribute, replacement)
1746
+
1747
+ torch.cuda.synchronize(candidates[0][1].weight.device)
1748
+ serialized = [asdict(record) for record in records]
1749
+ cosines = [record.probe_cosine for record in records]
1750
+ return {
1751
+ "policy": policy,
1752
+ "backend": "direct_m1+tensorcore" if direct_m1 else "tensorcore",
1753
+ "modules": len(records),
1754
+ "parameters": sum(record.parameters for record in records),
1755
+ "theoretical_bf16_source_bytes": sum(record.parameters * 2 for record in records),
1756
+ "packed_weight_bytes": _packed_weight_bytes(model),
1757
+ "probe_cosine_min": min(cosines),
1758
+ "probe_cosine_mean": sum(cosines) / len(cosines),
1759
+ "probe_cosine_max": max(cosines),
1760
+ "records": serialized,
1761
+ }
runtime/experimental/nvfp4/server.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Threaded Fish Speech queue for standalone mixed NVFP4 checkpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import queue
6
+ import threading
7
+ import traceback
8
+ from pathlib import Path
9
+
10
+ import torch
11
+ from loguru import logger
12
+
13
+ from fish_speech.models.text2semantic.inference import (
14
+ GenerateRequest,
15
+ WrappedGenerateResponse,
16
+ decode_one_token_ar,
17
+ generate_long,
18
+ )
19
+
20
+ from experimental.fp8 import MXFP8Linear
21
+ from .checkpoint import load_mixed_nvfp4_checkpoint
22
+ from .modules import NVFP4Linear
23
+
24
+
25
+ def launch_mixed_nvfp4_thread_safe_queue(
26
+ checkpoint_path: str | Path,
27
+ device: str | torch.device,
28
+ precision: torch.dtype,
29
+ compile: bool = False,
30
+ *,
31
+ max_length: int = 3072,
32
+ verify_checksums: bool = False,
33
+ ) -> queue.Queue:
34
+ """Load the frozen mixed checkpoint once and serialize generation."""
35
+ if precision is not torch.bfloat16:
36
+ raise ValueError("The mixed NVFP4 service requires BF16 exclusions")
37
+ if compile:
38
+ raise ValueError("torch.compile is not qualified for this checkpoint")
39
+ if max_length < 1024:
40
+ raise ValueError("NVFP4 API cache length must be at least 1024")
41
+
42
+ input_queue: queue.Queue = queue.Queue()
43
+ init_event = threading.Event()
44
+ init_error: list[BaseException] = []
45
+
46
+ def worker() -> None:
47
+ try:
48
+ model = load_mixed_nvfp4_checkpoint(
49
+ checkpoint_path,
50
+ device=device,
51
+ max_length=max_length,
52
+ verify_checksums=verify_checksums,
53
+ )
54
+ with torch.device(device):
55
+ model.setup_caches(
56
+ max_batch_size=1,
57
+ max_seq_len=model.config.max_seq_len,
58
+ dtype=torch.bfloat16,
59
+ )
60
+ model._cache_setup_done = True
61
+ nvfp4_count = sum(
62
+ isinstance(module, NVFP4Linear) for module in model.modules()
63
+ )
64
+ mxfp8_count = sum(
65
+ isinstance(module, MXFP8Linear) for module in model.modules()
66
+ )
67
+ if (nvfp4_count, mxfp8_count) != (60, 120):
68
+ raise RuntimeError(
69
+ f"Expected 60/120 NVFP4/MXFP8 modules, got {nvfp4_count}/{mxfp8_count}"
70
+ )
71
+ logger.info(
72
+ "Loaded standalone English NVFP4 checkpoint with "
73
+ f"{nvfp4_count} NVFP4 and {mxfp8_count} MXFP8 projections on {device}"
74
+ )
75
+ except BaseException as error:
76
+ init_error.append(error)
77
+ logger.error(traceback.format_exc())
78
+ init_event.set()
79
+ return
80
+
81
+ init_event.set()
82
+ while True:
83
+ item: GenerateRequest | None = input_queue.get()
84
+ if item is None:
85
+ break
86
+ response_queue = item.response_queue
87
+ try:
88
+ for chunk in generate_long(
89
+ model=model,
90
+ decode_one_token=decode_one_token_ar,
91
+ **item.request,
92
+ ):
93
+ response_queue.put(
94
+ WrappedGenerateResponse(status="success", response=chunk)
95
+ )
96
+ except Exception as error:
97
+ logger.error(traceback.format_exc())
98
+ response_queue.put(
99
+ WrappedGenerateResponse(status="error", response=error)
100
+ )
101
+ finally:
102
+ if torch.cuda.is_available():
103
+ torch.cuda.empty_cache()
104
+
105
+ threading.Thread(
106
+ target=worker,
107
+ name="fish-s2-pro-mixed-nvfp4-worker",
108
+ daemon=True,
109
+ ).start()
110
+ init_event.wait()
111
+ if init_error:
112
+ raise RuntimeError("Mixed NVFP4 model worker failed to initialize") from init_error[0]
113
+ return input_queue
runtime/native/direct_w4a4_m1/direct_w4a4_m1.cu ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "direct_w4a4_m1.h"
2
+
3
+ #include <ATen/cuda/CUDAContext.h>
4
+ #include <c10/cuda/CUDAGuard.h>
5
+ #include <cuda_bf16.h>
6
+ #include <cuda_fp8.h>
7
+ #include <cuda_runtime.h>
8
+
9
+ #include <cstdint>
10
+ #include <limits>
11
+ #include <optional>
12
+
13
+ namespace {
14
+
15
+ constexpr int kWarpSize = 32;
16
+ constexpr int kWarpsPerBlock = 8;
17
+ constexpr int kThreads = kWarpSize * kWarpsPerBlock;
18
+ constexpr int kFp4BlockElements = 16;
19
+ constexpr int kScaleTileOuter = 128;
20
+
21
+ __device__ __forceinline__ size_t scale_offset(
22
+ int outer,
23
+ int inner_scale,
24
+ int scale_inner_dim) {
25
+ const int outer_tile = outer / kScaleTileOuter;
26
+ const int local_outer = outer % kScaleTileOuter;
27
+ const int local_inner = inner_scale & 3;
28
+ const int inner_tile_start = inner_scale - local_inner;
29
+ const size_t tile_base =
30
+ static_cast<size_t>(
31
+ inner_tile_start + outer_tile * scale_inner_dim) *
32
+ kScaleTileOuter;
33
+ return tile_base + static_cast<size_t>(local_outer & 31) * 16 +
34
+ static_cast<size_t>(local_outer >> 5) * 4 + local_inner;
35
+ }
36
+
37
+ __device__ __forceinline__ float e4m3_to_float(uint8_t raw) {
38
+ const __half_raw half_raw = __nv_cvt_fp8_to_halfraw(raw, __NV_E4M3);
39
+ return __half2float(static_cast<__half>(half_raw));
40
+ }
41
+
42
+ __device__ __forceinline__ float2 e2m1x2_to_float2(uint8_t packed) {
43
+ const __half2_raw raw =
44
+ __nv_cvt_fp4x2_to_halfraw2(packed, __NV_E2M1);
45
+ const __half2 converted(raw);
46
+ return __half22float2(converted);
47
+ }
48
+
49
+ __global__ void direct_w4a4_m1_kernel(
50
+ const uint8_t* __restrict__ activation_qdata,
51
+ const uint8_t* __restrict__ activation_block_scales,
52
+ const float* __restrict__ activation_tensor_scale,
53
+ const uint8_t* __restrict__ weight_qdata,
54
+ const uint8_t* __restrict__ weight_block_scales,
55
+ const float* __restrict__ weight_tensor_scale,
56
+ const __nv_bfloat16* __restrict__ bias,
57
+ __nv_bfloat16* __restrict__ output,
58
+ int n,
59
+ int packed_k,
60
+ int activation_scale_inner_dim,
61
+ int weight_scale_inner_dim) {
62
+ const int lane = threadIdx.x & (kWarpSize - 1);
63
+ const int warp_in_block = threadIdx.x / kWarpSize;
64
+ const int row_n = blockIdx.x * kWarpsPerBlock + warp_in_block;
65
+ if (row_n >= n) {
66
+ return;
67
+ }
68
+
69
+ const uint8_t* weight_row =
70
+ weight_qdata + static_cast<int64_t>(row_n) * packed_k;
71
+ const float activation_global_scale = activation_tensor_scale[0];
72
+ const float weight_global_scale = weight_tensor_scale[0];
73
+ float accumulator = 0.0f;
74
+
75
+ for (int pair = lane; pair < packed_k; pair += kWarpSize) {
76
+ const int scale_block = pair / (kFp4BlockElements / 2);
77
+ const float activation_scale =
78
+ e4m3_to_float(activation_block_scales[
79
+ scale_offset(0, scale_block, activation_scale_inner_dim)]) *
80
+ activation_global_scale;
81
+ const float weight_scale =
82
+ e4m3_to_float(weight_block_scales[
83
+ scale_offset(row_n, scale_block, weight_scale_inner_dim)]) *
84
+ weight_global_scale;
85
+ const float2 activations = e2m1x2_to_float2(activation_qdata[pair]);
86
+ const float2 weights = e2m1x2_to_float2(weight_row[pair]);
87
+ accumulator = fmaf(
88
+ activations.y * activation_scale,
89
+ weights.y * weight_scale,
90
+ accumulator);
91
+ accumulator = fmaf(
92
+ activations.x * activation_scale,
93
+ weights.x * weight_scale,
94
+ accumulator);
95
+ }
96
+
97
+ #pragma unroll
98
+ for (int offset = 16; offset > 0; offset >>= 1) {
99
+ accumulator += __shfl_down_sync(0xFFFFFFFF, accumulator, offset);
100
+ }
101
+ if (lane == 0) {
102
+ if (bias != nullptr) {
103
+ accumulator += __bfloat162float(bias[row_n]);
104
+ }
105
+ output[row_n] = __float2bfloat16_rn(accumulator);
106
+ }
107
+ }
108
+
109
+ } // namespace
110
+
111
+ torch::Tensor direct_w4a4_m1_linear_cuda(
112
+ const torch::Tensor& activation_qdata,
113
+ const torch::Tensor& activation_block_scales,
114
+ const torch::Tensor& activation_tensor_scale,
115
+ const torch::Tensor& weight_qdata,
116
+ const torch::Tensor& weight_block_scales,
117
+ const torch::Tensor& weight_tensor_scale,
118
+ const std::optional<torch::Tensor>& bias) {
119
+ const auto device = activation_qdata.device();
120
+ c10::cuda::CUDAGuard guard(device);
121
+ const int64_t n64 = weight_qdata.size(0);
122
+ const int64_t packed_k64 = weight_qdata.size(1);
123
+ TORCH_CHECK(
124
+ n64 <= static_cast<int64_t>(std::numeric_limits<int>::max()) &&
125
+ packed_k64 <= static_cast<int64_t>(std::numeric_limits<int>::max()),
126
+ "direct W4A4 M=1 N or K is out of range");
127
+ const int n = static_cast<int>(n64);
128
+ const int packed_k = static_cast<int>(packed_k64);
129
+ torch::Tensor output = torch::empty(
130
+ {1, n64}, activation_qdata.options().dtype(at::kBFloat16));
131
+ const int block_count = (n + kWarpsPerBlock - 1) / kWarpsPerBlock;
132
+ const auto stream = at::cuda::getCurrentCUDAStream(device.index()).stream();
133
+ const __nv_bfloat16* bias_pointer =
134
+ bias.has_value()
135
+ ? reinterpret_cast<const __nv_bfloat16*>(bias->data_ptr())
136
+ : nullptr;
137
+ direct_w4a4_m1_kernel<<<block_count, kThreads, 0, stream>>>(
138
+ reinterpret_cast<const uint8_t*>(activation_qdata.data_ptr()),
139
+ reinterpret_cast<const uint8_t*>(activation_block_scales.data_ptr()),
140
+ reinterpret_cast<const float*>(activation_tensor_scale.data_ptr()),
141
+ reinterpret_cast<const uint8_t*>(weight_qdata.data_ptr()),
142
+ reinterpret_cast<const uint8_t*>(weight_block_scales.data_ptr()),
143
+ reinterpret_cast<const float*>(weight_tensor_scale.data_ptr()),
144
+ bias_pointer,
145
+ reinterpret_cast<__nv_bfloat16*>(output.data_ptr()),
146
+ n,
147
+ packed_k,
148
+ static_cast<int>(activation_block_scales.size(1)),
149
+ static_cast<int>(weight_block_scales.size(1)));
150
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
151
+ return output;
152
+ }
runtime/native/direct_w4a4_m1/direct_w4a4_m1.h ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/extension.h>
4
+
5
+ #include <optional>
6
+
7
+ torch::Tensor direct_w4a4_m1_linear_cuda(
8
+ const torch::Tensor& activation_qdata,
9
+ const torch::Tensor& activation_block_scales,
10
+ const torch::Tensor& activation_tensor_scale,
11
+ const torch::Tensor& weight_qdata,
12
+ const torch::Tensor& weight_block_scales,
13
+ const torch::Tensor& weight_tensor_scale,
14
+ const std::optional<torch::Tensor>& bias);
runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cpp ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "silu_product_nvfp4_m1.h"
2
+
3
+ #include <torch/extension.h>
4
+
5
+ #include <vector>
6
+
7
+ namespace {
8
+
9
+ std::vector<torch::Tensor> silu_product_nvfp4_m1(
10
+ const torch::Tensor& gate,
11
+ const torch::Tensor& up) {
12
+ TORCH_CHECK(
13
+ gate.is_cuda() && gate.scalar_type() == at::kBFloat16 &&
14
+ gate.dim() == 2 && gate.size(0) == 1 && gate.is_contiguous(),
15
+ "gate must be contiguous CUDA bfloat16 [1,K]");
16
+ TORCH_CHECK(
17
+ up.is_cuda() && up.scalar_type() == at::kBFloat16 &&
18
+ up.dim() == 2 && up.size(0) == 1 && up.is_contiguous(),
19
+ "up must be contiguous CUDA bfloat16 [1,K]");
20
+ TORCH_CHECK(
21
+ gate.device() == up.device() && gate.sizes() == up.sizes(),
22
+ "gate and up shapes/devices differ");
23
+ TORCH_CHECK(
24
+ gate.size(1) > 0 && gate.size(1) % 32 == 0,
25
+ "SiLU/product-to-NVFP4 requires K divisible by 32");
26
+ return silu_product_nvfp4_m1_cuda(gate, up);
27
+ }
28
+
29
+ std::vector<torch::Tensor> product_nvfp4_m1(
30
+ const torch::Tensor& left,
31
+ const torch::Tensor& right) {
32
+ TORCH_CHECK(
33
+ left.is_cuda() && left.scalar_type() == at::kBFloat16 &&
34
+ left.dim() == 2 && left.size(0) == 1 && left.is_contiguous(),
35
+ "left must be contiguous CUDA bfloat16 [1,K]");
36
+ TORCH_CHECK(
37
+ right.is_cuda() && right.scalar_type() == at::kBFloat16 &&
38
+ right.dim() == 2 && right.size(0) == 1 && right.is_contiguous(),
39
+ "right must be contiguous CUDA bfloat16 [1,K]");
40
+ TORCH_CHECK(
41
+ left.device() == right.device() && left.sizes() == right.sizes(),
42
+ "left and right shapes/devices differ");
43
+ TORCH_CHECK(
44
+ left.size(1) > 0 && left.size(1) % 32 == 0,
45
+ "product-to-NVFP4 requires K divisible by 32");
46
+ return product_nvfp4_m1_cuda(left, right);
47
+ }
48
+
49
+ std::vector<torch::Tensor> pack_nvfp4_m1(const torch::Tensor& input) {
50
+ TORCH_CHECK(
51
+ input.is_cuda() && input.scalar_type() == at::kBFloat16 &&
52
+ input.dim() == 2 && input.size(0) == 1 && input.is_contiguous(),
53
+ "input must be contiguous CUDA bfloat16 [1,K]");
54
+ TORCH_CHECK(
55
+ input.size(1) > 0 && input.size(1) % 32 == 0,
56
+ "NVFP4 pack requires K divisible by 32");
57
+ return pack_nvfp4_m1_cuda(input);
58
+ }
59
+
60
+ std::vector<torch::Tensor> pack_nvfp4_fixed_scale_m1(
61
+ const torch::Tensor& input,
62
+ const torch::Tensor& tensor_scale) {
63
+ TORCH_CHECK(
64
+ input.is_cuda() && input.scalar_type() == at::kBFloat16 &&
65
+ input.dim() == 2 && input.size(0) == 1 && input.is_contiguous(),
66
+ "input must be contiguous CUDA bfloat16 [1,K]");
67
+ TORCH_CHECK(
68
+ input.size(1) > 0 && input.size(1) % 32 == 0,
69
+ "fixed-scale NVFP4 pack requires K divisible by 32");
70
+ TORCH_CHECK(
71
+ tensor_scale.is_cuda() && tensor_scale.device() == input.device() &&
72
+ tensor_scale.scalar_type() == at::kFloat &&
73
+ tensor_scale.numel() == 1 && tensor_scale.is_contiguous(),
74
+ "tensor scale must be a contiguous CUDA float32 scalar");
75
+ return pack_nvfp4_fixed_scale_m1_cuda(input, tensor_scale);
76
+ }
77
+
78
+ } // namespace
79
+
80
+ PYBIND11_MODULE(TORCH_EXTENSION_NAME, module) {
81
+ module.def(
82
+ "quantize",
83
+ &silu_product_nvfp4_m1,
84
+ "Fused BF16 SiLU/product to packed NVFP4 at logical M=1");
85
+ module.def(
86
+ "quantize_product",
87
+ &product_nvfp4_m1,
88
+ "Fused BF16 product to packed NVFP4 at logical M=1");
89
+ module.def(
90
+ "quantize_input",
91
+ &pack_nvfp4_m1,
92
+ "Pack a materialized BF16 input to NVFP4 at logical M=1");
93
+ module.def(
94
+ "quantize_input_fixed_scale",
95
+ &pack_nvfp4_fixed_scale_m1,
96
+ "Pack BF16 to NVFP4 with a supplied tensor scale at logical M=1");
97
+ }
runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.cu ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "silu_product_nvfp4_m1.h"
2
+
3
+ #include <ATen/cuda/CUDAContext.h>
4
+ #include <c10/cuda/CUDAGuard.h>
5
+ #include <cuda_bf16.h>
6
+ #include <cuda_fp4.h>
7
+ #include <cuda_fp8.h>
8
+ #include <cuda_runtime.h>
9
+
10
+ #include <cstdint>
11
+ #include <vector>
12
+
13
+ namespace {
14
+
15
+ constexpr int kThreads = 256;
16
+ constexpr int kFp4BlockElements = 16;
17
+ constexpr int kScaleTileOuter = 128;
18
+ constexpr float kFp4Max = 6.0f;
19
+ constexpr float kFp8Max = 448.0f;
20
+ constexpr float kCombinedMax = kFp4Max * kFp8Max;
21
+
22
+ __device__ __forceinline__ size_t scale_offset(
23
+ int outer,
24
+ int inner_scale,
25
+ int scale_inner_dim) {
26
+ const int outer_tile = outer / kScaleTileOuter;
27
+ const int local_outer = outer % kScaleTileOuter;
28
+ const int local_inner = inner_scale & 3;
29
+ const int inner_tile_start = inner_scale - local_inner;
30
+ const size_t tile_base =
31
+ static_cast<size_t>(inner_tile_start + outer_tile * scale_inner_dim) *
32
+ kScaleTileOuter;
33
+ return tile_base + static_cast<size_t>(local_outer & 31) * 16 +
34
+ static_cast<size_t>(local_outer >> 5) * 4 + local_inner;
35
+ }
36
+
37
+ __device__ __forceinline__ float e4m3_to_float(uint8_t raw) {
38
+ const __half_raw half_raw = __nv_cvt_fp8_to_halfraw(raw, __NV_E4M3);
39
+ return __half2float(static_cast<__half>(half_raw));
40
+ }
41
+
42
+ // Match PyTorch's two BF16 materialization boundaries:
43
+ // silu(gate_bf16) -> bfloat16, then * up_bf16 -> bfloat16.
44
+ __device__ __forceinline__ float silu_product_value(
45
+ const __nv_bfloat16* gate,
46
+ const __nv_bfloat16* up,
47
+ int index) {
48
+ const float gate_value = __bfloat162float(gate[index]);
49
+ const float silu_value = gate_value / (1.0f + expf(-gate_value));
50
+ const __nv_bfloat16 silu_bf16 = __float2bfloat16_rn(silu_value);
51
+ const float product =
52
+ __bfloat162float(silu_bf16) * __bfloat162float(up[index]);
53
+ return __bfloat162float(__float2bfloat16_rn(product));
54
+ }
55
+
56
+ __device__ __forceinline__ float product_value(
57
+ const __nv_bfloat16* left,
58
+ const __nv_bfloat16* right,
59
+ int index) {
60
+ const float product =
61
+ __bfloat162float(left[index]) * __bfloat162float(right[index]);
62
+ return __bfloat162float(__float2bfloat16_rn(product));
63
+ }
64
+
65
+ template <int kMode>
66
+ __global__ void product_nvfp4_m1_kernel(
67
+ const __nv_bfloat16* __restrict__ left,
68
+ const __nv_bfloat16* __restrict__ right,
69
+ uint8_t* __restrict__ qdata,
70
+ uint8_t* __restrict__ block_scales,
71
+ float* __restrict__ tensor_scale,
72
+ int k,
73
+ int scale_inner_dim) {
74
+ __shared__ float reduction[kThreads];
75
+ const int tid = threadIdx.x;
76
+ float local_max = 0.0f;
77
+ for (int index = tid; index < k; index += kThreads) {
78
+ const float value = kMode == 0
79
+ ? silu_product_value(left, right, index)
80
+ : (kMode == 1
81
+ ? product_value(left, right, index)
82
+ : __bfloat162float(left[index]));
83
+ local_max = fmaxf(
84
+ local_max,
85
+ fabsf(value));
86
+ }
87
+ reduction[tid] = local_max;
88
+ __syncthreads();
89
+ for (int offset = kThreads / 2; offset > 0; offset >>= 1) {
90
+ if (tid < offset) {
91
+ reduction[tid] = fmaxf(reduction[tid], reduction[tid + offset]);
92
+ }
93
+ __syncthreads();
94
+ }
95
+ // TensorCoreNVFP4Layout derives its default scale from a BF16 amax and
96
+ // rounds the division result to BF16 before storing a scalar FP32 Params.
97
+ const float global_scale = __bfloat162float(__float2bfloat16_rn(
98
+ __fdiv_rn(reduction[0], kCombinedMax)));
99
+ if (tid == 0) {
100
+ tensor_scale[0] = global_scale;
101
+ }
102
+ __syncthreads();
103
+
104
+ const int block_count = k / kFp4BlockElements;
105
+ for (int block = tid; block < block_count; block += kThreads) {
106
+ const int base = block * kFp4BlockElements;
107
+ float values[kFp4BlockElements];
108
+ float block_max = 0.0f;
109
+ #pragma unroll
110
+ for (int element = 0; element < kFp4BlockElements; ++element) {
111
+ values[element] = kMode == 0
112
+ ? silu_product_value(left, right, base + element)
113
+ : (kMode == 1
114
+ ? product_value(left, right, base + element)
115
+ : __bfloat162float(left[base + element]));
116
+ block_max = fmaxf(block_max, fabsf(values[element]));
117
+ }
118
+ float scaled_block_scale = (block_max / kFp4Max) / global_scale;
119
+ scaled_block_scale = fminf(scaled_block_scale, kFp8Max);
120
+ const uint8_t raw_block_scale = static_cast<uint8_t>(
121
+ __nv_cvt_float_to_fp8(
122
+ scaled_block_scale, __NV_SATFINITE, __NV_E4M3));
123
+ block_scales[scale_offset(0, block, scale_inner_dim)] = raw_block_scale;
124
+ const float total_scale = global_scale * e4m3_to_float(raw_block_scale);
125
+ #pragma unroll
126
+ for (int pair = 0; pair < kFp4BlockElements / 2; ++pair) {
127
+ const float even = values[pair * 2] / total_scale;
128
+ const float odd = values[pair * 2 + 1] / total_scale;
129
+ const float2 arguments = make_float2(odd, even);
130
+ qdata[base / 2 + pair] = static_cast<uint8_t>(
131
+ __nv_cvt_float2_to_fp4x2(arguments, __NV_E2M1, cudaRoundNearest));
132
+ }
133
+ }
134
+ }
135
+
136
+ __global__ void pack_nvfp4_fixed_scale_m1_kernel(
137
+ const __nv_bfloat16* __restrict__ input,
138
+ uint8_t* __restrict__ qdata,
139
+ uint8_t* __restrict__ block_scales,
140
+ const float* __restrict__ tensor_scale,
141
+ int k,
142
+ int scale_inner_dim) {
143
+ const int tid = threadIdx.x;
144
+ const float global_scale = tensor_scale[0];
145
+ const int block_count = k / kFp4BlockElements;
146
+ for (int block = tid; block < block_count; block += blockDim.x) {
147
+ const int base = block * kFp4BlockElements;
148
+ float values[kFp4BlockElements];
149
+ float block_max = 0.0f;
150
+ #pragma unroll
151
+ for (int element = 0; element < kFp4BlockElements; ++element) {
152
+ values[element] = __bfloat162float(input[base + element]);
153
+ block_max = fmaxf(block_max, fabsf(values[element]));
154
+ }
155
+ float scaled_block_scale = (block_max / kFp4Max) / global_scale;
156
+ scaled_block_scale = fminf(scaled_block_scale, kFp8Max);
157
+ const uint8_t raw_block_scale = static_cast<uint8_t>(
158
+ __nv_cvt_float_to_fp8(
159
+ scaled_block_scale, __NV_SATFINITE, __NV_E4M3));
160
+ block_scales[scale_offset(0, block, scale_inner_dim)] = raw_block_scale;
161
+ const float total_scale = global_scale * e4m3_to_float(raw_block_scale);
162
+ #pragma unroll
163
+ for (int pair = 0; pair < kFp4BlockElements / 2; ++pair) {
164
+ const float2 arguments = make_float2(
165
+ values[pair * 2 + 1] / total_scale,
166
+ values[pair * 2] / total_scale);
167
+ qdata[base / 2 + pair] = static_cast<uint8_t>(
168
+ __nv_cvt_float2_to_fp4x2(arguments, __NV_E2M1, cudaRoundNearest));
169
+ }
170
+ }
171
+ }
172
+
173
+ } // namespace
174
+
175
+ std::vector<torch::Tensor> silu_product_nvfp4_m1_cuda(
176
+ const torch::Tensor& gate,
177
+ const torch::Tensor& up) {
178
+ const auto device = gate.device();
179
+ c10::cuda::CUDAGuard guard(device);
180
+ const int64_t k = gate.size(1);
181
+ const int64_t scale_cols = (k / 16 + 3) / 4 * 4;
182
+ torch::Tensor qdata = torch::zeros(
183
+ {16, k / 2}, gate.options().dtype(at::kByte));
184
+ torch::Tensor block_scales = torch::zeros(
185
+ {128, scale_cols},
186
+ gate.options().dtype(at::ScalarType::Float8_e4m3fn));
187
+ torch::Tensor tensor_scale = torch::empty(
188
+ {}, gate.options().dtype(at::kFloat));
189
+ const auto stream = at::cuda::getCurrentCUDAStream(device.index()).stream();
190
+ product_nvfp4_m1_kernel<0><<<1, kThreads, 0, stream>>>(
191
+ reinterpret_cast<const __nv_bfloat16*>(gate.data_ptr()),
192
+ reinterpret_cast<const __nv_bfloat16*>(up.data_ptr()),
193
+ reinterpret_cast<uint8_t*>(qdata.data_ptr()),
194
+ reinterpret_cast<uint8_t*>(block_scales.data_ptr()),
195
+ reinterpret_cast<float*>(tensor_scale.data_ptr()),
196
+ static_cast<int>(k),
197
+ static_cast<int>(scale_cols));
198
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
199
+ return {qdata, block_scales, tensor_scale};
200
+ }
201
+
202
+ std::vector<torch::Tensor> product_nvfp4_m1_cuda(
203
+ const torch::Tensor& left,
204
+ const torch::Tensor& right) {
205
+ const auto device = left.device();
206
+ c10::cuda::CUDAGuard guard(device);
207
+ const int64_t k = left.size(1);
208
+ const int64_t scale_cols = (k / 16 + 3) / 4 * 4;
209
+ torch::Tensor qdata = torch::zeros(
210
+ {16, k / 2}, left.options().dtype(at::kByte));
211
+ torch::Tensor block_scales = torch::zeros(
212
+ {128, scale_cols},
213
+ left.options().dtype(at::ScalarType::Float8_e4m3fn));
214
+ torch::Tensor tensor_scale = torch::empty(
215
+ {}, left.options().dtype(at::kFloat));
216
+ const auto stream = at::cuda::getCurrentCUDAStream(device.index()).stream();
217
+ product_nvfp4_m1_kernel<1><<<1, kThreads, 0, stream>>>(
218
+ reinterpret_cast<const __nv_bfloat16*>(left.data_ptr()),
219
+ reinterpret_cast<const __nv_bfloat16*>(right.data_ptr()),
220
+ reinterpret_cast<uint8_t*>(qdata.data_ptr()),
221
+ reinterpret_cast<uint8_t*>(block_scales.data_ptr()),
222
+ reinterpret_cast<float*>(tensor_scale.data_ptr()),
223
+ static_cast<int>(k),
224
+ static_cast<int>(scale_cols));
225
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
226
+ return {qdata, block_scales, tensor_scale};
227
+ }
228
+
229
+ std::vector<torch::Tensor> pack_nvfp4_m1_cuda(const torch::Tensor& input) {
230
+ const auto device = input.device();
231
+ c10::cuda::CUDAGuard guard(device);
232
+ const int64_t k = input.size(1);
233
+ const int64_t scale_cols = (k / 16 + 3) / 4 * 4;
234
+ torch::Tensor qdata = torch::zeros(
235
+ {16, k / 2}, input.options().dtype(at::kByte));
236
+ torch::Tensor block_scales = torch::zeros(
237
+ {128, scale_cols},
238
+ input.options().dtype(at::ScalarType::Float8_e4m3fn));
239
+ torch::Tensor tensor_scale = torch::empty(
240
+ {}, input.options().dtype(at::kFloat));
241
+ const auto stream = at::cuda::getCurrentCUDAStream(device.index()).stream();
242
+ product_nvfp4_m1_kernel<2><<<1, kThreads, 0, stream>>>(
243
+ reinterpret_cast<const __nv_bfloat16*>(input.data_ptr()),
244
+ reinterpret_cast<const __nv_bfloat16*>(input.data_ptr()),
245
+ reinterpret_cast<uint8_t*>(qdata.data_ptr()),
246
+ reinterpret_cast<uint8_t*>(block_scales.data_ptr()),
247
+ reinterpret_cast<float*>(tensor_scale.data_ptr()),
248
+ static_cast<int>(k),
249
+ static_cast<int>(scale_cols));
250
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
251
+ return {qdata, block_scales, tensor_scale};
252
+ }
253
+
254
+ std::vector<torch::Tensor> pack_nvfp4_fixed_scale_m1_cuda(
255
+ const torch::Tensor& input,
256
+ const torch::Tensor& tensor_scale) {
257
+ const auto device = input.device();
258
+ c10::cuda::CUDAGuard guard(device);
259
+ const int64_t k = input.size(1);
260
+ const int64_t scale_cols = (k / 16 + 3) / 4 * 4;
261
+ torch::Tensor qdata = torch::zeros(
262
+ {16, k / 2}, input.options().dtype(at::kByte));
263
+ torch::Tensor block_scales = torch::zeros(
264
+ {128, scale_cols},
265
+ input.options().dtype(at::ScalarType::Float8_e4m3fn));
266
+ const auto stream = at::cuda::getCurrentCUDAStream(device.index()).stream();
267
+ pack_nvfp4_fixed_scale_m1_kernel<<<1, kThreads, 0, stream>>>(
268
+ reinterpret_cast<const __nv_bfloat16*>(input.data_ptr()),
269
+ reinterpret_cast<uint8_t*>(qdata.data_ptr()),
270
+ reinterpret_cast<uint8_t*>(block_scales.data_ptr()),
271
+ reinterpret_cast<const float*>(tensor_scale.data_ptr()),
272
+ static_cast<int>(k),
273
+ static_cast<int>(scale_cols));
274
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
275
+ return {qdata, block_scales};
276
+ }
runtime/native/silu_product_nvfp4_m1/silu_product_nvfp4_m1.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/extension.h>
4
+
5
+ #include <vector>
6
+
7
+ std::vector<torch::Tensor> silu_product_nvfp4_m1_cuda(
8
+ const torch::Tensor& gate,
9
+ const torch::Tensor& up);
10
+
11
+ std::vector<torch::Tensor> product_nvfp4_m1_cuda(
12
+ const torch::Tensor& left,
13
+ const torch::Tensor& right);
14
+
15
+ std::vector<torch::Tensor> pack_nvfp4_m1_cuda(
16
+ const torch::Tensor& input);
17
+
18
+ std::vector<torch::Tensor> pack_nvfp4_fixed_scale_m1_cuda(
19
+ const torch::Tensor& input,
20
+ const torch::Tensor& tensor_scale);
runtime/server.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Serve the self-contained English S2-Pro mixed NVFP4 V1 checkpoint."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import multiprocessing
9
+ import os
10
+ import sys
11
+ from argparse import Namespace
12
+ from pathlib import Path
13
+
14
+ import torch
15
+ import uvicorn
16
+ from kui.asgi import JSONResponse
17
+
18
+
19
+ ROOT = Path(
20
+ os.environ.get("FISH_NVFP4_ROOT", Path(__file__).resolve().parents[1])
21
+ ).resolve()
22
+ RUNTIME_ROOT = ROOT / "runtime"
23
+ if str(RUNTIME_ROOT) not in sys.path:
24
+ sys.path.insert(0, str(RUNTIME_ROOT))
25
+
26
+ from experimental.codec import (
27
+ load_compact_codec_model,
28
+ load_reference_audio_soundfile,
29
+ warm_reference_encoder,
30
+ )
31
+ from experimental.nvfp4 import launch_mixed_nvfp4_thread_safe_queue
32
+
33
+
34
+ DEFAULT_CHECKPOINT = ROOT
35
+ DEFAULT_WEB_UI = RUNTIME_ROOT / "web" / "index.html"
36
+ EXPECTED_FORMAT = "fish-s2-pro-project-local-nvfp4-mixed"
37
+ EXPECTED_POLICY = "w4a16_gate_up_middle30_mxfp8_rest"
38
+
39
+
40
+ def parse_args() -> argparse.Namespace:
41
+ parser = argparse.ArgumentParser(description=__doc__)
42
+ parser.add_argument("--checkpoint", type=Path, default=DEFAULT_CHECKPOINT)
43
+ parser.add_argument("--host", default="0.0.0.0")
44
+ parser.add_argument("--port", type=int, default=8080)
45
+ parser.add_argument("--device", default="cuda:0")
46
+ parser.add_argument("--cache-length", type=int, default=3072)
47
+ parser.add_argument("--max-text-length", type=int, default=0)
48
+ parser.add_argument("--api-key")
49
+ parser.add_argument("--verify-checksums", action="store_true")
50
+ return parser.parse_args()
51
+
52
+
53
+ def validate(args: argparse.Namespace) -> dict:
54
+ if not 1 <= args.port <= 65535:
55
+ raise SystemExit("--port must be between 1 and 65535")
56
+ metadata_path = args.checkpoint / "quantization.json"
57
+ codec_path = args.checkpoint / "codec.pth"
58
+ if not metadata_path.is_file() or not codec_path.is_file():
59
+ raise SystemExit(f"Incomplete NVFP4 checkpoint: {args.checkpoint}")
60
+ metadata = json.loads(metadata_path.read_text())
61
+ if metadata.get("format") != EXPECTED_FORMAT:
62
+ raise SystemExit(f"Unsupported checkpoint format: {metadata.get('format')}")
63
+ if metadata.get("policy") != EXPECTED_POLICY:
64
+ raise SystemExit(f"Unexpected NVFP4 policy: {metadata.get('policy')}")
65
+ if metadata.get("fresh_load_verification", {}).get("status") != "passed":
66
+ raise SystemExit("Checkpoint lacks a passed fresh-load verification")
67
+ if not torch.cuda.is_available() or torch.cuda.get_device_capability(args.device)[0] != 12:
68
+ raise SystemExit("The mixed NVFP4 kernels require an SM120 CUDA GPU")
69
+ return metadata
70
+
71
+
72
+ def main() -> int:
73
+ args = parse_args()
74
+ metadata = validate(args)
75
+
76
+ import tools.server.model_manager as model_manager_module
77
+ import tools.server.views as server_views
78
+ from fish_speech.inference_engine.reference_loader import ReferenceLoader
79
+
80
+ def checkpoint_queue_loader(checkpoint_path, device, precision, compile=False):
81
+ return launch_mixed_nvfp4_thread_safe_queue(
82
+ checkpoint_path,
83
+ device,
84
+ precision,
85
+ compile,
86
+ max_length=args.cache_length,
87
+ verify_checksums=args.verify_checksums,
88
+ )
89
+
90
+ def compact_codec_loader(config_name, checkpoint_path, device):
91
+ codec = load_compact_codec_model(
92
+ config_name,
93
+ checkpoint_path,
94
+ device,
95
+ torch.bfloat16,
96
+ offload_reference=True,
97
+ )
98
+ codec._reference_warmup_report = warm_reference_encoder(codec, device)
99
+ return codec
100
+
101
+ model_manager_module.launch_thread_safe_queue = checkpoint_queue_loader
102
+ model_manager_module.load_decoder_model = compact_codec_loader
103
+ ReferenceLoader.load_audio = staticmethod(load_reference_audio_soundfile)
104
+ server_views._WEBUI_HTML = DEFAULT_WEB_UI
105
+
106
+ @server_views.routes.http.get("/v1/model")
107
+ async def model_info():
108
+ return JSONResponse(
109
+ {
110
+ "model": "V1 · Fish Audio S2-Pro NVFP4 Balanced",
111
+ "checkpoint": str(args.checkpoint),
112
+ "checkpoint_status": metadata["status"],
113
+ "quantization": "60 native NVFP4 W4A16/W4A4 + 120 native MXFP8 W8A8",
114
+ "release": metadata.get("release"),
115
+ "policy": metadata["policy"],
116
+ "sampling": metadata["qualified_sampling"],
117
+ "fresh_load_verification": metadata["fresh_load_verification"],
118
+ "device": args.device,
119
+ "cache_length": args.cache_length,
120
+ }
121
+ )
122
+
123
+ from tools.api_server import API
124
+
125
+ upstream_args = Namespace(
126
+ mode="tts",
127
+ device=args.device,
128
+ half=False,
129
+ compile=False,
130
+ llama_checkpoint_path=str(args.checkpoint),
131
+ decoder_checkpoint_path=str(args.checkpoint / "codec.pth"),
132
+ decoder_config_name="modded_dac_vq",
133
+ max_text_length=args.max_text_length,
134
+ listen=f"{args.host}:{args.port}",
135
+ workers=1,
136
+ api_key=args.api_key,
137
+ )
138
+ multiprocessing.set_start_method("spawn", force=True)
139
+ app = API(args=upstream_args).app
140
+ uvicorn.run(app, host=args.host, port=args.port, workers=1, log_level="info")
141
+ return 0
142
+
143
+
144
+ if __name__ == "__main__":
145
+ raise SystemExit(main())
runtime/torch-overrides.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ torch==2.11.0
2
+ torchaudio==2.11.0
3
+ protobuf>=3.20.0,<6.0.0
4
+ tensorboard==2.20.0
5
+ transformers==4.56.1
6
+ tokenizers==0.22.0
7
+ huggingface-hub==0.34.4
special_tokens_map.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff
 
validate_release.py ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Validate the self-contained Fish S2-Pro NVFP4/MXFP8 V1 release."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import hashlib
7
+ import json
8
+ import struct
9
+ from pathlib import Path, PurePosixPath
10
+
11
+
12
+ ROOT = Path(__file__).resolve().parent
13
+ DTYPE_BYTES = {
14
+ "BF16": 2,
15
+ "F32": 4,
16
+ "F8_E4M3": 1,
17
+ "I32": 4,
18
+ "U8": 1,
19
+ }
20
+
21
+
22
+ def fail(message: str) -> None:
23
+ raise RuntimeError(message)
24
+
25
+
26
+ def sha256(path: Path) -> str:
27
+ digest = hashlib.sha256()
28
+ with path.open("rb") as handle:
29
+ for chunk in iter(lambda: handle.read(8 * 1024 * 1024), b""):
30
+ digest.update(chunk)
31
+ return digest.hexdigest()
32
+
33
+
34
+ def load_json(relative: str) -> dict:
35
+ path = ROOT / relative
36
+ if not path.is_file():
37
+ fail(f"missing required JSON file: {relative}")
38
+ try:
39
+ return json.loads(path.read_text(encoding="utf-8"))
40
+ except (OSError, json.JSONDecodeError) as error:
41
+ fail(f"invalid JSON in {relative}: {error}")
42
+
43
+
44
+ def safetensors_header(path: Path) -> dict:
45
+ with path.open("rb") as handle:
46
+ raw_length = handle.read(8)
47
+ if len(raw_length) != 8:
48
+ fail(f"truncated safetensors length: {path.name}")
49
+ header_length = struct.unpack("<Q", raw_length)[0]
50
+ if header_length <= 2 or header_length > path.stat().st_size - 8:
51
+ fail(f"invalid safetensors header length: {path.name}")
52
+ try:
53
+ return json.loads(handle.read(header_length))
54
+ except json.JSONDecodeError as error:
55
+ fail(f"invalid safetensors header in {path.name}: {error}")
56
+
57
+
58
+ def validate_metadata() -> dict:
59
+ config = load_json("config.json")
60
+ policy = config.get("fish_s2_quantization")
61
+ if not isinstance(policy, dict):
62
+ fail("config.json has no fish_s2_quantization dictionary")
63
+ expected = {
64
+ "format": "mixed_nvfp4_mxfp8",
65
+ "profile": "balanced",
66
+ "release": "v1",
67
+ "policy": "w4a16_gate_up_middle30_mxfp8_rest",
68
+ "nvfp4_modules": 60,
69
+ "mxfp8_modules": 120,
70
+ "runtime": "bundled",
71
+ "hardware_family": "sm_120",
72
+ }
73
+ if policy != expected:
74
+ fail(f"unexpected config quantization policy: {policy}")
75
+
76
+ quantization = load_json("quantization.json")
77
+ if quantization.get("format") != "fish-s2-pro-project-local-nvfp4-mixed":
78
+ fail("unexpected quantization format")
79
+ if quantization.get("policy") != "w4a16_gate_up_middle30_mxfp8_rest":
80
+ fail("unexpected quantization policy")
81
+ release = quantization.get("release", {})
82
+ if release.get("version") != "1.0" or release.get("xpo3_release") is not False:
83
+ fail("release must identify V1 and explicitly remain outside XPO3")
84
+ if release.get("repository_name") != "ajh-code/Fish-Audio-S2-Pro-NVFP4-Balanced":
85
+ fail("release metadata has the wrong Hugging Face repository name")
86
+ if release.get("self_contained_weights") is not True:
87
+ fail("release does not declare self-contained weights")
88
+ fresh_load = quantization.get("fresh_load_verification", {})
89
+ if fresh_load.get("status") != "passed":
90
+ fail("checkpoint lacks passed fresh-load verification")
91
+ conversion = quantization.get("conversion", {})
92
+ if len(conversion.get("records", [])) != 180:
93
+ fail("quantization metadata must contain 180 projection records")
94
+ if conversion.get("correction_parameters") != 0:
95
+ fail("V1 loader does not accept correction-bearing checkpoints")
96
+ if conversion.get("w4a16_max_m") != 1:
97
+ fail("V1 must use the qualified M=1 W4A16 decode boundary")
98
+
99
+ source = (ROOT / ".source").read_text(encoding="utf-8")
100
+ for revision in (
101
+ "1de9996b6be38b745688de084d87a5633f714e4e",
102
+ "e5e292632cb11e7a27b2b7487f58f612bc101e13",
103
+ "a04c1b63b1a7a670840fb3e97a82c0dbe2a35ded",
104
+ "7a03467b90d6feff6bd196928dfe156bd173f36e",
105
+ ):
106
+ if revision not in source:
107
+ fail(f".source is missing pinned revision {revision}")
108
+
109
+ license_text = (ROOT / "LICENSE.md").read_text(encoding="utf-8")
110
+ if "FISH AUDIO RESEARCH LICENSE AGREEMENT" not in license_text:
111
+ fail("LICENSE.md is not the Fish Audio Research License")
112
+ notice = (ROOT / "Notice").read_text(encoding="utf-8")
113
+ if "This model is licensed under the Fish Audio Research License" not in notice:
114
+ fail("Notice lacks the required Fish Audio attribution")
115
+ if "Built with Fish Audio" not in notice:
116
+ fail("Notice lacks the required Built with Fish Audio statement")
117
+ readme = (ROOT / "README.md").read_text(encoding="utf-8")
118
+ for required in (
119
+ "Built with Fish Audio",
120
+ "This is not yet an XPO3 release",
121
+ "Commercial use requires a separate",
122
+ ):
123
+ if required not in readme:
124
+ fail(f"README.md lacks required release statement: {required}")
125
+ return quantization
126
+
127
+
128
+ def validate_checkpoint(quantization: dict) -> tuple[int, int, int]:
129
+ index = load_json("model.safetensors.index.json")
130
+ weight_map = index.get("weight_map")
131
+ if not isinstance(weight_map, dict) or not weight_map:
132
+ fail("checkpoint index has no weight map")
133
+ shard_names = sorted(set(weight_map.values()))
134
+ if shard_names != [
135
+ "model-00001-of-00003.safetensors",
136
+ "model-00002-of-00003.safetensors",
137
+ "model-00003-of-00003.safetensors",
138
+ ]:
139
+ fail(f"unexpected checkpoint shards: {shard_names}")
140
+
141
+ discovered: dict[str, str] = {}
142
+ logical_bytes = 0
143
+ for shard_name in shard_names:
144
+ shard_path = ROOT / shard_name
145
+ if not shard_path.is_file():
146
+ fail(f"missing checkpoint shard: {shard_name}")
147
+ header = safetensors_header(shard_path)
148
+ for name, record in header.items():
149
+ if name == "__metadata__":
150
+ continue
151
+ if name in discovered:
152
+ fail(f"duplicate tensor across shards: {name}")
153
+ dtype = record.get("dtype")
154
+ shape = record.get("shape")
155
+ offsets = record.get("data_offsets")
156
+ if dtype not in DTYPE_BYTES or not isinstance(shape, list):
157
+ fail(f"unsupported tensor metadata for {name}")
158
+ if (
159
+ not isinstance(offsets, list)
160
+ or len(offsets) != 2
161
+ or not all(isinstance(value, int) for value in offsets)
162
+ or offsets[0] < 0
163
+ or offsets[1] < offsets[0]
164
+ ):
165
+ fail(f"invalid data offsets for {name}")
166
+ elements = 1
167
+ for dimension in shape:
168
+ if not isinstance(dimension, int) or dimension < 0:
169
+ fail(f"invalid shape for {name}")
170
+ elements *= dimension
171
+ tensor_bytes = elements * DTYPE_BYTES[dtype]
172
+ if offsets[1] - offsets[0] != tensor_bytes:
173
+ fail(f"tensor byte range mismatch for {name}")
174
+ logical_bytes += tensor_bytes
175
+ discovered[name] = shard_name
176
+
177
+ if discovered != weight_map:
178
+ missing = sorted(set(weight_map) - set(discovered))
179
+ extra = sorted(set(discovered) - set(weight_map))
180
+ fail(f"checkpoint index mismatch; missing={missing[:3]} extra={extra[:3]}")
181
+ expected_size = int(index.get("metadata", {}).get("total_size", -1))
182
+ if logical_bytes != expected_size:
183
+ fail(f"logical checkpoint size mismatch: {logical_bytes} != {expected_size}")
184
+ if logical_bytes != quantization.get("state_payload_bytes"):
185
+ fail("quantization state_payload_bytes does not match the checkpoint")
186
+
187
+ counts = {
188
+ "qdata": sum(name.endswith(".qdata") for name in weight_map),
189
+ "weight_block_scale": sum(
190
+ name.endswith(".weight_block_scale") for name in weight_map
191
+ ),
192
+ "weight_scale": sum(name.endswith(".weight_scale") for name in weight_map),
193
+ "weight_fp8": sum(name.endswith(".weight_fp8") for name in weight_map),
194
+ "weight_scale_storage": sum(
195
+ name.endswith(".weight_scale_storage") for name in weight_map
196
+ ),
197
+ }
198
+ if counts != {
199
+ "qdata": 60,
200
+ "weight_block_scale": 60,
201
+ "weight_scale": 60,
202
+ "weight_fp8": 120,
203
+ "weight_scale_storage": 120,
204
+ }:
205
+ fail(f"unexpected packed tensor counts: {counts}")
206
+ if counts != quantization.get("packed_tensor_counts"):
207
+ fail("packed tensor counts disagree with quantization.json")
208
+ return len(weight_map), len(shard_names), logical_bytes
209
+
210
+
211
+ def validate_runtime() -> None:
212
+ required = (
213
+ "codec.pth",
214
+ "client.py",
215
+ "launch.sh",
216
+ "install.sh",
217
+ "Dockerfile",
218
+ "compose.yaml",
219
+ "runtime/server.py",
220
+ "runtime/web/index.html",
221
+ "runtime/experimental/codec.py",
222
+ "runtime/experimental/nvfp4/checkpoint.py",
223
+ "runtime/experimental/nvfp4/modules.py",
224
+ "runtime/experimental/fp8/modules.py",
225
+ "runtime/native/smallm_gemv/smallm_gemv.cpp",
226
+ "runtime/native/smallm_gemv/smallm_gemv.cu",
227
+ "runtime/native/smallm_gemv/smallm_gemv.h",
228
+ "runtime/native/LICENSE",
229
+ "vendor/fish-speech/.project-root",
230
+ "vendor/fish-speech/LICENSE",
231
+ "vendor/fish-speech/pyproject.toml",
232
+ "vendor/fish-speech/fish_speech/configs/modded_dac_vq.yaml",
233
+ "vendor/fish-speech/tools/api_server.py",
234
+ )
235
+ for relative in required:
236
+ if not (ROOT / relative).is_file():
237
+ fail(f"missing required release file: {relative}")
238
+
239
+
240
+ def validate_manifest() -> int:
241
+ manifest = load_json("MANIFEST.json")
242
+ records = manifest.get("files")
243
+ if not isinstance(records, list) or not records:
244
+ fail("MANIFEST.json has no file records")
245
+ seen: set[str] = set()
246
+ for record in records:
247
+ relative = record.get("path")
248
+ if not isinstance(relative, str):
249
+ fail("manifest record has no path")
250
+ pure = PurePosixPath(relative)
251
+ if pure.is_absolute() or ".." in pure.parts or relative == "MANIFEST.json":
252
+ fail(f"unsafe or recursive manifest path: {relative}")
253
+ if relative in seen:
254
+ fail(f"duplicate manifest path: {relative}")
255
+ seen.add(relative)
256
+ path = ROOT.joinpath(*pure.parts)
257
+ if not path.is_file():
258
+ fail(f"manifest file is missing: {relative}")
259
+ if path.stat().st_size != record.get("size"):
260
+ fail(f"manifest size mismatch: {relative}")
261
+ if sha256(path) != record.get("sha256"):
262
+ fail(f"manifest hash mismatch: {relative}")
263
+ return len(records)
264
+
265
+
266
+ def main() -> None:
267
+ quantization = validate_metadata()
268
+ checkpoint_tensors, checkpoint_shards, logical_bytes = validate_checkpoint(
269
+ quantization
270
+ )
271
+ validate_runtime()
272
+ manifest_files = validate_manifest()
273
+ print(
274
+ json.dumps(
275
+ {
276
+ "status": "pass",
277
+ "release": "v1",
278
+ "xpo3_release": False,
279
+ "checkpoint_tensors": checkpoint_tensors,
280
+ "checkpoint_shards": checkpoint_shards,
281
+ "checkpoint_logical_bytes": logical_bytes,
282
+ "nvfp4_projections": 60,
283
+ "mxfp8_projections": 120,
284
+ "manifest_files": manifest_files,
285
+ "self_contained_weights": True,
286
+ },
287
+ indent=2,
288
+ )
289
+ )
290
+
291
+
292
+ if __name__ == "__main__":
293
+ main()
vendor/fish-speech/.gitignore ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =============================================================================
2
+ # Fish Speech - .gitignore
3
+ # =============================================================================
4
+
5
+ # Operating System Files
6
+ # -----------------------
7
+ .DS_Store
8
+ .DS_Store?
9
+ ._*
10
+ .Spotlight-V100
11
+ .Trashes
12
+ ehthumbs.db
13
+ Thumbs.db
14
+
15
+ # IDEs and Editors
16
+ # ----------------
17
+ .vscode/
18
+ .idea/
19
+ *.swp
20
+ *.swo
21
+ *~
22
+
23
+ # Python
24
+ # ------
25
+ __pycache__/
26
+ *.py[cod]
27
+ *$py.class
28
+ *.so
29
+ .Python
30
+ build/
31
+ develop-eggs/
32
+ dist/
33
+ downloads/
34
+ eggs/
35
+ .eggs/
36
+ lib/
37
+ lib64/
38
+ parts/
39
+ sdist/
40
+ var/
41
+ wheels/
42
+ *.egg-info/
43
+ .installed.cfg
44
+ *.egg
45
+ MANIFEST
46
+
47
+ # Virtual Environments
48
+ # --------------------
49
+ .env
50
+ .venv
51
+ env/
52
+ venv/
53
+ ENV/
54
+ env.bak/
55
+ venv.bak/
56
+ /fishenv/
57
+
58
+ # Project Dependencies
59
+ # --------------------
60
+ .pdm-python
61
+ /fish_speech.egg-info
62
+
63
+ # Data and Model Files
64
+ # --------------------
65
+ data/
66
+ results/
67
+ checkpoints/
68
+ references/
69
+ demo-audios/
70
+ example/
71
+ filelists/
72
+ *.filelist
73
+
74
+ # Audio Files
75
+ # -----------
76
+ *.wav
77
+ *.mp3
78
+ *.flac
79
+ *.ogg
80
+ *.m4a
81
+
82
+ # Data Files
83
+ # ----------
84
+ *.npy
85
+ *.npz
86
+ *.pkl
87
+ *.pickle
88
+ *.lab
89
+ /fish_speech/text/cmudict_cache.pickle
90
+
91
+ # Cache and Temporary Files
92
+ # --------------------------
93
+ /.cache/
94
+ /.gradio/
95
+ /.locale/
96
+ .pgx.*
97
+ *log
98
+ *.log
99
+ site/
100
+
101
+ # External Tools
102
+ # --------------
103
+ ffmpeg.exe
104
+ ffprobe.exe
105
+ /faster_whisper/
106
+
107
+ # Server Related
108
+ # --------------
109
+ /data_server/target/
110
+
111
+ # Test Files
112
+ # ----------
113
+ /*.test.sh
114
+ asr-label*
vendor/fish-speech/.project-root ADDED
File without changes
vendor/fish-speech/.readthedocs.yaml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Read the Docs configuration file for MkDocs projects
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ # Required
5
+ version: 2
6
+
7
+ # Set the version of Python and other tools you might need
8
+ build:
9
+ os: ubuntu-22.04
10
+ tools:
11
+ python: "3.12"
12
+
13
+ mkdocs:
14
+ configuration: mkdocs.yml
15
+
16
+ # Optionally declare the Python requirements required to build your docs
17
+ python:
18
+ install:
19
+ - requirements: docs/requirements.txt
vendor/fish-speech/API_FLAGS.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ # --infer
2
+ --api
3
+ --listen 0.0.0.0:8080 \
4
+ --llama-checkpoint-path "checkpoints/openaudio-s1-mini" \
5
+ --decoder-checkpoint-path "checkpoints/openaudio-s1-mini/codec.pth" \
6
+ --decoder-config-name modded_dac_vq
vendor/fish-speech/README.md ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+ <h1>Fish Speech</h1>
3
+
4
+ **English** | [简体中文](docs/README.zh.md) | [Portuguese](docs/README.pt-BR.md) | [日本語](docs/README.ja.md) | [한국어](docs/README.ko.md) | [العربية](docs/README.ar.md) | [Español](docs/README.es.md) <br>
5
+
6
+ <a href="https://www.producthunt.com/products/fish-speech?embed=true&utm_source=badge-top-post-badge&utm_medium=badge&utm_source=badge-fish&#0045;audio&#0045;s1" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=1023740&theme=light&period=daily&t=1761164814710" alt="Fish&#0032;Audio&#0032;S1 - Expressive&#0032;Voice&#0032;Cloning&#0032;and&#0032;Text&#0045;to&#0045;Speech | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
7
+ <a href="https://trendshift.io/repositories/7014" target="_blank">
8
+ <img src="https://trendshift.io/api/badge/repositories/7014" alt="fishaudio%2Ffish-speech | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
9
+ </a>
10
+ <br>
11
+ </div>
12
+ <br>
13
+
14
+ <div align="center">
15
+ <img src="https://count.getloli.com/get/@fish-speech?theme=asoul" /><br>
16
+ </div>
17
+
18
+ <br>
19
+
20
+ <div align="center">
21
+ <a target="_blank" href="https://discord.gg/Es5qTB9BcN">
22
+ <img alt="Discord" src="https://img.shields.io/discord/1214047546020728892?color=%23738ADB&label=Discord&logo=discord&logoColor=white&style=flat-square"/>
23
+ </a>
24
+ <a target="_blank" href="https://hub.docker.com/r/fishaudio/fish-speech">
25
+ <img alt="Docker" src="https://img.shields.io/docker/pulls/fishaudio/fish-speech?style=flat-square&logo=docker"/>
26
+ </a>
27
+ <a target="_blank" href="https://pd.qq.com/s/bwxia254o">
28
+ <img alt="QQ Channel" src="https://img.shields.io/badge/QQ-blue?logo=tencentqq">
29
+ </a>
30
+ </div>
31
+
32
+ <div align="center">
33
+ <a target="_blank" href="https://huggingface.co/fishaudio/s2-pro">
34
+ <img alt="HuggingFace Model" src="https://img.shields.io/badge/🤗%20-models-orange"/>
35
+ </a>
36
+ <a target="_blank" href="https://fish.audio/blog/fish-audio-open-sources-s2/">
37
+ <img alt="Fish Audio Blog" src="https://img.shields.io/badge/Blog-Fish_Audio_S2-1f7a8c?style=flat-square&logo=readme&logoColor=white"/>
38
+ </a>
39
+ <a target="_blank" href="https://arxiv.org/abs/2603.08823">
40
+ <img alt="Paper | Technical Report" src="https://img.shields.io/badge/Paper-Technical_Report-b31b1b?style=flat-square"/>
41
+ </a>
42
+ </div>
43
+
44
+ > [!IMPORTANT]
45
+ > **License Notice**
46
+ > This codebase and its associated model weights are released under **[FISH AUDIO RESEARCH LICENSE](LICENSE)**. Please refer to [LICENSE](LICENSE) for more details. We will take action against any violation of the license.
47
+
48
+ > [!WARNING]
49
+ > **Legal Disclaimer**
50
+ > We do not hold any responsibility for any illegal usage of the codebase. Please refer to your local laws about DMCA and other related laws.
51
+
52
+ ## Quick Start
53
+
54
+ ### For Human
55
+
56
+ Here are the official documents for Fish Audio S2, follow the instructions to get started easily.
57
+
58
+ - [Installation](https://speech.fish.audio/install/)
59
+ - [Command Line Inference](https://speech.fish.audio/inference/#command-line-inference)
60
+ - [WebUI Inference](https://speech.fish.audio/inference/#webui-inference)
61
+ - [Server Inference](https://speech.fish.audio/server/)
62
+ - [Docker Setup](https://speech.fish.audio/install/#docker-setup)
63
+
64
+ > [!IMPORTANT]
65
+ > **For SGLang server, please read [SGLang-Omni README](https://github.com/sgl-project/sglang-omni/blob/main/sglang_omni/models/fishaudio_s2_pro/README.md).**
66
+ >
67
+ > **For vLLM Omni server, please read [vLLM-Omni Fish Speech S2 Pro Recipe](https://github.com/vllm-project/vllm-omni/blob/main/recipes/fishaudio/Fish-Speech-S2-Pro.md) and the [User Guide](https://github.com/vllm-project/vllm-omni/blob/main/docs/user_guide/examples/online_serving/text_to_speech.md#fish-speech-s2-pro).**
68
+
69
+ ### For LLM Agent
70
+
71
+ ```
72
+ Install and configure Fish-Audio S2 by following the instructions here: https://speech.fish.audio/install/
73
+ ```
74
+
75
+ ## Fish Audio S2 Pro
76
+ **State-of-the-art multilingual text-to-speech (TTS) system, redefining the boundaries of voice generation.**
77
+
78
+ Fish Audio S2 Pro is the most advanced multimodal model developed by [Fish Audio](https://fish.audio/). Trained on over **10 million hours** of audio data covering more than **80 languages**, S2 Pro combines a **Dual-Autoregressive (Dual-AR)** architecture with reinforcement learning (RL) alignment to generate speech that is exceptionally natural, realistic, and emotionally rich, leading the competition among both open-source and closed-source systems.
79
+
80
+ The core strength of S2 Pro lies in its support for **sub-word level** fine-grained control of prosody and emotion using natural language tags (e.g., `[whisper]`, `[excited]`, `[angry]`), while natively supporting multi-speaker and multi-turn conversation generation.
81
+
82
+ Visit the [Fish Audio website](https://fish.audio/) for a live playground, or read our [technical report](https://arxiv.org/abs/2603.08823) and [blog post](https://fish.audio/blog/fish-audio-open-sources-s2/) for more details.
83
+
84
+ ### Model Variants
85
+
86
+ | Model | Size | Availability | Description |
87
+ |------|------|-------------|-------------|
88
+ | S2-Pro | 4B parameters | [HuggingFace](https://huggingface.co/fishaudio/s2-pro) | Full-featured flagship model with maximum quality and stability |
89
+
90
+ More details of the model can be found in the [technical report](https://arxiv.org/abs/2411.01156).
91
+
92
+ ## Benchmark Results
93
+
94
+ | Benchmark | Fish Audio S2 |
95
+ |------|------|
96
+ | Seed-TTS Eval — WER (Chinese) | **0.54%** (best overall) |
97
+ | Seed-TTS Eval — WER (English) | **0.99%** (best overall) |
98
+ | Audio Turing Test (with instruction) | **0.515** posterior mean |
99
+ | EmergentTTS-Eval — Win Rate | **81.88%** (highest overall) |
100
+ | Fish Instruction Benchmark — TAR | **93.3%** |
101
+ | Fish Instruction Benchmark — Quality | **4.51 / 5.0** |
102
+ | Multilingual (MiniMax Testset) — Best WER | **11 of 24** languages |
103
+ | Multilingual (MiniMax Testset) — Best SIM | **17 of 24** languages |
104
+
105
+ On Seed-TTS Eval, S2 achieves the lowest WER among all evaluated models including closed-source systems: Qwen3-TTS (0.77/1.24), MiniMax Speech-02 (0.99/1.90), Seed-TTS (1.12/2.25). On the Audio Turing Test, 0.515 surpasses Seed-TTS (0.417) by 24% and MiniMax-Speech (0.387) by 33%. On EmergentTTS-Eval, S2 achieves particularly strong results in paralinguistics (91.61% win rate), questions (84.41%), and syntactic complexity (83.39%).
106
+
107
+ ## Highlights
108
+
109
+ <img src="./docs/assets/totalability.png" width=200%>
110
+
111
+ ### Fine-Grained Inline Control via Natural Language
112
+
113
+ S2 Pro brings unprecedented "soul" to speech. Using simple `[tag]` syntax, you can precisely embed emotional instructions at any position in the text.
114
+ - **15,000+ Unique Tags Supported**: Not limited to fixed presets; S2 supports **free-form text descriptions**. Try `[whisper in small voice]`, `[professional broadcast tone]`, or `[pitch up]`.
115
+ - **Rich Emotion Library**:
116
+ `[pause]` `[emphasis]` `[laughing]` `[inhale]` `[chuckle]` `[tsk]` `[singing]` `[excited]` `[laughing tone]` `[interrupting]` `[chuckling]` `[excited tone]` `[volume up]` `[echo]` `[angry]` `[low volume]` `[sigh]` `[low voice]` `[whisper]` `[screaming]` `[shouting]` `[loud]` `[surprised]` `[short pause]` `[exhale]` `[delight]` `[panting]` `[audience laughter]` `[with strong accent]` `[volume down]` `[clearing throat]` `[sad]` `[moaning]` `[shocked]`
117
+
118
+ ### Innovative Dual-Autoregressive (Dual-AR) Architecture
119
+
120
+ S2 Pro adopts a master-slave Dual-AR architecture consisting of a decoder-only transformer and an RVQ audio codec (10 codebooks, ~21 Hz):
121
+
122
+ - **Slow AR (4B parameters)**: Operates along the time axis, predicting the primary semantic codebook.
123
+ - **Fast AR (400M parameters)**: Generates the remaining 9 residual codebooks at each time step, reconstructing exquisite acoustic details.
124
+
125
+ This asymmetric design achieves peak audio fidelity while significantly boosting inference speed.
126
+
127
+ ### Reinforcement Learning (RL) Alignment
128
+
129
+ S2 Pro utilizes **Group Relative Policy Optimization (GRPO)** for post-training alignment. We use the same model suite for data cleaning and annotation directly as Reward Models, perfectly resolving the distribution mismatch between pre-training data and post-training objectives.
130
+ - **Multi-Dimensional Reward Signals**: Comprehensively evaluates semantic accuracy, instruction adherence, acoustic preference scoring, and timbre similarity to ensure every second of generated speech feels intuitive to humans.
131
+
132
+ ### Extreme Streaming Performance (Powered by SGLang)
133
+
134
+ As the Dual-AR architecture is structurally isomorphic to standard LLMs, S2 Pro natively supports all SGLang inference acceleration features, including Continuous Batching, Paged KV Cache, CUDA Graph, and RadixAttention-based Prefix Caching.
135
+
136
+ **Performance on a single NVIDIA H200 GPU:**
137
+ - **Real-Time Factor (RTF)**: 0.195
138
+ - **Time-to-First-Audio (TTFA)**: ~100 ms
139
+ - **Extreme Throughput**: 3,000+ acoustic tokens/s while maintaining RTF < 0.5
140
+
141
+ ### Robust Multilingual Support
142
+
143
+ S2 Pro supports over 80 languages without requiring phonemes or language-specific preprocessing:
144
+
145
+ - **Tier 1**: Japanese (ja), English (en), Chinese (zh)
146
+ - **Tier 2**: Korean (ko), Spanish (es), Portuguese (pt), Arabic (ar), Russian (ru), French (fr), German (de)
147
+ - **Global Coverage**: sv, it, tr, no, nl, cy, eu, ca, da, gl, ta, hu, fi, pl, et, hi, la, ur, th, vi, jw, bn, yo, xsl, cs, sw, nn, he, ms, uk, id, kk, bg, lv, my, tl, sk, ne, fa, af, el, bo, hr, ro, sn, mi, yi, am, be, km, is, az, sd, br, sq, ps, mn, ht, ml, sr, sa, te, ka, bs, pa, lt, kn, si, hy, mr, as, gu, fo, etc.
148
+
149
+ ### Native Multi-Speaker Generation
150
+
151
+ <img src="./docs/assets/chattemplate.png" width=200%>
152
+
153
+ Fish Audio S2 allows users to upload reference audio containing multiple speakers, and the model processes each speaker's features via the `<|speaker:i|>` token. You can then control the model's performance via speaker ID tokens, enabling a single generation to include multiple speakers. There is no longer a need to upload separate reference audio for each individual speaker.
154
+
155
+ ### Multi-Turn Generation
156
+
157
+ Thanks to the expansion of the model context, our model can now leverage previous information to improve the expressiveness of subsequent generated content, thereby increasing the naturalness of the dialogue.
158
+
159
+ ### Rapid Voice Cloning
160
+
161
+ Fish Audio S2 supports accurate voice cloning using short reference samples (typically 10-30 seconds). The model captures timbre, speaking style, and emotional tendencies, producing realistic and consistent cloned voices without additional fine-tuning.
162
+ For SGLang Server usage, please refer to the [SGLang-Omni README](https://github.com/sgl-project/sglang-omni/blob/main/sglang_omni/models/fishaudio_s2_pro/README.md).
163
+
164
+ ---
165
+
166
+ ## Credits
167
+
168
+ - [VITS2 (daniilrobnikov)](https://github.com/daniilrobnikov/vits2)
169
+ - [Bert-VITS2](https://github.com/fishaudio/Bert-VITS2)
170
+ - [GPT VITS](https://github.com/innnky/gpt-vits)
171
+ - [MQTTS](https://github.com/b04901014/MQTTS)
172
+ - [GPT Fast](https://github.com/pytorch-labs/gpt-fast)
173
+ - [GPT-SoVITS](https://github.com/RVC-Boss/GPT-SoVITS)
174
+ - [Qwen3](https://github.com/QwenLM/Qwen3)
175
+
176
+ ## Tech Report
177
+ ```bibtex
178
+ @misc{fish-speech-v1.4,
179
+ title={Fish-Speech: Leveraging Large Language Models for Advanced Multilingual Text-to-Speech Synthesis},
180
+ author={Shijia Liao and Yuxuan Wang and Tianyu Li and Yifan Cheng and Ruoyi Zhang and Rongzhi Zhou and Yijin Xing},
181
+ year={2024},
182
+ eprint={2411.01156},
183
+ archivePrefix={arXiv},
184
+ primaryClass={cs.SD},
185
+ url={https://arxiv.org/abs/2411.01156},
186
+ }
187
+
188
+ @misc{liao2026fishaudios2technical,
189
+ title={Fish Audio S2 Technical Report},
190
+ author={Shijia Liao and Yuxuan Wang and Songting Liu and Yifan Cheng and Ruoyi Zhang and Tianyu Li and Shidong Li and Yisheng Zheng and Xingwei Liu and Qingzheng Wang and Zhizhuo Zhou and Jiahua Liu and Xin Chen and Dawei Han},
191
+ year={2026},
192
+ eprint={2603.08823},
193
+ archivePrefix={arXiv},
194
+ primaryClass={cs.SD},
195
+ url={https://arxiv.org/abs/2603.08823},
196
+ }
197
+ ```
vendor/fish-speech/compose.base.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ app-base:
3
+ build:
4
+ context: .
5
+ dockerfile: docker/Dockerfile
6
+ args:
7
+ BACKEND: ${BACKEND:-cuda} # or cpu
8
+ CUDA_VER: ${CUDA_VER:-12.9.0}
9
+ UV_EXTRA: ${UV_EXTRA:-cu129}
10
+ UV_VERSION: ${UV_VERSION:-0.8.15}
11
+ volumes:
12
+ - ./checkpoints:/app/checkpoints
13
+ - ./references:/app/references
14
+ environment:
15
+ COMPILE: ${COMPILE:-0}
16
+ # GPU (remove this block if CPU-only):
17
+ deploy:
18
+ resources:
19
+ reservations:
20
+ devices:
21
+ - driver: nvidia
22
+ count: all
23
+ capabilities: [gpu]
24
+ tty: true
25
+ stdin_open: true
vendor/fish-speech/compose.rocm.yml ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: fish-speech-rocm
2
+
3
+ # AMD ROCm compose for Fish Speech (RDNA3 / RDNA4).
4
+ # Mount your checkpoints into ./checkpoints before running.
5
+ #
6
+ # docker compose -f compose.rocm.yml --profile webui up --build
7
+ # docker compose -f compose.rocm.yml --profile server up --build
8
+
9
+ services:
10
+ webui:
11
+ build:
12
+ context: .
13
+ dockerfile: docker/Dockerfile.rocm
14
+ target: webui
15
+ image: fish-speech-webui:rocm
16
+ profiles: ["webui"]
17
+ ports:
18
+ - "${GRADIO_PORT:-7860}:7860"
19
+ volumes:
20
+ - ./checkpoints:/app/checkpoints
21
+ - ./references:/app/references
22
+ environment:
23
+ - ROCBLAS_USE_HIPBLASLT=0
24
+ - COMPILE=${COMPILE:-1}
25
+ devices:
26
+ - /dev/kfd
27
+ - /dev/dri
28
+ group_add:
29
+ - video
30
+ - render
31
+ shm_size: "16g"
32
+ tty: true
33
+ stdin_open: true
34
+
35
+ server:
36
+ build:
37
+ context: .
38
+ dockerfile: docker/Dockerfile.rocm
39
+ target: server
40
+ image: fish-speech-server:rocm
41
+ profiles: ["server"]
42
+ ports:
43
+ - "${API_PORT:-8080}:8080"
44
+ volumes:
45
+ - ./checkpoints:/app/checkpoints
46
+ - ./references:/app/references
47
+ environment:
48
+ - ROCBLAS_USE_HIPBLASLT=0
49
+ - COMPILE=${COMPILE:-1}
50
+ devices:
51
+ - /dev/kfd
52
+ - /dev/dri
53
+ group_add:
54
+ - video
55
+ - render
56
+ shm_size: "16g"
57
+ tty: true
58
+ stdin_open: true
vendor/fish-speech/compose.yml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: fish-speech
2
+
3
+ services:
4
+ webui:
5
+ extends:
6
+ file: compose.base.yml
7
+ service: app-base
8
+ build:
9
+ target: webui
10
+ environment:
11
+ COMPILE: ${COMPILE:-0}
12
+ profiles: ["webui"]
13
+ ports:
14
+ - "${GRADIO_PORT:-7860}:7860"
15
+
16
+ server:
17
+ extends:
18
+ file: compose.base.yml
19
+ service: app-base
20
+ build:
21
+ target: server
22
+ environment:
23
+ COMPILE: ${COMPILE:-0}
24
+ profiles: ["server"]
25
+ ports:
26
+ - "${API_PORT:-8080}:8080"
vendor/fish-speech/dockerfile.dev ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ARG VERSION=dev
2
+ ARG BASE_IMAGE=ghcr.io/fishaudio/fish-speech:${VERSION}
3
+
4
+ FROM ${BASE_IMAGE}
5
+
6
+ ARG TOOLS=" \
7
+ git \
8
+ curl \
9
+ build-essential \
10
+ ffmpeg \
11
+ libsm6 \
12
+ libxext6 \
13
+ libjpeg-dev \
14
+ zlib1g-dev \
15
+ aria2 \
16
+ zsh \
17
+ openssh-server \
18
+ sudo \
19
+ protobuf-compiler \
20
+ libasound-dev \
21
+ portaudio19-dev \
22
+ libportaudio2 \
23
+ libportaudiocpp0 \
24
+ cmake"
25
+
26
+ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
27
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
28
+ set -ex \
29
+ && apt-get update \
30
+ && apt-get -y install --no-install-recommends ${TOOLS}
31
+
32
+ # Install oh-my-zsh so your terminal looks nice
33
+ RUN sh -c "$(curl https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" "" --unattended
34
+
35
+ # Set zsh as default shell
36
+ RUN chsh -s /usr/bin/zsh
37
+ ENV SHELL=/usr/bin/zsh
vendor/fish-speech/entrypoint.sh ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ CUDA_ENABLED=${CUDA_ENABLED:-true}
4
+ DEVICE=""
5
+
6
+ if [ "${CUDA_ENABLED}" != "true" ]; then
7
+ DEVICE="--device cpu"
8
+ fi
9
+
10
+ exec python tools/run_webui.py ${DEVICE}
vendor/fish-speech/inference.ipynb ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Fish Speech"
8
+ ]
9
+ },
10
+ {
11
+ "cell_type": "markdown",
12
+ "metadata": {},
13
+ "source": [
14
+ "### For Windows User / win用户"
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "code",
19
+ "execution_count": null,
20
+ "metadata": {
21
+ "vscode": {
22
+ "languageId": "bat"
23
+ }
24
+ },
25
+ "outputs": [],
26
+ "source": [
27
+ "!chcp 65001"
28
+ ]
29
+ },
30
+ {
31
+ "cell_type": "markdown",
32
+ "metadata": {},
33
+ "source": [
34
+ "### For Linux User / Linux 用户"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": null,
40
+ "metadata": {},
41
+ "outputs": [],
42
+ "source": [
43
+ "import locale\n",
44
+ "locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')"
45
+ ]
46
+ },
47
+ {
48
+ "cell_type": "markdown",
49
+ "metadata": {},
50
+ "source": [
51
+ "### Prepare Model"
52
+ ]
53
+ },
54
+ {
55
+ "cell_type": "code",
56
+ "execution_count": null,
57
+ "metadata": {},
58
+ "outputs": [],
59
+ "source": [
60
+ "# For Chinese users, you probably want to use mirror to accelerate downloading\n",
61
+ "# !set HF_ENDPOINT=https://hf-mirror.com\n",
62
+ "# !export HF_ENDPOINT=https://hf-mirror.com \n",
63
+ "\n",
64
+ "!hf download fishaudio/openaudio-s1-mini --local-dir checkpoints/openaudio-s1-mini/"
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "markdown",
69
+ "metadata": {},
70
+ "source": [
71
+ "## WebUI Inference\n",
72
+ "\n",
73
+ "> You can use --compile to fuse CUDA kernels for faster inference (10x)."
74
+ ]
75
+ },
76
+ {
77
+ "cell_type": "code",
78
+ "execution_count": null,
79
+ "metadata": {
80
+ "vscode": {
81
+ "languageId": "shellscript"
82
+ }
83
+ },
84
+ "outputs": [],
85
+ "source": [
86
+ "!python tools/run_webui.py \\\n",
87
+ " --llama-checkpoint-path checkpoints/openaudio-s1-mini \\\n",
88
+ " --decoder-checkpoint-path checkpoints/openaudio-s1-mini/codec.pth \\\n",
89
+ " # --compile"
90
+ ]
91
+ },
92
+ {
93
+ "cell_type": "markdown",
94
+ "metadata": {},
95
+ "source": [
96
+ "## Break-down CLI Inference"
97
+ ]
98
+ },
99
+ {
100
+ "cell_type": "markdown",
101
+ "metadata": {},
102
+ "source": [
103
+ "### 1. Encode reference audio: / 从语音生成 prompt: \n",
104
+ "\n",
105
+ "You should get a `fake.npy` file.\n",
106
+ "\n",
107
+ "你应该能得到一个 `fake.npy` 文件."
108
+ ]
109
+ },
110
+ {
111
+ "cell_type": "code",
112
+ "execution_count": null,
113
+ "metadata": {
114
+ "vscode": {
115
+ "languageId": "shellscript"
116
+ }
117
+ },
118
+ "outputs": [],
119
+ "source": [
120
+ "## Enter the path to the audio file here\n",
121
+ "src_audio = r\"D:\\PythonProject\\vo_hutao_draw_appear.wav\"\n",
122
+ "\n",
123
+ "!python fish_speech/models/dac/inference.py \\\n",
124
+ " -i {src_audio} \\\n",
125
+ " --checkpoint-path \"checkpoints/openaudio-s1-mini/codec.pth\"\n",
126
+ "\n",
127
+ "from IPython.display import Audio, display\n",
128
+ "audio = Audio(filename=\"fake.wav\")\n",
129
+ "display(audio)"
130
+ ]
131
+ },
132
+ {
133
+ "cell_type": "markdown",
134
+ "metadata": {},
135
+ "source": [
136
+ "### 2. Generate semantic tokens from text: / 从文本生成语义 token:\n",
137
+ "\n",
138
+ "> This command will create a codes_N file in the working directory, where N is an integer starting from 0.\n",
139
+ "\n",
140
+ "> You may want to use `--compile` to fuse CUDA kernels for faster inference (~30 tokens/second -> ~300 tokens/second).\n",
141
+ "\n",
142
+ "> 该命令会在工作目录下创建 codes_N 文件, 其中 N 是从 0 开始的整数.\n",
143
+ "\n",
144
+ "> 您可以使用 `--compile` 来融合 cuda 内核以实现更快的推理 (~30 tokens/秒 -> ~300 tokens/秒)"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "code",
149
+ "execution_count": null,
150
+ "metadata": {
151
+ "vscode": {
152
+ "languageId": "shellscript"
153
+ }
154
+ },
155
+ "outputs": [],
156
+ "source": [
157
+ "!python fish_speech/models/text2semantic/inference.py \\\n",
158
+ " --text \"hello world\" \\\n",
159
+ " --prompt-text \"The text corresponding to reference audio\" \\\n",
160
+ " --prompt-tokens \"fake.npy\" \\\n",
161
+ " --checkpoint-path \"checkpoints/openaudio-s1-mini\" \\\n",
162
+ " --num-samples 2\n",
163
+ " # --compile"
164
+ ]
165
+ },
166
+ {
167
+ "cell_type": "markdown",
168
+ "metadata": {},
169
+ "source": [
170
+ "### 3. Generate speech from semantic tokens: / 从语义 token 生成人声:"
171
+ ]
172
+ },
173
+ {
174
+ "cell_type": "code",
175
+ "execution_count": null,
176
+ "metadata": {
177
+ "vscode": {
178
+ "languageId": "shellscript"
179
+ }
180
+ },
181
+ "outputs": [],
182
+ "source": [
183
+ "!python fish_speech/models/dac/inference.py \\\n",
184
+ " -i \"codes_0.npy\" \\\n",
185
+ " --checkpoint-path \"checkpoints/openaudio-s1-mini/codec.pth\"\n",
186
+ "\n",
187
+ "from IPython.display import Audio, display\n",
188
+ "audio = Audio(filename=\"fake.wav\")\n",
189
+ "display(audio)"
190
+ ]
191
+ }
192
+ ],
193
+ "metadata": {
194
+ "kernelspec": {
195
+ "display_name": "Python 3",
196
+ "language": "python",
197
+ "name": "python3"
198
+ },
199
+ "language_info": {
200
+ "codemirror_mode": {
201
+ "name": "ipython",
202
+ "version": 3
203
+ },
204
+ "file_extension": ".py",
205
+ "mimetype": "text/x-python",
206
+ "name": "python",
207
+ "nbconvert_exporter": "python",
208
+ "pygments_lexer": "ipython3",
209
+ "version": "3.10.14"
210
+ }
211
+ },
212
+ "nbformat": 4,
213
+ "nbformat_minor": 2
214
+ }
vendor/fish-speech/mkdocs.yml ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ site_name: Fish Audio
2
+ site_description: Targeting SOTA TTS solutions.
3
+ site_url: https://speech.fish.audio
4
+
5
+ # Repository
6
+ repo_name: fishaudio/fish-speech
7
+ repo_url: https://github.com/fishaudio/fish-speech
8
+ edit_uri: blob/main/docs
9
+
10
+ # Copyright
11
+ copyright: Copyright &copy; 2023-2025 by Fish Audio
12
+
13
+ theme:
14
+ name: material
15
+ favicon: assets/logo.svg
16
+ language: en
17
+ features:
18
+ - content.action.edit
19
+ - content.action.view
20
+ - navigation.tracking
21
+ - navigation.footer
22
+ # - navigation.tabs
23
+ - search
24
+ - search.suggest
25
+ - search.highlight
26
+ - search.share
27
+ - content.code.copy
28
+ logo: assets/logo.svg
29
+
30
+ palette:
31
+ # Palette toggle for automatic mode
32
+ - media: "(prefers-color-scheme)"
33
+ toggle:
34
+ icon: material/brightness-auto
35
+ name: Switch to light mode
36
+
37
+ # Palette toggle for light mode
38
+ - media: "(prefers-color-scheme: light)"
39
+ scheme: default
40
+ toggle:
41
+ icon: material/brightness-7
42
+ name: Switch to dark mode
43
+ primary: black
44
+ font:
45
+ code: Roboto Mono
46
+
47
+ # Palette toggle for dark mode
48
+ - media: "(prefers-color-scheme: dark)"
49
+ scheme: slate
50
+ toggle:
51
+ icon: material/brightness-4
52
+ name: Switch to light mode
53
+ primary: black
54
+ font:
55
+ code: Roboto Mono
56
+
57
+ nav:
58
+ - Introduction: en/index.md
59
+ - Installation: en/install.md
60
+ - Finetune: en/finetune.md
61
+ - Inference: en/inference.md
62
+ - Server: en/server.md
63
+ - Samples: en/samples.md
64
+
65
+ # Plugins
66
+ plugins:
67
+ - search:
68
+ separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
69
+ lang:
70
+ - en
71
+ - zh
72
+ - ja
73
+ - pt
74
+ - ko
75
+ - ar
76
+ - i18n:
77
+ docs_structure: folder
78
+ languages:
79
+ - locale: en
80
+ name: English
81
+ default: true
82
+ build: true
83
+ - locale: zh
84
+ name: 简体中文
85
+ build: true
86
+ nav:
87
+ - 介绍: zh/index.md
88
+ - 安装: zh/install.md
89
+ - 微调: zh/finetune.md
90
+ - 推理: zh/inference.md
91
+ - 示例: zh/samples.md
92
+ - locale: ja
93
+ name: 日本語
94
+ build: true
95
+ nav:
96
+ - はじめに: ja/index.md
97
+ - インストール: ja/install.md
98
+ - ファインチューニング: ja/finetune.md
99
+ - 推論: ja/inference.md
100
+ - サンプル: ja/samples.md
101
+ - locale: pt
102
+ name: Português (Brasil)
103
+ build: true
104
+ nav:
105
+ - Introdução: pt/index.md
106
+ - Instalação: pt/install.md
107
+ - Ajuste Fino: pt/finetune.md
108
+ - Inferência: pt/inference.md
109
+ - Amostras: pt/samples.md
110
+ - locale: ko
111
+ name: 한국어
112
+ build: true
113
+ nav:
114
+ - 소개: ko/index.md
115
+ - 설치: ko/install.md
116
+ - 파인튜닝: ko/finetune.md
117
+ - 추론: ko/inference.md
118
+ - 샘플: ko/samples.md
119
+ - locale: ar
120
+ name: العربية
121
+ build: true
122
+ nav:
123
+ - مقدمة: ar/index.md
124
+ - التثبيت: ar/install.md
125
+ - الضبط الدقيق: ar/finetune.md
126
+ - الاستنتاج: ar/inference.md
127
+ - العينات: ar/samples.md
128
+
129
+ markdown_extensions:
130
+ - pymdownx.highlight:
131
+ anchor_linenums: true
132
+ line_spans: __span
133
+ pygments_lang_class: true
134
+ - pymdownx.inlinehilite
135
+ - pymdownx.snippets
136
+ - pymdownx.superfences
137
+ - admonition
138
+ - pymdownx.details
139
+ - pymdownx.superfences
140
+ - attr_list
141
+ - md_in_html
142
+ - pymdownx.superfences
143
+
144
+ extra_css:
145
+ - stylesheets/extra.css
146
+
147
+ extra:
148
+ social:
149
+ - icon: fontawesome/brands/discord
150
+ link: https://discord.gg/Es5qTB9BcN
151
+ - icon: fontawesome/brands/docker
152
+ link: https://hub.docker.com/r/fishaudio/fish-speech
153
+ - icon: fontawesome/brands/qq
154
+ link: http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=jCKlUP7QgSm9kh95UlBoYv6s1I-Apl1M&authKey=xI5ttVAp3do68IpEYEalwXSYZFdfxZSkah%2BctF5FIMyN2NqAa003vFtLqJyAVRfF&noverify=0&group_code=593946093
155
+ homepage: https://speech.fish.audio
vendor/fish-speech/pyrightconfig.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "exclude": [
3
+ "data",
4
+ "filelists"
5
+ ]
6
+ }