Skip to content

Commit 45947b4

Browse files
authored
HttpGPT v1.5.4: Add chat history persistence to editor tool
2 parents e49ef63 + 3c31589 commit 45947b4

File tree

8 files changed

+108
-17
lines changed

8 files changed

+108
-17
lines changed

HttpGPT.uplugin

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"FileVersion": 3,
3-
"Version": 16,
4-
"VersionName": "1.5.3",
3+
"Version": 17,
4+
"VersionName": "1.5.4",
55
"FriendlyName": "HttpGPT - GPT Integration",
66
"Description": "HttpGPT is an Unreal Engine plugin that facilitates integration with OpenAI's GPT based services (ChatGPT and DALL-E) through asynchronous REST requests, making it easy for developers to communicate with these services. HttpGPT also includes new Editor Tools to integrate Chat GPT and DALL-E image generation directly in the Engine.",
77
"Category": "Game Features",

Source/HttpGPTChatModule/Private/Tasks/HttpGPTChatRequest.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ FString UHttpGPTChatRequest::SetRequestContent()
105105

106106
UE_LOG(LogHttpGPT_Internal, Display, TEXT("%s (%d): Mounting content"), *FString(__func__), GetUniqueID());
107107

108-
const TSharedPtr<FJsonObject> JsonRequest = MakeShareable(new FJsonObject);
108+
const TSharedPtr<FJsonObject> JsonRequest = MakeShared<FJsonObject>();
109109
JsonRequest->SetStringField("model", UHttpGPTHelper::ModelToName(GetChatOptions().Model).ToString().ToLower());
110110
JsonRequest->SetNumberField("max_tokens", GetChatOptions().MaxTokens);
111111
JsonRequest->SetNumberField("temperature", GetChatOptions().Temperature);
@@ -125,15 +125,15 @@ FString UHttpGPTChatRequest::SetRequestContent()
125125
TArray<TSharedPtr<FJsonValue>> StopJson;
126126
for (const FName& Iterator : GetChatOptions().Stop)
127127
{
128-
StopJson.Add(MakeShareable(new FJsonValueString(Iterator.ToString())));
128+
StopJson.Add(MakeShared<FJsonValueString>(Iterator.ToString()));
129129
}
130130

131131
JsonRequest->SetArrayField("stop", StopJson);
132132
}
133133

134134
if (!HttpGPT::Internal::HasEmptyParam(GetChatOptions().LogitBias))
135135
{
136-
TSharedPtr<FJsonObject> LogitBiasJson = MakeShareable(new FJsonObject());
136+
TSharedPtr<FJsonObject> LogitBiasJson = MakeShared<FJsonObject>();
137137
for (const TPair<int32, float>& Iterator : GetChatOptions().LogitBias)
138138
{
139139
LogitBiasJson->SetNumberField(FString::FromInt(Iterator.Key), Iterator.Value);
@@ -314,7 +314,7 @@ void UHttpGPTChatRequest::DeserializeSingleResponse(const FString& Content)
314314
}
315315

316316
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Content);
317-
TSharedPtr<FJsonObject> JsonResponse = MakeShareable(new FJsonObject);
317+
TSharedPtr<FJsonObject> JsonResponse = MakeShared<FJsonObject>();
318318
FJsonSerializer::Deserialize(Reader, JsonResponse);
319319

320320
if (CheckError(JsonResponse, Response.Error))

Source/HttpGPTCommonModule/Private/Structures/HttpGPTChatTypes.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ FHttpGPTChatMessage::FHttpGPTChatMessage(const FName& Role, const FString& Conte
1919

2020
TSharedPtr<FJsonValue> FHttpGPTChatMessage::GetMessage() const
2121
{
22-
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
22+
TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
2323
JsonObject->SetStringField("role", UHttpGPTHelper::RoleToName(Role).ToString().ToLower());
2424
JsonObject->SetStringField("content", Content);
2525

26-
return MakeShareable(new FJsonValueObject(JsonObject));
26+
return MakeShared<FJsonValueObject>(JsonObject);
2727
}
2828

2929
FHttpGPTChatOptions::FHttpGPTChatOptions()

Source/HttpGPTEditorModule/HttpGPTEditorModule.Build.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public HttpGPTEditorModule(ReadOnlyTargetRules Target) : base(Target)
3737
"AssetRegistry",
3838
"HttpGPTCommonModule",
3939
"HttpGPTChatModule",
40-
"HttpGPTImageModule"
40+
"HttpGPTImageModule",
41+
"Json"
4142
});
4243
}
4344
}

