This commit is contained in:
tuna2134
2026-07-23 11:51:07 +09:00
parent 4f3bcfd252
commit 9cfaa27f3f
5 changed files with 87 additions and 17 deletions

View File

@@ -55,7 +55,7 @@ def process_line(x: tuple[str, bool]):
bert_path = wav_path.replace(".WAV", ".wav").replace(".wav", ".bert.pt") bert_path = wav_path.replace(".WAV", ".wav").replace(".wav", ".bert.pt")
try: try:
bert = torch.load(bert_path) bert = torch.load(bert_path, weights_only=True)
assert bert.shape[-1] == len(phone) assert bert.shape[-1] == len(phone)
except Exception: except Exception:
bert = extract_bert_feature(text, word2ph, Languages(language_str), device) bert = extract_bert_feature(text, word2ph, Languages(language_str), device)

View File

@@ -129,7 +129,7 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
if self.use_mel_spec_posterior: if self.use_mel_spec_posterior:
spec_filename = spec_filename.replace(".spec.pt", ".mel.pt") spec_filename = spec_filename.replace(".spec.pt", ".mel.pt")
try: try:
spec = torch.load(spec_filename) spec = torch.load(spec_filename, weights_only=True)
except: except:
if self.use_mel_spec_posterior: if self.use_mel_spec_posterior:
spec = mel_spectrogram_torch( spec = mel_spectrogram_torch(
@@ -168,7 +168,7 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
word2ph[0] += 1 word2ph[0] += 1
bert_path = wav_path.replace(".wav", ".bert.pt") bert_path = wav_path.replace(".wav", ".bert.pt")
try: try:
bert_ori = torch.load(bert_path) bert_ori = torch.load(bert_path, weights_only=True)
assert bert_ori.shape[-1] == len(phone) assert bert_ori.shape[-1] == len(phone)
except Exception as e: except Exception as e:
logger.warning("Bert load Failed") logger.warning("Bert load Failed")

View File

@@ -32,7 +32,9 @@ def load_checkpoint(
""" """
assert os.path.isfile(checkpoint_path) assert os.path.isfile(checkpoint_path)
checkpoint_dict = torch.load(checkpoint_path, map_location=device) checkpoint_dict = torch.load(
checkpoint_path, map_location=device, weights_only=True
)
iteration = checkpoint_dict["iteration"] iteration = checkpoint_dict["iteration"]
learning_rate = checkpoint_dict["learning_rate"] learning_rate = checkpoint_dict["learning_rate"]
logger.info( logger.info(

View File

@@ -9,7 +9,13 @@ from enum import Enum
from re import findall, fullmatch from re import findall, fullmatch
from typing import List, Optional from typing import List, Optional
from pydantic import BaseModel, Field, validator from pydantic import (
BaseModel,
ConfigDict,
Field,
ValidationInfo,
field_validator,
)
USER_DICT_MIN_PRIORITY = 0 USER_DICT_MIN_PRIORITY = 0
@@ -39,11 +45,11 @@ class UserDictWord(BaseModel):
mora_count: Optional[int] = Field(title="モーラ数", default=None) mora_count: Optional[int] = Field(title="モーラ数", default=None)
accent_associative_rule: str = Field(title="アクセント結合規則") accent_associative_rule: str = Field(title="アクセント結合規則")
class Config: model_config = ConfigDict(validate_assignment=True, validate_default=True)
validate_assignment = True
@validator("surface") @field_validator("surface")
def convert_to_zenkaku(cls, surface): @classmethod
def convert_to_zenkaku(cls, surface: str) -> str:
return surface.translate( return surface.translate(
str.maketrans( str.maketrans(
"".join(chr(0x21 + i) for i in range(94)), "".join(chr(0x21 + i) for i in range(94)),
@@ -51,8 +57,9 @@ class UserDictWord(BaseModel):
) )
) )
@validator("pronunciation", pre=True) @field_validator("pronunciation", mode="before")
def check_is_katakana(cls, pronunciation): @classmethod
def check_is_katakana(cls, pronunciation: str) -> str:
if not fullmatch(r"[ァ-ヴー]+", pronunciation): if not fullmatch(r"[ァ-ヴー]+", pronunciation):
raise ValueError("発音は有効なカタカナでなくてはいけません。") raise ValueError("発音は有効なカタカナでなくてはいけません。")
sutegana = ["", "", "", "", "", "", "", "", "", ""] sutegana = ["", "", "", "", "", "", "", "", "", ""]
@@ -75,9 +82,12 @@ class UserDictWord(BaseModel):
) )
return pronunciation return pronunciation
@validator("mora_count", pre=True, always=True) @field_validator("mora_count", mode="before")
def check_mora_count_and_accent_type(cls, mora_count, values): @classmethod
if "pronunciation" not in values or "accent_type" not in values: def check_mora_count_and_accent_type(
cls, mora_count: Optional[int], info: ValidationInfo
) -> Optional[int]:
if "pronunciation" not in info.data or "accent_type" not in info.data:
# 適切な場所でエラーを出すようにする # 適切な場所でエラーを出すようにする
return mora_count return mora_count
@@ -91,14 +101,14 @@ class UserDictWord(BaseModel):
mora_count = len( mora_count = len(
findall( findall(
f"(?:{rule_others}|{rule_line_i}|{rule_line_u}|{rule_one_mora})", f"(?:{rule_others}|{rule_line_i}|{rule_line_u}|{rule_one_mora})",
values["pronunciation"], info.data["pronunciation"],
) )
) )
if not 0 <= values["accent_type"] <= mora_count: if not 0 <= info.data["accent_type"] <= mora_count:
raise ValueError( raise ValueError(
"誤ったアクセント型です({})。 expect: 0 <= accent_type <= {}".format( "誤ったアクセント型です({})。 expect: 0 <= accent_type <= {}".format(
values["accent_type"], mora_count info.data["accent_type"], mora_count
) )
) )
return mora_count return mora_count

View File

@@ -0,0 +1,58 @@
from pathlib import Path
import pytest
import torch
from pydantic import ValidationError
from style_bert_vits2.models.utils.checkpoints import load_checkpoint, save_checkpoint
from style_bert_vits2.nlp.japanese.user_dict.word_model import UserDictWord
def _user_dict_word(**overrides: object) -> UserDictWord:
values = {
"surface": "test",
"priority": 5,
"part_of_speech": "名詞",
"part_of_speech_detail_1": "一般",
"part_of_speech_detail_2": "*",
"part_of_speech_detail_3": "*",
"inflectional_type": "*",
"inflectional_form": "*",
"stem": "*",
"yomi": "テスト",
"pronunciation": "テスト",
"accent_type": 1,
"accent_associative_rule": "*",
}
values.update(overrides)
return UserDictWord.model_validate(values)
def test_user_dict_word_uses_pydantic_v2_validation() -> None:
word = _user_dict_word()
assert word.surface == ""
assert word.mora_count == 3
with pytest.raises(ValidationError):
_user_dict_word(pronunciation="てすと")
def test_checkpoint_round_trip_with_safe_torch_load(tmp_path: Path) -> None:
checkpoint_path = tmp_path / "checkpoint.pth"
source = torch.nn.Linear(2, 1)
optimizer = torch.optim.AdamW(source.parameters())
save_checkpoint(source, optimizer, 1e-4, 12, checkpoint_path)
destination = torch.nn.Linear(2, 1)
destination_optimizer = torch.optim.AdamW(destination.parameters())
_, _, learning_rate, iteration = load_checkpoint(
checkpoint_path, destination, destination_optimizer
)
assert learning_rate == 1e-4
assert iteration == 12
for source_parameter, destination_parameter in zip(
source.parameters(), destination.parameters()
):
assert torch.equal(source_parameter, destination_parameter)