refactor: Decouple prompt template manager from their users (#115)

This makes it possible to test the user classes
This commit is contained in:
Povilas Kanapickas 2025-03-10 03:13:10 +02:00 committed by GitHub
parent b6f36d61ae
commit 98e1047bf1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 179 additions and 20 deletions

View File

@ -45,7 +45,8 @@ namespace QodeAssist::Chat {
ChatRootView::ChatRootView(QQuickItem *parent)
: QQuickItem(parent)
, m_chatModel(new ChatModel(this))
, m_clientInterface(new ClientInterface(m_chatModel, this))
, m_promptProvider(LLMCore::PromptTemplateManager::instance())
, m_clientInterface(new ClientInterface(m_chatModel, &m_promptProvider, this))
{
m_isSyncOpenFiles = Settings::chatAssistantSettings().linkOpenFiles();
connect(

View File

@ -23,6 +23,7 @@
#include "ChatModel.hpp"
#include "ClientInterface.hpp"
#include "llmcore/PromptProviderChat.hpp"
#include <coreplugin/editormanager/editormanager.h>
namespace QodeAssist::Chat {
@ -99,6 +100,7 @@ private:
QString getSuggestedFileName() const;
ChatModel *m_chatModel;
LLMCore::PromptProviderChat m_promptProvider;
ClientInterface *m_clientInterface;
QString m_currentTemplate;
QString m_recentFilePath;

View File

@ -36,15 +36,16 @@
#include "ContextManager.hpp"
#include "GeneralSettings.hpp"
#include "Logger.hpp"
#include "PromptTemplateManager.hpp"
#include "ProvidersManager.hpp"
namespace QodeAssist::Chat {
ClientInterface::ClientInterface(ChatModel *chatModel, QObject *parent)
ClientInterface::ClientInterface(
ChatModel *chatModel, LLMCore::IPromptProvider *promptProvider, QObject *parent)
: QObject(parent)
, m_requestHandler(new LLMCore::RequestHandler(this))
, m_chatModel(chatModel)
, m_promptProvider(promptProvider)
{
connect(
m_requestHandler,
@ -86,8 +87,7 @@ void ClientInterface::sendMessage(
}
auto templateName = Settings::generalSettings().caTemplate();
auto promptTemplate = LLMCore::PromptTemplateManager::instance().getChatTemplateByName(
templateName);
auto promptTemplate = m_promptProvider->getTemplateByName(templateName);
if (!promptTemplate) {
LOG_MESSAGE(QString("No template found with name: %1").arg(templateName));

View File

@ -25,6 +25,7 @@
#include "ChatModel.hpp"
#include "RequestHandler.hpp"
#include "llmcore/IPromptProvider.hpp"
namespace QodeAssist::Chat {
@ -33,7 +34,8 @@ class ClientInterface : public QObject
Q_OBJECT
public:
explicit ClientInterface(ChatModel *chatModel, QObject *parent = nullptr);
explicit ClientInterface(
ChatModel *chatModel, LLMCore::IPromptProvider *promptProvider, QObject *parent = nullptr);
~ClientInterface();
void sendMessage(
@ -53,8 +55,9 @@ private:
QString getSystemPromptWithLinkedFiles(
const QString &basePrompt, const QList<QString> &linkedFiles) const;
LLMCore::RequestHandler *m_requestHandler;
LLMCore::IPromptProvider *m_promptProvider = nullptr;
ChatModel *m_chatModel;
LLMCore::RequestHandler *m_requestHandler;
};
} // namespace QodeAssist::Chat

View File

@ -40,10 +40,12 @@ namespace QodeAssist {
LLMClientInterface::LLMClientInterface(
const Settings::GeneralSettings &generalSettings,
const Settings::CodeCompletionSettings &completeSettings)
const Settings::CodeCompletionSettings &completeSettings,
LLMCore::IPromptProvider *promptProvider)
: m_requestHandler(this)
, m_generalSettings(generalSettings)
, m_completeSettings(completeSettings)
, m_promptProvider(promptProvider)
{
connect(
&m_requestHandler,
@ -175,8 +177,7 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request)
auto templateName = !isPreset1Active ? m_generalSettings.ccTemplate()
: m_generalSettings.ccPreset1Template();
auto promptTemplate = LLMCore::PromptTemplateManager::instance().getFimTemplateByName(
templateName);
auto promptTemplate = m_promptProvider->getTemplateByName(templateName);
if (!promptTemplate) {
LOG_MESSAGE(QString("No template found with name: %1").arg(templateName));
@ -281,8 +282,7 @@ void LLMClientInterface::sendCompletionToClient(
auto templateName = !isPreset1Active ? m_generalSettings.ccTemplate()
: m_generalSettings.ccPreset1Template();
auto promptTemplate = LLMCore::PromptTemplateManager::instance().getFimTemplateByName(
templateName);
auto promptTemplate = m_promptProvider->getTemplateByName(templateName);
QJsonObject position = request["params"].toObject()["doc"].toObject()["position"].toObject();

View File

@ -24,6 +24,7 @@
#include <context/ProgrammingLanguage.hpp>
#include <llmcore/ContextData.hpp>
#include <llmcore/IPromptProvider.hpp>
#include <llmcore/RequestHandler.hpp>
#include <settings/CodeCompletionSettings.hpp>
#include <settings/GeneralSettings.hpp>
@ -40,7 +41,8 @@ class LLMClientInterface : public LanguageClient::BaseClientInterface
public:
LLMClientInterface(
const Settings::GeneralSettings &generalSettings,
const Settings::CodeCompletionSettings &completeSettings);
const Settings::CodeCompletionSettings &completeSettings,
LLMCore::IPromptProvider *promptProvider);
Utils::FilePath serverDeviceTemplate() const override;
@ -67,6 +69,7 @@ private:
const Settings::CodeCompletionSettings &m_completeSettings;
const Settings::GeneralSettings &m_generalSettings;
LLMCore::IPromptProvider *m_promptProvider = nullptr;
LLMCore::RequestHandler m_requestHandler;
QElapsedTimer m_completionTimer;
QMap<QString, qint64> m_requestStartTimes;

View File

@ -44,9 +44,9 @@ using namespace Core;
namespace QodeAssist {
QodeAssistClient::QodeAssistClient()
: LanguageClient::Client(
new LLMClientInterface(Settings::generalSettings(), Settings::codeCompletionSettings()))
QodeAssistClient::QodeAssistClient(LLMCore::IPromptProvider *promptProvider)
: LanguageClient::Client(new LLMClientInterface(
Settings::generalSettings(), Settings::codeCompletionSettings(), promptProvider))
, m_recentCharCount(0)
{
setName("Qode Assist");

View File

@ -24,16 +24,16 @@
#pragma once
#include <languageclient/client.h>
#include "LSPCompletion.hpp"
#include <languageclient/client.h>
#include <llmcore/IPromptProvider.hpp>
namespace QodeAssist {
class QodeAssistClient : public LanguageClient::Client
{
public:
explicit QodeAssistClient();
explicit QodeAssistClient(LLMCore::IPromptProvider *promptProvider);
~QodeAssistClient() override;
void openDocument(TextEditor::TextDocument *document) override;

View File

@ -3,6 +3,9 @@ add_library(LLMCore STATIC
Provider.hpp
ProvidersManager.hpp ProvidersManager.cpp
ContextData.hpp
IPromptProvider.hpp
PromptProviderChat.hpp
PromptProviderFim.hpp
PromptTemplate.hpp
PromptTemplateManager.hpp PromptTemplateManager.cpp
RequestConfig.hpp

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2025 Povilas Kanapickas <povilas@radix.lt>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "PromptTemplate.hpp"
#include <QString>
namespace QodeAssist::LLMCore {
class IPromptProvider
{
public:
virtual ~IPromptProvider() = default;
virtual PromptTemplate *getTemplateByName(const QString &templateName) const = 0;
virtual QStringList templatesNames() const = 0;
virtual QStringList getTemplatesForProvider(ProviderID id) const = 0;
};
} // namespace QodeAssist::LLMCore

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2025 Povilas Kanapickas <povilas@radix.lt>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "IPromptProvider.hpp"
#include "PromptTemplate.hpp"
#include "PromptTemplateManager.hpp"
namespace QodeAssist::LLMCore {
class PromptProviderChat : public IPromptProvider
{
public:
explicit PromptProviderChat(PromptTemplateManager &templateManager)
: m_templateManager(templateManager)
{}
~PromptProviderChat() = default;
PromptTemplate *getTemplateByName(const QString &templateName) const override
{
return m_templateManager.getChatTemplateByName(templateName);
}
QStringList templatesNames() const override { return m_templateManager.chatTemplatesNames(); }
QStringList getTemplatesForProvider(ProviderID id) const override
{
return m_templateManager.getChatTemplatesForProvider(id);
}
private:
PromptTemplateManager &m_templateManager;
};
} // namespace QodeAssist::LLMCore

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2025 Povilas Kanapickas <povilas@radix.lt>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "IPromptProvider.hpp"
#include "PromptTemplateManager.hpp"
namespace QodeAssist::LLMCore {
class PromptProviderFim : public IPromptProvider
{
public:
explicit PromptProviderFim(PromptTemplateManager &templateManager)
: m_templateManager(templateManager)
{}
~PromptProviderFim() = default;
PromptTemplate *getTemplateByName(const QString &templateName) const override
{
return m_templateManager.getFimTemplateByName(templateName);
}
QStringList templatesNames() const override { return m_templateManager.fimTemplatesNames(); }
QStringList getTemplatesForProvider(ProviderID id) const override
{
return m_templateManager.getFimTemplatesForProvider(id);
}
private:
PromptTemplateManager &m_templateManager;
};
} // namespace QodeAssist::LLMCore

View File

@ -46,6 +46,7 @@
#include "Version.hpp"
#include "chat/ChatOutputPane.h"
#include "chat/NavigationPanel.hpp"
#include "llmcore/PromptProviderFim.hpp"
#include "settings/GeneralSettings.hpp"
#include "settings/ProjectSettingsPanel.hpp"
#include "settings/SettingsConstants.hpp"
@ -68,6 +69,7 @@ class QodeAssistPlugin final : public ExtensionSystem::IPlugin
public:
QodeAssistPlugin()
: m_updater(new PluginUpdater(this))
, m_promptProvider(LLMCore::PromptTemplateManager::instance())
{}
~QodeAssistPlugin() final
@ -135,7 +137,7 @@ public:
void restartClient()
{
LanguageClient::LanguageClientManager::shutdownClient(m_qodeAssistClient);
m_qodeAssistClient = new QodeAssistClient();
m_qodeAssistClient = new QodeAssistClient(&m_promptProvider);
}
bool delayedInitialize() final
@ -176,6 +178,7 @@ private:
}
QPointer<QodeAssistClient> m_qodeAssistClient;
LLMCore::PromptProviderFim m_promptProvider;
QPointer<Chat::ChatOutputPane> m_chatOutputPane;
QPointer<Chat::NavigationPanel> m_navigationPanel;
QPointer<PluginUpdater> m_updater;