Compare commits

...

8 Commits

Author SHA1 Message Date
6703a7026d 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
2024-09-01 12:09:15 +02:00
d7fc62f94b Move instractoins out from FIM request 2024-09-01 12:06:55 +02:00
dec8967df2 Add performance benchmark 2024-09-01 00:06:11 +02:00
4f0f9338dc Add DeepSeekCoderV2 template 2024-08-31 23:20:23 +02:00
ec26a31ec5 Merge pull request #4 from Palm1r/version-0.0.6
Version 0.0.6
- Fix authorization to API
- Fix reset to provider default settings after reboot qtc
2024-08-30 08:48:09 +02:00
55d359e44e Fix reset to provider default settings on restart qtc 2024-08-30 08:28:27 +02:00
46258a11f6 Fix authorization to the API. 2024-08-30 07:47:33 +02:00
4bccd8db91 Add new provider to README.md 2024-08-29 23:35:34 +02:00
23 changed files with 196 additions and 84 deletions

View File

@ -35,10 +35,11 @@ add_qtc_plugin(QodeAssist
templates/CodeLLamaTemplate.hpp templates/CodeLLamaTemplate.hpp
templates/StarCoder2Template.hpp templates/StarCoder2Template.hpp
templates/CodeQwenChat.hpp templates/CodeQwenChat.hpp
templates/DeepSeekCoderV2.hpp
providers/LLMProvider.hpp providers/LLMProvider.hpp
providers/OllamaProvider.hpp providers/OllamaProvider.cpp providers/OllamaProvider.hpp providers/OllamaProvider.cpp
providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp
providers/OpenAICompatProvider.h providers/OpenAICompatProvider.cpp providers/OpenAICompatProvider.hpp providers/OpenAICompatProvider.cpp
LLMProvidersManager.hpp LLMProvidersManager.cpp LLMProvidersManager.hpp LLMProvidersManager.cpp
QodeAssistSettings.hpp QodeAssistSettings.cpp QodeAssistSettings.hpp QodeAssistSettings.cpp
QodeAssist.qrc QodeAssist.qrc
@ -48,4 +49,5 @@ add_qtc_plugin(QodeAssist
QodeAssistClient.hpp QodeAssistClient.cpp QodeAssistClient.hpp QodeAssistClient.cpp
QodeAssistUtils.hpp QodeAssistUtils.hpp
DocumentContextReader.hpp DocumentContextReader.cpp DocumentContextReader.hpp DocumentContextReader.cpp
QodeAssistData.hpp
) )

View File

@ -130,7 +130,7 @@ QString DocumentContextReader::getLanguageAndFileInfo() const
QString filePath = m_textDocument->filePath().toString(); QString filePath = m_textDocument->filePath().toString();
QString fileExtension = QFileInfo(filePath).suffix(); 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); .arg(language, mimeType, filePath, fileExtension);
} }
@ -138,7 +138,7 @@ QString DocumentContextReader::getSpecificInstructions() const
{ {
QString specificInstruction = settings().specificInstractions().arg( QString specificInstruction = settings().specificInstractions().arg(
LanguageServerProtocol::TextDocumentItem::mimeTypeToLanguageId(m_textDocument->mimeType())); LanguageServerProtocol::TextDocumentItem::mimeTypeToLanguageId(m_textDocument->mimeType()));
return QString("//Instructions: %1").arg(specificInstruction); return QString("Instructions: %1").arg(specificInstruction);
} }
CopyrightInfo DocumentContextReader::findCopyright() CopyrightInfo DocumentContextReader::findCopyright()

View File

@ -69,6 +69,8 @@ void LLMClientInterface::sendData(const QByteArray &data)
} else if (method == "textDocument/didOpen") { } else if (method == "textDocument/didOpen") {
handleTextDocumentDidOpen(request); handleTextDocumentDidOpen(request);
} else if (method == "getCompletionsCycling") { } else if (method == "getCompletionsCycling") {
QString requestId = request["id"].toString();
startTimeMeasurement(requestId);
handleCompletion(request); handleCompletion(request);
} else if (method == "$/cancelRequest") { } else if (method == "$/cancelRequest") {
handleCancelRequest(request); handleCancelRequest(request);
@ -136,8 +138,7 @@ QString LLMClientInterface::сontextBefore(TextEditor::TextEditorWidget *widget,
settings().readStringsBeforeCursor()); settings().readStringsBeforeCursor());
} }
return QString("%1\n%2\n%3") return contextBefore;
.arg(reader.getSpecificInstructions(), reader.getLanguageAndFileInfo(), contextBefore);
} }
QString LLMClientInterface::сontextAfter(TextEditor::TextEditorWidget *widget, QString LLMClientInterface::сontextAfter(TextEditor::TextEditorWidget *widget,
@ -249,8 +250,8 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request,
sendLLMRequest(request, updatedContext); sendLLMRequest(request, updatedContext);
} }
LLMClientInterface::ContextPair LLMClientInterface::prepareContext( ContextData LLMClientInterface::prepareContext(const QJsonObject &request,
const QJsonObject &request, const QString &accumulatedCompletion) const QString &accumulatedCompletion)
{ {
QJsonObject params = request["params"].toObject(); QJsonObject params = request["params"].toObject();
QJsonObject doc = params["doc"].toObject(); QJsonObject doc = params["doc"].toObject();
@ -272,20 +273,25 @@ LLMClientInterface::ContextPair LLMClientInterface::prepareContext(
auto textEditor = TextEditor::BaseTextEditor::currentTextEditor(); auto textEditor = TextEditor::BaseTextEditor::currentTextEditor();
TextEditor::TextEditorWidget *widget = textEditor->editorWidget(); TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
DocumentContextReader reader(widget->textDocument());
QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition);
QString contextAfter = сontextAfter(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; QString updatedContextBefore = contextBefore + accumulatedCompletion;
return {updatedContextBefore, contextAfter}; return {updatedContextBefore, contextAfter, instructions};
} }
void LLMClientInterface::updateProvider() void LLMClientInterface::updateProvider()
{ {
m_serverUrl = QUrl(QString("%1:%2%3") m_serverUrl = QUrl(QString("%1%2").arg(settings().url(), settings().endPoint()));
.arg(settings().url.value())
.arg(settings().port.value())
.arg(settings().endPoint.value()));
} }
void LLMClientInterface::sendCompletionToClient(const QString &completion, void LLMClientInterface::sendCompletionToClient(const QString &completion,
@ -319,27 +325,36 @@ void LLMClientInterface::sendCompletionToClient(const QString &completion,
logMessage(QString("Full response: \n%1") logMessage(QString("Full response: \n%1")
.arg(QString::fromUtf8(QJsonDocument(response).toJson(QJsonDocument::Indented)))); .arg(QString::fromUtf8(QJsonDocument(response).toJson(QJsonDocument::Indented))));
QString requestId = request["id"].toString();
endTimeMeasurement(requestId);
emit messageReceived(LanguageServerProtocol::JsonRpcMessage(response)); emit messageReceived(LanguageServerProtocol::JsonRpcMessage(response));
} }
void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const ContextPair &prompt) void LLMClientInterface::sendLLMRequest(const QJsonObject &request, const ContextData &prompt)
{ {
QJsonObject qodeRequest = {{"model", settings().modelName.value()}, {"stream", true}}; QJsonObject providerRequest = {{"model", settings().modelName.value()}, {"stream", true}};
auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate(); auto currentTemplate = PromptTemplateManager::instance().getCurrentTemplate();
currentTemplate->prepareRequest(qodeRequest, prompt.prefix, prompt.suffix); currentTemplate->prepareRequest(providerRequest, prompt);
auto &providerManager = LLMProvidersManager::instance(); auto &providerManager = LLMProvidersManager::instance();
providerManager.getCurrentProvider()->prepareRequest(qodeRequest); providerManager.getCurrentProvider()->prepareRequest(providerRequest);
logMessage( logMessage(QString("Sending request to llm: \nurl: %1\nRequest body:\n%2")
QString("Sending request to llm: \nurl: %1\nRequest body:\n%2") .arg(m_serverUrl.toString(),
.arg(m_serverUrl.toString()) QString::fromUtf8(
.arg(QString::fromUtf8(QJsonDocument(qodeRequest).toJson(QJsonDocument::Indented)))); QJsonDocument(providerRequest).toJson(QJsonDocument::Indented))));
QNetworkRequest networkRequest(m_serverUrl); QNetworkRequest networkRequest(m_serverUrl);
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_manager->post(networkRequest, QJsonDocument(qodeRequest).toJson());
if (providerRequest.contains("api_key")) {
QString apiKey = providerRequest["api_key"].toString();
networkRequest.setRawHeader("Authorization", QString("Bearer %1").arg(apiKey).toUtf8());
providerRequest.remove("api_key");
}
QNetworkReply *reply = m_manager->post(networkRequest, QJsonDocument(providerRequest).toJson());
if (!reply) { if (!reply) {
logMessage("Error: Failed to create network reply"); logMessage("Error: Failed to create network reply");
return; return;
@ -377,6 +392,29 @@ QString LLMClientInterface::removeStopWords(const QString &completion)
return filteredCompletion; 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() {} void LLMClientInterface::parseCurrentMessage() {}
} // namespace QodeAssist } // namespace QodeAssist

View File

@ -22,6 +22,8 @@
#include <languageclient/languageclientinterface.h> #include <languageclient/languageclientinterface.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include "QodeAssistData.hpp"
class QNetworkReply; class QNetworkReply;
class QNetworkAccessManager; class QNetworkAccessManager;
@ -35,12 +37,6 @@ public:
LLMClientInterface(); LLMClientInterface();
public: public:
struct ContextPair
{
QString prefix;
QString suffix;
};
Utils::FilePath serverDeviceTemplate() const override; Utils::FilePath serverDeviceTemplate() const override;
void sendCompletionToClient(const QString &completion, void sendCompletionToClient(const QString &completion,
@ -50,10 +46,10 @@ public:
void handleCompletion(const QJsonObject &request, void handleCompletion(const QJsonObject &request,
const QString &accumulatedCompletion = QString()); 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); void handleLLMResponse(QNetworkReply *reply, const QJsonObject &request);
ContextPair prepareContext(const QJsonObject &request, ContextData prepareContext(const QJsonObject &request,
const QString &accumulatedCompletion = QString{}); const QString &accumulatedCompletion = QString{});
void updateProvider(); void updateProvider();
@ -81,6 +77,13 @@ private:
QNetworkAccessManager *m_manager; QNetworkAccessManager *m_manager;
QMap<QString, QNetworkReply *> m_activeRequests; QMap<QString, QNetworkReply *> m_activeRequests;
QMap<QNetworkReply *, QString> m_accumulatedResponses; 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 } // namespace QodeAssist

View File

@ -1,6 +1,6 @@
{ {
"Name" : "QodeAssist", "Name" : "QodeAssist",
"Version" : "0.0.5", "Version" : "0.0.7",
"CompatVersion" : "${IDE_VERSION_COMPAT}", "CompatVersion" : "${IDE_VERSION_COMPAT}",
"Vendor" : "Petr Mironychev", "Vendor" : "Petr Mironychev",
"Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",

View File

@ -30,7 +30,6 @@ const char ENABLE_AUTO_COMPLETE[] = "QodeAssist.enableAutoComplete";
const char ENABLE_LOGGING[] = "QodeAssist.enableLogging"; const char ENABLE_LOGGING[] = "QodeAssist.enableLogging";
const char LLM_PROVIDERS[] = "QodeAssist.llmProviders"; const char LLM_PROVIDERS[] = "QodeAssist.llmProviders";
const char URL[] = "QodeAssist.url"; const char URL[] = "QodeAssist.url";
const char PORT[] = "QodeAssist.port";
const char END_POINT[] = "QodeAssist.endPoint"; const char END_POINT[] = "QodeAssist.endPoint";
const char MODEL_NAME[] = "QodeAssist.modelName"; const char MODEL_NAME[] = "QodeAssist.modelName";
const char SELECT_MODELS[] = "QodeAssist.selectModels"; const char SELECT_MODELS[] = "QodeAssist.selectModels";
@ -55,6 +54,8 @@ const char OLLAMA_LIVETIME[] = "QodeAssist.ollamaLivetime";
const char SPECIFIC_INSTRUCTIONS[] = "QodeAssist.specificInstractions"; const char SPECIFIC_INSTRUCTIONS[] = "QodeAssist.specificInstractions";
const char MULTILINE_COMPLETION[] = "QodeAssist.multilineCompletion"; const char MULTILINE_COMPLETION[] = "QodeAssist.multilineCompletion";
const char API_KEY[] = "QodeAssist.apiKey"; 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_ID[] = "QodeAssist.GeneralOptions";
const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category"; const char QODE_ASSIST_GENERAL_OPTIONS_CATEGORY[] = "QodeAssist.Category";

33
QodeAssistData.hpp Normal file
View 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

View File

@ -68,10 +68,6 @@ QodeAssistSettings::QodeAssistSettings()
endPoint.setLabelText(Tr::tr("Endpoint:")); endPoint.setLabelText(Tr::tr("Endpoint:"));
endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay); endPoint.setDisplayStyle(Utils::StringAspect::LineEditDisplay);
port.setSettingsKey(Constants::PORT);
port.setLabelText(Tr::tr("Port:"));
port.setRange(1, 65535);
modelName.setSettingsKey(Constants::MODEL_NAME); modelName.setSettingsKey(Constants::MODEL_NAME);
modelName.setLabelText(Tr::tr("LLM Name:")); modelName.setLabelText(Tr::tr("LLM Name:"));
modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay); modelName.setDisplayStyle(Utils::StringAspect::LineEditDisplay);
@ -157,6 +153,14 @@ QodeAssistSettings::QodeAssistSettings()
startSuggestionTimer.setRange(10, 10000); startSuggestionTimer.setRange(10, 10000);
startSuggestionTimer.setDefaultValue(500); 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.setSettingsKey(Constants::SPECIFIC_INSTRUCTIONS);
specificInstractions.setDisplayStyle(Utils::StringAspect::TextEditDisplay); specificInstractions.setDisplayStyle(Utils::StringAspect::TextEditDisplay);
specificInstractions.setLabelText( specificInstractions.setLabelText(
@ -199,9 +203,9 @@ QodeAssistSettings::QodeAssistSettings()
frequencyPenalty.setEnabled(useFrequencyPenalty()); frequencyPenalty.setEnabled(useFrequencyPenalty());
readStringsAfterCursor.setEnabled(!readFullFile()); readStringsAfterCursor.setEnabled(!readFullFile());
readStringsBeforeCursor.setEnabled(!readFullFile()); readStringsBeforeCursor.setEnabled(!readFullFile());
specificInstractions.setEnabled(useSpecificInstructions());
PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue()); PromptTemplateManager::instance().setCurrentTemplate(fimPrompts.stringValue());
LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue()); LLMProvidersManager::instance().setCurrentProvider(llmProviders.stringValue());
updateProviderSettings();
setLoggingEnabled(enableLogging()); setLoggingEnabled(enableLogging());
@ -215,7 +219,7 @@ QodeAssistSettings::QodeAssistSettings()
enableLogging, enableLogging,
Row{Stretch{1}, resetToDefaults}}}}, Row{Stretch{1}, resetToDefaults}}}},
Group{title(Tr::tr("LLM Providers")), Group{title(Tr::tr("LLM Providers")),
Form{Column{llmProviders, Row{url, port, endPoint}, providerPaths}}}, Form{Column{llmProviders, Row{url, endPoint}, providerPaths}}},
Group{title(Tr::tr("LLM Model Settings")), Group{title(Tr::tr("LLM Model Settings")),
Form{Column{Row{selectModels, modelName}}}}, Form{Column{Row{selectModels, modelName}}}},
Group{title(Tr::tr("FIM Prompt Settings")), Group{title(Tr::tr("FIM Prompt Settings")),
@ -226,6 +230,8 @@ QodeAssistSettings::QodeAssistSettings()
readStringsAfterCursor, readStringsAfterCursor,
ollamaLivetime, ollamaLivetime,
apiKey, apiKey,
useFilePathInContext,
useSpecificInstructions,
specificInstractions, specificInstractions,
temperature, temperature,
maxTokens, maxTokens,
@ -279,6 +285,9 @@ void QodeAssistSettings::setupConnections()
connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() { connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() {
setLoggingEnabled(enableLogging.volatileValue()); setLoggingEnabled(enableLogging.volatileValue());
}); });
connect(&useSpecificInstructions, &Utils::BoolAspect::volatileValueChanged, this, [this]() {
specificInstractions.setEnabled(useSpecificInstructions.volatileValue());
});
} }
void QodeAssistSettings::updateProviderSettings() void QodeAssistSettings::updateProviderSettings()
@ -288,7 +297,6 @@ void QodeAssistSettings::updateProviderSettings()
if (provider) { if (provider) {
logMessage(QString("currentProvider %1").arg(provider->name())); logMessage(QString("currentProvider %1").arg(provider->name()));
url.setValue(provider->url()); url.setValue(provider->url());
port.setValue(provider->defaultPort());
endPoint.setValue(provider->completionEndpoint()); endPoint.setValue(provider->completionEndpoint());
ollamaLivetime.setEnabled(provider->name() == "Ollama"); ollamaLivetime.setEnabled(provider->name() == "Ollama");
} }
@ -347,7 +355,6 @@ void QodeAssistSettings::resetSettingsToDefaults()
resetAspect(enableAutoComplete); resetAspect(enableAutoComplete);
resetAspect(llmProviders); resetAspect(llmProviders);
resetAspect(url); resetAspect(url);
resetAspect(port);
resetAspect(endPoint); resetAspect(endPoint);
resetAspect(modelName); resetAspect(modelName);
resetAspect(fimPrompts); resetAspect(fimPrompts);

View File

@ -63,7 +63,6 @@ public:
Utils::SelectionAspect llmProviders{this}; Utils::SelectionAspect llmProviders{this};
Utils::StringAspect url{this}; Utils::StringAspect url{this};
Utils::IntegerAspect port{this};
Utils::StringAspect endPoint{this}; Utils::StringAspect endPoint{this};
Utils::StringAspect modelName{this}; Utils::StringAspect modelName{this};
@ -96,6 +95,8 @@ public:
Utils::StringAspect ollamaLivetime{this}; Utils::StringAspect ollamaLivetime{this};
Utils::StringAspect specificInstractions{this}; Utils::StringAspect specificInstractions{this};
Utils::BoolAspect useSpecificInstructions{this};
Utils::BoolAspect useFilePathInContext{this};
Utils::BoolAspect multiLineCompletion{this}; Utils::BoolAspect multiLineCompletion{this};
Utils::StringAspect apiKey{this}; Utils::StringAspect apiKey{this};

View File

@ -7,9 +7,10 @@ QodeAssist is an AI-powered coding assistant plugin for Qt Creator. It provides
QodeAssist currently supports the following LLM (Large Language Model) providers: QodeAssist currently supports the following LLM (Large Language Model) providers:
- [Ollama](https://ollama.com) - [Ollama](https://ollama.com)
- [LM Studio](https://lmstudio.ai) - [LM Studio](https://lmstudio.ai)
- OpenAI compatible providers
## Supported Models ## Supported Models
QodeAssist has been tested with the following language models: QodeAssist has been tested with the following language models, all trained for Fill-in-theMiddle:
Ollama: Ollama:
- [starcoder2](https://ollama.com/library/starcoder2) - [starcoder2](https://ollama.com/library/starcoder2)

View File

@ -34,7 +34,6 @@ public:
virtual QString name() const = 0; virtual QString name() const = 0;
virtual QString url() const = 0; virtual QString url() const = 0;
virtual int defaultPort() const = 0;
virtual QString completionEndpoint() const = 0; virtual QString completionEndpoint() const = 0;
virtual void prepareRequest(QJsonObject &request) = 0; virtual void prepareRequest(QJsonObject &request) = 0;

View File

@ -39,12 +39,7 @@ QString LMStudioProvider::name() const
QString LMStudioProvider::url() const QString LMStudioProvider::url() const
{ {
return "http://localhost"; return "http://localhost:1234";
}
int LMStudioProvider::defaultPort() const
{
return 1234;
} }
QString LMStudioProvider::completionEndpoint() const QString LMStudioProvider::completionEndpoint() const

View File

@ -30,7 +30,6 @@ public:
QString name() const override; QString name() const override;
QString url() const override; QString url() const override;
int defaultPort() const override;
QString completionEndpoint() const override; QString completionEndpoint() const override;
void prepareRequest(QJsonObject &request) override; void prepareRequest(QJsonObject &request) override;
bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override;

View File

@ -39,12 +39,7 @@ QString OllamaProvider::name() const
QString OllamaProvider::url() const QString OllamaProvider::url() const
{ {
return "http://localhost"; return "http://localhost:11434";
}
int OllamaProvider::defaultPort() const
{
return 11434;
} }
QString OllamaProvider::completionEndpoint() const QString OllamaProvider::completionEndpoint() const

View File

@ -30,7 +30,6 @@ public:
QString name() const override; QString name() const override;
QString url() const override; QString url() const override;
int defaultPort() const override;
QString completionEndpoint() const override; QString completionEndpoint() const override;
void prepareRequest(QJsonObject &request) override; void prepareRequest(QJsonObject &request) override;
bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override;

View File

@ -17,7 +17,7 @@
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>. * along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "OpenAICompatProvider.h" #include "OpenAICompatProvider.hpp"
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
@ -39,12 +39,7 @@ QString OpenAICompatProvider::name() const
QString OpenAICompatProvider::url() const QString OpenAICompatProvider::url() const
{ {
return "http://localhost"; return "http://localhost:1234";
}
int OpenAICompatProvider::defaultPort() const
{
return 1234;
} }
QString OpenAICompatProvider::completionEndpoint() const QString OpenAICompatProvider::completionEndpoint() const

View File

@ -30,7 +30,6 @@ public:
QString name() const override; QString name() const override;
QString url() const override; QString url() const override;
int defaultPort() const override;
QString completionEndpoint() const override; QString completionEndpoint() const override;
void prepareRequest(QJsonObject &request) override; void prepareRequest(QJsonObject &request) override;
bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override;

View File

@ -43,9 +43,10 @@
#include "QodeAssistClient.hpp" #include "QodeAssistClient.hpp"
#include "providers/LMStudioProvider.hpp" #include "providers/LMStudioProvider.hpp"
#include "providers/OllamaProvider.hpp" #include "providers/OllamaProvider.hpp"
#include "providers/OpenAICompatProvider.h" #include "providers/OpenAICompatProvider.hpp"
#include "templates/CodeLLamaTemplate.hpp" #include "templates/CodeLLamaTemplate.hpp"
#include "templates/CodeQwenChat.hpp" #include "templates/CodeQwenChat.hpp"
#include "templates/DeepSeekCoderV2.hpp"
#include "templates/StarCoder2Template.hpp" #include "templates/StarCoder2Template.hpp"
using namespace Utils; using namespace Utils;
@ -80,6 +81,7 @@ public:
templateManager.registerTemplate<Templates::CodeLLamaTemplate>(); templateManager.registerTemplate<Templates::CodeLLamaTemplate>();
templateManager.registerTemplate<Templates::StarCoder2Template>(); templateManager.registerTemplate<Templates::StarCoder2Template>();
templateManager.registerTemplate<Templates::CodeQwenChatTemplate>(); templateManager.registerTemplate<Templates::CodeQwenChatTemplate>();
templateManager.registerTemplate<Templates::DeepSeekCoderV2Template>();
Utils::Icon QCODEASSIST_ICON( Utils::Icon QCODEASSIST_ICON(
{{":/resources/images/qoderassist-icon.png", Utils::Theme::IconsBaseColor}}); {{":/resources/images/qoderassist-icon.png", Utils::Theme::IconsBaseColor}});

View File

@ -27,17 +27,17 @@ class CodeLLamaTemplate : public PromptTemplate
{ {
public: public:
QString name() const override { return "CodeLlama"; } 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 QStringList stopWords() const override
{ {
return QStringList() << "<EOT>" << "<PRE>" << "<SUF" << "<MID>"; return QStringList() << "<EOT>" << "<PRE>" << "<SUF" << "<MID>";
} }
void prepareRequest(QJsonObject &request, void prepareRequest(QJsonObject &request, const ContextData &context) const override
const QString &prefix,
const QString &suffix) const override
{ {
QString formattedPrompt = promptTemplate().arg(prefix, suffix); QString formattedPrompt = promptTemplate().arg(context.instriuctions,
context.prefix,
context.suffix);
request["prompt"] = formattedPrompt; request["prompt"] = formattedPrompt;
} }
}; };

View File

@ -27,16 +27,16 @@ class CodeQwenChatTemplate : public PromptTemplate
{ {
public: public:
QString name() const override { return "CodeQwenChat (experimental)"; } 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 QStringList stopWords() const override
{ {
return QStringList() << "### Instruction:" << "### Response:" << "\n\n### "; return QStringList() << "### Instruction:" << "### Response:" << "\n\n### ";
} }
void prepareRequest(QJsonObject &request, void prepareRequest(QJsonObject &request, const ContextData &context) const override
const QString &prefix,
const QString &suffix) const override
{ {
QString formattedPrompt = promptTemplate().arg(prefix, suffix); QString formattedPrompt = promptTemplate().arg(context.instriuctions,
context.prefix,
context.suffix);
request["prompt"] = formattedPrompt; request["prompt"] = formattedPrompt;
} }
}; };

View 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

View File

@ -23,6 +23,8 @@
#include <QList> #include <QList>
#include <QString> #include <QString>
#include "QodeAssistData.hpp"
namespace QodeAssist::Templates { namespace QodeAssist::Templates {
class PromptTemplate class PromptTemplate
@ -32,9 +34,6 @@ public:
virtual QString name() const = 0; virtual QString name() const = 0;
virtual QString promptTemplate() const = 0; virtual QString promptTemplate() const = 0;
virtual QStringList stopWords() const = 0; virtual QStringList stopWords() const = 0;
virtual void prepareRequest(QJsonObject &request, virtual void prepareRequest(QJsonObject &request, const ContextData &context) const = 0;
const QString &prefix,
const QString &suffix) const
= 0;
}; };
} // namespace QodeAssist::Templates } // namespace QodeAssist::Templates

View File

@ -27,17 +27,17 @@ class StarCoder2Template : public PromptTemplate
{ {
public: public:
QString name() const override { return "StarCoder2"; } 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 QStringList stopWords() const override
{ {
return QStringList() << "<|endoftext|>" << "<file_sep>" << "<fim_prefix>" << "<fim_suffix>" return QStringList() << "<|endoftext|>" << "<file_sep>" << "<fim_prefix>" << "<fim_suffix>"
<< "<fim_middle>"; << "<fim_middle>";
} }
void prepareRequest(QJsonObject &request, void prepareRequest(QJsonObject &request, const ContextData &context) const override
const QString &prefix,
const QString &suffix) const override
{ {
QString formattedPrompt = promptTemplate().arg(prefix, suffix); QString formattedPrompt = promptTemplate().arg(context.instriuctions,
context.prefix,
context.suffix);
request["prompt"] = formattedPrompt; request["prompt"] = formattedPrompt;
} }
}; };