From 44add994b9a076919fe71cc867b52a13213793db Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:18:57 +0200 Subject: [PATCH 01/14] Optimize string --- LLMClientInterface.cpp | 14 ++++++-------- LLMClientInterface.hpp | 6 +++--- QodeAssist.json.in | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 9bfbc62..f7d314d 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -244,14 +244,14 @@ void LLMClientInterface::handleLLMResponse(QNetworkReply *reply, const QJsonObje } void LLMClientInterface::handleCompletion(const QJsonObject &request, - const QString &accumulatedCompletion) + const QStringView &accumulatedCompletion) { auto updatedContext = prepareContext(request, accumulatedCompletion); sendLLMRequest(request, updatedContext); } ContextData LLMClientInterface::prepareContext(const QJsonObject &request, - const QString &accumulatedCompletion) + const QStringView &accumulatedCompletion) { QJsonObject params = request["params"].toObject(); QJsonObject doc = params["doc"].toObject(); @@ -264,7 +264,7 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, if (!textDocument) { logMessage("Error: Document is not available for" + filePath.toString()); - return {"", ""}; + return ContextData{}; } int cursorPosition = position["character"].toInt(); @@ -284,9 +284,7 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, ? reader.getLanguageAndFileInfo() : QString()); - QString updatedContextBefore = contextBefore + accumulatedCompletion; - - return {updatedContextBefore, contextAfter, instructions}; + return {QString("%1%2").arg(contextBefore, accumulatedCompletion), contextAfter, instructions}; } void LLMClientInterface::updateProvider() @@ -378,9 +376,9 @@ void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const Contex }); } -QString LLMClientInterface::removeStopWords(const QString &completion) +QString LLMClientInterface::removeStopWords(const QStringView &completion) { - QString filteredCompletion = completion; + QString filteredCompletion = completion.toString(); auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); QStringList stopWords = currentTemplate->stopWords(); diff --git a/LLMClientInterface.hpp b/LLMClientInterface.hpp index 04ce29a..3de65d5 100644 --- a/LLMClientInterface.hpp +++ b/LLMClientInterface.hpp @@ -45,12 +45,12 @@ public: bool isComplete); void handleCompletion(const QJsonObject &request, - const QString &accumulatedCompletion = QString()); + const QStringView &accumulatedCompletion = QString()); void sendLLMRequest(const QJsonObject &request, const ContextData &prompt); void handleLLMResponse(QNetworkReply *reply, const QJsonObject &request); ContextData prepareContext(const QJsonObject &request, - const QString &accumulatedCompletion = QString{}); + const QStringView &accumulatedCompletion = QString{}); void updateProvider(); protected: @@ -71,7 +71,7 @@ private: QString сontextBefore(TextEditor::TextEditorWidget *widget, int lineNumber, int cursorPosition); QString сontextAfter(TextEditor::TextEditorWidget *widget, int lineNumber, int cursorPosition); - QString removeStopWords(const QString &completion); + QString removeStopWords(const QStringView &completion); QUrl m_serverUrl; QNetworkAccessManager *m_manager; diff --git a/QodeAssist.json.in b/QodeAssist.json.in index 9b060ef..d8b1f23 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.0.8", + "Version" : "0.1.0", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Vendor" : "Petr Mironychev", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", From 1e0063a7bbcf96fa31769a3d3c2a167e161a3318 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:07:28 +0200 Subject: [PATCH 02/14] Add custom template prompt --- CMakeLists.txt | 1 + QodeAssistConstants.hpp | 1 + QodeAssistSettings.cpp | 28 ++++++++++ QodeAssistSettings.hpp | 1 + providers/LMStudioProvider.cpp | 3 +- providers/OllamaProvider.cpp | 2 + providers/OpenAICompatProvider.cpp | 2 + qodeassist.cpp | 2 + templates/CustomTemplate.hpp | 86 ++++++++++++++++++++++++++++++ 9 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 templates/CustomTemplate.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b5d121..42f8ec3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ add_qtc_plugin(QodeAssist templates/StarCoder2Template.hpp templates/CodeQwenChat.hpp templates/DeepSeekCoderV2.hpp + templates/CustomTemplate.hpp providers/LLMProvider.hpp providers/OllamaProvider.hpp providers/OllamaProvider.cpp providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp index 4cb9971..57fb905 100644 --- a/QodeAssistConstants.hpp +++ b/QodeAssistConstants.hpp @@ -56,6 +56,7 @@ const char MULTILINE_COMPLETION[] = "QodeAssist.multilineCompletion"; const char API_KEY[] = "QodeAssist.apiKey"; const char USE_SPECIFIC_INSTRUCTIONS[] = "QodeAssist.useSpecificInstructions"; const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext"; +const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index 188441e..f2c1aab 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -176,6 +176,29 @@ QodeAssistSettings::QodeAssistSettings() apiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); apiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); + customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); + customJsonTemplate.setLabelText("Custom JSON Template:"); + customJsonTemplate.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + customJsonTemplate.setDefaultValue(R"({ + "prompt": "{{QODE_INSTRUCTIONS}}{{QODE_PREFIX}}{{QODE_SUFFIX}}", + "options": { + "temperature": 0.7, + "top_p": 0.95, + "top_k": 40, + "num_predict": 100, + "stop": [ + "<|endoftext|>", + "", + "", + "", + "" + ], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "stream": true +})"); + const auto &manager = LLMProvidersManager::instance(); if (!manager.getProviderNames().isEmpty()) { const auto providerNames = manager.getProviderNames(); @@ -203,6 +226,8 @@ QodeAssistSettings::QodeAssistSettings() specificInstractions.setEnabled(useSpecificInstructions()); PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue()); LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue()); + customJsonTemplate.setVisible(PromptTemplateManager::instance().getCurrentTemplate()->name() + == "Custom Template"); setLoggingEnabled(enableLogging()); @@ -221,6 +246,7 @@ QodeAssistSettings::QodeAssistSettings() Form{Column{Row{selectModels, modelName}}}}, Group{title(Tr::tr("FIM Prompt Settings")), Form{Column{fimPrompts, + Row{customJsonTemplate, Space{40}}, readFullFile, maxFileThreshold, readStringsBeforeCursor, @@ -256,6 +282,7 @@ void QodeAssistSettings::setupConnections() int index = fimPrompts.volatileValue(); logMessage(QString("currentPrompt %1").arg(fimPrompts.displayForIndex(index))); PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.displayForIndex(index)); + customJsonTemplate.setVisible(fimPrompts.displayForIndex(index) == "Custom Template"); }); connect(&selectModels, &ButtonAspect::clicked, this, [this]() { showModelSelectionDialog(); }); @@ -366,6 +393,7 @@ void QodeAssistSettings::resetSettingsToDefaults() resetAspect(multiLineCompletion); resetAspect(useFilePathInContext); resetAspect(useSpecificInstructions); + resetAspect(customJsonTemplate); fimPrompts.setStringValue("StarCoder2"); llmProviders.setStringValue("Ollama"); diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index 641f9d2..5ea788c 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -97,6 +97,7 @@ public: Utils::BoolAspect useFilePathInContext{this}; Utils::BoolAspect multiLineCompletion{this}; + Utils::StringAspect customJsonTemplate{this}; Utils::StringAspect apiKey{this}; ButtonAspect resetToDefaults{this}; diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index 4aa5df3..ca00925 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -51,7 +51,8 @@ QString LMStudioProvider::completionEndpoint() const void LMStudioProvider::prepareRequest(QJsonObject &request) { const auto ¤tTemplate = PromptTemplateManager::instance().getCurrentTemplate(); - + if (currentTemplate->name() == "Custom Template") + return; if (request.contains("prompt")) { QJsonArray messages{ {QJsonObject{{"role", "user"}, {"content", request.take("prompt").toString()}}}}; diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index 41aaaa7..9bbbf29 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -51,6 +51,8 @@ QString OllamaProvider::completionEndpoint() const void OllamaProvider::prepareRequest(QJsonObject &request) { auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); + if (currentTemplate->name() == "Custom Template") + return; QJsonObject options; options["num_predict"] = settings().maxTokens(); diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index 64d0b3a..b3641e1 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -49,6 +49,8 @@ QString OpenAICompatProvider::completionEndpoint() const void OpenAICompatProvider::prepareRequest(QJsonObject &request) { const auto ¤tTemplate = PromptTemplateManager::instance().getCurrentTemplate(); + if (currentTemplate->name() == "Custom Template") + return; if (request.contains("prompt")) { QJsonArray messages{ diff --git a/qodeassist.cpp b/qodeassist.cpp index ffcd0f6..43ed118 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -46,6 +46,7 @@ #include "providers/OpenAICompatProvider.hpp" #include "templates/CodeLLamaTemplate.hpp" #include "templates/CodeQwenChat.hpp" +#include "templates/CustomTemplate.hpp" #include "templates/DeepSeekCoderV2.hpp" #include "templates/StarCoder2Template.hpp" @@ -82,6 +83,7 @@ public: templateManager.registerTemplate(); templateManager.registerTemplate(); templateManager.registerTemplate(); + templateManager.registerTemplate(); Utils::Icon QCODEASSIST_ICON( {{":/resources/images/qoderassist-icon.png", Utils::Theme::IconsBaseColor}}); diff --git a/templates/CustomTemplate.hpp b/templates/CustomTemplate.hpp new file mode 100644 index 0000000..ac4173c --- /dev/null +++ b/templates/CustomTemplate.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include "PromptTemplate.hpp" + +#include +#include + +#include "QodeAssistSettings.hpp" +#include "QodeAssistUtils.hpp" + +namespace QodeAssist::Templates { + +class CustomTemplate : public PromptTemplate +{ +public: + QString name() const override { return "Custom Template"; } + QString promptTemplate() const override { return settings().customJsonTemplate(); } + QStringList stopWords() const override { return QStringList(); } + + void prepareRequest(QJsonObject &request, const ContextData &context) const override + { + QJsonDocument doc = QJsonDocument::fromJson(promptTemplate().toUtf8()); + if (doc.isNull() || !doc.isObject()) { + logMessage(QString("Invalid JSON template in settings")); + + return; + } + + QJsonObject templateObj = doc.object(); + QJsonObject processedObj = processJsonTemplate(templateObj, context); + + for (auto it = processedObj.begin(); it != processedObj.end(); ++it) { + request[it.key()] = it.value(); + } + } + +private: + QJsonValue processJsonValue(const QJsonValue &value, const ContextData &context) const + { + if (value.isString()) { + QString str = value.toString(); + str.replace("{{QODE_INSTRUCTIONS}}", context.instriuctions); + str.replace("{{QODE_PREFIX}}", context.prefix); + str.replace("{{QODE_SUFFIX}}", context.suffix); + return str; + } else if (value.isObject()) { + return processJsonTemplate(value.toObject(), context); + } else if (value.isArray()) { + QJsonArray newArray; + for (const QJsonValue &arrayValue : value.toArray()) { + newArray.append(processJsonValue(arrayValue, context)); + } + return newArray; + } + return value; + } + + QJsonObject processJsonTemplate(const QJsonObject &templateObj, const ContextData &context) const + { + QJsonObject result; + for (auto it = templateObj.begin(); it != templateObj.end(); ++it) { + result[it.key()] = processJsonValue(it.value(), context); + } + return result; + } +}; +} // namespace QodeAssist::Templates From 8e61651bae5137a439fbabfe223d78a778c0f7a3 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:27:10 +0200 Subject: [PATCH 03/14] Add button for save and load Custom Template --- QodeAssistSettings.cpp | 77 +++++++++++++++++++++++++++++++++++++++++- QodeAssistSettings.hpp | 4 +++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index f2c1aab..bcf7e28 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -19,7 +19,9 @@ #include "QodeAssistSettings.hpp" +#include #include +#include #include #include #include @@ -199,6 +201,9 @@ QodeAssistSettings::QodeAssistSettings() "stream": true })"); + saveCustomTemplateButton.m_buttonText = (Tr::tr("Save Custom Template to JSON")); + loadCustomTemplateButton.m_buttonText = (Tr::tr("Load Custom Template from JSON")); + const auto &manager = LLMProvidersManager::instance(); if (!manager.getProviderNames().isEmpty()) { const auto providerNames = manager.getProviderNames(); @@ -246,7 +251,10 @@ QodeAssistSettings::QodeAssistSettings() Form{Column{Row{selectModels, modelName}}}}, Group{title(Tr::tr("FIM Prompt Settings")), Form{Column{fimPrompts, - Row{customJsonTemplate, Space{40}}, + Column{customJsonTemplate, + Row{saveCustomTemplateButton, + loadCustomTemplateButton, + Stretch{1}}}, readFullFile, maxFileThreshold, readStringsBeforeCursor, @@ -312,6 +320,15 @@ void QodeAssistSettings::setupConnections() connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() { specificInstractions.setEnabled(useSpecificInstructions.volatileValue()); }); + + connect(&saveCustomTemplateButton, + &ButtonAspect::clicked, + this, + &QodeAssistSettings::saveCustomTemplate); + connect(&loadCustomTemplateButton, + &ButtonAspect::clicked, + this, + &QodeAssistSettings::loadCustomTemplate); } void QodeAssistSettings::updateProviderSettings() @@ -407,6 +424,64 @@ void QodeAssistSettings::resetSettingsToDefaults() } } +void QodeAssistSettings::saveCustomTemplate() +{ + QString fileName = QFileDialog::getSaveFileName(nullptr, + Tr::tr("Save JSON Template"), + QString(), + Tr::tr("JSON Files (*.json)")); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&file); + out << customJsonTemplate.value(); + file.close(); + QMessageBox::information(nullptr, + Tr::tr("Save Successful"), + Tr::tr("JSON template has been saved successfully.")); + } else { + QMessageBox::critical(nullptr, + Tr::tr("Save Failed"), + Tr::tr("Failed to save JSON template.")); + } +} + +void QodeAssistSettings::loadCustomTemplate() +{ + QString fileName = QFileDialog::getOpenFileName(nullptr, + Tr::tr("Load JSON Template"), + QString(), + Tr::tr("JSON Files (*.json)")); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + QString jsonContent = in.readAll(); + file.close(); + + QJsonParseError parseError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); + if (parseError.error == QJsonParseError::NoError) { + customJsonTemplate.setValue(jsonContent); + QMessageBox::information(nullptr, + Tr::tr("Load Successful"), + Tr::tr("JSON template has been loaded successfully.")); + } else { + QMessageBox::critical(nullptr, + Tr::tr("Invalid JSON"), + Tr::tr("The selected file contains invalid JSON.")); + } + } else { + QMessageBox::critical(nullptr, + Tr::tr("Load Failed"), + Tr::tr("Failed to load JSON template.")); + } +} + class QodeAssistSettingsPage : public Core::IOptionsPage { public: diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index 5ea788c..d9802bb 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -98,6 +98,8 @@ public: Utils::BoolAspect multiLineCompletion{this}; Utils::StringAspect customJsonTemplate{this}; + ButtonAspect saveCustomTemplateButton{this}; + ButtonAspect loadCustomTemplateButton{this}; Utils::StringAspect apiKey{this}; ButtonAspect resetToDefaults{this}; @@ -109,6 +111,8 @@ private: void showModelSelectionDialog(); Utils::Environment getEnvironmentWithProviderPaths() const; void resetSettingsToDefaults(); + void saveCustomTemplate(); + void loadCustomTemplate(); }; QodeAssistSettings &settings(); From d49cd07dd0ba488dc7f18f5a6a98df6b9a317844 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sat, 7 Sep 2024 20:11:54 +0200 Subject: [PATCH 04/14] Add empty pages for future settings --- CMakeLists.txt | 4 ++ QodeAssistConstants.hpp | 6 +++ settings/ContextSettings.cpp | 63 ++++++++++++++++++++++++++++++ settings/ContextSettings.hpp | 34 ++++++++++++++++ settings/CustomPromptSettings.cpp | 62 +++++++++++++++++++++++++++++ settings/CustomPromptSettings.hpp | 34 ++++++++++++++++ settings/GeneralSettings.cpp | 62 +++++++++++++++++++++++++++++ settings/GeneralSettings.hpp | 34 ++++++++++++++++ settings/PresetPromptsSettings.cpp | 62 +++++++++++++++++++++++++++++ settings/PresetPromptsSettings.hpp | 34 ++++++++++++++++ 10 files changed, 395 insertions(+) create mode 100644 settings/ContextSettings.cpp create mode 100644 settings/ContextSettings.hpp create mode 100644 settings/CustomPromptSettings.cpp create mode 100644 settings/CustomPromptSettings.hpp create mode 100644 settings/GeneralSettings.cpp create mode 100644 settings/GeneralSettings.hpp create mode 100644 settings/PresetPromptsSettings.cpp create mode 100644 settings/PresetPromptsSettings.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 42f8ec3..6f92826 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,4 +51,8 @@ add_qtc_plugin(QodeAssist DocumentContextReader.hpp DocumentContextReader.cpp QodeAssistData.hpp utils/CounterTooltip.hpp utils/CounterTooltip.cpp + settings/GeneralSettings.hpp settings/GeneralSettings.cpp + settings/ContextSettings.hpp settings/ContextSettings.cpp + settings/CustomPromptSettings.hpp settings/CustomPromptSettings.cpp + settings/PresetPromptsSettings.hpp settings/PresetPromptsSettings.cpp ) diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp index 57fb905..65a4029 100644 --- a/QodeAssistConstants.hpp +++ b/QodeAssistConstants.hpp @@ -59,6 +59,12 @@ const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; +const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId"; +const char QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID[] = "QodeAssist.2ContextSettingsPageId"; +const char QODE_ASSIST_PRESET_PROMPTS_SETTINGS_PAGE_ID[] + = "QodeAssist.3PresetPromptsSettingsPageId"; +const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.4CustomPromptSettingsPageId"; + const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; const char QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY[] = "Qode Assist"; diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp new file mode 100644 index 0000000..e986b2e --- /dev/null +++ b/settings/ContextSettings.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include "ContextSettings.hpp" + +#include +#include + +#include "QodeAssistConstants.hpp" +#include "QodeAssisttr.h" + +namespace QodeAssist::Settings { +ContextSettings &contextSettings() +{ + static ContextSettings settings; + return settings; +} + +ContextSettings::ContextSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("Context")); + + setLayouter([this]() { + using namespace Layouting; + return Column{Stretch{1}}; + }); +} + +class ContextSettingsPage : public Core::IOptionsPage +{ +public: + ContextSettingsPage() + { + setId(Constants::QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("Context")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &contextSettings(); }); + } +}; + +const ContextSettingsPage contextSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/ContextSettings.hpp b/settings/ContextSettings.hpp new file mode 100644 index 0000000..884ce29 --- /dev/null +++ b/settings/ContextSettings.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include + +namespace QodeAssist::Settings { + +class ContextSettings : public Utils::AspectContainer +{ +public: + ContextSettings(); +}; + +ContextSettings &contextSettings(); + +} // namespace QodeAssist::Settings diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp new file mode 100644 index 0000000..aa64ca7 --- /dev/null +++ b/settings/CustomPromptSettings.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#include "CustomPromptSettings.hpp" + +#include +#include + +#include "QodeAssistConstants.hpp" +#include "QodeAssisttr.h" + +namespace QodeAssist::Settings { + +CustomPromptSettings &customPromptSettings() +{ + static CustomPromptSettings settings; + return settings; +} + +CustomPromptSettings::CustomPromptSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("Custom Prompt")); + + setLayouter([this]() { + using namespace Layouting; + return Column{Stretch{1}}; + }); +} + +class CustomPromptSettingsPage : public Core::IOptionsPage +{ +public: + CustomPromptSettingsPage() + { + setId(Constants::QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("Custom Prompt")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &customPromptSettings(); }); + } +}; + +const CustomPromptSettingsPage customPromptSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/CustomPromptSettings.hpp b/settings/CustomPromptSettings.hpp new file mode 100644 index 0000000..980b28d --- /dev/null +++ b/settings/CustomPromptSettings.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include + +namespace QodeAssist::Settings { + +class CustomPromptSettings : public Utils::AspectContainer +{ +public: + CustomPromptSettings(); +}; + +CustomPromptSettings &customPromptSettings(); + +} // namespace QodeAssist::Settings diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp new file mode 100644 index 0000000..335a59c --- /dev/null +++ b/settings/GeneralSettings.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#include "GeneralSettings.hpp" + +#include +#include + +#include "QodeAssistConstants.hpp" +#include "QodeAssisttr.h" + +namespace QodeAssist::Settings { + +GeneralSettings &generalSettings() +{ + static GeneralSettings settings; + return settings; +} + +GeneralSettings::GeneralSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("General")); + + setLayouter([this]() { + using namespace Layouting; + return Column{Stretch{1}}; + }); +} + +class GeneralSettingsPage : public Core::IOptionsPage +{ +public: + GeneralSettingsPage() + { + setId(Constants::QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("General")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &generalSettings(); }); + } +}; + +const GeneralSettingsPage generalSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp new file mode 100644 index 0000000..be876c2 --- /dev/null +++ b/settings/GeneralSettings.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include + +namespace QodeAssist::Settings { + +class GeneralSettings : public Utils::AspectContainer +{ +public: + GeneralSettings(); +}; + +GeneralSettings &generalSettings(); + +} // namespace QodeAssist::Settings diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp new file mode 100644 index 0000000..35d5c91 --- /dev/null +++ b/settings/PresetPromptsSettings.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#include "PresetPromptsSettings.hpp" + +#include +#include + +#include "QodeAssistConstants.hpp" +#include "QodeAssisttr.h" + +namespace QodeAssist::Settings { + +PresetPromptsSettings &presetPromptsSettings() +{ + static PresetPromptsSettings settings; + return settings; +} + +PresetPromptsSettings::PresetPromptsSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("Preset Prompts Params")); + + setLayouter([this]() { + using namespace Layouting; + return Column{Stretch{1}}; + }); +} + +class PresetPromptsSettingsPage : public Core::IOptionsPage +{ +public: + PresetPromptsSettingsPage() + { + setId(Constants::QODE_ASSIST_PRESET_PROMPTS_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("Preset Prompts Params")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &presetPromptsSettings(); }); + } +}; + +const PresetPromptsSettingsPage presetPromptsSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/PresetPromptsSettings.hpp b/settings/PresetPromptsSettings.hpp new file mode 100644 index 0000000..7f4e7c1 --- /dev/null +++ b/settings/PresetPromptsSettings.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include + +namespace QodeAssist::Settings { + +class PresetPromptsSettings : public Utils::AspectContainer +{ +public: + PresetPromptsSettings(); +}; + +PresetPromptsSettings &presetPromptsSettings(); + +} // namespace QodeAssist::Settings From b5ca11ed3840f7b6ba574c41a67d1abcd5499bfc Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sat, 7 Sep 2024 23:10:11 +0200 Subject: [PATCH 05/14] Move settings to General Page --- CMakeLists.txt | 1 + LLMClientInterface.cpp | 7 +- QodeAssistClient.cpp | 5 +- QodeAssistSettings.cpp | 141 +++-------------------------- QodeAssistSettings.hpp | 14 --- settings/GeneralSettings.cpp | 170 ++++++++++++++++++++++++++++++++++- settings/GeneralSettings.hpp | 22 +++++ settings/SettingsUtils.hpp | 55 ++++++++++++ 8 files changed, 268 insertions(+), 147 deletions(-) create mode 100644 settings/SettingsUtils.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f92826..fe51fc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,4 +55,5 @@ add_qtc_plugin(QodeAssist settings/ContextSettings.hpp settings/ContextSettings.cpp settings/CustomPromptSettings.hpp settings/CustomPromptSettings.cpp settings/PresetPromptsSettings.hpp settings/PresetPromptsSettings.cpp + settings/SettingsUtils.hpp ) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index f7d314d..ee434d7 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -30,6 +30,7 @@ #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" +#include "settings/GeneralSettings.hpp" namespace QodeAssist { @@ -289,7 +290,8 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, void LLMClientInterface::updateProvider() { - m_serverUrl = QUrl(QString("%1%2").arg(settings().url(), settings().endPoint())); + m_serverUrl = QUrl(QString("%1%2").arg(Settings::generalSettings().url(), + Settings::generalSettings().endPoint())); } void LLMClientInterface::sendCompletionToClient(const QString &completion, @@ -330,7 +332,8 @@ void LLMClientInterface::sendCompletionToClient(const QString &completion, void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const ContextData &prompt) { - QJsonObject providerRequest = {{"model", settings().modelName.value()}, {"stream", true}}; + QJsonObject providerRequest = {{"model", Settings::generalSettings().modelName.value()}, + {"stream", true}}; auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); currentTemplate->prepareRequest(providerRequest, prompt); diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index 296c519..cfaf367 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -32,6 +32,7 @@ #include "LLMClientInterface.hpp" #include "LLMSuggestion.hpp" #include "QodeAssistSettings.hpp" +#include "settings/GeneralSettings.hpp" using namespace LanguageServerProtocol; using namespace TextEditor; @@ -70,7 +71,7 @@ void QodeAssistClient::openDocument(TextEditor::TextDocument *document) this, [this, document](int position, int charsRemoved, int charsAdded) { Q_UNUSED(charsRemoved) - if (!settings().enableAutoComplete()) + if (!Settings::generalSettings().enableAutoComplete()) return; auto project = ProjectManager::projectForFile(document->filePath()); @@ -204,7 +205,7 @@ void QodeAssistClient::cancelRunningRequest(TextEditor::TextEditorWidget *editor bool QodeAssistClient::isEnabled(ProjectExplorer::Project *project) const { - return settings().enableQodeAssist(); + return Settings::generalSettings().enableQodeAssist(); } void QodeAssistClient::setupConnections() diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index bcf7e28..a69f632 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -45,41 +45,11 @@ QodeAssistSettings::QodeAssistSettings() { setAutoApply(false); - enableQodeAssist.setSettingsKey(Constants::ENABLE_QODE_ASSIST); - enableQodeAssist.setLabelText(Tr::tr("Enable Qode Assist")); - enableQodeAssist.setDefaultValue(true); - - enableAutoComplete.setSettingsKey(Constants::ENABLE_AUTO_COMPLETE); - enableAutoComplete.setLabelText(Tr::tr("Enable Auto Complete")); - enableAutoComplete.setDefaultValue(true); - - enableLogging.setSettingsKey(Constants::ENABLE_LOGGING); - enableLogging.setLabelText(Tr::tr("Enable Logging")); - enableLogging.setDefaultValue(false); - - llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); - llmProviders.setDisplayName(Tr::tr("LLM Providers:")); - llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); - llmProviders.setDefaultValue(0); - - url.setSettingsKey(Constants::URL); - url.setLabelText(Tr::tr("URL:")); - url.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - endPoint.setSettingsKey(Constants::END_POINT); - endPoint.setLabelText(Tr::tr("Endpoint:")); - endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - modelName.setSettingsKey(Constants::MODEL_NAME); - modelName.setLabelText(Tr::tr("LLM Name:")); - modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - temperature.setSettingsKey(Constants::TEMPERATURE); temperature.setLabelText(Tr::tr("Temperature:")); temperature.setDefaultValue(0.2); temperature.setRange(0.0, 10.0); - selectModels.m_buttonText = Tr::tr("Select Model"); ollamaLivetime.setSettingsKey(Constants::OLLAMA_LIVETIME); ollamaLivetime.setLabelText( @@ -88,11 +58,6 @@ QodeAssistSettings::QodeAssistSettings() ollamaLivetime.setDefaultValue("5m"); ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - fimPrompts.setDisplayName(Tr::tr("Fill-In-Middle Prompt")); - fimPrompts.setSettingsKey(Constants::FIM_PROMPTS); - fimPrompts.setDefaultValue(0); - fimPrompts.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); - readFullFile.setSettingsKey(Constants::READ_FULL_FILE); readFullFile.setLabelText(Tr::tr("Read Full File")); readFullFile.setDefaultValue(false); @@ -204,22 +169,6 @@ QodeAssistSettings::QodeAssistSettings() saveCustomTemplateButton.m_buttonText = (Tr::tr("Save Custom Template to JSON")); loadCustomTemplateButton.m_buttonText = (Tr::tr("Load Custom Template from JSON")); - const auto &manager = LLMProvidersManager::instance(); - if (!manager.getProviderNames().isEmpty()) { - const auto providerNames = manager.getProviderNames(); - for (const QString &name : providerNames) { - llmProviders.addOption(name); - } - } - - const auto &promptManager = PromptTemplateManager::instance(); - if (!promptManager.getTemplateNames().isEmpty()) { - const auto promptNames = promptManager.getTemplateNames(); - for (const QString &name : promptNames) { - fimPrompts.addOption(name); - } - } - readSettings(); topK.setEnabled(useTopK()); @@ -229,29 +178,14 @@ QodeAssistSettings::QodeAssistSettings() readStringsAfterCursor.setEnabled(!readFullFile()); readStringsBeforeCursor.setEnabled(!readFullFile()); specificInstractions.setEnabled(useSpecificInstructions()); - PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue()); - LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue()); customJsonTemplate.setVisible(PromptTemplateManager::instance().getCurrentTemplate()->name() == "Custom Template"); - setLoggingEnabled(enableLogging()); - setLayouter([this]() { using namespace Layouting; - return Column{Group{title(Tr::tr("General Settings")), - Form{Column{enableQodeAssist, - enableAutoComplete, - multiLineCompletion, - enableLogging, - Row{Stretch{1}, resetToDefaults}}}}, - Group{title(Tr::tr("LLM Providers")), - Form{Column{llmProviders, Row{url, endPoint}}}}, - Group{title(Tr::tr("LLM Model Settings")), - Form{Column{Row{selectModels, modelName}}}}, - Group{title(Tr::tr("FIM Prompt Settings")), - Form{Column{fimPrompts, - Column{customJsonTemplate, + return Column{Group{title(Tr::tr("FIM Prompt Settings")), + Form{Column{Column{customJsonTemplate, Row{saveCustomTemplateButton, loadCustomTemplateButton, Stretch{1}}}, @@ -279,21 +213,6 @@ QodeAssistSettings::QodeAssistSettings() void QodeAssistSettings::setupConnections() { - connect(&llmProviders, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - int index = llmProviders.volatileValue(); - logMessage(QString("currentProvider %1").arg(llmProviders.displayForIndex(index))); - LLMProvidersManager::instance().setCurrentProvider(llmProviders.displayForIndex(index)); - updateProviderSettings(); - }); - - connect(&fimPrompts, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - int index = fimPrompts.volatileValue(); - logMessage(QString("currentPrompt %1").arg(fimPrompts.displayForIndex(index))); - PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.displayForIndex(index)); - customJsonTemplate.setVisible(fimPrompts.displayForIndex(index) == "Custom Template"); - }); - - connect(&selectModels, &ButtonAspect::clicked, this, [this]() { showModelSelectionDialog(); }); connect(&useTopP, &Utils::BoolAspect::volatileValueChanged, this, [this]() { topP.setEnabled(useTopP.volatileValue()); }); @@ -314,9 +233,7 @@ void QodeAssistSettings::setupConnections() &ButtonAspect::clicked, this, &QodeAssistSettings::resetSettingsToDefaults); - connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - setLoggingEnabled(enableLogging.volatileValue()); - }); + connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() { specificInstractions.setEnabled(useSpecificInstructions.volatileValue()); }); @@ -331,18 +248,6 @@ void QodeAssistSettings::setupConnections() &QodeAssistSettings::loadCustomTemplate); } -void QodeAssistSettings::updateProviderSettings() -{ - auto *provider = LLMProvidersManager::instance().getCurrentProvider(); - - if (provider) { - logMessage(QString("currentProvider %1").arg(provider->name())); - url.setValue(provider->url()); - endPoint.setValue(provider->completionEndpoint()); - ollamaLivetime.setEnabled(provider->name() == "Ollama"); - } -} - QStringList QodeAssistSettings::getInstalledModels() { auto *provider = LLMProvidersManager::instance().getCurrentProvider(); @@ -353,25 +258,6 @@ QStringList QodeAssistSettings::getInstalledModels() return {}; } -void QodeAssistSettings::showModelSelectionDialog() -{ - QStringList models = getInstalledModels(); - - bool ok; - QString selectedModel = QInputDialog::getItem(Core::ICore::dialogParent(), - Tr::tr("Select LLM Model"), - Tr::tr("Choose a model:"), - models, - 0, - false, - &ok); - - if (ok && !selectedModel.isEmpty()) { - modelName.setValue(selectedModel); - writeSettings(); - } -} - void QodeAssistSettings::resetSettingsToDefaults() { QMessageBox::StandardButton reply; @@ -382,13 +268,13 @@ void QodeAssistSettings::resetSettingsToDefaults() QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { - resetAspect(enableQodeAssist); - resetAspect(enableAutoComplete); - resetAspect(llmProviders); - resetAspect(url); - resetAspect(endPoint); - resetAspect(modelName); - resetAspect(fimPrompts); + // resetAspect(enableQodeAssist); + // resetAspect(enableAutoComplete); + // resetAspect(llmProviders); + // resetAspect(url); + // resetAspect(endPoint); + // resetAspect(modelName); + // resetAspect(fimPrompts); resetAspect(temperature); resetAspect(maxTokens); resetAspect(readFullFile); @@ -404,7 +290,7 @@ void QodeAssistSettings::resetSettingsToDefaults() resetAspect(useFrequencyPenalty); resetAspect(frequencyPenalty); resetAspect(startSuggestionTimer); - resetAspect(enableLogging); + // resetAspect(enableLogging); resetAspect(ollamaLivetime); resetAspect(specificInstractions); resetAspect(multiLineCompletion); @@ -412,10 +298,9 @@ void QodeAssistSettings::resetSettingsToDefaults() resetAspect(useSpecificInstructions); resetAspect(customJsonTemplate); - fimPrompts.setStringValue("StarCoder2"); - llmProviders.setStringValue("Ollama"); + // fimPrompts.setStringValue("StarCoder2"); + // llmProviders.setStringValue("Ollama"); - updateProviderSettings(); apply(); QMessageBox::information(Core::ICore::dialogParent(), diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index d9802bb..c3962c6 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -57,18 +57,6 @@ class QodeAssistSettings : public Utils::AspectContainer public: QodeAssistSettings(); - Utils::BoolAspect enableQodeAssist{this}; - Utils::BoolAspect enableAutoComplete{this}; - Utils::BoolAspect enableLogging{this}; - - Utils::SelectionAspect llmProviders{this}; - Utils::StringAspect url{this}; - Utils::StringAspect endPoint{this}; - - Utils::StringAspect modelName{this}; - ButtonAspect selectModels{this}; - - Utils::SelectionAspect fimPrompts{this}; Utils::DoubleAspect temperature{this}; Utils::IntegerAspect maxTokens{this}; @@ -106,9 +94,7 @@ public: private: void setupConnections(); - void updateProviderSettings(); QStringList getInstalledModels(); - void showModelSelectionDialog(); Utils::Environment getEnvironmentWithProviderPaths() const; void resetSettingsToDefaults(); void saveCustomTemplate(); diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 335a59c..b4ac424 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -19,10 +19,16 @@ #include "GeneralSettings.hpp" +#include +#include #include +#include #include +#include "LLMProvidersManager.hpp" +#include "PromptTemplateManager.hpp" #include "QodeAssistConstants.hpp" +#include "QodeAssistUtils.hpp" #include "QodeAssisttr.h" namespace QodeAssist::Settings { @@ -39,12 +45,174 @@ GeneralSettings::GeneralSettings() setDisplayName(Tr::tr("General")); + enableQodeAssist.setSettingsKey(Constants::ENABLE_QODE_ASSIST); + enableQodeAssist.setLabelText(Tr::tr("Enable Qode Assist")); + enableQodeAssist.setDefaultValue(true); + + enableAutoComplete.setSettingsKey(Constants::ENABLE_AUTO_COMPLETE); + enableAutoComplete.setLabelText(Tr::tr("Enable Auto Complete")); + enableAutoComplete.setDefaultValue(true); + + enableLogging.setSettingsKey(Constants::ENABLE_LOGGING); + enableLogging.setLabelText(Tr::tr("Enable Logging")); + enableLogging.setDefaultValue(false); + + multiLineCompletion.setSettingsKey(Constants::MULTILINE_COMPLETION); + multiLineCompletion.setDefaultValue(true); + multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion")); + + llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); + llmProviders.setDisplayName(Tr::tr("LLM Providers:")); + llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); + llmProviders.setDefaultValue(0); + + url.setSettingsKey(Constants::URL); + url.setLabelText(Tr::tr("URL:")); + url.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + endPoint.setSettingsKey(Constants::END_POINT); + endPoint.setLabelText(Tr::tr("Endpoint:")); + endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + modelName.setSettingsKey(Constants::MODEL_NAME); + modelName.setLabelText(Tr::tr("LLM Name:")); + modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + selectModels.m_buttonText = Tr::tr("Select Model"); + + fimPrompts.setDisplayName(Tr::tr("Fill-In-Middle Prompt")); + fimPrompts.setSettingsKey(Constants::FIM_PROMPTS); + fimPrompts.setDefaultValue(0); + fimPrompts.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); + resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + + const auto &manager = LLMProvidersManager::instance(); + if (!manager.getProviderNames().isEmpty()) { + const auto providerNames = manager.getProviderNames(); + for (const QString &name : providerNames) { + llmProviders.addOption(name); + } + } + + const auto &promptManager = PromptTemplateManager::instance(); + if (!promptManager.getTemplateNames().isEmpty()) { + const auto promptNames = promptManager.getTemplateNames(); + for (const QString &name : promptNames) { + fimPrompts.addOption(name); + } + } + + readSettings(); + + LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue()); + PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue()); + setLoggingEnabled(enableLogging()); + + setupConnections(); + setLayouter([this]() { using namespace Layouting; - return Column{Stretch{1}}; + + auto rootLayout = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults}, + enableAutoComplete, + multiLineCompletion, + Space{8}, + enableLogging, + Space{8}, + llmProviders, + Row{url, endPoint}, + Space{8}, + Row{selectModels, modelName}, + Space{8}, + fimPrompts, + Stretch{1}}; + return rootLayout; }); } +void GeneralSettings::setupConnections() +{ + connect(&llmProviders, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { + int index = llmProviders.volatileValue(); + logMessage(QString("currentProvider %1").arg(llmProviders.displayForIndex(index))); + LLMProvidersManager::instance().setCurrentProvider(llmProviders.displayForIndex(index)); + updateProviderSettings(); + }); + connect(&fimPrompts, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { + int index = fimPrompts.volatileValue(); + logMessage(QString("currentPrompt %1").arg(fimPrompts.displayForIndex(index))); + PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.displayForIndex(index)); + }); + connect(&selectModels, &ButtonAspect::clicked, this, [this]() { showModelSelectionDialog(); }); + connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + setLoggingEnabled(enableLogging.volatileValue()); + }); + connect(&resetToDefaults, &ButtonAspect::clicked, this, &GeneralSettings::resetPageToDefaults); +} + +void GeneralSettings::updateProviderSettings() +{ + const auto provider = LLMProvidersManager::instance().getCurrentProvider(); + + if (provider) { + url.setValue(provider->url()); + endPoint.setValue(provider->completionEndpoint()); + } +} + +void GeneralSettings::showModelSelectionDialog() +{ + auto *provider = LLMProvidersManager::instance().getCurrentProvider(); + Utils::Environment env = Utils::Environment::systemEnvironment(); + + if (provider) { + QStringList models = provider->getInstalledModels(env); + bool ok; + QString selectedModel = QInputDialog::getItem(Core::ICore::dialogParent(), + Tr::tr("Select LLM Model"), + Tr::tr("Choose a model:"), + models, + 0, + false, + &ok); + + if (ok && !selectedModel.isEmpty()) { + modelName.setValue(selectedModel); + writeSettings(); + } + } +} + +void GeneralSettings::resetPageToDefaults() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + Core::ICore::dialogParent(), + Tr::tr("Reset Settings"), + Tr::tr("Are you sure you want to reset all settings to default values?"), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + resetAspect(enableQodeAssist); + resetAspect(enableAutoComplete); + resetAspect(llmProviders); + resetAspect(url); + resetAspect(endPoint); + resetAspect(modelName); + resetAspect(fimPrompts); + resetAspect(enableLogging); + } + + fimPrompts.setStringValue("StarCoder2"); + llmProviders.setStringValue("Ollama"); + + apply(); + + QMessageBox::information(Core::ICore::dialogParent(), + Tr::tr("Settings Reset"), + Tr::tr("All settings have been reset to their default values.")); +} + class GeneralSettingsPage : public Core::IOptionsPage { public: diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index be876c2..3b57d4a 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -21,12 +21,34 @@ #include +#include "settings/SettingsUtils.hpp" + namespace QodeAssist::Settings { class GeneralSettings : public Utils::AspectContainer { public: GeneralSettings(); + + Utils::BoolAspect enableQodeAssist{this}; + Utils::BoolAspect enableAutoComplete{this}; + Utils::BoolAspect multiLineCompletion{this}; + Utils::BoolAspect enableLogging{this}; + + Utils::SelectionAspect llmProviders{this}; + Utils::StringAspect url{this}; + Utils::StringAspect endPoint{this}; + + Utils::StringAspect modelName{this}; + ButtonAspect selectModels{this}; + Utils::SelectionAspect fimPrompts{this}; + ButtonAspect resetToDefaults{this}; + +private: + void setupConnections(); + void updateProviderSettings(); + void showModelSelectionDialog(); + void resetPageToDefaults(); }; GeneralSettings &generalSettings(); diff --git a/settings/SettingsUtils.hpp b/settings/SettingsUtils.hpp new file mode 100644 index 0000000..2844a0d --- /dev/null +++ b/settings/SettingsUtils.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace QodeAssist::Settings { + +template +void resetAspect(AspectType &aspect) +{ + aspect.setValue(aspect.defaultValue()); +} + +class ButtonAspect : public Utils::BaseAspect +{ + Q_OBJECT + +public: + ButtonAspect(Utils::AspectContainer *container = nullptr) + : Utils::BaseAspect(container) + {} + + void addToLayout(Layouting::Layout &parent) override + { + auto button = new QPushButton(m_buttonText); + connect(button, &QPushButton::clicked, this, &ButtonAspect::clicked); + parent.addItem(button); + } + + QString m_buttonText; +signals: + void clicked(); +}; + +} // namespace QodeAssist::Settings From 356f28a97b06c156f2e1b95649af944126d37150 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sat, 7 Sep 2024 23:51:23 +0200 Subject: [PATCH 06/14] Move context settings to page --- DocumentContextReader.cpp | 3 +- LLMClientInterface.cpp | 20 +++++---- QodeAssistSettings.cpp | 79 ++++++++------------------------- QodeAssistSettings.hpp | 9 ---- settings/ContextSettings.cpp | 85 +++++++++++++++++++++++++++++++++++- settings/ContextSettings.hpp | 16 +++++++ settings/GeneralSettings.cpp | 8 ++-- settings/SettingsUtils.hpp | 2 +- 8 files changed, 134 insertions(+), 88 deletions(-) diff --git a/DocumentContextReader.cpp b/DocumentContextReader.cpp index 0aa42b5..b8d8fad 100644 --- a/DocumentContextReader.cpp +++ b/DocumentContextReader.cpp @@ -24,6 +24,7 @@ #include #include "QodeAssistSettings.hpp" +#include "settings/ContextSettings.hpp" const QRegularExpression &getYearRegex() { @@ -136,7 +137,7 @@ QString DocumentContextReader::getLanguageAndFileInfo() const QString DocumentContextReader::getSpecificInstructions() const { - QString specificInstruction = settings().specificInstractions().arg( + QString specificInstruction = Settings::contextSettings().specificInstractions().arg( LanguageServerProtocol::TextDocumentItem::mimeTypeToLanguageId(m_textDocument->mimeType())); return QString("%1").arg(specificInstruction); } diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index ee434d7..217f3b8 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -30,6 +30,7 @@ #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" +#include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" namespace QodeAssist { @@ -131,12 +132,13 @@ QString LLMClientInterface::сontextBefore(TextEditor::TextEditorWidget *widget, return QString(); QString contextBefore; - if (settings().readFullFile()) { + if (Settings::contextSettings().readFullFile()) { contextBefore = reader.readWholeFileBefore(lineNumber, cursorPosition); } else { - contextBefore = reader.getContextBefore(lineNumber, - cursorPosition, - settings().readStringsBeforeCursor()); + contextBefore + = reader.getContextBefore(lineNumber, + cursorPosition, + Settings::contextSettings().readStringsBeforeCursor()); } return contextBefore; @@ -154,12 +156,12 @@ QString LLMClientInterface::сontextAfter(TextEditor::TextEditorWidget *widget, return QString(); QString contextAfter; - if (settings().readFullFile()) { + if (Settings::contextSettings().readFullFile()) { contextAfter = reader.readWholeFileAfter(lineNumber, cursorPosition); } else { contextAfter = reader.getContextAfter(lineNumber, cursorPosition, - settings().readStringsAfterCursor()); + Settings::contextSettings().readStringsAfterCursor()); } return contextAfter; @@ -228,7 +230,7 @@ void LLMClientInterface::handleLLMResponse(QNetworkReply *reply, const QJsonObje QJsonObject position = request["params"].toObject()["doc"].toObject()["position"].toObject(); - if (!settings().multiLineCompletion() + if (!Settings::generalSettings().multiLineCompletion() && processSingleLineCompletion(reply, request, accumulatedResponse)) { return; } @@ -278,10 +280,10 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition); - QString instructions = QString("%1%2").arg(settings().useSpecificInstructions() + QString instructions = QString("%1%2").arg(Settings::contextSettings().useSpecificInstructions() ? reader.getSpecificInstructions() : QString(), - settings().useFilePathInContext() + Settings::contextSettings().useFilePathInContext() ? reader.getLanguageAndFileInfo() : QString()); diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index a69f632..56c6725 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -58,23 +58,6 @@ QodeAssistSettings::QodeAssistSettings() ollamaLivetime.setDefaultValue("5m"); ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - readFullFile.setSettingsKey(Constants::READ_FULL_FILE); - readFullFile.setLabelText(Tr::tr("Read Full File")); - readFullFile.setDefaultValue(false); - - maxFileThreshold.setSettingsKey(Constants::MAX_FILE_THRESHOLD); - maxFileThreshold.setLabelText(Tr::tr("Max File Threshold:")); - maxFileThreshold.setRange(10, 100000); - maxFileThreshold.setDefaultValue(600); - - readStringsBeforeCursor.setSettingsKey(Constants::READ_STRINGS_BEFORE_CURSOR); - readStringsBeforeCursor.setLabelText(Tr::tr("Read Strings Before Cursor")); - readStringsBeforeCursor.setDefaultValue(50); - - readStringsAfterCursor.setSettingsKey(Constants::READ_STRINGS_AFTER_CURSOR); - readStringsAfterCursor.setLabelText(Tr::tr("Read Strings After Cursor")); - readStringsAfterCursor.setDefaultValue(30); - maxTokens.setSettingsKey(Constants::MAX_TOKENS); maxTokens.setLabelText(Tr::tr("Max Tokens")); maxTokens.setRange(-1, 10000); @@ -117,26 +100,7 @@ QodeAssistSettings::QodeAssistSettings() startSuggestionTimer.setRange(10, 10000); startSuggestionTimer.setDefaultValue(500); - useFilePathInContext.setSettingsKey(Constants::USE_FILE_PATH_IN_CONTEXT); - useFilePathInContext.setDefaultValue(false); - useFilePathInContext.setLabelText(Tr::tr("Use File Path in Context")); - - useSpecificInstructions.setSettingsKey(Constants::USE_SPECIFIC_INSTRUCTIONS); - useSpecificInstructions.setDefaultValue(false); - useSpecificInstructions.setLabelText(Tr::tr("Use Specific Instructions")); - - specificInstractions.setSettingsKey(Constants::SPECIFIC_INSTRUCTIONS); - specificInstractions.setDisplayStyle(Utils::StringAspect::TextEditDisplay); - specificInstractions.setLabelText( - Tr::tr("Instructions: Please keep %1 for languge name, warning, it shouldn't too big")); - specificInstractions.setDefaultValue( - "You are an expert %1 code completion AI." - "CRITICAL: Please provide minimal the best possible code completion suggestions.\n"); - resetToDefaults.m_buttonText = Tr::tr("Reset to Defaults"); - multiLineCompletion.setSettingsKey(Constants::MULTILINE_COMPLETION); - multiLineCompletion.setDefaultValue(true); - multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion")); apiKey.setSettingsKey(Constants::API_KEY); apiKey.setLabelText(Tr::tr("API Key:")); @@ -175,9 +139,7 @@ QodeAssistSettings::QodeAssistSettings() topP.setEnabled(useTopP()); presencePenalty.setEnabled(usePresencePenalty()); frequencyPenalty.setEnabled(useFrequencyPenalty()); - readStringsAfterCursor.setEnabled(!readFullFile()); - readStringsBeforeCursor.setEnabled(!readFullFile()); - specificInstractions.setEnabled(useSpecificInstructions()); + customJsonTemplate.setVisible(PromptTemplateManager::instance().getCurrentTemplate()->name() == "Custom Template"); @@ -189,15 +151,15 @@ QodeAssistSettings::QodeAssistSettings() Row{saveCustomTemplateButton, loadCustomTemplateButton, Stretch{1}}}, - readFullFile, - maxFileThreshold, - readStringsBeforeCursor, - readStringsAfterCursor, + // readFullFile, + // maxFileThreshold, + // readStringsBeforeCursor, + // readStringsAfterCursor, ollamaLivetime, apiKey, - useFilePathInContext, - useSpecificInstructions, - specificInstractions, + // useFilePathInContext, + // useSpecificInstructions, + // specificInstractions, temperature, maxTokens, startSuggestionTimer, @@ -225,19 +187,12 @@ void QodeAssistSettings::setupConnections() connect(&useFrequencyPenalty, &Utils::BoolAspect::volatileValueChanged, this, [this]() { frequencyPenalty.setEnabled(useFrequencyPenalty.volatileValue()); }); - connect(&readFullFile, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - readStringsAfterCursor.setEnabled(!readFullFile.volatileValue()); - readStringsBeforeCursor.setEnabled(!readFullFile.volatileValue()); - }); + connect(&resetToDefaults, &ButtonAspect::clicked, this, &QodeAssistSettings::resetSettingsToDefaults); - connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - specificInstractions.setEnabled(useSpecificInstructions.volatileValue()); - }); - connect(&saveCustomTemplateButton, &ButtonAspect::clicked, this, @@ -277,10 +232,10 @@ void QodeAssistSettings::resetSettingsToDefaults() // resetAspect(fimPrompts); resetAspect(temperature); resetAspect(maxTokens); - resetAspect(readFullFile); - resetAspect(maxFileThreshold); - resetAspect(readStringsBeforeCursor); - resetAspect(readStringsAfterCursor); + // resetAspect(readFullFile); + // resetAspect(maxFileThreshold); + // resetAspect(readStringsBeforeCursor); + // resetAspect(readStringsAfterCursor); resetAspect(useTopP); resetAspect(topP); resetAspect(useTopK); @@ -292,10 +247,10 @@ void QodeAssistSettings::resetSettingsToDefaults() resetAspect(startSuggestionTimer); // resetAspect(enableLogging); resetAspect(ollamaLivetime); - resetAspect(specificInstractions); - resetAspect(multiLineCompletion); - resetAspect(useFilePathInContext); - resetAspect(useSpecificInstructions); + // resetAspect(specificInstractions); + // resetAspect(multiLineCompletion); + // resetAspect(useFilePathInContext); + // resetAspect(useSpecificInstructions); resetAspect(customJsonTemplate); // fimPrompts.setStringValue("StarCoder2"); diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index c3962c6..797e333 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -60,10 +60,6 @@ public: Utils::DoubleAspect temperature{this}; Utils::IntegerAspect maxTokens{this}; - Utils::BoolAspect readFullFile{this}; - Utils::IntegerAspect readStringsBeforeCursor{this}; - Utils::IntegerAspect readStringsAfterCursor{this}; - Utils::BoolAspect useTopP{this}; Utils::DoubleAspect topP{this}; @@ -77,13 +73,8 @@ public: Utils::DoubleAspect frequencyPenalty{this}; Utils::IntegerAspect startSuggestionTimer{this}; - Utils::IntegerAspect maxFileThreshold{this}; Utils::StringAspect ollamaLivetime{this}; - Utils::StringAspect specificInstractions{this}; - Utils::BoolAspect useSpecificInstructions{this}; - Utils::BoolAspect useFilePathInContext{this}; - Utils::BoolAspect multiLineCompletion{this}; Utils::StringAspect customJsonTemplate{this}; ButtonAspect saveCustomTemplateButton{this}; diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index e986b2e..1f2ae76 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -21,7 +21,9 @@ #include "ContextSettings.hpp" +#include #include +#include #include #include "QodeAssistConstants.hpp" @@ -40,12 +42,93 @@ ContextSettings::ContextSettings() setDisplayName(Tr::tr("Context")); + readFullFile.setSettingsKey(Constants::READ_FULL_FILE); + readFullFile.setLabelText(Tr::tr("Read Full File")); + readFullFile.setDefaultValue(false); + + readStringsBeforeCursor.setSettingsKey(Constants::READ_STRINGS_BEFORE_CURSOR); + readStringsBeforeCursor.setLabelText(Tr::tr("Read Strings Before Cursor")); + readStringsBeforeCursor.setRange(0, 10000); + readStringsBeforeCursor.setDefaultValue(50); + + readStringsAfterCursor.setSettingsKey(Constants::READ_STRINGS_AFTER_CURSOR); + readStringsAfterCursor.setLabelText(Tr::tr("Read Strings After Cursor")); + readStringsAfterCursor.setRange(0, 10000); + readStringsAfterCursor.setDefaultValue(30); + + useFilePathInContext.setSettingsKey(Constants::USE_FILE_PATH_IN_CONTEXT); + useFilePathInContext.setDefaultValue(false); + useFilePathInContext.setLabelText(Tr::tr("Use File Path in Context")); + + useSpecificInstructions.setSettingsKey(Constants::USE_SPECIFIC_INSTRUCTIONS); + useSpecificInstructions.setDefaultValue(false); + useSpecificInstructions.setLabelText(Tr::tr("Use Specific Instructions")); + + specificInstractions.setSettingsKey(Constants::SPECIFIC_INSTRUCTIONS); + specificInstractions.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + specificInstractions.setLabelText( + Tr::tr("Instructions: Please keep %1 for languge name, warning, it shouldn't too big")); + specificInstractions.setDefaultValue( + "You are an expert %1 code completion AI." + "CRITICAL: Please provide minimal the best possible code completion suggestions.\n"); + + resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + + readSettings(); + + readStringsAfterCursor.setEnabled(!readFullFile()); + readStringsBeforeCursor.setEnabled(!readFullFile()); + specificInstractions.setEnabled(useSpecificInstructions()); + + setupConnection(); + setLayouter([this]() { using namespace Layouting; - return Column{Stretch{1}}; + return Column{Row{readFullFile, Stretch{1}, resetToDefaults}, + readStringsBeforeCursor, + readStringsAfterCursor, + useFilePathInContext, + useSpecificInstructions, + specificInstractions, + Stretch{1}}; }); } +void ContextSettings::setupConnection() +{ + connect(&readFullFile, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + readStringsAfterCursor.setEnabled(!readFullFile.volatileValue()); + readStringsBeforeCursor.setEnabled(!readFullFile.volatileValue()); + }); + connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + specificInstractions.setEnabled(useSpecificInstructions.volatileValue()); + }); + connect(&resetToDefaults, &ButtonAspect::clicked, this, &ContextSettings::resetPageToDefaults); +} + +void ContextSettings::resetPageToDefaults() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + Core::ICore::dialogParent(), + Tr::tr("Reset Settings"), + Tr::tr("Are you sure you want to reset all settings to default values?"), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + resetAspect(readFullFile); + resetAspect(readStringsBeforeCursor); + resetAspect(readStringsAfterCursor); + resetAspect(useFilePathInContext); + resetAspect(useSpecificInstructions); + resetAspect(specificInstractions); + } + + QMessageBox::information(Core::ICore::dialogParent(), + Tr::tr("Settings Reset"), + Tr::tr("All settings have been reset to their default values.")); +} + class ContextSettingsPage : public Core::IOptionsPage { public: diff --git a/settings/ContextSettings.hpp b/settings/ContextSettings.hpp index 884ce29..4a6f539 100644 --- a/settings/ContextSettings.hpp +++ b/settings/ContextSettings.hpp @@ -21,12 +21,28 @@ #include +#include "SettingsUtils.hpp" + namespace QodeAssist::Settings { class ContextSettings : public Utils::AspectContainer { public: ContextSettings(); + + Utils::BoolAspect readFullFile{this}; + Utils::IntegerAspect readStringsBeforeCursor{this}; + Utils::IntegerAspect readStringsAfterCursor{this}; + + Utils::StringAspect specificInstractions{this}; + Utils::BoolAspect useSpecificInstructions{this}; + Utils::BoolAspect useFilePathInContext{this}; + + ButtonAspect resetToDefaults{this}; + +private: + void setupConnection(); + void resetPageToDefaults(); }; ContextSettings &contextSettings(); diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index b4ac424..c701d1b 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -155,8 +155,8 @@ void GeneralSettings::updateProviderSettings() const auto provider = LLMProvidersManager::instance().getCurrentProvider(); if (provider) { - url.setValue(provider->url()); - endPoint.setValue(provider->completionEndpoint()); + url.setVolatileValue(provider->url()); + endPoint.setVolatileValue(provider->completionEndpoint()); } } @@ -177,7 +177,7 @@ void GeneralSettings::showModelSelectionDialog() &ok); if (ok && !selectedModel.isEmpty()) { - modelName.setValue(selectedModel); + modelName.setVolatileValue(selectedModel); writeSettings(); } } @@ -206,8 +206,6 @@ void GeneralSettings::resetPageToDefaults() fimPrompts.setStringValue("StarCoder2"); llmProviders.setStringValue("Ollama"); - apply(); - QMessageBox::information(Core::ICore::dialogParent(), Tr::tr("Settings Reset"), Tr::tr("All settings have been reset to their default values.")); diff --git a/settings/SettingsUtils.hpp b/settings/SettingsUtils.hpp index 2844a0d..0e56712 100644 --- a/settings/SettingsUtils.hpp +++ b/settings/SettingsUtils.hpp @@ -28,7 +28,7 @@ namespace QodeAssist::Settings { template void resetAspect(AspectType &aspect) { - aspect.setValue(aspect.defaultValue()); + aspect.setVolatileValue(aspect.defaultValue()); } class ButtonAspect : public Utils::BaseAspect From 4d06541a3617e9b1649531b8be8df71824cbd3d8 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 00:13:48 +0200 Subject: [PATCH 07/14] Move preset params to separate settings page --- QodeAssistSettings.cpp | 113 +++++--------------------- QodeAssistSettings.hpp | 18 ----- providers/LMStudioProvider.cpp | 22 ++--- providers/OllamaProvider.cpp | 24 +++--- providers/OpenAICompatProvider.cpp | 24 +++--- settings/PresetPromptsSettings.cpp | 125 ++++++++++++++++++++++++++++- settings/PresetPromptsSettings.hpp | 25 ++++++ 7 files changed, 207 insertions(+), 144 deletions(-) diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index 56c6725..f6938ca 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -45,56 +45,6 @@ QodeAssistSettings::QodeAssistSettings() { setAutoApply(false); - temperature.setSettingsKey(Constants::TEMPERATURE); - temperature.setLabelText(Tr::tr("Temperature:")); - temperature.setDefaultValue(0.2); - temperature.setRange(0.0, 10.0); - - - ollamaLivetime.setSettingsKey(Constants::OLLAMA_LIVETIME); - ollamaLivetime.setLabelText( - Tr::tr("Time to suspend Ollama after completion request (in minutes), " - "Only Ollama, -1 to disable")); - ollamaLivetime.setDefaultValue("5m"); - ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - maxTokens.setSettingsKey(Constants::MAX_TOKENS); - maxTokens.setLabelText(Tr::tr("Max Tokens")); - maxTokens.setRange(-1, 10000); - maxTokens.setDefaultValue(150); - - useTopP.setSettingsKey(Constants::USE_TOP_P); - useTopP.setDefaultValue(false); - - topP.setSettingsKey(Constants::TOP_P); - topP.setLabelText(Tr::tr("top_p")); - topP.setDefaultValue(0.9); - topP.setRange(0.0, 1.0); - - useTopK.setSettingsKey(Constants::USE_TOP_K); - useTopK.setDefaultValue(false); - - topK.setSettingsKey(Constants::TOP_K); - topK.setLabelText(Tr::tr("top_k")); - topK.setDefaultValue(50); - topK.setRange(1, 1000); - - usePresencePenalty.setSettingsKey(Constants::USE_PRESENCE_PENALTY); - usePresencePenalty.setDefaultValue(false); - - presencePenalty.setSettingsKey(Constants::PRESENCE_PENALTY); - presencePenalty.setLabelText(Tr::tr("presence_penalty")); - presencePenalty.setDefaultValue(0.0); - presencePenalty.setRange(-2.0, 2.0); - - useFrequencyPenalty.setSettingsKey(Constants::USE_FREQUENCY_PENALTY); - useFrequencyPenalty.setDefaultValue(false); - - frequencyPenalty.setSettingsKey(Constants::FREQUENCY_PENALTY); - frequencyPenalty.setLabelText(Tr::tr("frequency_penalty")); - frequencyPenalty.setDefaultValue(0.0); - frequencyPenalty.setRange(-2.0, 2.0); - startSuggestionTimer.setSettingsKey(Constants::START_SUGGESTION_TIMER); startSuggestionTimer.setLabelText(Tr::tr("Start Suggestion Timer:")); startSuggestionTimer.setRange(10, 10000); @@ -102,11 +52,6 @@ QodeAssistSettings::QodeAssistSettings() resetToDefaults.m_buttonText = Tr::tr("Reset to Defaults"); - apiKey.setSettingsKey(Constants::API_KEY); - apiKey.setLabelText(Tr::tr("API Key:")); - apiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - apiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); - customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); customJsonTemplate.setLabelText("Custom JSON Template:"); customJsonTemplate.setDisplayStyle(Utils::StringAspect::TextEditDisplay); @@ -135,11 +80,6 @@ QodeAssistSettings::QodeAssistSettings() readSettings(); - topK.setEnabled(useTopK()); - topP.setEnabled(useTopP()); - presencePenalty.setEnabled(usePresencePenalty()); - frequencyPenalty.setEnabled(useFrequencyPenalty()); - customJsonTemplate.setVisible(PromptTemplateManager::instance().getCurrentTemplate()->name() == "Custom Template"); @@ -155,18 +95,18 @@ QodeAssistSettings::QodeAssistSettings() // maxFileThreshold, // readStringsBeforeCursor, // readStringsAfterCursor, - ollamaLivetime, - apiKey, + // ollamaLivetime, + // apiKey, // useFilePathInContext, // useSpecificInstructions, // specificInstractions, - temperature, - maxTokens, - startSuggestionTimer, - Row{useTopP, topP, Stretch{1}}, - Row{useTopK, topK, Stretch{1}}, - Row{usePresencePenalty, presencePenalty, Stretch{1}}, - Row{useFrequencyPenalty, frequencyPenalty, Stretch{1}}}}}, + // temperature, + // maxTokens, + // startSuggestionTimer, + // Row{useTopP, topP, Stretch{1}}, + // Row{useTopK, topK, Stretch{1}}, +/* Row{usePresencePenalty, presencePenalty, Stretch{1}}, + Row{useFrequencyPenalty, frequencyPenalty, Stretch{1}}*/}}}, st}; }); @@ -175,19 +115,6 @@ QodeAssistSettings::QodeAssistSettings() void QodeAssistSettings::setupConnections() { - connect(&useTopP, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - topP.setEnabled(useTopP.volatileValue()); - }); - connect(&useTopK, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - topK.setEnabled(useTopK.volatileValue()); - }); - connect(&usePresencePenalty, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - presencePenalty.setEnabled(usePresencePenalty.volatileValue()); - }); - connect(&useFrequencyPenalty, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - frequencyPenalty.setEnabled(useFrequencyPenalty.volatileValue()); - }); - connect(&resetToDefaults, &ButtonAspect::clicked, this, @@ -230,23 +157,23 @@ void QodeAssistSettings::resetSettingsToDefaults() // resetAspect(endPoint); // resetAspect(modelName); // resetAspect(fimPrompts); - resetAspect(temperature); - resetAspect(maxTokens); + // resetAspect(temperature); + // resetAspect(maxTokens); // resetAspect(readFullFile); // resetAspect(maxFileThreshold); // resetAspect(readStringsBeforeCursor); // resetAspect(readStringsAfterCursor); - resetAspect(useTopP); - resetAspect(topP); - resetAspect(useTopK); - resetAspect(topK); - resetAspect(usePresencePenalty); - resetAspect(presencePenalty); - resetAspect(useFrequencyPenalty); - resetAspect(frequencyPenalty); + // resetAspect(useTopP); + // resetAspect(topP); + // resetAspect(useTopK); + // resetAspect(topK); + // resetAspect(usePresencePenalty); + // resetAspect(presencePenalty); + // resetAspect(useFrequencyPenalty); + // resetAspect(frequencyPenalty); resetAspect(startSuggestionTimer); // resetAspect(enableLogging); - resetAspect(ollamaLivetime); + // resetAspect(ollamaLivetime); // resetAspect(specificInstractions); // resetAspect(multiLineCompletion); // resetAspect(useFilePathInContext); diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index 797e333..2323443 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -57,29 +57,11 @@ class QodeAssistSettings : public Utils::AspectContainer public: QodeAssistSettings(); - Utils::DoubleAspect temperature{this}; - Utils::IntegerAspect maxTokens{this}; - - Utils::BoolAspect useTopP{this}; - Utils::DoubleAspect topP{this}; - - Utils::BoolAspect useTopK{this}; - Utils::IntegerAspect topK{this}; - - Utils::BoolAspect usePresencePenalty{this}; - Utils::DoubleAspect presencePenalty{this}; - - Utils::BoolAspect useFrequencyPenalty{this}; - Utils::DoubleAspect frequencyPenalty{this}; - Utils::IntegerAspect startSuggestionTimer{this}; - Utils::StringAspect ollamaLivetime{this}; - Utils::StringAspect customJsonTemplate{this}; ButtonAspect saveCustomTemplateButton{this}; ButtonAspect loadCustomTemplateButton{this}; - Utils::StringAspect apiKey{this}; ButtonAspect resetToDefaults{this}; diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index ca00925..96cf058 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -28,6 +28,7 @@ #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" +#include "settings/PresetPromptsSettings.hpp" namespace QodeAssist::Providers { @@ -50,6 +51,7 @@ QString LMStudioProvider::completionEndpoint() const void LMStudioProvider::prepareRequest(QJsonObject &request) { + auto &settings = Settings::presetPromptsSettings(); const auto ¤tTemplate = PromptTemplateManager::instance().getCurrentTemplate(); if (currentTemplate->name() == "Custom Template") return; @@ -59,17 +61,17 @@ void LMStudioProvider::prepareRequest(QJsonObject &request) request["messages"] = std::move(messages); } - request["max_tokens"] = settings().maxTokens(); - request["temperature"] = settings().temperature(); + request["max_tokens"] = settings.maxTokens(); + request["temperature"] = settings.temperature(); request["stop"] = QJsonArray::fromStringList(currentTemplate->stopWords()); - if (settings().useTopP()) - request["top_p"] = settings().topP(); - if (settings().useTopK()) - request["top_k"] = settings().topK(); - if (settings().useFrequencyPenalty()) - request["frequency_penalty"] = settings().frequencyPenalty(); - if (settings().usePresencePenalty()) - request["presence_penalty"] = settings().presencePenalty(); + if (settings.useTopP()) + request["top_p"] = settings.topP(); + if (settings.useTopK()) + request["top_k"] = settings.topK(); + if (settings.useFrequencyPenalty()) + request["frequency_penalty"] = settings.frequencyPenalty(); + if (settings.usePresencePenalty()) + request["presence_penalty"] = settings.presencePenalty(); } bool LMStudioProvider::handleResponse(QNetworkReply *reply, QString &accumulatedResponse) diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index 9bbbf29..d3900d5 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -28,6 +28,7 @@ #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" +#include "settings/PresetPromptsSettings.hpp" namespace QodeAssist::Providers { @@ -50,23 +51,24 @@ QString OllamaProvider::completionEndpoint() const void OllamaProvider::prepareRequest(QJsonObject &request) { + auto &settings = Settings::presetPromptsSettings(); auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); if (currentTemplate->name() == "Custom Template") return; QJsonObject options; - options["num_predict"] = settings().maxTokens(); - options["keep_alive"] = settings().ollamaLivetime(); - options["temperature"] = settings().temperature(); + options["num_predict"] = settings.maxTokens(); + options["keep_alive"] = settings.ollamaLivetime(); + options["temperature"] = settings.temperature(); options["stop"] = QJsonArray::fromStringList(currentTemplate->stopWords()); - if (settings().useTopP()) - options["top_p"] = settings().topP(); - if (settings().useTopK()) - options["top_k"] = settings().topK(); - if (settings().useFrequencyPenalty()) - options["frequency_penalty"] = settings().frequencyPenalty(); - if (settings().usePresencePenalty()) - options["presence_penalty"] = settings().presencePenalty(); + if (settings.useTopP()) + options["top_p"] = settings.topP(); + if (settings.useTopK()) + options["top_k"] = settings.topK(); + if (settings.useFrequencyPenalty()) + options["frequency_penalty"] = settings.frequencyPenalty(); + if (settings.usePresencePenalty()) + options["presence_penalty"] = settings.presencePenalty(); request["options"] = options; } diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index b3641e1..d55ca45 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -26,6 +26,7 @@ #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" +#include "settings/PresetPromptsSettings.hpp" namespace QodeAssist::Providers { @@ -48,6 +49,7 @@ QString OpenAICompatProvider::completionEndpoint() const void OpenAICompatProvider::prepareRequest(QJsonObject &request) { + auto &settings = Settings::presetPromptsSettings(); const auto ¤tTemplate = PromptTemplateManager::instance().getCurrentTemplate(); if (currentTemplate->name() == "Custom Template") return; @@ -58,19 +60,19 @@ void OpenAICompatProvider::prepareRequest(QJsonObject &request) request["messages"] = std::move(messages); } - request["max_tokens"] = settings().maxTokens(); - request["temperature"] = settings().temperature(); + request["max_tokens"] = settings.maxTokens(); + request["temperature"] = settings.temperature(); request["stop"] = QJsonArray::fromStringList(currentTemplate->stopWords()); - if (settings().useTopP()) - request["top_p"] = settings().topP(); - if (settings().useTopK()) - request["top_k"] = settings().topK(); - if (settings().useFrequencyPenalty()) - request["frequency_penalty"] = settings().frequencyPenalty(); - if (settings().usePresencePenalty()) - request["presence_penalty"] = settings().presencePenalty(); + if (settings.useTopP()) + request["top_p"] = settings.topP(); + if (settings.useTopK()) + request["top_k"] = settings.topK(); + if (settings.useFrequencyPenalty()) + request["frequency_penalty"] = settings.frequencyPenalty(); + if (settings.usePresencePenalty()) + request["presence_penalty"] = settings.presencePenalty(); - const QString &apiKey = settings().apiKey.value(); + const QString &apiKey = settings.apiKey.value(); if (!apiKey.isEmpty()) { request["api_key"] = apiKey; } diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp index 35d5c91..89c8de5 100644 --- a/settings/PresetPromptsSettings.cpp +++ b/settings/PresetPromptsSettings.cpp @@ -19,7 +19,9 @@ #include "PresetPromptsSettings.hpp" +#include #include +#include #include #include "QodeAssistConstants.hpp" @@ -39,12 +41,133 @@ PresetPromptsSettings::PresetPromptsSettings() setDisplayName(Tr::tr("Preset Prompts Params")); + temperature.setSettingsKey(Constants::TEMPERATURE); + temperature.setLabelText(Tr::tr("Temperature:")); + temperature.setDefaultValue(0.2); + temperature.setRange(0.0, 10.0); + + ollamaLivetime.setSettingsKey(Constants::OLLAMA_LIVETIME); + ollamaLivetime.setLabelText( + Tr::tr("Time to suspend Ollama after completion request (in minutes), " + "Only Ollama, -1 to disable")); + ollamaLivetime.setDefaultValue("5m"); + ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + maxTokens.setSettingsKey(Constants::MAX_TOKENS); + maxTokens.setLabelText(Tr::tr("Max Tokens")); + maxTokens.setRange(-1, 10000); + maxTokens.setDefaultValue(150); + + useTopP.setSettingsKey(Constants::USE_TOP_P); + useTopP.setDefaultValue(false); + + topP.setSettingsKey(Constants::TOP_P); + topP.setLabelText(Tr::tr("top_p")); + topP.setDefaultValue(0.9); + topP.setRange(0.0, 1.0); + + useTopK.setSettingsKey(Constants::USE_TOP_K); + useTopK.setDefaultValue(false); + + topK.setSettingsKey(Constants::TOP_K); + topK.setLabelText(Tr::tr("top_k")); + topK.setDefaultValue(50); + topK.setRange(1, 1000); + + usePresencePenalty.setSettingsKey(Constants::USE_PRESENCE_PENALTY); + usePresencePenalty.setDefaultValue(false); + + presencePenalty.setSettingsKey(Constants::PRESENCE_PENALTY); + presencePenalty.setLabelText(Tr::tr("presence_penalty")); + presencePenalty.setDefaultValue(0.0); + presencePenalty.setRange(-2.0, 2.0); + + useFrequencyPenalty.setSettingsKey(Constants::USE_FREQUENCY_PENALTY); + useFrequencyPenalty.setDefaultValue(false); + + frequencyPenalty.setSettingsKey(Constants::FREQUENCY_PENALTY); + frequencyPenalty.setLabelText(Tr::tr("frequency_penalty")); + frequencyPenalty.setDefaultValue(0.0); + frequencyPenalty.setRange(-2.0, 2.0); + + apiKey.setSettingsKey(Constants::API_KEY); + apiKey.setLabelText(Tr::tr("API Key:")); + apiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + apiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); + + resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + + readSettings(); + + topK.setEnabled(useTopK()); + topP.setEnabled(useTopP()); + presencePenalty.setEnabled(usePresencePenalty()); + frequencyPenalty.setEnabled(useFrequencyPenalty()); + + setupConnections(); + setLayouter([this]() { using namespace Layouting; - return Column{Stretch{1}}; + return Column{Row{temperature, Stretch{1}, resetToDefaults}, + maxTokens, + Row{useTopP, topP, Stretch{1}}, + Row{useTopK, topK, Stretch{1}}, + Row{usePresencePenalty, presencePenalty, Stretch{1}}, + Row{useFrequencyPenalty, frequencyPenalty, Stretch{1}}, + apiKey, + Stretch{1}}; }); } +void PresetPromptsSettings::setupConnections() +{ + connect(&useTopP, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + topP.setEnabled(useTopP.volatileValue()); + }); + connect(&useTopK, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + topK.setEnabled(useTopK.volatileValue()); + }); + connect(&usePresencePenalty, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + presencePenalty.setEnabled(usePresencePenalty.volatileValue()); + }); + connect(&useFrequencyPenalty, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + frequencyPenalty.setEnabled(useFrequencyPenalty.volatileValue()); + }); + + connect(&resetToDefaults, + &ButtonAspect::clicked, + this, + &PresetPromptsSettings::resetSettingsToDefaults); +} + +void PresetPromptsSettings::resetSettingsToDefaults() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + Core::ICore::dialogParent(), + Tr::tr("Reset Settings"), + Tr::tr("Are you sure you want to reset all settings to default values?"), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + resetAspect(temperature); + resetAspect(maxTokens); + resetAspect(ollamaLivetime); + resetAspect(useTopP); + resetAspect(topP); + resetAspect(useTopK); + resetAspect(topK); + resetAspect(usePresencePenalty); + resetAspect(presencePenalty); + resetAspect(useFrequencyPenalty); + resetAspect(frequencyPenalty); + } + + QMessageBox::information(Core::ICore::dialogParent(), + Tr::tr("Settings Reset"), + Tr::tr("All settings have been reset to their default values.")); +} + class PresetPromptsSettingsPage : public Core::IOptionsPage { public: diff --git a/settings/PresetPromptsSettings.hpp b/settings/PresetPromptsSettings.hpp index 7f4e7c1..b953c4b 100644 --- a/settings/PresetPromptsSettings.hpp +++ b/settings/PresetPromptsSettings.hpp @@ -19,6 +19,7 @@ #pragma once +#include "settings/SettingsUtils.hpp" #include namespace QodeAssist::Settings { @@ -27,6 +28,30 @@ class PresetPromptsSettings : public Utils::AspectContainer { public: PresetPromptsSettings(); + + Utils::DoubleAspect temperature{this}; + Utils::IntegerAspect maxTokens{this}; + + Utils::BoolAspect useTopP{this}; + Utils::DoubleAspect topP{this}; + + Utils::BoolAspect useTopK{this}; + Utils::IntegerAspect topK{this}; + + Utils::BoolAspect usePresencePenalty{this}; + Utils::DoubleAspect presencePenalty{this}; + + Utils::BoolAspect useFrequencyPenalty{this}; + Utils::DoubleAspect frequencyPenalty{this}; + + Utils::StringAspect ollamaLivetime{this}; + Utils::StringAspect apiKey{this}; + + ButtonAspect resetToDefaults{this}; + +private: + void setupConnections(); + void resetSettingsToDefaults(); }; PresetPromptsSettings &presetPromptsSettings(); From 384e07ba627f0fd89fb8a9aff0de30d6942cea1d Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 00:18:23 +0200 Subject: [PATCH 08/14] Move suggestionTimer to general settings --- QodeAssistClient.cpp | 2 +- QodeAssistSettings.cpp | 7 +------ QodeAssistSettings.hpp | 2 -- settings/GeneralSettings.cpp | 7 +++++++ settings/GeneralSettings.hpp | 1 + 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index cfaf367..3a46793 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -145,7 +145,7 @@ void QodeAssistClient::scheduleRequest(TextEditor::TextEditorWidget *editor) } it.value()->setProperty("cursorPosition", editor->textCursor().position()); - it.value()->start(settings().startSuggestionTimer()); + it.value()->start(Settings::generalSettings().startSuggestionTimer()); } void QodeAssistClient::handleCompletions(const GetCompletionRequest::Response &response, diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index f6938ca..ac98392 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -45,11 +45,6 @@ QodeAssistSettings::QodeAssistSettings() { setAutoApply(false); - startSuggestionTimer.setSettingsKey(Constants::START_SUGGESTION_TIMER); - startSuggestionTimer.setLabelText(Tr::tr("Start Suggestion Timer:")); - startSuggestionTimer.setRange(10, 10000); - startSuggestionTimer.setDefaultValue(500); - resetToDefaults.m_buttonText = Tr::tr("Reset to Defaults"); customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); @@ -171,7 +166,7 @@ void QodeAssistSettings::resetSettingsToDefaults() // resetAspect(presencePenalty); // resetAspect(useFrequencyPenalty); // resetAspect(frequencyPenalty); - resetAspect(startSuggestionTimer); + // resetAspect(startSuggestionTimer); // resetAspect(enableLogging); // resetAspect(ollamaLivetime); // resetAspect(specificInstractions); diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index 2323443..eb7032c 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -57,8 +57,6 @@ class QodeAssistSettings : public Utils::AspectContainer public: QodeAssistSettings(); - Utils::IntegerAspect startSuggestionTimer{this}; - Utils::StringAspect customJsonTemplate{this}; ButtonAspect saveCustomTemplateButton{this}; ButtonAspect loadCustomTemplateButton{this}; diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index c701d1b..6b7167a 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -61,6 +61,11 @@ GeneralSettings::GeneralSettings() multiLineCompletion.setDefaultValue(true); multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion")); + startSuggestionTimer.setSettingsKey(Constants::START_SUGGESTION_TIMER); + startSuggestionTimer.setLabelText(Tr::tr("Start Suggestion Timer:")); + startSuggestionTimer.setRange(10, 10000); + startSuggestionTimer.setDefaultValue(500); + llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); llmProviders.setDisplayName(Tr::tr("LLM Providers:")); llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); @@ -115,6 +120,7 @@ GeneralSettings::GeneralSettings() auto rootLayout = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults}, enableAutoComplete, + startSuggestionTimer, multiLineCompletion, Space{8}, enableLogging, @@ -201,6 +207,7 @@ void GeneralSettings::resetPageToDefaults() resetAspect(modelName); resetAspect(fimPrompts); resetAspect(enableLogging); + resetAspect(startSuggestionTimer); } fimPrompts.setStringValue("StarCoder2"); diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index 3b57d4a..4014a74 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -34,6 +34,7 @@ public: Utils::BoolAspect enableAutoComplete{this}; Utils::BoolAspect multiLineCompletion{this}; Utils::BoolAspect enableLogging{this}; + Utils::IntegerAspect startSuggestionTimer{this}; Utils::SelectionAspect llmProviders{this}; Utils::StringAspect url{this}; From 314ba06db192f77bbee0a5a4039522cbc1c2296e Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 00:59:44 +0200 Subject: [PATCH 09/14] Move custom promt to settings page --- QodeAssistSettings.cpp | 145 +++++++++++------------------- QodeAssistSettings.hpp | 6 -- settings/CustomPromptSettings.cpp | 132 ++++++++++++++++++++++++++- settings/CustomPromptSettings.hpp | 13 +++ templates/CustomTemplate.hpp | 6 +- 5 files changed, 199 insertions(+), 103 deletions(-) diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index ac98392..85faa5c 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -45,47 +45,14 @@ QodeAssistSettings::QodeAssistSettings() { setAutoApply(false); - resetToDefaults.m_buttonText = Tr::tr("Reset to Defaults"); - - customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); - customJsonTemplate.setLabelText("Custom JSON Template:"); - customJsonTemplate.setDisplayStyle(Utils::StringAspect::TextEditDisplay); - customJsonTemplate.setDefaultValue(R"({ - "prompt": "{{QODE_INSTRUCTIONS}}{{QODE_PREFIX}}{{QODE_SUFFIX}}", - "options": { - "temperature": 0.7, - "top_p": 0.95, - "top_k": 40, - "num_predict": 100, - "stop": [ - "<|endoftext|>", - "", - "", - "", - "" - ], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "stream": true -})"); - - saveCustomTemplateButton.m_buttonText = (Tr::tr("Save Custom Template to JSON")); - loadCustomTemplateButton.m_buttonText = (Tr::tr("Load Custom Template from JSON")); - readSettings(); - customJsonTemplate.setVisible(PromptTemplateManager::instance().getCurrentTemplate()->name() - == "Custom Template"); - setLayouter([this]() { using namespace Layouting; return Column{Group{title(Tr::tr("FIM Prompt Settings")), - Form{Column{Column{customJsonTemplate, - Row{saveCustomTemplateButton, - loadCustomTemplateButton, - Stretch{1}}}, + Form{Column{Column{ + }, // readFullFile, // maxFileThreshold, // readStringsBeforeCursor, @@ -110,19 +77,7 @@ QodeAssistSettings::QodeAssistSettings() void QodeAssistSettings::setupConnections() { - connect(&resetToDefaults, - &ButtonAspect::clicked, - this, - &QodeAssistSettings::resetSettingsToDefaults); - connect(&saveCustomTemplateButton, - &ButtonAspect::clicked, - this, - &QodeAssistSettings::saveCustomTemplate); - connect(&loadCustomTemplateButton, - &ButtonAspect::clicked, - this, - &QodeAssistSettings::loadCustomTemplate); } QStringList QodeAssistSettings::getInstalledModels() @@ -173,7 +128,7 @@ void QodeAssistSettings::resetSettingsToDefaults() // resetAspect(multiLineCompletion); // resetAspect(useFilePathInContext); // resetAspect(useSpecificInstructions); - resetAspect(customJsonTemplate); + // resetAspect(customJsonTemplate); // fimPrompts.setStringValue("StarCoder2"); // llmProviders.setStringValue("Ollama"); @@ -188,60 +143,60 @@ void QodeAssistSettings::resetSettingsToDefaults() void QodeAssistSettings::saveCustomTemplate() { - QString fileName = QFileDialog::getSaveFileName(nullptr, - Tr::tr("Save JSON Template"), - QString(), - Tr::tr("JSON Files (*.json)")); - if (fileName.isEmpty()) - return; + // QString fileName = QFileDialog::getSaveFileName(nullptr, + // Tr::tr("Save JSON Template"), + // QString(), + // Tr::tr("JSON Files (*.json)")); + // if (fileName.isEmpty()) + // return; - QFile file(fileName); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QTextStream out(&file); - out << customJsonTemplate.value(); - file.close(); - QMessageBox::information(nullptr, - Tr::tr("Save Successful"), - Tr::tr("JSON template has been saved successfully.")); - } else { - QMessageBox::critical(nullptr, - Tr::tr("Save Failed"), - Tr::tr("Failed to save JSON template.")); - } + // QFile file(fileName); + // if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + // QTextStream out(&file); + // out << customJsonTemplate.value(); + // file.close(); + // QMessageBox::information(nullptr, + // Tr::tr("Save Successful"), + // Tr::tr("JSON template has been saved successfully.")); + // } else { + // QMessageBox::critical(nullptr, + // Tr::tr("Save Failed"), + // Tr::tr("Failed to save JSON template.")); + // } } void QodeAssistSettings::loadCustomTemplate() { - QString fileName = QFileDialog::getOpenFileName(nullptr, - Tr::tr("Load JSON Template"), - QString(), - Tr::tr("JSON Files (*.json)")); - if (fileName.isEmpty()) - return; + // QString fileName = QFileDialog::getOpenFileName(nullptr, + // Tr::tr("Load JSON Template"), + // QString(), + // Tr::tr("JSON Files (*.json)")); + // if (fileName.isEmpty()) + // return; - QFile file(fileName); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&file); - QString jsonContent = in.readAll(); - file.close(); + // QFile file(fileName); + // if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + // QTextStream in(&file); + // QString jsonContent = in.readAll(); + // file.close(); - QJsonParseError parseError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); - if (parseError.error == QJsonParseError::NoError) { - customJsonTemplate.setValue(jsonContent); - QMessageBox::information(nullptr, - Tr::tr("Load Successful"), - Tr::tr("JSON template has been loaded successfully.")); - } else { - QMessageBox::critical(nullptr, - Tr::tr("Invalid JSON"), - Tr::tr("The selected file contains invalid JSON.")); - } - } else { - QMessageBox::critical(nullptr, - Tr::tr("Load Failed"), - Tr::tr("Failed to load JSON template.")); - } + // QJsonParseError parseError; + // QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); + // if (parseError.error == QJsonParseError::NoError) { + // customJsonTemplate.setValue(jsonContent); + // QMessageBox::information(nullptr, + // Tr::tr("Load Successful"), + // Tr::tr("JSON template has been loaded successfully.")); + // } else { + // QMessageBox::critical(nullptr, + // Tr::tr("Invalid JSON"), + // Tr::tr("The selected file contains invalid JSON.")); + // } + // } else { + // QMessageBox::critical(nullptr, + // Tr::tr("Load Failed"), + // Tr::tr("Failed to load JSON template.")); + // } } class QodeAssistSettingsPage : public Core::IOptionsPage diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index eb7032c..753ea98 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -57,12 +57,6 @@ class QodeAssistSettings : public Utils::AspectContainer public: QodeAssistSettings(); - Utils::StringAspect customJsonTemplate{this}; - ButtonAspect saveCustomTemplateButton{this}; - ButtonAspect loadCustomTemplateButton{this}; - - ButtonAspect resetToDefaults{this}; - private: void setupConnections(); QStringList getInstalledModels(); diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp index aa64ca7..1c98b67 100644 --- a/settings/CustomPromptSettings.cpp +++ b/settings/CustomPromptSettings.cpp @@ -19,7 +19,11 @@ #include "CustomPromptSettings.hpp" +#include +#include +#include #include +#include #include #include "QodeAssistConstants.hpp" @@ -39,12 +43,138 @@ CustomPromptSettings::CustomPromptSettings() setDisplayName(Tr::tr("Custom Prompt")); + customJsonLabel.setLabelText("Custom JSON Template:"); + customJsonLabel.setDisplayStyle(Utils::StringAspect::LabelDisplay); + + customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); + customJsonTemplate.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + customJsonTemplate.setDefaultValue(R"({ + "prompt": "{{QODE_INSTRUCTIONS}}{{QODE_PREFIX}}{{QODE_SUFFIX}}", + "options": { + "temperature": 0.7, + "top_p": 0.95, + "top_k": 40, + "num_predict": 100, + "stop": [ + "<|endoftext|>", + "", + "", + "", + "" + ], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "stream": true +})"); + saveCustomTemplateButton.m_buttonText = (Tr::tr("Save Custom Template to JSON")); + loadCustomTemplateButton.m_buttonText = (Tr::tr("Load Custom Template from JSON")); + resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + + readSettings(); + + setupConnection(); + setLayouter([this]() { using namespace Layouting; - return Column{Stretch{1}}; + return Column{Row{customJsonLabel, Stretch{1}, resetToDefaults}, + Row{customJsonTemplate, + Column{saveCustomTemplateButton, loadCustomTemplateButton, Stretch{1}}}}; }); } +void CustomPromptSettings::setupConnection() +{ + connect(&resetToDefaults, + &ButtonAspect::clicked, + this, + &CustomPromptSettings::resetSettingsToDefaults); + connect(&saveCustomTemplateButton, + &ButtonAspect::clicked, + this, + &CustomPromptSettings::saveCustomTemplate); + connect(&loadCustomTemplateButton, + &ButtonAspect::clicked, + this, + &CustomPromptSettings::loadCustomTemplate); +} + +void CustomPromptSettings::resetSettingsToDefaults() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + Core::ICore::dialogParent(), + Tr::tr("Reset Settings"), + Tr::tr("Are you sure you want to reset all settings to default values?"), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + resetAspect(customJsonTemplate); + } + + QMessageBox::information(Core::ICore::dialogParent(), + Tr::tr("Settings Reset"), + Tr::tr("All settings have been reset to their default values.")); +} + +void CustomPromptSettings::saveCustomTemplate() +{ + QString fileName = QFileDialog::getSaveFileName(nullptr, + Tr::tr("Save JSON Template"), + QString(), + Tr::tr("JSON Files (*.json)")); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&file); + out << customJsonTemplate.value(); + file.close(); + QMessageBox::information(nullptr, + Tr::tr("Save Successful"), + Tr::tr("JSON template has been saved successfully.")); + } else { + QMessageBox::critical(nullptr, + Tr::tr("Save Failed"), + Tr::tr("Failed to save JSON template.")); + } +} + +void CustomPromptSettings::loadCustomTemplate() +{ + QString fileName = QFileDialog::getOpenFileName(nullptr, + Tr::tr("Load JSON Template"), + QString(), + Tr::tr("JSON Files (*.json)")); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + QString jsonContent = in.readAll(); + file.close(); + + QJsonParseError parseError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); + if (parseError.error == QJsonParseError::NoError) { + customJsonTemplate.setValue(jsonContent); + QMessageBox::information(nullptr, + Tr::tr("Load Successful"), + Tr::tr("JSON template has been loaded successfully.")); + } else { + QMessageBox::critical(nullptr, + Tr::tr("Invalid JSON"), + Tr::tr("The selected file contains invalid JSON.")); + } + } else { + QMessageBox::critical(nullptr, + Tr::tr("Load Failed"), + Tr::tr("Failed to load JSON template.")); + } +} + class CustomPromptSettingsPage : public Core::IOptionsPage { public: diff --git a/settings/CustomPromptSettings.hpp b/settings/CustomPromptSettings.hpp index 980b28d..0c83bda 100644 --- a/settings/CustomPromptSettings.hpp +++ b/settings/CustomPromptSettings.hpp @@ -19,6 +19,7 @@ #pragma once +#include "settings/SettingsUtils.hpp" #include namespace QodeAssist::Settings { @@ -27,6 +28,18 @@ class CustomPromptSettings : public Utils::AspectContainer { public: CustomPromptSettings(); + + Utils::StringAspect customJsonLabel{this}; + Utils::StringAspect customJsonTemplate{this}; + ButtonAspect saveCustomTemplateButton{this}; + ButtonAspect loadCustomTemplateButton{this}; + ButtonAspect resetToDefaults{this}; + +private: + void setupConnection(); + void resetSettingsToDefaults(); + void saveCustomTemplate(); + void loadCustomTemplate(); }; CustomPromptSettings &customPromptSettings(); diff --git a/templates/CustomTemplate.hpp b/templates/CustomTemplate.hpp index ac4173c..0c41824 100644 --- a/templates/CustomTemplate.hpp +++ b/templates/CustomTemplate.hpp @@ -26,6 +26,7 @@ #include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" +#include "settings/CustomPromptSettings.hpp" namespace QodeAssist::Templates { @@ -33,7 +34,10 @@ class CustomTemplate : public PromptTemplate { public: QString name() const override { return "Custom Template"; } - QString promptTemplate() const override { return settings().customJsonTemplate(); } + QString promptTemplate() const override + { + return Settings::customPromptSettings().customJsonTemplate(); + } QStringList stopWords() const override { return QStringList(); } void prepareRequest(QJsonObject &request, const ContextData &context) const override From f64ea420711268d028cf4db3636df2e94ca67997 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 01:07:39 +0200 Subject: [PATCH 10/14] Remove origin qodesettings --- CMakeLists.txt | 1 - DocumentContextReader.cpp | 1 - LLMClientInterface.cpp | 1 - QodeAssistClient.cpp | 1 - QodeAssistSettings.cpp | 218 ----------------------------- QodeAssistSettings.hpp | 71 ---------- providers/LMStudioProvider.cpp | 1 - providers/OllamaProvider.cpp | 1 - providers/OpenAICompatProvider.cpp | 1 - templates/CustomTemplate.hpp | 1 - 10 files changed, 297 deletions(-) delete mode 100644 QodeAssistSettings.cpp delete mode 100644 QodeAssistSettings.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fe51fc1..343e53c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,6 @@ add_qtc_plugin(QodeAssist providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp providers/OpenAICompatProvider.hpp providers/OpenAICompatProvider.cpp LLMProvidersManager.hpp LLMProvidersManager.cpp - QodeAssistSettings.hpp QodeAssistSettings.cpp QodeAssist.qrc LSPCompletion.hpp LLMSuggestion.hpp LLMSuggestion.cpp diff --git a/DocumentContextReader.cpp b/DocumentContextReader.cpp index b8d8fad..063162b 100644 --- a/DocumentContextReader.cpp +++ b/DocumentContextReader.cpp @@ -23,7 +23,6 @@ #include #include -#include "QodeAssistSettings.hpp" #include "settings/ContextSettings.hpp" const QRegularExpression &getYearRegex() diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 217f3b8..a473ac1 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -28,7 +28,6 @@ #include "DocumentContextReader.hpp" #include "LLMProvidersManager.hpp" #include "PromptTemplateManager.hpp" -#include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" #include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index 3a46793..34cea5e 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -31,7 +31,6 @@ #include "LLMClientInterface.hpp" #include "LLMSuggestion.hpp" -#include "QodeAssistSettings.hpp" #include "settings/GeneralSettings.hpp" using namespace LanguageServerProtocol; diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp deleted file mode 100644 index 85faa5c..0000000 --- a/QodeAssistSettings.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2024 Petr Mironychev - * - * This file is part of QodeAssist. - * - * QodeAssist is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * QodeAssist is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with QodeAssist. If not, see . - */ - -#include "QodeAssistSettings.hpp" - -#include -#include -#include -#include -#include -#include - -#include "QodeAssistConstants.hpp" -#include "QodeAssisttr.h" - -#include "LLMProvidersManager.hpp" -#include "PromptTemplateManager.hpp" -#include "QodeAssistUtils.hpp" - -namespace QodeAssist { - -QodeAssistSettings &settings() -{ - static QodeAssistSettings settings; - return settings; -} - -QodeAssistSettings::QodeAssistSettings() -{ - setAutoApply(false); - - readSettings(); - - setLayouter([this]() { - using namespace Layouting; - - return Column{Group{title(Tr::tr("FIM Prompt Settings")), - Form{Column{Column{ - }, - // readFullFile, - // maxFileThreshold, - // readStringsBeforeCursor, - // readStringsAfterCursor, - // ollamaLivetime, - // apiKey, - // useFilePathInContext, - // useSpecificInstructions, - // specificInstractions, - // temperature, - // maxTokens, - // startSuggestionTimer, - // Row{useTopP, topP, Stretch{1}}, - // Row{useTopK, topK, Stretch{1}}, -/* Row{usePresencePenalty, presencePenalty, Stretch{1}}, - Row{useFrequencyPenalty, frequencyPenalty, Stretch{1}}*/}}}, - st}; - }); - - setupConnections(); -} - -void QodeAssistSettings::setupConnections() -{ - -} - -QStringList QodeAssistSettings::getInstalledModels() -{ - auto *provider = LLMProvidersManager::instance().getCurrentProvider(); - if (provider) { - Utils::Environment env = Utils::Environment::systemEnvironment(); - return provider->getInstalledModels(env); - } - return {}; -} - -void QodeAssistSettings::resetSettingsToDefaults() -{ - QMessageBox::StandardButton reply; - reply = QMessageBox::question( - Core::ICore::dialogParent(), - Tr::tr("Reset Settings"), - Tr::tr("Are you sure you want to reset all settings to default values?"), - QMessageBox::Yes | QMessageBox::No); - - if (reply == QMessageBox::Yes) { - // resetAspect(enableQodeAssist); - // resetAspect(enableAutoComplete); - // resetAspect(llmProviders); - // resetAspect(url); - // resetAspect(endPoint); - // resetAspect(modelName); - // resetAspect(fimPrompts); - // resetAspect(temperature); - // resetAspect(maxTokens); - // resetAspect(readFullFile); - // resetAspect(maxFileThreshold); - // resetAspect(readStringsBeforeCursor); - // resetAspect(readStringsAfterCursor); - // resetAspect(useTopP); - // resetAspect(topP); - // resetAspect(useTopK); - // resetAspect(topK); - // resetAspect(usePresencePenalty); - // resetAspect(presencePenalty); - // resetAspect(useFrequencyPenalty); - // resetAspect(frequencyPenalty); - // resetAspect(startSuggestionTimer); - // resetAspect(enableLogging); - // resetAspect(ollamaLivetime); - // resetAspect(specificInstractions); - // resetAspect(multiLineCompletion); - // resetAspect(useFilePathInContext); - // resetAspect(useSpecificInstructions); - // resetAspect(customJsonTemplate); - - // fimPrompts.setStringValue("StarCoder2"); - // llmProviders.setStringValue("Ollama"); - - apply(); - - QMessageBox::information(Core::ICore::dialogParent(), - Tr::tr("Settings Reset"), - Tr::tr("All settings have been reset to their default values.")); - } -} - -void QodeAssistSettings::saveCustomTemplate() -{ - // QString fileName = QFileDialog::getSaveFileName(nullptr, - // Tr::tr("Save JSON Template"), - // QString(), - // Tr::tr("JSON Files (*.json)")); - // if (fileName.isEmpty()) - // return; - - // QFile file(fileName); - // if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - // QTextStream out(&file); - // out << customJsonTemplate.value(); - // file.close(); - // QMessageBox::information(nullptr, - // Tr::tr("Save Successful"), - // Tr::tr("JSON template has been saved successfully.")); - // } else { - // QMessageBox::critical(nullptr, - // Tr::tr("Save Failed"), - // Tr::tr("Failed to save JSON template.")); - // } -} - -void QodeAssistSettings::loadCustomTemplate() -{ - // QString fileName = QFileDialog::getOpenFileName(nullptr, - // Tr::tr("Load JSON Template"), - // QString(), - // Tr::tr("JSON Files (*.json)")); - // if (fileName.isEmpty()) - // return; - - // QFile file(fileName); - // if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - // QTextStream in(&file); - // QString jsonContent = in.readAll(); - // file.close(); - - // QJsonParseError parseError; - // QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); - // if (parseError.error == QJsonParseError::NoError) { - // customJsonTemplate.setValue(jsonContent); - // QMessageBox::information(nullptr, - // Tr::tr("Load Successful"), - // Tr::tr("JSON template has been loaded successfully.")); - // } else { - // QMessageBox::critical(nullptr, - // Tr::tr("Invalid JSON"), - // Tr::tr("The selected file contains invalid JSON.")); - // } - // } else { - // QMessageBox::critical(nullptr, - // Tr::tr("Load Failed"), - // Tr::tr("Failed to load JSON template.")); - // } -} - -class QodeAssistSettingsPage : public Core::IOptionsPage -{ -public: - QodeAssistSettingsPage() - { - setId(Constants::QODE_ASSIST_GENERAL_OPTIONS_ID); - setDisplayName("Qode Assist"); - setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); - setDisplayCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY); - setCategoryIconPath(":/resources/images/qoderassist-icon.png"); - setSettingsProvider([] { return &settings(); }); - } -}; - -const QodeAssistSettingsPage settingsPage; - -} // namespace QodeAssist diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp deleted file mode 100644 index 753ea98..0000000 --- a/QodeAssistSettings.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2024 Petr Mironychev - * - * This file is part of QodeAssist. - * - * QodeAssist is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * QodeAssist is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with QodeAssist. If not, see . - */ - -#pragma once - -#include -#include -#include - -namespace QodeAssist { - -template -void resetAspect(AspectType &aspect) -{ - aspect.setValue(aspect.defaultValue()); -} - -class ButtonAspect : public Utils::BaseAspect -{ - Q_OBJECT - -public: - ButtonAspect(Utils::AspectContainer *container = nullptr) - : Utils::BaseAspect(container) - {} - - void addToLayout(Layouting::Layout &parent) override - { - auto button = new QPushButton(m_buttonText); - connect(button, &QPushButton::clicked, this, &ButtonAspect::clicked); - parent.addItem(button); - } - - QString m_buttonText; -signals: - void clicked(); -}; - -class QodeAssistSettings : public Utils::AspectContainer -{ -public: - QodeAssistSettings(); - -private: - void setupConnections(); - QStringList getInstalledModels(); - Utils::Environment getEnvironmentWithProviderPaths() const; - void resetSettingsToDefaults(); - void saveCustomTemplate(); - void loadCustomTemplate(); -}; - -QodeAssistSettings &settings(); - -} // namespace QodeAssist diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index 96cf058..dba91bc 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -26,7 +26,6 @@ #include #include "PromptTemplateManager.hpp" -#include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" #include "settings/PresetPromptsSettings.hpp" diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index d3900d5..ab9a1ce 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -26,7 +26,6 @@ #include #include "PromptTemplateManager.hpp" -#include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" #include "settings/PresetPromptsSettings.hpp" diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index d55ca45..6214678 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -25,7 +25,6 @@ #include #include "PromptTemplateManager.hpp" -#include "QodeAssistSettings.hpp" #include "settings/PresetPromptsSettings.hpp" namespace QodeAssist::Providers { diff --git a/templates/CustomTemplate.hpp b/templates/CustomTemplate.hpp index 0c41824..5ae2e24 100644 --- a/templates/CustomTemplate.hpp +++ b/templates/CustomTemplate.hpp @@ -24,7 +24,6 @@ #include #include -#include "QodeAssistSettings.hpp" #include "QodeAssistUtils.hpp" #include "settings/CustomPromptSettings.hpp" From 216c28aa5e51c2c13028a81a68c8b5f4d4db8623 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 01:42:23 +0200 Subject: [PATCH 11/14] Fix names, icon and tips --- settings/ContextSettings.cpp | 2 ++ settings/CustomPromptSettings.cpp | 12 +++++++++++- settings/CustomPromptSettings.hpp | 1 + settings/GeneralSettings.cpp | 8 ++++---- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index 1f2ae76..f9af061 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -137,6 +137,8 @@ public: setId(Constants::QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID); setDisplayName(Tr::tr("Context")); setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setDisplayCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY); + setCategoryIconPath(":/resources/images/qoderassist-icon.png"); setSettingsProvider([] { return &contextSettings(); }); } }; diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp index 1c98b67..c938a2f 100644 --- a/settings/CustomPromptSettings.cpp +++ b/settings/CustomPromptSettings.cpp @@ -46,8 +46,15 @@ CustomPromptSettings::CustomPromptSettings() customJsonLabel.setLabelText("Custom JSON Template:"); customJsonLabel.setDisplayStyle(Utils::StringAspect::LabelDisplay); + customJsonLegend.setLabelText(Tr::tr(R"(Prompt components: +- {{QODE_INSTRUCTIONS}}: Placeholder for specific instructions or context. +- {{QODE_PREFIX}}: Will be replaced with the actual code before the cursor. +- {{QODE_SUFFIX}}: Will be replaced with the actual code after the cursor. +)")); + customJsonTemplate.setSettingsKey(Constants::CUSTOM_JSON_TEMPLATE); customJsonTemplate.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + customJsonTemplate.setDefaultValue(R"({ "prompt": "{{QODE_INSTRUCTIONS}}{{QODE_PREFIX}}{{QODE_SUFFIX}}", "options": { @@ -79,7 +86,10 @@ CustomPromptSettings::CustomPromptSettings() using namespace Layouting; return Column{Row{customJsonLabel, Stretch{1}, resetToDefaults}, Row{customJsonTemplate, - Column{saveCustomTemplateButton, loadCustomTemplateButton, Stretch{1}}}}; + Column{saveCustomTemplateButton, + loadCustomTemplateButton, + customJsonLegend, + Stretch{1}}}}; }); } diff --git a/settings/CustomPromptSettings.hpp b/settings/CustomPromptSettings.hpp index 0c83bda..7ff0515 100644 --- a/settings/CustomPromptSettings.hpp +++ b/settings/CustomPromptSettings.hpp @@ -31,6 +31,7 @@ public: Utils::StringAspect customJsonLabel{this}; Utils::StringAspect customJsonTemplate{this}; + Utils::StringAspect customJsonLegend{this}; ButtonAspect saveCustomTemplateButton{this}; ButtonAspect loadCustomTemplateButton{this}; ButtonAspect resetToDefaults{this}; diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 6b7167a..8b4eff0 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -67,7 +67,7 @@ GeneralSettings::GeneralSettings() startSuggestionTimer.setDefaultValue(500); llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); - llmProviders.setDisplayName(Tr::tr("LLM Providers:")); + llmProviders.setDisplayName(Tr::tr("FIM Provider:")); llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); llmProviders.setDefaultValue(0); @@ -76,16 +76,16 @@ GeneralSettings::GeneralSettings() url.setDisplayStyle(Utils::StringAspect::LineEditDisplay); endPoint.setSettingsKey(Constants::END_POINT); - endPoint.setLabelText(Tr::tr("Endpoint:")); + endPoint.setLabelText(Tr::tr("FIM Endpoint:")); endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); modelName.setSettingsKey(Constants::MODEL_NAME); modelName.setLabelText(Tr::tr("LLM Name:")); modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - selectModels.m_buttonText = Tr::tr("Select Model"); + selectModels.m_buttonText = Tr::tr("Select Fill-In-the-Middle Model"); - fimPrompts.setDisplayName(Tr::tr("Fill-In-Middle Prompt")); + fimPrompts.setDisplayName(Tr::tr("Fill-In-the-Middle Prompt")); fimPrompts.setSettingsKey(Constants::FIM_PROMPTS); fimPrompts.setDefaultValue(0); fimPrompts.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); From 24ad5fd01589d044de3f6b54e7ebf8e770e015d0 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 01:47:17 +0200 Subject: [PATCH 12/14] Fix saving template after closing qtc --- settings/CustomPromptSettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp index c938a2f..74ae7f9 100644 --- a/settings/CustomPromptSettings.cpp +++ b/settings/CustomPromptSettings.cpp @@ -169,7 +169,7 @@ void CustomPromptSettings::loadCustomTemplate() QJsonParseError parseError; QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonContent.toUtf8(), &parseError); if (parseError.error == QJsonParseError::NoError) { - customJsonTemplate.setValue(jsonContent); + customJsonTemplate.setVolatileValue(jsonContent); QMessageBox::information(nullptr, Tr::tr("Load Successful"), Tr::tr("JSON template has been loaded successfully.")); From 15af137728a3a38c22e39fa0ccf8be3ca3b9a908 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 02:25:21 +0200 Subject: [PATCH 13/14] Add examples of customs request --- CMakeLists.txt | 1 - qodeassist.cpp | 2 - rawPromptExamples/OllamaStarCoder2FIM.json | 19 ++++++++++ rawPromptExamples/OpenAICodeqwenChat.json | 16 ++++++++ settings/CustomPromptSettings.cpp | 1 + templates/CodeQwenChat.hpp | 44 ---------------------- 6 files changed, 36 insertions(+), 47 deletions(-) create mode 100644 rawPromptExamples/OllamaStarCoder2FIM.json create mode 100644 rawPromptExamples/OpenAICodeqwenChat.json delete mode 100644 templates/CodeQwenChat.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 343e53c..9e98f4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,6 @@ add_qtc_plugin(QodeAssist templates/PromptTemplate.hpp templates/CodeLLamaTemplate.hpp templates/StarCoder2Template.hpp - templates/CodeQwenChat.hpp templates/DeepSeekCoderV2.hpp templates/CustomTemplate.hpp providers/LLMProvider.hpp diff --git a/qodeassist.cpp b/qodeassist.cpp index 43ed118..a679547 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -45,7 +45,6 @@ #include "providers/OllamaProvider.hpp" #include "providers/OpenAICompatProvider.hpp" #include "templates/CodeLLamaTemplate.hpp" -#include "templates/CodeQwenChat.hpp" #include "templates/CustomTemplate.hpp" #include "templates/DeepSeekCoderV2.hpp" #include "templates/StarCoder2Template.hpp" @@ -81,7 +80,6 @@ public: auto &templateManager = PromptTemplateManager::instance(); templateManager.registerTemplate(); templateManager.registerTemplate(); - templateManager.registerTemplate(); templateManager.registerTemplate(); templateManager.registerTemplate(); diff --git a/rawPromptExamples/OllamaStarCoder2FIM.json b/rawPromptExamples/OllamaStarCoder2FIM.json new file mode 100644 index 0000000..7ce65cc --- /dev/null +++ b/rawPromptExamples/OllamaStarCoder2FIM.json @@ -0,0 +1,19 @@ +{ + "prompt": "{{QODE_INSTRUCTIONS}}{{QODE_PREFIX}}{{QODE_SUFFIX}}", + "options": { + "temperature": 0.7, + "top_p": 0.95, + "top_k": 40, + "num_predict": 175, + "stop": [ + "<|endoftext|>", + "", + "", + "", + "" + ], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "stream": true +} \ No newline at end of file diff --git a/rawPromptExamples/OpenAICodeqwenChat.json b/rawPromptExamples/OpenAICodeqwenChat.json new file mode 100644 index 0000000..6ff0546 --- /dev/null +++ b/rawPromptExamples/OpenAICodeqwenChat.json @@ -0,0 +1,16 @@ +{ + "max_tokens": 150, + "messages": [ + { + "content": "{{QODE_INSTRUCTIONS}}\n### Instruction:{{QODE_PREFIX}}{{QODE_SUFFIX}} ### Response:\n", + "role": "user" + } + ], + "stop": [ + "### Instruction:", + "### Response:", + "\n\n### " + ], + "stream": true, + "temperature": 0.2 +} \ No newline at end of file diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp index 74ae7f9..ee5ad78 100644 --- a/settings/CustomPromptSettings.cpp +++ b/settings/CustomPromptSettings.cpp @@ -47,6 +47,7 @@ CustomPromptSettings::CustomPromptSettings() customJsonLabel.setDisplayStyle(Utils::StringAspect::LabelDisplay); customJsonLegend.setLabelText(Tr::tr(R"(Prompt components: +- model is set on General Page - {{QODE_INSTRUCTIONS}}: Placeholder for specific instructions or context. - {{QODE_PREFIX}}: Will be replaced with the actual code before the cursor. - {{QODE_SUFFIX}}: Will be replaced with the actual code after the cursor. diff --git a/templates/CodeQwenChat.hpp b/templates/CodeQwenChat.hpp deleted file mode 100644 index dfae27e..0000000 --- a/templates/CodeQwenChat.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2024 Petr Mironychev - * - * This file is part of QodeAssist. - * - * QodeAssist is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * QodeAssist is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with QodeAssist. If not, see . - */ - -#pragma once - -#include "PromptTemplate.hpp" - -namespace QodeAssist::Templates { - -class CodeQwenChatTemplate : public PromptTemplate -{ -public: - QString name() const override { return "CodeQwenChat (experimental)"; } - QString promptTemplate() const override { return "%1\n### Instruction:%2%3 ### Response:\n"; } - QStringList stopWords() const override - { - return QStringList() << "### Instruction:" << "### Response:" << "\n\n### "; - } - void prepareRequest(QJsonObject &request, const ContextData &context) const override - { - QString formattedPrompt = promptTemplate().arg(context.instriuctions, - context.prefix, - context.suffix); - request["prompt"] = formattedPrompt; - } -}; - -} // namespace QodeAssist::Templates From 9361c27d6e52ef504bfc183a9c58d125e2f209ef Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 8 Sep 2024 02:51:56 +0200 Subject: [PATCH 14/14] Add smart trigger for call suggestion --- QodeAssistClient.cpp | 20 +++++++++++++++++--- QodeAssistClient.hpp | 3 +++ QodeAssistConstants.hpp | 2 ++ settings/GeneralSettings.cpp | 22 ++++++++++++++++++++++ settings/GeneralSettings.hpp | 2 ++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index 34cea5e..d8593ec 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -43,6 +43,7 @@ namespace QodeAssist { QodeAssistClient::QodeAssistClient() : LanguageClient::Client(new LLMClientInterface()) + , m_recentCharCount(0) { setName("Qode Assist"); LanguageClient::LanguageFilter filter; @@ -51,6 +52,8 @@ QodeAssistClient::QodeAssistClient() start(); setupConnections(); + + m_typingTimer.start(); } QodeAssistClient::~QodeAssistClient() @@ -86,7 +89,18 @@ void QodeAssistClient::openDocument(TextEditor::TextDocument *document) const int cursorPosition = widget->textCursor().position(); if (cursorPosition < position || cursorPosition > position + charsAdded) return; - scheduleRequest(widget); + + m_recentCharCount += charsAdded; + + if (m_typingTimer.elapsed() + > Settings::generalSettings().autoCompletionTypingInterval()) { + m_recentCharCount = charsAdded; + m_typingTimer.restart(); + } + + if (m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) { + scheduleRequest(widget); + } }); } @@ -130,7 +144,8 @@ void QodeAssistClient::scheduleRequest(TextEditor::TextEditorWidget *editor) connect(timer, &QTimer::timeout, this, [this, editor]() { if (editor && editor->textCursor().position() - == m_scheduledRequests[editor]->property("cursorPosition").toInt()) + == m_scheduledRequests[editor]->property("cursorPosition").toInt() + && m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) requestCompletions(editor); }); connect(editor, &TextEditorWidget::destroyed, this, [this, editor]() { @@ -146,7 +161,6 @@ void QodeAssistClient::scheduleRequest(TextEditor::TextEditorWidget *editor) it.value()->setProperty("cursorPosition", editor->textCursor().position()); it.value()->start(Settings::generalSettings().startSuggestionTimer()); } - void QodeAssistClient::handleCompletions(const GetCompletionRequest::Response &response, TextEditor::TextEditorWidget *editor) { diff --git a/QodeAssistClient.hpp b/QodeAssistClient.hpp index 0271839..2605b26 100644 --- a/QodeAssistClient.hpp +++ b/QodeAssistClient.hpp @@ -55,6 +55,9 @@ private: QHash m_scheduledRequests; QMetaObject::Connection m_documentOpenedConnection; QMetaObject::Connection m_documentClosedConnection; + + QElapsedTimer m_typingTimer; + int m_recentCharCount; }; } // namespace QodeAssist diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp index 65a4029..774bdca 100644 --- a/QodeAssistConstants.hpp +++ b/QodeAssistConstants.hpp @@ -49,6 +49,8 @@ const char USE_FREQUENCY_PENALTY[] = "QodeAssist.useFrequencyPenalty"; const char FREQUENCY_PENALTY[] = "QodeAssist.frequencyPenalty"; const char PROVIDER_PATHS[] = "QodeAssist.providerPaths"; const char START_SUGGESTION_TIMER[] = "QodeAssist.startSuggestionTimer"; +const char AUTO_COMPLETION_CHAR_THRESHOLD[] = "QodeAssist.autoCompletionCharThreshold"; +const char AUTO_COMPLETION_TYPING_INTERVAL[] = "QodeAssist.autoCompletionTypingInterval"; const char MAX_FILE_THRESHOLD[] = "QodeAssist.maxFileThreshold"; const char OLLAMA_LIVETIME[] = "QodeAssist.ollamaLivetime"; const char SPECIFIC_INSTRUCTIONS[] = "QodeAssist.specificInstractions"; diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 8b4eff0..0edb0b0 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -66,6 +66,24 @@ GeneralSettings::GeneralSettings() startSuggestionTimer.setRange(10, 10000); startSuggestionTimer.setDefaultValue(500); + autoCompletionCharThreshold.setSettingsKey(Constants::AUTO_COMPLETION_CHAR_THRESHOLD); + autoCompletionCharThreshold.setLabelText( + Tr::tr("Character threshold for AI suggestion start:")); + autoCompletionCharThreshold.setToolTip( + Tr::tr("The number of characters that need to be typed within the typing interval " + "before an AI suggestion request is sent.")); + autoCompletionCharThreshold.setRange(1, 10); + autoCompletionCharThreshold.setDefaultValue(2); + + autoCompletionTypingInterval.setSettingsKey(Constants::AUTO_COMPLETION_TYPING_INTERVAL); + autoCompletionTypingInterval.setLabelText( + Tr::tr("Typing interval for AI suggestion start(ms):")); + autoCompletionTypingInterval.setToolTip( + Tr::tr("The time window (in milliseconds) during which the character threshold " + "must be met to trigger an AI suggestion request.")); + autoCompletionTypingInterval.setRange(500, 5000); + autoCompletionTypingInterval.setDefaultValue(2000); + llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); llmProviders.setDisplayName(Tr::tr("FIM Provider:")); llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); @@ -121,6 +139,8 @@ GeneralSettings::GeneralSettings() auto rootLayout = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults}, enableAutoComplete, startSuggestionTimer, + autoCompletionCharThreshold, + autoCompletionTypingInterval, multiLineCompletion, Space{8}, enableLogging, @@ -208,6 +228,8 @@ void GeneralSettings::resetPageToDefaults() resetAspect(fimPrompts); resetAspect(enableLogging); resetAspect(startSuggestionTimer); + resetAspect(autoCompletionTypingInterval); + resetAspect(autoCompletionCharThreshold); } fimPrompts.setStringValue("StarCoder2"); diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index 4014a74..d82da9c 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -35,6 +35,8 @@ public: Utils::BoolAspect multiLineCompletion{this}; Utils::BoolAspect enableLogging{this}; Utils::IntegerAspect startSuggestionTimer{this}; + Utils::IntegerAspect autoCompletionCharThreshold{this}; + Utils::IntegerAspect autoCompletionTypingInterval{this}; Utils::SelectionAspect llmProviders{this}; Utils::StringAspect url{this};