From a974b0aa82e5340ee04fea192c137569b0a42717 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Sun, 1 Sep 2024 18:19:37 +0200 Subject: [PATCH] Move to get models by request to provider --- QodeAssist.json.in | 2 +- QodeAssistSettings.cpp | 19 ++-------- QodeAssistSettings.hpp | 2 - README.md | 8 ++-- providers/LMStudioProvider.cpp | 60 ++++++++++-------------------- providers/OllamaProvider.cpp | 58 ++++++++++------------------- providers/OpenAICompatProvider.cpp | 1 - 7 files changed, 48 insertions(+), 102 deletions(-) diff --git a/QodeAssist.json.in b/QodeAssist.json.in index 264266e..9b060ef 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.0.7", + "Version" : "0.0.8", "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/QodeAssistSettings.cpp b/QodeAssistSettings.cpp index b280afe..4997af6 100644 --- a/QodeAssistSettings.cpp +++ b/QodeAssistSettings.cpp @@ -77,7 +77,7 @@ QodeAssistSettings::QodeAssistSettings() temperature.setDefaultValue(0.2); temperature.setRange(0.0, 10.0); - selectModels.m_buttonText = Tr::tr("Select Models"); + selectModels.m_buttonText = Tr::tr("Select Model"); ollamaLivetime.setSettingsKey(Constants::OLLAMA_LIVETIME); ollamaLivetime.setLabelText( @@ -145,9 +145,6 @@ QodeAssistSettings::QodeAssistSettings() frequencyPenalty.setDefaultValue(0.0); frequencyPenalty.setRange(-2.0, 2.0); - providerPaths.setSettingsKey(Constants::PROVIDER_PATHS); - providerPaths.setLabelText(Tr::tr("Provider Paths:")); - startSuggestionTimer.setSettingsKey(Constants::START_SUGGESTION_TIMER); startSuggestionTimer.setLabelText(Tr::tr("Start Suggestion Timer:")); startSuggestionTimer.setRange(10, 10000); @@ -219,7 +216,7 @@ QodeAssistSettings::QodeAssistSettings() enableLogging, Row{Stretch{1}, resetToDefaults}}}}, Group{title(Tr::tr("LLM Providers")), - Form{Column{llmProviders, Row{url, endPoint}, providerPaths}}}, + Form{Column{llmProviders, Row{url, endPoint}}}}, Group{title(Tr::tr("LLM Model Settings")), Form{Column{Row{selectModels, modelName}}}}, Group{title(Tr::tr("FIM Prompt Settings")), @@ -306,7 +303,7 @@ QStringList QodeAssistSettings::getInstalledModels() { auto *provider = LLMProvidersManager::instance().getCurrentProvider(); if (provider) { - auto env = getEnvironmentWithProviderPaths(); + Utils::Environment env = Utils::Environment::systemEnvironment(); return provider->getInstalledModels(env); } return {}; @@ -331,16 +328,6 @@ void QodeAssistSettings::showModelSelectionDialog() } } -Utils::Environment QodeAssistSettings::getEnvironmentWithProviderPaths() const -{ - Utils::Environment env = Utils::Environment::systemEnvironment(); - const QStringList additionalPaths = providerPaths.volatileValue(); - for (const QString &path : additionalPaths) { - env.prependOrSetPath(path); - } - return env; -} - void QodeAssistSettings::resetSettingsToDefaults() { QMessageBox::StandardButton reply; diff --git a/QodeAssistSettings.hpp b/QodeAssistSettings.hpp index f974874..641f9d2 100644 --- a/QodeAssistSettings.hpp +++ b/QodeAssistSettings.hpp @@ -88,8 +88,6 @@ public: Utils::BoolAspect useFrequencyPenalty{this}; Utils::DoubleAspect frequencyPenalty{this}; - Utils::StringListAspect providerPaths{this}; - Utils::IntegerAspect startSuggestionTimer{this}; Utils::IntegerAspect maxFileThreshold{this}; diff --git a/README.md b/README.md index 32f1559..a463a31 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ QodeAssist has been tested with the following language models, all trained for F Ollama: - [starcoder2](https://ollama.com/library/starcoder2) - [codellama](https://ollama.com/library/codellama) +- DeepSeek-Coder-V2-Lite-Base LM studio: - [second-state/StarCoder2-7B-GGUF](https://huggingface.co/second-state/StarCoder2-7B-GGUF) @@ -30,7 +31,7 @@ If you've successfully used a model that's not listed here, please let us know b - [ ] Add chat functionality - [ ] Support for more providers and models -## Installation Plugin +## Plugin installation using Ollama as an example 1. Install QtCreator 14.0 2. Install [Ollama](https://ollama.com). Make sure to review the system requirements before installation. @@ -50,9 +51,8 @@ ollama run starcoder2:7b 1. Open Qt Creator settings 2. Navigate to the "Qode Assist" tab 3. Choose your LLM provider (e.g., Ollama) - - If you haven't added the provider to your system PATH, specify the path to the provider executable in the "Provider Paths" field -4. Select the installed model - - If you need to enter the model name manually, it indicates that the plugin cannot locate the provider's executable file. However, this doesn't affect the plugin's functionality – it will still work correctly. This autoselector input option is provided for your convenience, allowing you to easily select and use different models +4. Select the installed model by the "Select Model" button + - For LM Studio you will see current load model 5. Choose the prompt template that corresponds to your model 6. Apply the settings diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index 946787d..4aa5df3 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -19,14 +19,15 @@ #include "LMStudioProvider.hpp" +#include #include #include #include #include -#include #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" +#include "QodeAssistUtils.hpp" namespace QodeAssist::Providers { @@ -113,53 +114,32 @@ bool LMStudioProvider::handleResponse(QNetworkReply *reply, QString &accumulated QList LMStudioProvider::getInstalledModels(const Utils::Environment &env) { - QProcess process; - process.setEnvironment(env.toStringList()); - QString lmsConsoleName; -#ifdef Q_OS_WIN - lmsConsoleName = "lms.exe"; -#else - lmsConsoleName = "lms"; -#endif - auto lmsPath = env.searchInPath(lmsConsoleName).toString(); + QList models; + QNetworkAccessManager manager; + QNetworkRequest request(QUrl(url() + "/v1/models")); - if (!QFileInfo::exists(lmsPath)) { - qWarning() << "LMS executable not found at" << lmsPath; - return {}; - } + QNetworkReply *reply = manager.get(request); - process.start(lmsPath, QStringList() << "ls"); - if (!process.waitForStarted()) { - qWarning() << "Failed to start LMS process:" << process.errorString(); - return {}; - } + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); - if (!process.waitForFinished()) { - qWarning() << "LMS process did not finish:" << process.errorString(); - return {}; - } + if (reply->error() == QNetworkReply::NoError) { + QByteArray responseData = reply->readAll(); + QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData); + QJsonObject jsonObject = jsonResponse.object(); + QJsonArray modelArray = jsonObject["data"].toArray(); - QStringList models; - if (process.exitCode() == 0) { - QString output = QString::fromUtf8(process.readAllStandardOutput()); - QStringList lines = output.split('\n', Qt::SkipEmptyParts); - - // Skip the header lines - for (int i = 2; i < lines.size(); ++i) { - QString line = lines[i].trimmed(); - if (!line.isEmpty()) { - // The model name is the first column - QString modelName = line.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts) - .first(); - models.append(modelName); - } + for (const QJsonValue &value : modelArray) { + QJsonObject modelObject = value.toObject(); + QString modelId = modelObject["id"].toString(); + models.append(modelId); } - qDebug() << "Models:" << models; } else { - // Handle error - qWarning() << "Error running 'lms list':" << process.errorString(); + logMessage(QString("Error fetching models: %1").arg(reply->errorString())); } + reply->deleteLater(); return models; } diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index 4da417e..41aaaa7 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -23,10 +23,11 @@ #include #include #include -#include +#include #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp" +#include "QodeAssistUtils.hpp" namespace QodeAssist::Providers { @@ -96,50 +97,31 @@ bool OllamaProvider::handleResponse(QNetworkReply *reply, QString &accumulatedRe QList OllamaProvider::getInstalledModels(const Utils::Environment &env) { - QProcess process; - process.setEnvironment(env.toStringList()); - QString ollamaConsoleName; -#ifdef Q_OS_WIN - ollamaConsoleName = "ollama.exe"; -#else - ollamaConsoleName = "ollama"; -#endif + QList models; + QNetworkAccessManager manager; + QNetworkRequest request(QUrl(url() + "/api/tags")); + QNetworkReply *reply = manager.get(request); - auto ollamaPath = env.searchInPath(ollamaConsoleName).toString(); + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); - if (!QFileInfo::exists(ollamaPath)) { - qWarning() << "Ollama executable not found at" << ollamaPath; - return {}; - } + if (reply->error() == QNetworkReply::NoError) { + QByteArray responseData = reply->readAll(); + QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData); + QJsonObject jsonObject = jsonResponse.object(); + QJsonArray modelArray = jsonObject["models"].toArray(); - process.start(ollamaPath, QStringList() << "list"); - if (!process.waitForStarted()) { - qWarning() << "Failed to start Ollama process:" << process.errorString(); - return {}; - } - - if (!process.waitForFinished()) { - qWarning() << "Ollama process did not finish:" << process.errorString(); - return {}; - } - - QStringList models; - if (process.exitCode() == 0) { - QString output = QString::fromUtf8(process.readAllStandardOutput()); - QStringList lines = output.split('\n', Qt::SkipEmptyParts); - - for (int i = 1; i < lines.size(); ++i) { - QString line = lines[i].trimmed(); - if (!line.isEmpty()) { - QString modelName = line.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts) - .first(); - models.append(modelName); - } + for (const QJsonValue &value : modelArray) { + QJsonObject modelObject = value.toObject(); + QString modelName = modelObject["name"].toString(); + models.append(modelName); } } else { - qWarning() << "Error running 'ollama list':" << process.errorString(); + logMessage(QString("Error fetching models: %1").arg(reply->errorString())); } + reply->deleteLater(); return models; } diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index 51fdc54..64d0b3a 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include "PromptTemplateManager.hpp" #include "QodeAssistSettings.hpp"