mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Say when the processor build landed instead of the Vulkan one
The install falls back to upstream's CPU archive whenever Dikte's own release, the file in it, or its reviewed digest is not there, and until the package is published by hand that is every download. It happened without a word: the window said "Downloaded, version v1.9.3." either way, and a graphics card sitting idle looks exactly like one being used. The install record now carries which of the two builds landed, written only where both were on offer, and the settings window says so on the line that already reports the version.
This commit is contained in:
+36
-6
@@ -284,6 +284,17 @@ def _wanted_assets(program):
|
|||||||
return (f"bin-ubuntu-{arch}.tar.gz",)
|
return (f"bin-ubuntu-{arch}.tar.gz",)
|
||||||
|
|
||||||
|
|
||||||
|
def _managed_whisper(program, tag=""):
|
||||||
|
"""Whether this machine is one Dikte publishes its own whisper-server for.
|
||||||
|
|
||||||
|
Linux x86_64 with a Vulkan loader on it, and no version asked for by hand:
|
||||||
|
a pinned version is upstream's to answer.
|
||||||
|
"""
|
||||||
|
return (not tag and program is WHISPER and sys.platform == "linux"
|
||||||
|
and platform.machine().lower() in ("x86_64", "amd64")
|
||||||
|
and _has_vulkan())
|
||||||
|
|
||||||
|
|
||||||
def _install_record(program):
|
def _install_record(program):
|
||||||
return BIN_DIR / program.name / "installed.json"
|
return BIN_DIR / program.name / "installed.json"
|
||||||
|
|
||||||
@@ -307,6 +318,21 @@ def installed_version(program):
|
|||||||
return _read_record(program).get("tag") or ""
|
return _read_record(program).get("tag") or ""
|
||||||
|
|
||||||
|
|
||||||
|
def vulkan_missing(program):
|
||||||
|
"""Whether what Dikte installed is the processor build on a machine the
|
||||||
|
Vulkan one was fetched for.
|
||||||
|
|
||||||
|
The Vulkan whisper-server is a release of Dikte's own, published by hand
|
||||||
|
once the reviewed archive is built, and the install falls back to the
|
||||||
|
upstream processor build whenever that release, the file in it, or its
|
||||||
|
reviewed digest is not there. Nothing is wrong with the fallback except
|
||||||
|
that it is invisible: a graphics card sitting idle looks exactly like a
|
||||||
|
graphics card being used.
|
||||||
|
"""
|
||||||
|
return (bool(installed_program(program))
|
||||||
|
and _read_record(program).get("backend") == "processor")
|
||||||
|
|
||||||
|
|
||||||
def program_path(program, custom=""):
|
def program_path(program, custom=""):
|
||||||
"""Which copy of the program to run, or "" when there is none.
|
"""Which copy of the program to run, or "" when there is none.
|
||||||
|
|
||||||
@@ -382,10 +408,8 @@ def install_program(program, tag="", on_progress=None, should_stop=None,
|
|||||||
"""
|
"""
|
||||||
repo = program.repo
|
repo = program.repo
|
||||||
release_tag = tag or "latest"
|
release_tag = tag or "latest"
|
||||||
managed = (not tag and program is WHISPER and sys.platform == "linux"
|
managed = _managed_whisper(program, tag)
|
||||||
and platform.machine().lower() in ("x86_64", "amd64")
|
item, vulkan = None, False
|
||||||
and _has_vulkan())
|
|
||||||
item = None
|
|
||||||
if managed:
|
if managed:
|
||||||
repo = DIKTE_REPO
|
repo = DIKTE_REPO
|
||||||
release_tag = MANAGED_WHISPER_RELEASE
|
release_tag = MANAGED_WHISPER_RELEASE
|
||||||
@@ -398,6 +422,7 @@ def install_program(program, tag="", on_progress=None, should_stop=None,
|
|||||||
item = next((a for a in assets
|
item = next((a for a in assets
|
||||||
if a.name.endswith(MANAGED_WHISPER_VULKAN)
|
if a.name.endswith(MANAGED_WHISPER_VULKAN)
|
||||||
and a.sha256 == MANAGED_WHISPER_SHA256), None)
|
and a.sha256 == MANAGED_WHISPER_SHA256), None)
|
||||||
|
vulkan = item is not None
|
||||||
if item:
|
if item:
|
||||||
tag = MANAGED_WHISPER_VERSION
|
tag = MANAGED_WHISPER_VERSION
|
||||||
|
|
||||||
@@ -476,8 +501,13 @@ def install_program(program, tag="", on_progress=None, should_stop=None,
|
|||||||
# Found under the sibling, run from the final directory.
|
# Found under the sibling, run from the final directory.
|
||||||
binary = into / binary.relative_to(fresh)
|
binary = into / binary.relative_to(fresh)
|
||||||
# Written last, so the record never points at anything half-made.
|
# Written last, so the record never points at anything half-made.
|
||||||
_install_record(program).write_text(
|
record = {"tag": tag, "binary": str(binary)}
|
||||||
json.dumps({"tag": tag, "binary": str(binary)}), encoding="utf-8")
|
if managed:
|
||||||
|
# Which of the two builds this machine ended up with. Only written
|
||||||
|
# where both were on offer, so an install that never had the
|
||||||
|
# choice is not made to look like a fallback.
|
||||||
|
record["backend"] = "vulkan" if vulkan else "processor"
|
||||||
|
_install_record(program).write_text(json.dumps(record), encoding="utf-8")
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
raise LocalError(t("Could not install {name}: {error}",
|
raise LocalError(t("Could not install {name}: {error}",
|
||||||
name=program.name, error=exc)) from exc
|
name=program.name, error=exc)) from exc
|
||||||
|
|||||||
@@ -780,6 +780,9 @@ TR = {
|
|||||||
"Not installed.": "Kurulu değil.",
|
"Not installed.": "Kurulu değil.",
|
||||||
"Installed on the system: {path}": "Sistemde kurulu: {path}",
|
"Installed on the system: {path}": "Sistemde kurulu: {path}",
|
||||||
"Downloaded, version {version}.": "İndirildi, sürüm {version}.",
|
"Downloaded, version {version}.": "İndirildi, sürüm {version}.",
|
||||||
|
"Downloaded, version {version}. There was no Vulkan build, "
|
||||||
|
"so this one runs on the processor.":
|
||||||
|
"İndirildi, sürüm {version}. Vulkan sürümü yoktu, bu sürüm işlemcide çalışıyor.",
|
||||||
"Fetching the model list…": "Model listesi çekiliyor…",
|
"Fetching the model list…": "Model listesi çekiliyor…",
|
||||||
"Downloading…": "İndiriliyor…",
|
"Downloading…": "İndiriliyor…",
|
||||||
"Downloading: {done} of {total}{share}": "İndiriliyor: {done} / {total}{share}",
|
"Downloading: {done} of {total}{share}": "İndiriliyor: {done} / {total}{share}",
|
||||||
|
|||||||
@@ -358,6 +358,13 @@ class LocalModelBox(QGroupBox):
|
|||||||
# for this machine and may reach the graphics card, while the
|
# for this machine and may reach the graphics card, while the
|
||||||
# released binaries carry processor backends only.
|
# released binaries carry processor backends only.
|
||||||
self.program_label.setText(t("Installed on the system: {path}", path=path))
|
self.program_label.setText(t("Installed on the system: {path}", path=path))
|
||||||
|
elif ggml.vulkan_missing(self.program):
|
||||||
|
# The download landed the processor build where the graphics card
|
||||||
|
# one belongs, and nothing else on this window would say so.
|
||||||
|
self.program_label.setText(
|
||||||
|
t("Downloaded, version {version}. There was no Vulkan build, "
|
||||||
|
"so this one runs on the processor.",
|
||||||
|
version=ggml.installed_version(self.program) or "?"))
|
||||||
else:
|
else:
|
||||||
self.program_label.setText(
|
self.program_label.setText(
|
||||||
t("Downloaded, version {version}.",
|
t("Downloaded, version {version}.",
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ class InstallProgram(Local):
|
|||||||
"whisper-bin-ubuntu-vulkan-x64.tar.gz"))
|
"whisper-bin-ubuntu-vulkan-x64.tar.gz"))
|
||||||
self.assertTrue(os.path.isfile(path))
|
self.assertTrue(os.path.isfile(path))
|
||||||
self.assertEqual("v1.9.3", ggml.installed_version(ggml.WHISPER))
|
self.assertEqual("v1.9.3", ggml.installed_version(ggml.WHISPER))
|
||||||
|
self.assertFalse(ggml.vulkan_missing(ggml.WHISPER))
|
||||||
|
|
||||||
def test_an_explicit_whisper_version_still_comes_from_upstream(self):
|
def test_an_explicit_whisper_version_still_comes_from_upstream(self):
|
||||||
self.patch_attr(ggml, "_arch", lambda: "x64")
|
self.patch_attr(ggml, "_arch", lambda: "x64")
|
||||||
@@ -339,6 +340,24 @@ class InstallProgram(Local):
|
|||||||
"whisper-bin-ubuntu-x64.tar.gz"))
|
"whisper-bin-ubuntu-x64.tar.gz"))
|
||||||
self.assertTrue(os.path.isfile(path))
|
self.assertTrue(os.path.isfile(path))
|
||||||
|
|
||||||
|
def test_a_fallback_to_the_processor_build_is_there_to_be_shown(self):
|
||||||
|
"""Until the Vulkan package is published every download lands the
|
||||||
|
processor build, and a graphics card sitting idle looks exactly like
|
||||||
|
one being used. The window asks this and says so."""
|
||||||
|
self.patch_attr(ggml, "_arch", lambda: "x64")
|
||||||
|
self.patch_attr(ggml, "_has_vulkan", lambda: True)
|
||||||
|
managed = self.release("Dikte-1.1.0-x86_64.AppImage")
|
||||||
|
managed["tag_name"] = "whisper.cpp-v1.9.3"
|
||||||
|
upstream = self.release("whisper-bin-ubuntu-x64.tar.gz")
|
||||||
|
with fake_urlopen(managed, upstream, body(self.archive)):
|
||||||
|
ggml.install_program(ggml.WHISPER)
|
||||||
|
self.assertTrue(ggml.vulkan_missing(ggml.WHISPER))
|
||||||
|
|
||||||
|
def test_a_machine_with_no_vulkan_is_not_told_it_is_missing_one(self):
|
||||||
|
# Nothing was on offer to fall back from, so there is nothing to say.
|
||||||
|
self.install("whisper-bin-ubuntu-x64.tar.gz")
|
||||||
|
self.assertFalse(ggml.vulkan_missing(ggml.WHISPER))
|
||||||
|
|
||||||
def test_a_release_with_nothing_for_this_machine_says_so(self):
|
def test_a_release_with_nothing_for_this_machine_says_so(self):
|
||||||
self.patch_attr(ggml, "_arch", lambda: "x64")
|
self.patch_attr(ggml, "_arch", lambda: "x64")
|
||||||
with fake_urlopen(self.release("whisper-bin-Win32.zip")):
|
with fake_urlopen(self.release("whisper-bin-Win32.zip")):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ save, so a setting added to one half and not the other is silently reset the
|
|||||||
next time anybody presses Save. That is the failure this catches.
|
next time anybody presses Save. That is the failure this catches.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
@@ -1214,6 +1215,34 @@ class LocalModels(DikteTest):
|
|||||||
for row in range(box.repo.count()))
|
for row in range(box.repo.count()))
|
||||||
self.assertGreaterEqual(view.minimumWidth(), widest)
|
self.assertGreaterEqual(view.minimumWidth(), widest)
|
||||||
|
|
||||||
|
def test_a_processor_build_where_the_vulkan_one_belongs_says_so(self):
|
||||||
|
# The Vulkan whisper-server is published by hand, and until it is
|
||||||
|
# there the download lands upstream's processor build. Said nowhere,
|
||||||
|
# an idle graphics card looks exactly like one that is being used.
|
||||||
|
binary = self.path("bin/whisper/v1.9.3/whisper-server")
|
||||||
|
binary.parent.mkdir(parents=True)
|
||||||
|
binary.write_text("")
|
||||||
|
binary.chmod(0o755)
|
||||||
|
self.path("bin/whisper/installed.json").write_text(json.dumps(
|
||||||
|
{"tag": "v1.9.3", "binary": str(binary), "backend": "processor"}))
|
||||||
|
# A whisper-server on this machine's PATH would win over the download.
|
||||||
|
self.patch_attr(ggml.shutil, "which", lambda name: None)
|
||||||
|
label = self.window(cfg.Config()).local_whisper.program_label.text()
|
||||||
|
self.assertIn("v1.9.3", label)
|
||||||
|
self.assertIn("Vulkan", label)
|
||||||
|
|
||||||
|
def test_an_ordinary_install_is_reported_without_a_word_about_vulkan(self):
|
||||||
|
binary = self.path("bin/whisper/v1.9.3/whisper-server")
|
||||||
|
binary.parent.mkdir(parents=True)
|
||||||
|
binary.write_text("")
|
||||||
|
binary.chmod(0o755)
|
||||||
|
self.path("bin/whisper/installed.json").write_text(json.dumps(
|
||||||
|
{"tag": "v1.9.3", "binary": str(binary)}))
|
||||||
|
self.patch_attr(ggml.shutil, "which", lambda name: None)
|
||||||
|
label = self.window(cfg.Config()).local_whisper.program_label.text()
|
||||||
|
self.assertIn("v1.9.3", label)
|
||||||
|
self.assertNotIn("Vulkan", label)
|
||||||
|
|
||||||
def test_only_the_chosen_transcriber_is_on_screen(self):
|
def test_only_the_chosen_transcriber_is_on_screen(self):
|
||||||
window = self.window(self.config(transcribe_provider="openai"))
|
window = self.window(self.config(transcribe_provider="openai"))
|
||||||
self.assertTrue(window.stt_form.isRowVisible(window.transcribe_model_row))
|
self.assertTrue(window.stt_form.isRowVisible(window.transcribe_model_row))
|
||||||
|
|||||||
Reference in New Issue
Block a user