diff --git a/src/calibre/ai/github/config.py b/src/calibre/ai/github/config.py index 5f5ca50bc0..430cf17e69 100644 --- a/src/calibre/ai/github/config.py +++ b/src/calibre/ai/github/config.py @@ -4,11 +4,11 @@ from collections.abc import Sequence from functools import partial -from qt.core import QComboBox, QFormLayout, QHBoxLayout, QLabel, QLineEdit, QWidget +from qt.core import QFormLayout, QHBoxLayout, QLabel, QLineEdit, QWidget from calibre.ai.github import GitHubAI from calibre.ai.prefs import decode_secret, encode_secret, pref_for_provider, set_prefs_for_provider -from calibre.ai.utils import configure, plugin_for_name +from calibre.ai.utils import configure, model_choice_strategy_config_widget, plugin_for_name from calibre.gui2 import error_dialog pref = partial(pref_for_provider, GitHubAI.name) @@ -39,17 +39,8 @@ class ConfigWidget(QWidget): l.addRow(_('Access &token:'), a) if key := pref('api_key'): a.setText(decode_secret(key)) - self.model_strategy = ms = QComboBox(self) + self.model_strategy = ms = model_choice_strategy_config_widget(pref('model_choice_strategy', 'medium'), self) l.addRow(_('Model &choice strategy:'), ms) - ms.addItem(_('Cheap and fastest'), 'low') - ms.addItem(_('Medium'), 'medium') - ms.addItem(_('High quality, expensive and slower'), 'high') - if strat := pref('model_choice_strategy', 'medium'): - ms.setCurrentIndex(max(0, ms.findData(strat))) - ms.setToolTip('
' + _( - 'The model choice strategy controls how a model to query is chosen. Cheaper and faster models give lower' - ' quality results.' - )) self.text_model_edit = lm = QLineEdit(self) lm.setClearButtonEnabled(True) lm.setToolTip(_( diff --git a/src/calibre/ai/google/config.py b/src/calibre/ai/google/config.py index c2d91a5bf5..df6f6d7076 100644 --- a/src/calibre/ai/google/config.py +++ b/src/calibre/ai/google/config.py @@ -4,11 +4,11 @@ from functools import partial -from qt.core import QCheckBox, QComboBox, QFormLayout, QLabel, QLineEdit, QWidget +from qt.core import QCheckBox, QFormLayout, QLabel, QLineEdit, QWidget from calibre.ai.google import GoogleAI from calibre.ai.prefs import decode_secret, encode_secret, pref_for_provider, set_prefs_for_provider -from calibre.ai.utils import configure +from calibre.ai.utils import configure, model_choice_strategy_config_widget, reasoning_strategy_config_widget from calibre.gui2 import error_dialog pref = partial(pref_for_provider, GoogleAI.name) @@ -39,32 +39,13 @@ class ConfigWidget(QWidget): l.addRow(_('API &key:'), a) if key := pref('api_key'): a.setText(decode_secret(key)) - self.model_strategy = ms = QComboBox(self) + self.model_strategy = ms = model_choice_strategy_config_widget(pref('model_choice_strategy', 'medium'), self) l.addRow(_('Model &choice strategy:'), ms) - ms.addItem(_('Cheap and fastest'), 'low') - ms.addItem(_('Medium'), 'medium') - ms.addItem(_('High quality, expensive and slower'), 'high') - if strat := pref('model_choice_strategy', 'medium'): - ms.setCurrentIndex(max(0, ms.findData(strat))) - ms.setToolTip('
' + _( - 'The model choice strategy controls how a model to query is chosen. Cheaper and faster models give lower' - ' quality results.' - )) self._allow_web_searches = aws = QCheckBox(_('Allow &searching the web when generating responses')) aws.setChecked(pref('allow_web_searches', True)) aws.setToolTip(_('If enabled, Gemini will use Google Web searches to return accurate and up-to-date information for queries, where possible')) - self.reasoning_strat = rs = QComboBox(self) + self.reasoning_strat = rs = reasoning_strategy_config_widget(pref('reasoning_strategy'), self) l.addRow(_('&Reasoning effort:'), rs) - rs.addItem(_('Automatic'), 'auto') - rs.addItem(_('Medium'), 'medium') - rs.addItem(_('High'), 'high') - rs.addItem(_('Low'), 'low') - rs.addItem(_('No reasoning'), 'none') - if strat := pref('reasoning_strategy', 'auto'): - rs.setCurrentIndex(max(0, rs.findData(strat))) - rs.setToolTip('
'+_( - 'Select how much "reasoning" AI does when answering queries. More reasoning leads to' - ' better quality responses at the cost of increased cost and reduced speed.')) @property def api_key(self) -> str: @@ -76,7 +57,7 @@ class ConfigWidget(QWidget): @property def reasoning_strategy(self) -> str: - return self.model_strategy.currentData() + return self.reasoning_strat.currentData() @property def allow_web_searches(self) -> bool: diff --git a/src/calibre/ai/open_router/config.py b/src/calibre/ai/open_router/config.py index d6619e84b0..80d87b2b84 100644 --- a/src/calibre/ai/open_router/config.py +++ b/src/calibre/ai/open_router/config.py @@ -36,7 +36,7 @@ from qt.core import ( from calibre.ai import AICapabilities from calibre.ai.open_router import OpenRouterAI from calibre.ai.prefs import decode_secret, encode_secret, pref_for_provider, set_prefs_for_provider -from calibre.ai.utils import configure +from calibre.ai.utils import configure, reasoning_strategy_config_widget from calibre.customize.ui import available_ai_provider_plugins from calibre.ebooks.txt.processor import create_markdown_object from calibre.gui2 import error_dialog, gprefs, safe_open_url @@ -408,17 +408,8 @@ class ConfigWidget(QWidget): " results, regardless of cost. Uses OpenRouter's own automatic model selection." )) - self.reasoning_strat = rs = QComboBox(self) + self.reasoning_strat = rs = reasoning_strategy_config_widget(pref('reasoning_strategy', 'auto'), self) l.addRow(_('&Reasoning effort:'), rs) - rs.addItem(_('Medium'), 'medium') - rs.addItem(_('High'), 'high') - rs.addItem(_('Low'), 'low') - rs.addItem(_('No reasoning'), 'none') - if strat := pref('reasoning_strategy'): - rs.setCurrentIndex(max(0, rs.findData(strat))) - rs.setToolTip('
'+_( - 'Select how much "reasoning" AI does when answering queries. More reasoning leads to' - ' better quality responses at the cost of increased cost and reduced speed.')) self.data_retention = dr = QCheckBox(_('Allow usage of providers that &store prompts'), self) dr.setToolTip(textwrap.fill(_( diff --git a/src/calibre/ai/utils.py b/src/calibre/ai/utils.py index f0cf485a7a..c01a178cee 100644 --- a/src/calibre/ai/utils.py +++ b/src/calibre/ai/utils.py @@ -319,6 +319,35 @@ def configure(plugin_name: str, parent: Any = None) -> None: plugin.save_settings(cw) +def reasoning_strategy_config_widget(current_val: str = 'auto', parent: Any = None) -> Any: + from qt.core import QComboBox + rs = QComboBox(parent) + rs.addItem(_('Automatic'), 'auto') + rs.addItem(_('Medium'), 'medium') + rs.addItem(_('High'), 'high') + rs.addItem(_('Low'), 'low') + rs.addItem(_('No reasoning'), 'none') + rs.setCurrentIndex(max(0, rs.findData(current_val))) + rs.setToolTip('
'+_( + 'Select how much "reasoning" AI does when answering queries. More reasoning leads to' + ' better quality responses at the cost of increased cost and reduced speed.')) + return rs + + +def model_choice_strategy_config_widget(current_val: str = 'medium', parent: Any = None) -> Any: + from qt.core import QComboBox + ms = QComboBox(parent) + ms.addItem(_('Cheap and fastest'), 'low') + ms.addItem(_('Medium'), 'medium') + ms.addItem(_('High quality, expensive and slower'), 'high') + ms.setCurrentIndex(max(0, ms.findData(current_val))) + ms.setToolTip('
' + _( + 'The model choice strategy controls how a model to query is chosen. Cheaper and faster models give lower' + ' quality results.' + )) + return ms + + def find_tests() -> None: import unittest class TestAIUtils(unittest.TestCase):