diff options
| -rw-r--r-- | llamachat/ui.py | 40 |
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() |
