aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llamachat/ui.py40
1 files changed, 39 insertions, 1 deletions
diff --git a/llamachat/ui.py b/llamachat/ui.py
index 94eb000..4dd758b 100644
--- a/llamachat/ui.py
+++ b/llamachat/ui.py
@@ -30,13 +30,15 @@ from PySide6.QtWidgets import (
QButtonGroup, QComboBox, QDialog, QDialogButtonBox, QFileDialog,
QHBoxLayout, QInputDialog, QLabel, QLineEdit, QListWidget,
QListWidgetItem, QMainWindow, QMenu, QMessageBox, QPlainTextEdit,
- QPushButton, QRadioButton, QSplitter, QTextBrowser, QVBoxLayout, QWidget,
+ QPushButton, QRadioButton, QSplitter, QTextBrowser, QToolButton,
+ QVBoxLayout, QWidget,
)
from . import backend, models as models_mod, prompts
from . import providers as providers_mod
from .backend import Attachment, BackendError, SearchConfig
from .config import GLOBAL_PROMPT
+from .modeldialog import ModelDialog
MODE_ONESHOT = "oneshot"
MODE_CHAT = "chat"
@@ -495,6 +497,14 @@ class ChatWindow(QMainWindow):
top.addWidget(QLabel("Model:"))
top.addWidget(self.model_box)
+ self.model_settings_button = QToolButton()
+ self.model_settings_button.setText("⚙")
+ self.model_settings_button.setToolTip(
+ "Context size, vision and prices for the selected model"
+ )
+ self.model_settings_button.clicked.connect(self.edit_model_settings)
+ top.addWidget(self.model_settings_button)
+
self.reload_button = QPushButton("⟳")
self.reload_button.setToolTip("Reload model list from the router")
self.reload_button.setFixedWidth(32)
@@ -813,7 +823,35 @@ class ChatWindow(QMainWindow):
names.append(name)
return names
+ def edit_model_settings(self, model_id: str | None = None) -> bool:
+ """Open the dialog for one model. True when values were saved."""
+ model_id = model_id or self.current_model()
+ if not model_id:
+ return False
+ current = models_mod.resolve(model_id, self.cfg.providers, self.store)
+ dialog = ModelDialog(model_id, current, self)
+ if dialog.exec() != QDialog.Accepted:
+ self.store.mark_skipped(model_id)
+ return False
+ self.store.save(model_id, dialog.info())
+ self.update_meter()
+ return True
+
+ def _maybe_offer_model_settings(self, model_id: str) -> None:
+ """Ask once, on first selection of an unconfigured cloud model.
+
+ Local models are exempt: presets.ini already answers context and
+ vision for them and they cost nothing. Cancelling records that the
+ offer was made, so a model tried once never asks again.
+ """
+ if not model_id or not models_mod.is_billable(model_id, self.cfg.providers):
+ return
+ if self.store.was_offered(model_id):
+ return
+ self.edit_model_settings(model_id)
+
def _on_model_changed(self, _text: str) -> None:
+ self._maybe_offer_model_settings(self.current_model())
if self.session_id is not None and not self.read_only:
self.history.touch_session(self.session_id, self.current_model())
self.update_meter()