diff --git a/ConfigurationManager.cpp b/ConfigurationManager.cpp index 603e20b..ec19375 100644 --- a/ConfigurationManager.cpp +++ b/ConfigurationManager.cpp @@ -137,9 +137,14 @@ void ConfigurationManager::selectTemplate() const bool isCodeCompletion = (settingsButton == &m_generalSettings.ccSelectTemplate); const bool isPreset1 = (settingsButton == &m_generalSettings.ccPreset1SelectTemplate); + const QString providerName = isCodeCompletion ? m_generalSettings.ccProvider.volatileValue() + : isPreset1 ? m_generalSettings.ccPreset1Provider.volatileValue() + : m_generalSettings.caProvider.volatileValue(); + auto providerID = m_providersManager.getProviderByName(providerName)->providerID(); - const auto templateList = isCodeCompletion || isPreset1 ? m_templateManger.fimTemplatesNames() - : m_templateManger.chatTemplatesNames(); + const auto templateList = isCodeCompletion || isPreset1 + ? m_templateManger.getFimTemplatesForProvider(providerID) + : m_templateManger.getChatTemplatesForProvider(providerID); auto &targetSettings = isCodeCompletion ? m_generalSettings.ccTemplate : isPreset1 ? m_generalSettings.ccPreset1Template diff --git a/llmcore/CMakeLists.txt b/llmcore/CMakeLists.txt index 4a8e0d9..988b164 100644 --- a/llmcore/CMakeLists.txt +++ b/llmcore/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(LLMCore STATIC OllamaMessage.hpp OllamaMessage.cpp OpenAIMessage.hpp OpenAIMessage.cpp ValidationUtils.hpp ValidationUtils.cpp + ProviderID.hpp ) target_link_libraries(LLMCore diff --git a/llmcore/PromptTemplate.hpp b/llmcore/PromptTemplate.hpp index 95cbe56..e0bdc8a 100644 --- a/llmcore/PromptTemplate.hpp +++ b/llmcore/PromptTemplate.hpp @@ -24,6 +24,7 @@ #include #include "ContextData.hpp" +#include "ProviderID.hpp" namespace QodeAssist::LLMCore { @@ -35,9 +36,9 @@ public: virtual ~PromptTemplate() = default; virtual TemplateType type() const = 0; virtual QString name() const = 0; - // virtual QString promptTemplate() const = 0; virtual QStringList stopWords() const = 0; virtual void prepareRequest(QJsonObject &request, const ContextData &context) const = 0; virtual QString description() const = 0; + virtual bool isSupportProvider(ProviderID id) const = 0; }; } // namespace QodeAssist::LLMCore diff --git a/llmcore/PromptTemplateManager.cpp b/llmcore/PromptTemplateManager.cpp index 644e934..2d40078 100644 --- a/llmcore/PromptTemplateManager.cpp +++ b/llmcore/PromptTemplateManager.cpp @@ -37,6 +37,32 @@ QStringList PromptTemplateManager::chatTemplatesNames() const return m_chatTemplates.keys(); } +QStringList PromptTemplateManager::getFimTemplatesForProvider(ProviderID id) +{ + QStringList templateList; + + for (const auto tmpl : m_fimTemplates) { + if (tmpl->isSupportProvider(id)) { + templateList.append(tmpl->name()); + } + } + + return templateList; +} + +QStringList PromptTemplateManager::getChatTemplatesForProvider(ProviderID id) +{ + QStringList templateList; + + for (const auto tmpl : m_chatTemplates) { + if (tmpl->isSupportProvider(id)) { + templateList.append(tmpl->name()); + } + } + + return templateList; +} + PromptTemplateManager::~PromptTemplateManager() { qDeleteAll(m_fimTemplates); @@ -44,11 +70,15 @@ PromptTemplateManager::~PromptTemplateManager() PromptTemplate *PromptTemplateManager::getFimTemplateByName(const QString &templateName) { + if (!m_fimTemplates.contains(templateName)) + return m_fimTemplates.first(); return m_fimTemplates[templateName]; } PromptTemplate *PromptTemplateManager::getChatTemplateByName(const QString &templateName) { + if (!m_chatTemplates.contains(templateName)) + return m_chatTemplates.first(); return m_chatTemplates[templateName]; } diff --git a/llmcore/PromptTemplateManager.hpp b/llmcore/PromptTemplateManager.hpp index 1cae0b0..912dc05 100644 --- a/llmcore/PromptTemplateManager.hpp +++ b/llmcore/PromptTemplateManager.hpp @@ -51,6 +51,9 @@ public: QStringList fimTemplatesNames() const; QStringList chatTemplatesNames() const; + QStringList getFimTemplatesForProvider(ProviderID id); + QStringList getChatTemplatesForProvider(ProviderID id); + private: PromptTemplateManager() = default; PromptTemplateManager(const PromptTemplateManager &) = delete; diff --git a/llmcore/Provider.hpp b/llmcore/Provider.hpp index a33d76e..5c820a9 100644 --- a/llmcore/Provider.hpp +++ b/llmcore/Provider.hpp @@ -54,6 +54,7 @@ public: virtual QList validateRequest(const QJsonObject &request, TemplateType type) = 0; virtual QString apiKey() const = 0; virtual void prepareNetworkRequest(QNetworkRequest &networkRequest) const = 0; + virtual ProviderID providerID() const = 0; }; } // namespace QodeAssist::LLMCore diff --git a/llmcore/ProviderID.hpp b/llmcore/ProviderID.hpp new file mode 100644 index 0000000..871fb26 --- /dev/null +++ b/llmcore/ProviderID.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 . + */ + +namespace QodeAssist::LLMCore { + +enum class ProviderID { + Any, + Ollama, + LMStudio, + Claude, + OpenAI, + OpenAICompatible, + MistralAI, + OpenRouter +}; + +} diff --git a/llmcore/ProvidersManager.cpp b/llmcore/ProvidersManager.cpp index 19a1d43..9fc248a 100644 --- a/llmcore/ProvidersManager.cpp +++ b/llmcore/ProvidersManager.cpp @@ -39,6 +39,8 @@ ProvidersManager::~ProvidersManager() Provider *ProvidersManager::getProviderByName(const QString &providerName) { + if (!m_providers.contains(providerName)) + return m_providers.first(); return m_providers[providerName]; } diff --git a/providers/ClaudeProvider.cpp b/providers/ClaudeProvider.cpp index e41e67e..75f5795 100644 --- a/providers/ClaudeProvider.cpp +++ b/providers/ClaudeProvider.cpp @@ -65,9 +65,9 @@ void ClaudeProvider::prepareRequest( LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); @@ -213,4 +213,9 @@ void ClaudeProvider::prepareNetworkRequest(QNetworkRequest &networkRequest) cons } } +LLMCore::ProviderID ClaudeProvider::providerID() const +{ + return LLMCore::ProviderID::Claude; +} + } // namespace QodeAssist::Providers diff --git a/providers/ClaudeProvider.hpp b/providers/ClaudeProvider.hpp index 55c68b1..014cf16 100644 --- a/providers/ClaudeProvider.hpp +++ b/providers/ClaudeProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index af6ab9e..7aba6cd 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -168,15 +168,20 @@ void LMStudioProvider::prepareNetworkRequest(QNetworkRequest &networkRequest) co networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); } +LLMCore::ProviderID LMStudioProvider::providerID() const +{ + return LLMCore::ProviderID::LMStudio; +} + void QodeAssist::Providers::LMStudioProvider::prepareRequest( QJsonObject &request, LLMCore::PromptTemplate *prompt, LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); diff --git a/providers/LMStudioProvider.hpp b/providers/LMStudioProvider.hpp index 1014a00..a55cf3a 100644 --- a/providers/LMStudioProvider.hpp +++ b/providers/LMStudioProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/MistralAIProvider.cpp b/providers/MistralAIProvider.cpp index 201e757..fa5852a 100644 --- a/providers/MistralAIProvider.cpp +++ b/providers/MistralAIProvider.cpp @@ -171,15 +171,20 @@ void MistralAIProvider::prepareNetworkRequest(QNetworkRequest &networkRequest) c } } +LLMCore::ProviderID MistralAIProvider::providerID() const +{ + return LLMCore::ProviderID::MistralAI; +} + void MistralAIProvider::prepareRequest( QJsonObject &request, LLMCore::PromptTemplate *prompt, LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); diff --git a/providers/MistralAIProvider.hpp b/providers/MistralAIProvider.hpp index 5ce3344..f7db450 100644 --- a/providers/MistralAIProvider.hpp +++ b/providers/MistralAIProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index d0cbf7a..8261294 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -64,9 +64,9 @@ void OllamaProvider::prepareRequest( LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); @@ -213,4 +213,9 @@ void OllamaProvider::prepareNetworkRequest(QNetworkRequest &networkRequest) cons networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); } +LLMCore::ProviderID OllamaProvider::providerID() const +{ + return LLMCore::ProviderID::Ollama; +} + } // namespace QodeAssist::Providers diff --git a/providers/OllamaProvider.hpp b/providers/OllamaProvider.hpp index 38cea88..2cdef5f 100644 --- a/providers/OllamaProvider.hpp +++ b/providers/OllamaProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index 547cec7..b5c6a55 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -65,9 +65,9 @@ void OpenAICompatProvider::prepareRequest( LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); @@ -180,4 +180,9 @@ void OpenAICompatProvider::prepareNetworkRequest(QNetworkRequest &networkRequest } } +LLMCore::ProviderID OpenAICompatProvider::providerID() const +{ + return LLMCore::ProviderID::OpenAICompatible; +} + } // namespace QodeAssist::Providers diff --git a/providers/OpenAICompatProvider.hpp b/providers/OpenAICompatProvider.hpp index cfcf890..42ce3ce 100644 --- a/providers/OpenAICompatProvider.hpp +++ b/providers/OpenAICompatProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAIProvider.cpp b/providers/OpenAIProvider.cpp index 81bd7ed..2104ea4 100644 --- a/providers/OpenAIProvider.cpp +++ b/providers/OpenAIProvider.cpp @@ -66,9 +66,9 @@ void OpenAIProvider::prepareRequest( LLMCore::ContextData context, LLMCore::RequestType type) { - // if (!isSupportedTemplate(prompt->name())) { - // LOG_MESSAGE(QString("Provider doesn't support %1 template").arg(prompt->name())); - // } + if (!prompt->isSupportProvider(providerID())) { + LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name())); + } prompt->prepareRequest(request, context); @@ -216,4 +216,9 @@ void OpenAIProvider::prepareNetworkRequest(QNetworkRequest &networkRequest) cons } } +LLMCore::ProviderID OpenAIProvider::providerID() const +{ + return LLMCore::ProviderID::OpenAI; +} + } // namespace QodeAssist::Providers diff --git a/providers/OpenAIProvider.hpp b/providers/OpenAIProvider.hpp index 5706a83..a5c39e8 100644 --- a/providers/OpenAIProvider.hpp +++ b/providers/OpenAIProvider.hpp @@ -41,6 +41,7 @@ public: QList validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override; QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenRouterAIProvider.cpp b/providers/OpenRouterAIProvider.cpp index a6381fd..c3fd3ba 100644 --- a/providers/OpenRouterAIProvider.cpp +++ b/providers/OpenRouterAIProvider.cpp @@ -19,8 +19,6 @@ #include "OpenRouterAIProvider.hpp" -#include "settings/ChatAssistantSettings.hpp" -#include "settings/CodeCompletionSettings.hpp" #include "settings/ProviderSettings.hpp" #include @@ -99,4 +97,9 @@ QString OpenRouterProvider::apiKey() const return Settings::providerSettings().openRouterApiKey(); } +LLMCore::ProviderID OpenRouterProvider::providerID() const +{ + return LLMCore::ProviderID::OpenRouter; +} + } // namespace QodeAssist::Providers diff --git a/providers/OpenRouterAIProvider.hpp b/providers/OpenRouterAIProvider.hpp index f7a2c08..eb8dfe5 100644 --- a/providers/OpenRouterAIProvider.hpp +++ b/providers/OpenRouterAIProvider.hpp @@ -31,6 +31,7 @@ public: QString url() const override; bool handleResponse(QNetworkReply *reply, QString &accumulatedResponse) override; QString apiKey() const override; + LLMCore::ProviderID providerID() const override; }; } // namespace QodeAssist::Providers diff --git a/templates/Alpaca.hpp b/templates/Alpaca.hpp index 472c3d8..7ea9749 100644 --- a/templates/Alpaca.hpp +++ b/templates/Alpaca.hpp @@ -61,6 +61,19 @@ public: { return "The message will contain the following tokens: ### Instruction:\n### Response:\n"; } + + bool isSupportProvider(LLMCore::ProviderID id) const override + { + switch (id) { + case QodeAssist::LLMCore::ProviderID::Ollama: + case QodeAssist::LLMCore::ProviderID::LMStudio: + case QodeAssist::LLMCore::ProviderID::OpenRouter: + case QodeAssist::LLMCore::ProviderID::OpenAICompatible: + return true; + default: + return false; + } + } }; } // namespace QodeAssist::Templates diff --git a/templates/ChatML.hpp b/templates/ChatML.hpp index 4a1bd02..7818606 100644 --- a/templates/ChatML.hpp +++ b/templates/ChatML.hpp @@ -60,6 +60,18 @@ public: { return "The message will contain the following tokens: <|im_start|>%1\n%2\n<|im_end|>"; } + bool isSupportProvider(LLMCore::ProviderID id) const override + { + switch (id) { + case QodeAssist::LLMCore::ProviderID::Ollama: + case QodeAssist::LLMCore::ProviderID::LMStudio: + case QodeAssist::LLMCore::ProviderID::OpenRouter: + case QodeAssist::LLMCore::ProviderID::OpenAICompatible: + return true; + default: + return false; + } + } }; } // namespace QodeAssist::Templates diff --git a/templates/Claude.hpp b/templates/Claude.hpp index 6043aa5..9ef77ca 100644 --- a/templates/Claude.hpp +++ b/templates/Claude.hpp @@ -50,6 +50,15 @@ public: request["messages"] = messages; } QString description() const override { return "Claude"; } + bool isSupportProvider(LLMCore::ProviderID id) const override + { + switch (id) { + case QodeAssist::LLMCore::ProviderID::Claude: + return true; + default: + return false; + } + } }; } // namespace QodeAssist::Templates diff --git a/templates/CodeLlamaFim.hpp b/templates/CodeLlamaFim.hpp index 63817b7..d957ae4 100644 --- a/templates/CodeLlamaFim.hpp +++ b/templates/CodeLlamaFim.hpp @@ -42,6 +42,15 @@ public: { return "The message will contain the following tokens:
 %1 %2 ";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/CodeLlamaQMLFim.hpp b/templates/CodeLlamaQMLFim.hpp
index df827be..d746493 100644
--- a/templates/CodeLlamaQMLFim.hpp
+++ b/templates/CodeLlamaQMLFim.hpp
@@ -43,6 +43,15 @@ public:
     {
         return "The message will contain the following tokens: %1
%2";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/Llama2.hpp b/templates/Llama2.hpp
index ffcdf3c..65c02dc 100644
--- a/templates/Llama2.hpp
+++ b/templates/Llama2.hpp
@@ -59,6 +59,18 @@ public:
     {
         return "The message will contain the following tokens: [INST]%1[/INST]\n";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+        case QodeAssist::LLMCore::ProviderID::LMStudio:
+        case QodeAssist::LLMCore::ProviderID::OpenRouter:
+        case QodeAssist::LLMCore::ProviderID::OpenAICompatible:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/Llama3.hpp b/templates/Llama3.hpp
index 26c5f68..37f4d3d 100644
--- a/templates/Llama3.hpp
+++ b/templates/Llama3.hpp
@@ -63,6 +63,18 @@ public:
         return "The message will contain the following tokens: "
                "<|start_header_id|>%1<|end_header_id|>%2<|eot_id|>";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+        case QodeAssist::LLMCore::ProviderID::LMStudio:
+        case QodeAssist::LLMCore::ProviderID::OpenRouter:
+        case QodeAssist::LLMCore::ProviderID::OpenAICompatible:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/MistralAI.hpp b/templates/MistralAI.hpp
index ddada9b..8db4631 100644
--- a/templates/MistralAI.hpp
+++ b/templates/MistralAI.hpp
@@ -37,6 +37,15 @@ public:
         request["suffix"] = context.suffix.value_or("");
     }
     QString description() const override { return "template will take from ollama modelfile"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::MistralAI:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 class MistralAIChat : public LLMCore::PromptTemplate
@@ -64,6 +73,15 @@ public:
         request["messages"] = messages;
     }
     QString description() const override { return "template will take from ollama modelfile"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::MistralAI:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/Ollama.hpp b/templates/Ollama.hpp
index 9f19e1f..d688eb3 100644
--- a/templates/Ollama.hpp
+++ b/templates/Ollama.hpp
@@ -38,6 +38,15 @@ public:
         request["system"] = context.systemPrompt.value_or("");
     }
     QString description() const override { return "template will take from ollama modelfile"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 class OllamaChat : public LLMCore::PromptTemplate
@@ -65,6 +74,15 @@ public:
         request["messages"] = messages;
     }
     QString description() const override { return "template will take from ollama modelfile"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/OpenAI.hpp b/templates/OpenAI.hpp
index 491f6e0..5267062 100644
--- a/templates/OpenAI.hpp
+++ b/templates/OpenAI.hpp
@@ -49,6 +49,15 @@ public:
         request["messages"] = messages;
     }
     QString description() const override { return "OpenAI"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::OpenAI:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/OpenAICompatible.hpp b/templates/OpenAICompatible.hpp
index d086faa..c549187 100644
--- a/templates/OpenAICompatible.hpp
+++ b/templates/OpenAICompatible.hpp
@@ -49,6 +49,17 @@ public:
         request["messages"] = messages;
     }
     QString description() const override { return "chat without tokens"; }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::OpenAICompatible:
+        case QodeAssist::LLMCore::ProviderID::OpenRouter:
+        case QodeAssist::LLMCore::ProviderID::LMStudio:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/Qwen.hpp b/templates/Qwen.hpp
index caeae74..4efd015 100644
--- a/templates/Qwen.hpp
+++ b/templates/Qwen.hpp
@@ -41,6 +41,15 @@ public:
         return "The message will contain the following tokens: "
                "<|fim_prefix|>%1<|fim_suffix|>%2<|fim_middle|>";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/StarCoder2Fim.hpp b/templates/StarCoder2Fim.hpp
index c3f535a..f00db39 100644
--- a/templates/StarCoder2Fim.hpp
+++ b/templates/StarCoder2Fim.hpp
@@ -44,6 +44,15 @@ public:
         return "The message will contain the following tokens: "
                "%1%2";
     }
+    bool isSupportProvider(LLMCore::ProviderID id) const override
+    {
+        switch (id) {
+        case QodeAssist::LLMCore::ProviderID::Ollama:
+            return true;
+        default:
+            return false;
+        }
+    }
 };
 
 } // namespace QodeAssist::Templates
diff --git a/templates/Templates.hpp b/templates/Templates.hpp
index 38c7255..d9e9f95 100644
--- a/templates/Templates.hpp
+++ b/templates/Templates.hpp
@@ -41,9 +41,9 @@ namespace QodeAssist::Templates {
 inline void registerTemplates()
 {
     auto &templateManager = LLMCore::PromptTemplateManager::instance();
-    templateManager.registerTemplate();
-    templateManager.registerTemplate();
     templateManager.registerTemplate();
+    templateManager.registerTemplate();
+    templateManager.registerTemplate();
     templateManager.registerTemplate();
     templateManager.registerTemplate();
     templateManager.registerTemplate();