mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-05-28 03:10:28 -04:00
Merge pull request #5 from Palm1r/version-0.0.7
Version 0.0.7 - Add DeepSeekV2 template - Add performance benchmark - Move instructions and file path from FIM
This commit is contained in:
commit
6703a7026d
@ -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
|
||||
@ -48,4 +49,5 @@ add_qtc_plugin(QodeAssist
|
||||
QodeAssistClient.hpp QodeAssistClient.cpp
|
||||
QodeAssistUtils.hpp
|
||||
DocumentContextReader.hpp DocumentContextReader.cpp
|
||||
QodeAssistData.hpp
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
@ -136,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,
|
||||
@ -249,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();
|
||||
@ -272,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()
|
||||
@ -316,15 +325,17 @@ 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));
|
||||
}
|
||||
|
||||
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);
|
||||
@ -381,6 +392,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
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <languageclient/languageclientinterface.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#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();
|
||||
|
||||
@ -81,6 +77,13 @@ private:
|
||||
QNetworkAccessManager *m_manager;
|
||||
QMap<QString, QNetworkReply *> m_activeRequests;
|
||||
QMap<QNetworkReply *, QString> m_accumulatedResponses;
|
||||
|
||||
QElapsedTimer m_completionTimer;
|
||||
QMap<QString, qint64> m_requestStartTimes;
|
||||
|
||||
void startTimeMeasurement(const QString &requestId);
|
||||
void endTimeMeasurement(const QString &requestId);
|
||||
void logPerformance(const QString &requestId, const QString &operation, qint64 elapsedMs);
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
@ -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",
|
||||
|
@ -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";
|
||||
|
33
QodeAssistData.hpp
Normal file
33
QodeAssistData.hpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
struct ContextData
|
||||
{
|
||||
QString prefix;
|
||||
QString suffix;
|
||||
QString instriuctions;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
@ -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()
|
||||
|
@ -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};
|
||||
|
@ -17,7 +17,7 @@
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "OpenAICompatProvider.h"
|
||||
#include "OpenAICompatProvider.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
@ -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<Templates::CodeLLamaTemplate>();
|
||||
templateManager.registerTemplate<Templates::StarCoder2Template>();
|
||||
templateManager.registerTemplate<Templates::CodeQwenChatTemplate>();
|
||||
templateManager.registerTemplate<Templates::DeepSeekCoderV2Template>();
|
||||
|
||||
Utils::Icon QCODEASSIST_ICON(
|
||||
{{":/resources/images/qoderassist-icon.png", Utils::Theme::IconsBaseColor}});
|
||||
|
@ -27,17 +27,17 @@ class CodeLLamaTemplate : public PromptTemplate
|
||||
{
|
||||
public:
|
||||
QString name() const override { return "CodeLlama"; }
|
||||
QString promptTemplate() const override { return "<PRE> %1 <SUF>%2 <MID>"; }
|
||||
QString promptTemplate() const override { return "%1<PRE> %2 <SUF>%3 <MID>"; }
|
||||
QStringList stopWords() const override
|
||||
{
|
||||
return QStringList() << "<EOT>" << "<PRE>" << "<SUF" << "<MID>";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
44
templates/DeepSeekCoderV2.hpp
Normal file
44
templates/DeepSeekCoderV2.hpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PromptTemplate.hpp"
|
||||
|
||||
namespace QodeAssist::Templates {
|
||||
|
||||
class DeepSeekCoderV2Template : public PromptTemplate
|
||||
{
|
||||
public:
|
||||
QString name() const override { return "DeepSeekCoderV2"; }
|
||||
QString promptTemplate() const override
|
||||
{
|
||||
return "%1<|fim▁begin|>%2<|fim▁hole|>%3<|fim▁end|>";
|
||||
}
|
||||
QStringList stopWords() const override { return QStringList(); }
|
||||
void prepareRequest(QJsonObject &request, const ContextData &context) const override
|
||||
{
|
||||
QString formattedPrompt = promptTemplate().arg(context.instriuctions,
|
||||
context.prefix,
|
||||
context.suffix);
|
||||
request["prompt"] = formattedPrompt;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Templates
|
@ -23,6 +23,8 @@
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#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
|
||||
|
@ -27,17 +27,17 @@ class StarCoder2Template : public PromptTemplate
|
||||
{
|
||||
public:
|
||||
QString name() const override { return "StarCoder2"; }
|
||||
QString promptTemplate() const override { return "<fim_prefix>%1<fim_suffix>%2<fim_middle>"; }
|
||||
QString promptTemplate() const override { return "%1<fim_prefix>%2<fim_suffix>%3<fim_middle>"; }
|
||||
QStringList stopWords() const override
|
||||
{
|
||||
return QStringList() << "<|endoftext|>" << "<file_sep>" << "<fim_prefix>" << "<fim_suffix>"
|
||||
<< "<fim_middle>";
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user