From 1ec60982101ddb987161e8a77aef597e83ba42bc Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 10 Nov 2024 18:56:57 +0100 Subject: [PATCH 1/8] Move ButtonAspect --- settings/ButtonAspect.hpp | 45 ++++++++++++++++++++++++++++++ settings/CMakeLists.txt | 2 ++ settings/ContextSettings.cpp | 2 ++ settings/ContextSettings.hpp | 2 +- settings/CustomPromptSettings.cpp | 2 ++ settings/CustomPromptSettings.hpp | 3 +- settings/GeneralSettings.cpp | 1 + settings/GeneralSettings.hpp | 2 +- settings/PresetPromptsSettings.cpp | 2 ++ settings/PresetPromptsSettings.hpp | 3 +- settings/SettingsTr.hpp | 31 ++++++++++++++++++++ settings/SettingsUtils.hpp | 26 ----------------- 12 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 settings/ButtonAspect.hpp create mode 100644 settings/SettingsTr.hpp diff --git a/settings/ButtonAspect.hpp b/settings/ButtonAspect.hpp new file mode 100644 index 0000000..100ff6a --- /dev/null +++ b/settings/ButtonAspect.hpp @@ -0,0 +1,45 @@ +/* + * 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 + +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(); +}; diff --git a/settings/CMakeLists.txt b/settings/CMakeLists.txt index e885f4b..882cc76 100644 --- a/settings/CMakeLists.txt +++ b/settings/CMakeLists.txt @@ -5,6 +5,8 @@ add_library(QodeAssistSettings STATIC PresetPromptsSettings.hpp PresetPromptsSettings.cpp SettingsUtils.hpp SettingsConstants.hpp + ButtonAspect.hpp + SettingsTr.hpp ) target_link_libraries(QodeAssistSettings diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index b18f757..d861f03 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -25,6 +25,8 @@ #include #include "SettingsConstants.hpp" +#include "SettingsTr.hpp" +#include "SettingsUtils.hpp" namespace QodeAssist::Settings { ContextSettings &contextSettings() diff --git a/settings/ContextSettings.hpp b/settings/ContextSettings.hpp index 83c8630..e207af0 100644 --- a/settings/ContextSettings.hpp +++ b/settings/ContextSettings.hpp @@ -21,7 +21,7 @@ #include -#include "SettingsUtils.hpp" +#include "ButtonAspect.hpp" namespace QodeAssist::Settings { diff --git a/settings/CustomPromptSettings.cpp b/settings/CustomPromptSettings.cpp index c2b2f12..584ce6b 100644 --- a/settings/CustomPromptSettings.cpp +++ b/settings/CustomPromptSettings.cpp @@ -27,6 +27,8 @@ #include #include "SettingsConstants.hpp" +#include "SettingsTr.hpp" +#include "SettingsUtils.hpp" namespace QodeAssist::Settings { diff --git a/settings/CustomPromptSettings.hpp b/settings/CustomPromptSettings.hpp index 18780ac..0f679ae 100644 --- a/settings/CustomPromptSettings.hpp +++ b/settings/CustomPromptSettings.hpp @@ -19,9 +19,10 @@ #pragma once -#include "SettingsUtils.hpp" #include +#include "ButtonAspect.hpp" + namespace QodeAssist::Settings { class CustomPromptSettings : public Utils::AspectContainer diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index fc54e1c..1c64d87 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -31,6 +31,7 @@ #include "Provider.hpp" #include "ProvidersManager.hpp" #include "SettingsConstants.hpp" +#include "SettingsTr.hpp" #include "SettingsUtils.hpp" namespace QodeAssist::Settings { diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index 392eca8..6584659 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -21,7 +21,7 @@ #include -#include "SettingsUtils.hpp" +#include "ButtonAspect.hpp" namespace QodeAssist::LLMCore { class Provider; diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp index cc6af09..861dd1a 100644 --- a/settings/PresetPromptsSettings.cpp +++ b/settings/PresetPromptsSettings.cpp @@ -26,6 +26,8 @@ #include "RequestType.hpp" #include "SettingsConstants.hpp" +#include "SettingsTr.hpp" +#include "SettingsUtils.hpp" namespace QodeAssist::Settings { diff --git a/settings/PresetPromptsSettings.hpp b/settings/PresetPromptsSettings.hpp index bf0386a..9cae0f1 100644 --- a/settings/PresetPromptsSettings.hpp +++ b/settings/PresetPromptsSettings.hpp @@ -19,9 +19,10 @@ #pragma once -#include "SettingsUtils.hpp" #include +#include "ButtonAspect.hpp" + namespace QodeAssist::Settings { class PresetPromptsSettings : public Utils::AspectContainer diff --git a/settings/SettingsTr.hpp b/settings/SettingsTr.hpp new file mode 100644 index 0000000..ec2b40f --- /dev/null +++ b/settings/SettingsTr.hpp @@ -0,0 +1,31 @@ +/* + * 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 { + +struct Tr +{ + Q_DECLARE_TR_FUNCTIONS(QtC::QodeAssist) +}; + +} // namespace QodeAssist::Settings diff --git a/settings/SettingsUtils.hpp b/settings/SettingsUtils.hpp index 6ff07bf..2761ec2 100644 --- a/settings/SettingsUtils.hpp +++ b/settings/SettingsUtils.hpp @@ -29,11 +29,6 @@ namespace QodeAssist::Settings { -struct Tr -{ - Q_DECLARE_TR_FUNCTIONS(QtC::QodeAssist) -}; - inline bool pingUrl(const QUrl &url, int timeout = 5000) { if (!url.isValid()) { @@ -72,25 +67,4 @@ void resetAspect(AspectType &aspect) aspect.setVolatileValue(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 b141e54e3e9eb03f9270f045ce5302279f221e85 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:31:57 +0100 Subject: [PATCH 2/8] Rework General Settings --- CMakeLists.txt | 12 +- ConfigurationManager.cpp | 167 ++++++++++++ ConfigurationManager.hpp | 61 +++++ LLMClientInterface.cpp | 34 +-- QodeAssistClient.cpp | 122 ++++----- chatview/ChatModel.cpp | 15 +- chatview/ChatRootView.cpp | 12 +- chatview/ClientInterface.cpp | 64 ++--- llmcore/PromptTemplateManager.cpp | 54 +--- llmcore/PromptTemplateManager.hpp | 9 +- llmcore/Provider.hpp | 2 +- llmcore/ProvidersManager.cpp | 51 +--- llmcore/ProvidersManager.hpp | 9 +- providers/LMStudioProvider.cpp | 3 +- providers/LMStudioProvider.hpp | 2 +- providers/OllamaProvider.cpp | 3 +- providers/OllamaProvider.hpp | 2 +- providers/OpenAICompatProvider.cpp | 3 +- providers/OpenAICompatProvider.hpp | 2 +- qodeassist.cpp | 3 + settings/CMakeLists.txt | 2 - settings/GeneralSettings.cpp | 391 +++++++---------------------- settings/GeneralSettings.hpp | 67 +++-- settings/PresetPromptsSettings.cpp | 6 +- settings/SettingsConstants.hpp | 11 + settings/SettingsTr.hpp | 21 ++ settings/SettingsUtils.hpp | 11 + 27 files changed, 564 insertions(+), 575 deletions(-) create mode 100644 ConfigurationManager.cpp create mode 100644 ConfigurationManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a989304..3eebde3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) find_package(QtCreator REQUIRED COMPONENTS Core) -find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED) +find_package(Qt6 COMPONENTS Core Gui Quick Widgets Network REQUIRED) add_subdirectory(llmcore) add_subdirectory(settings) @@ -22,11 +22,16 @@ add_qtc_plugin(QodeAssist QtCreator::Core QtCreator::LanguageClient QtCreator::TextEditor + QtCreator::ProjectExplorer DEPENDS + Qt::Core + Qt::Gui + Qt::Quick Qt::Widgets + Qt::Network QtCreator::ExtensionSystem QtCreator::Utils - QtCreator::ProjectExplorer + QodeAssistChatViewplugin SOURCES .github/workflows/build_cmake.yml .github/workflows/README.md @@ -55,6 +60,7 @@ add_qtc_plugin(QodeAssist core/ChangesManager.h core/ChangesManager.cpp chat/ChatOutputPane.h chat/ChatOutputPane.cpp chat/NavigationPanel.hpp chat/NavigationPanel.cpp + ConfigurationManager.hpp ConfigurationManager.cpp ) -target_link_libraries(QodeAssist PRIVATE QodeAssistChatViewplugin) +target_link_libraries(QodeAssist PRIVATE ) diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp new file mode 100644 index 0000000..e3cdb6e --- /dev/null +++ b/ConfigurationManager.cpp @@ -0,0 +1,167 @@ +/* + * 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 "ConfigurationManager.hpp" + +#include +#include + +#include "QodeAssisttr.h" + +namespace QodeAssist { + +ConfigurationManager &ConfigurationManager::instance() +{ + static ConfigurationManager instance; + return instance; +} + +void ConfigurationManager::init() +{ + setupConnections(); +} + +LLMCore::Provider *ConfigurationManager::getCurrentProvider() +{ + auto providerName = Settings::generalSettings().ccProvider(); + return LLMCore::ProvidersManager::instance().getProviderByName(providerName); +} + +LLMCore::PromptTemplate *ConfigurationManager::getCurrentTemplate() +{ + auto templateName = Settings::generalSettings().ccTemplate(); + return LLMCore::PromptTemplateManager::instance().getFimTemplateByName(templateName); +} + +ConfigurationManager::ConfigurationManager(QObject *parent) + : QObject(parent) + , m_generalSettings(Settings::generalSettings()) + , m_providersManager(LLMCore::ProvidersManager::instance()) + , m_templateManger(LLMCore::PromptTemplateManager::instance()) +{} + +void ConfigurationManager::setupConnections() +{ + using Config = ConfigurationManager; + using Button = ButtonAspect; + + connect(&m_generalSettings.ccSelectProvider, &Button::clicked, this, &Config::selectProvider); + connect(&m_generalSettings.caSelectProvider, &Button::clicked, this, &Config::selectProvider); + connect(&m_generalSettings.ccSelectModel, &Button::clicked, this, &Config::selectModel); + connect(&m_generalSettings.caSelectModel, &Button::clicked, this, &Config::selectModel); + connect(&m_generalSettings.ccSelectTemplate, &Button::clicked, this, &Config::selectTemplate); + connect(&m_generalSettings.caSelectTemplate, &Button::clicked, this, &Config::selectTemplate); + connect(&m_generalSettings.ccSetUrl, &Button::clicked, this, &Config::selectUrl); + connect(&m_generalSettings.caSetUrl, &Button::clicked, this, &Config::selectUrl); +} + +void ConfigurationManager::selectProvider() +{ + const auto providersList = m_providersManager.providersNames(); + + auto *settingsButton = qobject_cast(sender()); + if (!settingsButton) + return; + + auto &targetSettings = (settingsButton == &m_generalSettings.ccSelectProvider) + ? m_generalSettings.ccProvider + : m_generalSettings.caProvider; + + QTimer::singleShot(0, this, [this, providersList, &targetSettings] { + m_generalSettings.showSelectionDialog(providersList, + targetSettings, + Tr::tr("Select LLM Provider"), + Tr::tr("Providers:")); + }); +} + +void ConfigurationManager::selectModel() +{ + const QString providerName = m_generalSettings.ccProvider(); + + auto *settingsButton = qobject_cast(sender()); + if (!settingsButton) + return; + + const auto providerUrl = (settingsButton == &m_generalSettings.ccSelectModel) + ? m_generalSettings.ccUrl() + : m_generalSettings.caUrl(); + const auto modelList = m_providersManager.getProviderByName(providerName) + ->getInstalledModels(providerUrl); + + auto &targetSettings = (settingsButton == &m_generalSettings.ccSelectModel) + ? m_generalSettings.ccModel + : m_generalSettings.caModel; + + QTimer::singleShot(0, &m_generalSettings, [this, modelList, &targetSettings]() { + m_generalSettings.showSelectionDialog(modelList, + targetSettings, + Tr::tr("Select LLM Model"), + Tr::tr("Models:")); + }); +} + +void ConfigurationManager::selectTemplate() +{ + auto *settingsButton = qobject_cast(sender()); + if (!settingsButton) + return; + + const auto templateList = (settingsButton == &m_generalSettings.ccSelectTemplate) + ? m_templateManger.fimTemplatesNames() + : m_templateManger.chatTemplatesNames(); + + auto &targetSettings = (settingsButton == &m_generalSettings.ccSelectTemplate) + ? m_generalSettings.ccTemplate + : m_generalSettings.caTemplate; + + QTimer::singleShot(0, &m_generalSettings, [this, templateList, &targetSettings]() { + m_generalSettings.showSelectionDialog(templateList, + targetSettings, + Tr::tr("Select Template"), + Tr::tr("Templates:")); + }); +} + +void ConfigurationManager::selectUrl() +{ + QStringList urls; + for (const auto &name : m_providersManager.providersNames()) { + const auto url = m_providersManager.getProviderByName(name)->url(); + if (!urls.contains(url)) + urls.append(url); + } + + auto *settingsButton = qobject_cast(sender()); + if (!settingsButton) + return; + + auto &targetSettings = (settingsButton == &m_generalSettings.ccSetUrl) + ? m_generalSettings.ccUrl + : m_generalSettings.caUrl; + + QTimer::singleShot(0, &m_generalSettings, [this, urls, &targetSettings]() { + m_generalSettings.showSelectionDialog(urls, + targetSettings, + Tr::tr("Select URL"), + Tr::tr("URLs:")); + }); +} + +} // namespace QodeAssist diff --git a/ConfigurationManager.hpp b/ConfigurationManager.hpp new file mode 100644 index 0000000..ffe033c --- /dev/null +++ b/ConfigurationManager.hpp @@ -0,0 +1,61 @@ +/* + * 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 "llmcore/PromptTemplateManager.hpp" +#include "llmcore/ProvidersManager.hpp" +#include "settings/GeneralSettings.hpp" + +namespace QodeAssist { + +class ConfigurationManager : public QObject +{ + Q_OBJECT + +public: + static ConfigurationManager &instance(); + + void init(); + + LLMCore::Provider *getCurrentProvider(); + LLMCore::PromptTemplate *getCurrentTemplate(); + +public slots: + void selectProvider(); + void selectModel(); + void selectTemplate(); + void selectUrl(); + +private: + explicit ConfigurationManager(QObject *parent = nullptr); + ~ConfigurationManager() = default; + ConfigurationManager(const ConfigurationManager &) = delete; + ConfigurationManager &operator=(const ConfigurationManager &) = delete; + + Settings::GeneralSettings &m_generalSettings; + LLMCore::ProvidersManager &m_providersManager; + LLMCore::PromptTemplateManager &m_templateManger; + + void setupConnections(); +}; + +} // namespace QodeAssist diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 0360725..70e93ab 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -146,28 +146,28 @@ void LLMClientInterface::handleExit(const QJsonObject &request) void LLMClientInterface::handleCompletion(const QJsonObject &request) { - auto updatedContext = prepareContext(request); + // auto updatedContext = prepareContext(request); - LLMCore::LLMConfig config; - config.requestType = LLMCore::RequestType::Fim; - config.provider = LLMCore::ProvidersManager::instance().getCurrentFimProvider(); - config.promptTemplate = LLMCore::PromptTemplateManager::instance().getCurrentFimTemplate(); - config.url = QUrl(QString("%1%2").arg(Settings::generalSettings().url(), - Settings::generalSettings().endPoint())); + // LLMCore::LLMConfig config; + // config.requestType = LLMCore::RequestType::Fim; + // config.provider = LLMCore::ProvidersManager::instance().getCurrentFimProvider(); + // config.promptTemplate = LLMCore::PromptTemplateManager::instance().getCurrentFimTemplate(); + // config.url = QUrl(QString("%1%2").arg(Settings::generalSettings().url(), + // Settings::generalSettings().endPoint())); - config.providerRequest = {{"model", Settings::generalSettings().modelName.value()}, - {"stream", true}, - {"stop", - QJsonArray::fromStringList(config.promptTemplate->stopWords())}}; - config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); + // config.providerRequest = {{"model", Settings::generalSettings().modelName.value()}, + // {"stream", true}, + // {"stop", + // QJsonArray::fromStringList(config.promptTemplate->stopWords())}}; + // config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); - if (Settings::contextSettings().useSystemPrompt()) - config.providerRequest["system"] = Settings::contextSettings().systemPrompt(); + // if (Settings::contextSettings().useSystemPrompt()) + // config.providerRequest["system"] = Settings::contextSettings().systemPrompt(); - config.promptTemplate->prepareRequest(config.providerRequest, updatedContext); - config.provider->prepareRequest(config.providerRequest, LLMCore::RequestType::Fim); + // config.promptTemplate->prepareRequest(config.providerRequest, updatedContext); + // config.provider->prepareRequest(config.providerRequest, LLMCore::RequestType::Fim); - m_requestHandler.sendLLMRequest(config, request); + // m_requestHandler.sendLLMRequest(config, request); } LLMCore::ContextData LLMClientInterface::prepareContext(const QJsonObject &request, diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index f85056f..89549c0 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -65,52 +65,52 @@ QodeAssistClient::~QodeAssistClient() void QodeAssistClient::openDocument(TextEditor::TextDocument *document) { - auto project = ProjectManager::projectForFile(document->filePath()); - if (!isEnabled(project)) - return; + // auto project = ProjectManager::projectForFile(document->filePath()); + // if (!isEnabled(project)) + // return; - Client::openDocument(document); - connect(document, - &TextDocument::contentsChangedWithPosition, - this, - [this, document](int position, int charsRemoved, int charsAdded) { - Q_UNUSED(charsRemoved) - if (!Settings::generalSettings().enableAutoComplete()) - return; + // Client::openDocument(document); + // connect(document, + // &TextDocument::contentsChangedWithPosition, + // this, + // [this, document](int position, int charsRemoved, int charsAdded) { + // Q_UNUSED(charsRemoved) + // if (!Settings::generalSettings().enableAutoComplete()) + // return; - auto project = ProjectManager::projectForFile(document->filePath()); - if (!isEnabled(project)) - return; + // auto project = ProjectManager::projectForFile(document->filePath()); + // if (!isEnabled(project)) + // return; - auto textEditor = BaseTextEditor::currentTextEditor(); - if (!textEditor || textEditor->document() != document) - return; + // auto textEditor = BaseTextEditor::currentTextEditor(); + // if (!textEditor || textEditor->document() != document) + // return; - if (Settings::contextSettings().useProjectChangesCache()) - ChangesManager::instance().addChange(document, - position, - charsRemoved, - charsAdded); + // if (Settings::contextSettings().useProjectChangesCache()) + // ChangesManager::instance().addChange(document, + // position, + // charsRemoved, + // charsAdded); - TextEditorWidget *widget = textEditor->editorWidget(); - if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) - return; - const int cursorPosition = widget->textCursor().position(); - if (cursorPosition < position || cursorPosition > position + charsAdded) - return; + // TextEditorWidget *widget = textEditor->editorWidget(); + // if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) + // return; + // const int cursorPosition = widget->textCursor().position(); + // if (cursorPosition < position || cursorPosition > position + charsAdded) + // return; - m_recentCharCount += charsAdded; + // m_recentCharCount += charsAdded; - if (m_typingTimer.elapsed() - > Settings::generalSettings().autoCompletionTypingInterval()) { - m_recentCharCount = charsAdded; - m_typingTimer.restart(); - } + // if (m_typingTimer.elapsed() + // > Settings::generalSettings().autoCompletionTypingInterval()) { + // m_recentCharCount = charsAdded; + // m_typingTimer.restart(); + // } - if (m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) { - scheduleRequest(widget); - } - }); + // if (m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) { + // scheduleRequest(widget); + // } + // }); } bool QodeAssistClient::canOpenProject(ProjectExplorer::Project *project) @@ -144,31 +144,31 @@ void QodeAssistClient::requestCompletions(TextEditor::TextEditorWidget *editor) void QodeAssistClient::scheduleRequest(TextEditor::TextEditorWidget *editor) { - cancelRunningRequest(editor); + // cancelRunningRequest(editor); - auto it = m_scheduledRequests.find(editor); - if (it == m_scheduledRequests.end()) { - auto timer = new QTimer(this); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, this, [this, editor]() { - if (editor - && editor->textCursor().position() - == m_scheduledRequests[editor]->property("cursorPosition").toInt() - && m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) - requestCompletions(editor); - }); - connect(editor, &TextEditorWidget::destroyed, this, [this, editor]() { - delete m_scheduledRequests.take(editor); - cancelRunningRequest(editor); - }); - connect(editor, &TextEditorWidget::cursorPositionChanged, this, [this, editor] { - cancelRunningRequest(editor); - }); - it = m_scheduledRequests.insert(editor, timer); - } + // auto it = m_scheduledRequests.find(editor); + // if (it == m_scheduledRequests.end()) { + // auto timer = new QTimer(this); + // timer->setSingleShot(true); + // connect(timer, &QTimer::timeout, this, [this, editor]() { + // if (editor + // && editor->textCursor().position() + // == m_scheduledRequests[editor]->property("cursorPosition").toInt() + // && m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) + // requestCompletions(editor); + // }); + // connect(editor, &TextEditorWidget::destroyed, this, [this, editor]() { + // delete m_scheduledRequests.take(editor); + // cancelRunningRequest(editor); + // }); + // connect(editor, &TextEditorWidget::cursorPositionChanged, this, [this, editor] { + // cancelRunningRequest(editor); + // }); + // it = m_scheduledRequests.insert(editor, timer); + // } - it.value()->setProperty("cursorPosition", editor->textCursor().position()); - it.value()->start(Settings::generalSettings().startSuggestionTimer()); + // 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/chatview/ChatModel.cpp b/chatview/ChatModel.cpp index c5cf9f7..0656075 100644 --- a/chatview/ChatModel.cpp +++ b/chatview/ChatModel.cpp @@ -30,12 +30,12 @@ ChatModel::ChatModel(QObject *parent) : QAbstractListModel(parent) , m_totalTokens(0) { - auto &settings = Settings::generalSettings(); + // auto &settings = Settings::generalSettings(); - connect(&settings.chatTokensThreshold, - &Utils::BaseAspect::changed, - this, - &ChatModel::tokensThresholdChanged); + // connect(&settings.chatTokensThreshold, + // &Utils::BaseAspect::changed, + // this, + // &ChatModel::tokensThresholdChanged); } int ChatModel::rowCount(const QModelIndex &parent) const @@ -183,8 +183,9 @@ int ChatModel::totalTokens() const int ChatModel::tokensThreshold() const { - auto &settings = Settings::generalSettings(); - return settings.chatTokensThreshold(); + // auto &settings = Settings::generalSettings(); + // return settings.chatTokensThreshold(); + return 0; } QString ChatModel::lastMessageId() const diff --git a/chatview/ChatRootView.cpp b/chatview/ChatRootView.cpp index 6450c51..180c4ea 100644 --- a/chatview/ChatRootView.cpp +++ b/chatview/ChatRootView.cpp @@ -31,12 +31,12 @@ ChatRootView::ChatRootView(QQuickItem *parent) , m_chatModel(new ChatModel(this)) , m_clientInterface(new ClientInterface(m_chatModel, this)) { - auto &settings = Settings::generalSettings(); + // auto &settings = Settings::generalSettings(); - connect(&settings.chatModelName, - &Utils::BaseAspect::changed, - this, - &ChatRootView::currentTemplateChanged); + // connect(&settings.chatModelName, + // &Utils::BaseAspect::changed, + // this, + // &ChatRootView::currentTemplateChanged); generateColors(); } @@ -111,7 +111,7 @@ QColor ChatRootView::generateColor(const QColor &baseColor, QString ChatRootView::currentTemplate() const { auto &settings = Settings::generalSettings(); - return settings.chatModelName(); + return settings.caModel(); } QColor ChatRootView::primaryColor() const diff --git a/chatview/ClientInterface.cpp b/chatview/ClientInterface.cpp index 2d1c1b6..b99c7b8 100644 --- a/chatview/ClientInterface.cpp +++ b/chatview/ClientInterface.cpp @@ -56,46 +56,46 @@ ClientInterface::~ClientInterface() = default; void ClientInterface::sendMessage(const QString &message) { - cancelRequest(); + // cancelRequest(); - LOG_MESSAGE("Sending message: " + message); - LOG_MESSAGE("chatProvider " + Settings::generalSettings().chatLlmProviders.stringValue()); - LOG_MESSAGE("chatTemplate " + Settings::generalSettings().chatPrompts.stringValue()); + // LOG_MESSAGE("Sending message: " + message); + // LOG_MESSAGE("chatProvider " + Settings::generalSettings().chatLlmProviders.stringValue()); + // LOG_MESSAGE("chatTemplate " + Settings::generalSettings().chatPrompts.stringValue()); - auto chatTemplate = LLMCore::PromptTemplateManager::instance().getCurrentChatTemplate(); - auto chatProvider = LLMCore::ProvidersManager::instance().getCurrentChatProvider(); + // auto chatTemplate = LLMCore::PromptTemplateManager::instance().getCurrentChatTemplate(); + // auto chatProvider = LLMCore::ProvidersManager::instance().getCurrentChatProvider(); - LLMCore::ContextData context; - context.prefix = message; - context.suffix = ""; - if (Settings::contextSettings().useChatSystemPrompt()) - context.systemPrompt = Settings::contextSettings().chatSystemPrompt(); + // LLMCore::ContextData context; + // context.prefix = message; + // context.suffix = ""; + // if (Settings::contextSettings().useChatSystemPrompt()) + // context.systemPrompt = Settings::contextSettings().chatSystemPrompt(); - QJsonObject providerRequest; - providerRequest["model"] = Settings::generalSettings().chatModelName(); - providerRequest["stream"] = true; - providerRequest["messages"] = m_chatModel->prepareMessagesForRequest(context); + // QJsonObject providerRequest; + // providerRequest["model"] = Settings::generalSettings().chatModelName(); + // providerRequest["stream"] = true; + // providerRequest["messages"] = m_chatModel->prepareMessagesForRequest(context); - if (!chatTemplate || !chatProvider) { - LOG_MESSAGE("Check settings, provider or template are not set"); - } - chatTemplate->prepareRequest(providerRequest, context); - chatProvider->prepareRequest(providerRequest, LLMCore::RequestType::Chat); + // if (!chatTemplate || !chatProvider) { + // LOG_MESSAGE("Check settings, provider or template are not set"); + // } + // chatTemplate->prepareRequest(providerRequest, context); + // chatProvider->prepareRequest(providerRequest, LLMCore::RequestType::Chat); - LLMCore::LLMConfig config; - config.requestType = LLMCore::RequestType::Chat; - config.provider = chatProvider; - config.promptTemplate = chatTemplate; - config.url = QString("%1%2").arg(Settings::generalSettings().chatUrl(), - Settings::generalSettings().chatEndPoint()); - config.providerRequest = providerRequest; - config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); + // LLMCore::LLMConfig config; + // config.requestType = LLMCore::RequestType::Chat; + // config.provider = chatProvider; + // config.promptTemplate = chatTemplate; + // config.url = QString("%1%2").arg(Settings::generalSettings().chatUrl(), + // Settings::generalSettings().chatEndPoint()); + // config.providerRequest = providerRequest; + // config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); - QJsonObject request; - request["id"] = QUuid::createUuid().toString(); + // QJsonObject request; + // request["id"] = QUuid::createUuid().toString(); - m_chatModel->addMessage(message, ChatModel::ChatRole::User, ""); - m_requestHandler->sendLLMRequest(config, request); + // m_chatModel->addMessage(message, ChatModel::ChatRole::User, ""); + // m_requestHandler->sendLLMRequest(config, request); } void ClientInterface::clearMessages() diff --git a/llmcore/PromptTemplateManager.cpp b/llmcore/PromptTemplateManager.cpp index 2eafc18..c0b08fc 100644 --- a/llmcore/PromptTemplateManager.cpp +++ b/llmcore/PromptTemplateManager.cpp @@ -19,8 +19,6 @@ #include "PromptTemplateManager.hpp" -#include "Logger.hpp" - namespace QodeAssist::LLMCore { PromptTemplateManager &PromptTemplateManager::instance() @@ -29,48 +27,6 @@ PromptTemplateManager &PromptTemplateManager::instance() return instance; } -void PromptTemplateManager::setCurrentFimTemplate(const QString &name) -{ - LOG_MESSAGE("Setting current FIM provider to: " + name); - if (!m_fimTemplates.contains(name) || m_fimTemplates[name] == nullptr) { - LOG_MESSAGE("Error to set current FIM template" + name); - return; - } - - m_currentFimTemplate = m_fimTemplates[name]; -} - -PromptTemplate *PromptTemplateManager::getCurrentFimTemplate() -{ - if (m_currentFimTemplate == nullptr) { - LOG_MESSAGE("Current fim provider is null, return first"); - return m_fimTemplates.first(); - } - - return m_currentFimTemplate; -} - -void PromptTemplateManager::setCurrentChatTemplate(const QString &name) -{ - LOG_MESSAGE("Setting current chat provider to: " + name); - if (!m_chatTemplates.contains(name) || m_chatTemplates[name] == nullptr) { - LOG_MESSAGE("Error to set current chat template" + name); - return; - } - - m_currentChatTemplate = m_chatTemplates[name]; -} - -PromptTemplate *PromptTemplateManager::getCurrentChatTemplate() -{ - if (m_currentChatTemplate == nullptr) { - LOG_MESSAGE("Current chat provider is null, return first"); - return m_chatTemplates.first(); - } - - return m_currentChatTemplate; -} - QStringList PromptTemplateManager::fimTemplatesNames() const { return m_fimTemplates.keys(); @@ -87,4 +43,14 @@ PromptTemplateManager::~PromptTemplateManager() qDeleteAll(m_chatTemplates); } +PromptTemplate *PromptTemplateManager::getFimTemplateByName(const QString &templateName) +{ + return m_fimTemplates[templateName]; +} + +PromptTemplate *PromptTemplateManager::getChatTemplateByName(const QString &templateName) +{ + return m_chatTemplates[templateName]; +} + } // namespace QodeAssist::LLMCore diff --git a/llmcore/PromptTemplateManager.hpp b/llmcore/PromptTemplateManager.hpp index 5c2c3bf..4774a22 100644 --- a/llmcore/PromptTemplateManager.hpp +++ b/llmcore/PromptTemplateManager.hpp @@ -46,11 +46,8 @@ public: } } - void setCurrentFimTemplate(const QString &name); - PromptTemplate *getCurrentFimTemplate(); - - void setCurrentChatTemplate(const QString &name); - PromptTemplate *getCurrentChatTemplate(); + PromptTemplate *getFimTemplateByName(const QString &templateName); + PromptTemplate *getChatTemplateByName(const QString &templateName); QStringList fimTemplatesNames() const; QStringList chatTemplatesNames() const; @@ -62,8 +59,6 @@ private: QMap m_fimTemplates; QMap m_chatTemplates; - PromptTemplate *m_currentFimTemplate; - PromptTemplate *m_currentChatTemplate; }; } // namespace QodeAssist::LLMCore diff --git a/llmcore/Provider.hpp b/llmcore/Provider.hpp index e66f941..55f6da3 100644 --- a/llmcore/Provider.hpp +++ b/llmcore/Provider.hpp @@ -40,7 +40,7 @@ public: virtual void prepareRequest(QJsonObject &request, RequestType type) = 0; virtual bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) = 0; - virtual QList getInstalledModels(const Utils::Environment &env, const QString &url) = 0; + virtual QList getInstalledModels(const QString &url) = 0; }; } // namespace QodeAssist::LLMCore diff --git a/llmcore/ProvidersManager.cpp b/llmcore/ProvidersManager.cpp index fdde562..19a1d43 100644 --- a/llmcore/ProvidersManager.cpp +++ b/llmcore/ProvidersManager.cpp @@ -18,8 +18,6 @@ */ #include "ProvidersManager.hpp" -#include "Logger.hpp" -#include namespace QodeAssist::LLMCore { @@ -29,50 +27,6 @@ ProvidersManager &ProvidersManager::instance() return instance; } -Provider *ProvidersManager::setCurrentFimProvider(const QString &name) -{ - LOG_MESSAGE("Setting current FIM provider to: " + name); - if (!m_providers.contains(name)) { - LOG_MESSAGE("Can't find provider with name: " + name); - return nullptr; - } - - m_currentFimProvider = m_providers[name]; - return m_currentFimProvider; -} - -Provider *ProvidersManager::setCurrentChatProvider(const QString &name) -{ - LOG_MESSAGE("Setting current chat provider to: " + name); - if (!m_providers.contains(name)) { - LOG_MESSAGE("Can't find chat provider with name: " + name); - return nullptr; - } - - m_currentChatProvider = m_providers[name]; - return m_currentChatProvider; -} - -Provider *ProvidersManager::getCurrentFimProvider() -{ - if (m_currentFimProvider == nullptr) { - LOG_MESSAGE("Current fim provider is null, return first"); - return m_providers.first(); - } - - return m_currentFimProvider; -} - -Provider *ProvidersManager::getCurrentChatProvider() -{ - if (m_currentChatProvider == nullptr) { - LOG_MESSAGE("Current chat provider is null, return first"); - return m_providers.first(); - } - - return m_currentChatProvider; -} - QStringList ProvidersManager::providersNames() const { return m_providers.keys(); @@ -83,4 +37,9 @@ ProvidersManager::~ProvidersManager() qDeleteAll(m_providers); } +Provider *ProvidersManager::getProviderByName(const QString &providerName) +{ + return m_providers[providerName]; +} + } // namespace QodeAssist::LLMCore diff --git a/llmcore/ProvidersManager.hpp b/llmcore/ProvidersManager.hpp index 03eabd2..82a0c8e 100644 --- a/llmcore/ProvidersManager.hpp +++ b/llmcore/ProvidersManager.hpp @@ -21,6 +21,7 @@ #include +#include #include "Provider.hpp" namespace QodeAssist::LLMCore { @@ -40,11 +41,7 @@ public: m_providers[name] = provider; } - Provider *setCurrentFimProvider(const QString &name); - Provider *setCurrentChatProvider(const QString &name); - - Provider *getCurrentFimProvider(); - Provider *getCurrentChatProvider(); + Provider *getProviderByName(const QString &providerName); QStringList providersNames() const; @@ -54,8 +51,6 @@ private: ProvidersManager &operator=(const ProvidersManager &) = delete; QMap m_providers; - Provider *m_currentFimProvider = nullptr; - Provider *m_currentChatProvider = nullptr; }; } // namespace QodeAssist::LLMCore diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index edcd832..06bc67e 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -127,8 +127,7 @@ bool LMStudioProvider::handleResponse(QNetworkReply *reply, QString &accumulated return isComplete; } -QList LMStudioProvider::getInstalledModels(const Utils::Environment &env, - const QString &url) +QList LMStudioProvider::getInstalledModels(const QString &url) { QList models; QNetworkAccessManager manager; diff --git a/providers/LMStudioProvider.hpp b/providers/LMStudioProvider.hpp index 42964ab..a92a01f 100644 --- a/providers/LMStudioProvider.hpp +++ b/providers/LMStudioProvider.hpp @@ -34,7 +34,7 @@ public: QString chatEndpoint() const override; void prepareRequest(QJsonObject &request, LLMCore::RequestType type) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; - QList getInstalledModels(const Utils::Environment &env, const QString &url) override; + QList getInstalledModels(const QString &url) override; }; } // namespace QodeAssist::Providers diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index dd92033..223b568 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -25,7 +25,6 @@ #include #include -#include "llmcore/PromptTemplateManager.hpp" #include "logger/Logger.hpp" #include "settings/PresetPromptsSettings.hpp" @@ -124,7 +123,7 @@ bool OllamaProvider::handleResponse(QNetworkReply *reply, QString &accumulatedRe return isComplete; } -QList OllamaProvider::getInstalledModels(const Utils::Environment &env, const QString &url) +QList OllamaProvider::getInstalledModels(const QString &url) { QList models; QNetworkAccessManager manager; diff --git a/providers/OllamaProvider.hpp b/providers/OllamaProvider.hpp index 145d475..cd00e18 100644 --- a/providers/OllamaProvider.hpp +++ b/providers/OllamaProvider.hpp @@ -34,7 +34,7 @@ public: QString chatEndpoint() const override; void prepareRequest(QJsonObject &request, LLMCore::RequestType type) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; - QList getInstalledModels(const Utils::Environment &env, const QString &url) override; + QList getInstalledModels(const QString &url) override; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index d277015..8f7b7e9 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -129,8 +129,7 @@ bool OpenAICompatProvider::handleResponse(QNetworkReply *reply, QString &accumul return isComplete; } -QList OpenAICompatProvider::getInstalledModels(const Utils::Environment &env, - const QString &url) +QList OpenAICompatProvider::getInstalledModels(const QString &url) { return QStringList(); } diff --git a/providers/OpenAICompatProvider.hpp b/providers/OpenAICompatProvider.hpp index bd23c73..ebe1c0a 100644 --- a/providers/OpenAICompatProvider.hpp +++ b/providers/OpenAICompatProvider.hpp @@ -34,7 +34,7 @@ public: QString chatEndpoint() const override; void prepareRequest(QJsonObject &request, LLMCore::RequestType type) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; - QList getInstalledModels(const Utils::Environment &env, const QString &url) override; + QList getInstalledModels(const QString &url) override; }; } // namespace QodeAssist::Providers diff --git a/qodeassist.cpp b/qodeassist.cpp index 5007dd7..a8b2b2a 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -39,6 +39,7 @@ #include #include +#include "ConfigurationManager.hpp" #include "QodeAssistClient.hpp" #include "chat/ChatOutputPane.h" #include "chat/NavigationPanel.hpp" @@ -125,6 +126,8 @@ public: m_chatOutputPane = new Chat::ChatOutputPane(this); m_navigationPanel = new Chat::NavigationPanel(); + + ConfigurationManager::instance().init(); } void extensionsInitialized() final diff --git a/settings/CMakeLists.txt b/settings/CMakeLists.txt index 882cc76..f2062ec 100644 --- a/settings/CMakeLists.txt +++ b/settings/CMakeLists.txt @@ -16,7 +16,5 @@ target_link_libraries(QodeAssistSettings QtCreator::Core QtCreator::Utils QodeAssistLogger - PRIVATE - LLMCore ) target_include_directories(QodeAssistSettings PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 1c64d87..bfab84f 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -27,9 +27,6 @@ #include #include "Logger.hpp" -#include "PromptTemplateManager.hpp" -#include "Provider.hpp" -#include "ProvidersManager.hpp" #include "SettingsConstants.hpp" #include "SettingsTr.hpp" #include "SettingsUtils.hpp" @@ -46,117 +43,59 @@ GeneralSettings::GeneralSettings() { setAutoApply(false); - setDisplayName(Tr::tr("General")); + setDisplayName(TrConstants::GENERAL); enableQodeAssist.setSettingsKey(Constants::ENABLE_QODE_ASSIST); - enableQodeAssist.setLabelText(Tr::tr("Enable Qode Assist")); + enableQodeAssist.setLabelText(TrConstants::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.setLabelText(TrConstants::ENABLE_LOG); enableLogging.setDefaultValue(false); - multiLineCompletion.setSettingsKey(Constants::MULTILINE_COMPLETION); - multiLineCompletion.setDefaultValue(false); - multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion(experimental)")); + resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS; - startSuggestionTimer.setSettingsKey(Constants::START_SUGGESTION_TIMER); - startSuggestionTimer.setLabelText(Tr::tr("with delay(ms)")); - startSuggestionTimer.setRange(10, 10000); - startSuggestionTimer.setDefaultValue(500); + initStringAspect(ccProvider, Constants::CC_PROVIDER, TrConstants::PROVIDER, "Ollama"); + ccProvider.setReadOnly(true); + ccSelectProvider.m_buttonText = TrConstants::SELECT; - autoCompletionCharThreshold.setSettingsKey(Constants::AUTO_COMPLETION_CHAR_THRESHOLD); - autoCompletionCharThreshold.setLabelText(Tr::tr("AI suggestion triggers after typing")); - 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(0, 10); - autoCompletionCharThreshold.setDefaultValue(0); + initStringAspect(ccModel, Constants::CC_MODEL, TrConstants::MODEL, "codellama:7b-code"); + ccSelectModel.m_buttonText = TrConstants::SELECT; - autoCompletionTypingInterval.setSettingsKey(Constants::AUTO_COMPLETION_TYPING_INTERVAL); - autoCompletionTypingInterval.setLabelText(Tr::tr("character(s) within(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); + initStringAspect(ccTemplate, Constants::CC_TEMPLATE, TrConstants::TEMPLATE, "CodeLlama FIM"); + ccTemplate.setReadOnly(true); + ccSelectTemplate.m_buttonText = TrConstants::SELECT; - llmProviders.setSettingsKey(Constants::LLM_PROVIDERS); - llmProviders.setDisplayName(Tr::tr("AI Suggest Provider:")); - llmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); + initStringAspect(ccUrl, Constants::CC_URL, TrConstants::URL, "http://localhost:11434"); + ccSetUrl.m_buttonText = TrConstants::SELECT; - url.setSettingsKey(Constants::URL); - url.setLabelText(Tr::tr("URL:")); - url.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + ccStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay); + ccStatus.setLabelText(TrConstants::STATUS); + ccStatus.setDefaultValue(""); + ccTest.m_buttonText = TrConstants::TEST; - endPoint.setSettingsKey(Constants::END_POINT); - endPoint.setLabelText(Tr::tr("FIM Endpoint:")); - endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + initStringAspect(caProvider, Constants::CA_PROVIDER, TrConstants::PROVIDER, "Ollama"); + caProvider.setReadOnly(true); + caSelectProvider.m_buttonText = TrConstants::SELECT; - modelName.setSettingsKey(Constants::MODEL_NAME); - modelName.setLabelText(Tr::tr("Model name:")); - modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + initStringAspect(caModel, Constants::CA_MODEL, TrConstants::MODEL, "codellama:7b-instruct"); + caSelectModel.m_buttonText = TrConstants::SELECT; - selectModels.m_buttonText = Tr::tr("Select Fill-In-the-Middle Model"); + initStringAspect(caTemplate, Constants::CA_TEMPLATE, TrConstants::TEMPLATE, "CodeLlama Chat"); + caTemplate.setReadOnly(true); - fimPrompts.setDisplayName(Tr::tr("Fill-In-the-Middle Prompt")); - fimPrompts.setSettingsKey(Constants::FIM_PROMPTS); - fimPrompts.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); - resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + caSelectTemplate.m_buttonText = TrConstants::SELECT; - chatLlmProviders.setSettingsKey(Constants::CHAT_LLM_PROVIDERS); - chatLlmProviders.setDisplayName(Tr::tr("AI Chat Provider:")); - chatLlmProviders.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); + initStringAspect(caUrl, Constants::CA_URL, TrConstants::URL, "http://localhost:11434"); + caSetUrl.m_buttonText = TrConstants::SELECT; - chatUrl.setSettingsKey(Constants::CHAT_URL); - chatUrl.setLabelText(Tr::tr("URL:")); - chatUrl.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - chatEndPoint.setSettingsKey(Constants::CHAT_END_POINT); - chatEndPoint.setLabelText(Tr::tr("Chat Endpoint:")); - chatEndPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - chatModelName.setSettingsKey(Constants::CHAT_MODEL_NAME); - chatModelName.setLabelText(Tr::tr("Model name:")); - chatModelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - - chatSelectModels.m_buttonText = Tr::tr("Select Chat Model"); - - chatPrompts.setDisplayName(Tr::tr("Chat Prompt")); - chatPrompts.setSettingsKey(Constants::CHAT_PROMPTS); - chatPrompts.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox); - - chatTokensThreshold.setSettingsKey(Constants::CHAT_TOKENS_THRESHOLD); - chatTokensThreshold.setLabelText(Tr::tr("Chat History Token Limit")); - chatTokensThreshold.setToolTip(Tr::tr("Maximum number of tokens in chat history. When " - "exceeded, oldest messages will be removed.")); - chatTokensThreshold.setRange(1000, 16000); - chatTokensThreshold.setDefaultValue(8000); - - loadProviders(); - loadPrompts(); - - llmProviders.setDefaultValue(llmProviders.indexForDisplay("Ollama")); - chatLlmProviders.setDefaultValue(chatLlmProviders.indexForDisplay("Ollama")); - fimPrompts.setDefaultValue(fimPrompts.indexForDisplay("CodeLlama FIM")); - chatPrompts.setDefaultValue(chatPrompts.indexForDisplay("CodeLlama Chat")); - - auto fimProviderName = llmProviders.displayForIndex(llmProviders.value()); - setCurrentFimProvider(fimProviderName); - auto chatProviderName = chatLlmProviders.displayForIndex(chatLlmProviders.value()); - setCurrentChatProvider(chatProviderName); + caStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay); + caStatus.setLabelText(TrConstants::STATUS); + caStatus.setDefaultValue(""); + caTest.m_buttonText = TrConstants::TEST; readSettings(); - auto nameFimPromts = fimPrompts.displayForIndex(fimPrompts.value()); - LLMCore::PromptTemplateManager::instance().setCurrentFimTemplate(nameFimPromts); - auto nameChatPromts = chatPrompts.displayForIndex(chatPrompts.value()); - LLMCore::PromptTemplateManager::instance().setCurrentChatTemplate(nameChatPromts); - Logger::instance().setLoggingEnabled(enableLogging()); setupConnections(); @@ -164,226 +103,88 @@ GeneralSettings::GeneralSettings() setLayouter([this]() { using namespace Layouting; - auto rootLayout - = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults}, - Row{enableLogging, Stretch{1}}, - Space{8}, - Group{title(Tr::tr("AI Suggestions")), - Column{enableAutoComplete, - multiLineCompletion, - Row{autoCompletionCharThreshold, - autoCompletionTypingInterval, - startSuggestionTimer, - Stretch{1}}, - Row{llmProviders, Stretch{1}}, - Row{url, endPoint, fimUrlIndicator}, - Row{selectModels, modelName, fimModelIndicator}, - Row{fimPrompts, Stretch{1}}}}, - Space{16}, - Group{title(Tr::tr("AI Chat")), - Column{Row{chatLlmProviders, Stretch{1}}, - Row{chatUrl, chatEndPoint, chatUrlIndicator}, - Row{chatSelectModels, chatModelName, chatModelIndicator}, - Row{chatPrompts, Stretch{1}}, - Row{chatTokensThreshold, Stretch{1}}}}, - Stretch{1}}; + auto ccGrid = Grid{}; + ccGrid.addRow({ccProvider, ccSelectProvider}); + ccGrid.addRow({ccModel, ccSelectModel}); + ccGrid.addRow({ccTemplate, ccSelectTemplate}); + ccGrid.addRow({ccUrl, ccSetUrl}); + ccGrid.addRow({ccStatus, ccTest}); + + auto caGrid = Grid{}; + caGrid.addRow({caProvider, caSelectProvider}); + caGrid.addRow({caModel, caSelectModel}); + caGrid.addRow({caTemplate, caSelectTemplate}); + caGrid.addRow({caUrl, caSetUrl}); + caGrid.addRow({caStatus, caTest}); + + auto ccGroup = Group{title(TrConstants::CODE_COMPLETION), ccGrid}; + auto caGroup = Group{title(TrConstants::CHAT_ASSISTANT), caGrid}; + + auto rootLayout = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults}, + Row{enableLogging, Stretch{1}}, + Space{8}, + ccGroup, + Space{8}, + caGroup, + Stretch{1}}; + return rootLayout; }); - - updateStatusIndicators(); } -void GeneralSettings::setupConnections() +void GeneralSettings::showSelectionDialog(const QStringList &data, + Utils::StringAspect &aspect, + const QString &title, + const QString &text) { - connect(&llmProviders, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - auto providerName = llmProviders.displayForIndex(llmProviders.volatileValue()); - setCurrentFimProvider(providerName); - modelName.setVolatileValue(""); - }); - connect(&chatLlmProviders, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - auto providerName = chatLlmProviders.displayForIndex(chatLlmProviders.volatileValue()); - setCurrentChatProvider(providerName); - chatModelName.setVolatileValue(""); - }); + if (data.isEmpty()) + return; - connect(&fimPrompts, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - int index = fimPrompts.volatileValue(); - LLMCore::PromptTemplateManager::instance().setCurrentFimTemplate( - fimPrompts.displayForIndex(index)); - }); - connect(&chatPrompts, &Utils::SelectionAspect::volatileValueChanged, this, [this]() { - int index = chatPrompts.volatileValue(); - LLMCore::PromptTemplateManager::instance().setCurrentChatTemplate( - chatPrompts.displayForIndex(index)); - }); + bool ok; + QInputDialog dialog(Core::ICore::dialogParent()); + dialog.setWindowTitle(title); + dialog.setLabelText(text); + dialog.setComboBoxItems(data); + dialog.setComboBoxEditable(false); + dialog.setFixedSize(400, 150); - connect(&selectModels, &ButtonAspect::clicked, this, [this]() { - auto *provider = LLMCore::ProvidersManager::instance().getCurrentFimProvider(); - showModelSelectionDialog(&modelName, provider); - }); - connect(&chatSelectModels, &ButtonAspect::clicked, this, [this]() { - auto *provider = LLMCore::ProvidersManager::instance().getCurrentChatProvider(); - showModelSelectionDialog(&chatModelName, provider); - }); - - connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { - Logger::instance().setLoggingEnabled(enableLogging.volatileValue()); - }); - connect(&resetToDefaults, &ButtonAspect::clicked, this, &GeneralSettings::resetPageToDefaults); - - connect(&url, - &Utils::StringAspect::volatileValueChanged, - this, - &GeneralSettings::updateStatusIndicators); - connect(&modelName, - &Utils::StringAspect::volatileValueChanged, - this, - &GeneralSettings::updateStatusIndicators); - connect(&chatUrl, - &Utils::StringAspect::volatileValueChanged, - this, - &GeneralSettings::updateStatusIndicators); - connect(&chatModelName, - &Utils::StringAspect::volatileValueChanged, - this, - &GeneralSettings::updateStatusIndicators); -} - -void GeneralSettings::showModelSelectionDialog(Utils::StringAspect *modelNameObj, - LLMCore::Provider *provider) -{ - Utils::Environment env = Utils::Environment::systemEnvironment(); - QString providerUrl = (modelNameObj == &modelName) ? url() : chatUrl(); - - if (provider) { - QStringList models = provider->getInstalledModels(env, providerUrl); - 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()) { - modelNameObj->setVolatileValue(selectedModel); + if (dialog.exec() == QDialog::Accepted) { + QString result = dialog.textValue(); + if (!result.isEmpty()) { + aspect.setValue(result); writeSettings(); } } } +void GeneralSettings::setupConnections() +{ + connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + Logger::instance().setLoggingEnabled(enableLogging.volatileValue()); + }); + connect(&resetToDefaults, &ButtonAspect::clicked, this, &GeneralSettings::resetPageToDefaults); +} + 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); + reply = QMessageBox::question(Core::ICore::dialogParent(), + TrConstants::RESET_SETTINGS, + TrConstants::CONFIRMATION, + QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { resetAspect(enableQodeAssist); - resetAspect(enableAutoComplete); resetAspect(enableLogging); - resetAspect(startSuggestionTimer); - resetAspect(autoCompletionTypingInterval); - resetAspect(autoCompletionCharThreshold); - resetAspect(llmProviders); - resetAspect(chatLlmProviders); - resetAspect(fimPrompts); - resetAspect(chatPrompts); - resetAspect(chatTokensThreshold); - } - - modelName.setVolatileValue(""); - chatModelName.setVolatileValue(""); - - updateStatusIndicators(); -} - -void GeneralSettings::updateStatusIndicators() -{ - bool fimUrlValid = !url.volatileValue().isEmpty() && !endPoint.volatileValue().isEmpty(); - bool fimModelValid = !modelName.volatileValue().isEmpty(); - bool chatUrlValid = !chatUrl.volatileValue().isEmpty() - && !chatEndPoint.volatileValue().isEmpty(); - bool chatModelValid = !chatModelName.volatileValue().isEmpty(); - - bool fimPingSuccessful = false; - if (fimUrlValid) { - QUrl pingUrl(url.volatileValue()); - fimPingSuccessful = Settings::pingUrl(pingUrl); - } - bool chatPingSuccessful = false; - if (chatUrlValid) { - QUrl pingUrl(chatUrl.volatileValue()); - chatPingSuccessful = Settings::pingUrl(pingUrl); - } - - setIndicatorStatus(fimModelIndicator, - fimModelValid ? tr("Model is properly configured") - : tr("No model selected or model name is invalid"), - fimModelValid); - setIndicatorStatus(fimUrlIndicator, - fimPingSuccessful ? tr("Server is reachable") - : tr("Server is not reachable or URL is invalid"), - fimPingSuccessful); - - setIndicatorStatus(chatModelIndicator, - chatModelValid ? tr("Model is properly configured") - : tr("No model selected or model name is invalid"), - chatModelValid); - setIndicatorStatus(chatUrlIndicator, - chatPingSuccessful ? tr("Server is reachable") - : tr("Server is not reachable or URL is invalid"), - chatPingSuccessful); -} - -void GeneralSettings::setIndicatorStatus(Utils::StringAspect &indicator, - const QString &tooltip, - bool isValid) -{ - const Utils::Icon &icon = isValid ? Utils::Icons::OK : Utils::Icons::WARNING; - indicator.setLabelPixmap(icon.pixmap()); - indicator.setToolTip(tooltip); -} - -void GeneralSettings::setCurrentFimProvider(const QString &name) -{ - const auto provider = LLMCore::ProvidersManager::instance().setCurrentFimProvider(name); - if (!provider) - return; - - url.setValue(provider->url()); - endPoint.setValue(provider->completionEndpoint()); -} - -void GeneralSettings::setCurrentChatProvider(const QString &name) -{ - const auto provider = LLMCore::ProvidersManager::instance().setCurrentChatProvider(name); - if (!provider) - return; - - chatUrl.setValue(provider->url()); - chatEndPoint.setValue(provider->chatEndpoint()); -} - -void GeneralSettings::loadProviders() -{ - for (const auto &name : LLMCore::ProvidersManager::instance().providersNames()) { - llmProviders.addOption(name); - chatLlmProviders.addOption(name); - } -} - -void GeneralSettings::loadPrompts() -{ - for (const auto &name : LLMCore::PromptTemplateManager::instance().fimTemplatesNames()) { - fimPrompts.addOption(name); - } - for (const auto &name : LLMCore::PromptTemplateManager::instance().chatTemplatesNames()) { - chatPrompts.addOption(name); + resetAspect(ccProvider); + resetAspect(ccModel); + resetAspect(ccTemplate); + resetAspect(ccUrl); + resetAspect(caProvider); + resetAspect(caModel); + resetAspect(caTemplate); + resetAspect(caUrl); + writeSettings(); } } @@ -393,7 +194,7 @@ public: GeneralSettingsPage() { setId(Constants::QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID); - setDisplayName(Tr::tr("General")); + setDisplayName(TrConstants::GENERAL); setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); setSettingsProvider([] { return &generalSettings(); }); } diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index 6584659..9b0fc4f 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -34,50 +34,49 @@ public: GeneralSettings(); Utils::BoolAspect enableQodeAssist{this}; - Utils::BoolAspect enableAutoComplete{this}; - 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}; - Utils::StringAspect endPoint{this}; - - Utils::StringAspect modelName{this}; - ButtonAspect selectModels{this}; - Utils::SelectionAspect fimPrompts{this}; ButtonAspect resetToDefaults{this}; - Utils::SelectionAspect chatLlmProviders{this}; - Utils::StringAspect chatUrl{this}; - Utils::StringAspect chatEndPoint{this}; + // code completion setttings + Utils::StringAspect ccProvider{this}; + ButtonAspect ccSelectProvider{this}; - Utils::StringAspect chatModelName{this}; - ButtonAspect chatSelectModels{this}; - Utils::SelectionAspect chatPrompts{this}; + Utils::StringAspect ccModel{this}; + ButtonAspect ccSelectModel{this}; - Utils::StringAspect fimModelIndicator{this}; - Utils::StringAspect fimUrlIndicator{this}; - Utils::StringAspect chatModelIndicator{this}; - Utils::StringAspect chatUrlIndicator{this}; + Utils::StringAspect ccTemplate{this}; + ButtonAspect ccSelectTemplate{this}; - Utils::IntegerAspect chatTokensThreshold{this}; + Utils::StringAspect ccUrl{this}; + ButtonAspect ccSetUrl{this}; + + Utils::StringAspect ccStatus{this}; + ButtonAspect ccTest{this}; + + // chat assistant settings + Utils::StringAspect caProvider{this}; + ButtonAspect caSelectProvider{this}; + + Utils::StringAspect caModel{this}; + ButtonAspect caSelectModel{this}; + + Utils::StringAspect caTemplate{this}; + ButtonAspect caSelectTemplate{this}; + + Utils::StringAspect caUrl{this}; + ButtonAspect caSetUrl{this}; + + Utils::StringAspect caStatus{this}; + ButtonAspect caTest{this}; + + void showSelectionDialog(const QStringList &data, + Utils::StringAspect &aspect, + const QString &title = {}, + const QString &text = {}); private: void setupConnections(); - void showModelSelectionDialog(Utils::StringAspect *modelNameObj, LLMCore::Provider *provider); void resetPageToDefaults(); - - void updateStatusIndicators(); - void setIndicatorStatus(Utils::StringAspect &indicator, const QString &tooltip, bool isValid); - - void setCurrentFimProvider(const QString &name); - void setCurrentChatProvider(const QString &name); - - void loadProviders(); - void loadPrompts(); }; GeneralSettings &generalSettings(); diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp index 861dd1a..6c2a1b6 100644 --- a/settings/PresetPromptsSettings.cpp +++ b/settings/PresetPromptsSettings.cpp @@ -24,7 +24,6 @@ #include #include -#include "RequestType.hpp" #include "SettingsConstants.hpp" #include "SettingsTr.hpp" #include "SettingsUtils.hpp" @@ -193,9 +192,8 @@ PresetPromptsSettings::PresetPromptsSettings() PresetPromptsSettings::PromptSettings PresetPromptsSettings::getSettings(int type) const { - auto reqtype = static_cast(type); PromptSettings settings; - if (reqtype == LLMCore::RequestType::Fim) { + if (type == 0) { settings.temperature = fimTemperature(); settings.maxTokens = fimMaxTokens(); settings.useTopP = fimUseTopP(); @@ -208,7 +206,7 @@ PresetPromptsSettings::PromptSettings PresetPromptsSettings::getSettings(int typ settings.frequencyPenalty = fimFrequencyPenalty(); settings.ollamaLivetime = fimOllamaLivetime(); settings.apiKey = fimApiKey(); - } else if (reqtype == LLMCore::RequestType::Chat) { + } else if (type = 1) { settings.temperature = chatTemperature(); settings.maxTokens = chatMaxTokens(); settings.useTopP = chatUseTopP(); diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 0f7d573..1c66d3e 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -24,6 +24,17 @@ namespace QodeAssist::Constants { const char ACTION_ID[] = "QodeAssist.Action"; const char MENU_ID[] = "QodeAssist.Menu"; +// new settings +const char CC_PROVIDER[] = "QodeAssist.ccProvider"; +const char CC_MODEL[] = "QodeAssist.ccModel"; +const char CC_TEMPLATE[] = "QodeAssist.ccTemplate"; +const char CC_URL[] = "QodeAssist.ccUrl"; + +const char CA_PROVIDER[] = "QodeAssist.caProvider"; +const char CA_MODEL[] = "QodeAssist.caModel"; +const char CA_TEMPLATE[] = "QodeAssist.caTemplate"; +const char CA_URL[] = "QodeAssist.caUrl"; + // settings const char ENABLE_QODE_ASSIST[] = "QodeAssist.enableQodeAssist"; const char ENABLE_AUTO_COMPLETE[] = "QodeAssist.enableAutoComplete"; diff --git a/settings/SettingsTr.hpp b/settings/SettingsTr.hpp index ec2b40f..a47b279 100644 --- a/settings/SettingsTr.hpp +++ b/settings/SettingsTr.hpp @@ -23,6 +23,27 @@ namespace QodeAssist::Settings { +namespace TrConstants { +inline const char *ENABLE_QODE_ASSIST = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Enable Qode Assist"); +inline const char *GENERAL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "General"); +inline const char *RESET_TO_DEFAULTS = QT_TRANSLATE_NOOP("QtC::QodeAssist", + "Reset Page to Defaults"); +inline const char *SELECT = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Select..."); +inline const char *PROVIDER = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Provider:"); +inline const char *MODEL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Model:"); +inline const char *TEMPLATE = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Template:"); +inline const char *URL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "URL:"); +inline const char *STATUS = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Status:"); +inline const char *TEST = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Test"); +inline const char *ENABLE_LOG = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Enable Logging"); +inline const char *CODE_COMPLETION = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Code Completion"); +inline const char *CHAT_ASSISTANT = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Chat Assistant"); +inline const char *RESET_SETTINGS = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Reset Settings"); +inline const char *CONFIRMATION + = QT_TRANSLATE_NOOP("QtC::QodeAssist", + "Are you sure you want to reset all settings to default values?"); +} // namespace TrConstants + struct Tr { Q_DECLARE_TR_FUNCTIONS(QtC::QodeAssist) diff --git a/settings/SettingsUtils.hpp b/settings/SettingsUtils.hpp index 2761ec2..bca8115 100644 --- a/settings/SettingsUtils.hpp +++ b/settings/SettingsUtils.hpp @@ -67,4 +67,15 @@ void resetAspect(AspectType &aspect) aspect.setVolatileValue(aspect.defaultValue()); } +inline void initStringAspect(Utils::StringAspect &aspect, + const Utils::Key &settingsKey, + const QString &labelText, + const QString &defaultValue) +{ + aspect.setSettingsKey(settingsKey); + aspect.setLabelText(labelText); + aspect.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + aspect.setDefaultValue(defaultValue); +} + } // namespace QodeAssist::Settings From 2acaef553dcaa59876e9baf4e35d2e7a96d0757e Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 10 Nov 2024 21:21:37 +0100 Subject: [PATCH 3/8] Rework Code Completion Settings --- LLMClientInterface.cpp | 43 ++-- settings/CMakeLists.txt | 1 + settings/CodeCompletionSettings.cpp | 297 ++++++++++++++++++++++++++++ settings/CodeCompletionSettings.hpp | 81 ++++++++ settings/ContextSettings.cpp | 16 +- settings/PresetPromptsSettings.cpp | 24 +-- settings/SettingsConstants.hpp | 65 +++--- 7 files changed, 452 insertions(+), 75 deletions(-) create mode 100644 settings/CodeCompletionSettings.cpp create mode 100644 settings/CodeCompletionSettings.hpp diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 70e93ab..3d047f1 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -26,10 +26,12 @@ #include #include +#include "ConfigurationManager.hpp" #include "DocumentContextReader.hpp" -#include "logger/Logger.hpp" #include "llmcore/PromptTemplateManager.hpp" #include "llmcore/ProvidersManager.hpp" +#include "logger/Logger.hpp" +#include "settings/CodeCompletionSettings.hpp" #include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" @@ -146,28 +148,33 @@ void LLMClientInterface::handleExit(const QJsonObject &request) void LLMClientInterface::handleCompletion(const QJsonObject &request) { - // auto updatedContext = prepareContext(request); + auto updatedContext = prepareContext(request); + auto &completeSettings = Settings::codeCompletionSettings(); - // LLMCore::LLMConfig config; - // config.requestType = LLMCore::RequestType::Fim; - // config.provider = LLMCore::ProvidersManager::instance().getCurrentFimProvider(); - // config.promptTemplate = LLMCore::PromptTemplateManager::instance().getCurrentFimTemplate(); - // config.url = QUrl(QString("%1%2").arg(Settings::generalSettings().url(), - // Settings::generalSettings().endPoint())); + auto &configManager = ConfigurationManager::instance(); + auto provider = configManager.getCurrentProvider(); + auto promptTemplate = configManager.getCurrentTemplate(); - // config.providerRequest = {{"model", Settings::generalSettings().modelName.value()}, - // {"stream", true}, - // {"stop", - // QJsonArray::fromStringList(config.promptTemplate->stopWords())}}; - // config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); + LLMCore::LLMConfig config; + config.requestType = LLMCore::RequestType::Fim; + config.provider = provider; + config.promptTemplate = promptTemplate; + config.url = QUrl( + QString("%1%2").arg(Settings::generalSettings().ccUrl(), provider->completionEndpoint())); - // if (Settings::contextSettings().useSystemPrompt()) - // config.providerRequest["system"] = Settings::contextSettings().systemPrompt(); + config.providerRequest = {{"model", Settings::generalSettings().ccModel()}, + {"stream", true}, + {"stop", + QJsonArray::fromStringList(config.promptTemplate->stopWords())}}; + config.multiLineCompletion = completeSettings.multiLineCompletion(); - // config.promptTemplate->prepareRequest(config.providerRequest, updatedContext); - // config.provider->prepareRequest(config.providerRequest, LLMCore::RequestType::Fim); + if (completeSettings.useSystemPrompt()) + config.providerRequest["system"] = completeSettings.systemPrompt(); - // m_requestHandler.sendLLMRequest(config, request); + config.promptTemplate->prepareRequest(config.providerRequest, updatedContext); + config.provider->prepareRequest(config.providerRequest, LLMCore::RequestType::Fim); + + m_requestHandler.sendLLMRequest(config, request); } LLMCore::ContextData LLMClientInterface::prepareContext(const QJsonObject &request, diff --git a/settings/CMakeLists.txt b/settings/CMakeLists.txt index f2062ec..57a266d 100644 --- a/settings/CMakeLists.txt +++ b/settings/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(QodeAssistSettings STATIC SettingsConstants.hpp ButtonAspect.hpp SettingsTr.hpp + CodeCompletionSettings.hpp CodeCompletionSettings.cpp ) target_link_libraries(QodeAssistSettings diff --git a/settings/CodeCompletionSettings.cpp b/settings/CodeCompletionSettings.cpp new file mode 100644 index 0000000..90f81de --- /dev/null +++ b/settings/CodeCompletionSettings.cpp @@ -0,0 +1,297 @@ +/* + * 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 "CodeCompletionSettings.hpp" + +#include +#include +#include +#include + +#include "SettingsConstants.hpp" +#include "SettingsTr.hpp" +#include "SettingsUtils.hpp" + +namespace QodeAssist::Settings { + +CodeCompletionSettings &codeCompletionSettings() +{ + static CodeCompletionSettings settings; + return settings; +} + +CodeCompletionSettings::CodeCompletionSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("Code Completion")); + + // Auto Completion Settings + autoCompletion.setSettingsKey(Constants::CC_AUTO_COMPLETION); + autoCompletion.setLabelText(Tr::tr("Enable Auto Complete")); + autoCompletion.setDefaultValue(true); + + multiLineCompletion.setSettingsKey(Constants::CC_MULTILINE_COMPLETION); + multiLineCompletion.setDefaultValue(false); + multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion(experimental)")); + + // General Parameters Settings + temperature.setSettingsKey(Constants::CC_TEMPERATURE); + temperature.setLabelText(Tr::tr("Temperature:")); + temperature.setDefaultValue(0.2); + temperature.setRange(0.0, 10.0); + temperature.setSingleStep(0.1); + + maxTokens.setSettingsKey(Constants::CC_MAX_TOKENS); + maxTokens.setLabelText(Tr::tr("Max Tokens:")); + maxTokens.setRange(-1, 10000); + maxTokens.setDefaultValue(50); + + useTopP.setSettingsKey(Constants::CC_USE_TOP_P); + useTopP.setDefaultValue(false); + useTopP.setLabelText(Tr::tr("Top P:")); + + topP.setSettingsKey(Constants::CC_TOP_P); + topP.setDefaultValue(0.9); + topP.setRange(0.0, 1.0); + topP.setSingleStep(0.1); + + useTopK.setSettingsKey(Constants::CC_USE_TOP_K); + useTopK.setDefaultValue(false); + useTopK.setLabelText(Tr::tr("Top K:")); + + topK.setSettingsKey(Constants::CC_TOP_K); + topK.setDefaultValue(50); + topK.setRange(1, 1000); + + // Advanced Parameters + usePresencePenalty.setSettingsKey(Constants::CC_USE_PRESENCE_PENALTY); + usePresencePenalty.setDefaultValue(false); + usePresencePenalty.setLabelText(Tr::tr("Presence Penalty:")); + + presencePenalty.setSettingsKey(Constants::CC_PRESENCE_PENALTY); + presencePenalty.setDefaultValue(0.0); + presencePenalty.setRange(-2.0, 2.0); + presencePenalty.setSingleStep(0.1); + + useFrequencyPenalty.setSettingsKey(Constants::CC_USE_FREQUENCY_PENALTY); + useFrequencyPenalty.setDefaultValue(false); + useFrequencyPenalty.setLabelText(Tr::tr("Frequency Penalty:")); + + frequencyPenalty.setSettingsKey(Constants::CC_FREQUENCY_PENALTY); + frequencyPenalty.setDefaultValue(0.0); + frequencyPenalty.setRange(-2.0, 2.0); + frequencyPenalty.setSingleStep(0.1); + + // Context Settings + readFullFile.setSettingsKey(Constants::CC_READ_FULL_FILE); + readFullFile.setLabelText(Tr::tr("Read Full File")); + readFullFile.setDefaultValue(false); + + readFileParts.setLabelText(Tr::tr("Read Strings Before Cursor:")); + readFileParts.setDefaultValue(true); + + readStringsBeforeCursor.setSettingsKey(Constants::CC_READ_STRINGS_BEFORE_CURSOR); + readStringsBeforeCursor.setRange(0, 10000); + readStringsBeforeCursor.setDefaultValue(50); + + readStringsAfterCursor.setSettingsKey(Constants::CC_READ_STRINGS_AFTER_CURSOR); + readStringsAfterCursor.setLabelText(Tr::tr("Read Strings After Cursor:")); + readStringsAfterCursor.setRange(0, 10000); + readStringsAfterCursor.setDefaultValue(30); + + useSystemPrompt.setSettingsKey(Constants::CC_USE_SYSTEM_PROMPT); + useSystemPrompt.setDefaultValue(true); + useSystemPrompt.setLabelText(Tr::tr("Use System Prompt")); + + systemPrompt.setSettingsKey(Constants::CC_SYSTEM_PROMPT); + systemPrompt.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + systemPrompt.setDefaultValue( + "You are an expert C++, Qt, and QML code completion AI. Your task is to provide accurate " + "and " + "contextually appropriate code suggestions. Focus on completing the code in a way that " + "follows best practices, is efficient, and matches the surrounding code style. Prioritize " + "Qt and QML-specific completions when appropriate. Avoid adding comments or explanations " + "in your completions."); + + useFilePathInContext.setSettingsKey(Constants::CC_USE_FILE_PATH_IN_CONTEXT); + useFilePathInContext.setDefaultValue(false); + useFilePathInContext.setLabelText(Tr::tr("Use File Path in Context")); + + useProjectChangesCache.setSettingsKey(Constants::CC_USE_PROJECT_CHANGES_CACHE); + useProjectChangesCache.setDefaultValue(true); + useProjectChangesCache.setLabelText(Tr::tr("Max Changes Cache Size:")); + + maxChangesCacheSize.setSettingsKey(Constants::CC_MAX_CHANGES_CACHE_SIZE); + maxChangesCacheSize.setRange(2, 1000); + maxChangesCacheSize.setDefaultValue(20); + + // Ollama Settings + ollamaLivetime.setSettingsKey(Constants::CC_OLLAMA_LIVETIME); + ollamaLivetime.setToolTip( + Tr::tr("Time to suspend Ollama after completion request (in minutes), " + "Only Ollama, -1 to disable")); + ollamaLivetime.setLabelText("Livetime:"); + ollamaLivetime.setDefaultValue("5m"); + ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + contextWindow.setSettingsKey(Constants::CC_OLLAMA_CONTEXT_WINDOW); + contextWindow.setLabelText(Tr::tr("Context Window:")); + contextWindow.setRange(-1, 10000); + contextWindow.setDefaultValue(2048); + + // API Configuration Settings + apiKey.setSettingsKey(Constants::CC_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(); + + readFileParts.setValue(!readFullFile.value()); + + setupConnections(); + + setLayouter([this]() { + using namespace Layouting; + + auto genGrid = Grid{}; + genGrid.addRow({Row{temperature}}); + genGrid.addRow({Row{maxTokens}}); + + auto advancedGrid = Grid{}; + advancedGrid.addRow({useTopP, topP}); + advancedGrid.addRow({useTopK, topK}); + advancedGrid.addRow({usePresencePenalty, presencePenalty}); + advancedGrid.addRow({useFrequencyPenalty, frequencyPenalty}); + + auto ollamaGrid = Grid{}; + ollamaGrid.addRow({ollamaLivetime}); + ollamaGrid.addRow({contextWindow}); + + auto contextGrid = Grid{}; + contextGrid.addRow({Row{readFullFile}}); + contextGrid.addRow({Row{readFileParts, readStringsBeforeCursor, readStringsAfterCursor}}); + auto contextItem = Column{Row{contextGrid, Stretch{1}}, + Row{useSystemPrompt, Stretch{1}}, + systemPrompt, + Row{useFilePathInContext, Stretch{1}}, + Row{useProjectChangesCache, maxChangesCacheSize, Stretch{1}}}; + + return Column{Row{Stretch{1}, resetToDefaults}, + Space{8}, + Group{title(Tr::tr("Auto Completion Settings")), + Column{ + autoCompletion, + Space{8}, + multiLineCompletion, + }}, + Space{16}, + Group{title(Tr::tr("General Parameters")), + Column{ + Row{genGrid, Stretch{1}}, + }}, + Space{16}, + Group{title(Tr::tr("Advanced Parameters")), + Column{Row{advancedGrid, Stretch{1}}}}, + Space{16}, + Group{title(Tr::tr("Context Settings")), contextItem}, + Space{16}, + Group{title(Tr::tr("Ollama Settings")), Column{Row{ollamaGrid, Stretch{1}}}}, + Space{16}, + Group{title(Tr::tr("API Configuration")), Column{apiKey}}, + Stretch{1}}; + }); +} + +void CodeCompletionSettings::setupConnections() +{ + connect(&resetToDefaults, + &ButtonAspect::clicked, + this, + &CodeCompletionSettings::resetSettingsToDefaults); + + connect(&readFullFile, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + if (readFullFile.volatileValue()) { + readFileParts.setValue(false); + writeSettings(); + } + }); + + connect(&readFileParts, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + if (readFileParts.volatileValue()) { + readFullFile.setValue(false); + writeSettings(); + } + }); +} + +void CodeCompletionSettings::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(autoCompletion); + resetAspect(multiLineCompletion); + resetAspect(temperature); + resetAspect(maxTokens); + resetAspect(useTopP); + resetAspect(topP); + resetAspect(useTopK); + resetAspect(topK); + resetAspect(usePresencePenalty); + resetAspect(presencePenalty); + resetAspect(useFrequencyPenalty); + resetAspect(frequencyPenalty); + resetAspect(readFullFile); + resetAspect(readFileParts); + resetAspect(readStringsBeforeCursor); + resetAspect(readStringsAfterCursor); + resetAspect(useSystemPrompt); + resetAspect(systemPrompt); + resetAspect(useFilePathInContext); + resetAspect(useProjectChangesCache); + resetAspect(maxChangesCacheSize); + resetAspect(ollamaLivetime); + resetAspect(contextWindow); + } +} + +class CodeCompletionSettingsPage : public Core::IOptionsPage +{ +public: + CodeCompletionSettingsPage() + { + setId(Constants::QODE_ASSIST_CODE_COMPLETION_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("Code Completion")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &codeCompletionSettings(); }); + } +}; + +const CodeCompletionSettingsPage codeCompletionSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/CodeCompletionSettings.hpp b/settings/CodeCompletionSettings.hpp new file mode 100644 index 0000000..206e9f6 --- /dev/null +++ b/settings/CodeCompletionSettings.hpp @@ -0,0 +1,81 @@ +/* + * 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 "ButtonAspect.hpp" + +namespace QodeAssist::Settings { + +class CodeCompletionSettings : public Utils::AspectContainer +{ +public: + CodeCompletionSettings(); + + ButtonAspect resetToDefaults{this}; + + // Auto Completion Settings + Utils::BoolAspect autoCompletion{this}; + Utils::BoolAspect multiLineCompletion{this}; + + // General Parameters Settings + Utils::DoubleAspect temperature{this}; + Utils::IntegerAspect maxTokens{this}; + + Utils::BoolAspect useTopP{this}; + Utils::DoubleAspect topP{this}; + + Utils::BoolAspect useTopK{this}; + Utils::IntegerAspect topK{this}; + + // Advanced Parameters + Utils::BoolAspect usePresencePenalty{this}; + Utils::DoubleAspect presencePenalty{this}; + + Utils::BoolAspect useFrequencyPenalty{this}; + Utils::DoubleAspect frequencyPenalty{this}; + + // Context Settings + Utils::BoolAspect readFullFile{this}; + Utils::BoolAspect readFileParts{this}; + Utils::IntegerAspect readStringsBeforeCursor{this}; + Utils::IntegerAspect readStringsAfterCursor{this}; + Utils::BoolAspect useSystemPrompt{this}; + Utils::StringAspect systemPrompt{this}; + Utils::BoolAspect useFilePathInContext{this}; + Utils::BoolAspect useProjectChangesCache{this}; + Utils::IntegerAspect maxChangesCacheSize{this}; + + // Ollama Settings + Utils::StringAspect ollamaLivetime{this}; + Utils::IntegerAspect contextWindow{this}; + + // API Configuration Settings + Utils::StringAspect apiKey{this}; + +private: + void setupConnections(); + void resetSettingsToDefaults(); +}; + +CodeCompletionSettings &codeCompletionSettings(); + +} // namespace QodeAssist::Settings diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index d861f03..c4cfb0e 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -41,29 +41,29 @@ ContextSettings::ContextSettings() setDisplayName(Tr::tr("Context")); - readFullFile.setSettingsKey(Constants::READ_FULL_FILE); + readFullFile.setSettingsKey(Constants::CC_READ_FULL_FILE); readFullFile.setLabelText(Tr::tr("Read Full File")); readFullFile.setDefaultValue(false); - readStringsBeforeCursor.setSettingsKey(Constants::READ_STRINGS_BEFORE_CURSOR); + readStringsBeforeCursor.setSettingsKey(Constants::CC_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.setSettingsKey(Constants::CC_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.setSettingsKey(Constants::CC_USE_FILE_PATH_IN_CONTEXT); useFilePathInContext.setDefaultValue(false); useFilePathInContext.setLabelText(Tr::tr("Use File Path in Context")); - useSystemPrompt.setSettingsKey(Constants::USE_SYSTEM_PROMPT); + useSystemPrompt.setSettingsKey(Constants::CC_USE_SYSTEM_PROMPT); useSystemPrompt.setDefaultValue(true); useSystemPrompt.setLabelText(Tr::tr("Use System Prompt")); - systemPrompt.setSettingsKey(Constants::SYSTEM_PROMPT); + systemPrompt.setSettingsKey(Constants::CC_SYSTEM_PROMPT); systemPrompt.setDisplayStyle(Utils::StringAspect::TextEditDisplay); systemPrompt.setDefaultValue( "You are an expert C++, Qt, and QML code completion AI. Your task is to provide accurate " @@ -93,11 +93,11 @@ ContextSettings::ContextSettings() resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); - useProjectChangesCache.setSettingsKey(Constants::USE_PROJECT_CHANGES_CACHE); + useProjectChangesCache.setSettingsKey(Constants::CC_USE_PROJECT_CHANGES_CACHE); useProjectChangesCache.setDefaultValue(true); useProjectChangesCache.setLabelText(Tr::tr("Use Project Changes Cache")); - maxChangesCacheSize.setSettingsKey(Constants::MAX_CHANGES_CACHE_SIZE); + maxChangesCacheSize.setSettingsKey(Constants::CC_MAX_CHANGES_CACHE_SIZE); maxChangesCacheSize.setLabelText(Tr::tr("Max Changes Cache Size")); maxChangesCacheSize.setRange(2, 1000); maxChangesCacheSize.setDefaultValue(20); diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp index 6c2a1b6..97d847c 100644 --- a/settings/PresetPromptsSettings.cpp +++ b/settings/PresetPromptsSettings.cpp @@ -42,7 +42,7 @@ PresetPromptsSettings::PresetPromptsSettings() setDisplayName(Tr::tr("Preset Prompts Params")); - fimTemperature.setSettingsKey(Constants::FIM_TEMPERATURE); + fimTemperature.setSettingsKey(Constants::CC_TEMPERATURE); fimTemperature.setLabelText(Tr::tr("Temperature:")); fimTemperature.setDefaultValue(0.2); fimTemperature.setRange(0.0, 10.0); @@ -54,7 +54,7 @@ PresetPromptsSettings::PresetPromptsSettings() chatTemperature.setRange(0.0, 10.0); chatTemperature.setSingleStep(0.1); - fimOllamaLivetime.setSettingsKey(Constants::FIM_OLLAMA_LIVETIME); + fimOllamaLivetime.setSettingsKey(Constants::CC_OLLAMA_LIVETIME); fimOllamaLivetime.setLabelText( Tr::tr("Time to suspend Ollama after completion request (in minutes), " "Only Ollama, -1 to disable")); @@ -68,7 +68,7 @@ PresetPromptsSettings::PresetPromptsSettings() chatOllamaLivetime.setDefaultValue("5m"); chatOllamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - fimMaxTokens.setSettingsKey(Constants::FIM_MAX_TOKENS); + fimMaxTokens.setSettingsKey(Constants::CC_MAX_TOKENS); fimMaxTokens.setLabelText(Tr::tr("Max Tokens")); fimMaxTokens.setRange(-1, 10000); fimMaxTokens.setDefaultValue(50); @@ -78,10 +78,10 @@ PresetPromptsSettings::PresetPromptsSettings() chatMaxTokens.setRange(-1, 10000); chatMaxTokens.setDefaultValue(2000); - fimUseTopP.setSettingsKey(Constants::FIM_USE_TOP_P); + fimUseTopP.setSettingsKey(Constants::CC_USE_TOP_P); fimUseTopP.setDefaultValue(false); - fimTopP.setSettingsKey(Constants::FIM_TOP_P); + fimTopP.setSettingsKey(Constants::CC_TOP_P); fimTopP.setLabelText(Tr::tr("use top_p")); fimTopP.setDefaultValue(0.9); fimTopP.setRange(0.0, 1.0); @@ -96,10 +96,10 @@ PresetPromptsSettings::PresetPromptsSettings() chatTopP.setRange(0.0, 1.0); chatTopP.setSingleStep(0.1); - fimUseTopK.setSettingsKey(Constants::FIM_USE_TOP_K); + fimUseTopK.setSettingsKey(Constants::CC_USE_TOP_K); fimUseTopK.setDefaultValue(false); - fimTopK.setSettingsKey(Constants::FIM_TOP_K); + fimTopK.setSettingsKey(Constants::CC_TOP_K); fimTopK.setLabelText(Tr::tr("use top_k")); fimTopK.setDefaultValue(50); fimTopK.setRange(1, 1000); @@ -112,10 +112,10 @@ PresetPromptsSettings::PresetPromptsSettings() chatTopK.setDefaultValue(50); chatTopK.setRange(1, 1000); - fimUsePresencePenalty.setSettingsKey(Constants::FIM_USE_PRESENCE_PENALTY); + fimUsePresencePenalty.setSettingsKey(Constants::CC_USE_PRESENCE_PENALTY); fimUsePresencePenalty.setDefaultValue(false); - fimPresencePenalty.setSettingsKey(Constants::FIM_PRESENCE_PENALTY); + fimPresencePenalty.setSettingsKey(Constants::CC_PRESENCE_PENALTY); fimPresencePenalty.setLabelText(Tr::tr("use presence_penalty")); fimPresencePenalty.setDefaultValue(0.0); fimPresencePenalty.setRange(-2.0, 2.0); @@ -130,10 +130,10 @@ PresetPromptsSettings::PresetPromptsSettings() chatPresencePenalty.setRange(-2.0, 2.0); chatPresencePenalty.setSingleStep(0.1); - fimUseFrequencyPenalty.setSettingsKey(Constants::FIM_USE_FREQUENCY_PENALTY); + fimUseFrequencyPenalty.setSettingsKey(Constants::CC_USE_FREQUENCY_PENALTY); fimUseFrequencyPenalty.setDefaultValue(false); - fimFrequencyPenalty.setSettingsKey(Constants::FIM_FREQUENCY_PENALTY); + fimFrequencyPenalty.setSettingsKey(Constants::CC_FREQUENCY_PENALTY); fimFrequencyPenalty.setLabelText(Tr::tr("use frequency_penalty")); fimFrequencyPenalty.setDefaultValue(0.0); fimFrequencyPenalty.setRange(-2.0, 2.0); @@ -148,7 +148,7 @@ PresetPromptsSettings::PresetPromptsSettings() chatFrequencyPenalty.setRange(-2.0, 2.0); chatFrequencyPenalty.setSingleStep(0.1); - fimApiKey.setSettingsKey(Constants::FIM_API_KEY); + fimApiKey.setSettingsKey(Constants::CC_API_KEY); fimApiKey.setLabelText(Tr::tr("API Key:")); fimApiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); fimApiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 1c66d3e..3c568c6 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -37,35 +37,25 @@ const char CA_URL[] = "QodeAssist.caUrl"; // settings const char ENABLE_QODE_ASSIST[] = "QodeAssist.enableQodeAssist"; -const char ENABLE_AUTO_COMPLETE[] = "QodeAssist.enableAutoComplete"; +const char CC_AUTO_COMPLETION[] = "QodeAssist.ccAutoCompletion"; const char ENABLE_LOGGING[] = "QodeAssist.enableLogging"; -const char LLM_PROVIDERS[] = "QodeAssist.llmProviders"; -const char URL[] = "QodeAssist.url"; -const char END_POINT[] = "QodeAssist.endPoint"; -const char MODEL_NAME[] = "QodeAssist.modelName"; -const char SELECT_MODELS[] = "QodeAssist.selectModels"; -const char FIM_PROMPTS[] = "QodeAssist.fimPrompts"; 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 MULTILINE_COMPLETION[] = "QodeAssist.multilineCompletion"; +const char CC_MULTILINE_COMPLETION[] = "QodeAssist.ccMultilineCompletion"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; -const char CHAT_LLM_PROVIDERS[] = "QodeAssist.chatLlmProviders"; -const char CHAT_URL[] = "QodeAssist.chatUrl"; -const char CHAT_END_POINT[] = "QodeAssist.chatEndPoint"; -const char CHAT_MODEL_NAME[] = "QodeAssist.chatModelName"; -const char CHAT_SELECT_MODELS[] = "QodeAssist.chatSelectModels"; -const char CHAT_PROMPTS[] = "QodeAssist.chatPrompts"; const char CHAT_TOKENS_THRESHOLD[] = "QodeAssist.chatTokensThreshold"; 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_CODE_COMPLETION_SETTINGS_PAGE_ID[] + = "QodeAssist.2CodeCompletionSettingsPageId"; +const char QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID[] = "QodeAssist.3ContextSettingsPageId"; const char QODE_ASSIST_PRESET_PROMPTS_SETTINGS_PAGE_ID[] - = "QodeAssist.3PresetPromptsSettingsPageId"; -const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.4CustomPromptSettingsPageId"; + = "QodeAssist.4PresetPromptsSettingsPageId"; +const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.5CustomPromptSettingsPageId"; const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; const char QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY[] = "Qode Assist"; @@ -73,30 +63,31 @@ const char QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY[] = "Qode Assist"; const char QODE_ASSIST_REQUEST_SUGGESTION[] = "QodeAssist.RequestSuggestion"; // context settings -const char READ_FULL_FILE[] = "QodeAssist.readFullFile"; -const char READ_STRINGS_BEFORE_CURSOR[] = "QodeAssist.readStringsBeforeCursor"; -const char READ_STRINGS_AFTER_CURSOR[] = "QodeAssist.readStringsAfterCursor"; -const char USE_SYSTEM_PROMPT[] = "QodeAssist.useSystemPrompt"; -const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext"; -const char SYSTEM_PROMPT[] = "QodeAssist.systemPrompt"; -const char USE_PROJECT_CHANGES_CACHE[] = "QodeAssist.useProjectChangesCache"; -const char MAX_CHANGES_CACHE_SIZE[] = "QodeAssist.maxChangesCacheSize"; +const char CC_READ_FULL_FILE[] = "QodeAssist.ccReadFullFile"; +const char CC_READ_STRINGS_BEFORE_CURSOR[] = "QodeAssist.ccReadStringsBeforeCursor"; +const char CC_READ_STRINGS_AFTER_CURSOR[] = "QodeAssist.ccReadStringsAfterCursor"; +const char CC_USE_SYSTEM_PROMPT[] = "QodeAssist.ccUseSystemPrompt"; +const char CC_USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.ccUseFilePathInContext"; +const char CC_SYSTEM_PROMPT[] = "QodeAssist.ccSystemPrompt"; +const char CC_USE_PROJECT_CHANGES_CACHE[] = "QodeAssist.ccUseProjectChangesCache"; +const char CC_MAX_CHANGES_CACHE_SIZE[] = "QodeAssist.ccMaxChangesCacheSize"; const char USE_CHAT_SYSTEM_PROMPT[] = "QodeAssist.useChatSystemPrompt"; const char CHAT_SYSTEM_PROMPT[] = "QodeAssist.chatSystemPrompt"; // preset prompt settings -const char FIM_TEMPERATURE[] = "QodeAssist.fimTemperature"; -const char FIM_MAX_TOKENS[] = "QodeAssist.fimMaxTokens"; -const char FIM_USE_TOP_P[] = "QodeAssist.fimUseTopP"; -const char FIM_TOP_P[] = "QodeAssist.fimTopP"; -const char FIM_USE_TOP_K[] = "QodeAssist.fimUseTopK"; -const char FIM_TOP_K[] = "QodeAssist.fimTopK"; -const char FIM_USE_PRESENCE_PENALTY[] = "QodeAssist.fimUsePresencePenalty"; -const char FIM_PRESENCE_PENALTY[] = "QodeAssist.fimPresencePenalty"; -const char FIM_USE_FREQUENCY_PENALTY[] = "QodeAssist.fimUseFrequencyPenalty"; -const char FIM_FREQUENCY_PENALTY[] = "QodeAssist.fimFrequencyPenalty"; -const char FIM_OLLAMA_LIVETIME[] = "QodeAssist.fimOllamaLivetime"; -const char FIM_API_KEY[] = "QodeAssist.apiKey"; +const char CC_TEMPERATURE[] = "QodeAssist.ccTemperature"; +const char CC_MAX_TOKENS[] = "QodeAssist.ccMaxTokens"; +const char CC_USE_TOP_P[] = "QodeAssist.ccUseTopP"; +const char CC_TOP_P[] = "QodeAssist.ccTopP"; +const char CC_USE_TOP_K[] = "QodeAssist.ccUseTopK"; +const char CC_TOP_K[] = "QodeAssist.ccTopK"; +const char CC_USE_PRESENCE_PENALTY[] = "QodeAssist.ccUsePresencePenalty"; +const char CC_PRESENCE_PENALTY[] = "QodeAssist.ccPresencePenalty"; +const char CC_USE_FREQUENCY_PENALTY[] = "QodeAssist.fimUseFrequencyPenalty"; +const char CC_FREQUENCY_PENALTY[] = "QodeAssist.fimFrequencyPenalty"; +const char CC_OLLAMA_LIVETIME[] = "QodeAssist.fimOllamaLivetime"; +const char CC_OLLAMA_CONTEXT_WINDOW[] = "QodeAssist.ccOllamaContextWindow"; +const char CC_API_KEY[] = "QodeAssist.apiKey"; const char CHAT_TEMPERATURE[] = "QodeAssist.chatTemperature"; const char CHAT_MAX_TOKENS[] = "QodeAssist.chatMaxTokens"; const char CHAT_USE_TOP_P[] = "QodeAssist.chatUseTopP"; From 85d039cbd58b2ffc29a868f085e1886a8b1eab0d Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 10 Nov 2024 22:13:33 +0100 Subject: [PATCH 4/8] Rework Chat Assistant Settings --- ConfigurationManager.cpp | 12 -- ConfigurationManager.hpp | 3 - LLMClientInterface.cpp | 9 +- chatview/ChatModel.cpp | 17 +- chatview/ChatRootView.cpp | 10 +- chatview/ClientInterface.cpp | 80 +++++----- settings/CMakeLists.txt | 1 + settings/ChatAssistantSettings.cpp | 231 ++++++++++++++++++++++++++++ settings/ChatAssistantSettings.hpp | 73 +++++++++ settings/CodeCompletionSettings.cpp | 21 ++- settings/CodeCompletionSettings.hpp | 2 +- settings/ContextSettings.cpp | 4 +- settings/PresetPromptsSettings.cpp | 24 +-- settings/SettingsConstants.hpp | 39 ++--- 14 files changed, 412 insertions(+), 114 deletions(-) create mode 100644 settings/ChatAssistantSettings.cpp create mode 100644 settings/ChatAssistantSettings.hpp diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp index e3cdb6e..5ab05ff 100644 --- a/ConfigurationManager.cpp +++ b/ConfigurationManager.cpp @@ -37,18 +37,6 @@ void ConfigurationManager::init() setupConnections(); } -LLMCore::Provider *ConfigurationManager::getCurrentProvider() -{ - auto providerName = Settings::generalSettings().ccProvider(); - return LLMCore::ProvidersManager::instance().getProviderByName(providerName); -} - -LLMCore::PromptTemplate *ConfigurationManager::getCurrentTemplate() -{ - auto templateName = Settings::generalSettings().ccTemplate(); - return LLMCore::PromptTemplateManager::instance().getFimTemplateByName(templateName); -} - ConfigurationManager::ConfigurationManager(QObject *parent) : QObject(parent) , m_generalSettings(Settings::generalSettings()) diff --git a/ConfigurationManager.hpp b/ConfigurationManager.hpp index ffe033c..3d2d414 100644 --- a/ConfigurationManager.hpp +++ b/ConfigurationManager.hpp @@ -36,9 +36,6 @@ public: void init(); - LLMCore::Provider *getCurrentProvider(); - LLMCore::PromptTemplate *getCurrentTemplate(); - public slots: void selectProvider(); void selectModel(); diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 3d047f1..d94ea72 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -151,9 +151,12 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request) auto updatedContext = prepareContext(request); auto &completeSettings = Settings::codeCompletionSettings(); - auto &configManager = ConfigurationManager::instance(); - auto provider = configManager.getCurrentProvider(); - auto promptTemplate = configManager.getCurrentTemplate(); + auto providerName = Settings::generalSettings().ccProvider(); + auto provider = LLMCore::ProvidersManager::instance().getProviderByName(providerName); + + auto templateName = Settings::generalSettings().ccTemplate(); + auto promptTemplate = LLMCore::PromptTemplateManager::instance().getFimTemplateByName( + templateName); LLMCore::LLMConfig config; config.requestType = LLMCore::RequestType::Fim; diff --git a/chatview/ChatModel.cpp b/chatview/ChatModel.cpp index 0656075..d39c994 100644 --- a/chatview/ChatModel.cpp +++ b/chatview/ChatModel.cpp @@ -22,7 +22,7 @@ #include #include -#include "GeneralSettings.hpp" +#include "ChatAssistantSettings.hpp" namespace QodeAssist::Chat { @@ -30,12 +30,12 @@ ChatModel::ChatModel(QObject *parent) : QAbstractListModel(parent) , m_totalTokens(0) { - // auto &settings = Settings::generalSettings(); + auto &settings = Settings::chatAssistantSettings(); - // connect(&settings.chatTokensThreshold, - // &Utils::BaseAspect::changed, - // this, - // &ChatModel::tokensThresholdChanged); + connect(&settings.chatTokensThreshold, + &Utils::BaseAspect::changed, + this, + &ChatModel::tokensThresholdChanged); } int ChatModel::rowCount(const QModelIndex &parent) const @@ -183,9 +183,8 @@ int ChatModel::totalTokens() const int ChatModel::tokensThreshold() const { - // auto &settings = Settings::generalSettings(); - // return settings.chatTokensThreshold(); - return 0; + auto &settings = Settings::chatAssistantSettings(); + return settings.chatTokensThreshold(); } QString ChatModel::lastMessageId() const diff --git a/chatview/ChatRootView.cpp b/chatview/ChatRootView.cpp index 180c4ea..136a3aa 100644 --- a/chatview/ChatRootView.cpp +++ b/chatview/ChatRootView.cpp @@ -31,12 +31,12 @@ ChatRootView::ChatRootView(QQuickItem *parent) , m_chatModel(new ChatModel(this)) , m_clientInterface(new ClientInterface(m_chatModel, this)) { - // auto &settings = Settings::generalSettings(); + auto &settings = Settings::generalSettings(); - // connect(&settings.chatModelName, - // &Utils::BaseAspect::changed, - // this, - // &ChatRootView::currentTemplateChanged); + connect(&settings.caModel, + &Utils::BaseAspect::changed, + this, + &ChatRootView::currentTemplateChanged); generateColors(); } diff --git a/chatview/ClientInterface.cpp b/chatview/ClientInterface.cpp index b99c7b8..a75e99a 100644 --- a/chatview/ClientInterface.cpp +++ b/chatview/ClientInterface.cpp @@ -18,16 +18,17 @@ */ #include "ClientInterface.hpp" -#include "ContextSettings.hpp" -#include "GeneralSettings.hpp" -#include "Logger.hpp" -#include "PromptTemplateManager.hpp" -#include "ProvidersManager.hpp" #include #include #include +#include "ChatAssistantSettings.hpp" +#include "GeneralSettings.hpp" +#include "Logger.hpp" +#include "PromptTemplateManager.hpp" +#include "ProvidersManager.hpp" + namespace QodeAssist::Chat { ClientInterface::ClientInterface(ChatModel *chatModel, QObject *parent) @@ -56,46 +57,51 @@ ClientInterface::~ClientInterface() = default; void ClientInterface::sendMessage(const QString &message) { - // cancelRequest(); + cancelRequest(); - // LOG_MESSAGE("Sending message: " + message); - // LOG_MESSAGE("chatProvider " + Settings::generalSettings().chatLlmProviders.stringValue()); - // LOG_MESSAGE("chatTemplate " + Settings::generalSettings().chatPrompts.stringValue()); + auto &chatAssistantSettings = Settings::chatAssistantSettings(); - // auto chatTemplate = LLMCore::PromptTemplateManager::instance().getCurrentChatTemplate(); - // auto chatProvider = LLMCore::ProvidersManager::instance().getCurrentChatProvider(); + auto providerName = Settings::generalSettings().caProvider(); + auto provider = LLMCore::ProvidersManager::instance().getProviderByName(providerName); - // LLMCore::ContextData context; - // context.prefix = message; - // context.suffix = ""; - // if (Settings::contextSettings().useChatSystemPrompt()) - // context.systemPrompt = Settings::contextSettings().chatSystemPrompt(); + auto templateName = Settings::generalSettings().caTemplate(); + auto promptTemplate = LLMCore::PromptTemplateManager::instance().getChatTemplateByName( + templateName); - // QJsonObject providerRequest; - // providerRequest["model"] = Settings::generalSettings().chatModelName(); - // providerRequest["stream"] = true; - // providerRequest["messages"] = m_chatModel->prepareMessagesForRequest(context); + LLMCore::ContextData context; + context.prefix = message; + context.suffix = ""; + if (chatAssistantSettings.useSystemPrompt()) + context.systemPrompt = chatAssistantSettings.systemPrompt(); - // if (!chatTemplate || !chatProvider) { - // LOG_MESSAGE("Check settings, provider or template are not set"); - // } - // chatTemplate->prepareRequest(providerRequest, context); - // chatProvider->prepareRequest(providerRequest, LLMCore::RequestType::Chat); + QJsonObject providerRequest; + providerRequest["model"] = Settings::generalSettings().caModel(); + providerRequest["stream"] = true; + providerRequest["messages"] = m_chatModel->prepareMessagesForRequest(context); - // LLMCore::LLMConfig config; - // config.requestType = LLMCore::RequestType::Chat; - // config.provider = chatProvider; - // config.promptTemplate = chatTemplate; - // config.url = QString("%1%2").arg(Settings::generalSettings().chatUrl(), - // Settings::generalSettings().chatEndPoint()); - // config.providerRequest = providerRequest; - // config.multiLineCompletion = Settings::generalSettings().multiLineCompletion(); + if (promptTemplate) + promptTemplate->prepareRequest(providerRequest, context); + else + qWarning("No prompt template found"); - // QJsonObject request; - // request["id"] = QUuid::createUuid().toString(); + if (provider) + provider->prepareRequest(providerRequest, LLMCore::RequestType::Chat); + else + qWarning("No provider found"); - // m_chatModel->addMessage(message, ChatModel::ChatRole::User, ""); - // m_requestHandler->sendLLMRequest(config, request); + LLMCore::LLMConfig config; + config.requestType = LLMCore::RequestType::Chat; + config.provider = provider; + config.promptTemplate = promptTemplate; + config.url = QString("%1%2").arg(Settings::generalSettings().caUrl(), provider->chatEndpoint()); + config.providerRequest = providerRequest; + config.multiLineCompletion = false; + + QJsonObject request; + request["id"] = QUuid::createUuid().toString(); + + m_chatModel->addMessage(message, ChatModel::ChatRole::User, ""); + m_requestHandler->sendLLMRequest(config, request); } void ClientInterface::clearMessages() diff --git a/settings/CMakeLists.txt b/settings/CMakeLists.txt index 57a266d..84fe20f 100644 --- a/settings/CMakeLists.txt +++ b/settings/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(QodeAssistSettings STATIC ButtonAspect.hpp SettingsTr.hpp CodeCompletionSettings.hpp CodeCompletionSettings.cpp + ChatAssistantSettings.hpp ChatAssistantSettings.cpp ) target_link_libraries(QodeAssistSettings diff --git a/settings/ChatAssistantSettings.cpp b/settings/ChatAssistantSettings.cpp new file mode 100644 index 0000000..f4d7dc6 --- /dev/null +++ b/settings/ChatAssistantSettings.cpp @@ -0,0 +1,231 @@ +/* + * 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 "ChatAssistantSettings.hpp" + +#include +#include +#include +#include + +#include "SettingsConstants.hpp" +#include "SettingsTr.hpp" +#include "SettingsUtils.hpp" + +namespace QodeAssist::Settings { + +ChatAssistantSettings &chatAssistantSettings() +{ + static ChatAssistantSettings settings; + return settings; +} + +ChatAssistantSettings::ChatAssistantSettings() +{ + setAutoApply(false); + + setDisplayName(Tr::tr("Chat Assistant")); + + // Chat Settings + chatTokensThreshold.setSettingsKey(Constants::CA_TOKENS_THRESHOLD); + chatTokensThreshold.setLabelText(Tr::tr("Chat History Token Limit:")); + chatTokensThreshold.setToolTip(Tr::tr("Maximum number of tokens in chat history. When " + "exceeded, oldest messages will be removed.")); + chatTokensThreshold.setRange(1000, 16000); + chatTokensThreshold.setDefaultValue(8000); + + // General Parameters Settings + temperature.setSettingsKey(Constants::CA_TEMPERATURE); + temperature.setLabelText(Tr::tr("Temperature:")); + temperature.setDefaultValue(0.5); + temperature.setRange(0.0, 2.0); + temperature.setSingleStep(0.1); + + maxTokens.setSettingsKey(Constants::CA_MAX_TOKENS); + maxTokens.setLabelText(Tr::tr("Max Tokens:")); + maxTokens.setRange(-1, 10000); + maxTokens.setDefaultValue(2000); + + // Advanced Parameters + useTopP.setSettingsKey(Constants::CA_USE_TOP_P); + useTopP.setDefaultValue(false); + useTopP.setLabelText(Tr::tr("Top P:")); + + topP.setSettingsKey(Constants::CA_TOP_P); + topP.setDefaultValue(0.9); + topP.setRange(0.0, 1.0); + topP.setSingleStep(0.1); + + useTopK.setSettingsKey(Constants::CA_USE_TOP_K); + useTopK.setDefaultValue(false); + useTopK.setLabelText(Tr::tr("Top K:")); + + topK.setSettingsKey(Constants::CA_TOP_K); + topK.setDefaultValue(50); + topK.setRange(1, 1000); + + usePresencePenalty.setSettingsKey(Constants::CA_USE_PRESENCE_PENALTY); + usePresencePenalty.setDefaultValue(false); + usePresencePenalty.setLabelText(Tr::tr("Presence Penalty:")); + + presencePenalty.setSettingsKey(Constants::CA_PRESENCE_PENALTY); + presencePenalty.setDefaultValue(0.0); + presencePenalty.setRange(-2.0, 2.0); + presencePenalty.setSingleStep(0.1); + + useFrequencyPenalty.setSettingsKey(Constants::CA_USE_FREQUENCY_PENALTY); + useFrequencyPenalty.setDefaultValue(false); + useFrequencyPenalty.setLabelText(Tr::tr("Frequency Penalty:")); + + frequencyPenalty.setSettingsKey(Constants::CA_FREQUENCY_PENALTY); + frequencyPenalty.setDefaultValue(0.0); + frequencyPenalty.setRange(-2.0, 2.0); + frequencyPenalty.setSingleStep(0.1); + + // Context Settings + useSystemPrompt.setSettingsKey(Constants::CA_USE_SYSTEM_PROMPT); + useSystemPrompt.setDefaultValue(true); + useSystemPrompt.setLabelText(Tr::tr("Use System Prompt")); + + systemPrompt.setSettingsKey(Constants::CA_SYSTEM_PROMPT); + systemPrompt.setDisplayStyle(Utils::StringAspect::TextEditDisplay); + systemPrompt.setDefaultValue( + "You are an advanced AI assistant specializing in C++, Qt, and QML development. Your role " + "is to provide helpful, accurate, and detailed responses to questions about coding, " + "debugging, " + "and best practices in these technologies."); + + // Ollama Settings + ollamaLivetime.setSettingsKey(Constants::CA_OLLAMA_LIVETIME); + ollamaLivetime.setToolTip( + Tr::tr("Time to suspend Ollama after completion request (in minutes), " + "Only Ollama, -1 to disable")); + ollamaLivetime.setLabelText("Livetime:"); + ollamaLivetime.setDefaultValue("5m"); + ollamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); + + contextWindow.setSettingsKey(Constants::CA_OLLAMA_CONTEXT_WINDOW); + contextWindow.setLabelText(Tr::tr("Context Window:")); + contextWindow.setRange(-1, 10000); + contextWindow.setDefaultValue(2048); + + // API Configuration Settings + apiKey.setSettingsKey(Constants::CA_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 = TrConstants::RESET_TO_DEFAULTS; + + readSettings(); + + setupConnections(); + + setLayouter([this]() { + using namespace Layouting; + + auto genGrid = Grid{}; + genGrid.addRow({Row{temperature}}); + genGrid.addRow({Row{maxTokens}}); + + auto advancedGrid = Grid{}; + advancedGrid.addRow({useTopP, topP}); + advancedGrid.addRow({useTopK, topK}); + advancedGrid.addRow({usePresencePenalty, presencePenalty}); + advancedGrid.addRow({useFrequencyPenalty, frequencyPenalty}); + + auto ollamaGrid = Grid{}; + ollamaGrid.addRow({ollamaLivetime}); + ollamaGrid.addRow({contextWindow}); + + return Column{Row{Stretch{1}, resetToDefaults}, + Space{8}, + Group{title(Tr::tr("Chat Settings")), Row{chatTokensThreshold, Stretch{1}}}, + Space{8}, + Group{ + title(Tr::tr("General Parameters")), + Row{genGrid, Stretch{1}}, + }, + Space{8}, + Group{title(Tr::tr("Advanced Parameters")), + Column{Row{advancedGrid, Stretch{1}}}}, + Space{8}, + Group{title(Tr::tr("Context Settings")), + Column{ + Row{useSystemPrompt, Stretch{1}}, + systemPrompt, + }}, + Group{title(Tr::tr("Ollama Settings")), Column{Row{ollamaGrid, Stretch{1}}}}, + Space{8}, + Group{title(Tr::tr("API Configuration")), Column{apiKey}}, + Stretch{1}}; + }); +} + +void ChatAssistantSettings::setupConnections() +{ + connect(&resetToDefaults, + &ButtonAspect::clicked, + this, + &ChatAssistantSettings::resetSettingsToDefaults); +} + +void ChatAssistantSettings::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(chatTokensThreshold); + resetAspect(temperature); + resetAspect(maxTokens); + resetAspect(useTopP); + resetAspect(topP); + resetAspect(useTopK); + resetAspect(topK); + resetAspect(usePresencePenalty); + resetAspect(presencePenalty); + resetAspect(useFrequencyPenalty); + resetAspect(frequencyPenalty); + resetAspect(useSystemPrompt); + resetAspect(systemPrompt); + resetAspect(ollamaLivetime); + resetAspect(contextWindow); + } +} + +class ChatAssistantSettingsPage : public Core::IOptionsPage +{ +public: + ChatAssistantSettingsPage() + { + setId(Constants::QODE_ASSIST_CHAT_ASSISTANT_SETTINGS_PAGE_ID); + setDisplayName(Tr::tr("Chat Assistant")); + setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY); + setSettingsProvider([] { return &chatAssistantSettings(); }); + } +}; + +const ChatAssistantSettingsPage chatAssistantSettingsPage; + +} // namespace QodeAssist::Settings diff --git a/settings/ChatAssistantSettings.hpp b/settings/ChatAssistantSettings.hpp new file mode 100644 index 0000000..3a4dde1 --- /dev/null +++ b/settings/ChatAssistantSettings.hpp @@ -0,0 +1,73 @@ +/* + * 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 "ButtonAspect.hpp" + +namespace QodeAssist::Settings { + +class ChatAssistantSettings : public Utils::AspectContainer +{ +public: + ChatAssistantSettings(); + + ButtonAspect resetToDefaults{this}; + + // Chat settings + Utils::IntegerAspect chatTokensThreshold{this}; + + // General Parameters Settings + Utils::DoubleAspect temperature{this}; + Utils::IntegerAspect maxTokens{this}; + + // Advanced Parameters + 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}; + + // Context Settings + Utils::BoolAspect useSystemPrompt{this}; + Utils::StringAspect systemPrompt{this}; + + // Ollama Settings + Utils::StringAspect ollamaLivetime{this}; + Utils::IntegerAspect contextWindow{this}; + + // API Configuration Settings + Utils::StringAspect apiKey{this}; + +private: + void setupConnections(); + void resetSettingsToDefaults(); +}; + +ChatAssistantSettings &chatAssistantSettings(); + +} // namespace QodeAssist::Settings diff --git a/settings/CodeCompletionSettings.cpp b/settings/CodeCompletionSettings.cpp index 90f81de..3379ff6 100644 --- a/settings/CodeCompletionSettings.cpp +++ b/settings/CodeCompletionSettings.cpp @@ -55,7 +55,7 @@ CodeCompletionSettings::CodeCompletionSettings() temperature.setSettingsKey(Constants::CC_TEMPERATURE); temperature.setLabelText(Tr::tr("Temperature:")); temperature.setDefaultValue(0.2); - temperature.setRange(0.0, 10.0); + temperature.setRange(0.0, 2.0); temperature.setSingleStep(0.1); maxTokens.setSettingsKey(Constants::CC_MAX_TOKENS); @@ -63,6 +63,7 @@ CodeCompletionSettings::CodeCompletionSettings() maxTokens.setRange(-1, 10000); maxTokens.setDefaultValue(50); + // Advanced Parameters useTopP.setSettingsKey(Constants::CC_USE_TOP_P); useTopP.setDefaultValue(false); useTopP.setLabelText(Tr::tr("Top P:")); @@ -80,7 +81,6 @@ CodeCompletionSettings::CodeCompletionSettings() topK.setDefaultValue(50); topK.setRange(1, 1000); - // Advanced Parameters usePresencePenalty.setSettingsKey(Constants::CC_USE_PRESENCE_PENALTY); usePresencePenalty.setDefaultValue(false); usePresencePenalty.setLabelText(Tr::tr("Presence Penalty:")); @@ -124,11 +124,7 @@ CodeCompletionSettings::CodeCompletionSettings() systemPrompt.setDisplayStyle(Utils::StringAspect::TextEditDisplay); systemPrompt.setDefaultValue( "You are an expert C++, Qt, and QML code completion AI. Your task is to provide accurate " - "and " - "contextually appropriate code suggestions. Focus on completing the code in a way that " - "follows best practices, is efficient, and matches the surrounding code style. Prioritize " - "Qt and QML-specific completions when appropriate. Avoid adding comments or explanations " - "in your completions."); + "and contextually appropriate code suggestions."); useFilePathInContext.setSettingsKey(Constants::CC_USE_FILE_PATH_IN_CONTEXT); useFilePathInContext.setDefaultValue(false); @@ -190,6 +186,7 @@ CodeCompletionSettings::CodeCompletionSettings() auto contextGrid = Grid{}; contextGrid.addRow({Row{readFullFile}}); contextGrid.addRow({Row{readFileParts, readStringsBeforeCursor, readStringsAfterCursor}}); + auto contextItem = Column{Row{contextGrid, Stretch{1}}, Row{useSystemPrompt, Stretch{1}}, systemPrompt, @@ -204,19 +201,19 @@ CodeCompletionSettings::CodeCompletionSettings() Space{8}, multiLineCompletion, }}, - Space{16}, + Space{8}, Group{title(Tr::tr("General Parameters")), Column{ Row{genGrid, Stretch{1}}, }}, - Space{16}, + Space{8}, Group{title(Tr::tr("Advanced Parameters")), Column{Row{advancedGrid, Stretch{1}}}}, - Space{16}, + Space{8}, Group{title(Tr::tr("Context Settings")), contextItem}, - Space{16}, + Space{8}, Group{title(Tr::tr("Ollama Settings")), Column{Row{ollamaGrid, Stretch{1}}}}, - Space{16}, + Space{8}, Group{title(Tr::tr("API Configuration")), Column{apiKey}}, Stretch{1}}; }); diff --git a/settings/CodeCompletionSettings.hpp b/settings/CodeCompletionSettings.hpp index 206e9f6..52b2d8f 100644 --- a/settings/CodeCompletionSettings.hpp +++ b/settings/CodeCompletionSettings.hpp @@ -40,13 +40,13 @@ public: Utils::DoubleAspect temperature{this}; Utils::IntegerAspect maxTokens{this}; + // Advanced Parameters Utils::BoolAspect useTopP{this}; Utils::DoubleAspect topP{this}; Utils::BoolAspect useTopK{this}; Utils::IntegerAspect topK{this}; - // Advanced Parameters Utils::BoolAspect usePresencePenalty{this}; Utils::DoubleAspect presencePenalty{this}; diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index c4cfb0e..c66683a 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -73,11 +73,11 @@ ContextSettings::ContextSettings() "Qt and QML-specific completions when appropriate. Avoid adding comments or explanations " "in your completions."); - useChatSystemPrompt.setSettingsKey(Constants::USE_CHAT_SYSTEM_PROMPT); + useChatSystemPrompt.setSettingsKey(Constants::CA_SYSTEM_PROMPT); useChatSystemPrompt.setDefaultValue(true); useChatSystemPrompt.setLabelText(Tr::tr("Use System Prompt for chat")); - chatSystemPrompt.setSettingsKey(Constants::CHAT_SYSTEM_PROMPT); + chatSystemPrompt.setSettingsKey(Constants::CA_SYSTEM_PROMPT); chatSystemPrompt.setDisplayStyle(Utils::StringAspect::TextEditDisplay); chatSystemPrompt.setDefaultValue( "You are an advanced AI assistant specializing in C++, Qt, and QML development. Your role " diff --git a/settings/PresetPromptsSettings.cpp b/settings/PresetPromptsSettings.cpp index 97d847c..3132c7f 100644 --- a/settings/PresetPromptsSettings.cpp +++ b/settings/PresetPromptsSettings.cpp @@ -48,7 +48,7 @@ PresetPromptsSettings::PresetPromptsSettings() fimTemperature.setRange(0.0, 10.0); fimTemperature.setSingleStep(0.1); - chatTemperature.setSettingsKey(Constants::CHAT_TEMPERATURE); + chatTemperature.setSettingsKey(Constants::CA_TEMPERATURE); chatTemperature.setLabelText(Tr::tr("Temperature:")); chatTemperature.setDefaultValue(0.5); chatTemperature.setRange(0.0, 10.0); @@ -61,7 +61,7 @@ PresetPromptsSettings::PresetPromptsSettings() fimOllamaLivetime.setDefaultValue("5m"); fimOllamaLivetime.setDisplayStyle(Utils::StringAspect::LineEditDisplay); - chatOllamaLivetime.setSettingsKey(Constants::CHAT_OLLAMA_LIVETIME); + chatOllamaLivetime.setSettingsKey(Constants::CA_OLLAMA_LIVETIME); chatOllamaLivetime.setLabelText( Tr::tr("Time to suspend Ollama after completion request (in minutes), " "Only Ollama, -1 to disable")); @@ -73,7 +73,7 @@ PresetPromptsSettings::PresetPromptsSettings() fimMaxTokens.setRange(-1, 10000); fimMaxTokens.setDefaultValue(50); - chatMaxTokens.setSettingsKey(Constants::CHAT_MAX_TOKENS); + chatMaxTokens.setSettingsKey(Constants::CA_MAX_TOKENS); chatMaxTokens.setLabelText(Tr::tr("Max Tokens")); chatMaxTokens.setRange(-1, 10000); chatMaxTokens.setDefaultValue(2000); @@ -87,10 +87,10 @@ PresetPromptsSettings::PresetPromptsSettings() fimTopP.setRange(0.0, 1.0); fimTopP.setSingleStep(0.1); - chatUseTopP.setSettingsKey(Constants::CHAT_USE_TOP_P); + chatUseTopP.setSettingsKey(Constants::CA_USE_TOP_P); chatUseTopP.setDefaultValue(false); - chatTopP.setSettingsKey(Constants::CHAT_TOP_P); + chatTopP.setSettingsKey(Constants::CA_TOP_P); chatTopP.setLabelText(Tr::tr("use top_p")); chatTopP.setDefaultValue(0.9); chatTopP.setRange(0.0, 1.0); @@ -104,10 +104,10 @@ PresetPromptsSettings::PresetPromptsSettings() fimTopK.setDefaultValue(50); fimTopK.setRange(1, 1000); - chatUseTopK.setSettingsKey(Constants::CHAT_USE_TOP_K); + chatUseTopK.setSettingsKey(Constants::CA_USE_TOP_K); chatUseTopK.setDefaultValue(false); - chatTopK.setSettingsKey(Constants::CHAT_TOP_K); + chatTopK.setSettingsKey(Constants::CA_TOP_K); chatTopK.setLabelText(Tr::tr("use top_k")); chatTopK.setDefaultValue(50); chatTopK.setRange(1, 1000); @@ -121,10 +121,10 @@ PresetPromptsSettings::PresetPromptsSettings() fimPresencePenalty.setRange(-2.0, 2.0); fimPresencePenalty.setSingleStep(0.1); - chatUsePresencePenalty.setSettingsKey(Constants::CHAT_USE_PRESENCE_PENALTY); + chatUsePresencePenalty.setSettingsKey(Constants::CA_USE_PRESENCE_PENALTY); chatUsePresencePenalty.setDefaultValue(false); - chatPresencePenalty.setSettingsKey(Constants::CHAT_PRESENCE_PENALTY); + chatPresencePenalty.setSettingsKey(Constants::CA_PRESENCE_PENALTY); chatPresencePenalty.setLabelText(Tr::tr("use presence_penalty")); chatPresencePenalty.setDefaultValue(0.0); chatPresencePenalty.setRange(-2.0, 2.0); @@ -139,10 +139,10 @@ PresetPromptsSettings::PresetPromptsSettings() fimFrequencyPenalty.setRange(-2.0, 2.0); fimFrequencyPenalty.setSingleStep(0.1); - chatUseFrequencyPenalty.setSettingsKey(Constants::CHAT_USE_FREQUENCY_PENALTY); + chatUseFrequencyPenalty.setSettingsKey(Constants::CA_USE_FREQUENCY_PENALTY); chatUseFrequencyPenalty.setDefaultValue(false); - chatFrequencyPenalty.setSettingsKey(Constants::CHAT_FREQUENCY_PENALTY); + chatFrequencyPenalty.setSettingsKey(Constants::CA_FREQUENCY_PENALTY); chatFrequencyPenalty.setLabelText(Tr::tr("use frequency_penalty")); chatFrequencyPenalty.setDefaultValue(0.0); chatFrequencyPenalty.setRange(-2.0, 2.0); @@ -153,7 +153,7 @@ PresetPromptsSettings::PresetPromptsSettings() fimApiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); fimApiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); - chatApiKey.setSettingsKey(Constants::CHAT_API_KEY); + chatApiKey.setSettingsKey(Constants::CA_API_KEY); chatApiKey.setLabelText(Tr::tr("API Key:")); chatApiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay); chatApiKey.setPlaceHolderText(Tr::tr("Enter your API key here")); diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 3c568c6..b7e9074 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -46,16 +46,18 @@ const char AUTO_COMPLETION_TYPING_INTERVAL[] = "QodeAssist.autoCompletionTypingI const char MAX_FILE_THRESHOLD[] = "QodeAssist.maxFileThreshold"; const char CC_MULTILINE_COMPLETION[] = "QodeAssist.ccMultilineCompletion"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; -const char CHAT_TOKENS_THRESHOLD[] = "QodeAssist.chatTokensThreshold"; +const char CA_TOKENS_THRESHOLD[] = "QodeAssist.caTokensThreshold"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId"; const char QODE_ASSIST_CODE_COMPLETION_SETTINGS_PAGE_ID[] = "QodeAssist.2CodeCompletionSettingsPageId"; -const char QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID[] = "QodeAssist.3ContextSettingsPageId"; +const char QODE_ASSIST_CHAT_ASSISTANT_SETTINGS_PAGE_ID[] + = "QodeAssist.3ChatAssistantSettingsPageId"; +const char QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID[] = "QodeAssist.4ContextSettingsPageId"; const char QODE_ASSIST_PRESET_PROMPTS_SETTINGS_PAGE_ID[] - = "QodeAssist.4PresetPromptsSettingsPageId"; -const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.5CustomPromptSettingsPageId"; + = "QodeAssist.5PresetPromptsSettingsPageId"; +const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.6CustomPromptSettingsPageId"; const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; const char QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY[] = "Qode Assist"; @@ -71,8 +73,8 @@ const char CC_USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.ccUseFilePathInContext"; const char CC_SYSTEM_PROMPT[] = "QodeAssist.ccSystemPrompt"; const char CC_USE_PROJECT_CHANGES_CACHE[] = "QodeAssist.ccUseProjectChangesCache"; const char CC_MAX_CHANGES_CACHE_SIZE[] = "QodeAssist.ccMaxChangesCacheSize"; -const char USE_CHAT_SYSTEM_PROMPT[] = "QodeAssist.useChatSystemPrompt"; -const char CHAT_SYSTEM_PROMPT[] = "QodeAssist.chatSystemPrompt"; +const char CA_USE_SYSTEM_PROMPT[] = "QodeAssist.useChatSystemPrompt"; +const char CA_SYSTEM_PROMPT[] = "QodeAssist.chatSystemPrompt"; // preset prompt settings const char CC_TEMPERATURE[] = "QodeAssist.ccTemperature"; @@ -88,17 +90,18 @@ const char CC_FREQUENCY_PENALTY[] = "QodeAssist.fimFrequencyPenalty"; const char CC_OLLAMA_LIVETIME[] = "QodeAssist.fimOllamaLivetime"; const char CC_OLLAMA_CONTEXT_WINDOW[] = "QodeAssist.ccOllamaContextWindow"; const char CC_API_KEY[] = "QodeAssist.apiKey"; -const char CHAT_TEMPERATURE[] = "QodeAssist.chatTemperature"; -const char CHAT_MAX_TOKENS[] = "QodeAssist.chatMaxTokens"; -const char CHAT_USE_TOP_P[] = "QodeAssist.chatUseTopP"; -const char CHAT_TOP_P[] = "QodeAssist.chatTopP"; -const char CHAT_USE_TOP_K[] = "QodeAssist.chatUseTopK"; -const char CHAT_TOP_K[] = "QodeAssist.chatTopK"; -const char CHAT_USE_PRESENCE_PENALTY[] = "QodeAssist.chatUsePresencePenalty"; -const char CHAT_PRESENCE_PENALTY[] = "QodeAssist.chatPresencePenalty"; -const char CHAT_USE_FREQUENCY_PENALTY[] = "QodeAssist.chatUseFrequencyPenalty"; -const char CHAT_FREQUENCY_PENALTY[] = "QodeAssist.chatFrequencyPenalty"; -const char CHAT_OLLAMA_LIVETIME[] = "QodeAssist.chatOllamaLivetime"; -const char CHAT_API_KEY[] = "QodeAssist.chatApiKey"; +const char CA_TEMPERATURE[] = "QodeAssist.chatTemperature"; +const char CA_MAX_TOKENS[] = "QodeAssist.chatMaxTokens"; +const char CA_USE_TOP_P[] = "QodeAssist.chatUseTopP"; +const char CA_TOP_P[] = "QodeAssist.chatTopP"; +const char CA_USE_TOP_K[] = "QodeAssist.chatUseTopK"; +const char CA_TOP_K[] = "QodeAssist.chatTopK"; +const char CA_USE_PRESENCE_PENALTY[] = "QodeAssist.chatUsePresencePenalty"; +const char CA_PRESENCE_PENALTY[] = "QodeAssist.chatPresencePenalty"; +const char CA_USE_FREQUENCY_PENALTY[] = "QodeAssist.chatUseFrequencyPenalty"; +const char CA_FREQUENCY_PENALTY[] = "QodeAssist.chatFrequencyPenalty"; +const char CA_OLLAMA_LIVETIME[] = "QodeAssist.chatOllamaLivetime"; +const char CA_OLLAMA_CONTEXT_WINDOW[] = "QodeAssist.caOllamaContextWindow"; +const char CA_API_KEY[] = "QodeAssist.chatApiKey"; } // namespace QodeAssist::Constants From bc93bce03bff3d5fe4d9d75f762514e1640dd259 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 10 Nov 2024 23:42:06 +0100 Subject: [PATCH 5/8] Adapt new settings --- ConfigurationManager.cpp | 4 +- DocumentContextReader.cpp | 14 ++-- LLMClientInterface.cpp | 2 - QodeAssistClient.cpp | 126 ++++++++++++++-------------- chatview/ChatUtils.cpp | 19 +++++ chatview/ChatUtils.h | 19 +++++ core/ChangesManager.cpp | 5 +- llmcore/RequestType.hpp | 19 +++++ providers/LMStudioProvider.cpp | 56 +++++++------ providers/OllamaProvider.cpp | 40 +++++---- providers/OpenAICompatProvider.cpp | 59 ++++++------- settings/CMakeLists.txt | 2 - settings/CodeCompletionSettings.cpp | 35 ++++++-- settings/CodeCompletionSettings.hpp | 4 + settings/GeneralSettings.cpp | 4 + settings/SettingsConstants.hpp | 15 ++-- 16 files changed, 264 insertions(+), 159 deletions(-) diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp index 5ab05ff..e9e4e44 100644 --- a/ConfigurationManager.cpp +++ b/ConfigurationManager.cpp @@ -88,8 +88,8 @@ void ConfigurationManager::selectModel() return; const auto providerUrl = (settingsButton == &m_generalSettings.ccSelectModel) - ? m_generalSettings.ccUrl() - : m_generalSettings.caUrl(); + ? m_generalSettings.ccUrl.volatileValue() + : m_generalSettings.caUrl.volatileValue(); const auto modelList = m_providersManager.getProviderByName(providerName) ->getInstalledModels(providerUrl); diff --git a/DocumentContextReader.cpp b/DocumentContextReader.cpp index 7ac0189..2a2a864 100644 --- a/DocumentContextReader.cpp +++ b/DocumentContextReader.cpp @@ -24,7 +24,7 @@ #include #include "core/ChangesManager.h" -#include "settings/ContextSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" const QRegularExpression &getYearRegex() { @@ -214,11 +214,11 @@ LLMCore::ContextData DocumentContextReader::prepareContext(int lineNumber, int c QString DocumentContextReader::getContextBefore(int lineNumber, int cursorPosition) const { - if (Settings::contextSettings().readFullFile()) { + if (Settings::codeCompletionSettings().readFullFile()) { return readWholeFileBefore(lineNumber, cursorPosition); } else { int effectiveStartLine; - int beforeCursor = Settings::contextSettings().readStringsBeforeCursor(); + int beforeCursor = Settings::codeCompletionSettings().readStringsBeforeCursor(); if (m_copyrightInfo.found) { effectiveStartLine = qMax(m_copyrightInfo.endLine + 1, lineNumber - beforeCursor); } else { @@ -230,11 +230,11 @@ QString DocumentContextReader::getContextBefore(int lineNumber, int cursorPositi QString DocumentContextReader::getContextAfter(int lineNumber, int cursorPosition) const { - if (Settings::contextSettings().readFullFile()) { + if (Settings::codeCompletionSettings().readFullFile()) { return readWholeFileAfter(lineNumber, cursorPosition); } else { int endLine = qMin(m_document->blockCount() - 1, - lineNumber + Settings::contextSettings().readStringsAfterCursor()); + lineNumber + Settings::codeCompletionSettings().readStringsAfterCursor()); return getContextBetween(lineNumber + 1, endLine, -1); } } @@ -243,10 +243,10 @@ QString DocumentContextReader::getInstructions() const { QString instructions; - if (Settings::contextSettings().useFilePathInContext()) + if (Settings::codeCompletionSettings().useFilePathInContext()) instructions += getLanguageAndFileInfo(); - if (Settings::contextSettings().useProjectChangesCache()) + if (Settings::codeCompletionSettings().useProjectChangesCache()) instructions += ChangesManager::instance().getRecentChangesContext(m_textDocument); return instructions; diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index d94ea72..5a27114 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -26,13 +26,11 @@ #include #include -#include "ConfigurationManager.hpp" #include "DocumentContextReader.hpp" #include "llmcore/PromptTemplateManager.hpp" #include "llmcore/ProvidersManager.hpp" #include "logger/Logger.hpp" #include "settings/CodeCompletionSettings.hpp" -#include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" namespace QodeAssist { diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index 89549c0..26eb763 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -32,7 +32,7 @@ #include "LLMClientInterface.hpp" #include "LLMSuggestion.hpp" #include "core/ChangesManager.h" -#include "settings/ContextSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" #include "settings/GeneralSettings.hpp" using namespace LanguageServerProtocol; @@ -65,52 +65,53 @@ QodeAssistClient::~QodeAssistClient() void QodeAssistClient::openDocument(TextEditor::TextDocument *document) { - // auto project = ProjectManager::projectForFile(document->filePath()); - // if (!isEnabled(project)) - // return; + auto project = ProjectManager::projectForFile(document->filePath()); + if (!isEnabled(project)) + return; - // Client::openDocument(document); - // connect(document, - // &TextDocument::contentsChangedWithPosition, - // this, - // [this, document](int position, int charsRemoved, int charsAdded) { - // Q_UNUSED(charsRemoved) - // if (!Settings::generalSettings().enableAutoComplete()) - // return; + Client::openDocument(document); + connect(document, + &TextDocument::contentsChangedWithPosition, + this, + [this, document](int position, int charsRemoved, int charsAdded) { + Q_UNUSED(charsRemoved) + if (!Settings::codeCompletionSettings().autoCompletion()) + return; - // auto project = ProjectManager::projectForFile(document->filePath()); - // if (!isEnabled(project)) - // return; + auto project = ProjectManager::projectForFile(document->filePath()); + if (!isEnabled(project)) + return; - // auto textEditor = BaseTextEditor::currentTextEditor(); - // if (!textEditor || textEditor->document() != document) - // return; + auto textEditor = BaseTextEditor::currentTextEditor(); + if (!textEditor || textEditor->document() != document) + return; - // if (Settings::contextSettings().useProjectChangesCache()) - // ChangesManager::instance().addChange(document, - // position, - // charsRemoved, - // charsAdded); + if (Settings::codeCompletionSettings().useProjectChangesCache()) + ChangesManager::instance().addChange(document, + position, + charsRemoved, + charsAdded); - // TextEditorWidget *widget = textEditor->editorWidget(); - // if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) - // return; - // const int cursorPosition = widget->textCursor().position(); - // if (cursorPosition < position || cursorPosition > position + charsAdded) - // return; + TextEditorWidget *widget = textEditor->editorWidget(); + if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) + return; + const int cursorPosition = widget->textCursor().position(); + if (cursorPosition < position || cursorPosition > position + charsAdded) + return; - // m_recentCharCount += charsAdded; + m_recentCharCount += charsAdded; - // if (m_typingTimer.elapsed() - // > Settings::generalSettings().autoCompletionTypingInterval()) { - // m_recentCharCount = charsAdded; - // m_typingTimer.restart(); - // } + if (m_typingTimer.elapsed() + > Settings::codeCompletionSettings().autoCompletionTypingInterval()) { + m_recentCharCount = charsAdded; + m_typingTimer.restart(); + } - // if (m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) { - // scheduleRequest(widget); - // } - // }); + if (m_recentCharCount + > Settings::codeCompletionSettings().autoCompletionCharThreshold()) { + scheduleRequest(widget); + } + }); } bool QodeAssistClient::canOpenProject(ProjectExplorer::Project *project) @@ -144,31 +145,32 @@ void QodeAssistClient::requestCompletions(TextEditor::TextEditorWidget *editor) void QodeAssistClient::scheduleRequest(TextEditor::TextEditorWidget *editor) { - // cancelRunningRequest(editor); + cancelRunningRequest(editor); - // auto it = m_scheduledRequests.find(editor); - // if (it == m_scheduledRequests.end()) { - // auto timer = new QTimer(this); - // timer->setSingleShot(true); - // connect(timer, &QTimer::timeout, this, [this, editor]() { - // if (editor - // && editor->textCursor().position() - // == m_scheduledRequests[editor]->property("cursorPosition").toInt() - // && m_recentCharCount > Settings::generalSettings().autoCompletionCharThreshold()) - // requestCompletions(editor); - // }); - // connect(editor, &TextEditorWidget::destroyed, this, [this, editor]() { - // delete m_scheduledRequests.take(editor); - // cancelRunningRequest(editor); - // }); - // connect(editor, &TextEditorWidget::cursorPositionChanged, this, [this, editor] { - // cancelRunningRequest(editor); - // }); - // it = m_scheduledRequests.insert(editor, timer); - // } + auto it = m_scheduledRequests.find(editor); + if (it == m_scheduledRequests.end()) { + auto timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, this, [this, editor]() { + if (editor + && editor->textCursor().position() + == m_scheduledRequests[editor]->property("cursorPosition").toInt() + && m_recentCharCount + > Settings::codeCompletionSettings().autoCompletionCharThreshold()) + requestCompletions(editor); + }); + connect(editor, &TextEditorWidget::destroyed, this, [this, editor]() { + delete m_scheduledRequests.take(editor); + cancelRunningRequest(editor); + }); + connect(editor, &TextEditorWidget::cursorPositionChanged, this, [this, editor] { + cancelRunningRequest(editor); + }); + it = m_scheduledRequests.insert(editor, timer); + } - // it.value()->setProperty("cursorPosition", editor->textCursor().position()); - // it.value()->start(Settings::generalSettings().startSuggestionTimer()); + it.value()->setProperty("cursorPosition", editor->textCursor().position()); + it.value()->start(Settings::codeCompletionSettings().startSuggestionTimer()); } void QodeAssistClient::handleCompletions(const GetCompletionRequest::Response &response, TextEditor::TextEditorWidget *editor) diff --git a/chatview/ChatUtils.cpp b/chatview/ChatUtils.cpp index 97079bc..571c35c 100644 --- a/chatview/ChatUtils.cpp +++ b/chatview/ChatUtils.cpp @@ -1,3 +1,22 @@ +/* + * 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 "ChatUtils.h" #include diff --git a/chatview/ChatUtils.h b/chatview/ChatUtils.h index fd2c3a6..2584b2c 100644 --- a/chatview/ChatUtils.h +++ b/chatview/ChatUtils.h @@ -1,3 +1,22 @@ +/* + * 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 diff --git a/core/ChangesManager.cpp b/core/ChangesManager.cpp index ae5a4ca..40809f3 100644 --- a/core/ChangesManager.cpp +++ b/core/ChangesManager.cpp @@ -18,8 +18,7 @@ */ #include "ChangesManager.h" -#include "logger/Logger.hpp" -#include "settings/ContextSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" namespace QodeAssist { @@ -61,7 +60,7 @@ void ChangesManager::addChange(TextEditor::TextDocument *document, } else { documentQueue.enqueue(change); - if (documentQueue.size() > Settings::contextSettings().maxChangesCacheSize()) { + if (documentQueue.size() > Settings::codeCompletionSettings().maxChangesCacheSize()) { documentQueue.dequeue(); } } diff --git a/llmcore/RequestType.hpp b/llmcore/RequestType.hpp index 80f64d5..763e35e 100644 --- a/llmcore/RequestType.hpp +++ b/llmcore/RequestType.hpp @@ -1,3 +1,22 @@ +/* + * 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 namespace QodeAssist::LLMCore { diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index 06bc67e..dde92c8 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -26,7 +26,8 @@ #include #include "logger/Logger.hpp" -#include "settings/PresetPromptsSettings.hpp" +#include "settings/ChatAssistantSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" namespace QodeAssist::Providers { @@ -54,36 +55,43 @@ QString LMStudioProvider::chatEndpoint() const void LMStudioProvider::prepareRequest(QJsonObject &request, LLMCore::RequestType type) { - auto &promptSettings = Settings::presetPromptsSettings(); - auto settings = promptSettings.getSettings(type); + auto prepareMessages = [](QJsonObject &req) -> QJsonArray { + QJsonArray messages; + if (req.contains("system")) { + messages.append( + QJsonObject{{"role", "system"}, {"content", req.take("system").toString()}}); + } + if (req.contains("prompt")) { + messages.append( + QJsonObject{{"role", "user"}, {"content", req.take("prompt").toString()}}); + } + return messages; + }; - QJsonArray messages; + auto applyModelParams = [&request](const auto &settings) { + request["max_tokens"] = settings.maxTokens(); + request["temperature"] = settings.temperature(); - if (request.contains("system")) { - QJsonObject systemMessage{{"role", "system"}, - {"content", request.take("system").toString()}}; - messages.append(systemMessage); - } - - if (request.contains("prompt")) { - QJsonObject userMessage{{"role", "user"}, {"content", request.take("prompt").toString()}}; - messages.append(userMessage); - } + 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(); + }; + QJsonArray messages = prepareMessages(request); if (!messages.isEmpty()) { request["messages"] = std::move(messages); } - request["max_tokens"] = settings.maxTokens; - request["temperature"] = settings.temperature; - 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 (type == LLMCore::RequestType::Fim) { + applyModelParams(Settings::codeCompletionSettings()); + } else { + applyModelParams(Settings::chatAssistantSettings()); + } } bool LMStudioProvider::handleResponse(QNetworkReply *reply, QString &accumulatedResponse) diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index 223b568..65aa3ce 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -26,7 +26,8 @@ #include #include "logger/Logger.hpp" -#include "settings/PresetPromptsSettings.hpp" +#include "settings/ChatAssistantSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" namespace QodeAssist::Providers { @@ -54,22 +55,29 @@ QString OllamaProvider::chatEndpoint() const void OllamaProvider::prepareRequest(QJsonObject &request, LLMCore::RequestType type) { - auto &promptSettings = Settings::presetPromptsSettings(); - auto settings = promptSettings.getSettings(type); + auto applySettings = [&request](const auto &settings) { + QJsonObject options; + options["num_predict"] = settings.maxTokens(); + options["temperature"] = settings.temperature(); - QJsonObject options; - options["num_predict"] = settings.maxTokens; - options["temperature"] = settings.temperature; - 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; - request["keep_alive"] = settings.ollamaLivetime; + 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; + request["keep_alive"] = settings.ollamaLivetime(); + }; + + if (type == LLMCore::RequestType::Fim) { + applySettings(Settings::codeCompletionSettings()); + } else { + applySettings(Settings::chatAssistantSettings()); + } } bool OllamaProvider::handleResponse(QNetworkReply *reply, QString &accumulatedResponse) diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index 8f7b7e9..a0ea2bb 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -18,14 +18,14 @@ */ #include "OpenAICompatProvider.hpp" +#include "settings/ChatAssistantSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" #include #include #include #include -#include "settings/PresetPromptsSettings.hpp" - namespace QodeAssist::Providers { OpenAICompatProvider::OpenAICompatProvider() {} @@ -52,39 +52,42 @@ QString OpenAICompatProvider::chatEndpoint() const void OpenAICompatProvider::prepareRequest(QJsonObject &request, LLMCore::RequestType type) { - auto &promptSettings = Settings::presetPromptsSettings(); - auto settings = promptSettings.getSettings(type); - QJsonArray messages; + auto prepareMessages = [](QJsonObject &req) -> QJsonArray { + QJsonArray messages; + if (req.contains("system")) { + messages.append( + QJsonObject{{"role", "system"}, {"content", req.take("system").toString()}}); + } + if (req.contains("prompt")) { + messages.append( + QJsonObject{{"role", "user"}, {"content", req.take("prompt").toString()}}); + } + return messages; + }; - if (request.contains("system")) { - QJsonObject systemMessage{{"role", "system"}, - {"content", request.take("system").toString()}}; - messages.append(systemMessage); - } + auto applyModelParams = [&request](const auto &settings) { + request["max_tokens"] = settings.maxTokens(); + request["temperature"] = settings.temperature(); - if (request.contains("prompt")) { - QJsonObject userMessage{{"role", "user"}, {"content", request.take("prompt").toString()}}; - messages.append(userMessage); - } + 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(); + }; + QJsonArray messages = prepareMessages(request); if (!messages.isEmpty()) { request["messages"] = std::move(messages); } - request["max_tokens"] = settings.maxTokens; - request["temperature"] = settings.temperature; - 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; - if (!apiKey.isEmpty()) { - request["api_key"] = apiKey; + if (type == LLMCore::RequestType::Fim) { + applyModelParams(Settings::codeCompletionSettings()); + } else { + applyModelParams(Settings::chatAssistantSettings()); } } diff --git a/settings/CMakeLists.txt b/settings/CMakeLists.txt index 84fe20f..cd4b281 100644 --- a/settings/CMakeLists.txt +++ b/settings/CMakeLists.txt @@ -1,8 +1,6 @@ add_library(QodeAssistSettings STATIC GeneralSettings.hpp GeneralSettings.cpp - ContextSettings.hpp ContextSettings.cpp CustomPromptSettings.hpp CustomPromptSettings.cpp - PresetPromptsSettings.hpp PresetPromptsSettings.cpp SettingsUtils.hpp SettingsConstants.hpp ButtonAspect.hpp diff --git a/settings/CodeCompletionSettings.cpp b/settings/CodeCompletionSettings.cpp index 3379ff6..ebcb46e 100644 --- a/settings/CodeCompletionSettings.cpp +++ b/settings/CodeCompletionSettings.cpp @@ -51,6 +51,27 @@ CodeCompletionSettings::CodeCompletionSettings() multiLineCompletion.setDefaultValue(false); multiLineCompletion.setLabelText(Tr::tr("Enable Multiline Completion(experimental)")); + startSuggestionTimer.setSettingsKey(Constants::СС_START_SUGGESTION_TIMER); + startSuggestionTimer.setLabelText(Tr::tr("with delay(ms)")); + startSuggestionTimer.setRange(10, 10000); + startSuggestionTimer.setDefaultValue(500); + + autoCompletionCharThreshold.setSettingsKey(Constants::СС_AUTO_COMPLETION_CHAR_THRESHOLD); + autoCompletionCharThreshold.setLabelText(Tr::tr("AI suggestion triggers after typing")); + 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(0, 10); + autoCompletionCharThreshold.setDefaultValue(0); + + autoCompletionTypingInterval.setSettingsKey(Constants::СС_AUTO_COMPLETION_TYPING_INTERVAL); + autoCompletionTypingInterval.setLabelText(Tr::tr("character(s) within(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); + // General Parameters Settings temperature.setSettingsKey(Constants::CC_TEMPERATURE); temperature.setLabelText(Tr::tr("Temperature:")); @@ -136,7 +157,7 @@ CodeCompletionSettings::CodeCompletionSettings() maxChangesCacheSize.setSettingsKey(Constants::CC_MAX_CHANGES_CACHE_SIZE); maxChangesCacheSize.setRange(2, 1000); - maxChangesCacheSize.setDefaultValue(20); + maxChangesCacheSize.setDefaultValue(10); // Ollama Settings ollamaLivetime.setSettingsKey(Constants::CC_OLLAMA_LIVETIME); @@ -196,11 +217,13 @@ CodeCompletionSettings::CodeCompletionSettings() return Column{Row{Stretch{1}, resetToDefaults}, Space{8}, Group{title(Tr::tr("Auto Completion Settings")), - Column{ - autoCompletion, - Space{8}, - multiLineCompletion, - }}, + Column{autoCompletion, + Space{8}, + multiLineCompletion, + Row{autoCompletionCharThreshold, + autoCompletionTypingInterval, + startSuggestionTimer, + Stretch{1}}}}, Space{8}, Group{title(Tr::tr("General Parameters")), Column{ diff --git a/settings/CodeCompletionSettings.hpp b/settings/CodeCompletionSettings.hpp index 52b2d8f..c6b990c 100644 --- a/settings/CodeCompletionSettings.hpp +++ b/settings/CodeCompletionSettings.hpp @@ -36,6 +36,10 @@ public: Utils::BoolAspect autoCompletion{this}; Utils::BoolAspect multiLineCompletion{this}; + Utils::IntegerAspect startSuggestionTimer{this}; + Utils::IntegerAspect autoCompletionCharThreshold{this}; + Utils::IntegerAspect autoCompletionTypingInterval{this}; + // General Parameters Settings Utils::DoubleAspect temperature{this}; Utils::IntegerAspect maxTokens{this}; diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index bfab84f..ea39e9b 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -60,6 +60,7 @@ GeneralSettings::GeneralSettings() ccSelectProvider.m_buttonText = TrConstants::SELECT; initStringAspect(ccModel, Constants::CC_MODEL, TrConstants::MODEL, "codellama:7b-code"); + ccModel.setHistoryCompleter(Constants::CC_MODEL_HISTORY); ccSelectModel.m_buttonText = TrConstants::SELECT; initStringAspect(ccTemplate, Constants::CC_TEMPLATE, TrConstants::TEMPLATE, "CodeLlama FIM"); @@ -67,6 +68,7 @@ GeneralSettings::GeneralSettings() ccSelectTemplate.m_buttonText = TrConstants::SELECT; initStringAspect(ccUrl, Constants::CC_URL, TrConstants::URL, "http://localhost:11434"); + ccUrl.setHistoryCompleter(Constants::CC_URL_HISTORY); ccSetUrl.m_buttonText = TrConstants::SELECT; ccStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay); @@ -79,6 +81,7 @@ GeneralSettings::GeneralSettings() caSelectProvider.m_buttonText = TrConstants::SELECT; initStringAspect(caModel, Constants::CA_MODEL, TrConstants::MODEL, "codellama:7b-instruct"); + caModel.setHistoryCompleter(Constants::CA_MODEL_HISTORY); caSelectModel.m_buttonText = TrConstants::SELECT; initStringAspect(caTemplate, Constants::CA_TEMPLATE, TrConstants::TEMPLATE, "CodeLlama Chat"); @@ -87,6 +90,7 @@ GeneralSettings::GeneralSettings() caSelectTemplate.m_buttonText = TrConstants::SELECT; initStringAspect(caUrl, Constants::CA_URL, TrConstants::URL, "http://localhost:11434"); + caUrl.setHistoryCompleter(Constants::CA_URL_HISTORY); caSetUrl.m_buttonText = TrConstants::SELECT; caStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay); diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index b7e9074..1eae254 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -27,22 +27,26 @@ const char MENU_ID[] = "QodeAssist.Menu"; // new settings const char CC_PROVIDER[] = "QodeAssist.ccProvider"; const char CC_MODEL[] = "QodeAssist.ccModel"; +const char CC_MODEL_HISTORY[] = "QodeAssist.ccModelHistory"; const char CC_TEMPLATE[] = "QodeAssist.ccTemplate"; const char CC_URL[] = "QodeAssist.ccUrl"; +const char CC_URL_HISTORY[] = "QodeAssist.ccUrlHistory"; const char CA_PROVIDER[] = "QodeAssist.caProvider"; const char CA_MODEL[] = "QodeAssist.caModel"; +const char CA_MODEL_HISTORY[] = "QodeAssist.caModelHistory"; const char CA_TEMPLATE[] = "QodeAssist.caTemplate"; const char CA_URL[] = "QodeAssist.caUrl"; +const char CA_URL_HISTORY[] = "QodeAssist.caUrlHistory"; // settings const char ENABLE_QODE_ASSIST[] = "QodeAssist.enableQodeAssist"; const char CC_AUTO_COMPLETION[] = "QodeAssist.ccAutoCompletion"; const char ENABLE_LOGGING[] = "QodeAssist.enableLogging"; 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 СС_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 CC_MULTILINE_COMPLETION[] = "QodeAssist.ccMultilineCompletion"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; @@ -54,10 +58,7 @@ const char QODE_ASSIST_CODE_COMPLETION_SETTINGS_PAGE_ID[] = "QodeAssist.2CodeCompletionSettingsPageId"; const char QODE_ASSIST_CHAT_ASSISTANT_SETTINGS_PAGE_ID[] = "QodeAssist.3ChatAssistantSettingsPageId"; -const char QODE_ASSIST_CONTEXT_SETTINGS_PAGE_ID[] = "QodeAssist.4ContextSettingsPageId"; -const char QODE_ASSIST_PRESET_PROMPTS_SETTINGS_PAGE_ID[] - = "QodeAssist.5PresetPromptsSettingsPageId"; -const char QODE_ASSIST_CUSTOM_PROMPT_SETTINGS_PAGE_ID[] = "QodeAssist.6CustomPromptSettingsPageId"; +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"; From 61f1f0ae4f9fc62190017171fb4b23fba15c6aa1 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Mon, 11 Nov 2024 00:38:55 +0100 Subject: [PATCH 6/8] Add sharing current file with model --- ConfigurationManager.cpp | 4 +-- chatview/ChatRootView.cpp | 16 ++++++++-- chatview/ChatRootView.hpp | 8 ++++- chatview/ClientInterface.cpp | 51 ++++++++++++++++++++++++++++-- chatview/ClientInterface.hpp | 3 +- chatview/qml/RootItem.qml | 9 +++++- settings/ChatAssistantSettings.cpp | 7 +++- settings/ChatAssistantSettings.hpp | 1 + settings/SettingsConstants.hpp | 1 + 9 files changed, 89 insertions(+), 11 deletions(-) diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp index e9e4e44..5ab05ff 100644 --- a/ConfigurationManager.cpp +++ b/ConfigurationManager.cpp @@ -88,8 +88,8 @@ void ConfigurationManager::selectModel() return; const auto providerUrl = (settingsButton == &m_generalSettings.ccSelectModel) - ? m_generalSettings.ccUrl.volatileValue() - : m_generalSettings.caUrl.volatileValue(); + ? m_generalSettings.ccUrl() + : m_generalSettings.caUrl(); const auto modelList = m_providersManager.getProviderByName(providerName) ->getInstalledModels(providerUrl); diff --git a/chatview/ChatRootView.cpp b/chatview/ChatRootView.cpp index 136a3aa..c3b58c8 100644 --- a/chatview/ChatRootView.cpp +++ b/chatview/ChatRootView.cpp @@ -22,6 +22,7 @@ #include #include +#include "ChatAssistantSettings.hpp" #include "GeneralSettings.hpp" namespace QodeAssist::Chat { @@ -37,6 +38,12 @@ ChatRootView::ChatRootView(QQuickItem *parent) &Utils::BaseAspect::changed, this, &ChatRootView::currentTemplateChanged); + + connect(&Settings::chatAssistantSettings().sharingCurrentFile, + &Utils::BaseAspect::changed, + this, + &ChatRootView::isSharingCurrentFileChanged); + generateColors(); } @@ -50,9 +57,9 @@ QColor ChatRootView::backgroundColor() const return Utils::creatorColor(Utils::Theme::BackgroundColorNormal); } -void ChatRootView::sendMessage(const QString &message) const +void ChatRootView::sendMessage(const QString &message, bool sharingCurrentFile) const { - m_clientInterface->sendMessage(message); + m_clientInterface->sendMessage(message, sharingCurrentFile); } void ChatRootView::copyToClipboard(const QString &text) @@ -129,4 +136,9 @@ QColor ChatRootView::codeColor() const return m_codeColor; } +bool ChatRootView::isSharingCurrentFile() const +{ + return Settings::chatAssistantSettings().sharingCurrentFile(); +} + } // namespace QodeAssist::Chat diff --git a/chatview/ChatRootView.hpp b/chatview/ChatRootView.hpp index f0d7272..98206f6 100644 --- a/chatview/ChatRootView.hpp +++ b/chatview/ChatRootView.hpp @@ -35,6 +35,8 @@ class ChatRootView : public QQuickItem Q_PROPERTY(QColor primaryColor READ primaryColor CONSTANT FINAL) Q_PROPERTY(QColor secondaryColor READ secondaryColor CONSTANT FINAL) Q_PROPERTY(QColor codeColor READ codeColor CONSTANT FINAL) + Q_PROPERTY(bool isSharingCurrentFile READ isSharingCurrentFile NOTIFY + isSharingCurrentFileChanged FINAL) QML_ELEMENT public: @@ -49,8 +51,10 @@ public: QColor codeColor() const; + bool isSharingCurrentFile() const; + public slots: - void sendMessage(const QString &message) const; + void sendMessage(const QString &message, bool sharingCurrentFile = false) const; void copyToClipboard(const QString &text); void cancelRequest(); @@ -58,6 +62,8 @@ signals: void chatModelChanged(); void currentTemplateChanged(); + void isSharingCurrentFileChanged(); + private: void generateColors(); QColor generateColor(const QColor &baseColor, diff --git a/chatview/ClientInterface.cpp b/chatview/ClientInterface.cpp index a75e99a..483d193 100644 --- a/chatview/ClientInterface.cpp +++ b/chatview/ClientInterface.cpp @@ -19,9 +19,18 @@ #include "ClientInterface.hpp" +#include #include #include #include +#include + +#include +#include +#include + +#include +#include #include "ChatAssistantSettings.hpp" #include "GeneralSettings.hpp" @@ -55,7 +64,7 @@ ClientInterface::ClientInterface(ChatModel *chatModel, QObject *parent) ClientInterface::~ClientInterface() = default; -void ClientInterface::sendMessage(const QString &message) +void ClientInterface::sendMessage(const QString &message, bool includeCurrentFile) { cancelRequest(); @@ -71,8 +80,20 @@ void ClientInterface::sendMessage(const QString &message) LLMCore::ContextData context; context.prefix = message; context.suffix = ""; - if (chatAssistantSettings.useSystemPrompt()) - context.systemPrompt = chatAssistantSettings.systemPrompt(); + + QString systemPrompt = chatAssistantSettings.systemPrompt(); + if (includeCurrentFile) { + QString fileContext = getCurrentFileContext(); + if (!fileContext.isEmpty()) { + context.systemPrompt = QString("%1\n\n%2").arg(systemPrompt, fileContext); + LOG_MESSAGE("Using system prompt with file context"); + } else { + context.systemPrompt = systemPrompt; + LOG_MESSAGE("Failed to get file context, using default system prompt"); + } + } else { + context.systemPrompt = systemPrompt; + } QJsonObject providerRequest; providerRequest["model"] = Settings::generalSettings().caModel(); @@ -128,4 +149,28 @@ void ClientInterface::handleLLMResponse(const QString &response, } } +QString ClientInterface::getCurrentFileContext() const +{ + auto currentEditor = Core::EditorManager::currentEditor(); + if (!currentEditor) { + LOG_MESSAGE("No active editor found"); + return QString(); + } + + auto textDocument = qobject_cast(currentEditor->document()); + if (!textDocument) { + LOG_MESSAGE("Current document is not a text document"); + return QString(); + } + + QString fileInfo = QString("Language: %1\nFile: %2\n\n") + .arg(textDocument->mimeType(), textDocument->filePath().toString()); + + QString content = textDocument->document()->toPlainText(); + + LOG_MESSAGE(QString("Got context from file: %1").arg(textDocument->filePath().toString())); + + return QString("Current file context:\n%1\nFile content:\n%2").arg(fileInfo, content); +} + } // namespace QodeAssist::Chat diff --git a/chatview/ClientInterface.hpp b/chatview/ClientInterface.hpp index 4de4ea7..0fb1225 100644 --- a/chatview/ClientInterface.hpp +++ b/chatview/ClientInterface.hpp @@ -36,7 +36,7 @@ public: explicit ClientInterface(ChatModel *chatModel, QObject *parent = nullptr); ~ClientInterface(); - void sendMessage(const QString &message); + void sendMessage(const QString &message, bool includeCurrentFile = false); void clearMessages(); void cancelRequest(); @@ -45,6 +45,7 @@ signals: private: void handleLLMResponse(const QString &response, const QJsonObject &request, bool isComplete); + QString getCurrentFileContext() const; LLMCore::RequestHandler *m_requestHandler; ChatModel *m_chatModel; diff --git a/chatview/qml/RootItem.qml b/chatview/qml/RootItem.qml index 26b85c4..675526b 100644 --- a/chatview/qml/RootItem.qml +++ b/chatview/qml/RootItem.qml @@ -137,6 +137,13 @@ ChatRootView { text: qsTr("Clear Chat") onClicked: clearChat() } + + CheckBox { + id: sharingCurrentFile + + text: "Share current file with models" + checked: root.isSharingCurrentFile + } } } @@ -169,7 +176,7 @@ ChatRootView { } function sendChatMessage() { - root.sendMessage(messageInput.text); + root.sendMessage(messageInput.text, sharingCurrentFile.checked) messageInput.text = "" scrollToBottom() } diff --git a/settings/ChatAssistantSettings.cpp b/settings/ChatAssistantSettings.cpp index f4d7dc6..0e3ae0f 100644 --- a/settings/ChatAssistantSettings.cpp +++ b/settings/ChatAssistantSettings.cpp @@ -50,6 +50,10 @@ ChatAssistantSettings::ChatAssistantSettings() chatTokensThreshold.setRange(1000, 16000); chatTokensThreshold.setDefaultValue(8000); + sharingCurrentFile.setSettingsKey(Constants::CA_SHARING_CURRENT_FILE); + sharingCurrentFile.setLabelText(Tr::tr("Share Current File With Assistant by Default")); + sharingCurrentFile.setDefaultValue(true); + // General Parameters Settings temperature.setSettingsKey(Constants::CA_TEMPERATURE); temperature.setLabelText(Tr::tr("Temperature:")); @@ -156,7 +160,8 @@ ChatAssistantSettings::ChatAssistantSettings() return Column{Row{Stretch{1}, resetToDefaults}, Space{8}, - Group{title(Tr::tr("Chat Settings")), Row{chatTokensThreshold, Stretch{1}}}, + Group{title(Tr::tr("Chat Settings")), + Column{Row{chatTokensThreshold, Stretch{1}}, sharingCurrentFile}}, Space{8}, Group{ title(Tr::tr("General Parameters")), diff --git a/settings/ChatAssistantSettings.hpp b/settings/ChatAssistantSettings.hpp index 3a4dde1..303d068 100644 --- a/settings/ChatAssistantSettings.hpp +++ b/settings/ChatAssistantSettings.hpp @@ -34,6 +34,7 @@ public: // Chat settings Utils::IntegerAspect chatTokensThreshold{this}; + Utils::BoolAspect sharingCurrentFile{this}; // General Parameters Settings Utils::DoubleAspect temperature{this}; diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 1eae254..124429b 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -51,6 +51,7 @@ const char MAX_FILE_THRESHOLD[] = "QodeAssist.maxFileThreshold"; const char CC_MULTILINE_COMPLETION[] = "QodeAssist.ccMultilineCompletion"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; const char CA_TOKENS_THRESHOLD[] = "QodeAssist.caTokensThreshold"; +const char CA_SHARING_CURRENT_FILE[] = "QodeAssist.caSharingCurrentFile"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId"; From 9902623ba06e5e6117a93193605fddad08f00406 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Mon, 11 Nov 2024 01:00:54 +0100 Subject: [PATCH 7/8] Fix problem with wrong reading settings --- ConfigurationManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp index 5ab05ff..593b941 100644 --- a/ConfigurationManager.cpp +++ b/ConfigurationManager.cpp @@ -81,15 +81,15 @@ void ConfigurationManager::selectProvider() void ConfigurationManager::selectModel() { - const QString providerName = m_generalSettings.ccProvider(); + const QString providerName = m_generalSettings.ccProvider.volatileValue(); auto *settingsButton = qobject_cast(sender()); if (!settingsButton) return; const auto providerUrl = (settingsButton == &m_generalSettings.ccSelectModel) - ? m_generalSettings.ccUrl() - : m_generalSettings.caUrl(); + ? m_generalSettings.ccUrl.volatileValue() + : m_generalSettings.caUrl.volatileValue(); const auto modelList = m_providersManager.getProviderByName(providerName) ->getInstalledModels(providerUrl); From 5d496fee58064053706e26bf84134f0c15c24cd3 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Mon, 11 Nov 2024 01:01:26 +0100 Subject: [PATCH 8/8] Upgrade version --- QodeAssist.json.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QodeAssist.json.in b/QodeAssist.json.in index d7133bd..321e93a 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.3.4", + "Version" : "0.3.5", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Vendor" : "Petr Mironychev", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",