Text-to-Speech
PyTorch
moss_tts_nano
custom_code
schwarztgyt commited on
Commit
c69a5b6
·
1 Parent(s): 6e12827
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__
__init__.py CHANGED
@@ -1,31 +1,31 @@
1
- from .configuration_nanotts import NanoTTSConfig
2
- from .modeling_nanotts_global_local import (
3
- NanoTTSGenerationOutput,
4
- NanoTTSGlobalLocalForCausalLM,
5
- NanoTTSOutput,
6
  )
7
- from .tokenization_nanotts_sentencepiece import NanoTTSSentencePieceTokenizer
8
 
9
  try:
10
- NanoTTSConfig.register_for_auto_class()
11
  except Exception:
12
  pass
13
 
14
  for auto_class_name in ("AutoModel", "AutoModelForCausalLM"):
15
  try:
16
- NanoTTSGlobalLocalForCausalLM.register_for_auto_class(auto_class_name)
17
  except Exception:
18
  pass
19
 
20
  try:
21
- NanoTTSSentencePieceTokenizer.register_for_auto_class("AutoTokenizer")
22
  except Exception:
23
  pass
24
 
25
  __all__ = [
26
- "NanoTTSConfig",
27
- "NanoTTSGlobalLocalForCausalLM",
28
- "NanoTTSSentencePieceTokenizer",
29
- "NanoTTSGenerationOutput",
30
- "NanoTTSOutput",
31
  ]
 
1
+ from .configuration_moss_tts_nano import MossTTSNanoConfig
2
+ from .modeling_moss_tts_nano import (
3
+ MossTTSNanoForCausalLM,
4
+ MossTTSNanoGenerationOutput,
5
+ MossTTSNanoOutput,
6
  )
7
+ from .tokenization_moss_tts_nano import MossTTSNanoSentencePieceTokenizer
8
 
9
  try:
10
+ MossTTSNanoConfig.register_for_auto_class()
11
  except Exception:
12
  pass
13
 
14
  for auto_class_name in ("AutoModel", "AutoModelForCausalLM"):
15
  try:
16
+ MossTTSNanoForCausalLM.register_for_auto_class(auto_class_name)
17
  except Exception:
18
  pass
19
 
20
  try:
21
+ MossTTSNanoSentencePieceTokenizer.register_for_auto_class("AutoTokenizer")
22
  except Exception:
23
  pass
24
 
25
  __all__ = [
26
+ "MossTTSNanoConfig",
27
+ "MossTTSNanoForCausalLM",
28
+ "MossTTSNanoSentencePieceTokenizer",
29
+ "MossTTSNanoGenerationOutput",
30
+ "MossTTSNanoOutput",
31
  ]
config.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "add_cross_attention": false,
3
  "architectures": [
4
- "NanoTTSGlobalLocalForCausalLM"
5
  ],
6
  "attn_implementation": "flash_attention_2",
7
  "audio_assistant_slot_token_id": 9,
@@ -156,7 +156,7 @@
156
  "max_position_embeddings": 32768,
157
  "min_length": 0,
158
  "model_architecture": "global_local_transformer",
159
- "model_type": "nano_tts",
160
  "n_vq": 16,
161
  "no_repeat_ngram_size": 0,
162
  "num_beam_groups": 1,
@@ -180,7 +180,7 @@
180
  "tf_legacy_loss": false,
181
  "tie_encoder_decoder": false,
182
  "tie_word_embeddings": true,
183
- "tokenizer_class": "NanoTTSSentencePieceTokenizer",
184
  "tokenizer_use_fast": false,
185
  "top_k": 50,
186
  "top_p": 1.0,
@@ -190,8 +190,8 @@
190
  "use_bfloat16": false,
191
  "vocab_size": 16384,
192
  "auto_map": {
193
- "AutoConfig": "configuration_nanotts.NanoTTSConfig",
194
- "AutoModel": "modeling_nanotts_global_local.NanoTTSGlobalLocalForCausalLM",
195
- "AutoModelForCausalLM": "modeling_nanotts_global_local.NanoTTSGlobalLocalForCausalLM"
196
  }
197
  }
 
