mirror of
https://github.com/TaterTotterson/microWakeWord-Trainer-Nvidia-Docker.git
synced 2026-08-12 07:55:33 -06:00
Release NVIDIA WakeWord Trainer v16
This commit is contained in:
@@ -22,7 +22,7 @@ docker pull ghcr.io/tatertotterson/microwakeword:latest
|
|||||||
Tagged releases also publish matching immutable image tags:
|
Tagged releases also publish matching immutable image tags:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker pull ghcr.io/tatertotterson/microwakeword:v15
|
docker pull ghcr.io/tatertotterson/microwakeword:v16
|
||||||
```
|
```
|
||||||
|
|
||||||
The release tag must match `VERSION`. Update `WHATS_NEW.md` before tagging; the Docker workflow prepends it to GitHub's automatically generated release notes.
|
The release tag must match `VERSION`. Update `WHATS_NEW.md` before tagging; the Docker workflow prepends it to GitHub's automatically generated release notes.
|
||||||
@@ -32,7 +32,7 @@ Python 3.13 TensorFlow build for `sm_120`:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker pull ghcr.io/tatertotterson/microwakeword:blackwell
|
docker pull ghcr.io/tatertotterson/microwakeword:blackwell
|
||||||
docker pull ghcr.io/tatertotterson/microwakeword:v15-blackwell
|
docker pull ghcr.io/tatertotterson/microwakeword:v16-blackwell
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the Blackwell image only for RTX 50-series cards. It includes the
|
Use the Blackwell image only for RTX 50-series cards. It includes the
|
||||||
@@ -53,9 +53,9 @@ docker run -d \
|
|||||||
ghcr.io/tatertotterson/microwakeword:latest
|
ghcr.io/tatertotterson/microwakeword:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Use a version tag such as `ghcr.io/tatertotterson/microwakeword:v15` when you want to pin a known release instead of tracking `latest`.
|
Use a version tag such as `ghcr.io/tatertotterson/microwakeword:v16` when you want to pin a known release instead of tracking `latest`.
|
||||||
For RTX 50-series cards, use `ghcr.io/tatertotterson/microwakeword:blackwell`
|
For RTX 50-series cards, use `ghcr.io/tatertotterson/microwakeword:blackwell`
|
||||||
or a pinned tag such as `ghcr.io/tatertotterson/microwakeword:v15-blackwell`
|
or a pinned tag such as `ghcr.io/tatertotterson/microwakeword:v16-blackwell`
|
||||||
in the same `docker run` command.
|
in the same `docker run` command.
|
||||||
|
|
||||||
The flags:
|
The flags:
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
- Added secure Tater linking: enter the short-lived code from Tater Voice Settings instead of giving the trainer a general API token.
|
- Fixed a startup crash caused by newer pip-installed NVIDIA cuBLAS and cuDNN namespace packages not providing a module file path.
|
||||||
- Automatic and manual publishing now tell Tater which trained wake word is active, and Tater applies it globally to every connected satellite.
|
- CUDA library discovery now works across both the standard NVIDIA and Blackwell images and safely allows startup when the optional libraries are unavailable.
|
||||||
- Added clear linked, unlinked, and pairing-success states to the Auto Training interface.
|
|
||||||
|
|||||||
38
run.sh
38
run.sh
@@ -107,19 +107,33 @@ fi
|
|||||||
# Faster Whisper/CTranslate2 loads these CUDA libraries before Python starts.
|
# Faster Whisper/CTranslate2 loads these CUDA libraries before Python starts.
|
||||||
# They live in the persistent UI venv so both Docker image variants can use GPU STT.
|
# They live in the persistent UI venv so both Docker image variants can use GPU STT.
|
||||||
WHISPER_CUDA_LIBRARY_PATH="$("${PY}" - <<'PY'
|
WHISPER_CUDA_LIBRARY_PATH="$("${PY}" - <<'PY'
|
||||||
import os
|
from importlib.util import find_spec
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
try:
|
|
||||||
import nvidia.cublas.lib
|
def package_directory(name):
|
||||||
import nvidia.cudnn.lib
|
try:
|
||||||
except ImportError:
|
spec = find_spec(name)
|
||||||
print("")
|
except (ImportError, AttributeError, ValueError):
|
||||||
else:
|
return ""
|
||||||
print(
|
if spec is None:
|
||||||
os.path.dirname(nvidia.cublas.lib.__file__)
|
return ""
|
||||||
+ ":"
|
|
||||||
+ os.path.dirname(nvidia.cudnn.lib.__file__)
|
for location in spec.submodule_search_locations or ():
|
||||||
)
|
if location:
|
||||||
|
return str(Path(location).resolve())
|
||||||
|
|
||||||
|
origin = spec.origin
|
||||||
|
if origin and origin not in {"built-in", "frozen"}:
|
||||||
|
return str(Path(origin).resolve().parent)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
paths = [
|
||||||
|
package_directory("nvidia.cublas.lib"),
|
||||||
|
package_directory("nvidia.cudnn.lib"),
|
||||||
|
]
|
||||||
|
print(":".join(dict.fromkeys(path for path in paths if path)))
|
||||||
PY
|
PY
|
||||||
)"
|
)"
|
||||||
if [[ -n "${WHISPER_CUDA_LIBRARY_PATH}" ]]; then
|
if [[ -n "${WHISPER_CUDA_LIBRARY_PATH}" ]]; then
|
||||||
|
|||||||
66
tests/test_run_sh.py
Normal file
66
tests/test_run_sh.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
RUN_SH = REPO_ROOT / "run.sh"
|
||||||
|
|
||||||
|
|
||||||
|
def _cuda_path_probe() -> str:
|
||||||
|
source = RUN_SH.read_text(encoding="utf-8")
|
||||||
|
match = re.search(
|
||||||
|
r'WHISPER_CUDA_LIBRARY_PATH="\$\("\$\{PY\}" - <<\'PY\'\n(?P<probe>.*?)\nPY\n\)"',
|
||||||
|
source,
|
||||||
|
flags=re.DOTALL,
|
||||||
|
)
|
||||||
|
if match is None:
|
||||||
|
raise AssertionError("Could not locate the CUDA library path probe in run.sh")
|
||||||
|
return match.group("probe")
|
||||||
|
|
||||||
|
|
||||||
|
class RunShCudaLibraryPathTests(unittest.TestCase):
|
||||||
|
def _run_probe(self, python_path: Path) -> subprocess.CompletedProcess[str]:
|
||||||
|
env = dict(os.environ)
|
||||||
|
env["PYTHONPATH"] = str(python_path)
|
||||||
|
return subprocess.run(
|
||||||
|
[sys.executable, "-S", "-"],
|
||||||
|
input=_cuda_path_probe(),
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
check=False,
|
||||||
|
env=env,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_namespace_cuda_packages_do_not_require_module_file(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
root = Path(temp_dir)
|
||||||
|
cublas_lib = root / "nvidia" / "cublas" / "lib"
|
||||||
|
cudnn_lib = root / "nvidia" / "cudnn" / "lib"
|
||||||
|
cublas_lib.mkdir(parents=True)
|
||||||
|
cudnn_lib.mkdir(parents=True)
|
||||||
|
|
||||||
|
result = self._run_probe(root)
|
||||||
|
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertEqual(
|
||||||
|
result.stdout.strip().split(":"),
|
||||||
|
[str(cublas_lib.resolve()), str(cudnn_lib.resolve())],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_missing_cuda_packages_return_an_empty_path(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
result = self._run_probe(Path(temp_dir))
|
||||||
|
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertEqual(result.stdout.strip(), "")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user