Initialize AI processor during daemon startup
This commit is contained in:
parent
09090102a2
commit
85873d739f
3 changed files with 38 additions and 25 deletions
|
|
@ -111,7 +111,7 @@ Recording input can be a device index (preferred) or a substring of the device
|
|||
name.
|
||||
|
||||
AI cleanup is always enabled and uses the locked local Llama-3.2-3B GGUF model
|
||||
downloaded to `~/.cache/aman/models/` on first use.
|
||||
downloaded to `~/.cache/aman/models/` during daemon initialization.
|
||||
|
||||
Use `-v/--verbose` to enable DEBUG logs, including recognized/processed
|
||||
transcript text and llama.cpp logs (`llama::` prefix). Without `-v`, logs are
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ class Daemon:
|
|||
cfg.stt.model,
|
||||
cfg.stt.device,
|
||||
)
|
||||
self.ai_processor: LlamaProcessor | None = None
|
||||
logging.info("initializing ai processor")
|
||||
self.ai_processor = LlamaProcessor(verbose=self.verbose)
|
||||
logging.info("ai processor ready")
|
||||
self.log_transcript = verbose
|
||||
self.vocabulary = VocabularyEngine(cfg.vocabulary, cfg.domain_inference)
|
||||
self._stt_hint_kwargs_cache: dict[str, Any] | None = None
|
||||
|
|
@ -282,7 +284,7 @@ class Daemon:
|
|||
|
||||
def _get_ai_processor(self) -> LlamaProcessor:
|
||||
if self.ai_processor is None:
|
||||
self.ai_processor = LlamaProcessor(verbose=self.verbose)
|
||||
raise RuntimeError("ai processor is not initialized")
|
||||
return self.ai_processor
|
||||
|
||||
def _stt_hint_kwargs(self) -> dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -87,13 +87,25 @@ class DaemonTests(unittest.TestCase):
|
|||
cfg = Config()
|
||||
return cfg
|
||||
|
||||
def _build_daemon(
|
||||
self,
|
||||
desktop: FakeDesktop,
|
||||
model: FakeModel | FakeHintModel,
|
||||
*,
|
||||
cfg: Config | None = None,
|
||||
verbose: bool = False,
|
||||
) -> aman.Daemon:
|
||||
active_cfg = cfg if cfg is not None else self._config()
|
||||
with patch("aman._build_whisper_model", return_value=model), patch(
|
||||
"aman.LlamaProcessor", return_value=FakeAIProcessor()
|
||||
):
|
||||
return aman.Daemon(active_cfg, desktop, verbose=verbose)
|
||||
|
||||
@patch("aman.stop_audio_recording", return_value=FakeAudio(8))
|
||||
@patch("aman.start_audio_recording", return_value=(object(), object()))
|
||||
def test_toggle_start_stop_injects_text(self, _start_mock, _stop_mock):
|
||||
desktop = FakeDesktop()
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()):
|
||||
daemon = aman.Daemon(self._config(), desktop, verbose=False)
|
||||
daemon.ai_processor = FakeAIProcessor()
|
||||
daemon = self._build_daemon(desktop, FakeModel(), verbose=False)
|
||||
daemon._start_stop_worker = (
|
||||
lambda stream, record, trigger, process_audio: daemon._stop_and_process(
|
||||
stream, record, trigger, process_audio
|
||||
|
|
@ -112,9 +124,7 @@ class DaemonTests(unittest.TestCase):
|
|||
@patch("aman.start_audio_recording", return_value=(object(), object()))
|
||||
def test_shutdown_stops_recording_without_injection(self, _start_mock, _stop_mock):
|
||||
desktop = FakeDesktop()
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()):
|
||||
daemon = aman.Daemon(self._config(), desktop, verbose=False)
|
||||
daemon.ai_processor = FakeAIProcessor()
|
||||
daemon = self._build_daemon(desktop, FakeModel(), verbose=False)
|
||||
daemon._start_stop_worker = (
|
||||
lambda stream, record, trigger, process_audio: daemon._stop_and_process(
|
||||
stream, record, trigger, process_audio
|
||||
|
|
@ -136,9 +146,7 @@ class DaemonTests(unittest.TestCase):
|
|||
cfg = self._config()
|
||||
cfg.vocabulary.replacements = [VocabularyReplacement(source="Martha", target="Marta")]
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=model):
|
||||
daemon = aman.Daemon(cfg, desktop, verbose=False)
|
||||
daemon.ai_processor = FakeAIProcessor()
|
||||
daemon = self._build_daemon(desktop, model, cfg=cfg, verbose=False)
|
||||
daemon._start_stop_worker = (
|
||||
lambda stream, record, trigger, process_audio: daemon._stop_and_process(
|
||||
stream, record, trigger, process_audio
|
||||
|
|
@ -156,8 +164,7 @@ class DaemonTests(unittest.TestCase):
|
|||
cfg = self._config()
|
||||
cfg.vocabulary.terms = ["Docker", "Systemd"]
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=model):
|
||||
daemon = aman.Daemon(cfg, desktop, verbose=False)
|
||||
daemon = self._build_daemon(desktop, model, cfg=cfg, verbose=False)
|
||||
|
||||
result = daemon._transcribe(object())
|
||||
|
||||
|
|
@ -172,8 +179,7 @@ class DaemonTests(unittest.TestCase):
|
|||
cfg.vocabulary.terms = ["Systemd"]
|
||||
cfg.vocabulary.replacements = [VocabularyReplacement(source="docker", target="Docker")]
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=model):
|
||||
daemon = aman.Daemon(cfg, desktop, verbose=False)
|
||||
daemon = self._build_daemon(desktop, model, cfg=cfg, verbose=False)
|
||||
|
||||
result = daemon._transcribe(object())
|
||||
|
||||
|
|
@ -186,14 +192,22 @@ class DaemonTests(unittest.TestCase):
|
|||
desktop = FakeDesktop()
|
||||
cfg = self._config()
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()):
|
||||
daemon = aman.Daemon(cfg, desktop, verbose=False)
|
||||
daemon = self._build_daemon(desktop, FakeModel(), cfg=cfg, verbose=False)
|
||||
self.assertFalse(daemon.log_transcript)
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()):
|
||||
daemon_verbose = aman.Daemon(cfg, desktop, verbose=True)
|
||||
daemon_verbose = self._build_daemon(desktop, FakeModel(), cfg=cfg, verbose=True)
|
||||
self.assertTrue(daemon_verbose.log_transcript)
|
||||
|
||||
def test_ai_processor_is_initialized_during_daemon_init(self):
|
||||
desktop = FakeDesktop()
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()), patch(
|
||||
"aman.LlamaProcessor", return_value=FakeAIProcessor()
|
||||
) as processor_cls:
|
||||
daemon = aman.Daemon(self._config(), desktop, verbose=True)
|
||||
|
||||
processor_cls.assert_called_once_with(verbose=True)
|
||||
self.assertIsNotNone(daemon.ai_processor)
|
||||
|
||||
@patch("aman.stop_audio_recording", return_value=FakeAudio(8))
|
||||
@patch("aman.start_audio_recording", return_value=(object(), object()))
|
||||
def test_passes_clipboard_remove_option_to_desktop(self, _start_mock, _stop_mock):
|
||||
|
|
@ -202,9 +216,7 @@ class DaemonTests(unittest.TestCase):
|
|||
cfg = self._config()
|
||||
cfg.injection.remove_transcription_from_clipboard = True
|
||||
|
||||
with patch("aman._build_whisper_model", return_value=model):
|
||||
daemon = aman.Daemon(cfg, desktop, verbose=False)
|
||||
daemon.ai_processor = FakeAIProcessor()
|
||||
daemon = self._build_daemon(desktop, model, cfg=cfg, verbose=False)
|
||||
daemon._start_stop_worker = (
|
||||
lambda stream, record, trigger, process_audio: daemon._stop_and_process(
|
||||
stream, record, trigger, process_audio
|
||||
|
|
@ -218,8 +230,7 @@ class DaemonTests(unittest.TestCase):
|
|||
|
||||
def test_state_changes_are_debug_level(self):
|
||||
desktop = FakeDesktop()
|
||||
with patch("aman._build_whisper_model", return_value=FakeModel()):
|
||||
daemon = aman.Daemon(self._config(), desktop, verbose=False)
|
||||
daemon = self._build_daemon(desktop, FakeModel(), verbose=False)
|
||||
|
||||
with self.assertLogs(level="DEBUG") as logs:
|
||||
daemon.set_state(aman.State.RECORDING)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue