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;
     }
 };