view 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 source

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,
            ),
        )