diff --git a/Config/DefaultUnrealOpenAI.ini b/Config/DefaultUnrealOpenAI.ini index 69bb390..21700ca 100644 --- a/Config/DefaultUnrealOpenAI.ini +++ b/Config/DefaultUnrealOpenAI.ini @@ -3,4 +3,6 @@ +FunctionRedirects=(OldName="/Script/UnrealOpenAI.ListFineTuneEventsResultsProxy.ListFineTuneEventsResults",NewName="/Script/UnrealOpenAI.ListFineTuneEventsProxy.ListFineTuneEvents") +ClassRedirects=(OldName="/Script/UnrealOpenAI.ListFineTuneEventsResultsProxy",NewName="/Script/UnrealOpenAI.ListFineTuneEventsProxy") +ClassRedirects=(OldName="/Script/UnrealOpenAI.DeleteFineTuneModelResultsProxy",NewName="/Script/UnrealOpenAI.DeleteFineTuneModelProxy") -+FunctionRedirects=(OldName="/Script/UnrealOpenAI.UnrealOpenAIUtils.ConvertToTexture2D",NewName="/Script/UnrealOpenAI.UnrealOpenAIUtils.ConvertBytesToTexture2D") \ No newline at end of file ++FunctionRedirects=(OldName="/Script/UnrealOpenAI.UnrealOpenAIUtils.ConvertToTexture2D",NewName="/Script/UnrealOpenAI.UnrealOpenAIUtils.ConvertBytesToTexture2D") ++PropertyRedirects=(OldName="/Script/UnrealOpenAI.FunctionalTestPawn.CompletionFunctionalTest",NewName="/Script/UnrealOpenAI.FunctionalTestPawn.CreateCompletionFunctionalTest") ++FunctionRedirects=(OldName="/Script/UnrealOpenAI.FunctionalTestPawn.StartCompletionTest",NewName="/Script/UnrealOpenAI.FunctionalTestPawn.StartCreateCompletionTest") \ No newline at end of file diff --git a/Content/Maps/_Sandbox/BP_SandboxPawn.uasset b/Content/Maps/_Sandbox/BP_SandboxPawn.uasset index ffa4d23..9d0707c 100644 Binary files a/Content/Maps/_Sandbox/BP_SandboxPawn.uasset and b/Content/Maps/_Sandbox/BP_SandboxPawn.uasset differ diff --git a/Content/Test/BP_FunctionalTestPawn.uasset b/Content/Test/BP_FunctionalTestPawn.uasset new file mode 100644 index 0000000..bca6d7b Binary files /dev/null and b/Content/Test/BP_FunctionalTestPawn.uasset differ diff --git a/Content/Test/BP_TestMapGameMode.uasset b/Content/Test/BP_TestMapGameMode.uasset new file mode 100644 index 0000000..8ac10b2 Binary files /dev/null and b/Content/Test/BP_TestMapGameMode.uasset differ diff --git a/Content/Test/TestMap.umap b/Content/Test/TestMap.umap new file mode 100644 index 0000000..24b6c2d Binary files /dev/null and b/Content/Test/TestMap.umap differ diff --git a/Source/UnrealOpenAI/Private/Proxies/CompletionProxies.cpp b/Source/UnrealOpenAI/Private/Proxies/CompletionProxies.cpp index 5c4c05a..223f358 100644 --- a/Source/UnrealOpenAI/Private/Proxies/CompletionProxies.cpp +++ b/Source/UnrealOpenAI/Private/Proxies/CompletionProxies.cpp @@ -63,7 +63,7 @@ void UCreateCompletionRequestProxy::Activate() OnFailure.Broadcast(FCreateCompletionResponse(), ResponseString, ErrorMessage); return; } - + FCreateCompletionResponse CreateCompletionResponse; if (FJsonObjectConverter::JsonObjectStringToUStruct(ResponseString, &CreateCompletionResponse, 0, 0)) { diff --git a/Source/UnrealOpenAI/Private/Proxies/EmbeddingsProxies.cpp b/Source/UnrealOpenAI/Private/Proxies/EmbeddingsProxies.cpp index cddd2c0..ed40bcb 100644 --- a/Source/UnrealOpenAI/Private/Proxies/EmbeddingsProxies.cpp +++ b/Source/UnrealOpenAI/Private/Proxies/EmbeddingsProxies.cpp @@ -32,7 +32,6 @@ void UCreateEmbeddingsRequestProxy::Activate() OnFailure.Broadcast(FCreateEmbeddingsResponse(), TEXT(""), TEXT("Input is empty")); return; } - FString JSONPayload; FCreateEmbeddingsRequest RequestPayload; diff --git a/Source/UnrealOpenAI/Private/SampleContent/ChatbotDemo/ChatbotDemoWidget.cpp b/Source/UnrealOpenAI/Private/SampleContent/ChatbotDemo/ChatbotDemoWidget.cpp index 469bfc0..02f7e21 100644 --- a/Source/UnrealOpenAI/Private/SampleContent/ChatbotDemo/ChatbotDemoWidget.cpp +++ b/Source/UnrealOpenAI/Private/SampleContent/ChatbotDemo/ChatbotDemoWidget.cpp @@ -131,8 +131,8 @@ void UChatbotDemoWidget::SetInstruction(FString NewInstruction) void UChatbotDemoWidget::OnCompletionResponse(FCreateCompletionResponse Response, FString JSONString, FString Error) { - AddAIResponse(Response.choices.text); - Instruction += Response.choices.text + LINE_TERMINATOR + "Q: "; + AddAIResponse(Response.choices[0].text); + Instruction += Response.choices[0].text + LINE_TERMINATOR + "Q: "; ToggleUserInput(true); } diff --git a/Source/UnrealOpenAI/Private/Tests/Actors/FunctionalTestPawn.cpp b/Source/UnrealOpenAI/Private/Tests/Actors/FunctionalTestPawn.cpp new file mode 100644 index 0000000..fd237d0 --- /dev/null +++ b/Source/UnrealOpenAI/Private/Tests/Actors/FunctionalTestPawn.cpp @@ -0,0 +1,184 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#include "Tests/Actors/FunctionalTestPawn.h" + +#include "Enums/CompletionEnums.h" +#include "Proxies/CompletionProxies.h" +#include "Proxies/EditsProxies.h" +#include "Proxies/EmbeddingsProxies.h" +#include "Tests/FunctionalTests/CompletionFunctionalTest.h" +#include "Tests/FunctionalTests/EditsFunctionalTest.h" +#include "Tests/FunctionalTests/EmbeddingsFunctionalTest.h" + + +AFunctionalTestPawn::AFunctionalTestPawn() +{ + PrimaryActorTick.bCanEverTick = false; +} + + +void AFunctionalTestPawn::StartCreateCompletionTest(FString Prompt) +{ + if (!CreateCompletionFunctionalTest) + return; + + if (Prompt.IsEmpty() || Prompt.Len() <= 0 || Prompt == TEXT("")) + { + CreateCompletionFunctionalTest->FailTest(TEXT("Prompt is empty")); + } + + const auto Proxy = UCreateCompletionRequestProxy::CreateCompletion(this, Prompt, ECompletionModel::ECM_Davinci); + + if (!Proxy) + { + CreateCompletionFunctionalTest->FailTest(TEXT("Failed to create completion request proxy")); + return; + } + + Proxy->OnSuccess.AddDynamic(this, &AFunctionalTestPawn::OnCompletionSuccess); + + Proxy->OnFailure.AddDynamic(this, &AFunctionalTestPawn::OnCompletionFailure); + + Proxy->Activate(); +} + +void AFunctionalTestPawn::OnCompletionSuccess(FCreateCompletionResponse Response, FString JSONString, FString Error) +{ + if (JSONString.IsEmpty()) + { + CreateCompletionFunctionalTest->FailTest(TEXT("No JSON String returned")); + return; + } + + if (!Error.IsEmpty()) + { + CreateCompletionFunctionalTest->FailTest(TEXT("Error returned")); + return; + } + + if (Response.choices[0].text.IsEmpty()) + { + CreateCompletionFunctionalTest->FailTest(TEXT("No response text returned")); + return; + } + + CreateCompletionFunctionalTest->PassTest(FString::Printf(TEXT("Response text returned %s"), *Response.choices[0].text)); +} + +void AFunctionalTestPawn::OnCompletionFailure(FCreateCompletionResponse Response, FString JSONString, FString Error) +{ + CreateCompletionFunctionalTest->FailTest(TEXT("Should not fire failure delegate")); +} + +void AFunctionalTestPawn::StartCreateEditsTest(FString Input, FString Instruction) +{ + if (!CreateEditsFunctionalTest) + return; + + if (Input.IsEmpty() || Input.Len() <= 0 || Input == TEXT("")) + { + CreateEditsFunctionalTest->FailTest(TEXT("Input is empty")); + return; + } + + if (Instruction.IsEmpty() || Instruction.Len() <= 0 || Instruction == TEXT("")) + { + CreateEditsFunctionalTest->FailTest(TEXT("Instruction is empty")); + return; + } + + const auto Proxy = UCreateEditsRequestProxy::CreateEdits(this, Input, Instruction); + + if (!Proxy) + { + CreateEditsFunctionalTest->FailTest(TEXT("Failed to create edits request proxy")); + return; + } + + Proxy->OnSuccess.AddDynamic(this, &AFunctionalTestPawn::OnEditsSuccess); + Proxy->OnFailure.AddDynamic(this, &AFunctionalTestPawn::OnEditsFailure); + + Proxy->Activate(); +} + +void AFunctionalTestPawn::OnEditsSuccess(FCreateEditsResponse Response, FString JSONString, FString Error) +{ + if (JSONString.IsEmpty()) + { + CreateEditsFunctionalTest->FailTest(TEXT("No JSON String returned")); + return; + } + + if (!Error.IsEmpty()) + { + CreateEditsFunctionalTest->FailTest(TEXT("Error returned")); + return; + } + if (Response.choices[0].text.IsEmpty()) + { + CreateEditsFunctionalTest->FailTest(TEXT("No response text returned")); + return; + } + + CreateEditsFunctionalTest->PassTest(FString::Printf(TEXT("Response text returned %s"), *Response.choices[0].text)); +} + +void AFunctionalTestPawn::OnEditsFailure(FCreateEditsResponse Response, FString JSONString, FString Error) +{ + CreateEditsFunctionalTest->FailTest(TEXT("Should not fire failure delegate")); +} + +void AFunctionalTestPawn::StartCreateEmbeddingsTest(FString Input) +{ + if (!CreateEmbeddingsFunctionalTest) + { + return; + } + + if (Input.IsEmpty() || Input.Len() <= 0 || Input == TEXT("")) + { + CreateEmbeddingsFunctionalTest->FailTest(TEXT("Input is empty")); + return; + } + + const auto Proxy = UCreateEmbeddingsRequestProxy::CreateEmbeddings(this, Input); + + if (!Proxy) + { + CreateEmbeddingsFunctionalTest->FailTest(TEXT("Failed to create embeddings request proxy")); + return; + } + + Proxy->OnSuccess.AddDynamic(this, &AFunctionalTestPawn::OnEmbeddingsSuccess); + Proxy->OnFailure.AddDynamic(this, &AFunctionalTestPawn::OnEmbeddingsFailure); + + Proxy->Activate(); +} + +void AFunctionalTestPawn::OnEmbeddingsSuccess(FCreateEmbeddingsResponse Response, FString JSONString, FString Error) +{ + if (JSONString.IsEmpty()) + { + CreateEmbeddingsFunctionalTest->FailTest(TEXT("No JSON String returned")); + return; + } + + if (!Error.IsEmpty()) + { + CreateEmbeddingsFunctionalTest->FailTest(TEXT("Error returned")); + return; + } + + if (Response.data.Num() < 0) + { + CreateEmbeddingsFunctionalTest->FailTest(TEXT("No response data returned")); + return; + } + + CreateEmbeddingsFunctionalTest->PassTest(FString::Printf(TEXT("Response data returned with length of %d"), Response.data.Num())); +} + +void AFunctionalTestPawn::OnEmbeddingsFailure(FCreateEmbeddingsResponse Response, FString JSONString, FString Error) +{ + CreateEmbeddingsFunctionalTest->FailTest(TEXT("Should not fire failure delegate")); +} diff --git a/Source/UnrealOpenAI/Private/Tests/FunctionalTests/CompletionFunctionalTest.cpp b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/CompletionFunctionalTest.cpp new file mode 100644 index 0000000..2a2185d --- /dev/null +++ b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/CompletionFunctionalTest.cpp @@ -0,0 +1,25 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + + +#include "Tests/FunctionalTests/CompletionFunctionalTest.h" + +#include "Tests/Actors/FunctionalTestPawn.h" + +ACreateCompletionFunctionalTest::ACreateCompletionFunctionalTest() +{ + PrimaryActorTick.bCanEverTick = false; +} + +void ACreateCompletionFunctionalTest::OnTestStartHandler() +{ + Super::OnTestStartHandler(); + if (!TestPawn) + { + FailTest(TEXT("TestPawn is not set")); + return; + } + + TestPawn->CreateCompletionFunctionalTest = this; + + TestPawn->StartCreateCompletionTest("Say this is a test"); +} \ No newline at end of file diff --git a/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EditsFunctionalTest.cpp b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EditsFunctionalTest.cpp new file mode 100644 index 0000000..8281b79 --- /dev/null +++ b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EditsFunctionalTest.cpp @@ -0,0 +1,26 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + + +#include "Tests/FunctionalTests/EditsFunctionalTest.h" + +#include "Tests/Actors/FunctionalTestPawn.h" + +ACreateEditsFunctionalTest::ACreateEditsFunctionalTest() +{ + PrimaryActorTick.bCanEverTick = false; +} + +void ACreateEditsFunctionalTest::OnTestStartHandler() +{ + Super::OnTestStartHandler(); + + if (!TestPawn) + { + FailTest("TestPawn is not set"); + return; + } + + TestPawn->CreateEditsFunctionalTest = this; + + TestPawn->StartCreateEditsTest("What day of the wek is it?", "Fix the spelling mistakes"); +} diff --git a/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EmbeddingsFunctionalTest.cpp b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EmbeddingsFunctionalTest.cpp new file mode 100644 index 0000000..193a21f --- /dev/null +++ b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/EmbeddingsFunctionalTest.cpp @@ -0,0 +1,29 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + + +#include "Tests/FunctionalTests/EmbeddingsFunctionalTest.h" + +#include "Tests/Actors/FunctionalTestPawn.h" + + +ACreateEmbeddingsFunctionalTest::ACreateEmbeddingsFunctionalTest() +{ + PrimaryActorTick.bCanEverTick = false; +} + +void ACreateEmbeddingsFunctionalTest::OnTestStartHandler() +{ + Super::OnTestStartHandler(); + + if (!TestPawn) + { + FailTest("TestPawn is not set"); + return; + } + + TestPawn->CreateEmbeddingsFunctionalTest = this; + + TestPawn->StartCreateEmbeddingsTest(TEXT("The food was delicious and the waiter...")); +} + + diff --git a/Source/UnrealOpenAI/Private/Tests/FunctionalTests/OpenAIFunctionalTestBase.cpp b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/OpenAIFunctionalTestBase.cpp new file mode 100644 index 0000000..809d325 --- /dev/null +++ b/Source/UnrealOpenAI/Private/Tests/FunctionalTests/OpenAIFunctionalTestBase.cpp @@ -0,0 +1,71 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + + +#include "Tests/FunctionalTests/OpenAIFunctionalTestBase.h" + +#include "Kismet/GameplayStatics.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Utils/Utils.h" + +AOpenAIFunctionalTestBase::AOpenAIFunctionalTestBase() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void AOpenAIFunctionalTestBase::OnTestPrepareHandler() +{ + PrintDebugLogAndOnScreen("OnTestPrepareHandler"); + + StartTest(); +} + +void AOpenAIFunctionalTestBase::BeginPlay() +{ + Super::BeginPlay(); + + PrintDebugLogAndOnScreen("BeginPlay"); + + OnTestPrepare.AddDynamic(this, &AOpenAIFunctionalTestBase::OnTestPrepareHandler); + + OnTestStart.AddDynamic(this, &AOpenAIFunctionalTestBase::OnTestStartHandler); +} + +void AOpenAIFunctionalTestBase::OnTestStartHandler() +{ + PrintDebugLogAndOnScreen("Test started"); +} + +void AOpenAIFunctionalTestBase::PrepareTest() +{ + Super::PrepareTest(); + + PrintDebugLogAndOnScreen("PrepareTest"); +} + +bool AOpenAIFunctionalTestBase::IsReady_Implementation() +{ + return true; +} + +void AOpenAIFunctionalTestBase::StartTest() +{ + Super::StartTest(); + + PrintDebugLogAndOnScreen("StartTest"); +} + +void AOpenAIFunctionalTestBase::FailTest(FString Message) +{ + FinishTest(EFunctionalTestResult::Failed, Message); + + UKismetSystemLibrary::QuitGame(GetWorld(), UGameplayStatics::GetPlayerController(GetWorld(), 0), EQuitPreference::Quit, false); +} + +void AOpenAIFunctionalTestBase::PassTest(FString Message) +{ + FinishTest(EFunctionalTestResult::Succeeded, Message); + + UKismetSystemLibrary::QuitGame(GetWorld(), UGameplayStatics::GetPlayerController(GetWorld(), 0), EQuitPreference::Quit, false); +} + + diff --git a/Source/UnrealOpenAI/Private/Utils/UnrealOpenAIUtils.cpp b/Source/UnrealOpenAI/Private/Utils/UnrealOpenAIUtils.cpp index 85f3c8a..115e2c6 100644 --- a/Source/UnrealOpenAI/Private/Utils/UnrealOpenAIUtils.cpp +++ b/Source/UnrealOpenAI/Private/Utils/UnrealOpenAIUtils.cpp @@ -164,11 +164,21 @@ bool UUnrealOpenAIUtils::ConvertBase64ToTexture2D(FString Base64Data, UTexture2D if(Base64Data.IsEmpty()) return false; TArray FileData; - if(!FBase64::Decode(Base64Data, FileData)) return false; + + if (!ConvertBase64ToBytes(Base64Data, FileData)) + return false; return ConvertBytesToTexture2D(FileData, OutTexture); } +bool UUnrealOpenAIUtils::ConvertBase64ToBytes(FString Base64Data, TArray& OutBytes) +{ + OutBytes.Empty(); + if(Base64Data.IsEmpty()) return false; + + return FBase64::Decode(Base64Data, OutBytes); +} + void UUnrealOpenAIUtilsGetImageFromURL::OnProcessRequestComplete( TSharedPtr HttpRequest, TSharedPtr HttpResponse, bool bSuccessful) diff --git a/Source/UnrealOpenAI/Public/DataTypes/CommonDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/CommonDataTypes.h index 7aef961..6b91bd4 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/CommonDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/CommonDataTypes.h @@ -5,6 +5,23 @@ #include "CoreMinimal.h" #include "CommonDataTypes.generated.h" +USTRUCT(BlueprintType) +struct FLogprobs +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Logprobs") + TArray tokens; + + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Logprobs") + TArray token_logprobs; + + TArray> top_logprobs; + + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Logprobs") + TArray text_offset; +}; + USTRUCT(BlueprintType) struct FChoice { @@ -13,10 +30,10 @@ struct FChoice FString text; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Choice") - int index; + int index {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Choice") - int logprobs; + FLogprobs logprobs; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Choice") FString finish_reason; @@ -48,10 +65,10 @@ struct FOpenAIFile FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File") - int32 bytes; + int32 bytes {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File") - int32 created_at; + int32 created_at {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File") FString filename; @@ -90,7 +107,7 @@ struct FDeleteResponse FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Delete Response") - bool deleted; + bool deleted {false}; }; USTRUCT(BlueprintType) diff --git a/Source/UnrealOpenAI/Public/DataTypes/CompletionDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/CompletionDataTypes.h index 6f2cca8..95d81c9 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/CompletionDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/CompletionDataTypes.h @@ -70,13 +70,13 @@ struct FCreateCompletionResponse FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "OpenAI | Create Completion Response") - int32 created; + int32 created {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "OpenAI | Create Completion Response") FString model; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "OpenAI | Create Completion Response") - FChoice choices; + TArray choices; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "OpenAI | Create Completion Response") FUsage usage; diff --git a/Source/UnrealOpenAI/Public/DataTypes/EditsDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/EditsDataTypes.h index 2c518aa..19c1ac7 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/EditsDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/EditsDataTypes.h @@ -37,10 +37,10 @@ struct FCreateEditsResponse FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Edits Response") - int32 created; + int32 created {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Edits Response") - FChoice choices; + TArray choices; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Edits Response") FUsage usage; diff --git a/Source/UnrealOpenAI/Public/DataTypes/EmbeddingsDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/EmbeddingsDataTypes.h index 64b0505..42dbb61 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/EmbeddingsDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/EmbeddingsDataTypes.h @@ -18,7 +18,7 @@ struct FEmbeddingData TArray embedding; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Embedding Data") - int index; + int index {0}; }; diff --git a/Source/UnrealOpenAI/Public/DataTypes/FilesDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/FilesDataTypes.h index 045887c..52127ae 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/FilesDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/FilesDataTypes.h @@ -44,10 +44,10 @@ struct FFileResponse FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File Response") - int32 bytes; + int32 bytes {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File Response") - int32 created_at; + int32 created_at {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | File Response") FString filename; diff --git a/Source/UnrealOpenAI/Public/DataTypes/FineTuneDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/FineTuneDataTypes.h index 2f27b1a..7dd0a09 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/FineTuneDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/FineTuneDataTypes.h @@ -15,7 +15,7 @@ struct FFineTuneEvent FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Fine Tune Event") - int32 created_at; + int32 created_at {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Fine Tune Event") FString level; @@ -36,10 +36,10 @@ struct FFineTune FString object; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Fine Tune") - int32 created_at; + int32 created_at {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Fine Tune") - int32 updated_at; + int32 updated_at {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Fine Tune") FString model; @@ -83,16 +83,16 @@ struct FCreateFineTuneRequest FString model; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Create Fine Tune Request") - int n_epochs = 4; + int n_epochs {4}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Create Fine Tune Request") - int batch_size; + int batch_size {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Create Fine Tune Request") - float learning_rate_multiplier; + float learning_rate_multiplier {1.0f}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Open AI | Create Fine Tune Request") - float prompt_loss_weight; + float prompt_loss_weight {.01f}; TOptional compute_classification_metrics = false; diff --git a/Source/UnrealOpenAI/Public/DataTypes/ImageDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/ImageDataTypes.h index 3f2d8f9..7339100 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/ImageDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/ImageDataTypes.h @@ -81,7 +81,7 @@ struct FCreateImageResponseURL GENERATED_BODY() UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Image Response URL") - int32 created; + int32 created {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Image Response URL") TArray data; @@ -93,7 +93,7 @@ struct FCreateImageResponseBase64JSON GENERATED_BODY() UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Image Response Base64 JSON") - int32 created; + int32 created {0}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Create Image Response Base64 JSON") TArray data; diff --git a/Source/UnrealOpenAI/Public/DataTypes/ModerationDataTypes.h b/Source/UnrealOpenAI/Public/DataTypes/ModerationDataTypes.h index 1c70e94..1757e63 100644 --- a/Source/UnrealOpenAI/Public/DataTypes/ModerationDataTypes.h +++ b/Source/UnrealOpenAI/Public/DataTypes/ModerationDataTypes.h @@ -13,7 +13,7 @@ struct FModerationResult GENERATED_BODY() UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Moderation Result") - bool flagged; + bool flagged {false}; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Open AI | Moderation Result") TMap categories; diff --git a/Source/UnrealOpenAI/Public/Tests/Actors/FunctionalTestPawn.h b/Source/UnrealOpenAI/Public/Tests/Actors/FunctionalTestPawn.h new file mode 100644 index 0000000..ec9d936 --- /dev/null +++ b/Source/UnrealOpenAI/Public/Tests/Actors/FunctionalTestPawn.h @@ -0,0 +1,68 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#pragma once + +#include "CoreMinimal.h" +#include "DataTypes/CompletionDataTypes.h" +#include "DataTypes/EditsDataTypes.h" +#include "DataTypes/EmbeddingsDataTypes.h" +#include "GameFramework/Pawn.h" +#include "FunctionalTestPawn.generated.h" + +UCLASS() +class UNREALOPENAI_API AFunctionalTestPawn : public APawn +{ + GENERATED_BODY() + +public: + // Sets default values for this pawn's properties + AFunctionalTestPawn(); + +#pragma region Completion + + UPROPERTY() + class ACreateCompletionFunctionalTest* CreateCompletionFunctionalTest; + + UFUNCTION() + void StartCreateCompletionTest(FString Prompt); + + UFUNCTION() + void OnCompletionSuccess(FCreateCompletionResponse Response, FString JSONString, FString Error); + + UFUNCTION() + void OnCompletionFailure(FCreateCompletionResponse Response, FString JSONString, FString Error); + +#pragma endregion + +#pragma region Edits + + UPROPERTY() + class ACreateEditsFunctionalTest* CreateEditsFunctionalTest; + + UFUNCTION() + void StartCreateEditsTest(FString Input, FString Instruction); + + UFUNCTION() + void OnEditsSuccess(FCreateEditsResponse Response, FString JSONString, FString Error); + + UFUNCTION() + void OnEditsFailure(FCreateEditsResponse Response, FString JSONString, FString Error); + +#pragma endregion + +#pragma region Embeddings + + UPROPERTY() + class ACreateEmbeddingsFunctionalTest* CreateEmbeddingsFunctionalTest; + + UFUNCTION() + void StartCreateEmbeddingsTest(FString Input); + UFUNCTION() + void OnEmbeddingsSuccess(FCreateEmbeddingsResponse Response, FString JSONString, FString Error); + UFUNCTION() + void OnEmbeddingsFailure(FCreateEmbeddingsResponse Response, FString JSONString, FString Error); + + +#pragma endregion + +}; diff --git a/Source/UnrealOpenAI/Public/Tests/FunctionalTests/CompletionFunctionalTest.h b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/CompletionFunctionalTest.h new file mode 100644 index 0000000..b04542b --- /dev/null +++ b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/CompletionFunctionalTest.h @@ -0,0 +1,25 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#pragma once + +#include "CoreMinimal.h" +#include "OpenAIFunctionalTestBase.h" +#include "CompletionFunctionalTest.generated.h" + +/** + * + */ +UCLASS() +class UNREALOPENAI_API ACreateCompletionFunctionalTest : public AOpenAIFunctionalTestBase +{ + GENERATED_BODY() + +public: + + ACreateCompletionFunctionalTest(); + + virtual void OnTestStartHandler() override; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Open AI - Completion") + class AFunctionalTestPawn* TestPawn; +}; diff --git a/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EditsFunctionalTest.h b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EditsFunctionalTest.h new file mode 100644 index 0000000..85ac740 --- /dev/null +++ b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EditsFunctionalTest.h @@ -0,0 +1,25 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#pragma once + +#include "CoreMinimal.h" +#include "OpenAIFunctionalTestBase.h" +#include "UObject/Object.h" +#include "EditsFunctionalTest.generated.h" + +/** + * + */ +UCLASS() +class UNREALOPENAI_API ACreateEditsFunctionalTest : public AOpenAIFunctionalTestBase +{ + GENERATED_BODY() + +public: + ACreateEditsFunctionalTest(); + + virtual void OnTestStartHandler() override; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Open AI - Edits") + class AFunctionalTestPawn* TestPawn; +}; diff --git a/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EmbeddingsFunctionalTest.h b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EmbeddingsFunctionalTest.h new file mode 100644 index 0000000..18a09d6 --- /dev/null +++ b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/EmbeddingsFunctionalTest.h @@ -0,0 +1,22 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#pragma once + +#include "CoreMinimal.h" +#include "OpenAIFunctionalTestBase.h" +#include "GameFramework/Actor.h" +#include "EmbeddingsFunctionalTest.generated.h" + +UCLASS() +class UNREALOPENAI_API ACreateEmbeddingsFunctionalTest : public AOpenAIFunctionalTestBase +{ + GENERATED_BODY() + +public: + ACreateEmbeddingsFunctionalTest(); + + virtual void OnTestStartHandler() override; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Open AI - Edits") + class AFunctionalTestPawn* TestPawn; +}; diff --git a/Source/UnrealOpenAI/Public/Tests/FunctionalTests/OpenAIFunctionalTestBase.h b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/OpenAIFunctionalTestBase.h new file mode 100644 index 0000000..2320b36 --- /dev/null +++ b/Source/UnrealOpenAI/Public/Tests/FunctionalTests/OpenAIFunctionalTestBase.h @@ -0,0 +1,39 @@ +// Created, maintained by Vanan A. - rezonated @ github.com + +#pragma once + +#include "CoreMinimal.h" +#include "FunctionalTest.h" +#include "OpenAIFunctionalTestBase.generated.h" + +/** + * + */ +UCLASS() +class UNREALOPENAI_API AOpenAIFunctionalTestBase : public AFunctionalTest +{ + GENERATED_BODY() + +public: + AOpenAIFunctionalTestBase(); + + UFUNCTION() + void OnTestPrepareHandler(); + virtual void BeginPlay() override; + + UFUNCTION() + virtual void OnTestStartHandler(); + + virtual void PrepareTest() override; + + virtual bool IsReady_Implementation() override; + + virtual void StartTest() override; + + UFUNCTION() + virtual void FailTest(FString Message); + + UFUNCTION() + virtual void PassTest(FString Message); + +}; diff --git a/Source/UnrealOpenAI/Public/Utils/UnrealOpenAIUtils.h b/Source/UnrealOpenAI/Public/Utils/UnrealOpenAIUtils.h index b961caf..3781354 100644 --- a/Source/UnrealOpenAI/Public/Utils/UnrealOpenAIUtils.h +++ b/Source/UnrealOpenAI/Public/Utils/UnrealOpenAIUtils.h @@ -30,6 +30,9 @@ class UNREALOPENAI_API UUnrealOpenAIUtils : public UObject UFUNCTION(BlueprintCallable, Category = "UnrealOpenAIUtils", meta=(ExpandBoolAsExecs="ReturnValue")) static bool ConvertBase64ToTexture2D(FString Base64Data, UTexture2D*& OutTexture); + + UFUNCTION(BlueprintCallable, Category = "UnrealOpenAIUtils", meta=(ExpandBoolAsExecs="ReturnValue")) + static bool ConvertBase64ToBytes(FString Base64Data, TArray& OutBytes); }; diff --git a/Source/UnrealOpenAI/Public/Utils/Utils.h b/Source/UnrealOpenAI/Public/Utils/Utils.h index fb9a9aa..b9cda3e 100644 --- a/Source/UnrealOpenAI/Public/Utils/Utils.h +++ b/Source/UnrealOpenAI/Public/Utils/Utils.h @@ -5,6 +5,7 @@ #include "Engine/Classes/Engine/Texture2D.h" #include "Engine/Public/ImageUtils.h" #include "HttpModule.h" +#include "JsonObjectConverter.h" #include "UnrealOpenAI.h" #include "Config/UnrealOpenAIConfig.h" #include "Constants/UtilsConstants.h" @@ -21,7 +22,7 @@ static void PrintDebugOnScreen(const FString& Message, const float Duration = 2. static void PrintDebugLog(const FString& Message) { - UE_LOG(LogTypeOpenAI, Warning, TEXT("%s"), *Message); + UE_LOG(LogTypeOpenAI, Display, TEXT("%s"), *Message); } static void PrintDebugLogAndOnScreen(const FString& Message, const float Duration = 2.f, const FColor& Color = FColor::White) diff --git a/Source/UnrealOpenAI/UnrealOpenAI.Build.cs b/Source/UnrealOpenAI/UnrealOpenAI.Build.cs index e20241d..9a08213 100644 --- a/Source/UnrealOpenAI/UnrealOpenAI.Build.cs +++ b/Source/UnrealOpenAI/UnrealOpenAI.Build.cs @@ -25,7 +25,7 @@ public UnrealOpenAI(ReadOnlyTargetRules Target) : base(Target) PublicDependencyModuleNames.AddRange( new string[] { - "Core", "Engine", "Json", "JsonUtilities", "HTTP", "CoreUObject", "Sockets", "Networking", "UMG" + "Core", "Engine", "Json", "JsonUtilities", "HTTP", "CoreUObject", "Sockets", "Networking", "UMG", "FunctionalTesting" // ... add other public dependencies that you statically link with here ... } );