diff --git a/gpt4all-chat/bravesearch.cpp b/gpt4all-chat/bravesearch.cpp index 0a0ef8f9..e5505437 100644 --- a/gpt4all-chat/bravesearch.cpp +++ b/gpt4all-chat/bravesearch.cpp @@ -17,11 +17,18 @@ using namespace Qt::Literals::StringLiterals; +BraveSearch::BraveSearch() + : Tool(), m_error(ToolEnums::Error::NoError) +{ + connect(MySettings::globalInstance(), &MySettings::webSearchUsageModeChanged, + this, &Tool::usageModeChanged); +} + QString BraveSearch::run(const QJsonObject ¶meters, qint64 timeout) { const QString apiKey = MySettings::globalInstance()->braveSearchAPIKey(); const QString query = parameters["query"].toString(); - const int count = 2; // FIXME: This should be a setting + const int count = MySettings::globalInstance()->webSearchRetrievalSize(); QThread workerThread; BraveAPIWorker worker; worker.moveToThread(&workerThread); @@ -83,8 +90,7 @@ QJsonObject BraveSearch::exampleParams() const ToolEnums::UsageMode BraveSearch::usageMode() const { - // FIXME: This needs to be a setting - return ToolEnums::UsageMode::Enabled; + return MySettings::globalInstance()->webSearchUsageMode(); } void BraveAPIWorker::request(const QString &apiKey, const QString &query, int count) diff --git a/gpt4all-chat/bravesearch.h b/gpt4all-chat/bravesearch.h index ef7c14e1..78a73b60 100644 --- a/gpt4all-chat/bravesearch.h +++ b/gpt4all-chat/bravesearch.h @@ -41,7 +41,7 @@ private: class BraveSearch : public Tool { Q_OBJECT public: - BraveSearch() : Tool(), m_error(ToolEnums::Error::NoError) {} + BraveSearch(); virtual ~BraveSearch() {} QString run(const QJsonObject ¶meters, qint64 timeout = 2000) override; diff --git a/gpt4all-chat/mysettings.cpp b/gpt4all-chat/mysettings.cpp index 0d642979..999efd6b 100644 --- a/gpt4all-chat/mysettings.cpp +++ b/gpt4all-chat/mysettings.cpp @@ -26,6 +26,7 @@ #include using namespace Qt::Literals::StringLiterals; +using namespace ToolEnums; // used only for settings serialization, do not translate static const QStringList suggestionModeNames { "LocalDocsOnly", "On", "Off" }; @@ -47,22 +48,26 @@ static const QString languageAndLocale = "System Locale"; } // namespace defaults static const QVariantMap basicDefaults { - { "chatTheme", QVariant::fromValue(ChatTheme::Light) }, - { "fontSize", QVariant::fromValue(FontSize::Small) }, - { "lastVersionStarted", "" }, - { "networkPort", 4891, }, - { "saveChatsContext", false }, - { "serverChat", false }, - { "userDefaultModel", "Application default" }, - { "suggestionMode", QVariant::fromValue(SuggestionMode::SourceExcerptsOnly) }, - { "localdocs/chunkSize", 512 }, - { "localdocs/retrievalSize", 3 }, - { "localdocs/showReferences", true }, - { "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } }, - { "localdocs/useRemoteEmbed", false }, - { "localdocs/nomicAPIKey", "" }, - { "localdocs/embedDevice", "Auto" }, - { "network/attribution", "" }, + { "chatTheme", QVariant::fromValue(ChatTheme::Light) }, + { "fontSize", QVariant::fromValue(FontSize::Small) }, + { "lastVersionStarted", "" }, + { "networkPort", 4891, }, + { "saveChatsContext", false }, + { "serverChat", false }, + { "userDefaultModel", "Application default" }, + { "suggestionMode", QVariant::fromValue(SuggestionMode::SourceExcerptsOnly) }, + { "localdocs/chunkSize", 512 }, + { "localdocs/retrievalSize", 3 }, + { "localdocs/showReferences", true }, + { "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } }, + { "localdocs/useRemoteEmbed", false }, + { "localdocs/nomicAPIKey", "" }, + { "localdocs/embedDevice", "Auto" }, + { "network/attribution", "" }, + { "websearch/usageMode", QVariant::fromValue(UsageMode::Disabled) }, + { "websearch/retrievalSize", 2 }, + { "websearch/askBeforeRunning", false }, + { "bravesearch/APIKey", "" }, }; static QString defaultLocalModelsPath() @@ -230,6 +235,14 @@ void MySettings::restoreLocalDocsDefaults() setLocalDocsEmbedDevice(basicDefaults.value("localdocs/embedDevice").toString()); } +void MySettings::restoreWebSearchDefaults() +{ + setWebSearchUsageMode(basicDefaults.value("websearch/usageMode").value()); + setWebSearchRetrievalSize(basicDefaults.value("websearch/retrievalSize").toInt()); + setWebSearchAskBeforeRunning(basicDefaults.value("websearch/askBeforeRunning").toBool()); + setBraveSearchAPIKey(basicDefaults.value("bravesearch/APIKey").toString()); +} + void MySettings::eraseModel(const ModelInfo &info) { m_settings.remove(u"model-%1"_s.arg(info.id())); @@ -467,6 +480,9 @@ QString MySettings::localDocsNomicAPIKey() const { return getBasicSetting QString MySettings::localDocsEmbedDevice() const { return getBasicSetting("localdocs/embedDevice" ).toString(); } QString MySettings::networkAttribution() const { return getBasicSetting("network/attribution" ).toString(); } QString MySettings::braveSearchAPIKey() const { return getBasicSetting("bravesearch/APIKey" ).toString(); } +int MySettings::webSearchRetrievalSize() const { return getBasicSetting("websearch/retrievalSize").toInt(); } +bool MySettings::webSearchAskBeforeRunning() const { return getBasicSetting("websearch/askBeforeRunning").toBool(); } +UsageMode MySettings::webSearchUsageMode() const { return getBasicSetting("websearch/usageMode").value(); } ChatTheme MySettings::chatTheme() const { return ChatTheme (getEnumSetting("chatTheme", chatThemeNames)); } FontSize MySettings::fontSize() const { return FontSize (getEnumSetting("fontSize", fontSizeNames)); } @@ -486,6 +502,9 @@ void MySettings::setLocalDocsNomicAPIKey(const QString &value) { setBasic void MySettings::setLocalDocsEmbedDevice(const QString &value) { setBasicSetting("localdocs/embedDevice", value, "localDocsEmbedDevice"); } void MySettings::setNetworkAttribution(const QString &value) { setBasicSetting("network/attribution", value, "networkAttribution"); } void MySettings::setBraveSearchAPIKey(const QString &value) { setBasicSetting("bravesearch/APIKey", value, "braveSearchAPIKey"); } +void MySettings::setWebSearchUsageMode(ToolEnums::UsageMode value) { setBasicSetting("websearch/usageMode", int(value), "webSearchUsageMode"); } +void MySettings::setWebSearchRetrievalSize(int value) { setBasicSetting("websearch/retrievalSize", value, "webSearchRetrievalSize"); } +void MySettings::setWebSearchAskBeforeRunning(bool value) { setBasicSetting("websearch/askBeforeRunning", value, "webSearchAskBeforeRunning"); } void MySettings::setChatTheme(ChatTheme value) { setBasicSetting("chatTheme", chatThemeNames .value(int(value))); } void MySettings::setFontSize(FontSize value) { setBasicSetting("fontSize", fontSizeNames .value(int(value))); } @@ -701,7 +720,7 @@ QString MySettings::systemPromptInternal(const QString &proposedTemplate, QStrin int c = ToolModel::globalInstance()->count(); for (int i = 0; i < c; ++i) { Tool *t = ToolModel::globalInstance()->get(i); - if (t->usageMode() == ToolEnums::UsageMode::Enabled) + if (t->usageMode() == UsageMode::Enabled) toolList.push_back(t->jinjaValue()); } params.insert({"toolList", toolList}); diff --git a/gpt4all-chat/mysettings.h b/gpt4all-chat/mysettings.h index 6e1e8056..1518412b 100644 --- a/gpt4all-chat/mysettings.h +++ b/gpt4all-chat/mysettings.h @@ -2,6 +2,7 @@ #define MYSETTINGS_H #include "modellist.h" // IWYU pragma: keep +#include "tool.h" #include #include @@ -72,6 +73,9 @@ class MySettings : public QObject Q_PROPERTY(int networkPort READ networkPort WRITE setNetworkPort NOTIFY networkPortChanged) Q_PROPERTY(SuggestionMode suggestionMode READ suggestionMode WRITE setSuggestionMode NOTIFY suggestionModeChanged) Q_PROPERTY(QStringList uiLanguages MEMBER m_uiLanguages CONSTANT) + Q_PROPERTY(ToolEnums::UsageMode webSearchUsageMode READ webSearchUsageMode WRITE setWebSearchUsageMode NOTIFY webSearchUsageModeChanged) + Q_PROPERTY(int webSearchRetrievalSize READ webSearchRetrievalSize WRITE setWebSearchRetrievalSize NOTIFY webSearchRetrievalSizeChanged) + Q_PROPERTY(bool webSearchAskBeforeRunning READ webSearchAskBeforeRunning WRITE setWebSearchAskBeforeRunning NOTIFY webSearchAskBeforeRunningChanged) Q_PROPERTY(QString braveSearchAPIKey READ braveSearchAPIKey WRITE setBraveSearchAPIKey NOTIFY braveSearchAPIKeyChanged) public: @@ -81,6 +85,7 @@ public: Q_INVOKABLE void restoreModelDefaults(const ModelInfo &info); Q_INVOKABLE void restoreApplicationDefaults(); Q_INVOKABLE void restoreLocalDocsDefaults(); + Q_INVOKABLE void restoreWebSearchDefaults(); // Model/Character settings void eraseModel(const ModelInfo &info); @@ -188,7 +193,13 @@ public: QString localDocsEmbedDevice() const; void setLocalDocsEmbedDevice(const QString &value); - // Tool settings + // Web search settings + ToolEnums::UsageMode webSearchUsageMode() const; + void setWebSearchUsageMode(ToolEnums::UsageMode value); + int webSearchRetrievalSize() const; + void setWebSearchRetrievalSize(int value); + bool webSearchAskBeforeRunning() const; + void setWebSearchAskBeforeRunning(bool value); QString braveSearchAPIKey() const; void setBraveSearchAPIKey(const QString &value); @@ -251,6 +262,9 @@ Q_SIGNALS: void deviceChanged(); void suggestionModeChanged(); void languageAndLocaleChanged(); + void webSearchUsageModeChanged(); + void webSearchRetrievalSizeChanged() const; + void webSearchAskBeforeRunningChanged() const; void braveSearchAPIKeyChanged(); private: @@ -274,7 +288,6 @@ private: bool signal = false); QString filePathForLocale(const QLocale &locale); QString systemPromptInternal(const QString &proposedTemplate, QString &error); - }; #endif // MYSETTINGS_H diff --git a/gpt4all-chat/qml/ApplicationSettings.qml b/gpt4all-chat/qml/ApplicationSettings.qml index 5fe4bea5..57290606 100644 --- a/gpt4all-chat/qml/ApplicationSettings.qml +++ b/gpt4all-chat/qml/ApplicationSettings.qml @@ -354,13 +354,22 @@ MySettingsTab { ListElement { name: qsTr("Whenever possible") } ListElement { name: qsTr("Never") } } + function updateModel() { + suggestionModeBox.currentIndex = MySettings.suggestionMode; + } Accessible.name: suggestionModeLabel.text Accessible.description: suggestionModeLabel.helpText onActivated: { MySettings.suggestionMode = suggestionModeBox.currentIndex; } Component.onCompleted: { - suggestionModeBox.currentIndex = MySettings.suggestionMode; + suggestionModeBox.updateModel(); + } + Connections { + target: MySettings + function onSuggestionModeChanged() { + suggestionModeBox.updateModel(); + } } } MySettingsLabel { diff --git a/gpt4all-chat/qml/LocalDocsSettings.qml b/gpt4all-chat/qml/LocalDocsSettings.qml index 47f44090..c3c98e7c 100644 --- a/gpt4all-chat/qml/LocalDocsSettings.qml +++ b/gpt4all-chat/qml/LocalDocsSettings.qml @@ -255,13 +255,14 @@ MySettingsTab { MySettingsLabel { id: chunkLabel Layout.fillWidth: true - text: qsTr("Document snippet size (characters)") - helpText: qsTr("Number of characters per document snippet. Larger numbers increase likelihood of factual responses, but also result in slower generation.") + text: qsTr("Document excerpt size (characters)") + helpText: qsTr("Number of characters per document excerpt. Larger numbers increase likelihood of factual responses, but also result in slower generation.") } MyTextField { id: chunkSizeTextField text: MySettings.localDocsChunkSize + font.pixelSize: theme.fontSizeLarge validator: IntValidator { bottom: 1 } @@ -281,13 +282,14 @@ MySettingsTab { Layout.topMargin: 15 MySettingsLabel { id: contextItemsPerPrompt - text: qsTr("Max document snippets per prompt") - helpText: qsTr("Max best N matches of retrieved document snippets to add to the context for prompt. Larger numbers increase likelihood of factual responses, but also result in slower generation.") + text: qsTr("Max source excerpts per prompt") + helpText: qsTr("Max best N matches of retrieved source excerpts to add to the context for prompt. Larger numbers increase likelihood of factual responses, but also result in slower generation.") } MyTextField { text: MySettings.localDocsRetrievalSize + font.pixelSize: theme.fontSizeLarge validator: IntValidator { bottom: 1 } diff --git a/gpt4all-chat/qml/WebSearchSettings.qml b/gpt4all-chat/qml/WebSearchSettings.qml index 222f9e30..901883cd 100644 --- a/gpt4all-chat/qml/WebSearchSettings.qml +++ b/gpt4all-chat/qml/WebSearchSettings.qml @@ -11,7 +11,7 @@ import network MySettingsTab { onRestoreDefaultsClicked: { - MySettings.restoreLocalDocsDefaults(); + MySettings.restoreWebSearchDefaults(); } showRestoreDefaultsButton: true @@ -52,14 +52,24 @@ MySettingsTab { model: ListModel { ListElement { name: qsTr("Never") } ListElement { name: qsTr("Model decides") } - ListElement { name: qsTr("Ask for confirmation before executing") } - ListElement { name: qsTr("Force usage for every response when possible") } + ListElement { name: qsTr("Force usage for every response where possible") } + } + function updateModel() { + usageModeBox.currentIndex = MySettings.webSearchUsageMode; } Accessible.name: usageModeLabel.text Accessible.description: usageModeLabel.helpText onActivated: { + MySettings.webSearchUsageMode = usageModeBox.currentIndex; } Component.onCompleted: { + usageModeBox.updateModel(); + } + Connections { + target: MySettings + function onWebSearchUsageModeChanged() { + usageModeBox.updateModel(); + } } } } @@ -74,6 +84,7 @@ MySettingsTab { MyTextField { id: apiKeyField + enabled: usageModeBox.currentIndex !== 0 text: MySettings.braveSearchAPIKey color: theme.textColor font.pixelSize: theme.fontSizeLarge @@ -89,6 +100,46 @@ MySettingsTab { } } + RowLayout { + MySettingsLabel { + id: contextItemsPerPrompt + text: qsTr("Max source excerpts per prompt") + helpText: qsTr("Max best N matches of retrieved source excerpts to add to the context for prompt. Larger numbers increase likelihood of factual responses, but also result in slower generation.") + } + + MyTextField { + text: MySettings.webSearchRetrievalSize + font.pixelSize: theme.fontSizeLarge + validator: IntValidator { + bottom: 1 + } + onEditingFinished: { + var val = parseInt(text) + if (!isNaN(val)) { + MySettings.webSearchRetrievalSize = val + focus = false + } else { + text = MySettings.webSearchRetrievalSize + } + } + } + } + + RowLayout { + MySettingsLabel { + id: askBeforeRunningLabel + text: qsTr("Ask before running") + helpText: qsTr("The user is queried whether they want the tool to run in every instance") + } + MyCheckBox { + id: askBeforeRunningBox + checked: MySettings.webSearchAskBeforeRunning + onClicked: { + MySettings.webSearchAskBeforeRunning = !MySettings.webSearchAskBeforeRunning + } + } + } + Rectangle { Layout.topMargin: 15 Layout.fillWidth: true diff --git a/gpt4all-chat/tool.h b/gpt4all-chat/tool.h index 88a3dbc9..23c4c152 100644 --- a/gpt4all-chat/tool.h +++ b/gpt4all-chat/tool.h @@ -17,9 +17,9 @@ namespace ToolEnums { Q_ENUM_NS(Error) enum class UsageMode { - Disabled, // Completely disabled - Enabled, // Enabled and the model decides whether to run - ForceUsage, // Attempt to force usage of the tool rather than let the LLM decide. NOTE: Not always possible. + Disabled = 0, // Completely disabled + Enabled = 1, // Enabled and the model decides whether to run + ForceUsage = 2, // Attempt to force usage of the tool rather than let the LLM decide. NOTE: Not always possible. }; Q_ENUM_NS(UsageMode)