comparison 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
comparison
equal deleted inserted replaced
274:c9be578316a6 275:78699f810817
1 from __future__ import annotations
2
3 from dataclasses import dataclass
4 import os
5 from pathlib import Path
6
7
8 MODEL_REPOSITORY = "Systran/faster-whisper-small"
9 MODEL_REVISION = "536b0662742c02347bc0e980a01041f333bce120"
10
11
12 def _integer(name: str, default: int, minimum: int, maximum: int) -> int:
13 raw = os.environ.get(name)
14 if raw is None:
15 return default
16 try:
17 value = int(raw)
18 except ValueError as error:
19 raise ValueError(f"{name} must be an integer") from error
20 if value < minimum or value > maximum:
21 raise ValueError(f"{name} must be between {minimum} and {maximum}")
22 return value
23
24
25 def _float(name: str, default: float, minimum: float, maximum: float) -> float:
26 raw = os.environ.get(name)
27 if raw is None:
28 return default
29 try:
30 value = float(raw)
31 except ValueError as error:
32 raise ValueError(f"{name} must be a number") from error
33 if value < minimum or value > maximum:
34 raise ValueError(f"{name} must be between {minimum} and {maximum}")
35 return value
36
37
38 @dataclass(frozen=True)
39 class DictationConfig:
40 host: str
41 port: int
42 model_dir: Path
43 compute_type: str
44 max_sessions: int
45 partial_interval_ms: int
46 silence_ms: int
47 max_utterance_seconds: int
48 speech_threshold: float
49
50 @classmethod
51 def from_environment(cls) -> "DictationConfig":
52 cache_root = Path(
53 os.environ.get(
54 "XDG_CACHE_HOME",
55 str(Path.home() / ".cache"),
56 )
57 )
58 model_dir = Path(
59 os.environ.get(
60 "DICTATION_MODEL_DIR",
61 str(cache_root / "zenbu" / "faster-whisper-small"),
62 )
63 ).expanduser()
64 compute_type = os.environ.get(
65 "DICTATION_COMPUTE_TYPE",
66 "int8_float16",
67 )
68 if compute_type not in {
69 "float16",
70 "int8_float16",
71 "int8",
72 }:
73 raise ValueError(
74 "DICTATION_COMPUTE_TYPE must be float16, int8_float16, or int8"
75 )
76 host = os.environ.get("DICTATION_HOST", "127.0.0.1")
77 if not host:
78 raise ValueError("DICTATION_HOST must not be empty")
79 return cls(
80 host=host,
81 port=_integer("DICTATION_PORT", 8090, 1, 65535),
82 model_dir=model_dir,
83 compute_type=compute_type,
84 max_sessions=_integer("DICTATION_MAX_SESSIONS", 1, 1, 8),
85 partial_interval_ms=_integer(
86 "DICTATION_PARTIAL_INTERVAL_MS",
87 1200,
88 500,
89 10000,
90 ),
91 silence_ms=_integer("DICTATION_SILENCE_MS", 700, 200, 5000),
92 max_utterance_seconds=_integer(
93 "DICTATION_MAX_UTTERANCE_SECONDS",
94 30,
95 3,
96 120,
97 ),
98 speech_threshold=_float(
99 "DICTATION_SPEECH_THRESHOLD",
100 0.012,
101 0.001,
102 0.5,
103 ),
104 )