Complete DDS training workflow and delivery package

This commit is contained in:
andreysk0304 2026-09-24 01:10:49 +03:00
commit 4c4b91064f
229 changed files with 11969 additions and 1024 deletions

View file

@ -1,15 +1,21 @@
"""make models: веса моделей в backend/models/.
"""make models: вспомогательные веса голоса в backend/models/.
Эмбеддинги, распознавание (GigaAM v3, int8) и VAD качаются с Hugging Face.
Эмбеддинги и VAD качаются с Hugging Face. Whisper small, Qwen3 и Vikhr
скачиваются отдельным `make local-models` с проверкой SHA-256. Старый GigaAM
доступен через `--legacy-gigaam`, но в выбранный стек больше не входит.
Синтез (Silero TTS v5) лежит на models.silero.ai — российском хосте, который
не отвечает из-под VPN: его скрипт не качает, а проверяет и говорит, что делать.
Докачка продолжается с места обрыва: сеть на стенде бывает медленной.
"""
import argparse
import ssl
import sys
import urllib.request
from pathlib import Path
import certifi
ROOT = Path(__file__).resolve().parents[1]
MODELS = ROOT / "models"
@ -20,16 +26,16 @@ FILES = {
"e5-small/config.json": E5 + "config.json",
"e5-small/tokenizer.json": E5 + "tokenizer.json",
"e5-small/model_quantized.onnx": E5 + "onnx/model_quantized.onnx",
# RNNT — основная модель, CTC — запасная на случай, если RNNT не загрузится
# (по скорости CTC не выигрывает — docs/LATENCY.md).
"silero-vad/config.json": VAD + "config.json",
"silero-vad/silero_vad.onnx": VAD + "silero_vad.onnx",
}
LEGACY_GIGAAM_FILES = {
"gigaam-v3-onnx/config.json": GIGAAM + "config.json",
"gigaam-v3-onnx/v3_vocab.txt": GIGAAM + "v3_vocab.txt",
"gigaam-v3-onnx/v3_rnnt_encoder.int8.onnx": GIGAAM + "v3_rnnt_encoder.int8.onnx",
"gigaam-v3-onnx/v3_rnnt_decoder.int8.onnx": GIGAAM + "v3_rnnt_decoder.int8.onnx",
"gigaam-v3-onnx/v3_rnnt_joint.int8.onnx": GIGAAM + "v3_rnnt_joint.int8.onnx",
"gigaam-v3-onnx/v3_ctc.int8.onnx": GIGAAM + "v3_ctc.int8.onnx",
"silero-vad/config.json": VAD + "config.json",
"silero-vad/silero_vad.onnx": VAD + "silero_vad.onnx",
}
SILERO_TTS = "silero-tts/v5_ru.pt"
@ -40,19 +46,27 @@ def fetch(url: str, target: Path) -> None:
partial = target.with_suffix(target.suffix + ".part")
offset = partial.stat().st_size if partial.exists() else 0
request = urllib.request.Request(url, headers={"Range": f"bytes={offset}-"} if offset else {})
with urllib.request.urlopen(request, timeout=60) as response, partial.open("ab") as out:
total = offset + int(response.headers.get("Content-Length", 0))
while chunk := response.read(1 << 20):
out.write(chunk)
done = out.tell()
if total:
print(f"\r {target.name}: {done // (1 << 20)} из {total // (1 << 20)} МБ", end="", flush=True)
with urllib.request.urlopen(
request, timeout=60, context=ssl.create_default_context(cafile=certifi.where())
) as response:
resumed = offset > 0 and response.status == 206
with partial.open("ab" if resumed else "wb") as out:
total = (offset if resumed else 0) + int(response.headers.get("Content-Length", 0))
while chunk := response.read(1 << 20):
out.write(chunk)
done = out.tell()
if total:
print(f"\r {target.name}: {done // (1 << 20)} из {total // (1 << 20)} МБ", end="", flush=True)
partial.rename(target)
print()
def main() -> None:
for relative, url in FILES.items():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--legacy-gigaam", action="store_true")
args = parser.parse_args()
files = {**FILES, **(LEGACY_GIGAAM_FILES if args.legacy_gigaam else {})}
for relative, url in files.items():
target = MODELS / relative
if target.exists():
print(f" {relative}: уже есть")