1
  {
2
  "add_cross_attention": false,
3
  "architectures": [
4
+ "MossTTSNanoForCausalLM"
5
  ],
6
  "attn_implementation": "flash_attention_2",
7
  "audio_assistant_slot_token_id": 9,
 
156
  "max_position_embeddings": 32768,
157
  "min_length": 0,
158
  "model_architecture": "global_local_transformer",
159
+ "model_type": "moss_tts_nano",
160
  "n_vq": 16,
161
  "no_repeat_ngram_size": 0,
162
  "num_beam_groups": 1,
 
180
  "tf_legacy_loss": false,
181
  "tie_encoder_decoder": false,
182
  "tie_word_embeddings": true,
183
+ "tokenizer_class": "MossTTSNanoSentencePieceTokenizer",
184
  "tokenizer_use_fast": false,
185
  "top_k": 50,
186
  "top_p": 1.0,
 
190
  "use_bfloat16": false,
191
  "vocab_size": 16384,
192
  "auto_map": {
193
+ "AutoConfig": "configuration_moss_tts_nano.MossTTSNanoConfig",
194
+ "AutoModel": "modeling_moss_tts_nano.MossTTSNanoForCausalLM",
195
+ "AutoModelForCausalLM": "modeling_moss_tts_nano.MossTTSNanoForCausalLM"
196
  }
197
  }
configuration_nanotts.py → configuration_moss_tts_nano.py RENAMED
@@ -5,8 +5,8 @@ from transformers.configuration_utils import PretrainedConfig
5
  from transformers.models.gpt2.configuration_gpt2 import GPT2Config
6
 
7
 
8
- class NanoTTSConfig(PretrainedConfig):
9
- model_type = "nano_tts"
10
  keys_to_ignore_at_inference = ["past_key_values"]
11
 
