Text Generation
GGUF
llama.cpp
qwen3.5
quantized
agentic
tool-use
coding
reasoning
imatrix
conversational
Instructions to use ngquocvinh/NeoHorse-1-4B-GGUF with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use ngquocvinh/NeoHorse-1-4B-GGUF with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M # Run inference directly in the terminal: llama cli -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M # Run inference directly in the terminal: llama cli -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Use Docker
docker model run hf.co/ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use ngquocvinh/NeoHorse-1-4B-GGUF with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ngquocvinh/NeoHorse-1-4B-GGUF" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ngquocvinh/NeoHorse-1-4B-GGUF", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
- Ollama
How to use ngquocvinh/NeoHorse-1-4B-GGUF with Ollama:
ollama run hf.co/ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
- Unsloth Desktop
- Pi
How to use ngquocvinh/NeoHorse-1-4B-GGUF with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use ngquocvinh/NeoHorse-1-4B-GGUF with Docker Model Runner:
docker model run hf.co/ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
- Lemonade
How to use ngquocvinh/NeoHorse-1-4B-GGUF with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Run and chat with the model
lemonade run user.NeoHorse-1-4B-GGUF-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use ngquocvinh/NeoHorse-1-4B-GGUF with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use ngquocvinh/NeoHorse-1-4B-GGUF with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "ngquocvinh/NeoHorse-1-4B-GGUF:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Publish final card checksums and reproducibility manifests
Browse files- LICENSE +209 -0
- README.md +78 -19
- SHA256SUMS.txt +9 -0
- reproducibility/calibration-manifest.md +39 -0
- reproducibility/chat_template.jinja +154 -0
- reproducibility/manifest.md +64 -0
- reproducibility/quality-summary.tsv +10 -0
- reproducibility/quantization-manifest.tsv +10 -0
- reproducibility/runtime-version.txt +9 -0
- reproducibility/source-manifest.md +17 -0
- reproducibility/summarize_fidelity.py +78 -0
LICENSE
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Original Qwen model:
|
| 191 |
+
Copyright 2026 Alibaba Cloud
|
| 192 |
+
|
| 193 |
+
Fine-tuning and repackaging modifications:
|
| 194 |
+
Copyright 2026 TokenRhythm
|
| 195 |
+
|
| 196 |
+
NeoHorse-1-4B is based on Qwen/Qwen3.5-4B and was modified
|
| 197 |
+
by TokenRhythm through fine-tuning and repackaging.
|
| 198 |
+
|
| 199 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 200 |
+
you may not use this file except in compliance with the License.
|
| 201 |
+
You may obtain a copy of the License at
|
| 202 |
+
|
| 203 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 204 |
+
|
| 205 |
+
Unless required by applicable law or agreed to in writing, software
|
| 206 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 207 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 208 |
+
See the License for the specific language governing permissions and
|
| 209 |
+
limitations under the License.
|
README.md
CHANGED
|
@@ -27,10 +27,9 @@ I build and test these releases myself. Your coffee helps keep me going.<br>
|
|
| 27 |
Thank you for supporting this work.
|
| 28 |
</div>
|
| 29 |
|
| 30 |
-
> **Status:**
|
| 31 |
-
>
|
| 32 |
-
>
|
| 33 |
-
> after direct-from-BF16 conversion and runtime validation pass.
|
| 34 |
|
| 35 |
## About NeoHorse-1-4B
|
| 36 |
|
|
@@ -40,40 +39,100 @@ See the [official upstream model card](https://huggingface.co/TokenRhythm/NeoHor
|
|
| 40 |
|
| 41 |
These releases change the storage format through GGUF quantization only. No training or fine-tuning was performed here.
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
## Fidelity measurements
|
| 44 |
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
## Quick start
|
| 50 |
|
| 51 |
-
|
| 52 |
|
| 53 |
```bash
|
| 54 |
./llama-cli \
|
| 55 |
-
-m
|
| 56 |
-
--chat-template-file chat_template.jinja \
|
| 57 |
--jinja \
|
| 58 |
--reasoning off \
|
| 59 |
-p 'Answer briefly in English: What is GGUF and why is it useful for running language models locally?' \
|
| 60 |
-n 128 -c 4096 -ngl 99
|
| 61 |
```
|
| 62 |
|
| 63 |
-
The
|
|
|
|
| 64 |
|
| 65 |
## Reproducibility and validation
|
| 66 |
|
| 67 |
-
The locked upstream revision is
|
| 68 |
-
The
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
## License and attribution
|
| 76 |
|
| 77 |
-
NeoHorse-1-4B is released upstream under the Apache License 2.0. The upstream
|
|
|
|
| 78 |
|
| 79 |
These are community GGUF quantizations, not an official TokenRhythm release or endorsement.
|
|
|
|
| 27 |
Thank you for supporting this work.
|
| 28 |
</div>
|
| 29 |
|
| 30 |
+
> **Status:** Complete release. The nine GGUF files below were quantized
|
| 31 |
+
> directly from the locked upstream BF16 snapshot, loaded/generated on GPU 0,
|
| 32 |
+
> and checked against held-out next-token fidelity measurements.
|
|
|
|
| 33 |
|
| 34 |
## About NeoHorse-1-4B
|
| 35 |
|
|
|
|
| 39 |
|
| 40 |
These releases change the storage format through GGUF quantization only. No training or fine-tuning was performed here.
|
| 41 |
|
| 42 |
+
## Quantized files
|
| 43 |
+
|
| 44 |
+
`Q5_K_M` is the balanced starting point from this evaluation. Use `Q6_K` or
|
| 45 |
+
`Q8_0` when fidelity is more important than size; `Q4_K_M` is the smaller
|
| 46 |
+
practical option. `Q3_K_M` and below are included for experimentation, but the
|
| 47 |
+
hold-out results show a substantial fidelity drop. `IQ1_M` and `Q1_0` are
|
| 48 |
+
compatibility-only options here and are not recommended for normal use.
|
| 49 |
+
|
| 50 |
+
| File | Size (bytes) | Evaluation note |
|
| 51 |
+
|---|---:|---|
|
| 52 |
+
| `NeoHorse-1-4B-Q8_0.gguf` | 4482403104 | closest conventional quant |
|
| 53 |
+
| `NeoHorse-1-4B-Q6_K.gguf` | 3464055872 | high-fidelity option |
|
| 54 |
+
| `NeoHorse-1-4B-Q5_K_M.gguf` | 3074987072 | balanced starting point |
|
| 55 |
+
| `NeoHorse-1-4B-Q4_K_M.gguf` | 2708804672 | smaller practical option |
|
| 56 |
+
| `NeoHorse-1-4B-Q3_K_M.gguf` | 2262064192 | experimental; larger drift |
|
| 57 |
+
| `NeoHorse-1-4B-Q2_K.gguf` | 1915470912 | experimental; large drift |
|
| 58 |
+
| `NeoHorse-1-4B-IQ2_XS.gguf` | 1630594112 | experimental; large drift |
|
| 59 |
+
| `NeoHorse-1-4B-IQ1_M.gguf` | 1426418752 | compatibility-only |
|
| 60 |
+
| `NeoHorse-1-4B-Q1_0.gguf` | 1038189632 | compatibility-only |
|
| 61 |
+
|
| 62 |
## Fidelity measurements
|
| 63 |
|
| 64 |
+
The table averages eight chunks from each of `wiki.test.raw` and
|
| 65 |
+
`wiki.valid.raw`, using a 4,096-token context and the same llama.cpp runtime
|
| 66 |
+
against the BF16 GGUF reference. The average BF16 PPL in this evaluation was
|
| 67 |
+
8.635307. Lower Mean KLD, ΔPPL, and RMS Δp, and higher Top-1 agreement, indicate
|
| 68 |
+
closer next-token behavior to BF16. These are fidelity measurements, not a
|
| 69 |
+
direct percentage of capabilities retained.
|
| 70 |
+
|
| 71 |
+
| File | Mean KLD | Top-1 vs BF16 | ΔPPL | RMS Δp |
|
| 72 |
+
|---|---:|---:|---:|---:|
|
| 73 |
+
| `NeoHorse-1-4B-Q8_0.gguf` | 0.006291 | 98.065% | +0.192% | 2.041% |
|
| 74 |
+
| `NeoHorse-1-4B-Q6_K.gguf` | 0.010910 | 96.751% | +0.831% | 2.881% |
|
| 75 |
+
| `NeoHorse-1-4B-Q5_K_M.gguf` | 0.032008 | 94.498% | +1.706% | 4.631% |
|
| 76 |
+
| `NeoHorse-1-4B-Q4_K_M.gguf` | 0.055031 | 91.909% | +1.339% | 5.920% |
|
| 77 |
+
| `NeoHorse-1-4B-Q3_K_M.gguf` | 0.160972 | 85.173% | +11.466% | 10.610% |
|
| 78 |
+
| `NeoHorse-1-4B-Q2_K.gguf` | 0.348854 | 76.007% | +12.720% | 16.212% |
|
| 79 |
+
| `NeoHorse-1-4B-IQ2_XS.gguf` | 0.517311 | 70.662% | +32.407% | 20.489% |
|
| 80 |
+
| `NeoHorse-1-4B-IQ1_M.gguf` | 1.303395 | 54.895% | +168.381% | 32.950% |
|
| 81 |
+
| `NeoHorse-1-4B-Q1_0.gguf` | 12.339880 | 0.406% | +18400566.679% | 60.432% |
|
| 82 |
+
|
| 83 |
+
The fixed hold-out corpus is disjoint from the calibration inputs. See the
|
| 84 |
+
[compact quality summary](reproducibility/quality-summary.tsv) and the
|
| 85 |
+
[reproducibility manifest](reproducibility/manifest.md) for the exact split,
|
| 86 |
+
hashes, and runtime profile.
|
| 87 |
+
|
| 88 |
+
## Behavior and runtime validation
|
| 89 |
+
|
| 90 |
+
BF16 baseline probes covered English, Vietnamese, Chinese, coding, plain JSON,
|
| 91 |
+
and the upstream-style tool-call text format. Those probes generated usable
|
| 92 |
+
responses for the tested prompts. The strict llama.cpp `--json-schema` probe
|
| 93 |
+
failed during runtime sampler initialization and is recorded as a runtime
|
| 94 |
+
compatibility limitation, not counted as a model capability result. The
|
| 95 |
+
tool-call probe tested serialization format only; it was not an end-to-end tool
|
| 96 |
+
executor test.
|
| 97 |
+
|
| 98 |
+
BF16 and every published quantization loaded and generated non-empty output on
|
| 99 |
+
one NVIDIA A10M using the same GPU-0 profile. Low-bit files can pass this
|
| 100 |
+
compatibility gate while still producing poor responses; the fidelity table is
|
| 101 |
+
why Q3 and lower are marked experimental.
|
| 102 |
|
| 103 |
## Quick start
|
| 104 |
|
| 105 |
+
For the balanced starting point:
|
| 106 |
|
| 107 |
```bash
|
| 108 |
./llama-cli \
|
| 109 |
+
-m NeoHorse-1-4B-Q5_K_M.gguf \
|
|
|
|
| 110 |
--jinja \
|
| 111 |
--reasoning off \
|
| 112 |
-p 'Answer briefly in English: What is GGUF and why is it useful for running language models locally?' \
|
| 113 |
-n 128 -c 4096 -ngl 99
|
| 114 |
```
|
| 115 |
|
| 116 |
+
The GGUF contains the converted chat template. Reduce `-ngl` or the context
|
| 117 |
+
size if the available VRAM is smaller.
|
| 118 |
|
| 119 |
## Reproducibility and validation
|
| 120 |
|
| 121 |
+
The locked upstream revision is
|
| 122 |
+
`56f0584bb40578a2c33b1b40a08ccd17243ad710`. The BF16 source GGUF SHA256 is
|
| 123 |
+
`10aae5451e1c0b6089b25f68cfe32cd32a4bdcb92e30008e083e6ba351f3cbd8`; the
|
| 124 |
+
NeoHorse-specific combined imatrix SHA256 is
|
| 125 |
+
`8c66b45b73826b0b00fdd973d308d8f81f7db0f8a3b97cf93bc7813d722d6515`.
|
| 126 |
+
|
| 127 |
+
The package includes [SHA256SUMS.txt](SHA256SUMS.txt), the
|
| 128 |
+
[quantization manifest](reproducibility/quantization-manifest.tsv), source and
|
| 129 |
+
calibration manifests, the runtime version, and the copied upstream chat
|
| 130 |
+
template. Detailed conversion, quantization, smoke, behavior, and fidelity
|
| 131 |
+
logs remain local under `reports/neohorse-1-4b/` and are not uploaded.
|
| 132 |
|
| 133 |
## License and attribution
|
| 134 |
|
| 135 |
+
NeoHorse-1-4B is released upstream under the Apache License 2.0. The upstream
|
| 136 |
+
license and attribution notices are included in `LICENSE`.
|
| 137 |
|
| 138 |
These are community GGUF quantizations, not an official TokenRhythm release or endorsement.
|
SHA256SUMS.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
9b756eefd6ef534bf23ee3d62eb1b7e404ab4a21d8681a35791a0e39b76f17d0 NeoHorse-1-4B-Q8_0.gguf
|
| 2 |
+
3af3f1981b8bc0a1fd205b011dc17cd02d5a479e89d35d77b8c20f5e6f0d70d5 NeoHorse-1-4B-Q6_K.gguf
|
| 3 |
+
71b5e86dc409e1a5b17db34040f7df8dcd11688f27f6134d1c8595069ffe57fe NeoHorse-1-4B-Q5_K_M.gguf
|
| 4 |
+
5669ad48af5d54a29ed78aed77d2f2e2b921a8aca68c5482696bc8713cf8248b NeoHorse-1-4B-Q4_K_M.gguf
|
| 5 |
+
ef8b4386a54ec1d25024aeae5e5a1c976748bf2bd525c8cdc68edbec68a936f9 NeoHorse-1-4B-Q3_K_M.gguf
|
| 6 |
+
834bef5dfdbbd2545b2fac9dd46a75c08beab8803a1636fd459cbe27729d8154 NeoHorse-1-4B-Q2_K.gguf
|
| 7 |
+
a77f44a832a5978e4ce921c183cb07a80faa380fe4a8c22b0ba3a57699a34982 NeoHorse-1-4B-IQ2_XS.gguf
|
| 8 |
+
eccb688df4b1c1387bee976db5972fe766d4a9007d3983132957587387efc0bb NeoHorse-1-4B-IQ1_M.gguf
|
| 9 |
+
9ab2feb77d3ac44677468d32142804df8346b41dc644ff95d0358d868a40aba0 NeoHorse-1-4B-Q1_0.gguf
|
reproducibility/calibration-manifest.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Calibration manifest
|
| 2 |
+
|
| 3 |
+
The importance matrix is model-specific and was collected from the BF16 GGUF.
|
| 4 |
+
WikiText validation and test files were held out.
|
| 5 |
+
|
| 6 |
+
| Input | SHA256 | Collection |
|
| 7 |
+
|---|---|---|
|
| 8 |
+
| `neohorse_en_vi_zh_code_agent.txt` | `235ed59cfc43beeaee7a0787273ff6586829b3ecf19189f4567fe57f64a03c3a` | context 512, requested 4 chunks, 3 collected |
|
| 9 |
+
| `wiki.train.raw` | `6707892fa3788b5ab9ed78ab5ff37d9fe825f6011a2ad4fcd6a6d467f0e7da57` | context 4096, 96 chunks |
|
| 10 |
+
| `wiki.valid.raw` | `4cd0f6876d07a413aa911261ff6d363c72d757d47f0fdd6015702014c89cb9c7` | hold-out only |
|
| 11 |
+
| `wiki.test.raw` | `173c87a53759e0201f33e0ccf978e510c2042d7f2cb78229d9a50d79b9e7dd08` | hold-out only |
|
| 12 |
+
|
| 13 |
+
Commands, with paths relative to the workspace root:
|
| 14 |
+
|
| 15 |
+
```bash
|
| 16 |
+
CUDA_VISIBLE_DEVICES=0 llama-imatrix \
|
| 17 |
+
-m source-official-bf16-neohorse-1-4b/NeoHorse-1-4B-BF16.gguf \
|
| 18 |
+
-f calibration/neohorse-1-4b/neohorse_en_vi_zh_code_agent.txt \
|
| 19 |
+
-o calibration/neohorse-1-4b/NeoHorse-1-4B-custom.imatrix.gguf \
|
| 20 |
+
-c 512 -b 512 -ub 512 --chunks 4 --no-ppl --parse-special \
|
| 21 |
+
-ngl all --device CUDA0 --split-mode none --main-gpu 0 \
|
| 22 |
+
--fit on --fit-target 1024 -t 64 -tb 64
|
| 23 |
+
|
| 24 |
+
CUDA_VISIBLE_DEVICES=0 llama-imatrix \
|
| 25 |
+
-m source-official-bf16-neohorse-1-4b/NeoHorse-1-4B-BF16.gguf \
|
| 26 |
+
-f calibration/wikitext-2-raw/wiki.train.raw \
|
| 27 |
+
-o calibration/neohorse-1-4b/NeoHorse-1-4B-wikitext-train.imatrix.gguf \
|
| 28 |
+
-c 4096 -b 512 -ub 512 --chunks 96 --no-ppl \
|
| 29 |
+
-ngl all --device CUDA0 --split-mode none --main-gpu 0 \
|
| 30 |
+
--fit on --fit-target 1024 -t 64 -tb 64
|
| 31 |
+
|
| 32 |
+
llama-imatrix -m source-official-bf16-neohorse-1-4b/NeoHorse-1-4B-BF16.gguf \
|
| 33 |
+
--device none -ngl 0 \
|
| 34 |
+
--in-file calibration/neohorse-1-4b/NeoHorse-1-4B-custom.imatrix.gguf,calibration/neohorse-1-4b/NeoHorse-1-4B-wikitext-train.imatrix.gguf \
|
| 35 |
+
-o calibration/neohorse-1-4b/NeoHorse-1-4B-combined.imatrix.gguf
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
The combined imatrix SHA256 is
|
| 39 |
+
`8c66b45b73826b0b00fdd973d308d8f81f7db0f8a3b97cf93bc7813d722d6515`.
|
reproducibility/chat_template.jinja
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- set image_count = namespace(value=0) %}
|
| 2 |
+
{%- set video_count = namespace(value=0) %}
|
| 3 |
+
{%- macro render_content(content, do_vision_count, is_system_content=false) %}
|
| 4 |
+
{%- if content is string %}
|
| 5 |
+
{{- content }}
|
| 6 |
+
{%- elif content is iterable and content is not mapping %}
|
| 7 |
+
{%- for item in content %}
|
| 8 |
+
{%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
|
| 9 |
+
{%- if is_system_content %}
|
| 10 |
+
{{- raise_exception('System message cannot contain images.') }}
|
| 11 |
+
{%- endif %}
|
| 12 |
+
{%- if do_vision_count %}
|
| 13 |
+
{%- set image_count.value = image_count.value + 1 %}
|
| 14 |
+
{%- endif %}
|
| 15 |
+
{%- if add_vision_id %}
|
| 16 |
+
{{- 'Picture ' ~ image_count.value ~ ': ' }}
|
| 17 |
+
{%- endif %}
|
| 18 |
+
{{- '<|vision_start|><|image_pad|><|vision_end|>' }}
|
| 19 |
+
{%- elif 'video' in item or item.type == 'video' %}
|
| 20 |
+
{%- if is_system_content %}
|
| 21 |
+
{{- raise_exception('System message cannot contain videos.') }}
|
| 22 |
+
{%- endif %}
|
| 23 |
+
{%- if do_vision_count %}
|
| 24 |
+
{%- set video_count.value = video_count.value + 1 %}
|
| 25 |
+
{%- endif %}
|
| 26 |
+
{%- if add_vision_id %}
|
| 27 |
+
{{- 'Video ' ~ video_count.value ~ ': ' }}
|
| 28 |
+
{%- endif %}
|
| 29 |
+
{{- '<|vision_start|><|video_pad|><|vision_end|>' }}
|
| 30 |
+
{%- elif 'text' in item %}
|
| 31 |
+
{{- item.text }}
|
| 32 |
+
{%- else %}
|
| 33 |
+
{{- raise_exception('Unexpected item type in content.') }}
|
| 34 |
+
{%- endif %}
|
| 35 |
+
{%- endfor %}
|
| 36 |
+
{%- elif content is none or content is undefined %}
|
| 37 |
+
{{- '' }}
|
| 38 |
+
{%- else %}
|
| 39 |
+
{{- raise_exception('Unexpected content type.') }}
|
| 40 |
+
{%- endif %}
|
| 41 |
+
{%- endmacro %}
|
| 42 |
+
{%- if not messages %}
|
| 43 |
+
{{- raise_exception('No messages provided.') }}
|
| 44 |
+
{%- endif %}
|
| 45 |
+
{%- if tools and tools is iterable and tools is not mapping %}
|
| 46 |
+
{{- '<|im_start|>system\n' }}
|
| 47 |
+
{{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
|
| 48 |
+
{%- for tool in tools %}
|
| 49 |
+
{{- "\n" }}
|
| 50 |
+
{{- tool | tojson }}
|
| 51 |
+
{%- endfor %}
|
| 52 |
+
{{- "\n</tools>" }}
|
| 53 |
+
{{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
|
| 54 |
+
{%- if messages[0].role == 'system' %}
|
| 55 |
+
{%- set content = render_content(messages[0].content, false, true)|trim %}
|
| 56 |
+
{%- if content %}
|
| 57 |
+
{{- '\n\n' + content }}
|
| 58 |
+
{%- endif %}
|
| 59 |
+
{%- endif %}
|
| 60 |
+
{{- '<|im_end|>\n' }}
|
| 61 |
+
{%- else %}
|
| 62 |
+
{%- if messages[0].role == 'system' %}
|
| 63 |
+
{%- set content = render_content(messages[0].content, false, true)|trim %}
|
| 64 |
+
{{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
|
| 65 |
+
{%- endif %}
|
| 66 |
+
{%- endif %}
|
| 67 |
+
{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
|
| 68 |
+
{%- for message in messages[::-1] %}
|
| 69 |
+
{%- set index = (messages|length - 1) - loop.index0 %}
|
| 70 |
+
{%- if ns.multi_step_tool and message.role == "user" %}
|
| 71 |
+
{%- set content = render_content(message.content, false)|trim %}
|
| 72 |
+
{%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
|
| 73 |
+
{%- set ns.multi_step_tool = false %}
|
| 74 |
+
{%- set ns.last_query_index = index %}
|
| 75 |
+
{%- endif %}
|
| 76 |
+
{%- endif %}
|
| 77 |
+
{%- endfor %}
|
| 78 |
+
{%- if ns.multi_step_tool %}
|
| 79 |
+
{{- raise_exception('No user query found in messages.') }}
|
| 80 |
+
{%- endif %}
|
| 81 |
+
{%- for message in messages %}
|
| 82 |
+
{%- set content = render_content(message.content, true)|trim %}
|
| 83 |
+
{%- if message.role == "system" %}
|
| 84 |
+
{%- if not loop.first %}
|
| 85 |
+
{{- raise_exception('System message must be at the beginning.') }}
|
| 86 |
+
{%- endif %}
|
| 87 |
+
{%- elif message.role == "user" %}
|
| 88 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 89 |
+
{%- elif message.role == "assistant" %}
|
| 90 |
+
{%- set reasoning_content = '' %}
|
| 91 |
+
{%- if message.reasoning_content is string %}
|
| 92 |
+
{%- set reasoning_content = message.reasoning_content %}
|
| 93 |
+
{%- else %}
|
| 94 |
+
{%- if '</think>' in content %}
|
| 95 |
+
{%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
|
| 96 |
+
{%- set content = content.split('</think>')[-1].lstrip('\n') %}
|
| 97 |
+
{%- endif %}
|
| 98 |
+
{%- endif %}
|
| 99 |
+
{%- set reasoning_content = reasoning_content|trim %}
|
| 100 |
+
{%- if loop.index0 > ns.last_query_index %}
|
| 101 |
+
{{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
|
| 102 |
+
{%- else %}
|
| 103 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 104 |
+
{%- endif %}
|
| 105 |
+
{%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
|
| 106 |
+
{%- for tool_call in message.tool_calls %}
|
| 107 |
+
{%- if tool_call.function is defined %}
|
| 108 |
+
{%- set tool_call = tool_call.function %}
|
| 109 |
+
{%- endif %}
|
| 110 |
+
{%- if loop.first %}
|
| 111 |
+
{%- if content|trim %}
|
| 112 |
+
{{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 113 |
+
{%- else %}
|
| 114 |
+
{{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 115 |
+
{%- endif %}
|
| 116 |
+
{%- else %}
|
| 117 |
+
{{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
|
| 118 |
+
{%- endif %}
|
| 119 |
+
{%- if tool_call.arguments is defined %}
|
| 120 |
+
{%- for args_name, args_value in tool_call.arguments|items %}
|
| 121 |
+
{{- '<parameter=' + args_name + '>\n' }}
|
| 122 |
+
{%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
|
| 123 |
+
{{- args_value }}
|
| 124 |
+
{{- '\n</parameter>\n' }}
|
| 125 |
+
{%- endfor %}
|
| 126 |
+
{%- endif %}
|
| 127 |
+
{{- '</function>\n</tool_call>' }}
|
| 128 |
+
{%- endfor %}
|
| 129 |
+
{%- endif %}
|
| 130 |
+
{{- '<|im_end|>\n' }}
|
| 131 |
+
{%- elif message.role == "tool" %}
|
| 132 |
+
{%- if loop.previtem and loop.previtem.role != "tool" %}
|
| 133 |
+
{{- '<|im_start|>user' }}
|
| 134 |
+
{%- endif %}
|
| 135 |
+
{{- '\n<tool_response>\n' }}
|
| 136 |
+
{{- content }}
|
| 137 |
+
{{- '\n</tool_response>' }}
|
| 138 |
+
{%- if not loop.last and loop.nextitem.role != "tool" %}
|
| 139 |
+
{{- '<|im_end|>\n' }}
|
| 140 |
+
{%- elif loop.last %}
|
| 141 |
+
{{- '<|im_end|>\n' }}
|
| 142 |
+
{%- endif %}
|
| 143 |
+
{%- else %}
|
| 144 |
+
{{- raise_exception('Unexpected message role.') }}
|
| 145 |
+
{%- endif %}
|
| 146 |
+
{%- endfor %}
|
| 147 |
+
{%- if add_generation_prompt %}
|
| 148 |
+
{{- '<|im_start|>assistant\n' }}
|
| 149 |
+
{%- if enable_thinking is defined and enable_thinking is false %}
|
| 150 |
+
{{- '<think>\n\n</think>\n\n' }}
|
| 151 |
+
{%- else %}
|
| 152 |
+
{{- '<think>\n' }}
|
| 153 |
+
{%- endif %}
|
| 154 |
+
{%- endif %}
|
reproducibility/manifest.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# NeoHorse-1-4B GGUF reproducibility manifest
|
| 2 |
+
|
| 3 |
+
## Source
|
| 4 |
+
|
| 5 |
+
- Upstream repository: `TokenRhythm/NeoHorse-1-4B`
|
| 6 |
+
- Locked revision: `56f0584bb40578a2c33b1b40a08ccd17243ad710`
|
| 7 |
+
- Source format: upstream BF16 safetensors
|
| 8 |
+
- Architecture: `qwen3_5_text` / `Qwen3_5ForCausalLM`
|
| 9 |
+
- Source BF16 GGUF: `NeoHorse-1-4B-BF16.gguf`
|
| 10 |
+
- Source BF16 GGUF SHA256:
|
| 11 |
+
`10aae5451e1c0b6089b25f68cfe32cd32a4bdcb92e30008e083e6ba351f3cbd8`
|
| 12 |
+
- Conversion used `--outtype bf16 --no-nextn`; the source index contains no
|
| 13 |
+
`mtp`/`nextn` tensors even though the upstream config advertises one MTP
|
| 14 |
+
layer.
|
| 15 |
+
- The converter preserved the upstream text-only model and embedded its chat
|
| 16 |
+
template. It did not modify source weights or the upstream config.
|
| 17 |
+
|
| 18 |
+
## Importance matrix
|
| 19 |
+
|
| 20 |
+
- Combined imatrix: `NeoHorse-1-4B-combined.imatrix.gguf`
|
| 21 |
+
- Combined imatrix SHA256:
|
| 22 |
+
`8c66b45b73826b0b00fdd973d308d8f81f7db0f8a3b97cf93bc7813d722d6515`
|
| 23 |
+
- Input datasets: the model-specific multilingual/code/agent calibration text
|
| 24 |
+
and `wiki.train.raw`; neither WikiText validation nor test text was used.
|
| 25 |
+
- The custom run used context 512 and four requested chunks (three available
|
| 26 |
+
chunks were collected). The WikiText run used context 4096 and 96 chunks.
|
| 27 |
+
The combined file reports 771 normalized chunks because the input matrices
|
| 28 |
+
use different context sizes.
|
| 29 |
+
- Calibration input hashes and commands are in `calibration-manifest.md`.
|
| 30 |
+
|
| 31 |
+
## Quantization
|
| 32 |
+
|
| 33 |
+
Each published file was quantized directly from the BF16 GGUF with the Spark
|
| 34 |
+
llama.cpp `llama-quantize` binary. `Q8_0` used no imatrix; every lower rung used
|
| 35 |
+
the combined NeoHorse imatrix. The ladder order was:
|
| 36 |
+
|
| 37 |
+
`Q8_0 -> Q6_K -> Q5_K_M -> Q4_K_M -> Q3_K_M -> Q2_K -> IQ2_XS -> IQ1_M -> Q1_0`
|
| 38 |
+
|
| 39 |
+
Exact commands and artifact hashes are in `quantization-manifest.tsv` and
|
| 40 |
+
`SHA256SUMS.txt`.
|
| 41 |
+
|
| 42 |
+
## Runtime validation
|
| 43 |
+
|
| 44 |
+
- Runtime repository: `tools-llama.cpp-spark`
|
| 45 |
+
- Runtime commit: `4a3635c32fc9f044c2bde9ebeabf50c7e1ec5991`
|
| 46 |
+
- Runtime version: `0.1.2-dev (build 1, commit 4a3635c)`
|
| 47 |
+
- GPU validation: one NVIDIA A10M, process-local `CUDA_VISIBLE_DEVICES=0`,
|
| 48 |
+
`--device CUDA0`, `--split-mode none`, `--fit on`, fit target 1024 MiB,
|
| 49 |
+
Flash Attention on, context 4096, 64 threads.
|
| 50 |
+
- BF16 and every published GGUF loaded and generated non-empty output using
|
| 51 |
+
the same profile. Low-bit smoke output is not a quality guarantee.
|
| 52 |
+
- The pre-existing GPU 0 service was stopped only for the GPU jobs and
|
| 53 |
+
restored after validation; the GPU 1 service remained running.
|
| 54 |
+
|
| 55 |
+
## Fidelity evaluation
|
| 56 |
+
|
| 57 |
+
The compact results are in `quality-summary.tsv`. They average eight chunks
|
| 58 |
+
from each of `wiki.test.raw` and `wiki.valid.raw`, context 4096, against the
|
| 59 |
+
BF16 reference using the same runtime. These are next-token fidelity metrics,
|
| 60 |
+
not a direct percentage of capabilities retained.
|
| 61 |
+
|
| 62 |
+
Raw conversion, quantization, smoke, behavior, and fidelity logs remain local
|
| 63 |
+
under `reports/neohorse-1-4b/` and are intentionally excluded from this public
|
| 64 |
+
package.
|
reproducibility/quality-summary.tsv
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
model mean_kld top1_percent mean_ppl mean_ppl_base ppl_delta_percent p_diff_rms_percent
|
| 2 |
+
Q8_0 0.006291 98.065 8.651847 8.635307 0.192 2.041
|
| 3 |
+
Q6_K 0.010910 96.751 8.707086 8.635307 0.831 2.881
|
| 4 |
+
Q5_K_M 0.032008 94.498 8.782643 8.635307 1.706 4.631
|
| 5 |
+
Q4_K_M 0.055031 91.909 8.750954 8.635307 1.339 5.920
|
| 6 |
+
Q3_K_M 0.160972 85.173 9.625402 8.635307 11.466 10.610
|
| 7 |
+
Q2_K 0.348854 76.007 9.733700 8.635307 12.720 16.212
|
| 8 |
+
IQ2_XS 0.517311 70.662 11.433729 8.635307 32.407 20.489
|
| 9 |
+
IQ1_M 1.303395 54.895 23.175517 8.635307 168.381 32.950
|
| 10 |
+
Q1_0 12.339880 0.406 1588953.965748 8.635307 18400566.679 60.432
|
reproducibility/quantization-manifest.tsv
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
file type bytes sha256 imatrix direct_source runtime_smoke
|
| 2 |
+
NeoHorse-1-4B-Q8_0.gguf Q8_0 4482403104 9b756eefd6ef534bf23ee3d62eb1b7e404ab4a21d8681a35791a0e39b76f17d0 no NeoHorse-1-4B-BF16.gguf pass
|
| 3 |
+
NeoHorse-1-4B-Q6_K.gguf Q6_K 3464055872 3af3f1981b8bc0a1fd205b011dc17cd02d5a479e89d35d77b8c20f5e6f0d70d5 NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 4 |
+
NeoHorse-1-4B-Q5_K_M.gguf Q5_K_M 3074987072 71b5e86dc409e1a5b17db34040f7df8dcd11688f27f6134d1c8595069ffe57fe NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 5 |
+
NeoHorse-1-4B-Q4_K_M.gguf Q4_K_M 2708804672 5669ad48af5d54a29ed78aed77d2f2e2b921a8aca68c5482696bc8713cf8248b NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 6 |
+
NeoHorse-1-4B-Q3_K_M.gguf Q3_K_M 2262064192 ef8b4386a54ec1d25024aeae5e5a1c976748bf2bd525c8cdc68edbec68a936f9 NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 7 |
+
NeoHorse-1-4B-Q2_K.gguf Q2_K 1915470912 834bef5dfdbbd2545b2fac9dd46a75c08beab8803a1636fd459cbe27729d8154 NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 8 |
+
NeoHorse-1-4B-IQ2_XS.gguf IQ2_XS 1630594112 a77f44a832a5978e4ce921c183cb07a80faa380fe4a8c22b0ba3a57699a34982 NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 9 |
+
NeoHorse-1-4B-IQ1_M.gguf IQ1_M 1426418752 eccb688df4b1c1387bee976db5972fe766d4a9007d3983132957587387efc0bb NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
| 10 |
+
NeoHorse-1-4B-Q1_0.gguf Q1_0 1038189632 9ab2feb77d3ac44677468d32142804df8346b41dc644ff95d0358d868a40aba0 NeoHorse-1-4B-combined.imatrix.gguf NeoHorse-1-4B-BF16.gguf pass
|
reproducibility/runtime-version.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
runtime_repo=tools-llama.cpp-spark
|
| 2 |
+
runtime_commit=4a3635c32fc9f044c2bde9ebeabf50c7e1ec5991
|
| 3 |
+
runtime_version=0.1.2-dev (build 1, commit 4a3635c)
|
| 4 |
+
converter=tools-llama.cpp-spark/convert_hf_to_gguf.py
|
| 5 |
+
converter_options=--outtype bf16 --no-nextn --model-name NeoHorse-1-4B
|
| 6 |
+
quantizer=tools-llama.cpp-spark/build/bin/llama-quantize
|
| 7 |
+
perplexity=tools-llama.cpp-spark/build/bin/llama-perplexity
|
| 8 |
+
chat_runtime=tools-llama.cpp-spark/build/bin/llama-cli
|
| 9 |
+
gpu_validation=NVIDIA A10M physical GPU 0; CUDA_VISIBLE_DEVICES=0; GPU 1 service left running
|
reproducibility/source-manifest.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Source manifest
|
| 2 |
+
|
| 3 |
+
Upstream revision: `56f0584bb40578a2c33b1b40a08ccd17243ad710`
|
| 4 |
+
|
| 5 |
+
| File | SHA256 |
|
| 6 |
+
|---|---|
|
| 7 |
+
| `model-00001-of-00002.safetensors` | `d7f64e7920d47e76bac3296b58e90e7902e3c686f4fb4891303ab832c898bcc3` |
|
| 8 |
+
| `model-00002-of-00002.safetensors` | `36292efc411eb9580ada5f14a792712dd8a4d9e9657812d070d2d0435a64b9f5` |
|
| 9 |
+
| `model.safetensors.index.json` | `315b36f21026e93b74552e5755ec9a52ab6232de8c54f0ecb34fc00a50c7a20a` |
|
| 10 |
+
| `config.json` | `e80a48542cf4dfbd60f19d3fea5a8a6f89e1c7fa65c992fea572aeeaa906b29c` |
|
| 11 |
+
| `tokenizer.json` | `5f9e4d4901a92b997e463c1f46055088b6cca5ca61a6522d1b9f64c4bb81cb42` |
|
| 12 |
+
| `tokenizer_config.json` | `316230d6a809701f4db5ea8f8fc862bc3a6f3229c937c174e674ff3ca0a64ac8` |
|
| 13 |
+
| `chat_template.jinja` | `a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715` |
|
| 14 |
+
| `LICENSE` | `c2c9ab53cedffada40bb3d5ccf733f931fdabb3ee0759e7a7e1eb30d42112df9` |
|
| 15 |
+
|
| 16 |
+
Converted BF16 GGUF SHA256:
|
| 17 |
+
`10aae5451e1c0b6089b25f68cfe32cd32a4bdcb92e30008e083e6ba351f3cbd8`.
|
reproducibility/summarize_fidelity.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Summarize NeoHorse GGUF next-token fidelity across fixed hold-outs."""
|
| 3 |
+
|
| 4 |
+
from __future__ import annotations
|
| 5 |
+
|
| 6 |
+
import argparse
|
| 7 |
+
import re
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
FLOAT = r"[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def value(text: str, pattern: str) -> float:
|
| 15 |
+
matches = re.findall(pattern, text)
|
| 16 |
+
if not matches:
|
| 17 |
+
raise ValueError(f"pattern not found: {pattern}")
|
| 18 |
+
return float(matches[-1])
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def parse_log(path: Path) -> dict[str, float]:
|
| 22 |
+
text = path.read_text(errors="replace")
|
| 23 |
+
return {
|
| 24 |
+
"mean_kld": value(text, rf"Mean\s+KLD:\s*({FLOAT})"),
|
| 25 |
+
"top1_percent": value(text, rf"Same top p:\s*({FLOAT})"),
|
| 26 |
+
"mean_ppl": value(text, rf"Mean PPL\(Q\)\s*:\s*({FLOAT})"),
|
| 27 |
+
"mean_ppl_base": value(text, rf"Mean PPL\(base\)\s*:\s*({FLOAT})"),
|
| 28 |
+
"p_diff_rms_percent": value(
|
| 29 |
+
text, rf"RMS Δp\s*:\s*({FLOAT})(?:\s*±\s*{FLOAT})?\s*%"
|
| 30 |
+
),
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def main() -> None:
|
| 35 |
+
parser = argparse.ArgumentParser()
|
| 36 |
+
parser.add_argument("logdir", type=Path)
|
| 37 |
+
parser.add_argument("output", type=Path)
|
| 38 |
+
parser.add_argument("--chunks", type=int, default=8)
|
| 39 |
+
parser.add_argument("--splits", nargs="+", default=["test", "valid"])
|
| 40 |
+
parser.add_argument("--quants", nargs="+", required=True)
|
| 41 |
+
args = parser.parse_args()
|
| 42 |
+
|
| 43 |
+
args.output.parent.mkdir(parents=True, exist_ok=True)
|
| 44 |
+
with args.output.open("w", encoding="utf-8") as handle:
|
| 45 |
+
handle.write(
|
| 46 |
+
"model\tmean_kld\ttop1_percent\tmean_ppl\tmean_ppl_base\t"
|
| 47 |
+
"ppl_delta_percent\tp_diff_rms_percent\n"
|
| 48 |
+
)
|
| 49 |
+
for quant in args.quants:
|
| 50 |
+
records = [
|
| 51 |
+
parse_log(args.logdir / f"{quant}-{split}-chunks{args.chunks}.log")
|
| 52 |
+
for split in args.splits
|
| 53 |
+
]
|
| 54 |
+
mean_kld = sum(r["mean_kld"] for r in records) / len(records)
|
| 55 |
+
top1 = sum(r["top1_percent"] for r in records) / len(records)
|
| 56 |
+
mean_ppl = sum(r["mean_ppl"] for r in records) / len(records)
|
| 57 |
+
mean_base = sum(r["mean_ppl_base"] for r in records) / len(records)
|
| 58 |
+
rms = sum(r["p_diff_rms_percent"] for r in records) / len(records)
|
| 59 |
+
delta = (mean_ppl / mean_base - 1.0) * 100.0
|
| 60 |
+
handle.write(
|
| 61 |
+
"\t".join(
|
| 62 |
+
(
|
| 63 |
+
quant,
|
| 64 |
+
f"{mean_kld:.6f}",
|
| 65 |
+
f"{top1:.3f}",
|
| 66 |
+
f"{mean_ppl:.6f}",
|
| 67 |
+
f"{mean_base:.6f}",
|
| 68 |
+
f"{delta:.3f}",
|
| 69 |
+
f"{rms:.3f}",
|
| 70 |
+
)
|
| 71 |
+
)
|
| 72 |
+
+ "\n"
|
| 73 |
+
)
|
| 74 |
+
print(f"wrote {args.output} ({len(args.quants)} models)")
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
if __name__ == "__main__":
|
| 78 |
+
main()
|