mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 19:06:11 +00:00
Say what the local models are running on
"Use the graphics card" was a flag and nothing else: whisper got -ng when it was off, llama got -ngl 99 or 0, and nobody looked at what happened next. A build without a GPU backend runs on the processor while the box stays ticked, which is what the release archives for Linux do, every time. Nothing anywhere reported whether the local server was even up. Both servers already say where the model went, in the log Dikte captures. It is read back once the server reports ready and turned into a backend, a card and, for llama, the layers it offloaded. The verdict comes from what whisper committed to -- "using X backend" and the model buffer -- rather than from the devices it merely listed: a card that is found and then fails to initialise sends it back to the processor, and the listing alone would have called that a graphics card. A log that says nothing stays "could not tell" instead of being guessed at; a hand-built macOS whisper has Metal compiled in and prints no backend line at all. The state is then somewhere to be seen. Server.state() is a snapshot of the process and what it settled on, and it reaches `dikte status`, `dikte doctor` and a line under each local model box in the settings window. doctor reads the log from disk when no instance is running, so it still answers on a machine where Dikte is closed, and it says which of the three it is: what the last run used, that the last run said nothing, or that none ever ran here. Where the card was asked for and not obtained, the line says which of the two it is -- none was found, or this build carries none -- because only the second is worth replacing a download over. The tests grew a second isolation. They read ggml's own data directory, which is the real one on the machine running them, and program_path prefers a whisper-server on the PATH, so the suite answered from whatever the developer happened to have installed. Both are now the test's own. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019zqCqhmeaNT6m1GPp8ZWPp
This commit is contained in:
+55
-1
@@ -13,7 +13,7 @@ from typing import ClassVar
|
||||
from unittest import mock
|
||||
|
||||
from PyQt6.QtCore import QPoint, QPointF, Qt
|
||||
from PyQt6.QtGui import QWheelEvent
|
||||
from PyQt6.QtGui import QHideEvent, QShowEvent, QWheelEvent
|
||||
from PyQt6.QtWidgets import QApplication, QMessageBox
|
||||
|
||||
from dikte import audio
|
||||
@@ -1177,6 +1177,60 @@ class LocalModels(DikteTest):
|
||||
self.window(conf)._save()
|
||||
self.assertEqual(conf["local_model"], "ggml-large-v3-turbo-q5_0.bin")
|
||||
|
||||
def state(self, **values):
|
||||
base = {"running": True, "pid": 3, "port": 4321, "model": "ggml-small.bin",
|
||||
"gpu_wanted": True, "backend": "CUDA", "device": "RTX 4070",
|
||||
"layers": "", "available": ["CUDA", "CPU"]}
|
||||
base.update(values)
|
||||
return base
|
||||
|
||||
def shown(self, **values):
|
||||
"""The line the window writes under the local model boxes."""
|
||||
window = self.window(self.config(transcribe_provider="local"))
|
||||
with mock.patch.object(ggml, "state",
|
||||
return_value={"whisper": self.state(**values),
|
||||
"llama": self.state(running=False)}):
|
||||
window._show_local_state()
|
||||
return window.local_state.text(), window.local_llm_state.text()
|
||||
|
||||
def test_a_loaded_model_says_which_card_it_is_on(self):
|
||||
whisper, llm = self.shown()
|
||||
self.assertIn("graphics card", whisper)
|
||||
self.assertIn("RTX 4070", whisper)
|
||||
# The other box is about the other model, and that one is not loaded.
|
||||
self.assertIn("Not loaded", llm)
|
||||
|
||||
def test_a_card_asked_for_and_missing_is_not_left_to_be_guessed_at(self):
|
||||
whisper, _ = self.shown(backend="CPU", device="CPU", available=["CPU"])
|
||||
self.assertIn("processor", whisper)
|
||||
self.assertIn("no graphics backend", whisper)
|
||||
|
||||
def test_a_build_that_could_have_used_one_says_the_other_thing(self):
|
||||
whisper, _ = self.shown(backend="CPU", device="CPU",
|
||||
available=["CUDA", "CPU"])
|
||||
self.assertIn("none was found", whisper)
|
||||
self.assertNotIn("no graphics backend", whisper)
|
||||
|
||||
def test_a_processor_nobody_argued_about_is_stated_plainly(self):
|
||||
whisper, _ = self.shown(backend="CPU", device="CPU", gpu_wanted=False,
|
||||
available=["CPU"])
|
||||
self.assertEqual(whisper, "Loaded on the processor (CPU).")
|
||||
|
||||
def test_a_server_that_said_nothing_is_not_answered_for(self):
|
||||
"""A whisper built by hand on a Mac prints no backend line at all."""
|
||||
whisper, _ = self.shown(backend="", device="", available=[])
|
||||
self.assertIn("did not say", whisper)
|
||||
|
||||
def test_the_line_stops_being_written_while_the_window_is_away(self):
|
||||
# The events rather than show() and hide(): showing the window for real
|
||||
# would send the same event down to the download boxes, which answer it
|
||||
# by asking Hugging Face what models there are.
|
||||
window = self.window(self.config(transcribe_provider="local"))
|
||||
window.showEvent(QShowEvent())
|
||||
self.assertTrue(window._local_state_timer.isActive())
|
||||
window.hideEvent(QHideEvent())
|
||||
self.assertFalse(window._local_state_timer.isActive())
|
||||
|
||||
def test_nothing_is_fetched_for_a_window_nobody_opened(self):
|
||||
# DikteTest closes the network, so a request would fail the test. The
|
||||
# lists are asked for when the box is shown, not when it is built.
|
||||
|
||||
Reference in New Issue
Block a user