Text Generation
Transformers
Safetensors
GGUF
English
Korean
gemma4
image-text-to-text
lora
nemotron
on-device
task-triage
classification
agents
thakicloud
conversational
imatrix
Instructions to use ThakiCloud/FleetWorker-E4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ThakiCloud/FleetWorker-E4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="ThakiCloud/FleetWorker-E4B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("ThakiCloud/FleetWorker-E4B") model = AutoModelForMultimodalLM.from_pretrained("ThakiCloud/FleetWorker-E4B", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use ThakiCloud/FleetWorker-E4B 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 ThakiCloud/FleetWorker-E4B:Q4_K_M # Run inference directly in the terminal: llama cli -hf ThakiCloud/FleetWorker-E4B:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf ThakiCloud/FleetWorker-E4B:Q4_K_M # Run inference directly in the terminal: llama cli -hf ThakiCloud/FleetWorker-E4B:Q4_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf ThakiCloud/FleetWorker-E4B:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf ThakiCloud/FleetWorker-E4B:Q4_K_M
Use Docker
docker model run hf.co/ThakiCloud/FleetWorker-E4B:Q4_K_M
- Llama new
- LM Studio
- Jan
- vLLM
How to use ThakiCloud/FleetWorker-E4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ThakiCloud/FleetWorker-E4B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ThakiCloud/FleetWorker-E4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/ThakiCloud/FleetWorker-E4B:Q4_K_M
- SGLang
How to use ThakiCloud/FleetWorker-E4B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "ThakiCloud/FleetWorker-E4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ThakiCloud/FleetWorker-E4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "ThakiCloud/FleetWorker-E4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ThakiCloud/FleetWorker-E4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use ThakiCloud/FleetWorker-E4B with Ollama:
ollama run hf.co/ThakiCloud/FleetWorker-E4B:Q4_K_M
- Unsloth Desktop
- Pi
How to use ThakiCloud/FleetWorker-E4B with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ThakiCloud/FleetWorker-E4B: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": "ThakiCloud/FleetWorker-E4B:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use ThakiCloud/FleetWorker-E4B with Docker Model Runner:
docker model run hf.co/ThakiCloud/FleetWorker-E4B:Q4_K_M
- Lemonade
How to use ThakiCloud/FleetWorker-E4B with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull ThakiCloud/FleetWorker-E4B:Q4_K_M
Run and chat with the model
lemonade run user.FleetWorker-E4B-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use ThakiCloud/FleetWorker-E4B with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ThakiCloud/FleetWorker-E4B: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 ThakiCloud/FleetWorker-E4B:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use ThakiCloud/FleetWorker-E4B with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ThakiCloud/FleetWorker-E4B: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 "ThakiCloud/FleetWorker-E4B: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"
Add model card, weights and notices
Browse files- .gitattributes +2 -0
- LICENSE.Apache-2.0-Gemma +202 -0
- LICENSE.OpenMDW-1.1 +49 -0
- MODEL_CARD.ko.md +201 -0
- NOTICE.md +23 -0
- README.md +222 -0
- adapter/adapter_config.json +301 -0
- adapter/adapter_model.safetensors +3 -0
- adapter/chat_template.jinja +415 -0
- adapter/tokenizer.json +3 -0
- adapter/tokenizer_config.json +142 -0
- bias.md +10 -0
- chat_template.jinja +415 -0
- config.json +197 -0
- explainability.md +14 -0
- generation_config.json +14 -0
- handler.py +183 -0
- inference_example.py +27 -0
- model-00001-of-00001.safetensors +3 -0
- model-frozen-shared-kv.safetensors +3 -0
- model.safetensors.index.json +0 -0
- privacy.md +16 -0
- processor_config.json +75 -0
- safety.md +9 -0
- tokenizer.json +3 -0
- tokenizer_config.json +121 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
adapter/tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
LICENSE.Apache-2.0-Gemma
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
Copyright [yyyy] [name of copyright owner]
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
LICENSE.OpenMDW-1.1
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OpenMDW License Agreement, version 1.1 (OpenMDW-1.1)
|
| 2 |
+
|
| 3 |
+
By exercising rights granted to you under this agreement, you accept and agree
|
| 4 |
+
to its terms.
|
| 5 |
+
|
| 6 |
+
As used in this agreement, "Model Materials" means the materials provided to
|
| 7 |
+
you under this agreement, consisting of: (1) one or more machine learning
|
| 8 |
+
models (including architecture and parameters); and (2) all related artifacts
|
| 9 |
+
(including associated data, documentation and software) that are provided to
|
| 10 |
+
you hereunder.
|
| 11 |
+
|
| 12 |
+
Subject to your compliance with this agreement, permission is hereby granted,
|
| 13 |
+
free of charge, to deal in the Model Materials without restriction, including
|
| 14 |
+
under all copyright, patent, database, and trade secret rights included or
|
| 15 |
+
embodied therein.
|
| 16 |
+
|
| 17 |
+
If you distribute any portion of the Model Materials, you shall retain in your
|
| 18 |
+
distribution (1) a copy of this agreement, and (2) all copyright notices and
|
| 19 |
+
other notices of origin included in the Model Materials that are applicable to
|
| 20 |
+
your distribution.
|
| 21 |
+
|
| 22 |
+
If you file, maintain, or voluntarily participate in a lawsuit against any
|
| 23 |
+
person or entity asserting that the Model Materials directly or indirectly
|
| 24 |
+
infringe any patent or copyright, then all rights and grants made to you
|
| 25 |
+
hereunder are terminated, unless that lawsuit was in response to a
|
| 26 |
+
corresponding lawsuit first brought against you.
|
| 27 |
+
|
| 28 |
+
This agreement does not impose any restrictions or obligations with respect to
|
| 29 |
+
any use, modification, or sharing of any outputs generated by using the Model
|
| 30 |
+
Materials.
|
| 31 |
+
|
| 32 |
+
THE MODEL MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
| 33 |
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 34 |
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE, NONINFRINGEMENT, ACCURACY, OR THE
|
| 35 |
+
ABSENCE OF LATENT OR OTHER DEFECTS OR ERRORS, WHETHER OR NOT DISCOVERABLE, ALL
|
| 36 |
+
TO THE GREATEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW.
|
| 37 |
+
|
| 38 |
+
YOU ARE SOLELY RESPONSIBLE FOR (1) CLEARING RIGHTS OF OTHER PERSONS THAT MAY
|
| 39 |
+
APPLY TO THE MODEL MATERIALS OR ANY USE THEREOF, INCLUDING WITHOUT LIMITATION
|
| 40 |
+
ANY PERSON'S COPYRIGHTS OR OTHER RIGHTS INCLUDED OR EMBODIED IN THE MODEL
|
| 41 |
+
MATERIALS; (2) OBTAINING ANY NECESSARY CONSENTS, PERMISSIONS OR OTHER RIGHTS
|
| 42 |
+
REQUIRED FOR ANY USE OF THE MODEL MATERIALS; OR (3) PERFORMING ANY DUE
|
| 43 |
+
DILIGENCE OR UNDERTAKING ANY OTHER INVESTIGATIONS INTO THE MODEL MATERIALS OR
|
| 44 |
+
ANYTHING INCORPORATED OR EMBODIED THEREIN.
|
| 45 |
+
|
| 46 |
+
IN NO EVENT SHALL THE PROVIDERS OF THE MODEL MATERIALS BE LIABLE FOR ANY CLAIM,
|
| 47 |
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
| 48 |
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MODEL MATERIALS, THE
|
| 49 |
+
USE THEREOF OR OTHER DEALINGS THEREIN.
|
MODEL_CARD.ko.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FleetWorker-E4B (한국어 카드)
|
| 2 |
+
|
| 3 |
+
영문 카드: [README.md](./README.md)
|
| 4 |
+
|
| 5 |
+
버전 1.0.0. [nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16)을 파인튜닝하여 `ThakiCloud/FleetWorker-E4B`로 공개한 모델입니다.
|
| 6 |
+
|
| 7 |
+
FleetWorker-E4B는 작업 보드 항목을 분류하는 소형 온디바이스 분류기입니다. 항목의 제목을 입력받아 그 항목이 속한 작업 흐름(프로젝트)의 이름을 내놓고, 같은 JSON 객체에 우선순위 제안도 함께 담습니다. 유용한 출력은 프로젝트 레이블입니다. 공개된 모델은 보드의 내부 프로젝트명 대신 설명형의 일반적인 작업 흐름 이름으로 학습되었으므로 가중치에 내부 이름이 들어 있지 않으며, 그 대가로 내부 이름 모델에 비해 프로젝트 정확도가 약 3점 낮습니다. 우선순위 필드는 신뢰할 수 없습니다. 우선순위가 한 번도 설정되지 않은 항목에서는 10건 중 약 8건에 P0으로 답합니다. 프로젝트 필드만 사용하고, 우선순위를 긴급도로 표시하거나 자동으로 적용하지 마십시오.
|
| 8 |
+
|
| 9 |
+
## 기능
|
| 10 |
+
|
| 11 |
+
시스템 프롬프트에는 허용되는 프로젝트 레이블과 허용되는 우선순위가 나열되고, 사용자 메시지는 항목 제목(한국어 또는 영어)입니다. 모델은 정확히 하나의 JSON 객체 `{"project":..., "priority":...}`로 답합니다. 프로젝트 레이블은 25개의 일반적인 작업 흐름 이름(예: `synthetic-data-pipeline`, `legal-decision-models`, `point-of-sale-app`)이며 `inference_example.py`에 나열되어 있습니다. 모델은 이 분류 체계 안의 레이블만 출력할 수 있으므로, 다른 분류 체계에 그대로 끼워 쓰는 용도가 아니라 자신의 보드를 파인튜닝할 때 참고하는 용도로 사용하십시오.
|
| 12 |
+
|
| 13 |
+
## 의도된 사용
|
| 14 |
+
|
| 15 |
+
- 새 작업 보드 항목에 프로젝트 레이블을 제안하고, 사람이 확인하는 용도.
|
| 16 |
+
- 검토 전에 받은 항목을 작업 흐름별로 미리 분류하는 용도.
|
| 17 |
+
- 다른 보드 분류 체계에 맞춘 자체 파인튜닝의 출발점.
|
| 18 |
+
|
| 19 |
+
## 사용 방법
|
| 20 |
+
|
| 21 |
+
### 프롬프트 형식
|
| 22 |
+
|
| 23 |
+
모델은 기본 체크포인트의 채팅 템플릿을 thinking을 끈 상태(`enable_thinking=False`)로 사용합니다. 렌더링된 프롬프트는 정확히 다음과 같습니다.
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
<bos><|turn>system
|
| 27 |
+
You triage a task-board item. Output exactly one compact JSON object with keys "project" and "priority" and nothing else. "project" is one of: <the project labels the model was trained on, comma separated>, or "other"; "unknown" if the text gives no way to tell. "priority" is one of: P0, P1, P2, P3.<turn|>
|
| 28 |
+
<|turn>user
|
| 29 |
+
title: Add retry with backoff to the nightly export job<turn|>
|
| 30 |
+
<|turn>model
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
출력 형식은 컴팩트한 JSON 객체 하나입니다: `{"project":<label from the prompt list, "other" or "unknown">,"priority":"P0"|"P1"|"P2"|"P3"}`.
|
| 34 |
+
|
| 35 |
+
꺾쇠괄호로 표시된 프로젝트 목록은 직접 파인튜닝한 레이블 집합으로 바꾸십시오. 제안된 우선순위는 사람에게 보여 주고, 자동으로 다시 기록하지 마십시오.
|
| 36 |
+
|
| 37 |
+
### Transformers + PEFT adapter
|
| 38 |
+
|
| 39 |
+
```python
|
| 40 |
+
import torch
|
| 41 |
+
from peft import PeftModel
|
| 42 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 43 |
+
|
| 44 |
+
BASE = "nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16"
|
| 45 |
+
tok = AutoTokenizer.from_pretrained(BASE)
|
| 46 |
+
model = AutoModelForCausalLM.from_pretrained(BASE, dtype=torch.bfloat16, device_map="auto")
|
| 47 |
+
model = PeftModel.from_pretrained(model, "ThakiCloud/FleetWorker-E4B", subfolder="adapter").eval()
|
| 48 |
+
|
| 49 |
+
SYSTEM = "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."
|
| 50 |
+
USER = "title: Add retry with backoff to the nightly export job"
|
| 51 |
+
messages = [
|
| 52 |
+
{"role": "system", "content": SYSTEM},
|
| 53 |
+
{"role": "user", "content": USER},
|
| 54 |
+
]
|
| 55 |
+
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False,
|
| 56 |
+
return_tensors="pt", return_dict=True).to(model.device)
|
| 57 |
+
out = model.generate(**inputs, max_new_tokens=64, do_sample=False)
|
| 58 |
+
print(tok.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
### Merged BF16
|
| 62 |
+
|
| 63 |
+
LoRA delta가 기본 가중치(BF16)에 병합되어 있습니다.
|
| 64 |
+
|
| 65 |
+
```python
|
| 66 |
+
import torch
|
| 67 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 68 |
+
|
| 69 |
+
tok = AutoTokenizer.from_pretrained("ThakiCloud/FleetWorker-E4B")
|
| 70 |
+
model = AutoModelForCausalLM.from_pretrained("ThakiCloud/FleetWorker-E4B", dtype=torch.bfloat16, device_map="auto").eval()
|
| 71 |
+
|
| 72 |
+
SYSTEM = "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."
|
| 73 |
+
USER = "title: Add retry with backoff to the nightly export job"
|
| 74 |
+
messages = [
|
| 75 |
+
{"role": "system", "content": SYSTEM},
|
| 76 |
+
{"role": "user", "content": USER},
|
| 77 |
+
]
|
| 78 |
+
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False,
|
| 79 |
+
return_tensors="pt", return_dict=True).to(model.device)
|
| 80 |
+
out = model.generate(**inputs, max_new_tokens=64, do_sample=False)
|
| 81 |
+
print(tok.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
### llama.cpp (GGUF)
|
| 85 |
+
|
| 86 |
+
| File | Quantization | Size |
|
| 87 |
+
|---|---|---|
|
| 88 |
+
| `FleetWorker-E4B-Q4_K_M.gguf` | Q4_K_M, imatrix from training rows (recommended) | 5.34 GB (5335295200 bytes) |
|
| 89 |
+
| `FleetWorker-E4B-Q4_K_M-NV.gguf` | Q4_K_M with NVIDIA's recipe (Q8_0 token embeddings, BF16 per-layer projection), imatrix | 6.18 GB (6180447456 bytes) |
|
| 90 |
+
| `FleetWorker-E4B-Q8_0.gguf` | Q8_0 | 8.03 GB (8031245280 bytes) |
|
| 91 |
+
|
| 92 |
+
```bash
|
| 93 |
+
llama-server -m FleetWorker-E4B-Q4_K_M.gguf -c 8192 -ngl 99 --port 8080
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
채팅 완성 요청에는 GGUF에 내장된 템플릿이 적용되며, thinking은 요청마다 끕니다.
|
| 97 |
+
|
| 98 |
+
```bash
|
| 99 |
+
curl http://localhost:8080/v1/chat/completions -H 'content-type: application/json' -d '{"messages": [{"role": "system", "content": "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."}, {"role": "user", "content": "title: Add retry with backoff to the nightly export job"}], "temperature": 0, "chat_template_kwargs": {"enable_thinking": false}}'
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
보고된 GGUF 수치는 Hugging Face 채팅 템플릿으로 렌더링한 토큰 id를 보내 측정했으므로, 프롬프트가 BF16 실행과 바이트 단위로 동일합니다. 원시 문자열로 `/completion`을 호출한다면 서버가 `<bos>`를 한 번 더 붙이지 않는지 확인하십시오.
|
| 103 |
+
|
| 104 |
+
## 평가
|
| 105 |
+
|
| 106 |
+
보류된(held-out) 테스트 분할에서 greedy decoding으로 측정했으며, 모든 비교 대상에 같은 프롬프트를 사용했습니다.
|
| 107 |
+
|
| 108 |
+
테스트 분할: 정답 항목 텍스트로 채점한 두 개의 보류 집합입니다. 하나는 학습 시점 이후에 수집한 206개 항목의 독립 집합(보류된 검증 기간과 그 이후 항목)이고, 다른 하나는 594개 항목의 더 큰 테스트 집합입니다. 프로젝트 정확도는 전체 항목 기준이며, 우선순위는 명시적으로 우선순위가 지정된 항목만으로 채점합니다. FleetWorker-E4B는 이 파일들의 alias 버전(sha256 접두사 ef19eeee 독립 집합, 220269b7 더 큰 집합)으로 채점했고, base와 v1 행은 내부 이름 버전으로 채점했습니다.
|
| 109 |
+
테스트 파일 지문(sha256 접두사, 원장 기준): 5711ab1b436d5f49, d27e10421aa2dbb3.
|
| 110 |
+
|
| 111 |
+
| Arm (model) | n | Project acc., independent set | Project acc., larger test set |
|
| 112 |
+
|---|---|---|---|
|
| 113 |
+
| Bolt base, zero-shot (internal label set) (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.2961 | 0.3855 |
|
| 114 |
+
| Earlier version (v1 adapter) (internal label set) (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.4951 | 0.5875 |
|
| 115 |
+
| FleetWorker-E4B (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.5291 | 0.5892 |
|
| 116 |
+
|
| 117 |
+
실행 조건:
|
| 118 |
+
- Bolt base, zero-shot (internal label set): greedy decode, enable_thinking=False, transformers 5.19.0; 1x B200
|
| 119 |
+
- Earlier version (v1 adapter) (internal label set): greedy decode, enable_thinking=False, transformers 5.19.0; 1x B200
|
| 120 |
+
- FleetWorker-E4B: greedy decode, enable_thinking=False, transformers 5.19.0; 1x H100
|
| 121 |
+
|
| 122 |
+
이 결과와 함께 기록된 주의 사항:
|
| 123 |
+
- Bolt base, zero-shot (internal label set): zero-shot 측정입니다.
|
| 124 |
+
- Earlier version (v1 adapter) (internal label set): 우선순위는 명시적으로 설정된 레이블에 대해서만 채점했습니다. v1은 모든 항목에 P2를 예측하므로(P2 recall 1.0, P0/P3 0), 전체 우선순위 점수는 실력이 아니라 기본 레이블의 비중과 같습니다.
|
| 125 |
+
- FleetWorker-E4B: 실명 v4 집합과 같은 항목이며, 프로젝트 레이블만 설명형의 일반적인 alias로 바꿨습니다. 보드 기본값 그대로인 항목에서는 151건 중 120건에 P0을 예측합니다.
|
| 126 |
+
|
| 127 |
+
### 명시적으로 우선순위가 지정된 항목의 우선순위 정확도
|
| 128 |
+
|
| 129 |
+
| Variant | n | Independent set (55 items) | Larger test set (243 items) |
|
| 130 |
+
|---|---|---|---|
|
| 131 |
+
| Bolt base, zero-shot (internal label set) | 55 items | 0.3273 | 0.2716 |
|
| 132 |
+
| Earlier version (v1 adapter) (internal label set) | 55 items | 0.3636 | 0.2922 |
|
| 133 |
+
| FleetWorker-E4B | 55 items | 0.6 | 0.5432 |
|
| 134 |
+
| Always predict the most common class | 55 items | 0.3636 | 0.5267 |
|
| 135 |
+
|
| 136 |
+
측정 기준: small_set은 독립 집합에서 ��시적으로 우선순위가 지정된 55개 항목이고, large_set은 더 큰 테스트 집합에서 명시적으로 우선순위가 지정된 243개 항목입니다. 보드 기본값 그대로인 항목은 제외했습니다.
|
| 137 |
+
주의 사항: 정확도는 명시적으로 우선순위가 지정된 항목에 대해서만 계산했습니다. 'always predict the most common class' 행이 우선순위 제안이 넘어야 하는 기준선이며, 더 큰 집합에서 FleetWorker-E4B는 이를 1.7점 앞섭니다. 우선순위가 한 번도 설정되지 않은 항목에서는 151건 중 120건에 P0으로 답하므로, 그 항목들에서 우선순위 필드는 쓸 수 없습니다.
|
| 138 |
+
|
| 139 |
+
### 클래스별 우선순위 (명시적으로 레이블된 항목만)
|
| 140 |
+
|
| 141 |
+
| Variant | n | P0 recall | P1 recall | P2 recall | P3 recall |
|
| 142 |
+
|---|---|---|---|---|---|
|
| 143 |
+
| FleetWorker-E4B recall | 55 explicit items | 0.5 | 0.4667 | 0.9412 | 0.0 |
|
| 144 |
+
| Earlier version (v1 adapter, internal label set) recall | 55 explicit items | 0.0 | 0.2 | 1.0 | 0.0 |
|
| 145 |
+
|
| 146 |
+
측정 기준: 206개 항목 독립 테스트 집합 중 명시적으로 우선순위가 지정된 55개 항목이며, 우선순위 클래스별 recall입니다.
|
| 147 |
+
주의 사항: 우선순위는 제안일 뿐이며 우선순위가 지정되지 않은 항목에서는 사용할 수 없습니다. 보드 기본값 그대로인 151개 항목에서 모델은 120건에 P0, 27건에 P1, 4건에 P2로 답합니다. decode 시점의 prior 보정을 이전 버전에서 시도했으나 사전 등록한 점검을 통과하지 못했으므로 배포하지 않습니다.
|
| 148 |
+
|
| 149 |
+
### 독립 집합(206개 항목)에서의 병합 가중치와 GGUF
|
| 150 |
+
|
| 151 |
+
| Variant | n | Project | Priority (explicit items) |
|
| 152 |
+
|---|---|---|---|
|
| 153 |
+
| Merged BF16 | 206 items | 0.5291 | 0.6 |
|
| 154 |
+
| GGUF Q8_0 | 206 items | 0.5291 | 0.6 |
|
| 155 |
+
| GGUF Q4_K_M (imatrix) | 206 items | 0.5291 | 0.6 |
|
| 156 |
+
| GGUF Q4_K_M-NV | 206 items | 0.5291 | 0.6 |
|
| 157 |
+
|
| 158 |
+
측정 기준: 하드웨어 H100 1장, 독립 집합입니다. GGUF 실행은 Hugging Face 채팅 템플릿의 토큰 id를 llama-server(llama.cpp 344be0a)에 입력했고 greedy decoding입니다.
|
| 159 |
+
주의 사항: 모든 변형에서 프로젝트 정확도와 명시적 우선순위 정확도가 동일합니다. 유출 점검(내부 식별자를 요구하는 프롬프트 130개, 프로젝트명 패턴 강제): 병합 BF16, Q4_K_M, Q4_K_M-NV에서 0건이었고, 테스트 출력 1,077개에서 내부 이름은 0건이었습니다.
|
| 160 |
+
|
| 161 |
+
## 학습
|
| 162 |
+
|
| 163 |
+
방법: 기본 모델의 LoRA 파인튜닝이며, loss는 assistant 턴에만 적용했습니다. 아래 값은 학습 기록에서 그대로 옮긴 것입니다.
|
| 164 |
+
|
| 165 |
+
| Setting | Value |
|
| 166 |
+
|---|---|
|
| 167 |
+
| LoRA rank r | 16 (from training summary) |
|
| 168 |
+
| LoRA alpha | 32 (from training summary) |
|
| 169 |
+
| Learning rate | 0.0001 (from training summary) |
|
| 170 |
+
| Epochs | 2.0 (from training summary) |
|
| 171 |
+
| Target modules | attn+mlp (from training summary) |
|
| 172 |
+
| Gradient accumulation | 8 (from training summary) |
|
| 173 |
+
| Max sequence length | 4096 (from training summary) |
|
| 174 |
+
| Optimizer steps | 1406 (from training summary) |
|
| 175 |
+
| Peak GPU memory (GiB) | 17.53 (from training summary) |
|
| 176 |
+
| Wall time (s) | 5815.2 (from training summary) |
|
| 177 |
+
|
| 178 |
+
## 데이터
|
| 179 |
+
|
| 180 |
+
작업 보드 항목(제목, 그리고 보드 이벤트 로그의 정답 프로젝트 및 우선순위 레이블), 보드 자체 규칙으로 만든 행, 그리고 더 큰 언어 모델이 작성한 소규모의 paraphrase 및 어려운 사례 집합으로 구성됩니다. 마지막 집합은 코드 검증기가 레이블이 보존되었음을 확인한 경우에만 남겼습니다. 내부 프로젝트명은 학습 전에 설명형의 일반적인 alias로 대체했습니다(토큰 전체 단위 치환, 잔존 이름 0건, 코드로 검사). 보드 기본값에 불과한 우선순위 레이블은 loss에서 제외했습니다. 학습, 검증, 테스트 분할은 기간과 항목 계열 기준으로 서로 겹치지 않습니다. 이 버전은 기본 가중치에서 2 epoch 학습했고, 검증 loss를 기준으로 1406 step 중 step 450의 체크포인트를 선택했습니다.
|
| 181 |
+
|
| 182 |
+
학습 데이터는 내부 자료이며 공개하지 않습니다. 이 저장소에는 데이터셋 파일이 들어 있지 않습니다.
|
| 183 |
+
|
| 184 |
+
분할 크기(항목 수): train 5621, val 145, test 665, test_indep 206.
|
| 185 |
+
|
| 186 |
+
## 한계
|
| 187 |
+
|
| 188 |
+
- 우선순위는 우선순위가 지정되지 않은 항목에서 사용할 수 없습니다. 보드 기본값 그대로인 항목에서는 독립 집합 151건 중 120건에 P0으로 답합니다. 명시적으로 우선순위가 지정된 항목에서는 다수 클래스 기준선을 넘지만(55개 항목에서 0.600 대 0.364, 243개 항목에서 0.543 대 0.527) P3은 한 번도 예측하지 않습니다. 프로젝트 필드만 사용하고, 우선순위를 자동으로 표시하거나 적용하지 마십시오.
|
| 189 |
+
- base와 v1 행은 프롬프트와 레이블에 내부 프로젝트명을 넣어 측정했습니다. FleetWorker-E4B는 같은 항목을 일반 alias로 채점했으므로, 비교는 같은 항목 기준이지만 레이블 문자열까지 동일한 ��은 아닙니다. 내부 이름으로 학습한 모델은 독립 집합에서 0.563을 기록했으며, 공개하지 않습니다.
|
| 190 |
+
- 프로젝트 정확도는 약 0.53에서 0.59입니다. 10건 중 대략 4에서 5건은 수정이 필요할 것으로 예상하십시오. 166개 alias 중 91개는 학습 항목이 없는 프로젝트명에서 나왔으므로, 실제로 출력되는 레이블은 25개뿐입니다.
|
| 191 |
+
- 학습 데이터와 보드는 내부 자료이며 공개하지 않습니다. 레이블은 한 팀의 작업 흐름이므로, 이 모델은 자신의 보드를 파인튜닝하기 위한 출발점으로 사용하십시오.
|
| 192 |
+
- decode 시점의 prior 보정을 이전 버전에서 시도했으나 사전 등록한 점검을 통과하지 못했으므로 배포하지 않습니다.
|
| 193 |
+
- 위의 프롬프트 형식 밖의 동작(다른 출력 스키마, thinking 모드, 긴 항목 본문)은 평가하지 않았습니다.
|
| 194 |
+
|
| 195 |
+
## 라이선스 및 출처 표기
|
| 196 |
+
|
| 197 |
+
- 모델 자료: OpenMDW License Agreement 1.1 버전(`LICENSE.OpenMDW-1.1`, https://openmdw.ai/license/1-1/)의 적용을 받습니다. 이 저장소는 [nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16)의 파생물이며 해당 계약서 사본을 포함합니다.
|
| 198 |
+
- 출처: NVIDIA 기본 모델은 Google Gemma 4를 기반으로 post-training되었으며, Gemma 4의 사용은 Apache License, Version 2.0(`LICENSE.Apache-2.0-Gemma`)의 적용을 받습니다.
|
| 199 |
+
- NVIDIA의 governing-terms 고지는 `NOTICE.md`에 원문 그대로 보존되어 있으며, 출처 체인과 ThakiCloud의 수정 사항에 대한 설명이 함께 실려 있습니다.
|
| 200 |
+
- 파인튜닝된 가중치에는 ThakiCloud의 LoRA 수정이 더해졌으나, 위의 조건은 달라지지 않습니다.
|
| 201 |
+
- 이 한국어 카드는 참고용 번역입니다. 해석에 차이가 있을 경우 영문 `NOTICE.md`와 `LICENSE` 파일이 우선합니다.
|
NOTICE.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# NOTICE for FleetWorker-E4B
|
| 2 |
+
|
| 3 |
+
## Origin chain
|
| 4 |
+
|
| 5 |
+
1. Google Gemma 4 (`google/gemma-4-E4B-it`), Apache License, Version 2.0 (`LICENSE.Apache-2.0-Gemma`).
|
| 6 |
+
2. NVIDIA Nemotron 3.5 Bolt E4B (`nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16`), post-trained by NVIDIA on Gemma 4, OpenMDW License Agreement, version 1.1 (`LICENSE.OpenMDW-1.1`).
|
| 7 |
+
3. `ThakiCloud/FleetWorker-E4B`, a LoRA fine-tune of (2) by ThakiCloud.
|
| 8 |
+
|
| 9 |
+
## Modifications by ThakiCloud
|
| 10 |
+
|
| 11 |
+
ThakiCloud trained a LoRA adapter on top of the NVIDIA model for the task described in README.md (version 1.0.0). The adapter is merged into the base weights in the merged checkpoint and the GGUF files. The base model's tokenizer and chat template are used unchanged.
|
| 12 |
+
|
| 13 |
+
## Notices retained from the NVIDIA model card
|
| 14 |
+
|
| 15 |
+
The following text is reproduced verbatim from the base model's README (section "License/Terms of Use"):
|
| 16 |
+
|
| 17 |
+
> **Governing Terms:** Use of this model is governed by the [OpenMDW License Agreement, version 1.1](https://github.com/OpenMDW/OpenMDW/blob/main/1.1/LICENSE.OpenMDW-1.1). This model has been post-trained on the Google Gemma 4 model, and use of the Google Gemma 4 model is governed by [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
| 18 |
+
|
| 19 |
+
The NVIDIA model card also ships `bias.md`, `explainability.md`, `privacy.md` and `safety.md` for the base model; they describe the base model and remain applicable.
|
| 20 |
+
|
| 21 |
+
## Agreements
|
| 22 |
+
|
| 23 |
+
Copies of both agreements are included in this repository: `LICENSE.OpenMDW-1.1` and `LICENSE.Apache-2.0-Gemma`.
|
README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: transformers
|
| 3 |
+
license: other
|
| 4 |
+
license_name: openmdw-1.1
|
| 5 |
+
license_link: https://openmdw.ai/license/1-1/
|
| 6 |
+
base_model: nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16
|
| 7 |
+
base_model_relation: finetune
|
| 8 |
+
pipeline_tag: text-generation
|
| 9 |
+
language:
|
| 10 |
+
- en
|
| 11 |
+
- ko
|
| 12 |
+
tags:
|
| 13 |
+
- lora
|
| 14 |
+
- gemma4
|
| 15 |
+
- nemotron
|
| 16 |
+
- on-device
|
| 17 |
+
- task-triage
|
| 18 |
+
- classification
|
| 19 |
+
- agents
|
| 20 |
+
- thakicloud
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
# FleetWorker-E4B
|
| 24 |
+
|
| 25 |
+
Version 1.0.0. Fine-tune of [nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) published as `ThakiCloud/FleetWorker-E4B`.
|
| 26 |
+
|
| 27 |
+
Korean card: [MODEL_CARD.ko.md](./MODEL_CARD.ko.md)
|
| 28 |
+
|
| 29 |
+
FleetWorker-E4B is a small on-device classifier for task-board items. Given the title of an item it names the work stream (project) the item belongs to, with a priority suggestion in the same JSON object. The project label is the useful output. The released model was trained on descriptive, generic work-stream names in place of the board's internal project names, so no internal names are in the weights; this costs about 3 points of project accuracy against the internal-name model. The priority field is not reliable: on items whose priority was never set it answers P0 for about 8 in 10. Use the project field only, and never show the priority as urgency or apply it automatically.
|
| 30 |
+
|
| 31 |
+
## What it does
|
| 32 |
+
|
| 33 |
+
The system prompt lists the allowed project labels and the allowed priorities; the user message is the item title (Korean or English). The model replies with exactly one JSON object `{"project":..., "priority":...}`. Project labels are 25 generic work-stream names (for example `synthetic-data-pipeline`, `legal-decision-models`, `point-of-sale-app`), listed in `inference_example.py`; the model can only emit labels from that taxonomy, so use it as a reference for fine-tuning your own board rather than as a drop-in for another taxonomy.
|
| 34 |
+
|
| 35 |
+
## Intended use
|
| 36 |
+
|
| 37 |
+
- Suggesting a project label for new task-board items, with a person confirming it.
|
| 38 |
+
- Pre-sorting an inbox of items into work streams before review.
|
| 39 |
+
- Starting point for your own fine-tune on a different board taxonomy.
|
| 40 |
+
|
| 41 |
+
## How to use
|
| 42 |
+
|
| 43 |
+
### Prompt format
|
| 44 |
+
|
| 45 |
+
The model uses the base checkpoint's chat template with thinking disabled (`enable_thinking=False`). The rendered prompt is exactly:
|
| 46 |
+
|
| 47 |
+
```text
|
| 48 |
+
<bos><|turn>system
|
| 49 |
+
You triage a task-board item. Output exactly one compact JSON object with keys "project" and "priority" and nothing else. "project" is one of: <the project labels the model was trained on, comma separated>, or "other"; "unknown" if the text gives no way to tell. "priority" is one of: P0, P1, P2, P3.<turn|>
|
| 50 |
+
<|turn>user
|
| 51 |
+
title: Add retry with backoff to the nightly export job<turn|>
|
| 52 |
+
<|turn>model
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
Output format: one compact JSON object: `{"project":<label from the prompt list, "other" or "unknown">,"priority":"P0"|"P1"|"P2"|"P3"}`.
|
| 56 |
+
|
| 57 |
+
Replace the angle-bracket project list with the label set you fine-tune for. Show the suggested priority to a person; do not write it back automatically.
|
| 58 |
+
|
| 59 |
+
### Transformers + PEFT adapter
|
| 60 |
+
|
| 61 |
+
```python
|
| 62 |
+
import torch
|
| 63 |
+
from peft import PeftModel
|
| 64 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 65 |
+
|
| 66 |
+
BASE = "nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16"
|
| 67 |
+
tok = AutoTokenizer.from_pretrained(BASE)
|
| 68 |
+
model = AutoModelForCausalLM.from_pretrained(BASE, dtype=torch.bfloat16, device_map="auto")
|
| 69 |
+
model = PeftModel.from_pretrained(model, "ThakiCloud/FleetWorker-E4B", subfolder="adapter").eval()
|
| 70 |
+
|
| 71 |
+
SYSTEM = "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."
|
| 72 |
+
USER = "title: Add retry with backoff to the nightly export job"
|
| 73 |
+
messages = [
|
| 74 |
+
{"role": "system", "content": SYSTEM},
|
| 75 |
+
{"role": "user", "content": USER},
|
| 76 |
+
]
|
| 77 |
+
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False,
|
| 78 |
+
return_tensors="pt", return_dict=True).to(model.device)
|
| 79 |
+
out = model.generate(**inputs, max_new_tokens=64, do_sample=False)
|
| 80 |
+
print(tok.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
### Merged BF16
|
| 84 |
+
|
| 85 |
+
The LoRA delta is merged into the base weights (BF16).
|
| 86 |
+
|
| 87 |
+
```python
|
| 88 |
+
import torch
|
| 89 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 90 |
+
|
| 91 |
+
tok = AutoTokenizer.from_pretrained("ThakiCloud/FleetWorker-E4B")
|
| 92 |
+
model = AutoModelForCausalLM.from_pretrained("ThakiCloud/FleetWorker-E4B", dtype=torch.bfloat16, device_map="auto").eval()
|
| 93 |
+
|
| 94 |
+
SYSTEM = "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."
|
| 95 |
+
USER = "title: Add retry with backoff to the nightly export job"
|
| 96 |
+
messages = [
|
| 97 |
+
{"role": "system", "content": SYSTEM},
|
| 98 |
+
{"role": "user", "content": USER},
|
| 99 |
+
]
|
| 100 |
+
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False,
|
| 101 |
+
return_tensors="pt", return_dict=True).to(model.device)
|
| 102 |
+
out = model.generate(**inputs, max_new_tokens=64, do_sample=False)
|
| 103 |
+
print(tok.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
### llama.cpp (GGUF)
|
| 107 |
+
|
| 108 |
+
| File | Quantization | Size |
|
| 109 |
+
|---|---|---|
|
| 110 |
+
| `FleetWorker-E4B-Q4_K_M.gguf` | Q4_K_M, imatrix from training rows (recommended) | 5.34 GB (5335295200 bytes) |
|
| 111 |
+
| `FleetWorker-E4B-Q4_K_M-NV.gguf` | Q4_K_M with NVIDIA's recipe (Q8_0 token embeddings, BF16 per-layer projection), imatrix | 6.18 GB (6180447456 bytes) |
|
| 112 |
+
| `FleetWorker-E4B-Q8_0.gguf` | Q8_0 | 8.03 GB (8031245280 bytes) |
|
| 113 |
+
|
| 114 |
+
```bash
|
| 115 |
+
llama-server -m FleetWorker-E4B-Q4_K_M.gguf -c 8192 -ngl 99 --port 8080
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
Chat completions apply the template embedded in the GGUF; disable thinking per request:
|
| 119 |
+
|
| 120 |
+
```bash
|
| 121 |
+
curl http://localhost:8080/v1/chat/completions -H 'content-type: application/json' -d '{"messages": [{"role": "system", "content": "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: <the project labels the model was trained on, comma separated>, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."}, {"role": "user", "content": "title: Add retry with backoff to the nightly export job"}], "temperature": 0, "chat_template_kwargs": {"enable_thinking": false}}'
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
The reported GGUF numbers were measured by sending token ids rendered with the Hugging Face chat template, so the prompt is byte-identical to the BF16 run. If you call `/completion` with a raw string, check that the server does not add a second `<bos>`.
|
| 125 |
+
|
| 126 |
+
## Evaluation
|
| 127 |
+
|
| 128 |
+
Greedy decoding on a held-out test split, same prompts for every arm.
|
| 129 |
+
|
| 130 |
+
Test split: two held-out sets scored with the gold item text: an independent set of 206 items taken after the training cut-off (held-out validation period plus later items), and a larger test set of 594 items. Project accuracy is over all items; priority is scored on explicitly prioritised items only. FleetWorker-E4B is scored on the alias versions of these files (sha256 prefixes ef19eeee independent, 220269b7 larger); the base and v1 rows on the internal-name versions.
|
| 131 |
+
Test file fingerprint (sha256 prefix, from the ledger): 5711ab1b436d5f49, d27e10421aa2dbb3.
|
| 132 |
+
|
| 133 |
+
| Arm (model) | n | Project acc., independent set | Project acc., larger test set |
|
| 134 |
+
|---|---|---|---|
|
| 135 |
+
| Bolt base, zero-shot (internal label set) (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.2961 | 0.3855 |
|
| 136 |
+
| Earlier version (v1 adapter) (internal label set) (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.4951 | 0.5875 |
|
| 137 |
+
| FleetWorker-E4B (nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) | 206 items (independent) / 594 items (larger) | 0.5291 | 0.5892 |
|
| 138 |
+
|
| 139 |
+
Run conditions:
|
| 140 |
+
- Bolt base, zero-shot (internal label set): greedy decode, enable_thinking=False, transformers 5.19.0; 1x B200
|
| 141 |
+
- Earlier version (v1 adapter) (internal label set): greedy decode, enable_thinking=False, transformers 5.19.0; 1x B200
|
| 142 |
+
- FleetWorker-E4B: greedy decode, enable_thinking=False, transformers 5.19.0; 1x H100
|
| 143 |
+
|
| 144 |
+
Caveats recorded with these results:
|
| 145 |
+
- Bolt base, zero-shot (internal label set): zero-shot
|
| 146 |
+
- Earlier version (v1 adapter) (internal label set): priority on explicitly-set labels only: v1 predicts P2 for everything (recall P2 1.0, P0/P3 0), so its overall priority score equals the default-label share, not skill.
|
| 147 |
+
- FleetWorker-E4B: Same items as the real-name v4 sets, with project labels replaced by descriptive generic aliases. On items left at the board default it predicts P0 for 120/151.
|
| 148 |
+
|
| 149 |
+
### Priority accuracy on explicitly prioritised items
|
| 150 |
+
|
| 151 |
+
| Variant | n | Independent set (55 items) | Larger test set (243 items) |
|
| 152 |
+
|---|---|---|---|
|
| 153 |
+
| Bolt base, zero-shot (internal label set) | 55 items | 0.3273 | 0.2716 |
|
| 154 |
+
| Earlier version (v1 adapter) (internal label set) | 55 items | 0.3636 | 0.2922 |
|
| 155 |
+
| FleetWorker-E4B | 55 items | 0.6 | 0.5432 |
|
| 156 |
+
| Always predict the most common class | 55 items | 0.3636 | 0.5267 |
|
| 157 |
+
|
| 158 |
+
Measured with small_set = the 55 explicitly prioritised items of the independent set; large_set = the 243 explicitly prioritised items of the larger test set. Items left at the board default are excluded.
|
| 159 |
+
Caveats: Accuracy over explicitly prioritised items only. The 'always predict the most common class' row is the bar a priority suggestion has to beat; on the larger set FleetWorker-E4B clears it by 1.7 points. On items whose priority was never set it answers P0 for 120 of 151, so the priority field is not usable there.
|
| 160 |
+
|
| 161 |
+
### Priority by class (explicitly labelled items only)
|
| 162 |
+
|
| 163 |
+
| Variant | n | P0 recall | P1 recall | P2 recall | P3 recall |
|
| 164 |
+
|---|---|---|---|---|---|
|
| 165 |
+
| FleetWorker-E4B recall | 55 explicit items | 0.5 | 0.4667 | 0.9412 | 0.0 |
|
| 166 |
+
| Earlier version (v1 adapter, internal label set) recall | 55 explicit items | 0.0 | 0.2 | 1.0 | 0.0 |
|
| 167 |
+
|
| 168 |
+
Measured with the 55 explicitly prioritised items of the 206-item independent test set; recall per priority class.
|
| 169 |
+
Caveats: Priority is a suggestion only and is not usable on unprioritised items: on the 151 items left at the board default the model answers P0 for 120, P1 for 27 and P2 for 4. A decode-time prior correction was tried on an earlier version and failed its pre-registered check, so it is not shipped.
|
| 170 |
+
|
| 171 |
+
### Merged weights and GGUF on the independent set (206 items)
|
| 172 |
+
|
| 173 |
+
| Variant | n | Project | Priority (explicit items) |
|
| 174 |
+
|---|---|---|---|
|
| 175 |
+
| Merged BF16 | 206 items | 0.5291 | 0.6 |
|
| 176 |
+
| GGUF Q8_0 | 206 items | 0.5291 | 0.6 |
|
| 177 |
+
| GGUF Q4_K_M (imatrix) | 206 items | 0.5291 | 0.6 |
|
| 178 |
+
| GGUF Q4_K_M-NV | 206 items | 0.5291 | 0.6 |
|
| 179 |
+
|
| 180 |
+
Measured with hardware H100, 1 GPU; independent set; GGUF runs feed the Hugging Face chat-template token ids to llama-server (llama.cpp 344be0a), greedy.
|
| 181 |
+
Caveats: All variants give identical project and explicit-priority accuracy. Leak probe (130 prompts asking for internal identifiers, project-name pattern enforced): 0 hits on merged BF16, Q4_K_M and Q4_K_M-NV; 0 internal names in 1,077 test outputs.
|
| 182 |
+
|
| 183 |
+
## Training
|
| 184 |
+
|
| 185 |
+
Method: LoRA fine-tune of the base model, loss on assistant turns only. Values below are copied from the training record.
|
| 186 |
+
|
| 187 |
+
| Setting | Value |
|
| 188 |
+
|---|---|
|
| 189 |
+
| LoRA rank r | 16 (from training summary) |
|
| 190 |
+
| LoRA alpha | 32 (from training summary) |
|
| 191 |
+
| Learning rate | 0.0001 (from training summary) |
|
| 192 |
+
| Epochs | 2.0 (from training summary) |
|
| 193 |
+
| Target modules | attn+mlp (from training summary) |
|
| 194 |
+
| Gradient accumulation | 8 (from training summary) |
|
| 195 |
+
| Max sequence length | 4096 (from training summary) |
|
| 196 |
+
| Optimizer steps | 1406 (from training summary) |
|
| 197 |
+
| Peak GPU memory (GiB) | 17.53 (from training summary) |
|
| 198 |
+
| Wall time (s) | 5815.2 (from training summary) |
|
| 199 |
+
|
| 200 |
+
## Data
|
| 201 |
+
|
| 202 |
+
Task-board items (title and gold project and priority labels from the board's event log), plus rows built from the board's own rules, plus a smaller set of paraphrases and harder cases written by a larger language model and kept only when code validators confirmed the label was preserved. Internal project names were replaced by descriptive generic aliases (whole-token replacement, 0 residual names, checked by code) before training. Priority labels that were just the board default were masked out of the loss. Train, validation and test splits are disjoint by period and item family. This version was trained from the base weights for two epochs and the checkpoint at step 450 of 1406 was selected on validation loss.
|
| 203 |
+
|
| 204 |
+
The training data is internal and is not released. This repository contains no dataset files.
|
| 205 |
+
|
| 206 |
+
Split sizes (items): train 5621, val 145, test 665, test_indep 206.
|
| 207 |
+
|
| 208 |
+
## Limitations
|
| 209 |
+
|
| 210 |
+
- Priority is not usable on unprioritised items: on items left at the board default it answers P0 for 120 of 151 in the independent set. On explicitly prioritised items it beats the majority-class baseline (0.600 vs 0.364 on 55 items; 0.543 vs 0.527 on 243 items) and never predicts P3. Use the project field only; never show or apply the priority automatically.
|
| 211 |
+
- The base and v1 rows were measured with the internal project names in the prompt and labels; FleetWorker-E4B is scored on the same items with the generic aliases, so the comparison is on the same items but not on identical label strings. A model trained on the internal names reached 0.563 on the independent set; it is not released.
|
| 212 |
+
- Project accuracy is about 0.53 to 0.59: expect roughly 4 to 5 in 10 items to need a correction. 91 of the 166 aliases come from project names without any training items, so only 25 labels are emitted in practice.
|
| 213 |
+
- Training data and the board are internal and not released. The labels are one team's work streams; use the model as a starting point for fine-tuning your own board.
|
| 214 |
+
- A decode-time prior correction was tried on an earlier version and failed its pre-registered check, so it is not shipped.
|
| 215 |
+
- Behavior outside the prompt format above (other output schemas, thinking mode, long item bodies) was not evaluated.
|
| 216 |
+
|
| 217 |
+
## License and attribution
|
| 218 |
+
|
| 219 |
+
- Model materials: governed by the OpenMDW License Agreement, version 1.1 (`LICENSE.OpenMDW-1.1`, https://openmdw.ai/license/1-1/). This repository is a derivative of [nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16) and ships a copy of the agreement.
|
| 220 |
+
- Origin: the NVIDIA base model was post-trained on Google Gemma 4, whose use is governed by the Apache License, Version 2.0 (`LICENSE.Apache-2.0-Gemma`).
|
| 221 |
+
- NVIDIA's governing-terms notice is retained verbatim in `NOTICE.md`, together with the origin chain and a statement of ThakiCloud's modifications.
|
| 222 |
+
- The fine-tuned weights add ThakiCloud's LoRA modifications; they do not change the terms above.
|
adapter/adapter_config.json
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"alora_invocation_tokens": null,
|
| 3 |
+
"alpha_pattern": {},
|
| 4 |
+
"arrow_config": null,
|
| 5 |
+
"auto_mapping": null,
|
| 6 |
+
"base_model_name_or_path": "nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-BF16",
|
| 7 |
+
"bias": "none",
|
| 8 |
+
"corda_config": null,
|
| 9 |
+
"ensure_weight_tying": false,
|
| 10 |
+
"eva_config": null,
|
| 11 |
+
"exclude_modules": null,
|
| 12 |
+
"fan_in_fan_out": false,
|
| 13 |
+
"inference_mode": true,
|
| 14 |
+
"init_lora_weights": true,
|
| 15 |
+
"layer_replication": null,
|
| 16 |
+
"layers_pattern": null,
|
| 17 |
+
"layers_to_transform": null,
|
| 18 |
+
"loftq_config": {},
|
| 19 |
+
"lora_alpha": 32,
|
| 20 |
+
"lora_bias": false,
|
| 21 |
+
"lora_dropout": 0.05,
|
| 22 |
+
"lora_ga_config": null,
|
| 23 |
+
"megatron_config": null,
|
| 24 |
+
"megatron_core": "megatron.core",
|
| 25 |
+
"modules_to_save": null,
|
| 26 |
+
"monteclora_config": null,
|
| 27 |
+
"peft_type": "LORA",
|
| 28 |
+
"peft_version": "0.20.0",
|
| 29 |
+
"qalora_group_size": 16,
|
| 30 |
+
"r": 16,
|
| 31 |
+
"rank_pattern": {},
|
| 32 |
+
"revision": null,
|
| 33 |
+
"target_modules": [
|
| 34 |
+
"model.language_model.layers.26.self_attn.o_proj",
|
| 35 |
+
"model.language_model.layers.4.self_attn.o_proj",
|
| 36 |
+
"model.language_model.layers.16.mlp.up_proj",
|
| 37 |
+
"model.language_model.layers.4.mlp.up_proj",
|
| 38 |
+
"model.language_model.layers.19.mlp.gate_proj",
|
| 39 |
+
"model.language_model.layers.14.mlp.gate_proj",
|
| 40 |
+
"model.language_model.layers.35.self_attn.o_proj",
|
| 41 |
+
"model.language_model.layers.31.mlp.down_proj",
|
| 42 |
+
"model.language_model.layers.25.mlp.down_proj",
|
| 43 |
+
"model.language_model.layers.40.self_attn.o_proj",
|
| 44 |
+
"model.language_model.layers.31.self_attn.q_proj",
|
| 45 |
+
"model.language_model.layers.28.mlp.up_proj",
|
| 46 |
+
"model.language_model.layers.39.mlp.gate_proj",
|
| 47 |
+
"model.language_model.layers.31.mlp.gate_proj",
|
| 48 |
+
"model.language_model.layers.27.mlp.gate_proj",
|
| 49 |
+
"model.language_model.layers.32.mlp.down_proj",
|
| 50 |
+
"model.language_model.layers.15.self_attn.q_proj",
|
| 51 |
+
"model.language_model.layers.29.mlp.gate_proj",
|
| 52 |
+
"model.language_model.layers.3.self_attn.k_proj",
|
| 53 |
+
"model.language_model.layers.40.self_attn.q_proj",
|
| 54 |
+
"model.language_model.layers.7.mlp.up_proj",
|
| 55 |
+
"model.language_model.layers.13.self_attn.v_proj",
|
| 56 |
+
"model.language_model.layers.37.mlp.gate_proj",
|
| 57 |
+
"model.language_model.layers.2.mlp.up_proj",
|
| 58 |
+
"model.language_model.layers.23.self_attn.k_proj",
|
| 59 |
+
"model.language_model.layers.26.mlp.down_proj",
|
| 60 |
+
"model.language_model.layers.2.self_attn.v_proj",
|
| 61 |
+
"model.language_model.layers.22.self_attn.q_proj",
|
| 62 |
+
"model.language_model.layers.32.mlp.gate_proj",
|
| 63 |
+
"model.language_model.layers.22.mlp.gate_proj",
|
| 64 |
+
"model.language_model.layers.32.self_attn.o_proj",
|
| 65 |
+
"model.language_model.layers.30.mlp.down_proj",
|
| 66 |
+
"model.language_model.layers.16.mlp.gate_proj",
|
| 67 |
+
"model.language_model.layers.12.self_attn.q_proj",
|
| 68 |
+
"model.language_model.layers.12.self_attn.o_proj",
|
| 69 |
+
"model.language_model.layers.3.mlp.down_proj",
|
| 70 |
+
"model.language_model.layers.6.mlp.up_proj",
|
| 71 |
+
"model.language_model.layers.36.mlp.down_proj",
|
| 72 |
+
"model.language_model.layers.4.self_attn.v_proj",
|
| 73 |
+
"model.language_model.layers.6.self_attn.q_proj",
|
| 74 |
+
"model.language_model.layers.22.self_attn.o_proj",
|
| 75 |
+
"model.language_model.layers.21.mlp.gate_proj",
|
| 76 |
+
"model.language_model.layers.3.self_attn.o_proj",
|
| 77 |
+
"model.language_model.layers.33.mlp.up_proj",
|
| 78 |
+
"model.language_model.layers.12.mlp.down_proj",
|
| 79 |
+
"model.language_model.layers.11.self_attn.k_proj",
|
| 80 |
+
"model.language_model.layers.15.mlp.up_proj",
|
| 81 |
+
"model.language_model.layers.15.self_attn.k_proj",
|
| 82 |
+
"model.language_model.layers.23.mlp.up_proj",
|
| 83 |
+
"model.language_model.layers.26.mlp.up_proj",
|
| 84 |
+
"model.language_model.layers.30.mlp.gate_proj",
|
| 85 |
+
"model.language_model.layers.0.mlp.gate_proj",
|
| 86 |
+
"model.language_model.layers.30.self_attn.o_proj",
|
| 87 |
+
"model.language_model.layers.17.self_attn.v_proj",
|
| 88 |
+
"model.language_model.layers.34.self_attn.q_proj",
|
| 89 |
+
"model.language_model.layers.41.self_attn.q_proj",
|
| 90 |
+
"model.language_model.layers.37.self_attn.o_proj",
|
| 91 |
+
"model.language_model.layers.9.mlp.up_proj",
|
| 92 |
+
"model.language_model.layers.29.mlp.up_proj",
|
| 93 |
+
"model.language_model.layers.10.mlp.down_proj",
|
| 94 |
+
"model.language_model.layers.21.self_attn.k_proj",
|
| 95 |
+
"model.language_model.layers.14.self_attn.v_proj",
|
| 96 |
+
"model.language_model.layers.0.self_attn.v_proj",
|
| 97 |
+
"model.language_model.layers.15.self_attn.o_proj",
|
| 98 |
+
"model.language_model.layers.8.self_attn.q_proj",
|
| 99 |
+
"model.language_model.layers.26.mlp.gate_proj",
|
| 100 |
+
"model.language_model.layers.39.self_attn.o_proj",
|
| 101 |
+
"model.language_model.layers.17.self_attn.q_proj",
|
| 102 |
+
"model.language_model.layers.39.mlp.up_proj",
|
| 103 |
+
"model.language_model.layers.8.mlp.down_proj",
|
| 104 |
+
"model.language_model.layers.19.self_attn.o_proj",
|
| 105 |
+
"model.language_model.layers.15.mlp.gate_proj",
|
| 106 |
+
"model.language_model.layers.21.self_attn.q_proj",
|
| 107 |
+
"model.language_model.layers.24.self_attn.o_proj",
|
| 108 |
+
"model.language_model.layers.23.mlp.down_proj",
|
| 109 |
+
"model.language_model.layers.17.mlp.up_proj",
|
| 110 |
+
"model.language_model.layers.37.self_attn.q_proj",
|
| 111 |
+
"model.language_model.layers.1.self_attn.v_proj",
|
| 112 |
+
"model.language_model.layers.11.self_attn.o_proj",
|
| 113 |
+
"model.language_model.layers.17.self_attn.o_proj",
|
| 114 |
+
"model.language_model.layers.8.self_attn.v_proj",
|
| 115 |
+
"model.language_model.layers.1.mlp.up_proj",
|
| 116 |
+
"model.language_model.layers.36.mlp.gate_proj",
|
| 117 |
+
"model.language_model.layers.2.mlp.down_proj",
|
| 118 |
+
"model.language_model.layers.13.self_attn.k_proj",
|
| 119 |
+
"model.language_model.layers.38.mlp.up_proj",
|
| 120 |
+
"model.language_model.layers.31.self_attn.o_proj",
|
| 121 |
+
"model.language_model.layers.2.self_attn.k_proj",
|
| 122 |
+
"model.language_model.layers.13.mlp.gate_proj",
|
| 123 |
+
"model.language_model.layers.37.mlp.up_proj",
|
| 124 |
+
"model.language_model.layers.41.mlp.up_proj",
|
| 125 |
+
"model.language_model.layers.21.self_attn.v_proj",
|
| 126 |
+
"model.language_model.layers.22.mlp.up_proj",
|
| 127 |
+
"model.language_model.layers.0.self_attn.o_proj",
|
| 128 |
+
"model.language_model.layers.14.self_attn.k_proj",
|
| 129 |
+
"model.language_model.layers.15.mlp.down_proj",
|
| 130 |
+
"model.language_model.layers.36.self_attn.q_proj",
|
| 131 |
+
"model.language_model.layers.7.self_attn.q_proj",
|
| 132 |
+
"model.language_model.layers.7.mlp.down_proj",
|
| 133 |
+
"model.language_model.layers.9.mlp.down_proj",
|
| 134 |
+
"model.language_model.layers.37.mlp.down_proj",
|
| 135 |
+
"model.language_model.layers.23.self_attn.q_proj",
|
| 136 |
+
"model.language_model.layers.29.self_attn.q_proj",
|
| 137 |
+
"model.language_model.layers.23.self_attn.v_proj",
|
| 138 |
+
"model.language_model.layers.20.mlp.up_proj",
|
| 139 |
+
"model.language_model.layers.0.mlp.down_proj",
|
| 140 |
+
"model.language_model.layers.6.mlp.down_proj",
|
| 141 |
+
"model.language_model.layers.3.mlp.gate_proj",
|
| 142 |
+
"model.language_model.layers.17.self_attn.k_proj",
|
| 143 |
+
"model.language_model.layers.13.self_attn.q_proj",
|
| 144 |
+
"model.language_model.layers.28.self_attn.o_proj",
|
| 145 |
+
"model.language_model.layers.7.self_attn.v_proj",
|
| 146 |
+
"model.language_model.layers.30.mlp.up_proj",
|
| 147 |
+
"model.language_model.layers.35.self_attn.q_proj",
|
| 148 |
+
"model.language_model.layers.8.mlp.up_proj",
|
| 149 |
+
"model.language_model.layers.35.mlp.down_proj",
|
| 150 |
+
"model.language_model.layers.38.self_attn.q_proj",
|
| 151 |
+
"model.language_model.layers.24.self_attn.q_proj",
|
| 152 |
+
"model.language_model.layers.7.self_attn.k_proj",
|
| 153 |
+
"model.language_model.layers.40.mlp.gate_proj",
|
| 154 |
+
"model.language_model.layers.26.self_attn.q_proj",
|
| 155 |
+
"model.language_model.layers.25.self_attn.o_proj",
|
| 156 |
+
"model.language_model.layers.25.mlp.up_proj",
|
| 157 |
+
"model.language_model.layers.18.self_attn.v_proj",
|
| 158 |
+
"model.language_model.layers.25.mlp.gate_proj",
|
| 159 |
+
"model.language_model.layers.21.mlp.down_proj",
|
| 160 |
+
"model.language_model.layers.5.mlp.gate_proj",
|
| 161 |
+
"model.language_model.layers.11.self_attn.q_proj",
|
| 162 |
+
"model.language_model.layers.14.self_attn.o_proj",
|
| 163 |
+
"model.language_model.layers.2.self_attn.q_proj",
|
| 164 |
+
"model.language_model.layers.7.mlp.gate_proj",
|
| 165 |
+
"model.language_model.layers.5.mlp.up_proj",
|
| 166 |
+
"model.language_model.layers.0.self_attn.q_proj",
|
| 167 |
+
"model.language_model.layers.0.self_attn.k_proj",
|
| 168 |
+
"model.language_model.layers.11.mlp.up_proj",
|
| 169 |
+
"model.language_model.layers.35.mlp.gate_proj",
|
| 170 |
+
"model.language_model.layers.5.self_attn.k_proj",
|
| 171 |
+
"model.language_model.layers.11.mlp.gate_proj",
|
| 172 |
+
"model.language_model.layers.27.self_attn.q_proj",
|
| 173 |
+
"model.language_model.layers.18.self_attn.k_proj",
|
| 174 |
+
"model.language_model.layers.8.self_attn.k_proj",
|
| 175 |
+
"model.language_model.layers.4.self_attn.k_proj",
|
| 176 |
+
"model.language_model.layers.10.mlp.gate_proj",
|
| 177 |
+
"model.language_model.layers.11.self_attn.v_proj",
|
| 178 |
+
"model.language_model.layers.27.mlp.up_proj",
|
| 179 |
+
"model.language_model.layers.2.self_attn.o_proj",
|
| 180 |
+
"model.language_model.layers.7.self_attn.o_proj",
|
| 181 |
+
"model.language_model.layers.9.mlp.gate_proj",
|
| 182 |
+
"model.language_model.layers.19.self_attn.q_proj",
|
| 183 |
+
"model.language_model.layers.21.mlp.up_proj",
|
| 184 |
+
"model.language_model.layers.12.mlp.gate_proj",
|
| 185 |
+
"model.language_model.layers.18.mlp.gate_proj",
|
| 186 |
+
"model.language_model.layers.25.self_attn.q_proj",
|
| 187 |
+
"model.language_model.layers.22.mlp.down_proj",
|
| 188 |
+
"model.language_model.layers.30.self_attn.q_proj",
|
| 189 |
+
"model.language_model.layers.6.mlp.gate_proj",
|
| 190 |
+
"model.language_model.layers.21.self_attn.o_proj",
|
| 191 |
+
"model.language_model.layers.34.mlp.up_proj",
|
| 192 |
+
"model.language_model.layers.22.self_attn.v_proj",
|
| 193 |
+
"model.language_model.layers.16.self_attn.v_proj",
|
| 194 |
+
"model.language_model.layers.3.self_attn.q_proj",
|
| 195 |
+
"model.language_model.layers.1.self_attn.o_proj",
|
| 196 |
+
"model.language_model.layers.24.mlp.gate_proj",
|
| 197 |
+
"model.language_model.layers.36.self_attn.o_proj",
|
| 198 |
+
"model.language_model.layers.4.self_attn.q_proj",
|
| 199 |
+
"model.language_model.layers.16.self_attn.q_proj",
|
| 200 |
+
"model.language_model.layers.22.self_attn.k_proj",
|
| 201 |
+
"model.language_model.layers.8.self_attn.o_proj",
|
| 202 |
+
"model.language_model.layers.19.mlp.up_proj",
|
| 203 |
+
"model.language_model.layers.20.mlp.gate_proj",
|
| 204 |
+
"model.language_model.layers.14.self_attn.q_proj",
|
| 205 |
+
"model.language_model.layers.10.self_attn.q_proj",
|
| 206 |
+
"model.language_model.layers.15.self_attn.v_proj",
|
| 207 |
+
"model.language_model.layers.9.self_attn.k_proj",
|
| 208 |
+
"model.language_model.layers.16.mlp.down_proj",
|
| 209 |
+
"model.language_model.layers.41.self_attn.o_proj",
|
| 210 |
+
"model.language_model.layers.27.self_attn.o_proj",
|
| 211 |
+
"model.language_model.layers.29.mlp.down_proj",
|
| 212 |
+
"model.language_model.layers.28.mlp.gate_proj",
|
| 213 |
+
"model.language_model.layers.33.mlp.down_proj",
|
| 214 |
+
"model.language_model.layers.10.self_attn.v_proj",
|
| 215 |
+
"model.language_model.layers.19.self_attn.v_proj",
|
| 216 |
+
"model.language_model.layers.28.mlp.down_proj",
|
| 217 |
+
"model.language_model.layers.39.mlp.down_proj",
|
| 218 |
+
"model.language_model.layers.6.self_attn.k_proj",
|
| 219 |
+
"model.language_model.layers.38.self_attn.o_proj",
|
| 220 |
+
"model.language_model.layers.1.self_attn.q_proj",
|
| 221 |
+
"model.language_model.layers.24.mlp.down_proj",
|
| 222 |
+
"model.language_model.layers.23.mlp.gate_proj",
|
| 223 |
+
"model.language_model.layers.9.self_attn.v_proj",
|
| 224 |
+
"model.language_model.layers.38.mlp.down_proj",
|
| 225 |
+
"model.language_model.layers.34.mlp.down_proj",
|
| 226 |
+
"model.language_model.layers.4.mlp.down_proj",
|
| 227 |
+
"model.language_model.layers.1.mlp.down_proj",
|
| 228 |
+
"model.language_model.layers.12.mlp.up_proj",
|
| 229 |
+
"model.language_model.layers.13.self_attn.o_proj",
|
| 230 |
+
"model.language_model.layers.20.self_attn.v_proj",
|
| 231 |
+
"model.language_model.layers.33.mlp.gate_proj",
|
| 232 |
+
"model.language_model.layers.5.self_attn.o_proj",
|
| 233 |
+
"model.language_model.layers.12.self_attn.v_proj",
|
| 234 |
+
"model.language_model.layers.16.self_attn.k_proj",
|
| 235 |
+
"model.language_model.layers.20.self_attn.o_proj",
|
| 236 |
+
"model.language_model.layers.6.self_attn.o_proj",
|
| 237 |
+
"model.language_model.layers.18.mlp.up_proj",
|
| 238 |
+
"model.language_model.layers.20.self_attn.k_proj",
|
| 239 |
+
"model.language_model.layers.41.mlp.gate_proj",
|
| 240 |
+
"model.language_model.layers.19.mlp.down_proj",
|
| 241 |
+
"model.language_model.layers.13.mlp.down_proj",
|
| 242 |
+
"model.language_model.layers.14.mlp.down_proj",
|
| 243 |
+
"model.language_model.layers.4.mlp.gate_proj",
|
| 244 |
+
"model.language_model.layers.11.mlp.down_proj",
|
| 245 |
+
"model.language_model.layers.20.mlp.down_proj",
|
| 246 |
+
"model.language_model.layers.16.self_attn.o_proj",
|
| 247 |
+
"model.language_model.layers.10.self_attn.o_proj",
|
| 248 |
+
"model.language_model.layers.13.mlp.up_proj",
|
| 249 |
+
"model.language_model.layers.3.mlp.up_proj",
|
| 250 |
+
"model.language_model.layers.18.self_attn.o_proj",
|
| 251 |
+
"model.language_model.layers.10.self_attn.k_proj",
|
| 252 |
+
"model.language_model.layers.17.mlp.gate_proj",
|
| 253 |
+
"model.language_model.layers.34.mlp.gate_proj",
|
| 254 |
+
"model.language_model.layers.35.mlp.up_proj",
|
| 255 |
+
"model.language_model.layers.8.mlp.gate_proj",
|
| 256 |
+
"model.language_model.layers.9.self_attn.o_proj",
|
| 257 |
+
"model.language_model.layers.9.self_attn.q_proj",
|
| 258 |
+
"model.language_model.layers.20.self_attn.q_proj",
|
| 259 |
+
"model.language_model.layers.32.self_attn.q_proj",
|
| 260 |
+
"model.language_model.layers.23.self_attn.o_proj",
|
| 261 |
+
"model.language_model.layers.33.self_attn.o_proj",
|
| 262 |
+
"model.language_model.layers.5.self_attn.q_proj",
|
| 263 |
+
"model.language_model.layers.39.self_attn.q_proj",
|
| 264 |
+
"model.language_model.layers.5.mlp.down_proj",
|
| 265 |
+
"model.language_model.layers.28.self_attn.q_proj",
|
| 266 |
+
"model.language_model.layers.27.mlp.down_proj",
|
| 267 |
+
"model.language_model.layers.29.self_attn.o_proj",
|
| 268 |
+
"model.language_model.layers.1.mlp.gate_proj",
|
| 269 |
+
"model.language_model.layers.17.mlp.down_proj",
|
| 270 |
+
"model.language_model.layers.14.mlp.up_proj",
|
| 271 |
+
"model.language_model.layers.5.self_attn.v_proj",
|
| 272 |
+
"model.language_model.layers.6.self_attn.v_proj",
|
| 273 |
+
"model.language_model.layers.36.mlp.up_proj",
|
| 274 |
+
"model.language_model.layers.31.mlp.up_proj",
|
| 275 |
+
"model.language_model.layers.34.self_attn.o_proj",
|
| 276 |
+
"model.language_model.layers.2.mlp.gate_proj",
|
| 277 |
+
"model.language_model.layers.24.mlp.up_proj",
|
| 278 |
+
"model.language_model.layers.18.mlp.down_proj",
|
| 279 |
+
"model.language_model.layers.40.mlp.up_proj",
|
| 280 |
+
"model.language_model.layers.18.self_attn.q_proj",
|
| 281 |
+
"model.language_model.layers.10.mlp.up_proj",
|
| 282 |
+
"model.language_model.layers.12.self_attn.k_proj",
|
| 283 |
+
"model.language_model.layers.1.self_attn.k_proj",
|
| 284 |
+
"model.language_model.layers.19.self_attn.k_proj",
|
| 285 |
+
"model.language_model.layers.0.mlp.up_proj",
|
| 286 |
+
"model.language_model.layers.32.mlp.up_proj",
|
| 287 |
+
"model.language_model.layers.40.mlp.down_proj",
|
| 288 |
+
"model.language_model.layers.41.mlp.down_proj",
|
| 289 |
+
"model.language_model.layers.38.mlp.gate_proj",
|
| 290 |
+
"model.language_model.layers.3.self_attn.v_proj",
|
| 291 |
+
"model.language_model.layers.33.self_attn.q_proj"
|
| 292 |
+
],
|
| 293 |
+
"target_parameters": null,
|
| 294 |
+
"task_type": "CAUSAL_LM",
|
| 295 |
+
"trainable_token_indices": null,
|
| 296 |
+
"use_bdlora": null,
|
| 297 |
+
"use_dora": false,
|
| 298 |
+
"use_qalora": false,
|
| 299 |
+
"use_rslora": false,
|
| 300 |
+
"velora_config": null
|
| 301 |
+
}
|
adapter/adapter_model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:db3ba1be40dfbc7177c5b8b0d93aa9b781b0cb5d10783c7a9e9f583581f627ff
|
| 3 |
+
size 139602808
|
adapter/chat_template.jinja
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- if conversational_mode | default(false) -%}
|
| 2 |
+
{%- set spoken_instruction = "You are having a spoken conversation with the user. Respond as briefly as possible while still addressing their questions fully." -%}
|
| 3 |
+
{%- if messages and messages[0]['role'] in ['system', 'developer'] -%}
|
| 4 |
+
{%- set spoken = namespace(text='') -%}
|
| 5 |
+
{%- if messages[0]['content'] is string -%}
|
| 6 |
+
{%- set spoken.text = messages[0]['content'] | trim -%}
|
| 7 |
+
{%- else -%}
|
| 8 |
+
{%- for part in messages[0]['content'] -%}
|
| 9 |
+
{%- set spoken.text = spoken.text + (part['text'] | trim) + ' ' -%}
|
| 10 |
+
{%- endfor -%}
|
| 11 |
+
{%- set spoken.text = spoken.text | trim -%}
|
| 12 |
+
{%- endif -%}
|
| 13 |
+
{%- if spoken.text != spoken_instruction -%}
|
| 14 |
+
{%- set spoken.text = (spoken.text + '\n\n' if spoken.text else '') + spoken_instruction -%}
|
| 15 |
+
{%- endif -%}
|
| 16 |
+
{%- set messages = [{'role': messages[0]['role'], 'content': spoken.text}] + messages[1:] -%}
|
| 17 |
+
{%- else -%}
|
| 18 |
+
{%- set messages = [{'role': 'system', 'content': spoken_instruction}] + messages -%}
|
| 19 |
+
{%- endif -%}
|
| 20 |
+
{%- endif -%}
|
| 21 |
+
{#
|
| 22 |
+
Template: Nemotron updated Gemma4 chat template, reasoning-off suffix ablation
|
| 23 |
+
Published: 2026-08-20
|
| 24 |
+
Context: Preserve content ordering before tool-calls while matching the original
|
| 25 |
+
Gemma 4 generation prompt when enable_thinking=false.
|
| 26 |
+
#}
|
| 27 |
+
{%- macro format_parameters(properties, required, filter_keys=false) -%}
|
| 28 |
+
{%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}
|
| 29 |
+
{%- set ns = namespace(found_first=false) -%}
|
| 30 |
+
{%- for key, value in properties | dictsort -%}
|
| 31 |
+
{%- set add_comma = false -%}
|
| 32 |
+
{%- if not filter_keys or key not in standard_keys -%}
|
| 33 |
+
{%- if ns.found_first %},{% endif -%}
|
| 34 |
+
{%- set ns.found_first = true -%}
|
| 35 |
+
{{ key }}:{
|
| 36 |
+
{%- if value['description'] -%}
|
| 37 |
+
description:<|"|>{{ value['description'] }}<|"|>
|
| 38 |
+
{%- set add_comma = true -%}
|
| 39 |
+
{%- endif -%}
|
| 40 |
+
{%- if value['type'] | upper == 'STRING' -%}
|
| 41 |
+
{%- if value['enum'] -%}
|
| 42 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 43 |
+
enum:{{ format_argument(value['enum']) }}
|
| 44 |
+
{%- endif -%}
|
| 45 |
+
{%- elif value['type'] | upper == 'ARRAY' -%}
|
| 46 |
+
{%- if value['items'] is mapping and value['items'] -%}
|
| 47 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 48 |
+
items:{
|
| 49 |
+
{%- set ns_items = namespace(found_first=false) -%}
|
| 50 |
+
{%- for item_key, item_value in value['items'] | dictsort -%}
|
| 51 |
+
{%- if item_value is not none -%}
|
| 52 |
+
{%- if ns_items.found_first %},{% endif -%}
|
| 53 |
+
{%- set ns_items.found_first = true -%}
|
| 54 |
+
{%- if item_key == 'properties' -%}
|
| 55 |
+
properties:{
|
| 56 |
+
{%- if item_value is mapping -%}
|
| 57 |
+
{{- format_parameters(item_value, value['items']['required'] | default([])) -}}
|
| 58 |
+
{%- endif -%}
|
| 59 |
+
}
|
| 60 |
+
{%- elif item_key == 'required' -%}
|
| 61 |
+
required:[
|
| 62 |
+
{%- for req_item in item_value -%}
|
| 63 |
+
<|"|>{{- req_item -}}<|"|>
|
| 64 |
+
{%- if not loop.last %},{% endif -%}
|
| 65 |
+
{%- endfor -%}
|
| 66 |
+
]
|
| 67 |
+
{%- elif item_key == 'type' -%}
|
| 68 |
+
{%- if item_value is string -%}
|
| 69 |
+
type:{{ format_argument(item_value | upper) }}
|
| 70 |
+
{%- else -%}
|
| 71 |
+
type:{{ format_argument(item_value | map('upper') | list) }}
|
| 72 |
+
{%- endif -%}
|
| 73 |
+
{%- else -%}
|
| 74 |
+
{{ item_key }}:{{ format_argument(item_value) }}
|
| 75 |
+
{%- endif -%}
|
| 76 |
+
{%- endif -%}
|
| 77 |
+
{%- endfor -%}
|
| 78 |
+
}
|
| 79 |
+
{%- endif -%}
|
| 80 |
+
{%- endif -%}
|
| 81 |
+
{%- if value['nullable'] %}
|
| 82 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 83 |
+
nullable:true
|
| 84 |
+
{%- endif -%}
|
| 85 |
+
{%- if value['type'] | upper == 'OBJECT' -%}
|
| 86 |
+
{%- if value['properties'] is defined and value['properties'] is mapping -%}
|
| 87 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 88 |
+
properties:{
|
| 89 |
+
{{- format_parameters(value['properties'], value['required'] | default([])) -}}
|
| 90 |
+
}
|
| 91 |
+
{%- elif value is mapping -%}
|
| 92 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 93 |
+
properties:{
|
| 94 |
+
{{- format_parameters(value, value['required'] | default([]), filter_keys=true) -}}
|
| 95 |
+
}
|
| 96 |
+
{%- endif -%}
|
| 97 |
+
{%- if value['required'] -%}
|
| 98 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 99 |
+
required:[
|
| 100 |
+
{%- for item in value['required'] | default([]) -%}
|
| 101 |
+
<|"|>{{- item -}}<|"|>
|
| 102 |
+
{%- if not loop.last %},{% endif -%}
|
| 103 |
+
{%- endfor -%}
|
| 104 |
+
]
|
| 105 |
+
{%- endif -%}
|
| 106 |
+
{%- endif -%}
|
| 107 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 108 |
+
type:<|"|>{{ value['type'] | upper }}<|"|>}
|
| 109 |
+
{%- endif -%}
|
| 110 |
+
{%- endfor -%}
|
| 111 |
+
{%- endmacro -%}
|
| 112 |
+
{%- macro format_function_declaration(tool_data) -%}
|
| 113 |
+
declaration:{{- tool_data['function']['name'] -}}{description:<|"|>{{- tool_data['function']['description'] -}}<|"|>
|
| 114 |
+
{%- set params = tool_data['function']['parameters'] -%}
|
| 115 |
+
{%- if params -%}
|
| 116 |
+
,parameters:{
|
| 117 |
+
{%- if params['properties'] -%}
|
| 118 |
+
properties:{ {{- format_parameters(params['properties'], params['required']) -}} },
|
| 119 |
+
{%- endif -%}
|
| 120 |
+
{%- if params['required'] -%}
|
| 121 |
+
required:[
|
| 122 |
+
{%- for item in params['required'] -%}
|
| 123 |
+
<|"|>{{- item -}}<|"|>
|
| 124 |
+
{{- ',' if not loop.last -}}
|
| 125 |
+
{%- endfor -%}
|
| 126 |
+
],
|
| 127 |
+
{%- endif -%}
|
| 128 |
+
{%- if params['type'] -%}
|
| 129 |
+
type:<|"|>{{- params['type'] | upper -}}<|"|>}
|
| 130 |
+
{%- endif -%}
|
| 131 |
+
{%- endif -%}
|
| 132 |
+
{%- if 'response' in tool_data['function'] -%}
|
| 133 |
+
{%- set response_declaration = tool_data['function']['response'] -%}
|
| 134 |
+
,response:{
|
| 135 |
+
{%- if response_declaration['description'] -%}
|
| 136 |
+
description:<|"|>{{- response_declaration['description'] -}}<|"|>,
|
| 137 |
+
{%- endif -%}
|
| 138 |
+
{%- if response_declaration['type'] | upper == 'OBJECT' -%}
|
| 139 |
+
type:<|"|>{{- response_declaration['type'] | upper -}}<|"|>}
|
| 140 |
+
{%- endif -%}
|
| 141 |
+
{%- endif -%}
|
| 142 |
+
}
|
| 143 |
+
{%- endmacro -%}
|
| 144 |
+
{%- macro format_argument(argument, escape_keys=True) -%}
|
| 145 |
+
{%- if argument is none -%}
|
| 146 |
+
{{- 'null' -}}
|
| 147 |
+
{%- elif argument is string -%}
|
| 148 |
+
{{- '<|"|>' + argument + '<|"|>' -}}
|
| 149 |
+
{%- elif argument is boolean -%}
|
| 150 |
+
{{- 'true' if argument else 'false' -}}
|
| 151 |
+
{%- elif argument is mapping -%}
|
| 152 |
+
{{- '{' -}}
|
| 153 |
+
{%- set ns = namespace(found_first=false) -%}
|
| 154 |
+
{%- for key, value in argument | dictsort -%}
|
| 155 |
+
{%- if ns.found_first %},{% endif -%}
|
| 156 |
+
{%- set ns.found_first = true -%}
|
| 157 |
+
{%- if escape_keys -%}
|
| 158 |
+
{{- '<|"|>' + key + '<|"|>' -}}
|
| 159 |
+
{%- else -%}
|
| 160 |
+
{{- key -}}
|
| 161 |
+
{%- endif -%}
|
| 162 |
+
:{{- format_argument(value, escape_keys=escape_keys) -}}
|
| 163 |
+
{%- endfor -%}
|
| 164 |
+
{{- '}' -}}
|
| 165 |
+
{%- elif argument is sequence -%}
|
| 166 |
+
{{- '[' -}}
|
| 167 |
+
{%- for item in argument -%}
|
| 168 |
+
{{- format_argument(item, escape_keys=escape_keys) -}}
|
| 169 |
+
{%- if not loop.last %},{% endif -%}
|
| 170 |
+
{%- endfor -%}
|
| 171 |
+
{{- ']' -}}
|
| 172 |
+
{%- else -%}
|
| 173 |
+
{{- argument -}}
|
| 174 |
+
{%- endif -%}
|
| 175 |
+
{%- endmacro -%}
|
| 176 |
+
{%- macro strip_thinking(text) -%}
|
| 177 |
+
{%- set ns = namespace(result='') -%}
|
| 178 |
+
{%- for part in text.split('<channel|>') -%}
|
| 179 |
+
{%- if '<|channel>' in part -%}
|
| 180 |
+
{%- set ns.result = ns.result + part.split('<|channel>')[0] -%}
|
| 181 |
+
{%- else -%}
|
| 182 |
+
{%- set ns.result = ns.result + part -%}
|
| 183 |
+
{%- endif -%}
|
| 184 |
+
{%- endfor -%}
|
| 185 |
+
{{- ns.result | trim -}}
|
| 186 |
+
{%- endmacro -%}
|
| 187 |
+
|
| 188 |
+
{%- macro format_tool_response_block(tool_name, response) -%}
|
| 189 |
+
{{- '<|tool_response>' -}}
|
| 190 |
+
{%- if response is mapping -%}
|
| 191 |
+
{{- 'response:' + tool_name + '{' -}}
|
| 192 |
+
{%- for key, value in response | dictsort -%}
|
| 193 |
+
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
| 194 |
+
{%- if not loop.last %},{% endif -%}
|
| 195 |
+
{%- endfor -%}
|
| 196 |
+
{{- '}' -}}
|
| 197 |
+
{%- else -%}
|
| 198 |
+
{{- 'response:' + tool_name + '{value:' + format_argument(response, escape_keys=False) + '}' -}}
|
| 199 |
+
{%- endif -%}
|
| 200 |
+
{{- '<tool_response|>' -}}
|
| 201 |
+
{%- endmacro -%}
|
| 202 |
+
|
| 203 |
+
{#- ===== SETUP ===== -#}
|
| 204 |
+
{%- set ns = namespace(prev_message_type=None, prev_non_tool_role=None) -%}
|
| 205 |
+
{%- set loop_messages = messages -%}
|
| 206 |
+
{%- set enable_thinking = enable_thinking | default(false) -%}
|
| 207 |
+
{%- set preserve_thinking = preserve_thinking | default(false) -%}
|
| 208 |
+
{{- bos_token -}}
|
| 209 |
+
{#- Handle System/Tool Definitions Block -#}
|
| 210 |
+
{%- if enable_thinking or tools or (messages and messages[0]['role'] in ['system', 'developer']) -%}
|
| 211 |
+
{{- '<|turn>system\n' -}}
|
| 212 |
+
{#- Inject Thinking token at the very top of the FIRST system turn -#}
|
| 213 |
+
{%- if enable_thinking -%}
|
| 214 |
+
{{- '<|think|>\n' -}}
|
| 215 |
+
{%- set ns.prev_message_type = 'think' -%}
|
| 216 |
+
{%- endif -%}
|
| 217 |
+
{%- if messages and messages[0]['role'] in ['system', 'developer'] -%}
|
| 218 |
+
{%- if messages[0]['content'] is string -%}
|
| 219 |
+
{{- messages[0]['content'] | trim -}}
|
| 220 |
+
{%- elif messages[0]['content'] is sequence -%}
|
| 221 |
+
{%- for item in messages[0]['content'] -%}
|
| 222 |
+
{{- item['text'] | trim + ' '-}}
|
| 223 |
+
{%- endfor -%}
|
| 224 |
+
{%- endif -%}
|
| 225 |
+
{%- set loop_messages = messages[1:] -%}
|
| 226 |
+
{%- endif -%}
|
| 227 |
+
{%- if tools -%}
|
| 228 |
+
{%- for tool in tools %}
|
| 229 |
+
{{- '<|tool>' -}}
|
| 230 |
+
{{- format_function_declaration(tool) | trim -}}
|
| 231 |
+
{{- '<tool|>' -}}
|
| 232 |
+
{%- endfor %}
|
| 233 |
+
{%- set ns.prev_message_type = 'tool' -%}
|
| 234 |
+
{%- endif -%}
|
| 235 |
+
{{- '<turn|>\n' -}}
|
| 236 |
+
{%- endif %}
|
| 237 |
+
|
| 238 |
+
{#- Pre-scan: find last user message index for reasoning guard -#}
|
| 239 |
+
{%- set ns_turn = namespace(last_user_idx=-1) -%}
|
| 240 |
+
{%- for i in range(loop_messages | length) -%}
|
| 241 |
+
{%- if loop_messages[i]['role'] == 'user' -%}
|
| 242 |
+
{%- set ns_turn.last_user_idx = i -%}
|
| 243 |
+
{%- endif -%}
|
| 244 |
+
{%- endfor -%}
|
| 245 |
+
|
| 246 |
+
{#- Loop through messages -#}
|
| 247 |
+
{%- for message in loop_messages -%}
|
| 248 |
+
{%- if message['role'] != 'tool' -%}
|
| 249 |
+
{%- set ns.prev_message_type = None -%}
|
| 250 |
+
{%- set role = 'model' if message['role'] == 'assistant' else message['role'] -%}
|
| 251 |
+
{#- Detect continuation using tracked state — O(1) instead of O(n) backward scan -#}
|
| 252 |
+
{%- set continue_same_model_turn = (role == 'model' and ns.prev_non_tool_role == 'assistant') -%}
|
| 253 |
+
{%- if not continue_same_model_turn -%}
|
| 254 |
+
{{- '<|turn>' + role + '\n' }}
|
| 255 |
+
|
| 256 |
+
{%- endif -%}
|
| 257 |
+
|
| 258 |
+
{#- Render reasoning/reasoning_content as thinking channel -#}
|
| 259 |
+
{%- set thinking_text = message.get('reasoning') or message.get('reasoning_content') -%}
|
| 260 |
+
{%- set thinking_gate = (loop.index0 > ns_turn.last_user_idx) or (preserve_thinking and message.get('tool_calls')) -%}
|
| 261 |
+
{%- if thinking_text and thinking_gate -%}
|
| 262 |
+
{{- '<|channel>thought\n' + thinking_text + '\n<channel|>' -}}
|
| 263 |
+
{%- endif -%}
|
| 264 |
+
|
| 265 |
+
{%- set captured_content -%}
|
| 266 |
+
{%- if message.get('content') is string -%}
|
| 267 |
+
{%- if role == 'model' -%}
|
| 268 |
+
{{- strip_thinking(message['content']) -}}
|
| 269 |
+
{%- else -%}
|
| 270 |
+
{{- message['content'] | trim -}}
|
| 271 |
+
{%- endif -%}
|
| 272 |
+
{%- elif message.get('content') is sequence -%}
|
| 273 |
+
{%- for item in message['content'] -%}
|
| 274 |
+
{%- if item.get('type') == 'text' -%}
|
| 275 |
+
{%- if role == 'model' -%}
|
| 276 |
+
{{- strip_thinking(item['text']) -}}
|
| 277 |
+
{%- else -%}
|
| 278 |
+
{{- item['text'] | trim -}}
|
| 279 |
+
{%- endif -%}
|
| 280 |
+
{%- elif item.get('type') in ['image', 'image_url'] -%}
|
| 281 |
+
{{- '<|image|>' -}}
|
| 282 |
+
{%- elif item.get('type') in ['audio', 'input_audio'] -%}
|
| 283 |
+
{{- '<|audio|>' -}}
|
| 284 |
+
{%- elif item.get('type') == 'video' -%}
|
| 285 |
+
{{- '<|video|>' -}}
|
| 286 |
+
{%- endif -%}
|
| 287 |
+
{%- endfor -%}
|
| 288 |
+
{%- endif -%}
|
| 289 |
+
{%- endset -%}
|
| 290 |
+
|
| 291 |
+
{#- The sole intentional behavior change from HF main: preserve
|
| 292 |
+
OpenAI assistant content before its tool calls. -#}
|
| 293 |
+
{%- if role == 'model' and message.get('tool_calls') -%}
|
| 294 |
+
{{- captured_content -}}
|
| 295 |
+
{%- endif -%}
|
| 296 |
+
|
| 297 |
+
{%- if message.get('tool_calls') -%}
|
| 298 |
+
{%- for tool_call in message.get('tool_calls') -%}
|
| 299 |
+
{%- set function = tool_call['function'] -%}
|
| 300 |
+
{{- '<|tool_call>call:' + function['name'] + '{' -}}
|
| 301 |
+
{%- if function['arguments'] is mapping -%}
|
| 302 |
+
{%- set ns_args = namespace(found_first=false) -%}
|
| 303 |
+
{%- for key, value in function['arguments'] | dictsort -%}
|
| 304 |
+
{%- if ns_args.found_first %},{% endif -%}
|
| 305 |
+
{%- set ns_args.found_first = true -%}
|
| 306 |
+
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
| 307 |
+
{%- endfor -%}
|
| 308 |
+
{%- elif function['arguments'] is none -%}
|
| 309 |
+
{%- else -%}
|
| 310 |
+
{{- raise_exception(
|
| 311 |
+
"chat_template: tool_calls[].function.arguments must be a "
|
| 312 |
+
"JSON object (mapping), not a string. Deserialize arguments "
|
| 313 |
+
"before passing to the template."
|
| 314 |
+
) -}}
|
| 315 |
+
{%- endif -%}
|
| 316 |
+
{{- '}<tool_call|>' -}}
|
| 317 |
+
{%- endfor -%}
|
| 318 |
+
{%- set ns.prev_message_type = 'tool_call' -%}
|
| 319 |
+
{%- endif -%}
|
| 320 |
+
|
| 321 |
+
{%- set ns_tr_out = namespace(flag=false) -%}
|
| 322 |
+
{%- if message.get('tool_responses') -%}
|
| 323 |
+
{#- Legacy: tool_responses embedded on the assistant message (Google/Gemma native) -#}
|
| 324 |
+
{%- for tool_response in message.get('tool_responses') -%}
|
| 325 |
+
{{- format_tool_response_block(tool_response['name'] | default('unknown', true), tool_response['response']) -}}
|
| 326 |
+
{%- set ns_tr_out.flag = true -%}
|
| 327 |
+
{%- set ns.prev_message_type = 'tool_response' -%}
|
| 328 |
+
{%- endfor -%}
|
| 329 |
+
{%- elif message.get('tool_calls') -%}
|
| 330 |
+
{#- OpenAI Chat Completions: forward-scan consecutive role:tool messages -#}
|
| 331 |
+
{%- set ns_tool_scan = namespace(stopped=false) -%}
|
| 332 |
+
{%- for k in range(loop.index0 + 1, loop_messages | length) -%}
|
| 333 |
+
{%- if ns_tool_scan.stopped -%}
|
| 334 |
+
{%- elif loop_messages[k]['role'] != 'tool' -%}
|
| 335 |
+
{%- set ns_tool_scan.stopped = true -%}
|
| 336 |
+
{%- else -%}
|
| 337 |
+
{%- set follow = loop_messages[k] -%}
|
| 338 |
+
{#- Resolve tool_call_id to function name -#}
|
| 339 |
+
{%- set ns_tname = namespace(name=follow.get('name') or 'unknown') -%}
|
| 340 |
+
{%- for tc in message.get('tool_calls') -%}
|
| 341 |
+
{%- if tc.get('id') == follow.get('tool_call_id') -%}
|
| 342 |
+
{%- set ns_tname.name = tc['function']['name'] -%}
|
| 343 |
+
{%- endif -%}
|
| 344 |
+
{%- endfor -%}
|
| 345 |
+
{#- Handle content as string or content-parts array -#}
|
| 346 |
+
{%- set tool_body = follow.get('content') -%}
|
| 347 |
+
{%- if tool_body is string -%}
|
| 348 |
+
{{- format_tool_response_block(ns_tname.name, tool_body) -}}
|
| 349 |
+
{%- elif tool_body is sequence and tool_body is not string -%}
|
| 350 |
+
{%- set ns_txt = namespace(s='') -%}
|
| 351 |
+
{%- for part in tool_body -%}
|
| 352 |
+
{%- if part.get('type') == 'text' -%}
|
| 353 |
+
{%- set ns_txt.s = ns_txt.s + (part.get('text') | default('')) -%}
|
| 354 |
+
{%- endif -%}
|
| 355 |
+
{%- endfor -%}
|
| 356 |
+
{{- format_tool_response_block(ns_tname.name, ns_txt.s) -}}
|
| 357 |
+
{%- for part in tool_body -%}
|
| 358 |
+
{%- if part.get('type') in ['image', 'image_url'] -%}
|
| 359 |
+
{{- '<|image|>' -}}
|
| 360 |
+
{%- elif part.get('type') in ['audio', 'input_audio'] -%}
|
| 361 |
+
{{- '<|audio|>' -}}
|
| 362 |
+
{%- elif part.get('type') == 'video' -%}
|
| 363 |
+
{{- '<|video|>' -}}
|
| 364 |
+
{%- endif -%}
|
| 365 |
+
{%- endfor -%}
|
| 366 |
+
{%- else -%}
|
| 367 |
+
{{- format_tool_response_block(ns_tname.name, tool_body) -}}
|
| 368 |
+
{%- endif -%}
|
| 369 |
+
{%- set ns_tr_out.flag = true -%}
|
| 370 |
+
{%- set ns.prev_message_type = 'tool_response' -%}
|
| 371 |
+
{%- endif -%}
|
| 372 |
+
{%- endfor -%}
|
| 373 |
+
{%- endif -%}
|
| 374 |
+
|
| 375 |
+
{%- if not (role == 'model' and message.get('tool_calls')) -%}
|
| 376 |
+
{{- captured_content -}}
|
| 377 |
+
{%- endif -%}
|
| 378 |
+
{%- set has_content = captured_content | trim | length > 0 -%}
|
| 379 |
+
|
| 380 |
+
{#- Forward-scan: find next non-tool message role for continuation detection -#}
|
| 381 |
+
{%- set next_nt = namespace(role=None, found=false) -%}
|
| 382 |
+
{%- for j in range(loop.index0 + 1, loop_messages | length) -%}
|
| 383 |
+
{%- if not next_nt.found -%}
|
| 384 |
+
{%- if loop_messages[j]['role'] != 'tool' -%}
|
| 385 |
+
{%- set next_nt.role = loop_messages[j]['role'] -%}
|
| 386 |
+
{%- set next_nt.found = true -%}
|
| 387 |
+
{%- endif -%}
|
| 388 |
+
{%- endif -%}
|
| 389 |
+
{%- endfor -%}
|
| 390 |
+
|
| 391 |
+
{%- set continues_into_next = (
|
| 392 |
+
role == 'model'
|
| 393 |
+
and next_nt.role == 'assistant'
|
| 394 |
+
and (not message.get('tool_calls') or ns_tr_out.flag)
|
| 395 |
+
) -%}
|
| 396 |
+
|
| 397 |
+
{%- if ns.prev_message_type == 'tool_call' and not ns_tr_out.flag -%}
|
| 398 |
+
{{- '<|tool_response>' -}}
|
| 399 |
+
{%- elif continues_into_next -%}
|
| 400 |
+
{%- elif not (ns_tr_out.flag and not has_content and not next_nt.found) -%}
|
| 401 |
+
{{- '<turn|>\n' -}}
|
| 402 |
+
{%- endif -%}
|
| 403 |
+
|
| 404 |
+
{#- Track previous non-tool role for next iteration (avoids O(n) backward scan) -#}
|
| 405 |
+
{%- set ns.prev_non_tool_role = message['role'] -%}
|
| 406 |
+
{%- endif -%}
|
| 407 |
+
{%- endfor -%}
|
| 408 |
+
|
| 409 |
+
{%- if add_generation_prompt -%}
|
| 410 |
+
{%- if ns.prev_message_type != 'tool_response' and ns.prev_message_type != 'tool_call' -%}
|
| 411 |
+
{{- '<|turn>model\n' -}}
|
| 412 |
+
{%- elif ns.prev_message_type == 'tool_response' and enable_thinking -%}
|
| 413 |
+
{{- '<|channel>thought\n' -}}
|
| 414 |
+
{%- endif -%}
|
| 415 |
+
{%- endif -%}
|
adapter/tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cc8d3a0ce36466ccc1278bf987df5f71db1719b9ca6b4118264f45cb627bfe0f
|
| 3 |
+
size 32169626
|
adapter/tokenizer_config.json
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"audio_token": "<|audio|>",
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"boa_token": "<|audio>",
|
| 5 |
+
"boi_token": "<|image>",
|
| 6 |
+
"bos_token": "<bos>",
|
| 7 |
+
"eoa_token": "<audio|>",
|
| 8 |
+
"eoc_token": "<channel|>",
|
| 9 |
+
"eoi_token": "<image|>",
|
| 10 |
+
"eos_token": "<eos>",
|
| 11 |
+
"eot_token": "<turn|>",
|
| 12 |
+
"escape_token": "<|\"|>",
|
| 13 |
+
"etc_token": "<tool_call|>",
|
| 14 |
+
"etd_token": "<tool|>",
|
| 15 |
+
"etr_token": "<tool_response|>",
|
| 16 |
+
"extra_special_tokens": [
|
| 17 |
+
"<|video|>"
|
| 18 |
+
],
|
| 19 |
+
"image_token": "<|image|>",
|
| 20 |
+
"is_local": true,
|
| 21 |
+
"local_files_only": true,
|
| 22 |
+
"mask_token": "<mask>",
|
| 23 |
+
"model_max_length": 1000000000000000019884624838656,
|
| 24 |
+
"model_specific_special_tokens": {
|
| 25 |
+
"audio_token": "<|audio|>",
|
| 26 |
+
"boa_token": "<|audio>",
|
| 27 |
+
"boi_token": "<|image>",
|
| 28 |
+
"eoa_token": "<audio|>",
|
| 29 |
+
"eoc_token": "<channel|>",
|
| 30 |
+
"eoi_token": "<image|>",
|
| 31 |
+
"eot_token": "<turn|>",
|
| 32 |
+
"escape_token": "<|\"|>",
|
| 33 |
+
"etc_token": "<tool_call|>",
|
| 34 |
+
"etd_token": "<tool|>",
|
| 35 |
+
"etr_token": "<tool_response|>",
|
| 36 |
+
"image_token": "<|image|>",
|
| 37 |
+
"soc_token": "<|channel>",
|
| 38 |
+
"sot_token": "<|turn>",
|
| 39 |
+
"stc_token": "<|tool_call>",
|
| 40 |
+
"std_token": "<|tool>",
|
| 41 |
+
"str_token": "<|tool_response>",
|
| 42 |
+
"think_token": "<|think|>"
|
| 43 |
+
},
|
| 44 |
+
"pad_token": "<pad>",
|
| 45 |
+
"padding_side": "left",
|
| 46 |
+
"processor_class": "Gemma4Processor",
|
| 47 |
+
"response_schema": {
|
| 48 |
+
"properties": {
|
| 49 |
+
"content": {
|
| 50 |
+
"type": "string"
|
| 51 |
+
},
|
| 52 |
+
"role": {
|
| 53 |
+
"const": "assistant"
|
| 54 |
+
},
|
| 55 |
+
"thinking": {
|
| 56 |
+
"type": "string"
|
| 57 |
+
},
|
| 58 |
+
"tool_calls": {
|
| 59 |
+
"items": {
|
| 60 |
+
"properties": {
|
| 61 |
+
"function": {
|
| 62 |
+
"properties": {
|
| 63 |
+
"arguments": {
|
| 64 |
+
"additionalProperties": {},
|
| 65 |
+
"type": "object",
|
| 66 |
+
"x-parser": "gemma4-tool-call"
|
| 67 |
+
},
|
| 68 |
+
"name": {
|
| 69 |
+
"type": "string"
|
| 70 |
+
}
|
| 71 |
+
},
|
| 72 |
+
"type": "object",
|
| 73 |
+
"x-regex": "call\\:(?P<name>\\w+)(?P<arguments>\\{.*\\})"
|
| 74 |
+
},
|
| 75 |
+
"type": {
|
| 76 |
+
"const": "function"
|
| 77 |
+
}
|
| 78 |
+
},
|
| 79 |
+
"type": "object"
|
| 80 |
+
},
|
| 81 |
+
"type": "array",
|
| 82 |
+
"x-regex-iterator": "<\\|tool_call>(.*?)<tool_call\\|>"
|
| 83 |
+
}
|
| 84 |
+
},
|
| 85 |
+
"type": "object",
|
| 86 |
+
"x-regex": "(\\<\\|channel\\>thought\\n(?P<thinking>.*?)\\<channel\\|\\>)?(?P<tool_calls>\\<\\|tool_call\\>.*\\<tool_call\\|\\>)?(?P<content>(?:(?!\\<turn\\|\\>)(?!\\<\\|tool_response\\>).)+)?(?:\\<turn\\|\\>|\\<\\|tool_response\\>)?"
|
| 87 |
+
},
|
| 88 |
+
"response_template": {
|
| 89 |
+
"defaults": {
|
| 90 |
+
"role": "assistant"
|
| 91 |
+
},
|
| 92 |
+
"fields": {
|
| 93 |
+
"content": {
|
| 94 |
+
"close": [
|
| 95 |
+
"<turn|>",
|
| 96 |
+
"<|tool_response>",
|
| 97 |
+
"<eos>"
|
| 98 |
+
],
|
| 99 |
+
"content": "text"
|
| 100 |
+
},
|
| 101 |
+
"thinking": {
|
| 102 |
+
"close": "<channel|>",
|
| 103 |
+
"content": "text",
|
| 104 |
+
"open": "<|channel>thought\n"
|
| 105 |
+
},
|
| 106 |
+
"tool_calls": {
|
| 107 |
+
"close": "<tool_call|>",
|
| 108 |
+
"content": "json",
|
| 109 |
+
"content_args": {
|
| 110 |
+
"string_delims": [
|
| 111 |
+
[
|
| 112 |
+
"<|\"|>",
|
| 113 |
+
"<|\"|>"
|
| 114 |
+
]
|
| 115 |
+
],
|
| 116 |
+
"unquoted_keys": true
|
| 117 |
+
},
|
| 118 |
+
"open_pattern": "<\\|tool_call>call:(?P<name>\\w+)",
|
| 119 |
+
"repeats": true,
|
| 120 |
+
"transform": {
|
| 121 |
+
"function": {
|
| 122 |
+
"arguments": "{content}",
|
| 123 |
+
"name": "{name}"
|
| 124 |
+
},
|
| 125 |
+
"type": "function"
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
},
|
| 129 |
+
"start_anchor": [
|
| 130 |
+
"<|turn>model\n",
|
| 131 |
+
"<tool_response|>"
|
| 132 |
+
]
|
| 133 |
+
},
|
| 134 |
+
"soc_token": "<|channel>",
|
| 135 |
+
"sot_token": "<|turn>",
|
| 136 |
+
"stc_token": "<|tool_call>",
|
| 137 |
+
"std_token": "<|tool>",
|
| 138 |
+
"str_token": "<|tool_response>",
|
| 139 |
+
"think_token": "<|think|>",
|
| 140 |
+
"tokenizer_class": "GemmaTokenizer",
|
| 141 |
+
"unk_token": "<unk>"
|
| 142 |
+
}
|
bias.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| Field | Response |
|
| 2 |
+
| :---- | :---- |
|
| 3 |
+
| Participation considerations from adversely impacted groups [protected classes](https://www.senate.ca.gov/content/protected-classes) in model design and testing: | None |
|
| 4 |
+
| Bias Metric (If Measured): | [BBQ Accuracy Scores in Ambiguous Contexts](https://github.com/nyu-mll/BBQ/) |
|
| 5 |
+
| Which characteristic (feature) show(s) the greatest difference in performance?: | The model shows high variance in the characteristics when it is used with a high temperature. |
|
| 6 |
+
| Measures taken to mitigate against unwanted bias: | Supervised Fine-Tuning (SFT) and Reinforcement Learning from Human Feedback (RLHF) employed to calibrate the model’s reasoning capabilities to maintain logical consistency and appropriate complexity when interacting with or interpreting data from diverse age demographics. |
|
| 7 |
+
| If using internal data, description of methods implemented in data acquisition or processing, if any, to address the prevalence of identifiable biases in the training, testing, and validation data: | The training datasets contain a large amount of synthetic data generated by LLMs. We manually curated prompts. |
|
| 8 |
+
| Tools used to assess statistical imbalances and highlight patterns that may introduce bias into AI models: | [BBQ](https://github.com/nyu-mll/BBQ/) |
|
| 9 |
+
| Tools used to assess statistical imbalances and highlight patterns that may introduce bias into AI models: | These datasets, such as web-scraped finance reasoning data derived from SEC EDGAR filings, science and math problem datasets, OpenResearcher/source-document datasets, Common Crawl, CC-News, Wikimedia, and long-context document datasets, do not collectively or exhaustively represent all demographic groups (and proportionally therein). For instance, these datasets do not contain explicit mentions of demographic classes such as age, gender, or ethnicity in approximately 97% to 99.9% of finance reasoning samples and in over 85% of samples across the broader assessed datasets. In the subset where such terms are present, these datasets contain notable representational skews. For example, ethnicity mentions are often dominated by Middle Eastern contexts (found in finance documents) or "White," "Two or more," and "Black or African American" as the most frequent ethnic identifiers, while references categorized as male-only significantly outnumber those categorized as female-only. Furthermore, gender is explicitly mentioned in approximately 12% of samples across the broader dataset assessment, yet in only 0.9% of finance-specific samples. Dataset-level results vary by source type, with long-context/source-document datasets containing higher explicit demographic mention rates compared to certain web-scraped sources. To mitigate these imbalances, we recommend considering evaluation techniques such as bias audits, fine-tuning with demographically balanced datasets, and mitigation strategies such as counterfactual data augmentation to align with the desired model behavior. This evaluation used a 3,000-sample subset per dataset, identified as the optimal threshold for maximizing embedder accuracy. |
|
| 10 |
+
| Unwanted Bias Testing: | Constrained to English-language inputs. Multi-lingual parity is not currently claimed or guaranteed. |
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- if conversational_mode | default(false) -%}
|
| 2 |
+
{%- set spoken_instruction = "You are having a spoken conversation with the user. Respond as briefly as possible while still addressing their questions fully." -%}
|
| 3 |
+
{%- if messages and messages[0]['role'] in ['system', 'developer'] -%}
|
| 4 |
+
{%- set spoken = namespace(text='') -%}
|
| 5 |
+
{%- if messages[0]['content'] is string -%}
|
| 6 |
+
{%- set spoken.text = messages[0]['content'] | trim -%}
|
| 7 |
+
{%- else -%}
|
| 8 |
+
{%- for part in messages[0]['content'] -%}
|
| 9 |
+
{%- set spoken.text = spoken.text + (part['text'] | trim) + ' ' -%}
|
| 10 |
+
{%- endfor -%}
|
| 11 |
+
{%- set spoken.text = spoken.text | trim -%}
|
| 12 |
+
{%- endif -%}
|
| 13 |
+
{%- if spoken.text != spoken_instruction -%}
|
| 14 |
+
{%- set spoken.text = (spoken.text + '\n\n' if spoken.text else '') + spoken_instruction -%}
|
| 15 |
+
{%- endif -%}
|
| 16 |
+
{%- set messages = [{'role': messages[0]['role'], 'content': spoken.text}] + messages[1:] -%}
|
| 17 |
+
{%- else -%}
|
| 18 |
+
{%- set messages = [{'role': 'system', 'content': spoken_instruction}] + messages -%}
|
| 19 |
+
{%- endif -%}
|
| 20 |
+
{%- endif -%}
|
| 21 |
+
{#
|
| 22 |
+
Template: Nemotron updated Gemma4 chat template, reasoning-off suffix ablation
|
| 23 |
+
Published: 2026-08-20
|
| 24 |
+
Context: Preserve content ordering before tool-calls while matching the original
|
| 25 |
+
Gemma 4 generation prompt when enable_thinking=false.
|
| 26 |
+
#}
|
| 27 |
+
{%- macro format_parameters(properties, required, filter_keys=false) -%}
|
| 28 |
+
{%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}
|
| 29 |
+
{%- set ns = namespace(found_first=false) -%}
|
| 30 |
+
{%- for key, value in properties | dictsort -%}
|
| 31 |
+
{%- set add_comma = false -%}
|
| 32 |
+
{%- if not filter_keys or key not in standard_keys -%}
|
| 33 |
+
{%- if ns.found_first %},{% endif -%}
|
| 34 |
+
{%- set ns.found_first = true -%}
|
| 35 |
+
{{ key }}:{
|
| 36 |
+
{%- if value['description'] -%}
|
| 37 |
+
description:<|"|>{{ value['description'] }}<|"|>
|
| 38 |
+
{%- set add_comma = true -%}
|
| 39 |
+
{%- endif -%}
|
| 40 |
+
{%- if value['type'] | upper == 'STRING' -%}
|
| 41 |
+
{%- if value['enum'] -%}
|
| 42 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 43 |
+
enum:{{ format_argument(value['enum']) }}
|
| 44 |
+
{%- endif -%}
|
| 45 |
+
{%- elif value['type'] | upper == 'ARRAY' -%}
|
| 46 |
+
{%- if value['items'] is mapping and value['items'] -%}
|
| 47 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 48 |
+
items:{
|
| 49 |
+
{%- set ns_items = namespace(found_first=false) -%}
|
| 50 |
+
{%- for item_key, item_value in value['items'] | dictsort -%}
|
| 51 |
+
{%- if item_value is not none -%}
|
| 52 |
+
{%- if ns_items.found_first %},{% endif -%}
|
| 53 |
+
{%- set ns_items.found_first = true -%}
|
| 54 |
+
{%- if item_key == 'properties' -%}
|
| 55 |
+
properties:{
|
| 56 |
+
{%- if item_value is mapping -%}
|
| 57 |
+
{{- format_parameters(item_value, value['items']['required'] | default([])) -}}
|
| 58 |
+
{%- endif -%}
|
| 59 |
+
}
|
| 60 |
+
{%- elif item_key == 'required' -%}
|
| 61 |
+
required:[
|
| 62 |
+
{%- for req_item in item_value -%}
|
| 63 |
+
<|"|>{{- req_item -}}<|"|>
|
| 64 |
+
{%- if not loop.last %},{% endif -%}
|
| 65 |
+
{%- endfor -%}
|
| 66 |
+
]
|
| 67 |
+
{%- elif item_key == 'type' -%}
|
| 68 |
+
{%- if item_value is string -%}
|
| 69 |
+
type:{{ format_argument(item_value | upper) }}
|
| 70 |
+
{%- else -%}
|
| 71 |
+
type:{{ format_argument(item_value | map('upper') | list) }}
|
| 72 |
+
{%- endif -%}
|
| 73 |
+
{%- else -%}
|
| 74 |
+
{{ item_key }}:{{ format_argument(item_value) }}
|
| 75 |
+
{%- endif -%}
|
| 76 |
+
{%- endif -%}
|
| 77 |
+
{%- endfor -%}
|
| 78 |
+
}
|
| 79 |
+
{%- endif -%}
|
| 80 |
+
{%- endif -%}
|
| 81 |
+
{%- if value['nullable'] %}
|
| 82 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 83 |
+
nullable:true
|
| 84 |
+
{%- endif -%}
|
| 85 |
+
{%- if value['type'] | upper == 'OBJECT' -%}
|
| 86 |
+
{%- if value['properties'] is defined and value['properties'] is mapping -%}
|
| 87 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 88 |
+
properties:{
|
| 89 |
+
{{- format_parameters(value['properties'], value['required'] | default([])) -}}
|
| 90 |
+
}
|
| 91 |
+
{%- elif value is mapping -%}
|
| 92 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 93 |
+
properties:{
|
| 94 |
+
{{- format_parameters(value, value['required'] | default([]), filter_keys=true) -}}
|
| 95 |
+
}
|
| 96 |
+
{%- endif -%}
|
| 97 |
+
{%- if value['required'] -%}
|
| 98 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 99 |
+
required:[
|
| 100 |
+
{%- for item in value['required'] | default([]) -%}
|
| 101 |
+
<|"|>{{- item -}}<|"|>
|
| 102 |
+
{%- if not loop.last %},{% endif -%}
|
| 103 |
+
{%- endfor -%}
|
| 104 |
+
]
|
| 105 |
+
{%- endif -%}
|
| 106 |
+
{%- endif -%}
|
| 107 |
+
{%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
|
| 108 |
+
type:<|"|>{{ value['type'] | upper }}<|"|>}
|
| 109 |
+
{%- endif -%}
|
| 110 |
+
{%- endfor -%}
|
| 111 |
+
{%- endmacro -%}
|
| 112 |
+
{%- macro format_function_declaration(tool_data) -%}
|
| 113 |
+
declaration:{{- tool_data['function']['name'] -}}{description:<|"|>{{- tool_data['function']['description'] -}}<|"|>
|
| 114 |
+
{%- set params = tool_data['function']['parameters'] -%}
|
| 115 |
+
{%- if params -%}
|
| 116 |
+
,parameters:{
|
| 117 |
+
{%- if params['properties'] -%}
|
| 118 |
+
properties:{ {{- format_parameters(params['properties'], params['required']) -}} },
|
| 119 |
+
{%- endif -%}
|
| 120 |
+
{%- if params['required'] -%}
|
| 121 |
+
required:[
|
| 122 |
+
{%- for item in params['required'] -%}
|
| 123 |
+
<|"|>{{- item -}}<|"|>
|
| 124 |
+
{{- ',' if not loop.last -}}
|
| 125 |
+
{%- endfor -%}
|
| 126 |
+
],
|
| 127 |
+
{%- endif -%}
|
| 128 |
+
{%- if params['type'] -%}
|
| 129 |
+
type:<|"|>{{- params['type'] | upper -}}<|"|>}
|
| 130 |
+
{%- endif -%}
|
| 131 |
+
{%- endif -%}
|
| 132 |
+
{%- if 'response' in tool_data['function'] -%}
|
| 133 |
+
{%- set response_declaration = tool_data['function']['response'] -%}
|
| 134 |
+
,response:{
|
| 135 |
+
{%- if response_declaration['description'] -%}
|
| 136 |
+
description:<|"|>{{- response_declaration['description'] -}}<|"|>,
|
| 137 |
+
{%- endif -%}
|
| 138 |
+
{%- if response_declaration['type'] | upper == 'OBJECT' -%}
|
| 139 |
+
type:<|"|>{{- response_declaration['type'] | upper -}}<|"|>}
|
| 140 |
+
{%- endif -%}
|
| 141 |
+
{%- endif -%}
|
| 142 |
+
}
|
| 143 |
+
{%- endmacro -%}
|
| 144 |
+
{%- macro format_argument(argument, escape_keys=True) -%}
|
| 145 |
+
{%- if argument is none -%}
|
| 146 |
+
{{- 'null' -}}
|
| 147 |
+
{%- elif argument is string -%}
|
| 148 |
+
{{- '<|"|>' + argument + '<|"|>' -}}
|
| 149 |
+
{%- elif argument is boolean -%}
|
| 150 |
+
{{- 'true' if argument else 'false' -}}
|
| 151 |
+
{%- elif argument is mapping -%}
|
| 152 |
+
{{- '{' -}}
|
| 153 |
+
{%- set ns = namespace(found_first=false) -%}
|
| 154 |
+
{%- for key, value in argument | dictsort -%}
|
| 155 |
+
{%- if ns.found_first %},{% endif -%}
|
| 156 |
+
{%- set ns.found_first = true -%}
|
| 157 |
+
{%- if escape_keys -%}
|
| 158 |
+
{{- '<|"|>' + key + '<|"|>' -}}
|
| 159 |
+
{%- else -%}
|
| 160 |
+
{{- key -}}
|
| 161 |
+
{%- endif -%}
|
| 162 |
+
:{{- format_argument(value, escape_keys=escape_keys) -}}
|
| 163 |
+
{%- endfor -%}
|
| 164 |
+
{{- '}' -}}
|
| 165 |
+
{%- elif argument is sequence -%}
|
| 166 |
+
{{- '[' -}}
|
| 167 |
+
{%- for item in argument -%}
|
| 168 |
+
{{- format_argument(item, escape_keys=escape_keys) -}}
|
| 169 |
+
{%- if not loop.last %},{% endif -%}
|
| 170 |
+
{%- endfor -%}
|
| 171 |
+
{{- ']' -}}
|
| 172 |
+
{%- else -%}
|
| 173 |
+
{{- argument -}}
|
| 174 |
+
{%- endif -%}
|
| 175 |
+
{%- endmacro -%}
|
| 176 |
+
{%- macro strip_thinking(text) -%}
|
| 177 |
+
{%- set ns = namespace(result='') -%}
|
| 178 |
+
{%- for part in text.split('<channel|>') -%}
|
| 179 |
+
{%- if '<|channel>' in part -%}
|
| 180 |
+
{%- set ns.result = ns.result + part.split('<|channel>')[0] -%}
|
| 181 |
+
{%- else -%}
|
| 182 |
+
{%- set ns.result = ns.result + part -%}
|
| 183 |
+
{%- endif -%}
|
| 184 |
+
{%- endfor -%}
|
| 185 |
+
{{- ns.result | trim -}}
|
| 186 |
+
{%- endmacro -%}
|
| 187 |
+
|
| 188 |
+
{%- macro format_tool_response_block(tool_name, response) -%}
|
| 189 |
+
{{- '<|tool_response>' -}}
|
| 190 |
+
{%- if response is mapping -%}
|
| 191 |
+
{{- 'response:' + tool_name + '{' -}}
|
| 192 |
+
{%- for key, value in response | dictsort -%}
|
| 193 |
+
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
| 194 |
+
{%- if not loop.last %},{% endif -%}
|
| 195 |
+
{%- endfor -%}
|
| 196 |
+
{{- '}' -}}
|
| 197 |
+
{%- else -%}
|
| 198 |
+
{{- 'response:' + tool_name + '{value:' + format_argument(response, escape_keys=False) + '}' -}}
|
| 199 |
+
{%- endif -%}
|
| 200 |
+
{{- '<tool_response|>' -}}
|
| 201 |
+
{%- endmacro -%}
|
| 202 |
+
|
| 203 |
+
{#- ===== SETUP ===== -#}
|
| 204 |
+
{%- set ns = namespace(prev_message_type=None, prev_non_tool_role=None) -%}
|
| 205 |
+
{%- set loop_messages = messages -%}
|
| 206 |
+
{%- set enable_thinking = enable_thinking | default(false) -%}
|
| 207 |
+
{%- set preserve_thinking = preserve_thinking | default(false) -%}
|
| 208 |
+
{{- bos_token -}}
|
| 209 |
+
{#- Handle System/Tool Definitions Block -#}
|
| 210 |
+
{%- if enable_thinking or tools or (messages and messages[0]['role'] in ['system', 'developer']) -%}
|
| 211 |
+
{{- '<|turn>system\n' -}}
|
| 212 |
+
{#- Inject Thinking token at the very top of the FIRST system turn -#}
|
| 213 |
+
{%- if enable_thinking -%}
|
| 214 |
+
{{- '<|think|>\n' -}}
|
| 215 |
+
{%- set ns.prev_message_type = 'think' -%}
|
| 216 |
+
{%- endif -%}
|
| 217 |
+
{%- if messages and messages[0]['role'] in ['system', 'developer'] -%}
|
| 218 |
+
{%- if messages[0]['content'] is string -%}
|
| 219 |
+
{{- messages[0]['content'] | trim -}}
|
| 220 |
+
{%- elif messages[0]['content'] is sequence -%}
|
| 221 |
+
{%- for item in messages[0]['content'] -%}
|
| 222 |
+
{{- item['text'] | trim + ' '-}}
|
| 223 |
+
{%- endfor -%}
|
| 224 |
+
{%- endif -%}
|
| 225 |
+
{%- set loop_messages = messages[1:] -%}
|
| 226 |
+
{%- endif -%}
|
| 227 |
+
{%- if tools -%}
|
| 228 |
+
{%- for tool in tools %}
|
| 229 |
+
{{- '<|tool>' -}}
|
| 230 |
+
{{- format_function_declaration(tool) | trim -}}
|
| 231 |
+
{{- '<tool|>' -}}
|
| 232 |
+
{%- endfor %}
|
| 233 |
+
{%- set ns.prev_message_type = 'tool' -%}
|
| 234 |
+
{%- endif -%}
|
| 235 |
+
{{- '<turn|>\n' -}}
|
| 236 |
+
{%- endif %}
|
| 237 |
+
|
| 238 |
+
{#- Pre-scan: find last user message index for reasoning guard -#}
|
| 239 |
+
{%- set ns_turn = namespace(last_user_idx=-1) -%}
|
| 240 |
+
{%- for i in range(loop_messages | length) -%}
|
| 241 |
+
{%- if loop_messages[i]['role'] == 'user' -%}
|
| 242 |
+
{%- set ns_turn.last_user_idx = i -%}
|
| 243 |
+
{%- endif -%}
|
| 244 |
+
{%- endfor -%}
|
| 245 |
+
|
| 246 |
+
{#- Loop through messages -#}
|
| 247 |
+
{%- for message in loop_messages -%}
|
| 248 |
+
{%- if message['role'] != 'tool' -%}
|
| 249 |
+
{%- set ns.prev_message_type = None -%}
|
| 250 |
+
{%- set role = 'model' if message['role'] == 'assistant' else message['role'] -%}
|
| 251 |
+
{#- Detect continuation using tracked state — O(1) instead of O(n) backward scan -#}
|
| 252 |
+
{%- set continue_same_model_turn = (role == 'model' and ns.prev_non_tool_role == 'assistant') -%}
|
| 253 |
+
{%- if not continue_same_model_turn -%}
|
| 254 |
+
{{- '<|turn>' + role + '\n' }}
|
| 255 |
+
|
| 256 |
+
{%- endif -%}
|
| 257 |
+
|
| 258 |
+
{#- Render reasoning/reasoning_content as thinking channel -#}
|
| 259 |
+
{%- set thinking_text = message.get('reasoning') or message.get('reasoning_content') -%}
|
| 260 |
+
{%- set thinking_gate = (loop.index0 > ns_turn.last_user_idx) or (preserve_thinking and message.get('tool_calls')) -%}
|
| 261 |
+
{%- if thinking_text and thinking_gate -%}
|
| 262 |
+
{{- '<|channel>thought\n' + thinking_text + '\n<channel|>' -}}
|
| 263 |
+
{%- endif -%}
|
| 264 |
+
|
| 265 |
+
{%- set captured_content -%}
|
| 266 |
+
{%- if message.get('content') is string -%}
|
| 267 |
+
{%- if role == 'model' -%}
|
| 268 |
+
{{- strip_thinking(message['content']) -}}
|
| 269 |
+
{%- else -%}
|
| 270 |
+
{{- message['content'] | trim -}}
|
| 271 |
+
{%- endif -%}
|
| 272 |
+
{%- elif message.get('content') is sequence -%}
|
| 273 |
+
{%- for item in message['content'] -%}
|
| 274 |
+
{%- if item.get('type') == 'text' -%}
|
| 275 |
+
{%- if role == 'model' -%}
|
| 276 |
+
{{- strip_thinking(item['text']) -}}
|
| 277 |
+
{%- else -%}
|
| 278 |
+
{{- item['text'] | trim -}}
|
| 279 |
+
{%- endif -%}
|
| 280 |
+
{%- elif item.get('type') in ['image', 'image_url'] -%}
|
| 281 |
+
{{- '<|image|>' -}}
|
| 282 |
+
{%- elif item.get('type') in ['audio', 'input_audio'] -%}
|
| 283 |
+
{{- '<|audio|>' -}}
|
| 284 |
+
{%- elif item.get('type') == 'video' -%}
|
| 285 |
+
{{- '<|video|>' -}}
|
| 286 |
+
{%- endif -%}
|
| 287 |
+
{%- endfor -%}
|
| 288 |
+
{%- endif -%}
|
| 289 |
+
{%- endset -%}
|
| 290 |
+
|
| 291 |
+
{#- The sole intentional behavior change from HF main: preserve
|
| 292 |
+
OpenAI assistant content before its tool calls. -#}
|
| 293 |
+
{%- if role == 'model' and message.get('tool_calls') -%}
|
| 294 |
+
{{- captured_content -}}
|
| 295 |
+
{%- endif -%}
|
| 296 |
+
|
| 297 |
+
{%- if message.get('tool_calls') -%}
|
| 298 |
+
{%- for tool_call in message.get('tool_calls') -%}
|
| 299 |
+
{%- set function = tool_call['function'] -%}
|
| 300 |
+
{{- '<|tool_call>call:' + function['name'] + '{' -}}
|
| 301 |
+
{%- if function['arguments'] is mapping -%}
|
| 302 |
+
{%- set ns_args = namespace(found_first=false) -%}
|
| 303 |
+
{%- for key, value in function['arguments'] | dictsort -%}
|
| 304 |
+
{%- if ns_args.found_first %},{% endif -%}
|
| 305 |
+
{%- set ns_args.found_first = true -%}
|
| 306 |
+
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
| 307 |
+
{%- endfor -%}
|
| 308 |
+
{%- elif function['arguments'] is none -%}
|
| 309 |
+
{%- else -%}
|
| 310 |
+
{{- raise_exception(
|
| 311 |
+
"chat_template: tool_calls[].function.arguments must be a "
|
| 312 |
+
"JSON object (mapping), not a string. Deserialize arguments "
|
| 313 |
+
"before passing to the template."
|
| 314 |
+
) -}}
|
| 315 |
+
{%- endif -%}
|
| 316 |
+
{{- '}<tool_call|>' -}}
|
| 317 |
+
{%- endfor -%}
|
| 318 |
+
{%- set ns.prev_message_type = 'tool_call' -%}
|
| 319 |
+
{%- endif -%}
|
| 320 |
+
|
| 321 |
+
{%- set ns_tr_out = namespace(flag=false) -%}
|
| 322 |
+
{%- if message.get('tool_responses') -%}
|
| 323 |
+
{#- Legacy: tool_responses embedded on the assistant message (Google/Gemma native) -#}
|
| 324 |
+
{%- for tool_response in message.get('tool_responses') -%}
|
| 325 |
+
{{- format_tool_response_block(tool_response['name'] | default('unknown', true), tool_response['response']) -}}
|
| 326 |
+
{%- set ns_tr_out.flag = true -%}
|
| 327 |
+
{%- set ns.prev_message_type = 'tool_response' -%}
|
| 328 |
+
{%- endfor -%}
|
| 329 |
+
{%- elif message.get('tool_calls') -%}
|
| 330 |
+
{#- OpenAI Chat Completions: forward-scan consecutive role:tool messages -#}
|
| 331 |
+
{%- set ns_tool_scan = namespace(stopped=false) -%}
|
| 332 |
+
{%- for k in range(loop.index0 + 1, loop_messages | length) -%}
|
| 333 |
+
{%- if ns_tool_scan.stopped -%}
|
| 334 |
+
{%- elif loop_messages[k]['role'] != 'tool' -%}
|
| 335 |
+
{%- set ns_tool_scan.stopped = true -%}
|
| 336 |
+
{%- else -%}
|
| 337 |
+
{%- set follow = loop_messages[k] -%}
|
| 338 |
+
{#- Resolve tool_call_id to function name -#}
|
| 339 |
+
{%- set ns_tname = namespace(name=follow.get('name') or 'unknown') -%}
|
| 340 |
+
{%- for tc in message.get('tool_calls') -%}
|
| 341 |
+
{%- if tc.get('id') == follow.get('tool_call_id') -%}
|
| 342 |
+
{%- set ns_tname.name = tc['function']['name'] -%}
|
| 343 |
+
{%- endif -%}
|
| 344 |
+
{%- endfor -%}
|
| 345 |
+
{#- Handle content as string or content-parts array -#}
|
| 346 |
+
{%- set tool_body = follow.get('content') -%}
|
| 347 |
+
{%- if tool_body is string -%}
|
| 348 |
+
{{- format_tool_response_block(ns_tname.name, tool_body) -}}
|
| 349 |
+
{%- elif tool_body is sequence and tool_body is not string -%}
|
| 350 |
+
{%- set ns_txt = namespace(s='') -%}
|
| 351 |
+
{%- for part in tool_body -%}
|
| 352 |
+
{%- if part.get('type') == 'text' -%}
|
| 353 |
+
{%- set ns_txt.s = ns_txt.s + (part.get('text') | default('')) -%}
|
| 354 |
+
{%- endif -%}
|
| 355 |
+
{%- endfor -%}
|
| 356 |
+
{{- format_tool_response_block(ns_tname.name, ns_txt.s) -}}
|
| 357 |
+
{%- for part in tool_body -%}
|
| 358 |
+
{%- if part.get('type') in ['image', 'image_url'] -%}
|
| 359 |
+
{{- '<|image|>' -}}
|
| 360 |
+
{%- elif part.get('type') in ['audio', 'input_audio'] -%}
|
| 361 |
+
{{- '<|audio|>' -}}
|
| 362 |
+
{%- elif part.get('type') == 'video' -%}
|
| 363 |
+
{{- '<|video|>' -}}
|
| 364 |
+
{%- endif -%}
|
| 365 |
+
{%- endfor -%}
|
| 366 |
+
{%- else -%}
|
| 367 |
+
{{- format_tool_response_block(ns_tname.name, tool_body) -}}
|
| 368 |
+
{%- endif -%}
|
| 369 |
+
{%- set ns_tr_out.flag = true -%}
|
| 370 |
+
{%- set ns.prev_message_type = 'tool_response' -%}
|
| 371 |
+
{%- endif -%}
|
| 372 |
+
{%- endfor -%}
|
| 373 |
+
{%- endif -%}
|
| 374 |
+
|
| 375 |
+
{%- if not (role == 'model' and message.get('tool_calls')) -%}
|
| 376 |
+
{{- captured_content -}}
|
| 377 |
+
{%- endif -%}
|
| 378 |
+
{%- set has_content = captured_content | trim | length > 0 -%}
|
| 379 |
+
|
| 380 |
+
{#- Forward-scan: find next non-tool message role for continuation detection -#}
|
| 381 |
+
{%- set next_nt = namespace(role=None, found=false) -%}
|
| 382 |
+
{%- for j in range(loop.index0 + 1, loop_messages | length) -%}
|
| 383 |
+
{%- if not next_nt.found -%}
|
| 384 |
+
{%- if loop_messages[j]['role'] != 'tool' -%}
|
| 385 |
+
{%- set next_nt.role = loop_messages[j]['role'] -%}
|
| 386 |
+
{%- set next_nt.found = true -%}
|
| 387 |
+
{%- endif -%}
|
| 388 |
+
{%- endif -%}
|
| 389 |
+
{%- endfor -%}
|
| 390 |
+
|
| 391 |
+
{%- set continues_into_next = (
|
| 392 |
+
role == 'model'
|
| 393 |
+
and next_nt.role == 'assistant'
|
| 394 |
+
and (not message.get('tool_calls') or ns_tr_out.flag)
|
| 395 |
+
) -%}
|
| 396 |
+
|
| 397 |
+
{%- if ns.prev_message_type == 'tool_call' and not ns_tr_out.flag -%}
|
| 398 |
+
{{- '<|tool_response>' -}}
|
| 399 |
+
{%- elif continues_into_next -%}
|
| 400 |
+
{%- elif not (ns_tr_out.flag and not has_content and not next_nt.found) -%}
|
| 401 |
+
{{- '<turn|>\n' -}}
|
| 402 |
+
{%- endif -%}
|
| 403 |
+
|
| 404 |
+
{#- Track previous non-tool role for next iteration (avoids O(n) backward scan) -#}
|
| 405 |
+
{%- set ns.prev_non_tool_role = message['role'] -%}
|
| 406 |
+
{%- endif -%}
|
| 407 |
+
{%- endfor -%}
|
| 408 |
+
|
| 409 |
+
{%- if add_generation_prompt -%}
|
| 410 |
+
{%- if ns.prev_message_type != 'tool_response' and ns.prev_message_type != 'tool_call' -%}
|
| 411 |
+
{{- '<|turn>model\n' -}}
|
| 412 |
+
{%- elif ns.prev_message_type == 'tool_response' and enable_thinking -%}
|
| 413 |
+
{{- '<|channel>thought\n' -}}
|
| 414 |
+
{%- endif -%}
|
| 415 |
+
{%- endif -%}
|
config.json
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Gemma4ForConditionalGeneration"
|
| 4 |
+
],
|
| 5 |
+
"audio_config": {
|
| 6 |
+
"_name_or_path": "",
|
| 7 |
+
"architectures": null,
|
| 8 |
+
"attention_chunk_size": 12,
|
| 9 |
+
"attention_context_left": 13,
|
| 10 |
+
"attention_context_right": 0,
|
| 11 |
+
"attention_invalid_logits_value": -1000000000.0,
|
| 12 |
+
"attention_logit_cap": 50.0,
|
| 13 |
+
"chunk_size_feed_forward": 0,
|
| 14 |
+
"conv_kernel_size": 5,
|
| 15 |
+
"dtype": "bfloat16",
|
| 16 |
+
"gradient_clipping": 10000000000.0,
|
| 17 |
+
"hidden_act": "silu",
|
| 18 |
+
"hidden_size": 1024,
|
| 19 |
+
"id2label": {
|
| 20 |
+
"0": "LABEL_0",
|
| 21 |
+
"1": "LABEL_1"
|
| 22 |
+
},
|
| 23 |
+
"initializer_range": 0.02,
|
| 24 |
+
"is_encoder_decoder": false,
|
| 25 |
+
"label2id": {
|
| 26 |
+
"LABEL_0": 0,
|
| 27 |
+
"LABEL_1": 1
|
| 28 |
+
},
|
| 29 |
+
"model_type": "gemma4_audio",
|
| 30 |
+
"num_attention_heads": 8,
|
| 31 |
+
"num_hidden_layers": 12,
|
| 32 |
+
"output_attentions": false,
|
| 33 |
+
"output_hidden_states": false,
|
| 34 |
+
"output_proj_dims": 1536,
|
| 35 |
+
"problem_type": null,
|
| 36 |
+
"residual_weight": 0.5,
|
| 37 |
+
"return_dict": true,
|
| 38 |
+
"rms_norm_eps": 1e-06,
|
| 39 |
+
"subsampling_conv_channels": [
|
| 40 |
+
128,
|
| 41 |
+
32
|
| 42 |
+
],
|
| 43 |
+
"use_clipped_linears": true
|
| 44 |
+
},
|
| 45 |
+
"audio_token_id": 258881,
|
| 46 |
+
"boa_token_id": 256000,
|
| 47 |
+
"boi_token_id": 255999,
|
| 48 |
+
"dtype": "bfloat16",
|
| 49 |
+
"eoa_token_id": 258883,
|
| 50 |
+
"eoa_token_index": 258883,
|
| 51 |
+
"eoi_token_id": 258882,
|
| 52 |
+
"eos_token_id": [
|
| 53 |
+
1,
|
| 54 |
+
106
|
| 55 |
+
],
|
| 56 |
+
"image_token_id": 258880,
|
| 57 |
+
"initializer_range": 0.02,
|
| 58 |
+
"model_type": "gemma4",
|
| 59 |
+
"text_config": {
|
| 60 |
+
"attention_bias": false,
|
| 61 |
+
"attention_dropout": 0.0,
|
| 62 |
+
"attention_k_eq_v": false,
|
| 63 |
+
"bos_token_id": 2,
|
| 64 |
+
"dtype": "bfloat16",
|
| 65 |
+
"enable_moe_block": false,
|
| 66 |
+
"eos_token_id": 1,
|
| 67 |
+
"expert_intermediate_size": null,
|
| 68 |
+
"final_logit_softcapping": 30.0,
|
| 69 |
+
"global_head_dim": 512,
|
| 70 |
+
"head_dim": 256,
|
| 71 |
+
"hidden_activation": "gelu_pytorch_tanh",
|
| 72 |
+
"hidden_size": 2560,
|
| 73 |
+
"hidden_size_per_layer_input": 256,
|
| 74 |
+
"initializer_range": 0.02,
|
| 75 |
+
"intermediate_size": 10240,
|
| 76 |
+
"layer_types": [
|
| 77 |
+
"sliding_attention",
|
| 78 |
+
"sliding_attention",
|
| 79 |
+
"sliding_attention",
|
| 80 |
+
"sliding_attention",
|
| 81 |
+
"sliding_attention",
|
| 82 |
+
"full_attention",
|
| 83 |
+
"sliding_attention",
|
| 84 |
+
"sliding_attention",
|
| 85 |
+
"sliding_attention",
|
| 86 |
+
"sliding_attention",
|
| 87 |
+
"sliding_attention",
|
| 88 |
+
"full_attention",
|
| 89 |
+
"sliding_attention",
|
| 90 |
+
"sliding_attention",
|
| 91 |
+
"sliding_attention",
|
| 92 |
+
"sliding_attention",
|
| 93 |
+
"sliding_attention",
|
| 94 |
+
"full_attention",
|
| 95 |
+
"sliding_attention",
|
| 96 |
+
"sliding_attention",
|
| 97 |
+
"sliding_attention",
|
| 98 |
+
"sliding_attention",
|
| 99 |
+
"sliding_attention",
|
| 100 |
+
"full_attention",
|
| 101 |
+
"sliding_attention",
|
| 102 |
+
"sliding_attention",
|
| 103 |
+
"sliding_attention",
|
| 104 |
+
"sliding_attention",
|
| 105 |
+
"sliding_attention",
|
| 106 |
+
"full_attention",
|
| 107 |
+
"sliding_attention",
|
| 108 |
+
"sliding_attention",
|
| 109 |
+
"sliding_attention",
|
| 110 |
+
"sliding_attention",
|
| 111 |
+
"sliding_attention",
|
| 112 |
+
"full_attention",
|
| 113 |
+
"sliding_attention",
|
| 114 |
+
"sliding_attention",
|
| 115 |
+
"sliding_attention",
|
| 116 |
+
"sliding_attention",
|
| 117 |
+
"sliding_attention",
|
| 118 |
+
"full_attention"
|
| 119 |
+
],
|
| 120 |
+
"max_position_embeddings": 65536,
|
| 121 |
+
"model_type": "gemma4_text",
|
| 122 |
+
"num_attention_heads": 8,
|
| 123 |
+
"num_experts": null,
|
| 124 |
+
"num_global_key_value_heads": null,
|
| 125 |
+
"num_hidden_layers": 42,
|
| 126 |
+
"num_key_value_heads": 2,
|
| 127 |
+
"num_kv_shared_layers": 18,
|
| 128 |
+
"pad_token_id": 0,
|
| 129 |
+
"rms_norm_eps": 1e-06,
|
| 130 |
+
"rope_parameters": {
|
| 131 |
+
"full_attention": {
|
| 132 |
+
"partial_rotary_factor": 0.25,
|
| 133 |
+
"rope_theta": 1000000.0,
|
| 134 |
+
"rope_type": "proportional"
|
| 135 |
+
},
|
| 136 |
+
"sliding_attention": {
|
| 137 |
+
"rope_theta": 10000.0,
|
| 138 |
+
"rope_type": "default"
|
| 139 |
+
}
|
| 140 |
+
},
|
| 141 |
+
"sliding_window": 512,
|
| 142 |
+
"tie_word_embeddings": true,
|
| 143 |
+
"top_k_experts": null,
|
| 144 |
+
"use_bidirectional_attention": null,
|
| 145 |
+
"use_cache": true,
|
| 146 |
+
"use_double_wide_mlp": false,
|
| 147 |
+
"vocab_size": 262144,
|
| 148 |
+
"vocab_size_per_layer_input": 262144
|
| 149 |
+
},
|
| 150 |
+
"tie_word_embeddings": true,
|
| 151 |
+
"transformers_version": "5.5.0.dev0",
|
| 152 |
+
"video_token_id": 258884,
|
| 153 |
+
"vision_config": {
|
| 154 |
+
"_name_or_path": "",
|
| 155 |
+
"architectures": null,
|
| 156 |
+
"attention_bias": false,
|
| 157 |
+
"attention_dropout": 0.0,
|
| 158 |
+
"chunk_size_feed_forward": 0,
|
| 159 |
+
"default_output_length": 280,
|
| 160 |
+
"dtype": "bfloat16",
|
| 161 |
+
"global_head_dim": 64,
|
| 162 |
+
"head_dim": 64,
|
| 163 |
+
"hidden_activation": "gelu_pytorch_tanh",
|
| 164 |
+
"hidden_size": 768,
|
| 165 |
+
"id2label": {
|
| 166 |
+
"0": "LABEL_0",
|
| 167 |
+
"1": "LABEL_1"
|
| 168 |
+
},
|
| 169 |
+
"initializer_range": 0.02,
|
| 170 |
+
"intermediate_size": 3072,
|
| 171 |
+
"is_encoder_decoder": false,
|
| 172 |
+
"label2id": {
|
| 173 |
+
"LABEL_0": 0,
|
| 174 |
+
"LABEL_1": 1
|
| 175 |
+
},
|
| 176 |
+
"max_position_embeddings": 131072,
|
| 177 |
+
"model_type": "gemma4_vision",
|
| 178 |
+
"num_attention_heads": 12,
|
| 179 |
+
"num_hidden_layers": 16,
|
| 180 |
+
"num_key_value_heads": 12,
|
| 181 |
+
"output_attentions": false,
|
| 182 |
+
"output_hidden_states": false,
|
| 183 |
+
"patch_size": 16,
|
| 184 |
+
"pooling_kernel_size": 3,
|
| 185 |
+
"position_embedding_size": 10240,
|
| 186 |
+
"problem_type": null,
|
| 187 |
+
"return_dict": true,
|
| 188 |
+
"rms_norm_eps": 1e-06,
|
| 189 |
+
"rope_parameters": {
|
| 190 |
+
"rope_theta": 100.0,
|
| 191 |
+
"rope_type": "default"
|
| 192 |
+
},
|
| 193 |
+
"standardize": false,
|
| 194 |
+
"use_clipped_linears": true
|
| 195 |
+
},
|
| 196 |
+
"vision_soft_tokens_per_image": 280
|
| 197 |
+
}
|
explainability.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| Field | Response |
|
| 2 |
+
| :---- | :---- |
|
| 3 |
+
| Intended Task/Domain: | Text generation, reasoning, and chat |
|
| 4 |
+
| Model Type: | Text-to-text Gemma-4 |
|
| 5 |
+
| Intended Users: | Generative AI creators working with conversational AI models and image content. |
|
| 6 |
+
| Output: | Text |
|
| 7 |
+
| Tools used to evaluate datasets to identify synthetic data and ensure data authenticity. | We used a Gemma-3 4B-based filtering model fine-tuned on [Nemotron Content Safety Dataset v2](https://huggingface.co/datasets/nvidia/Aegis-AI-Content-Safety-Dataset-2.0) to ensure the quality of synthetic data. |
|
| 8 |
+
| Describe how the model works: | Generates text by predicting the next word or token based on the context provided in the input sequence using multiple self-attention layers. |
|
| 9 |
+
| List the groups (or group characteristics) for which this was tested to produce comparable outcomes: | Age, Disability Status, Gender Identity, Nationality, Physical Appearance, Ethnicity, Socioeconomic Status, Sexual Orientation, Religion |
|
| 10 |
+
| Technical Limitations & Mitigation: | This model performs particularly well in instruction following regimes, as such may be strongly influenced by untrusted inputs and should be paired with appropriate guardrails and data filtering to better align use-case behaviors when exposed to such data. |
|
| 11 |
+
| Verified to have met prescribed NVIDIA quality standards: | Yes |
|
| 12 |
+
| Performance Metrics: | Accuracy, Throughput, and User-side throughput |
|
| 13 |
+
| Potential Known Risks: | The model was optimized explicitly for instruction following and as such is more susceptible to prompt injection and jailbreaking in various forms as a result of its instruction tuning. This means that the model should be paired with additional rails or system filtering to limit exposure to instructions from malicious sources -- either directly or indirectly by retrieval (e.g. via visiting a website) -- as they may yield outputs that can lead to harmful, system-level outcomes up to and including remote code execution in agentic systems when effective security controls including guardrails are not in place. The model may generate answers that may be inaccurate, omit key information, include irrelevant or redundant text, or produce socially unacceptable or undesirable text, even if the prompt itself does not include anything explicitly offensive. |
|
| 14 |
+
| Licensing: | Use of this model is governed by the [OpenMDW License Agreement, version 1.1](https://github.com/OpenMDW/OpenMDW/blob/main/1.1/LICENSE.OpenMDW-1.1). This model has been post-trained on the Google Gemma 4 model, and use of the Google Gemma 4 model is governed by [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
generation_config.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token_id": 2,
|
| 3 |
+
"do_sample": true,
|
| 4 |
+
"eos_token_id": [
|
| 5 |
+
1,
|
| 6 |
+
106,
|
| 7 |
+
50
|
| 8 |
+
],
|
| 9 |
+
"pad_token_id": 0,
|
| 10 |
+
"temperature": 1.0,
|
| 11 |
+
"top_k": 64,
|
| 12 |
+
"top_p": 0.95,
|
| 13 |
+
"transformers_version": "5.5.0.dev0"
|
| 14 |
+
}
|
handler.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Custom Hugging Face Inference Endpoint handler for Gemma 4 checkpoints.
|
| 2 |
+
|
| 3 |
+
The checkpoint is a Gemma 4 image-text-to-text, tool-calling model
|
| 4 |
+
(``Gemma4ForConditionalGeneration``). The handler deliberately loads the
|
| 5 |
+
processor from ``path`` and calls its ``apply_chat_template`` method so the
|
| 6 |
+
``chat_template.jinja`` packaged with the individual checkpoint is used.
|
| 7 |
+
|
| 8 |
+
Request payload (``data``) keys:
|
| 9 |
+
|
| 10 |
+
inputs (required) A string prompt or a list of chat messages.
|
| 11 |
+
tools (optional) OpenAI-style tool/function schemas.
|
| 12 |
+
parameters (optional) Keyword arguments forwarded to ``model.generate``.
|
| 13 |
+
enable_thinking
|
| 14 |
+
(optional) Gemma 4 chat-template control; defaults to false,
|
| 15 |
+
matching the checkpoint template's own default.
|
| 16 |
+
chat_template_kwargs
|
| 17 |
+
(optional) Additional checkpoint-template keyword arguments.
|
| 18 |
+
|
| 19 |
+
Message content can be a string or a list of text/image/video parts. Image
|
| 20 |
+
parts accept ``image`` or ``image_url`` as a URL, data URI, or base64 string.
|
| 21 |
+
|
| 22 |
+
Response: ``[{"generated_text": "..."}]``.
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
from __future__ import annotations
|
| 26 |
+
|
| 27 |
+
import base64
|
| 28 |
+
import io
|
| 29 |
+
from typing import Any, Dict, List, Optional, Union
|
| 30 |
+
|
| 31 |
+
import torch
|
| 32 |
+
from PIL import Image
|
| 33 |
+
from transformers import AutoModelForImageTextToText, AutoProcessor
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
DEFAULT_GENERATION_KWARGS: Dict[str, Any] = {
|
| 37 |
+
"max_new_tokens": 1024,
|
| 38 |
+
"do_sample": False,
|
| 39 |
+
"temperature": 0.7,
|
| 40 |
+
"top_p": 0.9,
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class EndpointHandler:
|
| 45 |
+
def __init__(self, path: str = "") -> None:
|
| 46 |
+
# ``path`` is the model repository root supplied by the endpoint.
|
| 47 |
+
# Loading from this path also loads that checkpoint's chat_template.jinja.
|
| 48 |
+
self.processor = AutoProcessor.from_pretrained(path, trust_remote_code=True)
|
| 49 |
+
|
| 50 |
+
dtype = torch.bfloat16 if torch.cuda.is_available() else torch.float32
|
| 51 |
+
self.model = AutoModelForImageTextToText.from_pretrained(
|
| 52 |
+
path,
|
| 53 |
+
dtype=dtype,
|
| 54 |
+
device_map="auto" if torch.cuda.is_available() else None,
|
| 55 |
+
trust_remote_code=True,
|
| 56 |
+
)
|
| 57 |
+
self.model.eval()
|
| 58 |
+
|
| 59 |
+
self.tokenizer = getattr(self.processor, "tokenizer", self.processor)
|
| 60 |
+
|
| 61 |
+
@staticmethod
|
| 62 |
+
def _load_image(ref: str) -> Image.Image:
|
| 63 |
+
"""Load a PIL image from a URL, data URI, or raw base64 string."""
|
| 64 |
+
if ref.startswith(("http://", "https://")):
|
| 65 |
+
import requests
|
| 66 |
+
|
| 67 |
+
response = requests.get(ref, timeout=30)
|
| 68 |
+
response.raise_for_status()
|
| 69 |
+
return Image.open(io.BytesIO(response.content)).convert("RGB")
|
| 70 |
+
|
| 71 |
+
if ref.startswith("data:"):
|
| 72 |
+
try:
|
| 73 |
+
ref = ref.split(",", 1)[1]
|
| 74 |
+
except IndexError as exc:
|
| 75 |
+
raise ValueError("Malformed image data URI") from exc
|
| 76 |
+
|
| 77 |
+
return Image.open(io.BytesIO(base64.b64decode(ref))).convert("RGB")
|
| 78 |
+
|
| 79 |
+
def _collect_images(self, messages: List[Dict[str, Any]]) -> List[Image.Image]:
|
| 80 |
+
images: List[Image.Image] = []
|
| 81 |
+
for message in messages:
|
| 82 |
+
content = message.get("content")
|
| 83 |
+
if not isinstance(content, list):
|
| 84 |
+
continue
|
| 85 |
+
for item in content:
|
| 86 |
+
if not isinstance(item, dict):
|
| 87 |
+
continue
|
| 88 |
+
if item.get("type") == "image" or "image" in item or "image_url" in item:
|
| 89 |
+
ref = item.get("image") or item.get("image_url")
|
| 90 |
+
if isinstance(ref, dict):
|
| 91 |
+
ref = ref.get("url")
|
| 92 |
+
if isinstance(ref, str):
|
| 93 |
+
images.append(self._load_image(ref))
|
| 94 |
+
return images
|
| 95 |
+
|
| 96 |
+
@staticmethod
|
| 97 |
+
def _build_messages(
|
| 98 |
+
inputs: Union[str, List[Dict[str, Any]]],
|
| 99 |
+
) -> List[Dict[str, Any]]:
|
| 100 |
+
if isinstance(inputs, str):
|
| 101 |
+
return [{"role": "user", "content": inputs}]
|
| 102 |
+
if not isinstance(inputs, list):
|
| 103 |
+
raise TypeError("'inputs' must be a string or a list of chat messages")
|
| 104 |
+
return inputs
|
| 105 |
+
|
| 106 |
+
def _decode_completion(self, generated_ids: torch.Tensor) -> str:
|
| 107 |
+
# Gemma 4's channel and tool-call delimiters are special tokens. Do not
|
| 108 |
+
# use skip_special_tokens=True: doing so corrupts structured tool output.
|
| 109 |
+
text = self.processor.batch_decode(
|
| 110 |
+
generated_ids,
|
| 111 |
+
skip_special_tokens=False,
|
| 112 |
+
clean_up_tokenization_spaces=False,
|
| 113 |
+
)[0]
|
| 114 |
+
|
| 115 |
+
# Remove generation terminators without stripping structural special tokens.
|
| 116 |
+
for token in (self.tokenizer.eos_token, self.tokenizer.pad_token):
|
| 117 |
+
if token:
|
| 118 |
+
while text.endswith(token):
|
| 119 |
+
text = text[: -len(token)]
|
| 120 |
+
return text
|
| 121 |
+
|
| 122 |
+
@torch.inference_mode()
|
| 123 |
+
def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
| 124 |
+
if not isinstance(data, dict):
|
| 125 |
+
raise TypeError("Request payload must be a dictionary")
|
| 126 |
+
|
| 127 |
+
request = dict(data)
|
| 128 |
+
if "inputs" not in request:
|
| 129 |
+
raise ValueError("Request payload must include 'inputs'")
|
| 130 |
+
|
| 131 |
+
inputs = request.pop("inputs")
|
| 132 |
+
tools: Optional[List[Dict[str, Any]]] = request.pop("tools", None)
|
| 133 |
+
parameters: Dict[str, Any] = request.pop("parameters", {}) or {}
|
| 134 |
+
enable_thinking = bool(request.pop("enable_thinking", False))
|
| 135 |
+
chat_template_kwargs: Dict[str, Any] = request.pop(
|
| 136 |
+
"chat_template_kwargs", {}
|
| 137 |
+
) or {}
|
| 138 |
+
|
| 139 |
+
if request:
|
| 140 |
+
unknown = ", ".join(sorted(request))
|
| 141 |
+
raise ValueError(f"Unknown request key(s): {unknown}")
|
| 142 |
+
if not isinstance(parameters, dict):
|
| 143 |
+
raise TypeError("'parameters' must be a dictionary")
|
| 144 |
+
if not isinstance(chat_template_kwargs, dict):
|
| 145 |
+
raise TypeError("'chat_template_kwargs' must be a dictionary")
|
| 146 |
+
|
| 147 |
+
messages = self._build_messages(inputs)
|
| 148 |
+
images = self._collect_images(messages)
|
| 149 |
+
|
| 150 |
+
# Top-level enable_thinking is authoritative and is passed directly to
|
| 151 |
+
# the packaged Gemma 4 Jinja template.
|
| 152 |
+
chat_template_kwargs = {
|
| 153 |
+
**chat_template_kwargs,
|
| 154 |
+
"enable_thinking": enable_thinking,
|
| 155 |
+
}
|
| 156 |
+
prompt = self.processor.apply_chat_template(
|
| 157 |
+
messages,
|
| 158 |
+
tools=tools,
|
| 159 |
+
tokenize=False,
|
| 160 |
+
add_generation_prompt=True,
|
| 161 |
+
**chat_template_kwargs,
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
processor_kwargs: Dict[str, Any] = {
|
| 165 |
+
"text": [prompt],
|
| 166 |
+
"return_tensors": "pt",
|
| 167 |
+
}
|
| 168 |
+
if images:
|
| 169 |
+
processor_kwargs["images"] = images
|
| 170 |
+
|
| 171 |
+
model_inputs = self.processor(**processor_kwargs)
|
| 172 |
+
model_inputs = {key: value.to(self.model.device) for key, value in model_inputs.items()}
|
| 173 |
+
|
| 174 |
+
generation_kwargs = {**DEFAULT_GENERATION_KWARGS, **parameters}
|
| 175 |
+
if not generation_kwargs.get("do_sample", False):
|
| 176 |
+
for key in ("temperature", "top_p", "top_k"):
|
| 177 |
+
generation_kwargs.pop(key, None)
|
| 178 |
+
|
| 179 |
+
generated_ids = self.model.generate(**model_inputs, **generation_kwargs)
|
| 180 |
+
input_length = model_inputs["input_ids"].shape[1]
|
| 181 |
+
new_tokens = generated_ids[:, input_length:]
|
| 182 |
+
|
| 183 |
+
return [{"generated_text": self._decode_completion(new_tokens)}]
|
inference_example.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run FleetWorker-E4B on one task-board item. Use the project field; ignore priority (see the model card).
|
| 2 |
+
|
| 3 |
+
pip install "transformers>=5" torch
|
| 4 |
+
python inference_example.py "title: Add retry with backoff to the nightly export job"
|
| 5 |
+
"""
|
| 6 |
+
import json
|
| 7 |
+
import sys
|
| 8 |
+
|
| 9 |
+
import torch
|
| 10 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 11 |
+
|
| 12 |
+
REPO = "ThakiCloud/FleetWorker-E4B"
|
| 13 |
+
LABELS = ["ai-experiment-measurement", "gitops-deployment-health", "synthetic-data-pipeline", "company-operations-agents", "ondevice-small-model", "todo-board-tooling", "enterprise-ops-benchmark", "shop-assistant-console", "commerce-growth-agents", "platform-strategy-planning", "decision-routing-research", "legal-decision-models", "secops-automation-console", "multimodal-api-gateway", "character-ai-app", "telecom-phy-research", "engineering-blog-publishing", "generative-video-training", "semiconductor-design-llm", "agent-trajectory-distillation", "korean-humanization-corpus", "edge-inference-box", "unattended-agent-runs", "personal-agent-system", "music-generation-rooms"]
|
| 14 |
+
SYSTEM = "You triage a task-board item. Output exactly one compact JSON object with keys \"project\" and \"priority\" and nothing else. \"project\" is one of: ai-experiment-measurement, gitops-deployment-health, synthetic-data-pipeline, company-operations-agents, ondevice-small-model, todo-board-tooling, enterprise-ops-benchmark, shop-assistant-console, commerce-growth-agents, platform-strategy-planning, decision-routing-research, legal-decision-models, secops-automation-console, multimodal-api-gateway, character-ai-app, telecom-phy-research, engineering-blog-publishing, generative-video-training, semiconductor-design-llm, agent-trajectory-distillation, korean-humanization-corpus, edge-inference-box, unattended-agent-runs, personal-agent-system, music-generation-rooms, or \"other\"; \"unknown\" if the text gives no way to tell. \"priority\" is one of: P0, P1, P2, P3."
|
| 15 |
+
|
| 16 |
+
tok = AutoTokenizer.from_pretrained(REPO)
|
| 17 |
+
model = AutoModelForCausalLM.from_pretrained(REPO, dtype=torch.bfloat16, device_map="auto").eval()
|
| 18 |
+
stop = [i for i in {tok.eos_token_id, tok.convert_tokens_to_ids("<turn|>")} if isinstance(i, int)]
|
| 19 |
+
item = sys.argv[1] if len(sys.argv) > 1 else "title: Add retry with backoff to the nightly export job"
|
| 20 |
+
messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": item}]
|
| 21 |
+
prompt = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)
|
| 22 |
+
ids = tok(prompt, add_special_tokens=False, return_tensors="pt").to(model.device)
|
| 23 |
+
with torch.no_grad():
|
| 24 |
+
out = model.generate(**ids, max_new_tokens=64, do_sample=False, eos_token_id=stop)
|
| 25 |
+
text = tok.decode(out[0, ids["input_ids"].shape[1]:], skip_special_tokens=False).split("<turn|>")[0].strip()
|
| 26 |
+
pred = json.loads(text)
|
| 27 |
+
print({"project": pred.get("project"), "valid_label": pred.get("project") in LABELS + ["other", "unknown"]})
|
model-00001-of-00001.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:05a7213f8b0bf2409de51b5f0bba67aeae8d0d83383aaaebf64395303eb4d675
|
| 3 |
+
size 15882477468
|
model-frozen-shared-kv.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:32aaa38402af5a51c6d6b27aeb8a26d3e6964e5590330f0e7b2f546608da4023
|
| 3 |
+
size 110118048
|
model.safetensors.index.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
privacy.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| Field | Response |
|
| 2 |
+
| :---- | :---- |
|
| 3 |
+
| Generatable or reverse engineerable personal data\*? | No |
|
| 4 |
+
| Personal data used to create this model? | No |
|
| 5 |
+
| Was consent obtained for any personal data\* used? | Not Applicable |
|
| 6 |
+
| (For GPAI Models): A description of any methods implemented in data acquisition or processing, if any, to address the prevalence of personal data in the training data, where relevant and applicable. | We used only prompts that do not contain any personal data for synthetic data generation. |
|
| 7 |
+
| How often is dataset reviewed? | Before Release |
|
| 8 |
+
| Is a mechanism in place to honor data subject right of access or deletion of personal data? | Not Applicable |
|
| 9 |
+
| If personal data was collected for the development of the model, was it collected directly by NVIDIA? | Not Applicable |
|
| 10 |
+
| If personal data was collected for the development of the model by NVIDIA, do you maintain or have access to disclosures made to data subjects? | Not Applicable |
|
| 11 |
+
| If personal data was collected for the development of this AI model, was it minimized to only what was required? | Not Applicable |
|
| 12 |
+
| Was data from user interactions with the AI model (e.g. user input and prompts) used to train the model? | No |
|
| 13 |
+
| Is there provenance for all datasets used in training? | Yes |
|
| 14 |
+
| Does data labeling (annotation, metadata) comply with privacy laws? | Yes |
|
| 15 |
+
| Is data compliant with data subject requests for data correction or removal, if such a request was made? | No, not possible with externally-sourced data. |
|
| 16 |
+
| Applicable Privacy Policy | [https://www.nvidia.com/en-us/about-nvidia/privacy-policy/](https://www.nvidia.com/en-us/about-nvidia/privacy-policy/) |
|
processor_config.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"audio_ms_per_token": 40,
|
| 3 |
+
"audio_seq_length": 750,
|
| 4 |
+
"feature_extractor": {
|
| 5 |
+
"dither": 0.0,
|
| 6 |
+
"feature_extractor_type": "Gemma4AudioFeatureExtractor",
|
| 7 |
+
"feature_size": 128,
|
| 8 |
+
"fft_length": 512,
|
| 9 |
+
"fft_overdrive": false,
|
| 10 |
+
"frame_length": 320,
|
| 11 |
+
"hop_length": 160,
|
| 12 |
+
"input_scale_factor": 1.0,
|
| 13 |
+
"max_frequency": 8000.0,
|
| 14 |
+
"mel_floor": 0.001,
|
| 15 |
+
"min_frequency": 0.0,
|
| 16 |
+
"padding_side": "right",
|
| 17 |
+
"padding_value": 0.0,
|
| 18 |
+
"per_bin_mean": null,
|
| 19 |
+
"per_bin_stddev": null,
|
| 20 |
+
"preemphasis": 0.0,
|
| 21 |
+
"preemphasis_htk_flavor": true,
|
| 22 |
+
"return_attention_mask": true,
|
| 23 |
+
"sampling_rate": 16000
|
| 24 |
+
},
|
| 25 |
+
"image_processor": {
|
| 26 |
+
"do_convert_rgb": true,
|
| 27 |
+
"do_normalize": false,
|
| 28 |
+
"do_rescale": true,
|
| 29 |
+
"do_resize": true,
|
| 30 |
+
"image_mean": [
|
| 31 |
+
0.0,
|
| 32 |
+
0.0,
|
| 33 |
+
0.0
|
| 34 |
+
],
|
| 35 |
+
"image_processor_type": "Gemma4ImageProcessor",
|
| 36 |
+
"image_seq_length": 280,
|
| 37 |
+
"image_std": [
|
| 38 |
+
1.0,
|
| 39 |
+
1.0,
|
| 40 |
+
1.0
|
| 41 |
+
],
|
| 42 |
+
"max_soft_tokens": 280,
|
| 43 |
+
"patch_size": 16,
|
| 44 |
+
"pooling_kernel_size": 3,
|
| 45 |
+
"resample": 3,
|
| 46 |
+
"rescale_factor": 0.00392156862745098
|
| 47 |
+
},
|
| 48 |
+
"image_seq_length": 280,
|
| 49 |
+
"processor_class": "Gemma4Processor",
|
| 50 |
+
"video_processor": {
|
| 51 |
+
"do_convert_rgb": true,
|
| 52 |
+
"do_normalize": true,
|
| 53 |
+
"do_rescale": true,
|
| 54 |
+
"do_resize": true,
|
| 55 |
+
"do_sample_frames": true,
|
| 56 |
+
"image_mean": [
|
| 57 |
+
0.0,
|
| 58 |
+
0.0,
|
| 59 |
+
0.0
|
| 60 |
+
],
|
| 61 |
+
"image_std": [
|
| 62 |
+
1.0,
|
| 63 |
+
1.0,
|
| 64 |
+
1.0
|
| 65 |
+
],
|
| 66 |
+
"max_soft_tokens": 70,
|
| 67 |
+
"num_frames": 32,
|
| 68 |
+
"patch_size": 16,
|
| 69 |
+
"pooling_kernel_size": 3,
|
| 70 |
+
"resample": 3,
|
| 71 |
+
"rescale_factor": 0.00392156862745098,
|
| 72 |
+
"return_metadata": false,
|
| 73 |
+
"video_processor_type": "Gemma4VideoProcessor"
|
| 74 |
+
}
|
| 75 |
+
}
|
safety.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| Field | Response |
|
| 2 |
+
| :---- | :---- |
|
| 3 |
+
| Model Application Field(s): | Chat, Instruction Following, Chatbot Development, Code Generation, Reasoning, Customer Service |
|
| 4 |
+
| Describe the life critical impact (if present). | Not Applicable |
|
| 5 |
+
| Description of methods implemented in data acquisition or processing, if any, to address other types of potentially harmful data in the training, testing, and validation data: | We used a guard model for content safety to exclude potentially harmful data from training. |
|
| 6 |
+
| Description of any methods implemented in data acquisition or processing, if any, to address illegal or harmful content in the training data, including, but not limited to, child sexual abuse material (CSAM) and non-consensual intimate imagery (NCII) | We used a Gemma-3 4B-based guard model trained on [Nemotron Content Safety Dataset v2](https://huggingface.co/datasets/nvidia/Aegis-AI-Content-Safety-Dataset-2.0) for content safety to exclude potentially illegal or harmful content from the training. |
|
| 7 |
+
| Use Case Restrictions: | Use of this model is governed by the [OpenMDW License Agreement, version 1.1](https://github.com/OpenMDW/OpenMDW/blob/main/1.1/LICENSE.OpenMDW-1.1). This model has been post-trained on the Google Gemma 4 model, and use of the Google Gemma 4 model is governed by [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)|
|
| 8 |
+
| Model and dataset restrictions: | The Principle of least privilege (PoLP) is applied limiting access for dataset generation and model development. Restrictions enforce dataset access during training, and dataset license constraints adhered to. |
|
| 9 |
+
| This AI model was developed based on our policies to ensure responsible data handling and risk mitigation. The datasets used for training have been scanned for harmful content and illegal content, consistent with our policies including scanning for Child Sexual Abuse Material (CSAM). Ongoing review and monitoring mechanisms are in place based on our policies and to maintain data integrity. | True. We use [Nemotron Content Safety Dataset V2](https://huggingface.co/datasets/nvidia/Aegis-AI-Content-Safety-Dataset-2.0) and an internal safety dataset specialized for minority sexuality for content safety evaluation to ensure the safety of this model. |
|
tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cc8d3a0ce36466ccc1278bf987df5f71db1719b9ca6b4118264f45cb627bfe0f
|
| 3 |
+
size 32169626
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"audio_token": "<|audio|>",
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"boa_token": "<|audio>",
|
| 5 |
+
"boi_token": "<|image>",
|
| 6 |
+
"bos_token": "<bos>",
|
| 7 |
+
"eoa_token": "<audio|>",
|
| 8 |
+
"eoc_token": "<channel|>",
|
| 9 |
+
"eoi_token": "<image|>",
|
| 10 |
+
"eos_token": "<eos>",
|
| 11 |
+
"eot_token": "<turn|>",
|
| 12 |
+
"escape_token": "<|\"|>",
|
| 13 |
+
"etc_token": "<tool_call|>",
|
| 14 |
+
"etd_token": "<tool|>",
|
| 15 |
+
"etr_token": "<tool_response|>",
|
| 16 |
+
"extra_special_tokens": [
|
| 17 |
+
"<|video|>"
|
| 18 |
+
],
|
| 19 |
+
"image_token": "<|image|>",
|
| 20 |
+
"mask_token": "<mask>",
|
| 21 |
+
"model_max_length": 1000000000000000019884624838656,
|
| 22 |
+
"pad_token": "<pad>",
|
| 23 |
+
"padding_side": "left",
|
| 24 |
+
"processor_class": "Gemma4Processor",
|
| 25 |
+
"response_schema": {
|
| 26 |
+
"type": "object",
|
| 27 |
+
"properties": {
|
| 28 |
+
"role": {
|
| 29 |
+
"const": "assistant"
|
| 30 |
+
},
|
| 31 |
+
"thinking": {
|
| 32 |
+
"type": "string"
|
| 33 |
+
},
|
| 34 |
+
"content": {
|
| 35 |
+
"type": "string"
|
| 36 |
+
},
|
| 37 |
+
"tool_calls": {
|
| 38 |
+
"x-regex-iterator": "<\\|tool_call>(.*?)<tool_call\\|>",
|
| 39 |
+
"type": "array",
|
| 40 |
+
"items": {
|
| 41 |
+
"type": "object",
|
| 42 |
+
"properties": {
|
| 43 |
+
"type": {
|
| 44 |
+
"const": "function"
|
| 45 |
+
},
|
| 46 |
+
"function": {
|
| 47 |
+
"type": "object",
|
| 48 |
+
"x-regex": "call\\:(?P<name>\\w+)(?P<arguments>\\{.*\\})",
|
| 49 |
+
"properties": {
|
| 50 |
+
"name": {
|
| 51 |
+
"type": "string"
|
| 52 |
+
},
|
| 53 |
+
"arguments": {
|
| 54 |
+
"type": "object",
|
| 55 |
+
"x-parser": "gemma4-tool-call",
|
| 56 |
+
"additionalProperties": {}
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
},
|
| 64 |
+
"x-regex": "(\\<\\|channel\\>thought\\n(?P<thinking>.*?)\\<channel\\|\\>)?(?P<tool_calls>\\<\\|tool_call\\>.*\\<tool_call\\|\\>)?(?P<content>(?:(?!\\<turn\\|\\>)(?!\\<\\|tool_response\\>).)+)?(?:\\<turn\\|\\>|\\<\\|tool_response\\>)?"
|
| 65 |
+
},
|
| 66 |
+
"response_template": {
|
| 67 |
+
"defaults": {
|
| 68 |
+
"role": "assistant"
|
| 69 |
+
},
|
| 70 |
+
"fields": {
|
| 71 |
+
"content": {
|
| 72 |
+
"close": [
|
| 73 |
+
"<turn|>",
|
| 74 |
+
"<|tool_response>",
|
| 75 |
+
"<eos>"
|
| 76 |
+
],
|
| 77 |
+
"content": "text"
|
| 78 |
+
},
|
| 79 |
+
"thinking": {
|
| 80 |
+
"close": "<channel|>",
|
| 81 |
+
"content": "text",
|
| 82 |
+
"open": "<|channel>thought\n"
|
| 83 |
+
},
|
| 84 |
+
"tool_calls": {
|
| 85 |
+
"close": "<tool_call|>",
|
| 86 |
+
"content": "json",
|
| 87 |
+
"content_args": {
|
| 88 |
+
"string_delims": [
|
| 89 |
+
[
|
| 90 |
+
"<|\"|>",
|
| 91 |
+
"<|\"|>"
|
| 92 |
+
]
|
| 93 |
+
],
|
| 94 |
+
"unquoted_keys": true
|
| 95 |
+
},
|
| 96 |
+
"open_pattern": "<\\|tool_call>call:(?P<name>\\w+)",
|
| 97 |
+
"repeats": true,
|
| 98 |
+
"transform": {
|
| 99 |
+
"function": {
|
| 100 |
+
"arguments": "{content}",
|
| 101 |
+
"name": "{name}"
|
| 102 |
+
},
|
| 103 |
+
"type": "function"
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
},
|
| 107 |
+
"start_anchor": [
|
| 108 |
+
"<|turn>model\n",
|
| 109 |
+
"<tool_response|>"
|
| 110 |
+
]
|
| 111 |
+
},
|
| 112 |
+
"soc_token": "<|channel>",
|
| 113 |
+
"sot_token": "<|turn>",
|
| 114 |
+
"stc_token": "<|tool_call>",
|
| 115 |
+
"std_token": "<|tool>",
|
| 116 |
+
"str_token": "<|tool_response>",
|
| 117 |
+
"think_token": "<|think|>",
|
| 118 |
+
"tokenizer_class": "GemmaTokenizer",
|
| 119 |
+
"unk_token": "<unk>",
|
| 120 |
+
"chat_template": "{%- if conversational_mode | default(false) -%}\n {%- set spoken_instruction = \"You are having a spoken conversation with the user. Respond as briefly as possible while still addressing their questions fully.\" -%}\n {%- if messages and messages[0]['role'] in ['system', 'developer'] -%}\n {%- set spoken = namespace(text='') -%}\n {%- if messages[0]['content'] is string -%}\n {%- set spoken.text = messages[0]['content'] | trim -%}\n {%- else -%}\n {%- for part in messages[0]['content'] -%}\n {%- set spoken.text = spoken.text + (part['text'] | trim) + ' ' -%}\n {%- endfor -%}\n {%- set spoken.text = spoken.text | trim -%}\n {%- endif -%}\n {%- if spoken.text != spoken_instruction -%}\n {%- set spoken.text = (spoken.text + '\\n\\n' if spoken.text else '') + spoken_instruction -%}\n {%- endif -%}\n {%- set messages = [{'role': messages[0]['role'], 'content': spoken.text}] + messages[1:] -%}\n {%- else -%}\n {%- set messages = [{'role': 'system', 'content': spoken_instruction}] + messages -%}\n {%- endif -%}\n{%- endif -%}\n{#\n Template: Nemotron updated Gemma4 chat template, reasoning-off suffix ablation\n Published: 2026-08-20\n Context: Preserve content ordering before tool-calls while matching the original\n Gemma 4 generation prompt when enable_thinking=false.\n#}\n{%- macro format_parameters(properties, required, filter_keys=false) -%}\n {%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}\n {%- set ns = namespace(found_first=false) -%}\n {%- for key, value in properties | dictsort -%}\n {%- set add_comma = false -%}\n {%- if not filter_keys or key not in standard_keys -%}\n {%- if ns.found_first %},{% endif -%}\n {%- set ns.found_first = true -%}\n {{ key }}:{\n {%- if value['description'] -%}\n description:<|\"|>{{ value['description'] }}<|\"|>\n {%- set add_comma = true -%}\n {%- endif -%}\n {%- if value['type'] | upper == 'STRING' -%}\n {%- if value['enum'] -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n enum:{{ format_argument(value['enum']) }}\n {%- endif -%}\n {%- elif value['type'] | upper == 'ARRAY' -%}\n {%- if value['items'] is mapping and value['items'] -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n items:{\n {%- set ns_items = namespace(found_first=false) -%}\n {%- for item_key, item_value in value['items'] | dictsort -%}\n {%- if item_value is not none -%}\n {%- if ns_items.found_first %},{% endif -%}\n {%- set ns_items.found_first = true -%}\n {%- if item_key == 'properties' -%}\n properties:{\n {%- if item_value is mapping -%}\n {{- format_parameters(item_value, value['items']['required'] | default([])) -}}\n {%- endif -%}\n }\n {%- elif item_key == 'required' -%}\n required:[\n {%- for req_item in item_value -%}\n <|\"|>{{- req_item -}}<|\"|>\n {%- if not loop.last %},{% endif -%}\n {%- endfor -%}\n ]\n {%- elif item_key == 'type' -%}\n {%- if item_value is string -%}\n type:{{ format_argument(item_value | upper) }}\n {%- else -%}\n type:{{ format_argument(item_value | map('upper') | list) }}\n {%- endif -%}\n {%- else -%}\n {{ item_key }}:{{ format_argument(item_value) }}\n {%- endif -%}\n {%- endif -%}\n {%- endfor -%}\n }\n {%- endif -%}\n {%- endif -%}\n {%- if value['nullable'] %}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n nullable:true\n {%- endif -%}\n {%- if value['type'] | upper == 'OBJECT' -%}\n {%- if value['properties'] is defined and value['properties'] is mapping -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n properties:{\n {{- format_parameters(value['properties'], value['required'] | default([])) -}}\n }\n {%- elif value is mapping -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n properties:{\n {{- format_parameters(value, value['required'] | default([]), filter_keys=true) -}}\n }\n {%- endif -%}\n {%- if value['required'] -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n required:[\n {%- for item in value['required'] | default([]) -%}\n <|\"|>{{- item -}}<|\"|>\n {%- if not loop.last %},{% endif -%}\n {%- endfor -%}\n ]\n {%- endif -%}\n {%- endif -%}\n {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}\n type:<|\"|>{{ value['type'] | upper }}<|\"|>}\n {%- endif -%}\n {%- endfor -%}\n{%- endmacro -%}\n{%- macro format_function_declaration(tool_data) -%}\n declaration:{{- tool_data['function']['name'] -}}{description:<|\"|>{{- tool_data['function']['description'] -}}<|\"|>\n {%- set params = tool_data['function']['parameters'] -%}\n {%- if params -%}\n ,parameters:{\n {%- if params['properties'] -%}\n properties:{ {{- format_parameters(params['properties'], params['required']) -}} },\n {%- endif -%}\n {%- if params['required'] -%}\n required:[\n {%- for item in params['required'] -%}\n <|\"|>{{- item -}}<|\"|>\n {{- ',' if not loop.last -}}\n {%- endfor -%}\n ],\n {%- endif -%}\n {%- if params['type'] -%}\n type:<|\"|>{{- params['type'] | upper -}}<|\"|>}\n {%- endif -%}\n {%- endif -%}\n {%- if 'response' in tool_data['function'] -%}\n {%- set response_declaration = tool_data['function']['response'] -%}\n ,response:{\n {%- if response_declaration['description'] -%}\n description:<|\"|>{{- response_declaration['description'] -}}<|\"|>,\n {%- endif -%}\n {%- if response_declaration['type'] | upper == 'OBJECT' -%}\n type:<|\"|>{{- response_declaration['type'] | upper -}}<|\"|>}\n {%- endif -%}\n {%- endif -%}\n }\n{%- endmacro -%}\n{%- macro format_argument(argument, escape_keys=True) -%}\n {%- if argument is none -%}\n {{- 'null' -}}\n {%- elif argument is string -%}\n {{- '<|\"|>' + argument + '<|\"|>' -}}\n {%- elif argument is boolean -%}\n {{- 'true' if argument else 'false' -}}\n {%- elif argument is mapping -%}\n {{- '{' -}}\n {%- set ns = namespace(found_first=false) -%}\n {%- for key, value in argument | dictsort -%}\n {%- if ns.found_first %},{% endif -%}\n {%- set ns.found_first = true -%}\n {%- if escape_keys -%}\n {{- '<|\"|>' + key + '<|\"|>' -}}\n {%- else -%}\n {{- key -}}\n {%- endif -%}\n :{{- format_argument(value, escape_keys=escape_keys) -}}\n {%- endfor -%}\n {{- '}' -}}\n {%- elif argument is sequence -%}\n {{- '[' -}}\n {%- for item in argument -%}\n {{- format_argument(item, escape_keys=escape_keys) -}}\n {%- if not loop.last %},{% endif -%}\n {%- endfor -%}\n {{- ']' -}}\n {%- else -%}\n {{- argument -}}\n {%- endif -%}\n{%- endmacro -%}\n{%- macro strip_thinking(text) -%}\n {%- set ns = namespace(result='') -%}\n {%- for part in text.split('<channel|>') -%}\n {%- if '<|channel>' in part -%}\n {%- set ns.result = ns.result + part.split('<|channel>')[0] -%}\n {%- else -%}\n {%- set ns.result = ns.result + part -%}\n {%- endif -%}\n {%- endfor -%}\n {{- ns.result | trim -}}\n{%- endmacro -%}\n\n{%- macro format_tool_response_block(tool_name, response) -%}\n {{- '<|tool_response>' -}}\n {%- if response is mapping -%}\n {{- 'response:' + tool_name + '{' -}}\n {%- for key, value in response | dictsort -%}\n {{- key -}}:{{- format_argument(value, escape_keys=False) -}}\n {%- if not loop.last %},{% endif -%}\n {%- endfor -%}\n {{- '}' -}}\n {%- else -%}\n {{- 'response:' + tool_name + '{value:' + format_argument(response, escape_keys=False) + '}' -}}\n {%- endif -%}\n {{- '<tool_response|>' -}}\n{%- endmacro -%}\n\n{#- ===== SETUP ===== -#}\n{%- set ns = namespace(prev_message_type=None, prev_non_tool_role=None) -%}\n{%- set loop_messages = messages -%}\n{%- set enable_thinking = enable_thinking | default(false) -%}\n{%- set preserve_thinking = preserve_thinking | default(false) -%}\n{{- bos_token -}}\n{#- Handle System/Tool Definitions Block -#}\n{%- if enable_thinking or tools or (messages and messages[0]['role'] in ['system', 'developer']) -%}\n {{- '<|turn>system\\n' -}}\n {#- Inject Thinking token at the very top of the FIRST system turn -#}\n {%- if enable_thinking -%}\n {{- '<|think|>\\n' -}}\n {%- set ns.prev_message_type = 'think' -%}\n {%- endif -%}\n {%- if messages and messages[0]['role'] in ['system', 'developer'] -%}\n {%- if messages[0]['content'] is string -%}\n {{- messages[0]['content'] | trim -}}\n {%- elif messages[0]['content'] is sequence -%}\n {%- for item in messages[0]['content'] -%}\n {{- item['text'] | trim + ' '-}}\n {%- endfor -%}\n {%- endif -%}\n {%- set loop_messages = messages[1:] -%}\n {%- endif -%}\n {%- if tools -%}\n {%- for tool in tools %}\n {{- '<|tool>' -}}\n {{- format_function_declaration(tool) | trim -}}\n {{- '<tool|>' -}}\n {%- endfor %}\n {%- set ns.prev_message_type = 'tool' -%}\n {%- endif -%}\n {{- '<turn|>\\n' -}}\n{%- endif %}\n\n{#- Pre-scan: find last user message index for reasoning guard -#}\n{%- set ns_turn = namespace(last_user_idx=-1) -%}\n{%- for i in range(loop_messages | length) -%}\n {%- if loop_messages[i]['role'] == 'user' -%}\n {%- set ns_turn.last_user_idx = i -%}\n {%- endif -%}\n{%- endfor -%}\n\n{#- Loop through messages -#}\n{%- for message in loop_messages -%}\n {%- if message['role'] != 'tool' -%}\n {%- set ns.prev_message_type = None -%}\n {%- set role = 'model' if message['role'] == 'assistant' else message['role'] -%}\n {#- Detect continuation using tracked state \u2014 O(1) instead of O(n) backward scan -#}\n {%- set continue_same_model_turn = (role == 'model' and ns.prev_non_tool_role == 'assistant') -%}\n {%- if not continue_same_model_turn -%}\n {{- '<|turn>' + role + '\\n' }}\n\n {%- endif -%}\n\n {#- Render reasoning/reasoning_content as thinking channel -#}\n {%- set thinking_text = message.get('reasoning') or message.get('reasoning_content') -%}\n {%- set thinking_gate = (loop.index0 > ns_turn.last_user_idx) or (preserve_thinking and message.get('tool_calls')) -%}\n {%- if thinking_text and thinking_gate -%}\n {{- '<|channel>thought\\n' + thinking_text + '\\n<channel|>' -}}\n {%- endif -%}\n\n {%- set captured_content -%}\n {%- if message.get('content') is string -%}\n {%- if role == 'model' -%}\n {{- strip_thinking(message['content']) -}}\n {%- else -%}\n {{- message['content'] | trim -}}\n {%- endif -%}\n {%- elif message.get('content') is sequence -%}\n {%- for item in message['content'] -%}\n {%- if item.get('type') == 'text' -%}\n {%- if role == 'model' -%}\n {{- strip_thinking(item['text']) -}}\n {%- else -%}\n {{- item['text'] | trim -}}\n {%- endif -%}\n {%- elif item.get('type') in ['image', 'image_url'] -%}\n {{- '<|image|>' -}}\n {%- elif item.get('type') in ['audio', 'input_audio'] -%}\n {{- '<|audio|>' -}}\n {%- elif item.get('type') == 'video' -%}\n {{- '<|video|>' -}}\n {%- endif -%}\n {%- endfor -%}\n {%- endif -%}\n {%- endset -%}\n\n {#- The sole intentional behavior change from HF main: preserve\n OpenAI assistant content before its tool calls. -#}\n {%- if role == 'model' and message.get('tool_calls') -%}\n {{- captured_content -}}\n {%- endif -%}\n\n {%- if message.get('tool_calls') -%}\n {%- for tool_call in message.get('tool_calls') -%}\n {%- set function = tool_call['function'] -%}\n {{- '<|tool_call>call:' + function['name'] + '{' -}}\n {%- if function['arguments'] is mapping -%}\n {%- set ns_args = namespace(found_first=false) -%}\n {%- for key, value in function['arguments'] | dictsort -%}\n {%- if ns_args.found_first %},{% endif -%}\n {%- set ns_args.found_first = true -%}\n {{- key -}}:{{- format_argument(value, escape_keys=False) -}}\n {%- endfor -%}\n {%- elif function['arguments'] is none -%}\n {%- else -%}\n {{- raise_exception(\n \"chat_template: tool_calls[].function.arguments must be a \"\n \"JSON object (mapping), not a string. Deserialize arguments \"\n \"before passing to the template.\"\n ) -}}\n {%- endif -%}\n {{- '}<tool_call|>' -}}\n {%- endfor -%}\n {%- set ns.prev_message_type = 'tool_call' -%}\n {%- endif -%}\n\n {%- set ns_tr_out = namespace(flag=false) -%}\n {%- if message.get('tool_responses') -%}\n {#- Legacy: tool_responses embedded on the assistant message (Google/Gemma native) -#}\n {%- for tool_response in message.get('tool_responses') -%}\n {{- format_tool_response_block(tool_response['name'] | default('unknown', true), tool_response['response']) -}}\n {%- set ns_tr_out.flag = true -%}\n {%- set ns.prev_message_type = 'tool_response' -%}\n {%- endfor -%}\n {%- elif message.get('tool_calls') -%}\n {#- OpenAI Chat Completions: forward-scan consecutive role:tool messages -#}\n {%- set ns_tool_scan = namespace(stopped=false) -%}\n {%- for k in range(loop.index0 + 1, loop_messages | length) -%}\n {%- if ns_tool_scan.stopped -%}\n {%- elif loop_messages[k]['role'] != 'tool' -%}\n {%- set ns_tool_scan.stopped = true -%}\n {%- else -%}\n {%- set follow = loop_messages[k] -%}\n {#- Resolve tool_call_id to function name -#}\n {%- set ns_tname = namespace(name=follow.get('name') or 'unknown') -%}\n {%- for tc in message.get('tool_calls') -%}\n {%- if tc.get('id') == follow.get('tool_call_id') -%}\n {%- set ns_tname.name = tc['function']['name'] -%}\n {%- endif -%}\n {%- endfor -%}\n {#- Handle content as string or content-parts array -#}\n {%- set tool_body = follow.get('content') -%}\n {%- if tool_body is string -%}\n {{- format_tool_response_block(ns_tname.name, tool_body) -}}\n {%- elif tool_body is sequence and tool_body is not string -%}\n {%- set ns_txt = namespace(s='') -%}\n {%- for part in tool_body -%}\n {%- if part.get('type') == 'text' -%}\n {%- set ns_txt.s = ns_txt.s + (part.get('text') | default('')) -%}\n {%- endif -%}\n {%- endfor -%}\n {{- format_tool_response_block(ns_tname.name, ns_txt.s) -}}\n {%- for part in tool_body -%}\n {%- if part.get('type') in ['image', 'image_url'] -%}\n {{- '<|image|>' -}}\n {%- elif part.get('type') in ['audio', 'input_audio'] -%}\n {{- '<|audio|>' -}}\n {%- elif part.get('type') == 'video' -%}\n {{- '<|video|>' -}}\n {%- endif -%}\n {%- endfor -%}\n {%- else -%}\n {{- format_tool_response_block(ns_tname.name, tool_body) -}}\n {%- endif -%}\n {%- set ns_tr_out.flag = true -%}\n {%- set ns.prev_message_type = 'tool_response' -%}\n {%- endif -%}\n {%- endfor -%}\n {%- endif -%}\n\n {%- if not (role == 'model' and message.get('tool_calls')) -%}\n {{- captured_content -}}\n {%- endif -%}\n {%- set has_content = captured_content | trim | length > 0 -%}\n\n {#- Forward-scan: find next non-tool message role for continuation detection -#}\n {%- set next_nt = namespace(role=None, found=false) -%}\n {%- for j in range(loop.index0 + 1, loop_messages | length) -%}\n {%- if not next_nt.found -%}\n {%- if loop_messages[j]['role'] != 'tool' -%}\n {%- set next_nt.role = loop_messages[j]['role'] -%}\n {%- set next_nt.found = true -%}\n {%- endif -%}\n {%- endif -%}\n {%- endfor -%}\n\n {%- set continues_into_next = (\n role == 'model'\n and next_nt.role == 'assistant'\n and (not message.get('tool_calls') or ns_tr_out.flag)\n ) -%}\n\n {%- if ns.prev_message_type == 'tool_call' and not ns_tr_out.flag -%}\n {{- '<|tool_response>' -}}\n {%- elif continues_into_next -%}\n {%- elif not (ns_tr_out.flag and not has_content and not next_nt.found) -%}\n {{- '<turn|>\\n' -}}\n {%- endif -%}\n\n {#- Track previous non-tool role for next iteration (avoids O(n) backward scan) -#}\n {%- set ns.prev_non_tool_role = message['role'] -%}\n {%- endif -%}\n{%- endfor -%}\n\n{%- if add_generation_prompt -%}\n {%- if ns.prev_message_type != 'tool_response' and ns.prev_message_type != 'tool_call' -%}\n {{- '<|turn>model\\n' -}}\n {%- elif ns.prev_message_type == 'tool_response' and enable_thinking -%}\n {{- '<|channel>thought\\n' -}}\n {%- endif -%}\n{%- endif -%}\n"
|
| 121 |
+
}
|