diff dictation/config.py @ 275:78699f810817

Add Qwen3-VL and WebRTC dictation services Add Bazel targets for the CUDA-backed Qwen3-VL server and a local WebRTC faster-whisper dictation service. Co-authored-by: Copilot <[email protected]> Copilot-Session: e3d8cb06-6c95-4ae0-9757-651d3796ab00
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 10:58:47 -0700
parents
children 49e9e591c9bb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dictation/config.py	Mon Aug 17 10:58:47 2026 -0700
@@ -0,0 +1,104 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+import os
+from pathlib import Path
+
+
+MODEL_REPOSITORY = "Systran/faster-whisper-small"
+MODEL_REVISION = "536b0662742c02347bc0e980a01041f333bce120"
+
+
+def _integer(name: str, default: int, minimum: int, maximum: int) -> int:
+    raw = os.environ.get(name)
+    if raw is None:
+        return default
+    try:
+        value = int(raw)
+    except ValueError as error:
+        raise ValueError(f"{name} must be an integer") from error
+    if value < minimum or value > maximum:
+        raise ValueError(f"{name} must be between {minimum} and {maximum}")
+    return value
+
+
+def _float(name: str, default: float, minimum: float, maximum: float) -> float:
+    raw = os.environ.get(name)
+    if raw is None:
+        return default
+    try:
+        value = float(raw)
+    except ValueError as error:
+        raise ValueError(f"{name} must be a number") from error
+    if value < minimum or value > maximum:
+        raise ValueError(f"{name} must be between {minimum} and {maximum}")
+    return value
+
+
+@dataclass(frozen=True)
+class DictationConfig:
+    host: str
+    port: int
+    model_dir: Path
+    compute_type: str
+    max_sessions: int
+    partial_interval_ms: int
+    silence_ms: int
+    max_utterance_seconds: int
+    speech_threshold: float
+
+    @classmethod
+    def from_environment(cls) -> "DictationConfig":
+        cache_root = Path(
+            os.environ.get(
+                "XDG_CACHE_HOME",
+                str(Path.home() / ".cache"),
+            )
+        )
+        model_dir = Path(
+            os.environ.get(
+                "DICTATION_MODEL_DIR",
+                str(cache_root / "zenbu" / "faster-whisper-small"),
+            )
+        ).expanduser()
+        compute_type = os.environ.get(
+            "DICTATION_COMPUTE_TYPE",
+            "int8_float16",
+        )
+        if compute_type not in {
+            "float16",
+            "int8_float16",
+            "int8",
+        }:
+            raise ValueError(
+                "DICTATION_COMPUTE_TYPE must be float16, int8_float16, or int8"
+            )
+        host = os.environ.get("DICTATION_HOST", "127.0.0.1")
+        if not host:
+            raise ValueError("DICTATION_HOST must not be empty")
+        return cls(
+            host=host,
+            port=_integer("DICTATION_PORT", 8090, 1, 65535),
+            model_dir=model_dir,
+            compute_type=compute_type,
+            max_sessions=_integer("DICTATION_MAX_SESSIONS", 1, 1, 8),
+            partial_interval_ms=_integer(
+                "DICTATION_PARTIAL_INTERVAL_MS",
+                1200,
+                500,
+                10000,
+            ),
+            silence_ms=_integer("DICTATION_SILENCE_MS", 700, 200, 5000),
+            max_utterance_seconds=_integer(
+                "DICTATION_MAX_UTTERANCE_SECONDS",
+                30,
+                3,
+                120,
+            ),
+            speech_threshold=_float(
+                "DICTATION_SPEECH_THRESHOLD",
+                0.012,
+                0.001,
+                0.5,
+            ),
+        )