12
  def __init__(
@@ -103,3 +103,6 @@ class NanoTTSConfig(PretrainedConfig):
103
  output = super().to_dict()
104
  output["gpt2_config"] = self.gpt2_config.to_dict()
105
  return output
 
 
 
 
5
  from transformers.models.gpt2.configuration_gpt2 import GPT2Config
6
 
7
 
8
+ class MossTTSNanoConfig(PretrainedConfig):
9
+ model_type = "moss_tts_nano"
10
  keys_to_ignore_at_inference = ["past_key_values"]
11
 
12
  def __init__(
 
103
  output = super().to_dict()
104
  output["gpt2_config"] = self.gpt2_config.to_dict()
105
  return output
106
+
107
+
108
+ __all__ = ["MossTTSNanoConfig"]
gpt2_decoder.py CHANGED
@@ -33,7 +33,7 @@ class PackedSequenceMetadata:
33
  seq_len: Optional[int] = None
34
 
35
 
36
- class NanoGPT2RotaryEmbedding(nn.Module):
37
  def __init__(self, dim: int, base: float = 10000.0) -> None:
38
  super().__init__()
39
  if dim % 2 != 0:
@@ -70,7 +70,7 @@ def apply_rotary_pos_emb(
70
  return (hidden_states * cos) + (rotate_half(hidden_states) * sin)
71
 
72
 
73
- class NanoGPT2MLP(nn.Module):
74
  def __init__(self, config: GPT2Config) -> None:
75
  super().__init__()
76
  hidden_size = int(config.hidden_size)
@@ -87,7 +87,7 @@ class NanoGPT2MLP(nn.Module):
87
  return self.dropout(hidden_states)
88
 
89
 
90
- class NanoGPT2Attention(nn.Module):
91
  def __init__(self, config: GPT2Config, layer_idx: int, attn_implementation: str) -> None:
92
  super().__init__()
93
  hidden_size = int(config.hidden_size)
@@ -112,7 +112,7 @@ class NanoGPT2Attention(nn.Module):
112
  self.c_proj = nn.Linear(hidden_size, hidden_size)
113
  self.rotary_emb = None
114
  if self.position_embedding_type == "rope":
115
- self.rotary_emb = NanoGPT2RotaryEmbedding(
116
  self.head_dim,
117
  base=float(getattr(config, "rope_base", 10000.0)),
118
  )
@@ -353,14 +353,14 @@ class NanoGPT2Attention(nn.Module):
353
  return self.resid_dropout(attn_output), present
354
 
355
 
356
- class NanoGPT2Block(nn.Module):
357
  def __init__(self, config: GPT2Config, layer_idx: int, attn_implementation: str) -> None:
358
  super().__init__()
359
  hidden_size = int(config.hidden_size)
360
  self.ln_1 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
361
- self.attn = NanoGPT2Attention(config, layer_idx=layer_idx, attn_implementation=attn_implementation)
362
  self.ln_2 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
363
- self.mlp = NanoGPT2MLP(config)
364
 
365
  def forward(
366
  self,
@@ -384,7 +384,7 @@ class NanoGPT2Block(nn.Module):
384
  return hidden_states, present
385
 
386
 
387
- class NanoGPT2Model(nn.Module):
388
  def __init__(self, config: GPT2Config, attn_implementation: str = "eager") -> None:
389
  super().__init__()
390
  self.config = config
@@ -397,7 +397,7 @@ class NanoGPT2Model(nn.Module):
397
  self.wpe = nn.Embedding(config.n_positions, hidden_size) if self.position_embedding_type == "absolute" else nn.Identity()
398
  self.drop = nn.Dropout(config.embd_pdrop)
399
  self.h = nn.ModuleList(
400
- [NanoGPT2Block(config, layer_idx=index, attn_implementation=attn_implementation) for index in range(config.n_layer)]
401
  )
402
  self.ln_f = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
403
  self.gradient_checkpointing = False
@@ -445,7 +445,7 @@ class NanoGPT2Model(nn.Module):
445
  batch_size, seq_len = cu_seqlens.shape[0], cu_seqlens.shape[1] - 1
446
  device = cu_seqlens.device
447
  position_ids = torch.zeros((batch_size, seq_len), dtype=torch.long, device=device)
448
- counts = NanoGPT2Model._normalize_num_sequences(cu_seqlens, num_sequences, device=device)
449
  for batch_index in range(batch_size):
450
  sequence_count = int(counts[batch_index].item())
451
  boundaries = cu_seqlens[batch_index, : sequence_count + 1].tolist()
@@ -467,7 +467,7 @@ class NanoGPT2Model(nn.Module):
467
  if cu_seqlens.ndim == 1:
468
  cu_seqlens = cu_seqlens.unsqueeze(0)
469
  device = hidden_states.device
470
- counts = NanoGPT2Model._normalize_num_sequences(cu_seqlens, num_sequences, device=device)
471
  flat_indices = []
472
  cumulative = [0]
473
  max_seqlen = 0
 
33
  seq_len: Optional[int] = None
34
 
35
 
36
+ class MossTTSNanoGPT2RotaryEmbedding(nn.Module):
37
  def __init__(self, dim: int, base: float = 10000.0) -> None:
38
  super().__init__()
39
  if dim % 2 != 0:
 
70
  return (hidden_states * cos) + (rotate_half(hidden_states) * sin)
71
 
72
 
73
+ class MossTTSNanoGPT2MLP(nn.Module):
74
  def __init__(self, config: GPT2Config) -> None:
75
  super().__init__()
76
  hidden_size = int(config.hidden_size)
 
87
  return self.dropout(hidden_states)
88
 
89
 
90
+ class MossTTSNanoGPT2Attention(nn.Module):
91
  def __init__(self, config: GPT2Config, layer_idx: int, attn_implementation: str) -> None:
92
  super().__init__()
93
  hidden_size = int(config.hidden_size)
 
112
  self.c_proj = nn.Linear(hidden_size, hidden_size)
113
  self.rotary_emb = None
114
  if self.position_embedding_type == "rope":
115
+ self.rotary_emb = MossTTSNanoGPT2RotaryEmbedding(
116
  self.head_dim,
117
  base=float(getattr(config, "rope_base", 10000.0)),
118
  )
 
353
  return self.resid_dropout(attn_output), present
354
 
355
 
356
+ class MossTTSNanoGPT2Block(nn.Module):
357
  def __init__(self, config: GPT2Config, layer_idx: int, attn_implementation: str) -> None:
358
  super().__init__()
359
  hidden_size = int(config.hidden_size)
360
  self.ln_1 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
361
+ self.attn = MossTTSNanoGPT2Attention(config, layer_idx=layer_idx, attn_implementation=attn_implementation)
362
  self.ln_2 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
363
+ self.mlp = MossTTSNanoGPT2MLP(config)
364
 
365
  def forward(
366
  self,
 
384
  return hidden_states, present
385
 
386
 
387
+ class MossTTSNanoGPT2Model(nn.Module):
388
  def __init__(self, config: GPT2Config, attn_implementation: str = "eager") -> None:
389
  super().__init__()
390
  self.config = config
 
397
  self.wpe = nn.Embedding(config.n_positions, hidden_size) if self.position_embedding_type == "absolute" else nn.Identity()
398
  self.drop = nn.Dropout(config.embd_pdrop)
399
  self.h = nn.ModuleList(
400
+ [MossTTSNanoGPT2Block(config, layer_idx=index, attn_implementation=attn_implementation) for index in range(config.n_layer)]
401
  )
402
  self.ln_f = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
403
  self.gradient_checkpointing = False
 
445
  batch_size, seq_len = cu_seqlens.shape[0], cu_seqlens.shape[1] - 1
446
  device = cu_seqlens.device
447
  position_ids = torch.zeros((batch_size, seq_len), dtype=torch.long, device=device)
448
+ counts = MossTTSNanoGPT2Model._normalize_num_sequences(cu_seqlens, num_sequences, device=device)
449
  for batch_index in range(batch_size):
450
  sequence_count = int(counts[batch_index].item())
451
  boundaries = cu_seqlens[batch_index, : sequence_count + 1].tolist()
 
467
  if cu_seqlens.ndim == 1:
468
  cu_seqlens = cu_seqlens.unsqueeze(0)
469
  device = hidden_states.device
470
+ counts = MossTTSNanoGPT2Model._normalize_num_sequences(cu_seqlens, num_sequences, device=device)
471
  flat_indices = []
472
  cumulative = [0]
473
  max_seqlen = 0
modeling_nanotts_global_local.py → modeling_moss_tts_nano.py RENAMED
@@ -19,19 +19,19 @@ from transformers.modeling_outputs import ModelOutput
19
  from transformers.modeling_utils import PreTrainedModel
20
  from transformers.models.gpt2.configuration_gpt2 import GPT2Config
21
 
22
- from .configuration_nanotts import NanoTTSConfig
23
- from .gpt2_decoder import NanoGPT2Block, NanoGPT2Model
24
  from .prompting import (
25
  build_assistant_prompt_prefix,
26
  build_prompt_token_ids,
27
  build_user_prompt_after_reference,
28
  build_user_prompt_prefix,
29
  )
30
- from .tokenization_nanotts_sentencepiece import NanoTTSSentencePieceTokenizer
31
 
32
 
33
  @dataclass
34
- class NanoTTSOutput(ModelOutput):
35
  global_hidden_states: Optional[torch.FloatTensor] = None
36
  past_key_values: Optional[tuple[tuple[torch.Tensor, torch.Tensor], ...]] = None
37
  hidden_states: Optional[tuple[torch.FloatTensor, ...]] = None
@@ -39,7 +39,7 @@ class NanoTTSOutput(ModelOutput):
39
 
40
 
41
  @dataclass
42
- class NanoTTSGenerationOutput(ModelOutput):
43
  audio_token_ids: torch.LongTensor
44
  prompt_input_ids: Optional[torch.LongTensor] = None
45
 
@@ -55,24 +55,24 @@ _CLAUSE_SPLIT_PUNCTUATION = frozenset(",,、;;::")
55
  _CLOSING_PUNCTUATION = frozenset("\"'”’)]})】》」』")
56
 
57
 
58
- class NanoTTSPreTrainedModel(PreTrainedModel):
59
- config_class = NanoTTSConfig
60
  base_model_prefix = "transformer"
61
  supports_gradient_checkpointing = False
62
- _no_split_modules = ["NanoGPT2Block"]
63
  _supports_flash_attn_2 = True
64
  _supports_sdpa = True
65
 
66
 
67
- class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
68
  _keys_to_ignore_on_load_unexpected = [r"local_transformer\.wte\.weight"]
69
 
70
- def __init__(self, config: NanoTTSConfig) -> None:
71
  super().__init__(config)
72
  config.gpt2_config.pad_token_id = config.pad_token_id
73
  config.gpt2_config._attn_implementation = config.attn_implementation
74
 
75
- self.transformer = NanoGPT2Model(
76
  config.gpt2_config,
77
  attn_implementation=config.attn_implementation,
78
  )
@@ -97,7 +97,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
97
  local_gpt2_config["n_layer"] = int(config.local_transformer_layers)
98
  local_gpt2_config["n_positions"] = config.n_vq + 1
99
  local_gpt2_config["n_ctx"] = config.n_vq + 1
100
- self.local_transformer = NanoGPT2Model(
101
  GPT2Config(**local_gpt2_config),
102
  attn_implementation=str(config.local_transformer_attn_implementation),
103
  )
@@ -210,7 +210,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
210
  outputs.attentions,
211
  )
212
 
213
- return NanoTTSOutput(
214
  global_hidden_states=outputs.last_hidden_state,
215
  past_key_values=outputs.past_key_values,
216
  hidden_states=outputs.hidden_states,
@@ -258,7 +258,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
258
  while " " in normalized_text:
259
  normalized_text = normalized_text.replace(" ", " ")
260
 
261
- contains_cjk = NanoTTSGlobalLocalForCausalLM._contains_cjk(normalized_text)
262
  if contains_cjk:
263
  if normalized_text[-1] not in _SENTENCE_END_PUNCTUATION:
264
  normalized_text = normalized_text + "。"
@@ -360,7 +360,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
360
  return right
361
  if not right:
362
  return left
363
- if NanoTTSGlobalLocalForCausalLM._contains_cjk(left) or NanoTTSGlobalLocalForCausalLM._contains_cjk(right):
364
  return left + right
365
  return left + " " + right
366
 
@@ -880,7 +880,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
880
  sample_rate: int,
881
  first_audio_emitted_at: Optional[float],
882
  ) -> int:
883
- lead_seconds = NanoTTSGlobalLocalForCausalLM._compute_stream_lead_seconds(
884
  emitted_samples_total=emitted_samples_total,
885
  sample_rate=sample_rate,
886
  first_audio_emitted_at=first_audio_emitted_at,
@@ -1040,7 +1040,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
1040
  hf_dir = candidate_path / "hf_tokenizer"
1041
  if self._looks_like_hf_tokenizer_dir(hf_dir):
1042
  return hf_dir
1043
- sentencepiece_model = candidate_path / "sentencepiece" / "nanotts_spm_bpe.model"
1044
  if sentencepiece_model.is_file():
1045
  return sentencepiece_model
1046
  final_summary_path = candidate_path / "final_summary.json"
@@ -1057,7 +1057,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
1057
 
1058
  def _load_resolved_text_tokenizer(self, resolved_path: Path, cache_dir: str):
1059
  if resolved_path.is_file() and resolved_path.suffix == ".model":
1060
- return NanoTTSSentencePieceTokenizer(vocab_file=str(resolved_path))
1061
  try:
1062
  return AutoTokenizer.from_pretrained(
1063
  str(resolved_path),
@@ -1069,7 +1069,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
1069
  except Exception:
1070
  model_path = resolved_path / "tokenizer.model"
1071
  if model_path.is_file():
1072
- return NanoTTSSentencePieceTokenizer(vocab_file=str(model_path))
1073
  raise
1074
 
1075
  @staticmethod
@@ -1276,7 +1276,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
1276
  if isinstance(output, (list, tuple)) and output:
1277
  if len(output) == 2 and isinstance(output[1], (int, float)):
1278
  return output[0]
1279
- return NanoTTSGlobalLocalForCausalLM._extract_tensor_candidate(output[0])
1280
  raise TypeError(f"Unsupported audio tokenizer output type: {type(output)!r}")
1281
 
1282
  @staticmethod
@@ -1750,7 +1750,7 @@ class NanoTTSGlobalLocalForCausalLM(NanoTTSPreTrainedModel):
1750
  return
1751
  yield {
1752
  "type": "final",
1753
- "generation": NanoTTSGenerationOutput(audio_token_ids=audio_token_ids, prompt_input_ids=input_ids),
1754
  }
1755
 
1756
  @torch.no_grad()
 
19
  from transformers.modeling_utils import PreTrainedModel
20
  from transformers.models.gpt2.configuration_gpt2 import GPT2Config
21
 
22
+ from .configuration_moss_tts_nano import MossTTSNanoConfig
23
+ from .gpt2_decoder import MossTTSNanoGPT2Block, MossTTSNanoGPT2Model
24
  from .prompting import (
25
  build_assistant_prompt_prefix,
26
  build_prompt_token_ids,
27
  build_user_prompt_after_reference,
28
  build_user_prompt_prefix,
29
  )
30
+ from .tokenization_moss_tts_nano import MossTTSNanoSentencePieceTokenizer
31
 
32
 
33
  @dataclass
34
+ class MossTTSNanoOutput(ModelOutput):
35
  global_hidden_states: Optional[torch.FloatTensor] = None
36
  past_key_values: Optional[tuple[tuple[torch.Tensor, torch.Tensor], ...]] = None
37
  hidden_states: Optional[tuple[torch.FloatTensor, ...]] = None
 
39
 
40
 
41
  @dataclass
42
+ class MossTTSNanoGenerationOutput(ModelOutput):
43
  audio_token_ids: torch.LongTensor
44
  prompt_input_ids: Optional[torch.LongTensor] = None
45
 
 
55
  _CLOSING_PUNCTUATION = frozenset("\"'”’)]})】》」』")
56
 
57
 
58
+ class MossTTSNanoPreTrainedModel(PreTrainedModel):
59
+ config_class = MossTTSNanoConfig
60
  base_model_prefix = "transformer"
61
  supports_gradient_checkpointing = False
62
+ _no_split_modules = ["MossTTSNanoGPT2Block"]
63
  _supports_flash_attn_2 = True
64
  _supports_sdpa = True
65
 
66
 
67
+ class MossTTSNanoForCausalLM(MossTTSNanoPreTrainedModel):
68
  _keys_to_ignore_on_load_unexpected = [r"local_transformer\.wte\.weight"]
69
 
70
+ def __init__(self, config: MossTTSNanoConfig) -> None:
71
  super().__init__(config)
72
  config.gpt2_config.pad_token_id = config.pad_token_id
73
  config.gpt2_config._attn_implementation = config.attn_implementation
74
 
75
+ self.transformer = MossTTSNanoGPT2Model(
76
  config.gpt2_config,
77
  attn_implementation=config.attn_implementation,
78
  )
 
97
  local_gpt2_config["n_layer"] = int(config.local_transformer_layers)
98
  local_gpt2_config["n_positions"] = config.n_vq + 1
99
  local_gpt2_config["n_ctx"] = config.n_vq + 1
100
+ self.local_transformer = MossTTSNanoGPT2Model(
101
  GPT2Config(**local_gpt2_config),
102
  attn_implementation=str(config.local_transformer_attn_implementation),
103
  )
 
210
  outputs.attentions,
211
  )
212
 
213
+ return MossTTSNanoOutput(
214
  global_hidden_states=outputs.last_hidden_state,
215
  past_key_values=outputs.past_key_values,
216
  hidden_states=outputs.hidden_states,
 
258
  while " " in normalized_text:
259
  normalized_text = normalized_text.replace(" ", " ")
260
 
261
+ contains_cjk = MossTTSNanoForCausalLM._contains_cjk(normalized_text)
262
  if contains_cjk:
263
  if normalized_text[-1] not in _SENTENCE_END_PUNCTUATION:
264
  normalized_text = normalized_text + "。"
 
360
  return right
361
  if not right:
362
  return left
363
+ if MossTTSNanoForCausalLM._contains_cjk(left) or MossTTSNanoForCausalLM._contains_cjk(right):
364
  return left + right
365
  return left + " " + right
366
 
 
880
  sample_rate: int,
881
  first_audio_emitted_at: Optional[float],
882
  ) -> int:
883
+ lead_seconds = MossTTSNanoForCausalLM._compute_stream_lead_seconds(
884
  emitted_samples_total=emitted_samples_total,
885
  sample_rate=sample_rate,
886
  first_audio_emitted_at=first_audio_emitted_at,
 
1040
  hf_dir = candidate_path / "hf_tokenizer"
1041
  if self._looks_like_hf_tokenizer_dir(hf_dir):
1042
  return hf_dir
1043
+ sentencepiece_model = candidate_path / "sentencepiece" / "mossttsnano_spm_bpe.model"
1044
  if sentencepiece_model.is_file():
1045
  return sentencepiece_model
1046
  final_summary_path = candidate_path / "final_summary.json"
 
1057
 
1058
  def _load_resolved_text_tokenizer(self, resolved_path: Path, cache_dir: str):
1059
  if resolved_path.is_file() and resolved_path.suffix == ".model":
1060
+ return MossTTSNanoSentencePieceTokenizer(vocab_file=str(resolved_path))
1061
  try:
1062
  return AutoTokenizer.from_pretrained(
1063
  str(resolved_path),
 
1069
  except Exception:
1070
  model_path = resolved_path / "tokenizer.model"
1071
  if model_path.is_file():
1072
+ return MossTTSNanoSentencePieceTokenizer(vocab_file=str(model_path))
1073
  raise
1074
 
1075
  @staticmethod
 
1276
  if isinstance(output, (list, tuple)) and output:
1277
  if len(output) == 2 and isinstance(output[1], (int, float)):
1278
  return output[0]
1279
+ return MossTTSNanoForCausalLM._extract_tensor_candidate(output[0])
1280
  raise TypeError(f"Unsupported audio tokenizer output type: {type(output)!r}")
1281
 
1282
  @staticmethod
 
1750
  return
1751
  yield {
1752
  "type": "final",
1753
+ "generation": MossTTSNanoGenerationOutput(audio_token_ids=audio_token_ids, prompt_input_ids=input_ids),
1754
  }
1755
 
1756
  @torch.no_grad()
prompting.py CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
2
 
3
  from typing import List, Sequence
4
 
5
- from .configuration_nanotts import NanoTTSConfig
6
 
7
 
8
  USER_ROLE_PREFIX = "user\n"
@@ -48,7 +48,7 @@ def decode_text(tokenizer, token_ids: Sequence[int]) -> str:
48
  return str(tokenizer.decode(list(token_ids)))
49
 
50
 
51
- def build_user_prompt_prefix(tokenizer, config: NanoTTSConfig) -> List[int]:
52
  return [config.im_start_token_id] + encode_text(tokenizer, USER_ROLE_PREFIX) + encode_text(
53
  tokenizer,
54
  USER_TEMPLATE_REFERENCE_PREFIX,
@@ -59,7 +59,7 @@ def build_user_prompt_after_reference(tokenizer) -> List[int]:
59
  return encode_text(tokenizer, USER_TEMPLATE_AFTER_REFERENCE)
60
 
61
 
62
- def build_assistant_prompt_prefix(tokenizer, config: NanoTTSConfig) -> List[int]:
63
  return encode_text(tokenizer, USER_TEMPLATE_SUFFIX) + [config.im_end_token_id] + encode_text(
64
  tokenizer,
65
  ASSISTANT_TURN_PREFIX,
@@ -69,7 +69,7 @@ def build_assistant_prompt_prefix(tokenizer, config: NanoTTSConfig) -> List[int]
69
  )
70
 
71
 
72
- def build_prompt_prefix(tokenizer, config: NanoTTSConfig) -> List[int]:
73
  return (
74
  build_user_prompt_prefix(tokenizer, config)
75
  + encode_text(tokenizer, "None")
@@ -77,13 +77,13 @@ def build_prompt_prefix(tokenizer, config: NanoTTSConfig) -> List[int]:
77
  )
78
 
79
 
80
- def build_prompt_suffix(tokenizer, config: NanoTTSConfig) -> List[int]:
81
  return build_assistant_prompt_prefix(tokenizer, config)
82
 
83
 
84
  def build_prompt_token_ids(
85
  tokenizer,
86
- config: NanoTTSConfig,
87
  text_token_ids: Sequence[int],
88
  ) -> List[int]:
89
  return build_prompt_prefix(tokenizer, config) + [int(token_id) for token_id in text_token_ids] + build_prompt_suffix(
 
2
 
3
  from typing import List, Sequence
4
 
5
+ from .configuration_moss_tts_nano import MossTTSNanoConfig
6
 
7
 
8
  USER_ROLE_PREFIX = "user\n"
 
48
  return str(tokenizer.decode(list(token_ids)))
49
 
50
 
51
+ def build_user_prompt_prefix(tokenizer, config: MossTTSNanoConfig) -> List[int]:
52
  return [config.im_start_token_id] + encode_text(tokenizer, USER_ROLE_PREFIX) + encode_text(
53
  tokenizer,
54
  USER_TEMPLATE_REFERENCE_PREFIX,
 
59
  return encode_text(tokenizer, USER_TEMPLATE_AFTER_REFERENCE)
60
 
61
 
62
+ def build_assistant_prompt_prefix(tokenizer, config: MossTTSNanoConfig) -> List[int]:
63
  return encode_text(tokenizer, USER_TEMPLATE_SUFFIX) + [config.im_end_token_id] + encode_text(
64
  tokenizer,
65
  ASSISTANT_TURN_PREFIX,
 
69
  )
70
 
71
 
72
+ def build_prompt_prefix(tokenizer, config: MossTTSNanoConfig) -> List[int]:
73
  return (
74
  build_user_prompt_prefix(tokenizer, config)
75
  + encode_text(tokenizer, "None")
 
77
  )
78
 
79
 
80
+ def build_prompt_suffix(tokenizer, config: MossTTSNanoConfig) -> List[int]:
81
  return build_assistant_prompt_prefix(tokenizer, config)
82
 
83
 
84
  def build_prompt_token_ids(
85
  tokenizer,
86
+ config: MossTTSNanoConfig,
87
  text_token_ids: Sequence[int],
88
  ) -> List[int]:
89
  return build_prompt_prefix(tokenizer, config) + [int(token_id) for token_id in text_token_ids] + build_prompt_suffix(
tokenization_nanotts_sentencepiece.py → tokenization_moss_tts_nano.py RENAMED
@@ -11,7 +11,7 @@ from transformers import PreTrainedTokenizer
11
  VOCAB_FILES_NAMES = {"vocab_file": "tokenizer.model"}
12
 
13
 
14
- class NanoTTSSentencePieceTokenizer(PreTrainedTokenizer):
15
  vocab_files_names = VOCAB_FILES_NAMES
16
  model_input_names = ["input_ids", "attention_mask"]
17
 
@@ -101,3 +101,6 @@ class NanoTTSSentencePieceTokenizer(PreTrainedTokenizer):
101
  if token_ids_1 is None:
102
  return [0] * len(token_ids_0)
103
  return [0] * (len(token_ids_0) + len(token_ids_1))
 
 
 
 
11
  VOCAB_FILES_NAMES = {"vocab_file": "tokenizer.model"}
12
 
13
 
14
+ class MossTTSNanoSentencePieceTokenizer(PreTrainedTokenizer):
15
  vocab_files_names = VOCAB_FILES_NAMES
16
  model_input_names = ["input_ids", "attention_mask"]
17
 
 
101
  if token_ids_1 is None:
102
  return [0] * len(token_ids_0)
103
  return [0] * (len(token_ids_0) + len(token_ids_1))
104
+
105
+
106
+ __all__ = ["MossTTSNanoSentencePieceTokenizer"]
tokenizer_config.json CHANGED
@@ -36,7 +36,7 @@
36
  "additional_special_tokens": [],
37
  "auto_map": {
38
  "AutoTokenizer": [
39
- "tokenization_nanotts_sentencepiece.NanoTTSSentencePieceTokenizer",
40
  null
41
  ]
42
  },
@@ -47,6 +47,6 @@
47
  "extra_special_tokens": {},
48
  "model_max_length": 16384,
49
  "pad_token": "<pad>",
50
- "tokenizer_class": "NanoTTSSentencePieceTokenizer",
51
  "unk_token": "<unk>"
52
  }
 
36
  "additional_special_tokens": [],
37
  "auto_map": {
38
  "AutoTokenizer": [
39
+ "tokenization_moss_tts_nano.MossTTSNanoSentencePieceTokenizer",
40
  null
41
  ]
42
  },
 
47
  "extra_special_tokens": {},
48
  "model_max_length": 16384,
49
  "pad_token": "<pad>",
50
+ "tokenizer_class": "MossTTSNanoSentencePieceTokenizer",
51
  "unk_token": "<unk>"
52
  }