From 6ace39e6f290bcd26faa94ed9fa5376baa6a5435 Mon Sep 17 00:00:00 2001 From: dodoleon Date: Thu, 29 May 2025 17:05:01 +0800 Subject: [PATCH] Update support OpenAI-Compatible --- Source/Private/Core/N2CSettings.cpp | 16 ++++++++++ Source/Private/Core/N2CUserSecrets.cpp | 6 ++-- Source/Private/LLM/N2CLLMModule.cpp | 4 ++- .../Providers/N2COpenAICompatibleService.cpp | 9 ++++++ Source/Public/Core/N2CSettings.h | 12 ++++++++ Source/Public/Core/N2CUserSecrets.h | 4 +++ Source/Public/LLM/N2CLLMTypes.h | 3 +- .../Providers/N2COpenAICompatibleService.h | 29 +++++++++++++++++++ 8 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 Source/Private/LLM/Providers/N2COpenAICompatibleService.cpp create mode 100644 Source/Public/LLM/Providers/N2COpenAICompatibleService.h diff --git a/Source/Private/Core/N2CSettings.cpp b/Source/Private/Core/N2CSettings.cpp index 533026e..cccd5d3 100644 --- a/Source/Private/Core/N2CSettings.cpp +++ b/Source/Private/Core/N2CSettings.cpp @@ -44,6 +44,7 @@ UN2CSettings::UN2CSettings() Anthropic_API_Key_UI = UserSecrets->Anthropic_API_Key; Gemini_API_Key_UI = UserSecrets->Gemini_API_Key; DeepSeek_API_Key_UI = UserSecrets->DeepSeek_API_Key; + OpenAICompatible_API_Key_UI = UserSecrets->OpenAICompatible_API_Key; // Initialize token estimate EstimatedReferenceTokens = GetReferenceFilesTokenEstimate(); @@ -80,6 +81,8 @@ FString UN2CSettings::GetActiveApiKey() const return UserSecrets->Gemini_API_Key; case EN2CLLMProvider::DeepSeek: return UserSecrets->DeepSeek_API_Key; + case EN2CLLMProvider::OpenAICompatible: + return UserSecrets->OpenAICompatible_API_Key; default: return FString(); } @@ -99,6 +102,8 @@ FString UN2CSettings::GetActiveModel() const return FN2CLLMModelUtils::GetDeepSeekModelValue(DeepSeekModel); case EN2CLLMProvider::Ollama: return OllamaModel; + case EN2CLLMProvider::OpenAICompatible: + return OpenAICompatibleModel; default: return FString(); } @@ -259,6 +264,17 @@ void UN2CSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChanged UserSecrets->SaveSecrets(); return; } + if (PropertyName == GET_MEMBER_NAME_CHECKED(UN2CSettings, OpenAICompatible_API_Key_UI)) + { + if (!UserSecrets) + { + UserSecrets = NewObject(); + UserSecrets->LoadSecrets(); + } + UserSecrets->OpenAICompatible_API_Key = OpenAICompatible_API_Key_UI; + UserSecrets->SaveSecrets(); + return; + } // Update logger severity when MinSeverity changes if (PropertyName == GET_MEMBER_NAME_CHECKED(UN2CSettings, MinSeverity)) diff --git a/Source/Private/Core/N2CUserSecrets.cpp b/Source/Private/Core/N2CUserSecrets.cpp index 593b83a..c8254cf 100644 --- a/Source/Private/Core/N2CUserSecrets.cpp +++ b/Source/Private/Core/N2CUserSecrets.cpp @@ -71,7 +71,8 @@ void UN2CUserSecrets::LoadSecrets() Anthropic_API_Key = JsonObject->GetStringField(TEXT("Anthropic_API_Key")); Gemini_API_Key = JsonObject->GetStringField(TEXT("Gemini_API_Key")); DeepSeek_API_Key = JsonObject->GetStringField(TEXT("DeepSeek_API_Key")); - + OpenAICompatible_API_Key = JsonObject->GetStringField(TEXT("OpenAICompatible_API_Key")); + FN2CLogger::Get().Log( FString::Printf(TEXT("Successfully loaded secrets from: %s"), *SecretsFilePath), EN2CLogSeverity::Info); @@ -88,7 +89,8 @@ void UN2CUserSecrets::SaveSecrets() JsonObject->SetStringField(TEXT("Anthropic_API_Key"), Anthropic_API_Key); JsonObject->SetStringField(TEXT("Gemini_API_Key"), Gemini_API_Key); JsonObject->SetStringField(TEXT("DeepSeek_API_Key"), DeepSeek_API_Key); - + JsonObject->SetStringField(TEXT("OpenAICompatible_API_Key"), OpenAICompatible_API_Key); + // Serialize to string FString JsonString; TSharedRef> Writer = TJsonWriterFactory<>::Create(&JsonString); diff --git a/Source/Private/LLM/N2CLLMModule.cpp b/Source/Private/LLM/N2CLLMModule.cpp index 5c766d4..4db9ed5 100644 --- a/Source/Private/LLM/N2CLLMModule.cpp +++ b/Source/Private/LLM/N2CLLMModule.cpp @@ -13,6 +13,7 @@ #include "LLM/Providers/N2CGeminiService.h" #include "LLM/Providers/N2COpenAIService.h" #include "LLM/Providers/N2COllamaService.h" +#include "LLM/Providers/N2COpenAICompatibleService.h" #include "Utils/N2CLogger.h" UN2CLLMModule* UN2CLLMModule::Get() @@ -491,6 +492,7 @@ void UN2CLLMModule::InitializeProviderRegistry() Registry->RegisterProvider(EN2CLLMProvider::Gemini, UN2CGeminiService::StaticClass()); Registry->RegisterProvider(EN2CLLMProvider::DeepSeek, UN2CDeepSeekService::StaticClass()); Registry->RegisterProvider(EN2CLLMProvider::Ollama, UN2COllamaService::StaticClass()); - + Registry->RegisterProvider(EN2CLLMProvider::OpenAICompatible, UN2COpenAICompatibleService::StaticClass()); + FN2CLogger::Get().Log(TEXT("Provider registry initialized"), EN2CLogSeverity::Info, TEXT("LLMModule")); } diff --git a/Source/Private/LLM/Providers/N2COpenAICompatibleService.cpp b/Source/Private/LLM/Providers/N2COpenAICompatibleService.cpp new file mode 100644 index 0000000..18bd4b9 --- /dev/null +++ b/Source/Private/LLM/Providers/N2COpenAICompatibleService.cpp @@ -0,0 +1,9 @@ +#include "LLM/Providers/N2COpenAICompatibleService.h" + +#include "Core/N2CSettings.h" + +FString UN2COpenAICompatibleService::GetDefaultEndpoint() const +{ + const UN2CSettings* Settings = GetDefault(); + return Settings->OpenAICompatibleBaseUrl; +} diff --git a/Source/Public/Core/N2CSettings.h b/Source/Public/Core/N2CSettings.h index 059c3b3..810d3f3 100644 --- a/Source/Public/Core/N2CSettings.h +++ b/Source/Public/Core/N2CSettings.h @@ -429,6 +429,18 @@ class NODETOCODE_API UN2CSettings : public UDeveloperSettings UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Node to Code | LLM Services | Ollama", meta=(DisplayName="Model Name")) FString OllamaModel = "qwen2.5-coder:32b"; + + UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Node to Code | LLM Services | OpenAI Compatible", + meta = (DisplayName = "API Key")) + FString OpenAICompatible_API_Key_UI; + + UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Node to Code | LLM Services | OpenAI Compatible", + meta = (DisplayName = "Model Name")) + FString OpenAICompatibleModel; + + UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Node to Code | LLM Services | OpenAI Compatible", + meta = (DisplayName = "Base Url")) + FString OpenAICompatibleBaseUrl; /** OpenAI Model Pricing */ UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Node to Code | LLM Services | Pricing | OpenAI", DisplayName = "OpenAI Model Pricing") diff --git a/Source/Public/Core/N2CUserSecrets.h b/Source/Public/Core/N2CUserSecrets.h index 0c007ca..2339699 100644 --- a/Source/Public/Core/N2CUserSecrets.h +++ b/Source/Public/Core/N2CUserSecrets.h @@ -44,6 +44,10 @@ class NODETOCODE_API UN2CUserSecrets : public UObject /** DeepSeek API Key */ UPROPERTY(EditAnywhere, Category = "Node to Code | API Keys") FString DeepSeek_API_Key; + + /** OpenAI Compatible API Key */ + UPROPERTY(EditAnywhere, Category = "Node to Code | API Keys") + FString OpenAICompatible_API_Key; private: /** Ensure the secrets directory exists */ diff --git a/Source/Public/LLM/N2CLLMTypes.h b/Source/Public/LLM/N2CLLMTypes.h index 7a1efa0..42b671b 100644 --- a/Source/Public/LLM/N2CLLMTypes.h +++ b/Source/Public/LLM/N2CLLMTypes.h @@ -22,7 +22,8 @@ enum class EN2CLLMProvider : uint8 Anthropic UMETA(DisplayName = "Anthropic"), Gemini UMETA(DisplayName = "Gemini"), Ollama UMETA(DisplayName = "Ollama"), - DeepSeek UMETA(DisplayName = "DeepSeek") + DeepSeek UMETA(DisplayName = "DeepSeek"), + OpenAICompatible UMETA(DisplayName = "OpenAICompatible") }; /** Status of the Node to Code system */ diff --git a/Source/Public/LLM/Providers/N2COpenAICompatibleService.h b/Source/Public/LLM/Providers/N2COpenAICompatibleService.h new file mode 100644 index 0000000..94dc024 --- /dev/null +++ b/Source/Public/LLM/Providers/N2COpenAICompatibleService.h @@ -0,0 +1,29 @@ +// Copyright (c) 2025 Nick McClure (Protospatial). All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "LLM/N2CBaseLLMService.h" +#include "N2COpenAIService.h" +#include "N2COpenAICompatibleService.generated.h" + +// Forward declarations +class UN2CSystemPromptManager; + +/** + * @class UN2COpenAICompatibleService + * @brief Implementation of OpenAI's Chat Completion API integration + */ +UCLASS() +class NODETOCODE_API UN2COpenAICompatibleService : public UN2COpenAIService +{ + GENERATED_BODY() + +public: + // Provider-specific implementations + virtual EN2CLLMProvider GetProviderType() const override { return EN2CLLMProvider::OpenAICompatible; } + +protected: + // Provider-specific implementations + virtual FString GetDefaultEndpoint() const override; +};