Text Generation
Transformers
Safetensors
English
tokle
causal-lm
custom-architecture
custom_code
slm
small-language-model
Instructions to use techdotus/Tokle-3M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use techdotus/Tokle-3M with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="techdotus/Tokle-3M", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("techdotus/Tokle-3M", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use techdotus/Tokle-3M with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "techdotus/Tokle-3M" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "techdotus/Tokle-3M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/techdotus/Tokle-3M
- SGLang
How to use techdotus/Tokle-3M 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 "techdotus/Tokle-3M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "techdotus/Tokle-3M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "techdotus/Tokle-3M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "techdotus/Tokle-3M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use techdotus/Tokle-3M with Docker Model Runner:
docker model run hf.co/techdotus/Tokle-3M
Upload 10 files
Browse files- LICENSE +21 -0
- README.md +142 -0
- config.json +29 -0
- configuration_tokle.py +70 -0
- generation_config.json +11 -0
- model.safetensors +3 -0
- modeling_tokle.py +299 -0
- special_tokens_map.json +23 -0
- tokenizer.json +0 -0
- tokenizer_config.json +0 -0
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 tech.us
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
CHANGED
|
@@ -1,3 +1,145 @@
|
|
| 1 |
---
|
|
|
|
|
|
|
| 2 |
license: mit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
license: mit
|
| 5 |
+
library_name: transformers
|
| 6 |
+
pipeline_tag: text-generation
|
| 7 |
+
tags:
|
| 8 |
+
- text-generation
|
| 9 |
+
- causal-lm
|
| 10 |
+
- custom-architecture
|
| 11 |
+
- custom_code
|
| 12 |
+
- slm
|
| 13 |
+
- small-language-model
|
| 14 |
+
datasets:
|
| 15 |
+
- HuggingFaceFW/fineweb-edu
|
| 16 |
+
- HuggingFaceTB/cosmopedia
|
| 17 |
+
- agentlans/high-quality-english-sentences
|
| 18 |
+
- nampdn-ai/tiny-strange-textbooks
|
| 19 |
+
- armanc/ScienceQA
|
| 20 |
+
- nvidia/OpenMathInstruct-2
|
| 21 |
+
- microsoft/orca-math-word-problems-200k
|
| 22 |
---
|
| 23 |
+
|
| 24 |
+
# Tokle-3M
|
| 25 |
+
|
| 26 |
+
## Model Summary
|
| 27 |
+
|
| 28 |
+
Tokle-3M is a decoder-only language model with 2.91M parameters. It was first trained on 12B tokens with SPAB (Static Pairwise Attention Bias), a frozen table of 8.39M token-pair association scores built from Pointwise Mutual Information (PMI) over the training corpus, giving 11.3M parameters in total during this stage. During training, for every query-key pair, SPAB hashed the two token IDs into the table, retrieved their PMI value, scaled it by a learned per-head factor, and added it to the attention logits before softmax.
|
| 29 |
+
|
| 30 |
+
After this stage, the SPAB table was removed and the model was trained for an additional 0.5B tokens to distill the knowledge in the SPAB matrix into its own layers. As a result, Tokle-3M runs entirely on its 2.91M parameters at inference, with no SPAB table required.
|
| 31 |
+
|
| 32 |
+
## Model Architecture
|
| 33 |
+
|
| 34 |
+
| Parameter | Value |
|
| 35 |
+
|---|---|
|
| 36 |
+
| Architecture | Decoder-only transformer (RMSNorm, RoPE, GQA, SwiGLU) |
|
| 37 |
+
| Layers | 9 |
|
| 38 |
+
| Hidden size (d_model) | 144 |
|
| 39 |
+
| Attention heads | 3 |
|
| 40 |
+
| KV heads (GQA) | 1 (multi-query attention) |
|
| 41 |
+
| Head dim | 48 |
|
| 42 |
+
| FFN intermediate size | 432 |
|
| 43 |
+
| Max sequence length | 512 |
|
| 44 |
+
| Tie word embeddings | Yes |
|
| 45 |
+
| Precision | FP32 weights |
|
| 46 |
+
| Parameters | 2.91M |
|
| 47 |
+
|
| 48 |
+
## How to use
|
| 49 |
+
|
| 50 |
+
```python
|
| 51 |
+
import torch
|
| 52 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 53 |
+
|
| 54 |
+
model_id = "techdotus/Tokle-3M"
|
| 55 |
+
tok = AutoTokenizer.from_pretrained(model_id)
|
| 56 |
+
model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True).eval()
|
| 57 |
+
|
| 58 |
+
ids = tok("The climate change", return_tensors="pt")
|
| 59 |
+
with torch.no_grad():
|
| 60 |
+
out = model.generate(**ids, max_new_tokens=32, do_sample=False,
|
| 61 |
+
repetition_penalty=1.3) # greedy
|
| 62 |
+
print(tok.decode(out[0], skip_special_tokens=True))
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
## Benchmark Results
|
| 66 |
+
|
| 67 |
+
All scores are 0-shot acc_norm, using the Open SLM Leaderboard methodology.
|
| 68 |
+
|
| 69 |
+
| HellaSwag | ARC-Easy | ARC-Challenge | PIQA | ArithMark-3 |
|
| 70 |
+
|---|---|---|---|---|
|
| 71 |
+
| 27.20% | 34.89% | 23.98% | 55.01% | 41.00% |
|
| 72 |
+
|
| 73 |
+
### Ablation: SPAB vs. Distilled
|
| 74 |
+
|
| 75 |
+
Stage 1 model (SPAB active) vs. the released Tokle-3M (SPAB removed and distilled).
|
| 76 |
+
|
| 77 |
+
| Model | Params | Int Index | HellaSwag | ARC-Easy | ARC-Chal | PIQA | ArithMark-3 |
|
| 78 |
+
|---|---|---|---|---|---|---|---|
|
| 79 |
+
| Tokle-SPAB-11.3M (with SPAB) | 11.3M (2.91M trainable + 8.39M frozen) | 9.16 | 27.22% | 34.68% | 24.49% | 54.95% | 41.70% |
|
| 80 |
+
| Tokle-3M (SPAB distilled) | 2.91M | 8.96 | 27.20% | 34.89% | 23.98% | 55.01% | 41.00% |
|
| 81 |
+
|
| 82 |
+
## Comparison Results
|
| 83 |
+
|
| 84 |
+
All scores are 0-shot acc_norm, using the Open SLM Leaderboard methodology. Scores for the other models are from the Open SLM Leaderboard. Bold marks the best result in each column.
|
| 85 |
+
|
| 86 |
+
| Model | Params | Int Index | HellaSwag | ARC-Easy | ARC-Chal | PIQA | ArithMark-3 |
|
| 87 |
+
|---|---|---|---|---|---|---|---|
|
| 88 |
+
| Tokle-3M (Tech.us) | 2.91M | **8.96** | 27.20% | **34.89%** | **23.98%** | 55.01% | **41.00%** |
|
| 89 |
+
| Ember-2 (SurjoLabs) | 2.96M×2 | 7.21 | 27.28% | 33.42% | 22.01% | 55.11% | 35.90% |
|
| 90 |
+
| BananaMind-2-Micro (BananaMind) | 2.9M | 6.01 | **28.27%** | 33.12% | 21.93% | 53.21% | 34.00% |
|
| 91 |
+
| GPT-S-1.4M (Axiomic Labs) | 1.4M | 5.40 | 26.89% | 31.57% | 21.93% | **55.17%** | 30.20% |
|
| 92 |
+
|
| 93 |
+
## Training Details
|
| 94 |
+
|
| 95 |
+
Tokle-3M was trained in two stages on the same data mixture.
|
| 96 |
+
|
| 97 |
+
| Stage | Tokens | SPAB | Parameters |
|
| 98 |
+
|---|---|---|---|
|
| 99 |
+
| 1. Pretraining | 12B | Active (frozen PMI table) | 11.3M (2.91M trainable + 8.39M frozen) |
|
| 100 |
+
| 2. Distillation | 0.5B | Removed | 2.91M |
|
| 101 |
+
|
| 102 |
+
Stage 2 lets the trained weights absorb the prior the SPAB table had been providing, so the released model is self-contained rather than losing that knowledge when the table is removed.
|
| 103 |
+
|
| 104 |
+
## Training Data
|
| 105 |
+
|
| 106 |
+
We trained on a curated mixture with a strict cleaning pipeline that also removed topics not useful for a model of this size.
|
| 107 |
+
|
| 108 |
+
| Source | Percentage |
|
| 109 |
+
|---|---|
|
| 110 |
+
| FineWeb-Edu | 43.1% |
|
| 111 |
+
| Cosmopedia | 24.3% |
|
| 112 |
+
| OpenMathInstruct-2 | 13.5% |
|
| 113 |
+
| Tiny Strange Textbooks | 9.0% |
|
| 114 |
+
| MegaScience (medicine & biology, custom curated) | 5.0% |
|
| 115 |
+
| High-Quality English Sentences | 3.0% |
|
| 116 |
+
| ScienceQA | 1.2% |
|
| 117 |
+
| Orca-Math Word Problems 200k | 0.9% |
|
| 118 |
+
| **Total** | **100%** |
|
| 119 |
+
|
| 120 |
+
- **Tokenizer:** all data was tokenized with the model's 5,048-token BPE tokenizer, and 1% was held out for validation.
|
| 121 |
+
- **Blending:** sources were blended per dataset using the weights above.
|
| 122 |
+
|
| 123 |
+
## Limitations
|
| 124 |
+
|
| 125 |
+
- **Tiny model:** with 2.91M parameters and 144-dim hidden states, generations are often repetitive, incoherent or factually wrong. The model is a research artifact for studying small-scale LMs, not an assistant.
|
| 126 |
+
- **Short context:** 512 tokens maximum. RoPE tables are not built beyond that length.
|
| 127 |
+
- **English only:** trained on English web, educational, synthetic and math text.
|
| 128 |
+
- **Not instruction-tuned or safety-aligned:** it may reproduce biases present in web data.
|
| 129 |
+
|
| 130 |
+
## License
|
| 131 |
+
|
| 132 |
+
Model weights and code: MIT.
|
| 133 |
+
|
| 134 |
+
## Citation
|
| 135 |
+
|
| 136 |
+
```bibtex
|
| 137 |
+
@misc{tokle2026,
|
| 138 |
+
title = {{Tokle-3M}: Pointwise Mutual Information as a Removable
|
| 139 |
+
Inductive Bias for Self-Attention},
|
| 140 |
+
author = {{Tech.us Team}},
|
| 141 |
+
year = {2026},
|
| 142 |
+
publisher = {Hugging Face},
|
| 143 |
+
howpublished = {\url{https://huggingface.co/techdotus/Tokle-3M}}
|
| 144 |
+
}
|
| 145 |
+
```
|
config.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"TokleForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "configuration_tokle.TokleConfig",
|
| 7 |
+
"AutoModel": "modeling_tokle.TokleModel",
|
| 8 |
+
"AutoModelForCausalLM": "modeling_tokle.TokleForCausalLM"
|
| 9 |
+
},
|
| 10 |
+
"bos_token_id": 0,
|
| 11 |
+
"d_model": 144,
|
| 12 |
+
"dtype": "float32",
|
| 13 |
+
"eos_token_id": 1,
|
| 14 |
+
"ffn_hidden": 432,
|
| 15 |
+
"head_dim": 48,
|
| 16 |
+
"mask_padded_vocab_logits": true,
|
| 17 |
+
"max_seq_len": 512,
|
| 18 |
+
"model_type": "tokle",
|
| 19 |
+
"n_head": 3,
|
| 20 |
+
"n_kv_head": 1,
|
| 21 |
+
"n_layer": 9,
|
| 22 |
+
"norm_eps": 1e-05,
|
| 23 |
+
"pad_token_id": 2,
|
| 24 |
+
"real_vocab_size": 5048,
|
| 25 |
+
"rope_theta": 10000.0,
|
| 26 |
+
"transformers_version": "4.57.6",
|
| 27 |
+
"use_cache": false,
|
| 28 |
+
"vocab_size": 5056
|
| 29 |
+
}
|
configuration_tokle.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Tokle config. attribute_map aliases the short field names (n_layer, d_model,
|
| 2 |
+
...) to the ones Transformers and lm-eval look for.
|
| 3 |
+
"""
|
| 4 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class TokleConfig(PretrainedConfig):
|
| 8 |
+
"""Plain decoder-only LM: RMSNorm, RoPE, grouped-query attention with
|
| 9 |
+
QK-norm, SwiGLU, tied embeddings. No auxiliary tables or buffers.
|
| 10 |
+
|
| 11 |
+
Two fields are easy to trip over. vocab_size (5056) is the padded embedding
|
| 12 |
+
matrix; real_vocab_size (5048) is what the tokenizer can actually emit, and
|
| 13 |
+
the rows between them are unused filler. use_cache is False because the
|
| 14 |
+
model recomputes the prefix rather than carrying a KV cache.
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
model_type = "tokle"
|
| 18 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 19 |
+
|
| 20 |
+
attribute_map = {
|
| 21 |
+
"num_hidden_layers": "n_layer",
|
| 22 |
+
"hidden_size": "d_model",
|
| 23 |
+
"num_attention_heads": "n_head",
|
| 24 |
+
"num_key_value_heads": "n_kv_head",
|
| 25 |
+
"intermediate_size": "ffn_hidden",
|
| 26 |
+
"max_position_embeddings": "max_seq_len",
|
| 27 |
+
"rms_norm_eps": "norm_eps",
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
def __init__(
|
| 31 |
+
self,
|
| 32 |
+
vocab_size=5056,
|
| 33 |
+
real_vocab_size=5048,
|
| 34 |
+
max_seq_len=512,
|
| 35 |
+
n_layer=9,
|
| 36 |
+
d_model=144,
|
| 37 |
+
n_head=3,
|
| 38 |
+
n_kv_head=1,
|
| 39 |
+
head_dim=48,
|
| 40 |
+
ffn_hidden=432,
|
| 41 |
+
rope_theta=10000.0,
|
| 42 |
+
norm_eps=1e-5,
|
| 43 |
+
mask_padded_vocab_logits=True,
|
| 44 |
+
tie_word_embeddings=True,
|
| 45 |
+
bos_token_id=0,
|
| 46 |
+
eos_token_id=1,
|
| 47 |
+
pad_token_id=2,
|
| 48 |
+
use_cache=False,
|
| 49 |
+
**kwargs,
|
| 50 |
+
):
|
| 51 |
+
self.vocab_size = vocab_size
|
| 52 |
+
self.real_vocab_size = real_vocab_size
|
| 53 |
+
self.max_seq_len = max_seq_len
|
| 54 |
+
self.n_layer = n_layer
|
| 55 |
+
self.d_model = d_model
|
| 56 |
+
self.n_head = n_head
|
| 57 |
+
self.n_kv_head = n_kv_head
|
| 58 |
+
self.head_dim = head_dim
|
| 59 |
+
self.ffn_hidden = ffn_hidden
|
| 60 |
+
self.rope_theta = rope_theta
|
| 61 |
+
self.norm_eps = norm_eps
|
| 62 |
+
self.mask_padded_vocab_logits = mask_padded_vocab_logits
|
| 63 |
+
self.use_cache = use_cache
|
| 64 |
+
super().__init__(
|
| 65 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 66 |
+
bos_token_id=bos_token_id,
|
| 67 |
+
eos_token_id=eos_token_id,
|
| 68 |
+
pad_token_id=pad_token_id,
|
| 69 |
+
**kwargs,
|
| 70 |
+
)
|
generation_config.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token_id": 0,
|
| 3 |
+
"do_sample": true,
|
| 4 |
+
"eos_token_id": 1,
|
| 5 |
+
"max_new_tokens": 64,
|
| 6 |
+
"pad_token_id": 2,
|
| 7 |
+
"temperature": 0.8,
|
| 8 |
+
"top_p": 0.95,
|
| 9 |
+
"transformers_version": "4.57.6",
|
| 10 |
+
"use_cache": false
|
| 11 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:79a942536fbe699865c582b5a03f83f7e1a72dd13c71966593882162c1401f17
|
| 3 |
+
size 11646512
|
modeling_tokle.py
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Tokle: decoder-only transformer with RMSNorm, RoPE, GQA and SwiGLU.
|
| 2 |
+
|
| 3 |
+
Module and parameter names follow the usual Transformers layout.
|
| 4 |
+
|
| 5 |
+
Works on Transformers 4.x and 5.x; the v5 differences are marked inline.
|
| 6 |
+
"""
|
| 7 |
+
import math
|
| 8 |
+
from typing import Optional, Tuple, Union
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
import torch.nn as nn
|
| 12 |
+
import torch.nn.functional as F
|
| 13 |
+
from transformers import __version__ as _transformers_version
|
| 14 |
+
from transformers.generation import GenerationMixin
|
| 15 |
+
from transformers.modeling_outputs import BaseModelOutput, CausalLMOutput
|
| 16 |
+
from transformers.modeling_utils import PreTrainedModel
|
| 17 |
+
|
| 18 |
+
try: # as a Transformers dynamic module (trust_remote_code)
|
| 19 |
+
from .configuration_tokle import TokleConfig
|
| 20 |
+
except ImportError: # running the files straight out of a checkout
|
| 21 |
+
from configuration_tokle import TokleConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# ----------------------------------------------------------------------------- norms and rope
|
| 25 |
+
class TokleRMSNorm(nn.Module):
|
| 26 |
+
def __init__(self, d, eps=1e-5):
|
| 27 |
+
super().__init__()
|
| 28 |
+
self.eps = eps
|
| 29 |
+
self.weight = nn.Parameter(torch.ones(d))
|
| 30 |
+
|
| 31 |
+
def forward(self, x):
|
| 32 |
+
# Always reduce in fp32: in fp16 the mean of squares underflows on the
|
| 33 |
+
# long tail and the norm comes back slightly wrong.
|
| 34 |
+
dt = x.dtype
|
| 35 |
+
x = x.float()
|
| 36 |
+
x = x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
|
| 37 |
+
return (x * self.weight.float()).to(dt)
|
| 38 |
+
|
| 39 |
+
def extra_repr(self):
|
| 40 |
+
return f"{tuple(self.weight.shape)}, eps={self.eps}"
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def build_rope(head_dim, max_seq_len, theta, device=None):
|
| 44 |
+
inv = 1.0 / (theta ** (torch.arange(0, head_dim, 2, dtype=torch.float32,
|
| 45 |
+
device=device) / head_dim))
|
| 46 |
+
t = torch.arange(max_seq_len, dtype=torch.float32, device=device)
|
| 47 |
+
f = torch.outer(t, inv)
|
| 48 |
+
return torch.cos(f), torch.sin(f)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def apply_rope(x, cos, sin):
|
| 52 |
+
"""Half-split rotation (first half against second), not the interleaved
|
| 53 |
+
variant. The two are not interchangeable -- swapping them degrades output
|
| 54 |
+
without raising anything."""
|
| 55 |
+
b, h, t, d = x.shape
|
| 56 |
+
x1, x2 = x.float().chunk(2, dim=-1)
|
| 57 |
+
c = cos[:t].view(1, 1, t, d // 2).to(x1.device)
|
| 58 |
+
s = sin[:t].view(1, 1, t, d // 2).to(x1.device)
|
| 59 |
+
return torch.cat([x1 * c - x2 * s, x1 * s + x2 * c], dim=-1).to(x.dtype)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# ----------------------------------------------------------------------------- blocks
|
| 63 |
+
class TokleAttention(nn.Module):
|
| 64 |
+
def __init__(self, config: TokleConfig, layer_idx: int):
|
| 65 |
+
super().__init__()
|
| 66 |
+
self.layer_idx = layer_idx
|
| 67 |
+
self.n_head = config.n_head
|
| 68 |
+
self.n_kv_head = config.n_kv_head
|
| 69 |
+
self.head_dim = config.head_dim
|
| 70 |
+
self.rep = config.n_head // config.n_kv_head
|
| 71 |
+
self.q_proj = nn.Linear(config.d_model, config.n_head * config.head_dim, bias=False)
|
| 72 |
+
self.k_proj = nn.Linear(config.d_model, config.n_kv_head * config.head_dim, bias=False)
|
| 73 |
+
self.v_proj = nn.Linear(config.d_model, config.n_kv_head * config.head_dim, bias=False)
|
| 74 |
+
self.o_proj = nn.Linear(config.n_head * config.head_dim, config.d_model, bias=False)
|
| 75 |
+
self.q_norm = TokleRMSNorm(config.head_dim, config.norm_eps)
|
| 76 |
+
self.k_norm = TokleRMSNorm(config.head_dim, config.norm_eps)
|
| 77 |
+
|
| 78 |
+
def forward(self, x, cos, sin, attn_mask):
|
| 79 |
+
b, t, _ = x.shape
|
| 80 |
+
q = self.q_proj(x).view(b, t, self.n_head, self.head_dim).transpose(1, 2)
|
| 81 |
+
k = self.k_proj(x).view(b, t, self.n_kv_head, self.head_dim).transpose(1, 2)
|
| 82 |
+
v = self.v_proj(x).view(b, t, self.n_kv_head, self.head_dim).transpose(1, 2)
|
| 83 |
+
# QK-norm is applied before rope.
|
| 84 |
+
q = apply_rope(self.q_norm(q), cos, sin)
|
| 85 |
+
k = apply_rope(self.k_norm(k), cos, sin)
|
| 86 |
+
k = k.repeat_interleave(self.rep, dim=1)
|
| 87 |
+
v = v.repeat_interleave(self.rep, dim=1)
|
| 88 |
+
if attn_mask is None:
|
| 89 |
+
# Nothing padded: let SDPA build the causal mask itself, which is
|
| 90 |
+
# the fast kernel path and what an unpadded forward always hits.
|
| 91 |
+
o = F.scaled_dot_product_attention(q, k, v, is_causal=True)
|
| 92 |
+
else:
|
| 93 |
+
o = F.scaled_dot_product_attention(q, k, v, attn_mask=attn_mask.to(q.dtype))
|
| 94 |
+
return self.o_proj(o.transpose(1, 2).reshape(b, t, -1))
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
class TokleMLP(nn.Module):
|
| 98 |
+
def __init__(self, config: TokleConfig):
|
| 99 |
+
super().__init__()
|
| 100 |
+
self.gate_proj = nn.Linear(config.d_model, config.ffn_hidden, bias=False)
|
| 101 |
+
self.up_proj = nn.Linear(config.d_model, config.ffn_hidden, bias=False)
|
| 102 |
+
self.down_proj = nn.Linear(config.ffn_hidden, config.d_model, bias=False)
|
| 103 |
+
|
| 104 |
+
def forward(self, x):
|
| 105 |
+
return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
class TokleDecoderLayer(nn.Module):
|
| 109 |
+
def __init__(self, config: TokleConfig, layer_idx: int):
|
| 110 |
+
super().__init__()
|
| 111 |
+
self.input_layernorm = TokleRMSNorm(config.d_model, config.norm_eps)
|
| 112 |
+
self.self_attn = TokleAttention(config, layer_idx)
|
| 113 |
+
self.post_attention_layernorm = TokleRMSNorm(config.d_model, config.norm_eps)
|
| 114 |
+
self.mlp = TokleMLP(config)
|
| 115 |
+
|
| 116 |
+
def forward(self, x, cos, sin, attn_mask):
|
| 117 |
+
x = x + self.self_attn(self.input_layernorm(x), cos, sin, attn_mask)
|
| 118 |
+
return x + self.mlp(self.post_attention_layernorm(x))
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
# ----------------------------------------------------------------------------- model
|
| 122 |
+
class ToklePreTrainedModel(PreTrainedModel):
|
| 123 |
+
config_class = TokleConfig
|
| 124 |
+
base_model_prefix = "model"
|
| 125 |
+
supports_gradient_checkpointing = True
|
| 126 |
+
_no_split_modules = ["TokleDecoderLayer"]
|
| 127 |
+
_supports_sdpa = True
|
| 128 |
+
|
| 129 |
+
def _init_weights(self, module):
|
| 130 |
+
if isinstance(module, nn.Linear):
|
| 131 |
+
nn.init.normal_(module.weight, 0.0, 0.02)
|
| 132 |
+
if module.bias is not None:
|
| 133 |
+
nn.init.zeros_(module.bias)
|
| 134 |
+
elif isinstance(module, nn.Embedding):
|
| 135 |
+
nn.init.normal_(module.weight, 0.0, 0.02)
|
| 136 |
+
elif isinstance(module, TokleRMSNorm):
|
| 137 |
+
nn.init.ones_(module.weight)
|
| 138 |
+
# Residual-output projections get scaled down by depth so the residual
|
| 139 |
+
# stream does not blow up at init (GPT-2 trick).
|
| 140 |
+
if isinstance(module, (TokleAttention, TokleMLP)):
|
| 141 |
+
out = module.o_proj if isinstance(module, TokleAttention) else module.down_proj
|
| 142 |
+
nn.init.normal_(out.weight, 0.0, 0.02 / math.sqrt(2 * self.config.n_layer))
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
class TokleModel(ToklePreTrainedModel):
|
| 146 |
+
def __init__(self, config: TokleConfig):
|
| 147 |
+
super().__init__(config)
|
| 148 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.d_model)
|
| 149 |
+
self.layers = nn.ModuleList(
|
| 150 |
+
[TokleDecoderLayer(config, i) for i in range(config.n_layer)])
|
| 151 |
+
self.norm = TokleRMSNorm(config.d_model, config.norm_eps)
|
| 152 |
+
# A plain dict, not a buffer. Transformers 5 builds models on the meta
|
| 153 |
+
# device and fills only tensors the weights file contains, so a
|
| 154 |
+
# non-persistent buffer would come back as uninitialised memory.
|
| 155 |
+
# Keyed by device, so .to()/.cuda() need not move anything.
|
| 156 |
+
self._rope_cache = {}
|
| 157 |
+
self.gradient_checkpointing = False
|
| 158 |
+
self.post_init()
|
| 159 |
+
|
| 160 |
+
def get_input_embeddings(self):
|
| 161 |
+
return self.embed_tokens
|
| 162 |
+
|
| 163 |
+
def set_input_embeddings(self, value):
|
| 164 |
+
self.embed_tokens = value
|
| 165 |
+
|
| 166 |
+
def rope(self, device):
|
| 167 |
+
key = str(device)
|
| 168 |
+
if key not in self._rope_cache:
|
| 169 |
+
self._rope_cache[key] = build_rope(
|
| 170 |
+
self.config.head_dim, self.config.max_seq_len,
|
| 171 |
+
self.config.rope_theta, device=device)
|
| 172 |
+
return self._rope_cache[key]
|
| 173 |
+
|
| 174 |
+
def _causal_pad_mask(self, attention_mask, t, dtype, device):
|
| 175 |
+
"""Additive (b, 1, 1, t) padding mask folded together with the causal
|
| 176 |
+
mask, or None when nothing is padded so the caller can take the
|
| 177 |
+
is_causal fast path."""
|
| 178 |
+
if attention_mask is None:
|
| 179 |
+
return None
|
| 180 |
+
attention_mask = attention_mask.to(torch.bool)
|
| 181 |
+
if bool(attention_mask.all()):
|
| 182 |
+
return None
|
| 183 |
+
m = torch.zeros(attention_mask.shape, dtype=dtype, device=device)
|
| 184 |
+
m = m.masked_fill(~attention_mask, torch.finfo(dtype).min)[:, None, None, :]
|
| 185 |
+
# Under causal attention with right padding, position 0 always sees
|
| 186 |
+
# itself, so no row ends up fully masked (which would give NaNs).
|
| 187 |
+
causal = torch.ones(t, t, dtype=torch.bool, device=device).triu(1)
|
| 188 |
+
return m.masked_fill(causal, torch.finfo(dtype).min)
|
| 189 |
+
|
| 190 |
+
def forward(
|
| 191 |
+
self,
|
| 192 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 193 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 194 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 195 |
+
output_hidden_states: Optional[bool] = None,
|
| 196 |
+
return_dict: Optional[bool] = None,
|
| 197 |
+
**kwargs,
|
| 198 |
+
) -> Union[Tuple, BaseModelOutput]:
|
| 199 |
+
# getattr, not config.use_return_dict: that property is deprecated in
|
| 200 |
+
# Transformers 5 and warns on every call.
|
| 201 |
+
return_dict = (return_dict if return_dict is not None
|
| 202 |
+
else getattr(self.config, "return_dict", True))
|
| 203 |
+
output_hidden_states = (output_hidden_states if output_hidden_states is not None
|
| 204 |
+
else self.config.output_hidden_states)
|
| 205 |
+
if (input_ids is None) == (inputs_embeds is None):
|
| 206 |
+
raise ValueError("Pass exactly one of input_ids or inputs_embeds.")
|
| 207 |
+
|
| 208 |
+
x = self.embed_tokens(input_ids) if inputs_embeds is None else inputs_embeds
|
| 209 |
+
t = x.shape[1]
|
| 210 |
+
if t > self.config.max_seq_len:
|
| 211 |
+
raise ValueError(
|
| 212 |
+
f"Sequence length {t} exceeds max_seq_len {self.config.max_seq_len}.")
|
| 213 |
+
|
| 214 |
+
cos, sin = self.rope(x.device)
|
| 215 |
+
mask = self._causal_pad_mask(attention_mask, t, x.dtype, x.device)
|
| 216 |
+
|
| 217 |
+
hidden_states = () if output_hidden_states else None
|
| 218 |
+
for layer in self.layers:
|
| 219 |
+
if output_hidden_states:
|
| 220 |
+
hidden_states += (x,)
|
| 221 |
+
if self.gradient_checkpointing and self.training:
|
| 222 |
+
x = self._gradient_checkpointing_func(layer.__call__, x, cos, sin, mask)
|
| 223 |
+
else:
|
| 224 |
+
x = layer(x, cos, sin, mask)
|
| 225 |
+
x = self.norm(x)
|
| 226 |
+
if output_hidden_states:
|
| 227 |
+
hidden_states += (x,)
|
| 228 |
+
|
| 229 |
+
if not return_dict:
|
| 230 |
+
return tuple(v for v in (x, hidden_states) if v is not None)
|
| 231 |
+
return BaseModelOutput(last_hidden_state=x, hidden_states=hidden_states)
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
# Transformers 5 turned _tied_weights_keys from a list of names into a
|
| 235 |
+
# {tied: source} mapping and calls .keys() on it, so the old form raises.
|
| 236 |
+
_TRANSFORMERS_V5 = int(_transformers_version.split(".")[0]) >= 5
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
class TokleForCausalLM(ToklePreTrainedModel, GenerationMixin):
|
| 240 |
+
_tied_weights_keys = ({"lm_head.weight": "model.embed_tokens.weight"}
|
| 241 |
+
if _TRANSFORMERS_V5 else ["lm_head.weight"])
|
| 242 |
+
|
| 243 |
+
def __init__(self, config: TokleConfig):
|
| 244 |
+
super().__init__(config)
|
| 245 |
+
self.model = TokleModel(config)
|
| 246 |
+
self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False)
|
| 247 |
+
self.post_init()
|
| 248 |
+
|
| 249 |
+
def get_input_embeddings(self):
|
| 250 |
+
return self.model.embed_tokens
|
| 251 |
+
|
| 252 |
+
def set_input_embeddings(self, value):
|
| 253 |
+
self.model.embed_tokens = value
|
| 254 |
+
|
| 255 |
+
def get_output_embeddings(self):
|
| 256 |
+
return self.lm_head
|
| 257 |
+
|
| 258 |
+
def set_output_embeddings(self, new_embeddings):
|
| 259 |
+
self.lm_head = new_embeddings
|
| 260 |
+
|
| 261 |
+
def get_decoder(self):
|
| 262 |
+
return self.model
|
| 263 |
+
|
| 264 |
+
def forward(
|
| 265 |
+
self,
|
| 266 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 267 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 268 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 269 |
+
labels: Optional[torch.LongTensor] = None,
|
| 270 |
+
output_hidden_states: Optional[bool] = None,
|
| 271 |
+
return_dict: Optional[bool] = None,
|
| 272 |
+
**kwargs,
|
| 273 |
+
) -> Union[Tuple, CausalLMOutput]:
|
| 274 |
+
return_dict = (return_dict if return_dict is not None
|
| 275 |
+
else getattr(self.config, "return_dict", True))
|
| 276 |
+
out = self.model(
|
| 277 |
+
input_ids=input_ids,
|
| 278 |
+
attention_mask=attention_mask,
|
| 279 |
+
inputs_embeds=inputs_embeds,
|
| 280 |
+
output_hidden_states=output_hidden_states,
|
| 281 |
+
return_dict=True,
|
| 282 |
+
)
|
| 283 |
+
logits = self.lm_head(out.last_hidden_state)
|
| 284 |
+
# Rows past real_vocab_size only pad the matrix to a multiple of 64 and
|
| 285 |
+
# carry no meaning, so keep them out of sampling and out of any
|
| 286 |
+
# log-likelihood an evaluation harness sums.
|
| 287 |
+
rv = self.config.real_vocab_size
|
| 288 |
+
if self.config.mask_padded_vocab_logits and rv is not None and rv < self.config.vocab_size:
|
| 289 |
+
logits = logits.clone()
|
| 290 |
+
logits[..., rv:] = float("-inf")
|
| 291 |
+
|
| 292 |
+
loss = None
|
| 293 |
+
if labels is not None:
|
| 294 |
+
loss = self.loss_function(logits=logits, labels=labels,
|
| 295 |
+
vocab_size=self.config.vocab_size, **kwargs)
|
| 296 |
+
|
| 297 |
+
if not return_dict:
|
| 298 |
+
return (loss, logits) if loss is not None else (logits,)
|
| 299 |
+
return CausalLMOutput(loss=loss, logits=logits, hidden_states=out.hidden_states)
|
special_tokens_map.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": {
|
| 3 |
+
"content": "<s>",
|
| 4 |
+
"lstrip": false,
|
| 5 |
+
"normalized": false,
|
| 6 |
+
"rstrip": false,
|
| 7 |
+
"single_word": false
|
| 8 |
+
},
|
| 9 |
+
"eos_token": {
|
| 10 |
+
"content": "</s>",
|
| 11 |
+
"lstrip": false,
|
| 12 |
+
"normalized": false,
|
| 13 |
+
"rstrip": false,
|
| 14 |
+
"single_word": false
|
| 15 |
+
},
|
| 16 |
+
"pad_token": {
|
| 17 |
+
"content": "<pad>",
|
| 18 |
+
"lstrip": false,
|
| 19 |
+
"normalized": false,
|
| 20 |
+
"rstrip": false,
|
| 21 |
+
"single_word": false
|
| 22 |
+
}
|
| 23 |
+
}
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|