Source/HttpGPTEditorModule/Private/SHttpGPTChatView.cpp

+86-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
#include <Utils/HttpGPTHelper.h>
88
#include <HttpGPTInternalFuncs.h>
99
#include <Interfaces/IPluginManager.h>
10+
#include <Dom/JsonObject.h>
11+
#include <Serialization/JsonWriter.h>
12+
#include <Serialization/JsonReader.h>
13+
#include <Serialization/JsonSerializer.h>
14+
#include <Misc/FileHelper.h>
1015

1116
#ifdef UE_INLINE_GENERATED_CPP_BY_NAME
1217
#include UE_INLINE_GENERATED_CPP_BY_NAME(SHttpGPTChatView)
@@ -249,6 +254,13 @@ void SHttpGPTChatView::Construct([[maybe_unused]] const FArguments&)
249254
]
250255
]
251256
];
257+
258+
LoadChatHistory();
259+
}
260+
261+
SHttpGPTChatView::~SHttpGPTChatView()
262+
{
263+
SaveChatHistory();
252264
}
253265

254266
FReply SHttpGPTChatView::HandleSendMessageButton()
@@ -319,9 +331,11 @@ TArray<FHttpGPTChatMessage> SHttpGPTChatView::GetChatHistory() const
319331
FHttpGPTChatMessage(EHttpGPTChatRole::System, GetSystemContext())
320332
};
321333

322-
for (const auto& Item : ChatItems)
334+
for (const SHttpGPTChatItemPtr& Item : ChatItems)
323335
{
324-
Output.Add(FHttpGPTChatMessage(*Item->GetRoleText(), Item->GetMessageText()));
336+
FString RoleText = Item->GetRoleText();
337+
RoleText.RemoveFromEnd(TEXT(":"));
338+
Output.Add(FHttpGPTChatMessage(*RoleText, Item->GetMessageText()));
325339
}
326340

327341
return Output;
@@ -390,6 +404,76 @@ FString SHttpGPTChatView::GetSystemContext() const
390404
return FString::Format(TEXT("You are an assistant that will help with the development of projects in Unreal Engine in general.\n{0}\n{1}\n{2}\n{3}\n{4}\n{5}"), Arguments_SystemContext);
391405
}
392406

