"/" にファイルをアップロード

This commit is contained in:
2026-07-02 15:17:37 +00:00
parent 9334c5a165
commit ecc3f10152

169
changes.patch Normal file
View File

@@ -0,0 +1,169 @@
diff --git a/scripts/convert/README.md b/scripts/convert/README.md
index 3dbf86d..60dc1c1 100644
--- a/scripts/convert/README.md
+++ b/scripts/convert/README.md
@@ -25,6 +25,24 @@
python convert_model.py --style_file "ここにstyle_vectors.npyの場所" --config_file "同様にconfig.json場所" --model_file "同様に.safetensorsで終わるファイルの場所"
```
+TensorRT用のモデルを生成する場合は `--tensorrt` を追加します。
+
+```sh
+python convert_model.py --tensorrt --style_file "style_vectors.npy" --config_file "config.json" --model_file "model.safetensors"
+```
+
+TensorRTモードでは、非対応Opを含む確率的 Duration Predictor の代わりに決定論的 Duration Predictor を使用します。また、`RandomNormalLike` はTensorRT対応の要素演算による決定論的イズへ置換されます。
+
+### trtexecで検証
+
+変換したONNXからTensorRTエンジンをビルドし、実データ型のダミー入力で1回推論します。
+
+```sh
+uv run python test_tensorrt.py ../../models/model_名前.onnx --fp16
+```
+
+`trtexec` がPATHにない場合は `--trtexec /path/to/trtexec` または環境変数 `TRTEXEC` で指定します。デフォルトの動的長プロファイルは1256、最適値とテスト値は32です。必要に応じて `--min-length`、`--opt-length`、`--max-length`、`--test-length` を指定できます。追加の `trtexec` 引数は `--` の後ろへ渡します。
+
4. `models/名前.sbv2`というファイルが出力されます。GUI版のモデルファイルに入れてあげたら使えます。
## Deberta変換
diff --git a/scripts/convert/convert_model.py b/scripts/convert/convert_model.py
index 689809b..d054f83 100644
--- a/scripts/convert/convert_model.py
+++ b/scripts/convert/convert_model.py
@@ -4,6 +4,7 @@ from io import BytesIO
from style_bert_vits2.nlp import bert_models
from style_bert_vits2.constants import Languages
from style_bert_vits2.models.infer import get_net_g, get_text
+from style_bert_vits2.models import commons
from style_bert_vits2.models.hyper_parameters import HyperParameters
import torch
from style_bert_vits2.constants import (
@@ -23,6 +24,11 @@ parser = ArgumentParser()
parser.add_argument("--style_file", required=True)
parser.add_argument("--config_file", required=True)
parser.add_argument("--model_file", required=True)
+parser.add_argument(
+ "--tensorrt",
+ action="store_true",
+ help="Export a TensorRT-compatible deterministic inference graph.",
+)
args = parser.parse_args()
style_file = args.style_file
config_file = args.config_file
@@ -94,20 +100,70 @@ model = get_net_g(
)
-def forward(x, x_len, sid, tone, lang, bert, style, length_scale, sdp_ratio, noise_scale, noise_scale_w):
- return model.infer(
- x,
- x_len,
- sid,
- tone,
- lang,
- bert,
- style,
- sdp_ratio=sdp_ratio,
- length_scale=length_scale,
- noise_scale=noise_scale,
- noise_scale_w=noise_scale_w,
+def _tensorrt_noise_like(value, phase):
+ """Generate deterministic noise using TensorRT-supported elementwise ops."""
+ indices = torch.arange(
+ value.numel(), dtype=value.dtype, device=value.device
+ ).reshape_as(value)
+ # A sum of independent-looking sinusoids has approximately normal variance.
+ return (
+ torch.sin(indices * 12.9898 + phase)
+ + torch.sin(indices * 78.233 + phase * 1.37)
+ + torch.sin(indices * 37.719 + phase * 2.11)
+ ) * 0.816496580927726
+
+
+def forward(
+ x,
+ x_len,
+ sid,
+ tone,
+ lang,
+ bert,
+ style,
+ length_scale,
+ sdp_ratio,
+ noise_scale,
+ noise_scale_w,
+):
+ if not args.tensorrt:
+ return model.infer(
+ x,
+ x_len,
+ sid,
+ tone,
+ lang,
+ bert,
+ style,
+ sdp_ratio=sdp_ratio,
+ length_scale=length_scale,
+ noise_scale=noise_scale,
+ noise_scale_w=noise_scale_w,
+ )
+
+ # The stochastic duration predictor contains NonZero and ScatterND, and
+ # torch.randn_like exports as RandomNormalLike. Those operators cannot be
+ # compiled by TensorRT. Use the deterministic duration predictor and create
+ # latent noise from elementwise operations instead.
+ g = model.emb_g(sid).unsqueeze(-1)
+ hidden, m_p, logs_p, x_mask = model.enc_p(
+ x, x_len, tone, lang, bert, style, g=g
)
+ logw = model.dp(hidden, x_mask, g=g)
+ w = torch.exp(logw) * x_mask * length_scale
+ w_ceil = torch.ceil(w)
+ y_lengths = torch.clamp_min(torch.sum(w_ceil, [1, 2]), 1).long()
+ y_mask = commons.sequence_mask(y_lengths, None).unsqueeze(1).to(x_mask.dtype)
+ attn_mask = x_mask.unsqueeze(2) * y_mask.unsqueeze(-1)
+ attn = commons.generate_path(w_ceil, attn_mask)
+ m_p = torch.matmul(attn.squeeze(1), m_p.transpose(1, 2)).transpose(1, 2)
+ logs_p = torch.matmul(attn.squeeze(1), logs_p.transpose(1, 2)).transpose(1, 2)
+ # Keep both legacy controls as part of the deterministic phase so the ONNX
+ # input contract remains compatible with existing runtimes.
+ phase = noise_scale_w + sdp_ratio
+ z_p = m_p + _tensorrt_noise_like(m_p, phase) * torch.exp(logs_p) * noise_scale
+ z = model.flow(z_p, y_mask, g=g, reverse=True)
+ return model.dec(z * y_mask, g=g)
model.forward = forward
@@ -128,6 +184,9 @@ torch.onnx.export(
torch.tensor(0.8),
),
f"../../models/model_{out_name}.onnx",
+ # Preserve the established Style-Bert-VITS2 ONNX graph. The dynamo exporter
+ # (the default in recent PyTorch) cannot lower the complete inference path.
+ dynamo=False,
verbose=True,
dynamic_axes={
"x_tst": {0: "batch_size", 1: "x_tst_max_length"},
@@ -153,7 +212,20 @@ torch.onnx.export(
],
output_names=["output"],
)
-os.system(f"onnxsim ../../models/model_{out_name}.onnx ../../models/model_{out_name}.onnx")
+onnx_path = f"../../models/model_{out_name}.onnx"
+os.system(f"onnxsim {onnx_path} {onnx_path}")
+
+if args.tensorrt:
+ import onnx
+
+ unsupported_ops = {"NonZero", "RandomNormalLike", "ScatterND"}
+ graph_ops = {node.op_type for node in onnx.load(onnx_path).graph.node}
+ remaining_ops = unsupported_ops & graph_ops
+ if remaining_ops:
+ raise RuntimeError(
+ "TensorRT-incompatible operators remain after export: "
+ + ", ".join(sorted(remaining_ops))
+ )
onnxfile = open(f"../../models/model_{out_name}.onnx", "rb").read()
stylefile = open(f"../../models/style_vectors_{out_name}.json", "rb").read()
version = bytes("1", "utf8")