Move Whisper device/compute into Engines→STT; add LLM Type (local/cloud)
- Local-Whisper Device + Compute type now live under the STT engine section
("Local engine — device & precision"), removed from the General tab. The
local engine's Model field shows the effective whisper size.
- LLM engines gain a Type field (local | cloud), mirroring STT, stored in config.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
78350bdb99
commit
f1ee4bd4c5
@ -199,6 +199,7 @@ def load(path: Path = CONFIG_PATH) -> Config:
|
|||||||
model=e.get("model", "gpt-4o-mini"),
|
model=e.get("model", "gpt-4o-mini"),
|
||||||
api_key_env=e.get("api_key_env", ""),
|
api_key_env=e.get("api_key_env", ""),
|
||||||
temperature=float(e.get("temperature", cfg.temperature)),
|
temperature=float(e.get("temperature", cfg.temperature)),
|
||||||
|
type=e.get("type", "cloud"),
|
||||||
)
|
)
|
||||||
for e in data.get("llm_engine", [])
|
for e in data.get("llm_engine", [])
|
||||||
] or [LLMEngine("Default", cfg.base_url, cfg.rewrite_model, cfg.api_key_env, cfg.temperature)]
|
] or [LLMEngine("Default", cfg.base_url, cfg.rewrite_model, cfg.api_key_env, cfg.temperature)]
|
||||||
@ -266,7 +267,7 @@ def save(cfg: Config, path: Path = CONFIG_PATH) -> None:
|
|||||||
],
|
],
|
||||||
"llm": {"active": cfg.llm_active},
|
"llm": {"active": cfg.llm_active},
|
||||||
"llm_engine": [
|
"llm_engine": [
|
||||||
{"name": e.name, "url": e.url, "model": e.model,
|
{"name": e.name, "type": e.type, "url": e.url, "model": e.model,
|
||||||
"api_key_env": e.api_key_env, "temperature": e.temperature}
|
"api_key_env": e.api_key_env, "temperature": e.temperature}
|
||||||
for e in cfg.llm_engines
|
for e in cfg.llm_engines
|
||||||
],
|
],
|
||||||
@ -390,6 +391,7 @@ active = "Default"
|
|||||||
|
|
||||||
[[llm_engine]]
|
[[llm_engine]]
|
||||||
name = "Default"
|
name = "Default"
|
||||||
|
type = "cloud" # "local" | "cloud"
|
||||||
url = "https://api.openai.com/v1"
|
url = "https://api.openai.com/v1"
|
||||||
model = "gpt-4o-mini"
|
model = "gpt-4o-mini"
|
||||||
api_key_env = "OPENAI_API_KEY"
|
api_key_env = "OPENAI_API_KEY"
|
||||||
@ -397,6 +399,7 @@ temperature = 0.3
|
|||||||
|
|
||||||
# [[llm_engine]]
|
# [[llm_engine]]
|
||||||
# name = "Local llama-swap"
|
# name = "Local llama-swap"
|
||||||
|
# type = "local"
|
||||||
# url = "http://localhost:28080/v1"
|
# url = "http://localhost:28080/v1"
|
||||||
# model = "Qwen3.5-4B"
|
# model = "Qwen3.5-4B"
|
||||||
# api_key_env = ""
|
# api_key_env = ""
|
||||||
|
|||||||
@ -344,6 +344,12 @@ class SettingsDialog:
|
|||||||
self.stt_url.connect("changed", lambda _e: self._schedule_models("stt"))
|
self.stt_url.connect("changed", lambda _e: self._schedule_models("stt"))
|
||||||
self.stt_key.connect("changed", lambda _e: self._schedule_models("stt"))
|
self.stt_key.connect("changed", lambda _e: self._schedule_models("stt"))
|
||||||
self.stt_type.connect("changed", self._stt_type_changed)
|
self.stt_type.connect("changed", self._stt_type_changed)
|
||||||
|
|
||||||
|
sep = Gtk.Separator(); sep.set_margin_top(4); form.pack_start(sep, False, False, 4)
|
||||||
|
form.pack_start(Gtk.Label(label="Local engine (faster-whisper) — device & precision", xalign=0.0), False, False, 0)
|
||||||
|
self.stt_device = _labeled(form, "Device", _combo(["auto", "cpu", "cuda"], self.cfg.device))
|
||||||
|
self.stt_compute = _labeled(form, "Compute type", _combo(["auto", "int8", "float16", "int8_float16"], self.cfg.compute_type))
|
||||||
|
|
||||||
self.stt_result = Gtk.Label(xalign=0.0); self.stt_result.set_line_wrap(True)
|
self.stt_result = Gtk.Label(xalign=0.0); self.stt_result.set_line_wrap(True)
|
||||||
box.pack_start(self.stt_result, False, False, 2)
|
box.pack_start(self.stt_result, False, False, 2)
|
||||||
self._stt_load(self.stt_combo.get_active())
|
self._stt_load(self.stt_combo.get_active())
|
||||||
@ -368,6 +374,7 @@ class SettingsDialog:
|
|||||||
box.pack_start(bar, False, False, 2)
|
box.pack_start(bar, False, False, 2)
|
||||||
|
|
||||||
form = Gtk.Box(orientation=Gtk.Orientation.VERTICAL); box.pack_start(form, False, False, 2)
|
form = Gtk.Box(orientation=Gtk.Orientation.VERTICAL); box.pack_start(form, False, False, 2)
|
||||||
|
self.llm_type = _labeled(form, "Type", _combo(["local", "cloud"]))
|
||||||
self.llm_url = _url_field(form, "Base URL", "http://localhost:28080/v1 · https://api.openai.com/v1",
|
self.llm_url = _url_field(form, "Base URL", "http://localhost:28080/v1 · https://api.openai.com/v1",
|
||||||
lambda: self._populate_models(self.llm_model, self.llm_url.get_text().strip(), self.llm_key.get_text().strip()))
|
lambda: self._populate_models(self.llm_model, self.llm_url.get_text().strip(), self.llm_key.get_text().strip()))
|
||||||
self.llm_model = _labeled(form, "Model", _model_combo("pick after entering URL"))
|
self.llm_model = _labeled(form, "Model", _model_combo("pick after entering URL"))
|
||||||
@ -386,7 +393,7 @@ class SettingsDialog:
|
|||||||
self.stt_type.set_active(["local", "openai"].index(e.type) if e.type in ("local", "openai") else 0)
|
self.stt_type.set_active(["local", "openai"].index(e.type) if e.type in ("local", "openai") else 0)
|
||||||
self.stt_url.set_text(e.url); self.stt_key.set_text(e.api_key_env)
|
self.stt_url.set_text(e.url); self.stt_key.set_text(e.api_key_env)
|
||||||
if e.type == "local":
|
if e.type == "local":
|
||||||
_fill_combo(self.stt_model, ["tiny", "base", "small", "medium", "large-v3"], e.model)
|
_fill_combo(self.stt_model, ["tiny", "base", "small", "medium", "large-v3"], e.model or self.cfg.model)
|
||||||
else:
|
else:
|
||||||
_fill_combo(self.stt_model, [], e.model)
|
_fill_combo(self.stt_model, [], e.model)
|
||||||
self._populate_models(self.stt_model, e.url, e.api_key_env)
|
self._populate_models(self.stt_model, e.url, e.api_key_env)
|
||||||
@ -450,6 +457,7 @@ class SettingsDialog:
|
|||||||
if not (0 <= idx < len(self.cfg.llm_engines)):
|
if not (0 <= idx < len(self.cfg.llm_engines)):
|
||||||
return
|
return
|
||||||
e = self.cfg.llm_engines[idx]
|
e = self.cfg.llm_engines[idx]
|
||||||
|
self.llm_type.set_active(["local", "cloud"].index(e.type) if e.type in ("local", "cloud") else 1)
|
||||||
self.llm_url.set_text(e.url)
|
self.llm_url.set_text(e.url)
|
||||||
self.llm_key.set_text(e.api_key_env); self.llm_temp.set_text(str(e.temperature))
|
self.llm_key.set_text(e.api_key_env); self.llm_temp.set_text(str(e.temperature))
|
||||||
_fill_combo(self.llm_model, [], e.model)
|
_fill_combo(self.llm_model, [], e.model)
|
||||||
@ -461,6 +469,7 @@ class SettingsDialog:
|
|||||||
if not (0 <= idx < len(self.cfg.llm_engines)):
|
if not (0 <= idx < len(self.cfg.llm_engines)):
|
||||||
return
|
return
|
||||||
e = self.cfg.llm_engines[idx]
|
e = self.cfg.llm_engines[idx]
|
||||||
|
e.type = self.llm_type.get_active_text() or "cloud"
|
||||||
e.url = self.llm_url.get_text().strip().rstrip("/")
|
e.url = self.llm_url.get_text().strip().rstrip("/")
|
||||||
e.model = _combo_text(self.llm_model)
|
e.model = _combo_text(self.llm_model)
|
||||||
e.api_key_env = self.llm_key.get_text().strip()
|
e.api_key_env = self.llm_key.get_text().strip()
|
||||||
@ -609,12 +618,6 @@ class SettingsDialog:
|
|||||||
_labeled(page, "Notifications", self.gen_notify)
|
_labeled(page, "Notifications", self.gen_notify)
|
||||||
self.gen_boot = Gtk.Switch(); self.gen_boot.set_active(autostart.is_enabled()); self.gen_boot.set_halign(Gtk.Align.START)
|
self.gen_boot = Gtk.Switch(); self.gen_boot.set_active(autostart.is_enabled()); self.gen_boot.set_halign(Gtk.Align.START)
|
||||||
_labeled(page, "Launch on login", self.gen_boot)
|
_labeled(page, "Launch on login", self.gen_boot)
|
||||||
|
|
||||||
page.pack_start(Gtk.Separator(), False, False, 8)
|
|
||||||
page.pack_start(Gtk.Label(label="Local Whisper (for the local STT engine)", xalign=0.0), False, False, 2)
|
|
||||||
self.gen_model = _labeled(page, "Model", _entry(self.cfg.model))
|
|
||||||
self.gen_device = _labeled(page, "Device", _combo(["auto", "cpu", "cuda"], self.cfg.device))
|
|
||||||
self.gen_compute = _labeled(page, "Compute type", _combo(["auto", "int8", "float16", "int8_float16"], self.cfg.compute_type))
|
|
||||||
self._start_meter()
|
self._start_meter()
|
||||||
|
|
||||||
def _selected_mic_name(self) -> str:
|
def _selected_mic_name(self) -> str:
|
||||||
@ -700,9 +703,8 @@ class SettingsDialog:
|
|||||||
c.output = self.gen_output.get_active_text() or "type"
|
c.output = self.gen_output.get_active_text() or "type"
|
||||||
c.language = self.gen_lang.get_text().strip()
|
c.language = self.gen_lang.get_text().strip()
|
||||||
c.notify = self.gen_notify.get_active()
|
c.notify = self.gen_notify.get_active()
|
||||||
c.model = self.gen_model.get_text().strip()
|
c.device = self.stt_device.get_active_text() or "auto"
|
||||||
c.device = self.gen_device.get_active_text() or "auto"
|
c.compute_type = self.stt_compute.get_active_text() or "auto"
|
||||||
c.compute_type = self.gen_compute.get_active_text() or "auto"
|
|
||||||
autostart.set_enabled(self.gen_boot.get_active())
|
autostart.set_enabled(self.gen_boot.get_active())
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
self._error(f"Check numeric fields: {exc}")
|
self._error(f"Check numeric fields: {exc}")
|
||||||
|
|||||||
@ -24,6 +24,7 @@ class LLMEngine:
|
|||||||
model: str = "gpt-4o-mini"
|
model: str = "gpt-4o-mini"
|
||||||
api_key_env: str = "OPENAI_API_KEY"
|
api_key_env: str = "OPENAI_API_KEY"
|
||||||
temperature: float = 0.3
|
temperature: float = 0.3
|
||||||
|
type: str = "cloud" # "local" | "cloud" (label/category)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_key(self) -> str | None:
|
def api_key(self) -> str | None:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user