gijs commited on
Commit
c291e8b
·
verified ·
1 Parent(s): 3453199

Upload folder using huggingface_hub

Browse files
README.md ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: cc-by-4.0
3
+ language:
4
+ - en
5
+ - de
6
+ - fr
7
+ - es
8
+ - zh
9
+ library_name: transformers
10
+ pipeline_tag: feature-extraction
11
+ tags:
12
+ - audio
13
+ - speech
14
+ - emotion
15
+ - clap
16
+ - contrastive
17
+ - voice
18
+ - commercial-use
19
+ base_model: laion/voiceclap-small
20
+ ---
21
+
22
+ # VoiceCLAP-Commercial (small)
23
+
24
+ A **fully commercially-licensable** voice-text contrastive (CLAP-style) embedding
25
+ model for speech-emotion and talking-style retrieval. Same 110M dual-tower
26
+ architecture as [`laion/voiceclap-small`](https://huggingface.co/laion/voiceclap-small),
27
+ but trained **only on data that permits commercial use** — and, perhaps
28
+ surprisingly, it matches or beats the non-commercial-data model on 4 of 5
29
+ benchmarks.
30
+
31
+ ## Why this model exists
32
+
33
+ The standard VoiceCLAP training mix contains **CC BY-NC** (non-commercial)
34
+ corpora: Expresso and EARS (both Meta, CC BY-NC 4.0), and the bulk of
35
+ [Emilia](https://huggingface.co/datasets/amphion/Emilia-Dataset) (the original
36
+ 101k-hour split is CC BY-NC 4.0). That makes models trained on the full mix
37
+ unusable for commercial purposes.
38
+
39
+ This model removes every non-commercial source and keeps only commercially
40
+ usable data. A controlled ablation (below) shows the small model loses
41
+ **nothing** by doing so.
42
+
43
+ ## Training data (all commercially licensable)
44
+
45
+ | Corpus | License | Role |
46
+ |---|---|---|
47
+ | **Emilia-YODAS** (the CC BY 4.0 subset of Emilia, ~19% of emolia-balanced) | CC BY 4.0 | emotion / voice captions |
48
+ | **LAION's Got Talent** | LAION-released | talking-style captions |
49
+ | **Majestrino** | in-house | voice captions |
50
+
51
+ The non-commercial Emilia clips are filtered out **at training time** by clip-id
52
+ (original-Emilia ids look like `EN_B00087_S08178_W000004`; the retained
53
+ YODAS clips carry YouTube-style ids). Expresso and EARS are not used.
54
+ Captions use the **`__moss_short__`** scheme: the MOSS-Audio-8B-Thinking
55
+ emotion sentence plus one sampled talking-style sentence, 50/50 mixed with the
56
+ corpus's own caption.
57
+
58
+ ## Architecture
59
+
60
+ Identical to voiceclap-small — a dual-tower CLAP:
61
+
62
+ | | |
63
+ | --- | --- |
64
+ | Audio encoder | BUD-E-Whisper-Small: 12 layers × 768 dim × 12 heads, 80-mel @ 16 kHz |
65
+ | Text encoder | `all-MiniLM-L6-v2`: 6 layers × 384 dim, mean-pooled |
66
+ | Joint embedding | 768-d, L2-normalised |
67
+ | Loss | SigLIP sigmoid contrastive + Prototypical Contrastive (PCL, w=0.2) |
68
+ | Total parameters | ~110 M |
69
+
70
+ **PCL** adds 39 learned emotion prototypes and a cross-entropy term on
71
+ z-scored pseudo-labels derived from emolia's emotion-annotation scalars — a
72
+ small auxiliary loss that sharpens the emotion subspace.
73
+
74
+ ## Results — commercial data costs nothing
75
+
76
+ Controlled ablation, all arms trained identically (1 node, `__moss_short__` +
77
+ PCL w=0.2, 15 epochs), evaluated at each arm's best epoch:
78
+
79
+ | Training data | emonet top1 | emonet ρ | VoiceNet-Emo bal@pp | emolia ρ | MAEB-voice |
80
+ |---|---|---|---|---|---|
81
+ | full mix incl. **non-commercial** Emilia | 0.0712 | **0.2308** | 0.6112 | 0.2019 | 0.3472 |
82
+ | **this model — commercial only** | **0.0721** | 0.2061 | **0.6227** | **0.2034** | **0.3564** |
83
+
84
+ **This model wins 4 of 5 metrics** — emonet top-1, VoiceNet-Emo balanced
85
+ accuracy (+0.0115), emolia Spearman ρ, and MAEB-voice (+0.009). It trails only
86
+ on emonet ρ (−0.025, fine-grained intensity *ranking* on synthetic audio,
87
+ where the dropped Emilia diversity helped). On the in-domain emolia benchmark
88
+ and the 8-task MAEB-voice suite it is strictly better than the
89
+ non-commercial-data model.
90
+
91
+ Two recovery experiments were tried and discarded: adding VoxCeleb1/2 (CC BY)
92
+ *hurt*, and upweighting the existing safe corpora was flat. Plain commercial
93
+ data is best.
94
+
95
+ > Absolute numbers are from a 1-node training scale used for the controlled
96
+ > ablation; treat them as relative (commercial-vs-noncommercial deltas), not as
97
+ > the maximum achievable with a full multi-node run.
98
+
99
+ ## Usage
100
+
101
+ ```python
102
+ import torch, soundfile as sf
103
+ from transformers import AutoModel, AutoTokenizer
104
+
105
+ model = AutoModel.from_pretrained("laion/voiceclap-commercial", trust_remote_code=True).eval()
106
+ tok = AutoTokenizer.from_pretrained("laion/voiceclap-commercial")
107
+
108
+ # audio: raw mono waveform @ 16 kHz
109
+ wav, sr = sf.read("clip.wav", dtype="float32")
110
+ audio_emb = model.encode_waveform(torch.from_numpy(wav))
111
+
112
+ # text
113
+ t = tok(["a person speaking with quiet pride in their voice"], padding=True, return_tensors="pt")
114
+ text_emb = model.encode_text(t["input_ids"], attention_mask=t["attention_mask"])
115
+
116
+ score = (audio_emb @ text_emb.T).item() # cosine similarity (both L2-normalised)
117
+ ```
118
+
119
+ Conversion from the training checkpoint was verified functionally against the
120
+ original open_clip implementation (cosine ≥ 0.99999 on both towers).
121
+
122
+ ## License
123
+
124
+ **CC-BY-4.0** — all training data is commercially usable (Emilia-YODAS CC BY 4.0,
125
+ LAION's Got Talent, in-house Majestrino), and the architecture/weights carry no
126
+ non-commercial restriction. This is the distinguishing feature of this model
127
+ versus the standard VoiceCLAP releases, which inherit a non-commercial
128
+ restriction from their CC BY-NC training data.
config.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "VoiceCLAPSmall"
4
+ ],
5
+ "dtype": "float32",
6
+ "embed_dim": 768,
7
+ "model_type": "voiceclap-small",
8
+ "n_ctx": 1500,
9
+ "n_head": 12,
10
+ "n_layer": 12,
11
+ "n_mels": 80,
12
+ "n_state": 768,
13
+ "text_hidden_dim": 384,
14
+ "text_intermediate_size": 1536,
15
+ "text_layer_norm_eps": 1e-12,
16
+ "text_max_position_embeddings": 512,
17
+ "text_num_heads": 12,
18
+ "text_num_layers": 6,
19
+ "text_pad_token_id": 0,
20
+ "text_proj_hidden": 576,
21
+ "text_vocab_size": 30522,
22
+ "transformers_version": "5.7.0",
23
+ "auto_map": {
24
+ "AutoConfig": "configuration_voiceclap.VoiceCLAPSmallConfig",
25
+ "AutoModel": "modeling_voiceclap.VoiceCLAPSmall"
26
+ }
27
+ }
configuration_voiceclap.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """VoiceCLAP-Small config."""
2
+ from transformers import PretrainedConfig
3
+
4
+
5
+ class VoiceCLAPSmallConfig(PretrainedConfig):
6
+ model_type = "voiceclap-small"
7
+
8
+ def __init__(
9
+ self,
10
+ embed_dim: int = 768,
11
+ n_mels: int = 80,
12
+ n_ctx: int = 1500,
13
+ n_state: int = 768,
14
+ n_head: int = 12,
15
+ n_layer: int = 12,
16
+ text_hidden_dim: int = 384,
17
+ text_proj_hidden: int = 576,
18
+ text_vocab_size: int = 30522,
19
+ text_intermediate_size: int = 1536,
20
+ text_num_layers: int = 6,
21
+ text_num_heads: int = 12,
22
+ text_max_position_embeddings: int = 512,
23
+ text_layer_norm_eps: float = 1e-12,
24
+ text_pad_token_id: int = 0,
25
+ **kwargs,
26
+ ):
27
+ super().__init__(**kwargs)
28
+ self.embed_dim = embed_dim
29
+ self.n_mels = n_mels
30
+ self.n_ctx = n_ctx
31
+ self.n_state = n_state
32
+ self.n_head = n_head
33
+ self.n_layer = n_layer
34
+ self.text_hidden_dim = text_hidden_dim
35
+ self.text_proj_hidden = text_proj_hidden
36
+ self.text_vocab_size = text_vocab_size
37
+ self.text_intermediate_size = text_intermediate_size
38
+ self.text_num_layers = text_num_layers
39
+ self.text_num_heads = text_num_heads
40
+ self.text_max_position_embeddings = text_max_position_embeddings
41
+ self.text_layer_norm_eps = text_layer_norm_eps
42
+ self.text_pad_token_id = text_pad_token_id
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:07849965a3e852b43ddb1b782d7b006ec8b36fe0b91abcdc7fbc7438c81513d7
3
+ size 452717296
modeling_voiceclap.py ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """VoiceCLAP-Small: dual-tower CLAP using BUD-E-Whisper-Small + MiniLM.
2
+
3
+ Standalone single-file implementation. Only depends on PyTorch and
4
+ HuggingFace `transformers` (for `BertModel`, `PreTrainedModel`, and
5
+ `PretrainedConfig`).
6
+ """
7
+ import math
8
+ from typing import Optional
9
+
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.nn.functional as F
13
+ from transformers import BertConfig, BertModel, PreTrainedModel
14
+
15
+ try:
16
+ from .configuration_voiceclap import VoiceCLAPSmallConfig
17
+ except ImportError:
18
+ from configuration_voiceclap import VoiceCLAPSmallConfig
19
+
20
+
21
+ # 30 s of 16 kHz audio = 480_000 samples = 3000 STFT frames (hop 160) =
22
+ # 1500 post-conv frames, which matches the encoder's positional embedding.
23
+ _CHUNK_SAMPLES = 30 * 16000
24
+
25
+
26
+ class _LayerNorm(nn.LayerNorm):
27
+ def forward(self, x):
28
+ return super().forward(x.float()).type(x.dtype)
29
+
30
+
31
+ def _sinusoids(length: int, channels: int, max_timescale: float = 10000.0) -> torch.Tensor:
32
+ assert channels % 2 == 0
33
+ log_timescale_increment = math.log(max_timescale) / (channels // 2 - 1)
34
+ inv_timescales = torch.exp(-log_timescale_increment * torch.arange(channels // 2))
35
+ scaled_time = torch.arange(length)[:, None] * inv_timescales[None, :]
36
+ return torch.cat([torch.sin(scaled_time), torch.cos(scaled_time)], dim=1)
37
+
38
+
39
+ class _MultiHeadAttention(nn.Module):
40
+ def __init__(self, n_state: int, n_head: int):
41
+ super().__init__()
42
+ self.n_head = n_head
43
+ self.query = nn.Linear(n_state, n_state)
44
+ self.key = nn.Linear(n_state, n_state, bias=False)
45
+ self.value = nn.Linear(n_state, n_state)
46
+ self.out = nn.Linear(n_state, n_state)
47
+
48
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
49
+ q = self.query(x)
50
+ k = self.key(x)
51
+ v = self.value(x)
52
+ n_batch, n_ctx, n_state = q.shape
53
+ head_dim = n_state // self.n_head
54
+ q = q.view(n_batch, n_ctx, self.n_head, head_dim).transpose(1, 2)
55
+ k = k.view(n_batch, n_ctx, self.n_head, head_dim).transpose(1, 2)
56
+ v = v.view(n_batch, n_ctx, self.n_head, head_dim).transpose(1, 2)
57
+ out = F.scaled_dot_product_attention(q, k, v)
58
+ out = out.transpose(1, 2).reshape(n_batch, n_ctx, n_state)
59
+ return self.out(out)
60
+
61
+
62
+ class _ResidualAttentionBlock(nn.Module):
63
+ def __init__(self, n_state: int, n_head: int):
64
+ super().__init__()
65
+ self.attn = _MultiHeadAttention(n_state, n_head)
66
+ self.attn_ln = _LayerNorm(n_state)
67
+ n_mlp = n_state * 4
68
+ self.mlp = nn.Sequential(nn.Linear(n_state, n_mlp), nn.GELU(), nn.Linear(n_mlp, n_state))
69
+ self.mlp_ln = _LayerNorm(n_state)
70
+
71
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
72
+ x = x + self.attn(self.attn_ln(x))
73
+ x = x + self.mlp(self.mlp_ln(x))
74
+ return x
75
+
76
+
77
+ class _WhisperAudioEncoder(nn.Module):
78
+ """Whisper-style audio encoder. Takes a precomputed log-mel spectrogram."""
79
+
80
+ def __init__(
81
+ self,
82
+ n_mels: int = 80,
83
+ n_ctx: int = 1500,
84
+ n_state: int = 768,
85
+ n_head: int = 12,
86
+ n_layer: int = 12,
87
+ output_dim: int = 768,
88
+ ):
89
+ super().__init__()
90
+ self.conv1 = nn.Conv1d(n_mels, n_state, kernel_size=3, padding=1)
91
+ self.conv2 = nn.Conv1d(n_state, n_state, kernel_size=3, stride=2, padding=1)
92
+ self.register_buffer("positional_embedding", _sinusoids(n_ctx, n_state))
93
+ self.blocks = nn.ModuleList(
94
+ [_ResidualAttentionBlock(n_state, n_head) for _ in range(n_layer)]
95
+ )
96
+ self.ln_post = _LayerNorm(n_state)
97
+ self.avg_pooler = nn.AvgPool1d(kernel_size=2, stride=2)
98
+ self.proj = nn.Linear(n_state, output_dim)
99
+
100
+ def forward(self, mel: torch.Tensor) -> torch.Tensor:
101
+ # mel: (B, n_mels, T_mel)
102
+ x = F.gelu(self.conv1(mel))
103
+ x = F.gelu(self.conv2(x))
104
+ x = x.permute(0, 2, 1) # (B, T', D)
105
+ T = x.size(1)
106
+ x = x + self.positional_embedding[:T].to(dtype=x.dtype, device=x.device)
107
+ for block in self.blocks:
108
+ x = block(x)
109
+ x = x.permute(0, 2, 1)
110
+ x = self.avg_pooler(x)
111
+ x = x.permute(0, 2, 1)
112
+ x = self.ln_post(x)
113
+ x = self.proj(x)
114
+ return x
115
+
116
+
117
+ class VoiceCLAPSmall(PreTrainedModel):
118
+ config_class = VoiceCLAPSmallConfig
119
+
120
+ def __init__(self, config: VoiceCLAPSmallConfig):
121
+ super().__init__(config)
122
+ self.audio_encoder = _WhisperAudioEncoder(
123
+ n_mels=config.n_mels,
124
+ n_ctx=config.n_ctx,
125
+ n_state=config.n_state,
126
+ n_head=config.n_head,
127
+ n_layer=config.n_layer,
128
+ output_dim=config.embed_dim,
129
+ )
130
+ self.audio_proj = nn.Sequential(
131
+ nn.Linear(config.embed_dim, config.embed_dim),
132
+ nn.GELU(),
133
+ nn.Linear(config.embed_dim, config.embed_dim),
134
+ )
135
+ bert_config = BertConfig(
136
+ vocab_size=config.text_vocab_size,
137
+ hidden_size=config.text_hidden_dim,
138
+ num_hidden_layers=config.text_num_layers,
139
+ num_attention_heads=config.text_num_heads,
140
+ intermediate_size=config.text_intermediate_size,
141
+ max_position_embeddings=config.text_max_position_embeddings,
142
+ layer_norm_eps=config.text_layer_norm_eps,
143
+ pad_token_id=config.text_pad_token_id,
144
+ )
145
+ self.text_encoder = BertModel(bert_config, add_pooling_layer=False)
146
+ self.text_proj = nn.Sequential(
147
+ nn.Linear(config.text_hidden_dim, config.text_proj_hidden, bias=False),
148
+ nn.GELU(),
149
+ nn.Linear(config.text_proj_hidden, config.embed_dim, bias=False),
150
+ )
151
+ self.logit_scale = nn.Parameter(torch.zeros(()))
152
+ self.logit_bias = nn.Parameter(torch.zeros(()))
153
+
154
+ # Mel filterbank used by encode_waveform / compute_log_mel.
155
+ # 80 mel bins x 201 freq bins for n_fft=400, sr=16000 (Whisper-style).
156
+ self.register_buffer(
157
+ "mel_filters",
158
+ torch.zeros(config.n_mels, 201),
159
+ persistent=True,
160
+ )
161
+ self.post_init()
162
+
163
+ @torch.no_grad()
164
+ def compute_log_mel(
165
+ self, waveform: torch.Tensor, sample_rate: int = 16000
166
+ ) -> torch.Tensor:
167
+ """Whisper-style log-mel spectrogram. waveform: (B, T) or (T,) at 16 kHz.
168
+
169
+ Returns (B, n_mels, T_mel). Matches the training-time preprocessing
170
+ bit-exactly so embeddings reproduce the published results.
171
+ """
172
+ if sample_rate != 16000:
173
+ raise ValueError(f"sample_rate must be 16000, got {sample_rate}")
174
+ if waveform.dim() == 1:
175
+ waveform = waveform.unsqueeze(0)
176
+ device = self.mel_filters.device
177
+ waveform = waveform.to(device=device, dtype=torch.float32)
178
+ window = torch.hann_window(400, device=device)
179
+ stft = torch.stft(waveform, n_fft=400, hop_length=160, window=window, return_complex=True)
180
+ magnitudes = stft[..., :-1].abs() ** 2
181
+ mel = self.mel_filters.to(magnitudes.dtype) @ magnitudes
182
+ log_spec = torch.clamp(mel, min=1e-10).log10()
183
+ log_spec = torch.maximum(log_spec, log_spec.amax(dim=(-2, -1), keepdim=True) - 8.0)
184
+ log_spec = (log_spec + 4.0) / 4.0
185
+ return log_spec
186
+
187
+ def encode_waveform(self, waveform: torch.Tensor, sample_rate: int = 16000) -> torch.Tensor:
188
+ """Encode raw 16 kHz waveform; calls ``compute_log_mel`` then ``encode_audio``.
189
+
190
+ Handles any-length audio. Clips at or below 30 s are zero-padded to a
191
+ full 30 s window (matching Whisper's training-time padding). Longer
192
+ clips are split into non-overlapping 30 s chunks; each chunk is encoded
193
+ independently and the resulting embeddings are averaged and
194
+ re-normalised. Output shape: ``(B, embed_dim)``.
195
+ """
196
+ if sample_rate != 16000:
197
+ raise ValueError(f"sample_rate must be 16000, got {sample_rate}")
198
+ if waveform.dim() == 1:
199
+ waveform = waveform.unsqueeze(0)
200
+ B, T = waveform.shape
201
+ n_chunks = max(1, (T + _CHUNK_SAMPLES - 1) // _CHUNK_SAMPLES)
202
+ pad = n_chunks * _CHUNK_SAMPLES - T
203
+ if pad > 0:
204
+ waveform = F.pad(waveform, (0, pad))
205
+ chunks = waveform.view(B, n_chunks, _CHUNK_SAMPLES).reshape(B * n_chunks, _CHUNK_SAMPLES)
206
+ mel = self.compute_log_mel(chunks, sample_rate=sample_rate)
207
+ feats = self.encode_audio(mel)
208
+ if n_chunks == 1:
209
+ return feats
210
+ feats = feats.view(B, n_chunks, -1).mean(dim=1)
211
+ return F.normalize(feats, dim=-1)
212
+
213
+ def encode_audio(self, mel: torch.Tensor) -> torch.Tensor:
214
+ feats = self.audio_encoder(mel) # (B, T', D)
215
+ feats = feats.mean(dim=1) # clip-level mean
216
+ feats = self.audio_proj(feats)
217
+ return F.normalize(feats, dim=-1)
218
+
219
+ def encode_text(
220
+ self,
221
+ input_ids: torch.Tensor,
222
+ attention_mask: Optional[torch.Tensor] = None,
223
+ ) -> torch.Tensor:
224
+ if attention_mask is None:
225
+ attention_mask = (input_ids != self.config.text_pad_token_id).long()
226
+ out = self.text_encoder(input_ids=input_ids, attention_mask=attention_mask)
227
+ hidden = out.last_hidden_state # (B, T, H)
228
+ mask = attention_mask.unsqueeze(-1).to(hidden.dtype)
229
+ pooled = (hidden * mask).sum(dim=1) / mask.sum(dim=1).clamp(min=1e-9)
230
+ feats = self.text_proj(pooled)
231
+ return F.normalize(feats, dim=-1)
preprocessor_config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "chunk_length": 30,
3
+ "dither": 0.0,
4
+ "feature_extractor_type": "WhisperFeatureExtractor",
5
+ "feature_size": 80,
6
+ "hop_length": 160,
7
+ "n_fft": 400,
8
+ "n_samples": 480000,
9
+ "nb_max_frames": 3000,
10
+ "padding_side": "right",
11
+ "padding_value": 0.0,
12
+ "return_attention_mask": false,
13
+ "sampling_rate": 16000
14
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "cls_token": "[CLS]",
4
+ "do_basic_tokenize": true,
5
+ "do_lower_case": true,
6
+ "is_local": false,
7
+ "local_files_only": false,
8
+ "mask_token": "[MASK]",
9
+ "max_length": 128,
10
+ "model_max_length": 512,
11
+ "never_split": null,
12
+ "pad_to_multiple_of": null,
13
+ "pad_token": "[PAD]",
14
+ "pad_token_type_id": 0,
15
+ "padding_side": "right",
16
+ "sep_token": "[SEP]",
17
+ "stride": 0,
18
+ "strip_accents": null,
19
+ "tokenize_chinese_chars": true,
20
+ "tokenizer_class": "BertTokenizer",
21
+ "truncation_side": "right",
22
+ "truncation_strategy": "longest_first",
23
+ "unk_token": "[UNK]"
24
+ }
Free AI Image Generator No sign-up. Instant results. Open Now