diff --git a/providers/QwenProvider.cpp b/providers/QwenProvider.cpp index ff48b45..f8dfd1d 100644 --- a/providers/QwenProvider.cpp +++ b/providers/QwenProvider.cpp @@ -3,13 +3,27 @@ #include "QwenProvider.hpp" +#include +#include "logger/Logger.hpp" +#include "settings/ChatAssistantSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" +#include "settings/GeneralSettings.hpp" #include "settings/ProviderSettings.hpp" +#include "settings/QuickRefactorSettings.hpp" +#include "tools/ToolsRegistration.hpp" + +#include +#include +#include namespace QodeAssist::Providers { QwenProvider::QwenProvider(QObject *parent) - : OpenAICompatProvider(parent) -{} + : PluginLLMCore::Provider(parent) + , m_client(new ::LLMQore::OpenAIClient(QString(), QString(), QString(), this)) +{ + Tools::registerQodeAssistTools(m_client->tools()); +} QString QwenProvider::name() const { @@ -26,9 +40,73 @@ QString QwenProvider::url() const return "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"; } +QFuture> QwenProvider::getInstalledModels(const QString &url) +{ + m_client->setUrl(url); + m_client->setApiKey(apiKey()); + return m_client->listModels(); +} + PluginLLMCore::ProviderID QwenProvider::providerID() const { return PluginLLMCore::ProviderID::Qwen; } +PluginLLMCore::ProviderCapabilities QwenProvider::capabilities() const +{ + return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image + | PluginLLMCore::ProviderCapability::Thinking + | PluginLLMCore::ProviderCapability::ModelListing; +} + +void QwenProvider::prepareRequest( + QJsonObject &request, + PluginLLMCore::PromptTemplate *prompt, + PluginLLMCore::ContextData context, + PluginLLMCore::RequestType type, + bool isToolsEnabled, + bool isThinkingEnabled) +{ + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } + + prompt->prepareRequest(request, context); + + auto applyModelParams = [&request](const auto &settings) { + request["max_tokens"] = settings.maxTokens(); + request["temperature"] = settings.temperature(); + + if (settings.useTopP()) + request["top_p"] = settings.topP(); + if (settings.useTopK()) + request["top_k"] = settings.topK(); + if (settings.useFrequencyPenalty()) + request["frequency_penalty"] = settings.frequencyPenalty(); + if (settings.usePresencePenalty()) + request["presence_penalty"] = settings.presencePenalty(); + }; + + if (type == PluginLLMCore::RequestType::CodeCompletion) { + applyModelParams(Settings::codeCompletionSettings()); + } else if (type == PluginLLMCore::RequestType::QuickRefactoring) { + applyModelParams(Settings::quickRefactorSettings()); + } else { + applyModelParams(Settings::chatAssistantSettings()); + } + + if (isToolsEnabled) { + auto toolsDefinitions = m_client->tools()->getToolsDefinitions(); + if (!toolsDefinitions.isEmpty()) { + request["tools"] = toolsDefinitions; + LOG_MESSAGE(QString("Added %1 tools to Qwen request").arg(toolsDefinitions.size())); + } + } +} + +::LLMQore::BaseClient *QwenProvider::client() const +{ + return m_client; +} + } // namespace QodeAssist::Providers diff --git a/providers/QwenProvider.hpp b/providers/QwenProvider.hpp index 8cacedb..e9b289e 100644 --- a/providers/QwenProvider.hpp +++ b/providers/QwenProvider.hpp @@ -3,19 +3,35 @@ #pragma once -#include "providers/OpenAICompatProvider.hpp" +#include +#include namespace QodeAssist::Providers { -class QwenProvider : public OpenAICompatProvider +class QwenProvider : public PluginLLMCore::Provider { + Q_OBJECT public: explicit QwenProvider(QObject *parent = nullptr); QString name() const override; QString url() const override; - QString apiKey() const override; + void prepareRequest( + QJsonObject &request, + PluginLLMCore::PromptTemplate *prompt, + PluginLLMCore::ContextData context, + PluginLLMCore::RequestType type, + bool isToolsEnabled, + bool isThinkingEnabled) override; + QFuture> getInstalledModels(const QString &url) override; PluginLLMCore::ProviderID providerID() const override; + PluginLLMCore::ProviderCapabilities capabilities() const override; + + ::LLMQore::BaseClient *client() const override; + QString apiKey() const override; + +private: + ::LLMQore::OpenAIClient *m_client; }; } // namespace QodeAssist::Providers diff --git a/providers/QwenResponsesProvider.cpp b/providers/QwenResponsesProvider.cpp index 8bcc9b5..6577f82 100644 --- a/providers/QwenResponsesProvider.cpp +++ b/providers/QwenResponsesProvider.cpp @@ -3,13 +3,27 @@ #include "QwenResponsesProvider.hpp" +#include +#include "logger/Logger.hpp" +#include "settings/ChatAssistantSettings.hpp" +#include "settings/CodeCompletionSettings.hpp" +#include "settings/GeneralSettings.hpp" #include "settings/ProviderSettings.hpp" +#include "settings/QuickRefactorSettings.hpp" +#include "tools/ToolsRegistration.hpp" + +#include +#include +#include namespace QodeAssist::Providers { QwenResponsesProvider::QwenResponsesProvider(QObject *parent) - : OpenAIResponsesProvider(parent) -{} + : PluginLLMCore::Provider(parent) + , m_client(new ::LLMQore::OpenAIResponsesClient(QString(), QString(), QString(), this)) +{ + Tools::registerQodeAssistTools(m_client->tools()); +} QString QwenResponsesProvider::name() const { @@ -26,15 +40,96 @@ QString QwenResponsesProvider::url() const return "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"; } -QFuture> QwenResponsesProvider::getInstalledModels(const QString &) +void QwenResponsesProvider::prepareRequest( + QJsonObject &request, + PluginLLMCore::PromptTemplate *prompt, + PluginLLMCore::ContextData context, + PluginLLMCore::RequestType type, + bool isToolsEnabled, + bool isThinkingEnabled) { - return QtFuture::makeReadyFuture(QList{}); + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } + + prompt->prepareRequest(request, context); + + auto applyModelParams = [&request](const auto &settings) { + request["max_output_tokens"] = settings.maxTokens(); + + if (settings.useTopP()) { + request["top_p"] = settings.topP(); + } + }; + + auto applyThinkingMode = [&request](const auto &settings) { + QString effortStr = settings.openAIResponsesReasoningEffort.stringValue().toLower(); + if (effortStr.isEmpty()) { + effortStr = "medium"; + } + + QJsonObject reasoning; + reasoning["effort"] = effortStr; + request["reasoning"] = reasoning; + request["max_output_tokens"] = settings.thinkingMaxTokens(); + request["store"] = true; + + QJsonArray include; + include.append("reasoning.encrypted_content"); + request["include"] = include; + }; + + if (type == PluginLLMCore::RequestType::CodeCompletion) { + applyModelParams(Settings::codeCompletionSettings()); + } else if (type == PluginLLMCore::RequestType::QuickRefactoring) { + const auto &qrSettings = Settings::quickRefactorSettings(); + applyModelParams(qrSettings); + + if (isThinkingEnabled) { + applyThinkingMode(qrSettings); + } + } else { + const auto &chatSettings = Settings::chatAssistantSettings(); + applyModelParams(chatSettings); + + if (isThinkingEnabled) { + applyThinkingMode(chatSettings); + } + } + + if (isToolsEnabled) { + const auto toolsDefinitions = m_client->tools()->getToolsDefinitions(); + if (!toolsDefinitions.isEmpty()) { + request["tools"] = toolsDefinitions; + LOG_MESSAGE( + QString("Added %1 tools to Qwen Responses request").arg(toolsDefinitions.size())); + } + } + + request["stream"] = true; +} + +QFuture> QwenResponsesProvider::getInstalledModels(const QString &url) +{ + m_client->setUrl(url); + m_client->setApiKey(apiKey()); + return m_client->listModels(); +} + +PluginLLMCore::ProviderID QwenResponsesProvider::providerID() const +{ + return PluginLLMCore::ProviderID::OpenAIResponses; } PluginLLMCore::ProviderCapabilities QwenResponsesProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking - | PluginLLMCore::ProviderCapability::Image; + | PluginLLMCore::ProviderCapability::Image | PluginLLMCore::ProviderCapability::ModelListing; +} + +::LLMQore::BaseClient *QwenResponsesProvider::client() const +{ + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/QwenResponsesProvider.hpp b/providers/QwenResponsesProvider.hpp index a685670..95958b9 100644 --- a/providers/QwenResponsesProvider.hpp +++ b/providers/QwenResponsesProvider.hpp @@ -3,11 +3,12 @@ #pragma once -#include "providers/OpenAIResponsesProvider.hpp" +#include +#include namespace QodeAssist::Providers { -class QwenResponsesProvider : public OpenAIResponsesProvider +class QwenResponsesProvider : public PluginLLMCore::Provider { Q_OBJECT public: @@ -15,9 +16,22 @@ public: QString name() const override; QString url() const override; - QString apiKey() const override; + void prepareRequest( + QJsonObject &request, + PluginLLMCore::PromptTemplate *prompt, + PluginLLMCore::ContextData context, + PluginLLMCore::RequestType type, + bool isToolsEnabled, + bool isThinkingEnabled) override; QFuture> getInstalledModels(const QString &url) override; + PluginLLMCore::ProviderID providerID() const override; PluginLLMCore::ProviderCapabilities capabilities() const override; + + ::LLMQore::BaseClient *client() const override; + QString apiKey() const override; + +private: + ::LLMQore::OpenAIResponsesClient *m_client; }; } // namespace QodeAssist::Providers