407+
void SHttpGPTChatView::LoadChatHistory()
408+
{
409+
if (const FString LoadPath = GetHistoryPath(); FPaths::FileExists(LoadPath))
410+
{
411+
FString FileContent;
412+
if (!FFileHelper::LoadFileToString(FileContent, *LoadPath))
413+
{
414+
return;
415+
}
416+
417+
TSharedPtr<FJsonObject> JsonParsed;
418+
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(FileContent);
419+
if (FJsonSerializer::Deserialize(Reader, JsonParsed))
420+
{
421+
const TArray<TSharedPtr<FJsonValue>> Data = JsonParsed->GetArrayField("Data");
422+
for (const TSharedPtr<FJsonValue>& Item : Data)
423+
{
424+
if (const TSharedPtr<FJsonObject> MessageItObj = Item->AsObject())
425+
{
426+
const FString RoleString = MessageItObj->GetStringField("role");
427+
const EHttpGPTChatRole Role = UHttpGPTHelper::NameToRole(*RoleString);
428+
if (Role == EHttpGPTChatRole::System)
429+
{
430+
continue;
431+
}
432+
433+
const FString Message = MessageItObj->GetStringField("content");
434+
435+
ChatItems.Add(
436+
SNew(SHttpGPTChatItem)
437+
.MessageRole(Role)
438+
.InputText(Message)
439+
);
440+
}
441+
}
442+
}
443+
}
444+
445+
for (const SHttpGPTChatItemPtr& Item : ChatItems)
446+
{
447+
ChatBox->AddSlot().AutoHeight()[Item.ToSharedRef()];
448+
}
449+
}
450+
451+
void SHttpGPTChatView::SaveChatHistory() const
452+
{
453+
const TSharedPtr<FJsonObject> JsonRequest = MakeShared<FJsonObject>();
454+
455+
TArray<TSharedPtr<FJsonValue>> Data;
456+
for (const FHttpGPTChatMessage& Item : GetChatHistory())
457+
{
458+
Data.Add(Item.GetMessage());
459+
}
460+
461+
JsonRequest->SetArrayField("Data", Data);
462+
463+
FString RequestContentString;
464+
const TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&RequestContentString);
465+
466+
if (FJsonSerializer::Serialize(JsonRequest.ToSharedRef(), Writer))
467+
{
468+
FFileHelper::SaveStringToFile(RequestContentString, *GetHistoryPath());
469+
}
470+
}
471+
472+
FString SHttpGPTChatView::GetHistoryPath() const
473+
{
474+
return FPaths::Combine(FPaths::ProjectSavedDir(), "HttpGPT", "HttpGPTChatHistory.json");
475+
}
476+
393477
void SHttpGPTChatView::InitializeModelsOptions()
394478
{
395479
for (const FName& ModelName : UHttpGPTHelper::GetAvailableGPTModels())

Source/HttpGPTEditorModule/Private/SHttpGPTChatView.h

+6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class SHttpGPTChatView final : public SCompoundWidget
7878
SLATE_END_ARGS()
7979

8080
void Construct(const FArguments& InArgs);
81+
~SHttpGPTChatView();
8182

8283
FReply HandleSendMessageButton();
8384
bool IsSendMessageEnabled() const;
@@ -89,6 +90,11 @@ class SHttpGPTChatView final : public SCompoundWidget
8990
TArray<FHttpGPTChatMessage> GetChatHistory() const;
9091
FString GetSystemContext() const;
9192

93+
void LoadChatHistory();
94+
void SaveChatHistory() const;
95+
96+
FString GetHistoryPath() const;
97+
9298
void InitializeModelsOptions();
9399

94100
private:

Source/HttpGPTEditorModule/Private/SHttpGPTImageGenView.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,13 @@ void SHttpGPTImageGenView::InitializeImageNumOptions()
397397
constexpr uint8 MaxNum = 10u;
398398
for (uint8 Iterator = 1u; Iterator <= MaxNum; ++Iterator)
399399
{
400-
ImageNum.Add(MakeShareable(new FString(FString::FromInt(Iterator))));
400+
ImageNum.Add(MakeShared<FString>(FString::FromInt(Iterator)));
401401
}
402402
}
403403

404404
void SHttpGPTImageGenView::InitializeImageSizeOptions()
405405
{
406-
ImageSize.Add(MakeShareable(new FString(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x256).ToString())));
407-
ImageSize.Add(MakeShareable(new FString(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x512).ToString())));
408-
ImageSize.Add(MakeShareable(new FString(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x1024).ToString())));
406+
ImageSize.Add(MakeShared<FString>(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x256).ToString()));
407+
ImageSize.Add(MakeShared<FString>(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x512).ToString()));
408+
ImageSize.Add(MakeShared<FString>(UHttpGPTHelper::SizeToName(EHttpGPTImageSize::x1024).ToString()));
409409
}

Source/HttpGPTImageModule/Private/Tasks/HttpGPTImageRequest.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ FString UHttpGPTImageRequest::SetRequestContent()
103103

104104
UE_LOG(LogHttpGPT_Internal, Display, TEXT("%s (%d): Mounting content"), *FString(__func__), GetUniqueID());
105105

106-
const TSharedPtr<FJsonObject> JsonRequest = MakeShareable(new FJsonObject);
106+
const TSharedPtr<FJsonObject> JsonRequest = MakeShared<FJsonObject>();
107107
JsonRequest->SetStringField("prompt", Prompt);
108108
JsonRequest->SetNumberField("n", GetImageOptions().ImagesNum);
109109
JsonRequest->SetStringField("size", UHttpGPTHelper::SizeToName(GetImageOptions().Size).ToString());
@@ -178,7 +178,7 @@ void UHttpGPTImageRequest::DeserializeResponse(const FString& Content)
178178
}
179179

180180
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Content);
181-
TSharedPtr<FJsonObject> JsonResponse = MakeShareable(new FJsonObject);
181+
TSharedPtr<FJsonObject> JsonResponse = MakeShared<FJsonObject>();
182182
FJsonSerializer::Deserialize(Reader, JsonResponse);
183183

184184
if (CheckError(JsonResponse, Response.Error))

0 commit comments

Comments
 (0)