From 4f0f9338dccf44c69811cff13e8ca0a0377bdb45 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sat, 31 Aug 2024 23:20:23 +0200 Subject: [PATCH 1/3] Add DeepSeekCoderV2 template --- CMakeLists.txt | 3 +- QodeAssist.json.in | 2 +- providers/OpenAICompatProvider.cpp | 2 +- ...patProvider.h => OpenAICompatProvider.hpp} | 0 qodeassist.cpp | 4 +- templates/DeepSeekCoderV2.hpp | 44 +++++++++++++++++++ 6 files changed, 51 insertions(+), 4 deletions(-) rename providers/{OpenAICompatProvider.h => OpenAICompatProvider.hpp} (100%) create mode 100644 templates/DeepSeekCoderV2.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a269b24..9533a35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,10 +35,11 @@ add_qtc_plugin(QodeAssist templates/CodeLLamaTemplate.hpp templates/StarCoder2Template.hpp templates/CodeQwenChat.hpp + templates/DeepSeekCoderV2.hpp providers/LLMProvider.hpp providers/OllamaProvider.hpp providers/OllamaProvider.cpp providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp - providers/OpenAICompatProvider.h providers/OpenAICompatProvider.cpp + providers/OpenAICompatProvider.hpp providers/OpenAICompatProvider.cpp LLMProvidersManager.hpp LLMProvidersManager.cpp QodeAssistSettings.hpp QodeAssistSettings.cpp QodeAssist.qrc diff --git a/QodeAssist.json.in b/QodeAssist.json.in index 4cf3b12..264266e 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.0.6", + "Version" : "0.0.7", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Vendor" : "Petr Mironychev", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index 9ec55b5..51fdc54 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -17,7 +17,7 @@ * along with QodeAssist. If not, see . */ -#include "OpenAICompatProvider.h" +#include "OpenAICompatProvider.hpp" #include #include diff --git a/providers/OpenAICompatProvider.h b/providers/OpenAICompatProvider.hpp similarity index 100% rename from providers/OpenAICompatProvider.h rename to providers/OpenAICompatProvider.hpp diff --git a/qodeassist.cpp b/qodeassist.cpp index 90fd069..ffcd0f6 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -43,9 +43,10 @@ #include "QodeAssistClient.hpp" #include "providers/LMStudioProvider.hpp" #include "providers/OllamaProvider.hpp" -#include "providers/OpenAICompatProvider.h" +#include "providers/OpenAICompatProvider.hpp" #include "templates/CodeLLamaTemplate.hpp" #include "templates/CodeQwenChat.hpp" +#include "templates/DeepSeekCoderV2.hpp" #include "templates/StarCoder2Template.hpp" using namespace Utils; @@ -80,6 +81,7 @@ public: templateManager.registerTemplate(); templateManager.registerTemplate(); templateManager.registerTemplate(); + templateManager.registerTemplate(); Utils::Icon QCODEASSIST_ICON( {{":/resources/images/qoderassist-icon.png", Utils::Theme::IconsBaseColor}}); diff --git a/templates/DeepSeekCoderV2.hpp b/templates/DeepSeekCoderV2.hpp new file mode 100644 index 0000000..2c60f4b --- /dev/null +++ b/templates/DeepSeekCoderV2.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include "PromptTemplate.hpp" + +namespace QodeAssist::Templates { + +class DeepSeekCoderV2Template : public PromptTemplate +{ +public: + QString name() const override { return "DeepSeekCoderV2"; } + QString promptTemplate() const override + { + return "<|fim▁begin|>%1<|fim▁hole|>%2<|fim▁end|>"; + } + QStringList stopWords() const override { return QStringList(); } + void prepareRequest(QJsonObject &request, + const QString &prefix, + const QString &suffix) const override + { + QString formattedPrompt = promptTemplate().arg(prefix, suffix); + request["prompt"] = formattedPrompt; + } +}; + +} // namespace QodeAssist::Templates From dec8967df2f3592bba2b93ea39ede673748a8901 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sat, 31 Aug 2024 23:56:54 +0200 Subject: [PATCH 2/3] Add performance benchmark --- LLMClientInterface.cpp | 27 +++++++++++++++++++++++++++ LLMClientInterface.hpp | 7 +++++++ 2 files changed, 34 insertions(+) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 9414ebb..cba2f0b 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -69,6 +69,8 @@ void LLMClientInterface::sendData(const QByteArray &data) } else if (method == "textDocument/didOpen") { handleTextDocumentDidOpen(request); } else if (method == "getCompletionsCycling") { + QString requestId = request["id"].toString(); + startTimeMeasurement(requestId); handleCompletion(request); } else if (method == "$/cancelRequest") { handleCancelRequest(request); @@ -316,6 +318,8 @@ void LLMClientInterface::sendCompletionToClient(const QString &completion, logMessage(QString("Full response: \n%1") .arg(QString::fromUtf8(QJsonDocument(response).toJson(QJsonDocument::Indented)))); + QString requestId = request["id"].toString(); + endTimeMeasurement(requestId); emit messageReceived(LanguageServerProtocol::JsonRpcMessage(response)); } @@ -381,6 +385,29 @@ QString LLMClientInterface::removeStopWords(const QString &completion) return filteredCompletion; } +void LLMClientInterface::startTimeMeasurement(const QString &requestId) +{ + m_requestStartTimes[requestId] = QDateTime::currentMSecsSinceEpoch(); +} + +void LLMClientInterface::endTimeMeasurement(const QString &requestId) +{ + if (m_requestStartTimes.contains(requestId)) { + qint64 startTime = m_requestStartTimes[requestId]; + qint64 endTime = QDateTime::currentMSecsSinceEpoch(); + qint64 totalTime = endTime - startTime; + logPerformance(requestId, "TotalCompletionTime", totalTime); + m_requestStartTimes.remove(requestId); + } +} + +void LLMClientInterface::logPerformance(const QString &requestId, + const QString &operation, + qint64 elapsedMs) +{ + logMessage(QString("Performance: %1 %2 took %3 ms").arg(requestId, operation).arg(elapsedMs)); +} + void LLMClientInterface::parseCurrentMessage() {} } // namespace QodeAssist diff --git a/LLMClientInterface.hpp b/LLMClientInterface.hpp index 6fef777..a648806 100644 --- a/LLMClientInterface.hpp +++ b/LLMClientInterface.hpp @@ -81,6 +81,13 @@ private: QNetworkAccessManager *m_manager; QMap m_activeRequests; QMap m_accumulatedResponses; + + QElapsedTimer m_completionTimer; + QMap m_requestStartTimes; + + void startTimeMeasurement(const QString &requestId); + void endTimeMeasurement(const QString &requestId); + void logPerformance(const QString &requestId, const QString &operation, qint64 elapsedMs); }; } // namespace QodeAssist From d7fc62f94b23e6b51257b926fcbc7d0abd331ef9 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:00:14 +0200 Subject: [PATCH 3/3] Move instractoins out from FIM request --- CMakeLists.txt | 1 + DocumentContextReader.cpp | 4 ++-- LLMClientInterface.cpp | 21 +++++++++++++------- LLMClientInterface.hpp | 12 ++++-------- QodeAssistConstants.hpp | 2 ++ QodeAssistData.hpp | 33 ++++++++++++++++++++++++++++++++ QodeAssistSettings.cpp | 14 ++++++++++++++ QodeAssistSettings.hpp | 2 ++ templates/CodeLLamaTemplate.hpp | 10 +++++----- templates/CodeQwenChat.hpp | 10 +++++----- templates/DeepSeekCoderV2.hpp | 10 +++++----- templates/PromptTemplate.hpp | 7 +++---- templates/StarCoder2Template.hpp | 10 +++++----- 13 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 QodeAssistData.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9533a35..deb32f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,4 +49,5 @@ add_qtc_plugin(QodeAssist QodeAssistClient.hpp QodeAssistClient.cpp QodeAssistUtils.hpp DocumentContextReader.hpp DocumentContextReader.cpp + QodeAssistData.hpp ) diff --git a/DocumentContextReader.cpp b/DocumentContextReader.cpp index c52047e..997ae23 100644 --- a/DocumentContextReader.cpp +++ b/DocumentContextReader.cpp @@ -130,7 +130,7 @@ QString DocumentContextReader::getLanguageAndFileInfo() const QString filePath = m_textDocument->filePath().toString(); QString fileExtension = QFileInfo(filePath).suffix(); - return QString("//Language: %1 (MIME: %2) filepath: %3(%4)\n\n") + return QString("Language: %1 (MIME: %2) filepath: %3(%4)\n\n") .arg(language, mimeType, filePath, fileExtension); } @@ -138,7 +138,7 @@ QString DocumentContextReader::getSpecificInstructions() const { QString specificInstruction = settings().specificInstractions().arg( LanguageServerProtocol::TextDocumentItem::mimeTypeToLanguageId(m_textDocument->mimeType())); - return QString("//Instructions: %1").arg(specificInstruction); + return QString("Instructions: %1").arg(specificInstruction); } CopyrightInfo DocumentContextReader::findCopyright() diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index cba2f0b..9bfbc62 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -138,8 +138,7 @@ QString LLMClientInterface::сontextBefore(TextEditor::TextEditorWidget *widget, settings().readStringsBeforeCursor()); } - return QString("%1\n%2\n%3") - .arg(reader.getSpecificInstructions(), reader.getLanguageAndFileInfo(), contextBefore); + return contextBefore; } QString LLMClientInterface::сontextAfter(TextEditor::TextEditorWidget *widget, @@ -251,8 +250,8 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request, sendLLMRequest(request, updatedContext); } -LLMClientInterface::ContextPair LLMClientInterface::prepareContext( - const QJsonObject &request, const QString &accumulatedCompletion) +ContextData LLMClientInterface::prepareContext(const QJsonObject &request, + const QString &accumulatedCompletion) { QJsonObject params = request["params"].toObject(); QJsonObject doc = params["doc"].toObject(); @@ -274,12 +273,20 @@ LLMClientInterface::ContextPair LLMClientInterface::prepareContext( auto textEditor = TextEditor::BaseTextEditor::currentTextEditor(); TextEditor::TextEditorWidget *widget = textEditor->editorWidget(); + DocumentContextReader reader(widget->textDocument()); + QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition); + QString instructions = QString("%1%2").arg(settings().useSpecificInstructions() + ? reader.getSpecificInstructions() + : QString(), + settings().useFilePathInContext() + ? reader.getLanguageAndFileInfo() + : QString()); QString updatedContextBefore = contextBefore + accumulatedCompletion; - return {updatedContextBefore, contextAfter}; + return {updatedContextBefore, contextAfter, instructions}; } void LLMClientInterface::updateProvider() @@ -323,12 +330,12 @@ void LLMClientInterface::sendCompletionToClient(const QString &completion, emit messageReceived(LanguageServerProtocol::JsonRpcMessage(response)); } -void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const ContextPair &prompt) +void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const ContextData &prompt) { QJsonObject providerRequest = {{"model", settings().modelName.value()}, {"stream", true}}; auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); - currentTemplate->prepareRequest(providerRequest, prompt.prefix, prompt.suffix); + currentTemplate->prepareRequest(providerRequest, prompt); auto &providerManager = LLMProvidersManager::instance(); providerManager.getCurrentProvider()->prepareRequest(providerRequest); diff --git a/LLMClientInterface.hpp b/LLMClientInterface.hpp index a648806..04ce29a 100644 --- a/LLMClientInterface.hpp +++ b/LLMClientInterface.hpp @@ -22,6 +22,8 @@ #include #include +#include "QodeAssistData.hpp" + class QNetworkReply; class QNetworkAccessManager; @@ -35,12 +37,6 @@ public: LLMClientInterface(); public: - struct ContextPair - { - QString prefix; - QString suffix; - }; - Utils::FilePath serverDeviceTemplate() const override; void sendCompletionToClient(const QString &completion, @@ -50,10 +46,10 @@ public: void handleCompletion(const QJsonObject &request, const QString &accumulatedCompletion = QString()); - void sendLLMRequest(const QJsonObject &request, const ContextPair &prompt); + void sendLLMRequest(const QJsonObject &request, const ContextData &prompt); void handleLLMResponse(QNetworkReply *reply, const QJsonObject &request); - ContextPair prepareContext(const QJsonObject &request, + ContextData prepareContext(const QJsonObject &request, const QString &accumulatedCompletion = QString{}); void updateProvider(); diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp index a05cf4f..4cb9971 100644 --- a/QodeAssistConstants.hpp +++ b/QodeAssistConstants.hpp @@ -54,6 +54,8 @@ const char OLLAMA_LIVETIME[] = "QodeAssist.ollamaLivetime"; const char SPECIFIC_INSTRUCTIONS[] = "QodeAssist.specificInstractions"; const char MULTILINE_COMPLETION[] = "QodeAssist.multilineCompletion"; const char API_KEY[] = "QodeAssist.apiKey"; +const char USE_SPECIFIC_INSTRUCTIONS[] = "QodeAssist.useSpecificInstructions"; +const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; diff --git a/QodeAssistData.hpp b/QodeAssistData.hpp new file mode 100644 index 0000000..3a8c76e --- /dev/null +++ b/QodeAssistData.hpp @@ -0,0 +1,33 @@ +/* + * 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 { + +struct ContextData +{ + QString prefix; + QString suffix; + QString instriuctions; +}; + +} // namespace QodeAssist diff --git a/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index bf2630f..b280afe 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -153,6 +153,14 @@ QodeAssistSettings::QodeAssistSettings() startSuggestionTimer.setRange(10, 10000); startSuggestionTimer.setDefaultValue(500); + useFilePathInContext.setSettingsKey(Constants::USE_FILE_PATH_IN_CONTEXT); + useFilePathInContext.setDefaultValue(false); + useFilePathInContext.setLabelText(Tr::tr("Use File Path in Context")); + + useSpecificInstructions.setSettingsKey(Constants::USE_SPECIFIC_INSTRUCTIONS); + useSpecificInstructions.setDefaultValue(false); + useSpecificInstructions.setLabelText(Tr::tr("Use Specific Instructions")); + specificInstractions.setSettingsKey(Constants::SPECIFIC_INSTRUCTIONS); specificInstractions.setDisplayStyle(Utils::StringAspect::TextEditDisplay); specificInstractions.setLabelText( @@ -195,6 +203,7 @@ QodeAssistSettings::QodeAssistSettings() frequencyPenalty.setEnabled(useFrequencyPenalty()); readStringsAfterCursor.setEnabled(!readFullFile()); readStringsBeforeCursor.setEnabled(!readFullFile()); + specificInstractions.setEnabled(useSpecificInstructions()); PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue()); LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue()); @@ -221,6 +230,8 @@ QodeAssistSettings::QodeAssistSettings() readStringsAfterCursor, ollamaLivetime, apiKey, + useFilePathInContext, + useSpecificInstructions, specificInstractions, temperature, maxTokens, @@ -274,6 +285,9 @@ void QodeAssistSettings::setupConnections() connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { setLoggingEnabled(enableLogging.volatileValue()); }); + connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() { + specificInstractions.setEnabled(useSpecificInstructions.volatileValue()); + }); } void QodeAssistSettings::updateProviderSettings() diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index 18f6064..f974874 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -95,6 +95,8 @@ public: Utils::StringAspect ollamaLivetime{this}; Utils::StringAspect specificInstractions{this}; + Utils::BoolAspect useSpecificInstructions{this}; + Utils::BoolAspect useFilePathInContext{this}; Utils::BoolAspect multiLineCompletion{this}; Utils::StringAspect apiKey{this}; diff --git a/templates/CodeLLamaTemplate.hpp b/templates/CodeLLamaTemplate.hpp index 5159979..6115d28 100644 --- a/templates/CodeLLamaTemplate.hpp +++ b/templates/CodeLLamaTemplate.hpp @@ -27,17 +27,17 @@ class CodeLLamaTemplate : public PromptTemplate { public: QString name() const override { return "CodeLlama"; } - QString promptTemplate() const override { return "
 %1 %2 "; }
+    QString promptTemplate() const override { return "%1
 %2 %3 "; }
     QStringList stopWords() const override
     {
         return QStringList() << "" << "
" << "";
     }
 
-    void prepareRequest(QJsonObject &request,
-                        const QString &prefix,
-                        const QString &suffix) const override
+    void prepareRequest(QJsonObject &request, const ContextData &context) const override
     {
-        QString formattedPrompt = promptTemplate().arg(prefix, suffix);
+        QString formattedPrompt = promptTemplate().arg(context.instriuctions,
+                                                       context.prefix,
+                                                       context.suffix);
         request["prompt"] = formattedPrompt;
     }
 };
diff --git a/templates/CodeQwenChat.hpp b/templates/CodeQwenChat.hpp
index dff2f07..dfae27e 100644
--- a/templates/CodeQwenChat.hpp
+++ b/templates/CodeQwenChat.hpp
@@ -27,16 +27,16 @@ class CodeQwenChatTemplate : public PromptTemplate
 {
 public:
     QString name() const override { return "CodeQwenChat (experimental)"; }
-    QString promptTemplate() const override { return "\n### Instruction:%1%2 ### Response:\n"; }
+    QString promptTemplate() const override { return "%1\n### Instruction:%2%3 ### Response:\n"; }
     QStringList stopWords() const override
     {
         return QStringList() << "### Instruction:" << "### Response:" << "\n\n### ";
     }
-    void prepareRequest(QJsonObject &request,
-                        const QString &prefix,
-                        const QString &suffix) const override
+    void prepareRequest(QJsonObject &request, const ContextData &context) const override
     {
-        QString formattedPrompt = promptTemplate().arg(prefix, suffix);
+        QString formattedPrompt = promptTemplate().arg(context.instriuctions,
+                                                       context.prefix,
+                                                       context.suffix);
         request["prompt"] = formattedPrompt;
     }
 };
diff --git a/templates/DeepSeekCoderV2.hpp b/templates/DeepSeekCoderV2.hpp
index 2c60f4b..69886fb 100644
--- a/templates/DeepSeekCoderV2.hpp
+++ b/templates/DeepSeekCoderV2.hpp
@@ -29,14 +29,14 @@ public:
     QString name() const override { return "DeepSeekCoderV2"; }
     QString promptTemplate() const override
     {
-        return "<|fim▁begin|>%1<|fim▁hole|>%2<|fim▁end|>";
+        return "%1<|fim▁begin|>%2<|fim▁hole|>%3<|fim▁end|>";
     }
     QStringList stopWords() const override { return QStringList(); }
-    void prepareRequest(QJsonObject &request,
-                        const QString &prefix,
-                        const QString &suffix) const override
+    void prepareRequest(QJsonObject &request, const ContextData &context) const override
     {
-        QString formattedPrompt = promptTemplate().arg(prefix, suffix);
+        QString formattedPrompt = promptTemplate().arg(context.instriuctions,
+                                                       context.prefix,
+                                                       context.suffix);
         request["prompt"] = formattedPrompt;
     }
 };
