Add files using upload-large-folder tool
Browse files- README.md +86 -0
- audiovae.pth +3 -0
- config.json +67 -0
- lora_adapter/configs/voxcpm_finetune_lora.yaml +34 -0
- lora_adapter/lora_config.json +29 -0
- lora_adapter/lora_weights.safetensors +3 -0
- lora_adapter/training_state.json +1 -0
- merge_manifest.json +40 -0
- model.safetensors +3 -0
- special_tokens_map.json +81 -0
- tokenization_voxcpm2.py +72 -0
- tokenizer.json +0 -0
- tokenizer_config.json +218 -0
README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
base_model: openbmb/VoxCPM2
|
| 4 |
+
tags:
|
| 5 |
+
- text-to-speech
|
| 6 |
+
- turkish
|
| 7 |
+
- voxcpm2
|
| 8 |
+
- merged-lora
|
| 9 |
+
- speech-synthesis
|
| 10 |
+
- trendyol-tts
|
| 11 |
+
language:
|
| 12 |
+
- tr
|
| 13 |
+
pipeline_tag: text-to-speech
|
| 14 |
+
datasets:
|
| 15 |
+
- AlicanKiraz0/TR-Voice-TTS
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
# Trendyol-TTS
|
| 19 |
+
|
| 20 |
+
Trendyol-TTS is a Turkish text-to-speech research model derived from the Kahya TTS `step_2000` checkpoint. It contains a full merged VoxCPM2 model: the Kahya Turkish LoRA adapter has been applied to the `openbmb/VoxCPM2` base weights so the repository can be loaded as a standalone model artifact.
|
| 21 |
+
|
| 22 |
+
## Model Summary
|
| 23 |
+
|
| 24 |
+
- **Model type:** Turkish text-to-speech / speech synthesis
|
| 25 |
+
- **Base model:** `openbmb/VoxCPM2`
|
| 26 |
+
- **Source checkpoint:** `AlicanKiraz0/Kahya-TTS-step_2000`
|
| 27 |
+
- **Target repository:** `AlicanKiraz0/Trendyol-TTS`
|
| 28 |
+
- **Fine-tuning method:** LoRA adapter merged into the base model weights
|
| 29 |
+
- **Training dataset:** `AlicanKiraz0/TR-Voice-TTS`
|
| 30 |
+
- **Primary language:** Turkish (`tr`)
|
| 31 |
+
- **Recommended default checkpoint:** `step_0002000`
|
| 32 |
+
|
| 33 |
+
## Contents
|
| 34 |
+
|
| 35 |
+
This repository mirrors the merged `step_2000` model artifacts and includes:
|
| 36 |
+
|
| 37 |
+
- `model.safetensors`: merged VoxCPM2 weights with the Turkish LoRA adapter applied.
|
| 38 |
+
- `config.json`, tokenizer files, and `audiovae.pth`: runtime files inherited from `openbmb/VoxCPM2`.
|
| 39 |
+
- `merge_manifest.json`: source model, adapter, checkpoint, and merge metadata.
|
| 40 |
+
- `lora_adapter/`: original LoRA adapter files preserved for provenance and auditability.
|
| 41 |
+
|
| 42 |
+
## Intended Use
|
| 43 |
+
|
| 44 |
+
Trendyol-TTS is intended for Turkish TTS research, prototyping, and controlled internal evaluation. It is suitable for generating Turkish speech samples and comparing voice quality under fixed inference settings.
|
| 45 |
+
|
| 46 |
+
This repository is **not** a production serving endpoint by itself. Before production use, validate latency, throughput, stability, monitoring, abuse prevention, and output quality on the intended serving stack.
|
| 47 |
+
|
| 48 |
+
## Recommended Inference Settings
|
| 49 |
+
|
| 50 |
+
The currently recommended clean default settings are:
|
| 51 |
+
|
| 52 |
+
```text
|
| 53 |
+
cfg_value = 2.0
|
| 54 |
+
inference_timesteps = 16
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
A more expressive/natural setting to test is:
|
| 58 |
+
|
| 59 |
+
```text
|
| 60 |
+
cfg_value = 1.5
|
| 61 |
+
inference_timesteps = 16
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
Avoid using `cfg_value=2.5` as a general production default. Prior audio proxy checks showed peaks getting too close to `0 dBFS` in some samples, even when clipping fraction was zero.
|
| 65 |
+
|
| 66 |
+
## Evaluation Notes
|
| 67 |
+
|
| 68 |
+
The source `step_2000` checkpoint was selected as the default based on human listening preference, a snappy response profile, and the absence of obvious production-level regressions in the available evaluation set. Later continuation checkpoints (`step_0002250` and `step_0002500`) remain internal archive/challenger artifacts and are not promoted as the default.
|
| 69 |
+
|
| 70 |
+
Recent blind-evaluation tooling separates public listener packages from private mapping and resolved metrics. For release-grade evaluation, use public blind packages only during listening and generate post-unblind reports after mapping is opened.
|
| 71 |
+
|
| 72 |
+
## Limitations
|
| 73 |
+
|
| 74 |
+
- The model is a research artifact and should be validated before customer-facing deployment.
|
| 75 |
+
- The training data is a private Turkish speech dataset; distribution and usage should respect the dataset owner policies.
|
| 76 |
+
- Formal MOS, large-scale stress testing, ASR/CER semantic regression checks, and production serving validation are not included in this model repository.
|
| 77 |
+
- Generated speech may still contain pronunciation, prosody, normalization, or artifact issues, especially for unusual names, abbreviations, numbers, and long-form text.
|
| 78 |
+
- This model should not be used for impersonation, deception, unauthorized voice cloning, or any use that violates applicable law or platform policy.
|
| 79 |
+
|
| 80 |
+
## Provenance
|
| 81 |
+
|
| 82 |
+
This repository was copied from `AlicanKiraz0/Kahya-TTS-step_2000` and rebranded as `Trendyol-TTS`. The model weights are expected to be identical to the source merged `step_2000` model, except for the model card and repository metadata.
|
| 83 |
+
|
| 84 |
+
## License
|
| 85 |
+
|
| 86 |
+
The code/model artifact metadata follows the Apache-2.0 license declared by the upstream VoxCPM2 model where applicable. Users are responsible for checking the licenses and usage terms of `openbmb/VoxCPM2`, the dataset, and any downstream deployment environment.
|
audiovae.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:94b5d51e107e0507d4acc976cfdadb64edd6fd06d1f751dadbf2fd1594274bf1
|
| 3 |
+
size 376951122
|
config.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architecture": "voxcpm2",
|
| 3 |
+
"lm_config": {
|
| 4 |
+
"bos_token_id": 1,
|
| 5 |
+
"eos_token_id": 2,
|
| 6 |
+
"hidden_size": 2048,
|
| 7 |
+
"intermediate_size": 6144,
|
| 8 |
+
"max_position_embeddings": 32768,
|
| 9 |
+
"num_attention_heads": 16,
|
| 10 |
+
"num_hidden_layers": 28,
|
| 11 |
+
"num_key_value_heads": 2,
|
| 12 |
+
"rms_norm_eps": 1e-05,
|
| 13 |
+
"rope_theta": 10000,
|
| 14 |
+
"kv_channels": 128,
|
| 15 |
+
"rope_scaling": {
|
| 16 |
+
"type": "longrope",
|
| 17 |
+
"long_factor": [0.9977997200264581, 1.014658295992452, 1.0349680404997148, 1.059429246056193, 1.0888815016813513, 1.1243301355211495, 1.166977103606075, 1.2182568066927284, 1.2798772354275727, 1.3538666751582975, 1.4426259039919596, 1.5489853358570191, 1.6762658237220625, 1.8283407612492941, 2.0096956085876183, 2.225478927469756, 2.481536379650452, 2.784415934557119, 3.1413289096347365, 3.560047844772632, 4.048719380066383, 4.615569542115128, 5.2684819496549835, 6.014438591970396, 6.858830049237097, 7.804668263503327, 8.851768731513417, 9.99600492938444, 11.228766118181639, 12.536757560834843, 13.902257701387796, 15.303885189125953, 16.717837610115794, 18.119465097853947, 19.484965238406907, 20.792956681060105, 22.02571786985731, 23.16995406772833, 24.217054535738416, 25.16289275000465, 26.007284207271347, 26.753240849586767, 27.40615325712662, 27.973003419175363, 28.461674954469114, 28.880393889607006, 29.237306864684626, 29.540186419591297, 29.79624387177199, 30.01202719065413, 30.193382037992453, 30.34545697551969, 30.47273746338473, 30.579096895249787, 30.66785612408345, 30.741845563814174, 30.80346599254902, 30.85474569563567, 30.897392663720595, 30.932841297560394, 30.962293553185553, 30.986754758742034, 31.007064503249293, 31.02392307921529],
|
| 18 |
+
"short_factor": [0.9977997200264581, 1.014658295992452, 1.0349680404997148, 1.059429246056193, 1.0888815016813513, 1.1243301355211495, 1.166977103606075, 1.2182568066927284, 1.2798772354275727, 1.3538666751582975, 1.4426259039919596, 1.5489853358570191, 1.6762658237220625, 1.8283407612492941, 2.0096956085876183, 2.225478927469756, 2.481536379650452, 2.784415934557119, 3.1413289096347365, 3.560047844772632, 4.048719380066383, 4.615569542115128, 5.2684819496549835, 6.014438591970396, 6.858830049237097, 7.804668263503327, 8.851768731513417, 9.99600492938444, 11.228766118181639, 12.536757560834843, 13.902257701387796, 15.303885189125953, 16.717837610115794, 18.119465097853947, 19.484965238406907, 20.792956681060105, 22.02571786985731, 23.16995406772833, 24.217054535738416, 25.16289275000465, 26.007284207271347, 26.753240849586767, 27.40615325712662, 27.973003419175363, 28.461674954469114, 28.880393889607006, 29.237306864684626, 29.540186419591297, 29.79624387177199, 30.01202719065413, 30.193382037992453, 30.34545697551969, 30.47273746338473, 30.579096895249787, 30.66785612408345, 30.741845563814174, 30.80346599254902, 30.85474569563567, 30.897392663720595, 30.932841297560394, 30.962293553185553, 30.986754758742034, 31.007064503249293, 31.02392307921529],
|
| 19 |
+
"original_max_position_embeddings": 32768
|
| 20 |
+
},
|
| 21 |
+
"vocab_size": 73448,
|
| 22 |
+
"use_mup": false,
|
| 23 |
+
"scale_emb": 12,
|
| 24 |
+
"dim_model_base": 256,
|
| 25 |
+
"scale_depth": 1.4
|
| 26 |
+
},
|
| 27 |
+
"patch_size": 4,
|
| 28 |
+
"feat_dim": 64,
|
| 29 |
+
"scalar_quantization_latent_dim": 512,
|
| 30 |
+
"scalar_quantization_scale": 9,
|
| 31 |
+
"residual_lm_num_layers": 8,
|
| 32 |
+
"residual_lm_no_rope": true,
|
| 33 |
+
"encoder_config": {
|
| 34 |
+
"hidden_dim": 1024,
|
| 35 |
+
"ffn_dim": 4096,
|
| 36 |
+
"num_heads": 16,
|
| 37 |
+
"num_layers": 12,
|
| 38 |
+
"kv_channels": 128
|
| 39 |
+
},
|
| 40 |
+
"dit_config": {
|
| 41 |
+
"hidden_dim": 1024,
|
| 42 |
+
"ffn_dim": 4096,
|
| 43 |
+
"num_heads": 16,
|
| 44 |
+
"num_layers": 12,
|
| 45 |
+
"kv_channels": 128,
|
| 46 |
+
"mean_mode": false,
|
| 47 |
+
"cfm_config": {
|
| 48 |
+
"sigma_min": 1e-06,
|
| 49 |
+
"solver": "euler",
|
| 50 |
+
"t_scheduler": "log-norm",
|
| 51 |
+
"inference_cfg_rate": 2.0
|
| 52 |
+
}
|
| 53 |
+
},
|
| 54 |
+
"audio_vae_config": {
|
| 55 |
+
"encoder_dim": 128,
|
| 56 |
+
"encoder_rates": [2, 5, 8, 8],
|
| 57 |
+
"latent_dim": 64,
|
| 58 |
+
"decoder_dim": 2048,
|
| 59 |
+
"decoder_rates": [8, 6, 5, 2, 2, 2],
|
| 60 |
+
"sr_bin_boundaries": [20000, 30000, 40000],
|
| 61 |
+
"sample_rate": 16000,
|
| 62 |
+
"out_sample_rate": 48000
|
| 63 |
+
},
|
| 64 |
+
"max_length": 8192,
|
| 65 |
+
"device": "cuda",
|
| 66 |
+
"dtype": "bfloat16"
|
| 67 |
+
}
|
lora_adapter/configs/voxcpm_finetune_lora.yaml
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pretrained_path: /workspace/models/VoxCPM2/
|
| 2 |
+
train_manifest: /workspace/data/voxcpm_manifests/train.jsonl
|
| 3 |
+
val_manifest: /workspace/data/voxcpm_manifests/val.jsonl
|
| 4 |
+
|
| 5 |
+
sample_rate: 16000
|
| 6 |
+
out_sample_rate: 48000
|
| 7 |
+
batch_size: 2
|
| 8 |
+
grad_accum_steps: 8
|
| 9 |
+
num_workers: 2
|
| 10 |
+
num_iters: 2000
|
| 11 |
+
log_interval: 10
|
| 12 |
+
valid_interval: 250
|
| 13 |
+
save_interval: 250
|
| 14 |
+
|
| 15 |
+
learning_rate: 0.0001
|
| 16 |
+
weight_decay: 0.01
|
| 17 |
+
warmup_steps: 200
|
| 18 |
+
max_steps: 2000
|
| 19 |
+
max_batch_tokens: 8192
|
| 20 |
+
|
| 21 |
+
save_path: /workspace/checkpoints/lora
|
| 22 |
+
tensorboard: /workspace/logs/lora
|
| 23 |
+
|
| 24 |
+
lambdas:
|
| 25 |
+
loss/diff: 1.0
|
| 26 |
+
loss/stop: 1.0
|
| 27 |
+
|
| 28 |
+
lora:
|
| 29 |
+
enable_lm: true
|
| 30 |
+
enable_dit: true
|
| 31 |
+
enable_proj: false
|
| 32 |
+
r: 64
|
| 33 |
+
alpha: 64
|
| 34 |
+
dropout: 0.0
|
lora_adapter/lora_config.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"base_model": "/workspace/models/VoxCPM2/",
|
| 3 |
+
"lora_config": {
|
| 4 |
+
"enable_lm": true,
|
| 5 |
+
"enable_dit": true,
|
| 6 |
+
"enable_proj": false,
|
| 7 |
+
"r": 64,
|
| 8 |
+
"alpha": 64,
|
| 9 |
+
"dropout": 0.0,
|
| 10 |
+
"target_modules_lm": [
|
| 11 |
+
"q_proj",
|
| 12 |
+
"v_proj",
|
| 13 |
+
"k_proj",
|
| 14 |
+
"o_proj"
|
| 15 |
+
],
|
| 16 |
+
"target_modules_dit": [
|
| 17 |
+
"q_proj",
|
| 18 |
+
"v_proj",
|
| 19 |
+
"k_proj",
|
| 20 |
+
"o_proj"
|
| 21 |
+
],
|
| 22 |
+
"target_proj_modules": [
|
| 23 |
+
"enc_to_lm_proj",
|
| 24 |
+
"lm_to_dit_proj",
|
| 25 |
+
"res_to_dit_proj",
|
| 26 |
+
"fusion_concat_proj"
|
| 27 |
+
]
|
| 28 |
+
}
|
| 29 |
+
}
|
lora_adapter/lora_weights.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d3cf875aa83035a802234fe6b750e03c3b17d956e1ae6ce36c6b0ffaadd7afa9
|
| 3 |
+
size 144749240
|
lora_adapter/training_state.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"step": 2000}
|
merge_manifest.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"base_model": "openbmb/VoxCPM2",
|
| 3 |
+
"adapter_source": "AlicanKiraz0/Kahya-TTS-Turkish",
|
| 4 |
+
"checkpoint_step": 2000,
|
| 5 |
+
"training_state": {
|
| 6 |
+
"step": 2000
|
| 7 |
+
},
|
| 8 |
+
"lora_config": {
|
| 9 |
+
"base_model": "/workspace/models/VoxCPM2/",
|
| 10 |
+
"lora_config": {
|
| 11 |
+
"enable_lm": true,
|
| 12 |
+
"enable_dit": true,
|
| 13 |
+
"enable_proj": false,
|
| 14 |
+
"r": 64,
|
| 15 |
+
"alpha": 64,
|
| 16 |
+
"dropout": 0.0,
|
| 17 |
+
"target_modules_lm": [
|
| 18 |
+
"q_proj",
|
| 19 |
+
"v_proj",
|
| 20 |
+
"k_proj",
|
| 21 |
+
"o_proj"
|
| 22 |
+
],
|
| 23 |
+
"target_modules_dit": [
|
| 24 |
+
"q_proj",
|
| 25 |
+
"v_proj",
|
| 26 |
+
"k_proj",
|
| 27 |
+
"o_proj"
|
| 28 |
+
],
|
| 29 |
+
"target_proj_modules": [
|
| 30 |
+
"enc_to_lm_proj",
|
| 31 |
+
"lm_to_dit_proj",
|
| 32 |
+
"res_to_dit_proj",
|
| 33 |
+
"fusion_concat_proj"
|
| 34 |
+
]
|
| 35 |
+
}
|
| 36 |
+
},
|
| 37 |
+
"merge_scale": 1.0,
|
| 38 |
+
"merged_target_weights": 192,
|
| 39 |
+
"base_snapshot": "bffb3df5a29440629464e5e839f4d214c8714c3d"
|
| 40 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:70073e6d60adbceceea60ba3eb027fb5c57688cf40553f6e221a5546e7c87f9a
|
| 3 |
+
size 4580080752
|
special_tokens_map.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"additional_special_tokens": [
|
| 3 |
+
{
|
| 4 |
+
"content": "<|im_end|>",
|
| 5 |
+
"lstrip": false,
|
| 6 |
+
"normalized": false,
|
| 7 |
+
"rstrip": false,
|
| 8 |
+
"single_word": false
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"content": "<|im_start|>",
|
| 12 |
+
"lstrip": false,
|
| 13 |
+
"normalized": false,
|
| 14 |
+
"rstrip": false,
|
| 15 |
+
"single_word": false
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"content": "<|tool_call|>",
|
| 19 |
+
"lstrip": false,
|
| 20 |
+
"normalized": false,
|
| 21 |
+
"rstrip": false,
|
| 22 |
+
"single_word": false
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
"content": "<|execute_start|>",
|
| 26 |
+
"lstrip": false,
|
| 27 |
+
"normalized": false,
|
| 28 |
+
"rstrip": false,
|
| 29 |
+
"single_word": false
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"content": "<|execute_end|>",
|
| 33 |
+
"lstrip": false,
|
| 34 |
+
"normalized": false,
|
| 35 |
+
"rstrip": false,
|
| 36 |
+
"single_word": false
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"content": "<|fim_prefix|>",
|
| 40 |
+
"lstrip": false,
|
| 41 |
+
"normalized": false,
|
| 42 |
+
"rstrip": false,
|
| 43 |
+
"single_word": false
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"content": "<|fim_middle|>",
|
| 47 |
+
"lstrip": false,
|
| 48 |
+
"normalized": false,
|
| 49 |
+
"rstrip": false,
|
| 50 |
+
"single_word": false
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"content": "<|fim_suffix|>",
|
| 54 |
+
"lstrip": false,
|
| 55 |
+
"normalized": false,
|
| 56 |
+
"rstrip": false,
|
| 57 |
+
"single_word": false
|
| 58 |
+
}
|
| 59 |
+
],
|
| 60 |
+
"bos_token": {
|
| 61 |
+
"content": "<s>",
|
| 62 |
+
"lstrip": false,
|
| 63 |
+
"normalized": false,
|
| 64 |
+
"rstrip": false,
|
| 65 |
+
"single_word": false
|
| 66 |
+
},
|
| 67 |
+
"eos_token": {
|
| 68 |
+
"content": "</s>",
|
| 69 |
+
"lstrip": false,
|
| 70 |
+
"normalized": false,
|
| 71 |
+
"rstrip": false,
|
| 72 |
+
"single_word": false
|
| 73 |
+
},
|
| 74 |
+
"unk_token": {
|
| 75 |
+
"content": "<unk>",
|
| 76 |
+
"lstrip": false,
|
| 77 |
+
"normalized": false,
|
| 78 |
+
"rstrip": false,
|
| 79 |
+
"single_word": false
|
| 80 |
+
}
|
| 81 |
+
}
|
tokenization_voxcpm2.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Custom tokenizer for VoxCPM2 that splits multi-character Chinese tokens.
|
| 2 |
+
|
| 3 |
+
VoxCPM2 was trained with ``mask_multichar_chinese_tokens`` which splits
|
| 4 |
+
multi-character Chinese tokens (e.g. "你好" -> ["你", "好"]) into individual
|
| 5 |
+
character IDs before embedding. The base LlamaTokenizerFast produces
|
| 6 |
+
multi-character Chinese tokens that the model has never seen during training,
|
| 7 |
+
yielding garbled Chinese audio output in downstream inference frameworks.
|
| 8 |
+
|
| 9 |
+
This module provides ``VoxCPM2Tokenizer`` which transparently applies the
|
| 10 |
+
character splitting inside ``encode()`` and ``__call__()``, so any downstream
|
| 11 |
+
consumer (vLLM, vLLM-Omni, Nano-vLLM, etc.) gets correct single-character
|
| 12 |
+
IDs without code changes.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
from transformers import LlamaTokenizerFast
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class VoxCPM2Tokenizer(LlamaTokenizerFast):
|
| 19 |
+
|
| 20 |
+
def __init__(self, *args, **kwargs):
|
| 21 |
+
super().__init__(*args, **kwargs)
|
| 22 |
+
self._split_map = self._build_split_map()
|
| 23 |
+
|
| 24 |
+
def _build_split_map(self) -> dict[int, list[int]]:
|
| 25 |
+
vocab = self.get_vocab()
|
| 26 |
+
split_map: dict[int, list[int]] = {}
|
| 27 |
+
for token, tid in vocab.items():
|
| 28 |
+
clean = token.replace("\u2581", "")
|
| 29 |
+
if len(clean) >= 2 and all(self._is_cjk(c) for c in clean):
|
| 30 |
+
char_ids = self.convert_tokens_to_ids(list(clean))
|
| 31 |
+
if all(c != self.unk_token_id for c in char_ids):
|
| 32 |
+
split_map[tid] = char_ids
|
| 33 |
+
return split_map
|
| 34 |
+
|
| 35 |
+
@staticmethod
|
| 36 |
+
def _is_cjk(c: str) -> bool:
|
| 37 |
+
return (
|
| 38 |
+
"\u4e00" <= c <= "\u9fff"
|
| 39 |
+
or "\u3400" <= c <= "\u4dbf"
|
| 40 |
+
or "\uf900" <= c <= "\ufaff"
|
| 41 |
+
or "\U00020000" <= c <= "\U0002a6df"
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
def _expand_ids(self, ids: list[int]) -> list[int]:
|
| 45 |
+
result: list[int] = []
|
| 46 |
+
for tid in ids:
|
| 47 |
+
expansion = self._split_map.get(tid)
|
| 48 |
+
if expansion is not None:
|
| 49 |
+
result.extend(expansion)
|
| 50 |
+
else:
|
| 51 |
+
result.append(tid)
|
| 52 |
+
return result
|
| 53 |
+
|
| 54 |
+
def encode(self, text, *args, **kwargs):
|
| 55 |
+
ids = super().encode(text, *args, **kwargs)
|
| 56 |
+
return self._expand_ids(ids)
|
| 57 |
+
|
| 58 |
+
def __call__(self, text, *args, **kwargs):
|
| 59 |
+
result = super().__call__(text, *args, **kwargs)
|
| 60 |
+
if hasattr(result, "input_ids"):
|
| 61 |
+
ids = result["input_ids"]
|
| 62 |
+
if isinstance(ids, list) and ids and isinstance(ids[0], list):
|
| 63 |
+
result["input_ids"] = [self._expand_ids(x) for x in ids]
|
| 64 |
+
if "attention_mask" in result:
|
| 65 |
+
result["attention_mask"] = [
|
| 66 |
+
[1] * len(x) for x in result["input_ids"]
|
| 67 |
+
]
|
| 68 |
+
elif isinstance(ids, list):
|
| 69 |
+
result["input_ids"] = self._expand_ids(ids)
|
| 70 |
+
if "attention_mask" in result:
|
| 71 |
+
result["attention_mask"] = [1] * len(result["input_ids"])
|
| 72 |
+
return result
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_bos_token": true,
|
| 3 |
+
"add_eos_token": false,
|
| 4 |
+
"added_tokens_decoder": {
|
| 5 |
+
"0": {
|
| 6 |
+
"content": "<unk>",
|
| 7 |
+
"lstrip": false,
|
| 8 |
+
"normalized": false,
|
| 9 |
+
"rstrip": false,
|
| 10 |
+
"single_word": false,
|
| 11 |
+
"special": true
|
| 12 |
+
},
|
| 13 |
+
"1": {
|
| 14 |
+
"content": "<s>",
|
| 15 |
+
"lstrip": false,
|
| 16 |
+
"normalized": false,
|
| 17 |
+
"rstrip": false,
|
| 18 |
+
"single_word": false,
|
| 19 |
+
"special": true
|
| 20 |
+
},
|
| 21 |
+
"2": {
|
| 22 |
+
"content": "</s>",
|
| 23 |
+
"lstrip": false,
|
| 24 |
+
"normalized": false,
|
| 25 |
+
"rstrip": false,
|
| 26 |
+
"single_word": false,
|
| 27 |
+
"special": true
|
| 28 |
+
},
|
| 29 |
+
"101": {
|
| 30 |
+
"content": "<|audio_start|>",
|
| 31 |
+
"lstrip": false,
|
| 32 |
+
"normalized": false,
|
| 33 |
+
"rstrip": false,
|
| 34 |
+
"single_word": false,
|
| 35 |
+
"special": true
|
| 36 |
+
},
|
| 37 |
+
"102": {
|
| 38 |
+
"content": "<|audio_end|>",
|
| 39 |
+
"lstrip": false,
|
| 40 |
+
"normalized": false,
|
| 41 |
+
"rstrip": false,
|
| 42 |
+
"single_word": false,
|
| 43 |
+
"special": true
|
| 44 |
+
},
|
| 45 |
+
"103": {
|
| 46 |
+
"content": "<|audio_prompt_start|>",
|
| 47 |
+
"lstrip": false,
|
| 48 |
+
"normalized": false,
|
| 49 |
+
"rstrip": false,
|
| 50 |
+
"single_word": false,
|
| 51 |
+
"special": true
|
| 52 |
+
},
|
| 53 |
+
"104": {
|
| 54 |
+
"content": "<|audio_prompt_end|>",
|
| 55 |
+
"lstrip": false,
|
| 56 |
+
"normalized": false,
|
| 57 |
+
"rstrip": false,
|
| 58 |
+
"single_word": false,
|
| 59 |
+
"special": true
|
| 60 |
+
},
|
| 61 |
+
"105": {
|
| 62 |
+
"content": "<|background|>",
|
| 63 |
+
"lstrip": false,
|
| 64 |
+
"normalized": false,
|
| 65 |
+
"rstrip": false,
|
| 66 |
+
"single_word": false,
|
| 67 |
+
"special": true
|
| 68 |
+
},
|
| 69 |
+
"106": {
|
| 70 |
+
"content": "<|/background|>",
|
| 71 |
+
"lstrip": false,
|
| 72 |
+
"normalized": false,
|
| 73 |
+
"rstrip": false,
|
| 74 |
+
"single_word": false,
|
| 75 |
+
"special": true
|
| 76 |
+
},
|
| 77 |
+
"107": {
|
| 78 |
+
"content": "<|characters|>",
|
| 79 |
+
"lstrip": false,
|
| 80 |
+
"normalized": false,
|
| 81 |
+
"rstrip": false,
|
| 82 |
+
"single_word": false,
|
| 83 |
+
"special": true
|
| 84 |
+
},
|
| 85 |
+
"108": {
|
| 86 |
+
"content": "<|/characters|>",
|
| 87 |
+
"lstrip": false,
|
| 88 |
+
"normalized": false,
|
| 89 |
+
"rstrip": false,
|
| 90 |
+
"single_word": false,
|
| 91 |
+
"special": true
|
| 92 |
+
},
|
| 93 |
+
"109": {
|
| 94 |
+
"content": "<|speaker_id|>",
|
| 95 |
+
"lstrip": false,
|
| 96 |
+
"normalized": false,
|
| 97 |
+
"rstrip": false,
|
| 98 |
+
"single_word": false,
|
| 99 |
+
"special": true
|
| 100 |
+
},
|
| 101 |
+
"110": {
|
| 102 |
+
"content": "<|/speaker_id|>",
|
| 103 |
+
"lstrip": false,
|
| 104 |
+
"normalized": false,
|
| 105 |
+
"rstrip": false,
|
| 106 |
+
"single_word": false,
|
| 107 |
+
"special": true
|
| 108 |
+
},
|
| 109 |
+
"111": {
|
| 110 |
+
"content": "<|span|>",
|
| 111 |
+
"lstrip": false,
|
| 112 |
+
"normalized": false,
|
| 113 |
+
"rstrip": false,
|
| 114 |
+
"single_word": false,
|
| 115 |
+
"special": true
|
| 116 |
+
},
|
| 117 |
+
"112": {
|
| 118 |
+
"content": "<|/span|>",
|
| 119 |
+
"lstrip": false,
|
| 120 |
+
"normalized": false,
|
| 121 |
+
"rstrip": false,
|
| 122 |
+
"single_word": false,
|
| 123 |
+
"special": true
|
| 124 |
+
},
|
| 125 |
+
"73440": {
|
| 126 |
+
"content": "<|im_end|>",
|
| 127 |
+
"lstrip": false,
|
| 128 |
+
"normalized": false,
|
| 129 |
+
"rstrip": false,
|
| 130 |
+
"single_word": false,
|
| 131 |
+
"special": true
|
| 132 |
+
},
|
| 133 |
+
"73441": {
|
| 134 |
+
"content": "<|im_start|>",
|
| 135 |
+
"lstrip": false,
|
| 136 |
+
"normalized": false,
|
| 137 |
+
"rstrip": false,
|
| 138 |
+
"single_word": false,
|
| 139 |
+
"special": true
|
| 140 |
+
},
|
| 141 |
+
"73442": {
|
| 142 |
+
"content": "<|tool_call|>",
|
| 143 |
+
"lstrip": false,
|
| 144 |
+
"normalized": false,
|
| 145 |
+
"rstrip": false,
|
| 146 |
+
"single_word": false,
|
| 147 |
+
"special": true
|
| 148 |
+
},
|
| 149 |
+
"73443": {
|
| 150 |
+
"content": "<|execute_start|>",
|
| 151 |
+
"lstrip": false,
|
| 152 |
+
"normalized": false,
|
| 153 |
+
"rstrip": false,
|
| 154 |
+
"single_word": false,
|
| 155 |
+
"special": true
|
| 156 |
+
},
|
| 157 |
+
"73444": {
|
| 158 |
+
"content": "<|execute_end|>",
|
| 159 |
+
"lstrip": false,
|
| 160 |
+
"normalized": false,
|
| 161 |
+
"rstrip": false,
|
| 162 |
+
"single_word": false,
|
| 163 |
+
"special": true
|
| 164 |
+
},
|
| 165 |
+
"73445": {
|
| 166 |
+
"content": "<|fim_prefix|>",
|
| 167 |
+
"lstrip": false,
|
| 168 |
+
"normalized": false,
|
| 169 |
+
"rstrip": false,
|
| 170 |
+
"single_word": false,
|
| 171 |
+
"special": true
|
| 172 |
+
},
|
| 173 |
+
"73446": {
|
| 174 |
+
"content": "<|fim_middle|>",
|
| 175 |
+
"lstrip": false,
|
| 176 |
+
"normalized": false,
|
| 177 |
+
"rstrip": false,
|
| 178 |
+
"single_word": false,
|
| 179 |
+
"special": true
|
| 180 |
+
},
|
| 181 |
+
"73447": {
|
| 182 |
+
"content": "<|fim_suffix|>",
|
| 183 |
+
"lstrip": false,
|
| 184 |
+
"normalized": false,
|
| 185 |
+
"rstrip": false,
|
| 186 |
+
"single_word": false,
|
| 187 |
+
"special": true
|
| 188 |
+
}
|
| 189 |
+
},
|
| 190 |
+
"additional_special_tokens": [
|
| 191 |
+
"<|im_end|>",
|
| 192 |
+
"<|im_start|>",
|
| 193 |
+
"<|tool_call|>",
|
| 194 |
+
"<|execute_start|>",
|
| 195 |
+
"<|execute_end|>",
|
| 196 |
+
"<|fim_prefix|>",
|
| 197 |
+
"<|fim_middle|>",
|
| 198 |
+
"<|fim_suffix|>"
|
| 199 |
+
],
|
| 200 |
+
"bos_token": "<s>",
|
| 201 |
+
"clean_up_tokenization_spaces": false,
|
| 202 |
+
"eos_token": "<|im_end|>",
|
| 203 |
+
"legacy": true,
|
| 204 |
+
"model_max_length": 1000000000000000019884624838656,
|
| 205 |
+
"pad_token": null,
|
| 206 |
+
"sp_model_kwargs": {},
|
| 207 |
+
"spaces_between_special_tokens": false,
|
| 208 |
+
"tokenizer_class": "VoxCPM2Tokenizer",
|
| 209 |
+
"unk_token": "<unk>",
|
| 210 |
+
"use_default_system_prompt": false,
|
| 211 |
+
"chat_template": "{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}",
|
| 212 |
+
"auto_map": {
|
| 213 |
+
"AutoTokenizer": [
|
| 214 |
+
"tokenization_voxcpm2.VoxCPM2Tokenizer",
|
| 215 |
+
null
|
| 216 |
+
]
|
| 217 |
+
}
|
| 218 |
+
}
|