diff --git a/templates/PromptTemplate.hpp b/templates/PromptTemplate.hpp
index 72b254a..5b134ee 100644
--- a/templates/PromptTemplate.hpp
+++ b/templates/PromptTemplate.hpp
@@ -23,6 +23,8 @@
 #include 
 #include 
 
+#include "QodeAssistData.hpp"
+
 namespace QodeAssist::Templates {
 
 class PromptTemplate
@@ -32,9 +34,6 @@ public:
     virtual QString name() const = 0;
     virtual QString promptTemplate() const = 0;
     virtual QStringList stopWords() const = 0;
-    virtual void prepareRequest(QJsonObject &request,
-                                const QString &prefix,
-                                const QString &suffix) const
-        = 0;
+    virtual void prepareRequest(QJsonObject &request, const ContextData &context) const = 0;
 };
 } // namespace QodeAssist::Templates
diff --git a/templates/StarCoder2Template.hpp b/templates/StarCoder2Template.hpp
index 456b50a..8f89679 100644
--- a/templates/StarCoder2Template.hpp
+++ b/templates/StarCoder2Template.hpp
@@ -27,17 +27,17 @@ class StarCoder2Template : public PromptTemplate
 {
 public:
     QString name() const override { return "StarCoder2"; }
-    QString promptTemplate() const override { return "%1%2"; }
+    QString promptTemplate() const override { return "%1%2%3"; }
     QStringList stopWords() const override
     {
         return QStringList() << "<|endoftext|>" << "" << "" << ""
                              << "";
     }
-    void prepareRequest(QJsonObject &request,
-                        const QString &prefix,
-                        const QString &suffix) const override
+    void prepareRequest(QJsonObject &request, const ContextData &context) const override
     {
-        QString formattedPrompt = promptTemplate().arg(prefix, suffix);
+        QString formattedPrompt = promptTemplate().arg(context.instriuctions,
+                                                       context.prefix,
+                                                       context.suffix);
         request["prompt"] = formattedPrompt;
     }
 };