完善对话生成逻辑

This commit is contained in:
997146918 2025-07-09 14:55:51 +08:00
parent 5ce62f0bb5
commit 23b62b60a5
9 changed files with 236 additions and 133 deletions

View File

@ -188,8 +188,19 @@ void FAIGCModule::InitWebSocketManager()
auto& Settings = *GetDefault<UAIGCSetting>();
WebSocketManager = NewObject<UWebSocketManager>();
WebSocketManager->InitWebSocket(Settings.ServerIP);
WebSocketManager->OnConnectDelegate.AddLambda([this](bool bSuccess)
{
if (!bSuccess)
{
WebSocketManager->ConditionalBeginDestroy();
WebSocketManager = nullptr;
}
});
//WebSocketManager->OnConnectDelegate.AddRaw(this, &FAIGCModule::OnWebSocketConnect);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FAIGCModule, AIGC)

View File

@ -15,15 +15,6 @@ void SAIGCWindow::Construct(const FArguments& InArgs)
{
ChildSlot[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
[
SAssignNew(ServerIP, SConfigItem_Text)
.Title(LOCTEXT("Server", "服务器ip"))
.HintText(LOCTEXT("HintServer", "请输入服务器ip"))
.DefaultText(LOCTEXT("InputServer", "127.0.0.1"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
@ -36,35 +27,48 @@ void SAIGCWindow::Construct(const FArguments& InArgs)
.AutoHeight()
.Padding(10)
[
SAssignNew(NPCName1, SConfigItem_Text)
SAssignNew(NPCName1, SConfigItem_ComboBox<TSharedPtr<FCharacterInfo>>)
.Title(LOCTEXT("Name1", "名称1"))
.HintText(LOCTEXT("HintName", "请输入名称"))
.OptionsSource(&CharacterInfos)
.Content()
[
SNew(STextBlock)
.Text_Lambda([this]() -> FText {
return FText::FromString(SelectedCharacter1.name);
})
]
.OnGenerateWidget_Lambda([this](TSharedPtr<FCharacterInfo> CharacterInfo) {
return SNew(STextBlock).Text(FText::FromString(CharacterInfo->name));
})
.OnSelectionChanged_Lambda([this](TSharedPtr<FCharacterInfo> CharacterInfo, ESelectInfo::Type)
{
SelectedCharacter1 = *CharacterInfo;
})
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
[
SAssignNew(NPCJob1, SConfigItem_Text)
.Title(LOCTEXT("Job1", "职业1"))
.HintText(LOCTEXT("HintJon", "请输入职业"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
[
SAssignNew(NPCName2, SConfigItem_Text)
.Title(LOCTEXT("Name2", "名称2"))
.HintText(LOCTEXT("HintName", "请输入名称"))
]
.AutoHeight()
.Padding(10)
[
SAssignNew(NPCName2, SConfigItem_ComboBox<TSharedPtr<FCharacterInfo>>)
.Title(LOCTEXT("Name2", "名称2"))
.OptionsSource(&CharacterInfos)
.Content()
[
SNew(STextBlock)
.Text_Lambda([this]() -> FText {
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
[
SAssignNew(NPCJob2, SConfigItem_Text)
.Title(LOCTEXT("Job2", "职业2"))
.HintText(LOCTEXT("HintJon", "请输入职业"))
]
return FText::FromString(SelectedCharacter2.name);
})
]
.OnGenerateWidget_Lambda([this](TSharedPtr<FCharacterInfo> CharacterInfo) {
return SNew(STextBlock).Text(FText::FromString(CharacterInfo->name));
})
.OnSelectionChanged_Lambda([this](TSharedPtr<FCharacterInfo> CharacterInfo, ESelectInfo::Type)
{
SelectedCharacter2 = *CharacterInfo;
})
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
@ -111,14 +115,19 @@ EActiveTimerReturnType SAIGCWindow::OnPostPaint(double X, float Arg)
if (ModulePtr)
{
UWebSocketManager* WebSocketManager = ModulePtr->GetWebSocketManager();
if (!WebSocketManager)
if (!IsValid(WebSocketManager))
{
ModulePtr->InitWebSocketManager();
WebSocketManager = ModulePtr->GetWebSocketManager();
}
WebSocketManager->OnConnectDelegate.AddLambda([this](bool bSuccess)
else
{
WebSocketManager->SendData(FNetCommand::CharacterList, TEXT(""));
}
WebSocketManager->OnConnectDelegate.AddLambda([this, WebSocketManager](bool bSuccess)
{
GenerateButton->SetEnabled(bSuccess);
WebSocketManager->SendData(FNetCommand::CharacterList, TEXT(""));
});
WebSocketManager->OnDataReceiveDelaget.AddRaw(this, &SAIGCWindow::HandleReceiveData);
@ -131,11 +140,27 @@ void SAIGCWindow::OnAIGenerateClicked()
{
GenerateButton->SetEnabled(false);
RequireGenerateCount = GenerateCount->GetNumber();
UE_LOG(LogTemp, Warning, TEXT("生成次数 %d prompt:%s"), RequireGenerateCount, *GeneratePromptJson());
FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
//生成ai 配置信息
FRequestAIChat RequestAIChat;
RequestAIChat.DialogScene =DialogScene->GetInputText();
RequestAIChat.GenerateCount = GenerateCount->GetNumber();
RequestAIChat.CharacterName.Add(SelectedCharacter1.name);
RequestAIChat.CharacterName.Add(SelectedCharacter2.name);
FString dataJson;
FJsonObjectConverter::UStructToJsonObjectString(
FRequestAIChat::StaticStruct(),
&RequestAIChat,
dataJson,
0,
0
);
//发送ai对话生成请求
if (ModulePtr)
{
ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson());
ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, dataJson);
}
}
@ -143,58 +168,53 @@ void SAIGCWindow::OnAIGenerateClicked()
void SAIGCWindow::HandleReceiveData(FNetProtocol protocol)
{
// UE_LOG(LogTemp, Warning, TEXT("AI当前进度 %d/%d"), GeneratedCount, RequireGenerateCount);
// //添加数据到dataTable中
// if (AiMessages.Num() > 0)
// {
// FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
// if (ModulePtr) {
// FString DataPath = FString::Printf(TEXT("/Game/Test/%s.%s"), *DataName->GetInputText(), *DataName->GetInputText());
// FString Final = "";
// for (auto message: AiMessages)
// {
// Final += message + TEXT("|");
// }
// ModulePtr->CreateOrAddData(DataPath, Final);
// }
// }
//
// //是否生成足够数量
// if (GeneratedCount < RequireGenerateCount)
// {
// GeneratedCount++;
// FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
// if (ModulePtr)
// {
// ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson());
// }
//
// }
// else
// {
// GeneratedCount = 0;
// GenerateButton->SetEnabled(true);
// UE_LOG(LogTemp, Warning, TEXT("生成结束!"));
// }
if (protocol.cmd == FNetCommand::CharacterList)
{
}
//解析json角色信息
FJsonObjectConverter::JsonObjectStringToUStruct<FCharacterArray>(
protocol.data,
&Characters,
0, // 检查标志位
0 // 转换标志位
);
CharacterInfos.Empty();
for (auto Character: Characters.characterInfos)
{
CharacterInfos.Add(MakeShareable(new FCharacterInfo(Character)));
}
NPCName1->RefreshOptions();
NPCName2->RefreshOptions();
}
else if (protocol.cmd == FNetCommand::AiChatGenerate)
{
if (protocol.status == -1)
{
//需要重新生成
GenerateButton->SetEnabled(true);
UE_LOG(LogTemp, Error, TEXT("Chat Generate Failed reson = %s"), *protocol.message);
}
else if (protocol.status == 0)
{
UE_LOG(LogTemp, Warning, TEXT("Chat Generate warning reson = %s"), *protocol.message);
}
else if (protocol.status == 1)
{
UE_LOG(LogTemp, Warning, TEXT("Chat Generate success chat = %s"), *protocol.data);
FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
if (ModulePtr) {
FString DataPath = FString::Printf(TEXT("/Game/Test/%s.%s"), *DataName->GetInputText(), *DataName->GetInputText());
ModulePtr->CreateOrAddData(DataPath, protocol.data);
}
}
else if (protocol.status == 2)
{
//全部生成完成
UE_LOG(LogTemp, Warning, TEXT("Chat Generate has all generated"));
GenerateButton->SetEnabled(true);
}
}
FString SAIGCWindow::GeneratePromptJson()
{
FPrompt PromptData;
PromptData.DialogContent = FDialogContent(DialogScene->GetInputText());
PromptData.Persons.Add(FPersonInfo(NPCName1->GetInputText(), NPCJob1->GetInputText()));
PromptData.Persons.Add(FPersonInfo(NPCName2->GetInputText(), NPCJob2->GetInputText()));
// 结构体转JSON字符串
FString OutputString;
FJsonObjectConverter::UStructToJsonObjectString(
FPrompt::StaticStruct(),
&PromptData,
OutputString,
0,
0
);
return OutputString;
}

View File

@ -12,7 +12,6 @@
void SCharacterWindow::Construct(const FArguments& InArgs)
{
ChildSlot[
SNew(SVerticalBox)
+SVerticalBox::Slot()

View File

@ -0,0 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Widget/ConfigItem_ComboBox.h"

View File

@ -50,6 +50,7 @@ public:
void CreateOrAddData(const FString& DataTablePath, const FString& RowValue);
class UWebSocketManager* GetWebSocketManager();
void InitWebSocketManager();
//void OnWebSocketConnect(bool bSuccess);
private:
TSharedPtr<class FUICommandList> PluginCommands;

View File

@ -3,49 +3,42 @@
#include "CoreMinimal.h"
#include "Definations.generated.h"
// USTRUCT()
// struct FDialogContent
// {
// GENERATED_BODY()
// FDialogContent() {};
//
// FDialogContent(const FString& InDialogScene) : DialogScene(InDialogScene) {}
// UPROPERTY()
// FString DialogScene;
// };
// USTRUCT()
// struct FPersonInfo
// {
// GENERATED_BODY()
// FPersonInfo() {}
// FPersonInfo(const FString& InName, const FString& InJob):
// Name(InName), Job(InJob){}
// UPROPERTY()
// FString Name;
// UPROPERTY()
// FString Job;
//
// };
USTRUCT()
struct FDialogContent
struct FRequestAIChat
{
GENERATED_BODY()
FDialogContent() {};
FDialogContent(const FString& InDialogScene) : DialogScene(InDialogScene) {}
UPROPERTY()
FString DialogScene;
UPROPERTY()
int32 GenerateCount;
UPROPERTY()
TArray<FString> CharacterName;
};
USTRUCT()
struct FPersonInfo
{
GENERATED_BODY()
FPersonInfo() {}
FPersonInfo(const FString& InName, const FString& InJob):
Name(InName), Job(InJob){}
UPROPERTY()
FString Name;
UPROPERTY()
FString Job;
};
USTRUCT()
struct FPrompt
{
GENERATED_BODY()
UPROPERTY()
FDialogContent DialogContent;
UPROPERTY()
TArray<FPersonInfo> Persons;
};
USTRUCT()
struct FAIServerData
{
GENERATED_BODY()
UPROPERTY()
int32 statusCode;
UPROPERTY()
TArray<FString> messages;
};
USTRUCT()
struct FCharacterInfo

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "ConfigItem_ComboBox.h"
#include "ConfigItem_NumberSpin.h"
#include "ConfigItem_Text.h"
#include "Definations.h"
@ -26,19 +27,22 @@ public:
void HandleReceiveData(FNetProtocol protocol);
private:
FString GeneratePromptJson();
int32 RequireGenerateCount;
int32 GeneratedCount = 1;
FCharacterArray Characters;
TArray<TSharedPtr<FCharacterInfo>> CharacterInfos;
FCharacterInfo SelectedCharacter1;
FCharacterInfo SelectedCharacter2;
protected:
TSharedPtr<SConfigItem_Text> ServerIP; //服务器IP
TSharedPtr<SConfigItem_Text> DataName; //datatable 名称
TSharedPtr<SConfigItem_Text> NPCName1; //npc1的名称
TSharedPtr<SConfigItem_Text> NPCJob1; //npc1的职业
TSharedPtr<SConfigItem_Text> NPCName2; //npc2的名称
TSharedPtr<SConfigItem_Text> NPCJob2; //npc2的职业
TSharedPtr<SConfigItem_ComboBox<TSharedPtr<FCharacterInfo>>> NPCName1; //npc1的名称
TSharedPtr<SConfigItem_ComboBox<TSharedPtr<FCharacterInfo>>> NPCName2; //npc2的名称
TSharedPtr<SConfigItem_Text> DialogScene; //对话场景
TSharedPtr<SConfigItem_NumberSpin<int32>> GenerateCount; //生成数目
TSharedPtr<SButton> GenerateButton; //生成按钮
};

View File

@ -0,0 +1,69 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
/**
*
*/
template <typename OptionType>
class AIGC_API SConfigItem_ComboBox: public SCompoundWidget
{
public:
typedef typename TSlateDelegates<OptionType>::FOnGenerateWidget FOnGenerateWidget;
typedef typename TSlateDelegates<OptionType>::FOnSelectionChanged FOnSelectionChanged;
SLATE_BEGIN_ARGS( SConfigItem_ComboBox )
:_Title()
,_Content()
{}
SLATE_ARGUMENT(FText, Title) // 标题参数
SLATE_ITEMS_SOURCE_ARGUMENT( OptionType, OptionsSource ) //数据源
SLATE_EVENT(FOnGenerateWidget, OnGenerateWidget )
SLATE_EVENT( FOnSelectionChanged, OnSelectionChanged )
SLATE_NAMED_SLOT(FArguments, Content)//显示
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
//OptionSource = InArgs.GetOptionsSource();
ChildSlot
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(10, 0)
[
SNew(STextBlock)
.Text(InArgs._Title)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.Padding(10, 0)
[
SAssignNew(ComboBox, SComboBox<OptionType>)
.OptionsSource(InArgs.GetOptionsSource())
.Content()
[
InArgs._Content.Widget
]
.OnGenerateWidget(InArgs._OnGenerateWidget)
.OnSelectionChanged(InArgs._OnSelectionChanged)
]
];
}
void RefreshOptions()
{
ComboBox->RefreshOptions();
}
private:
TSharedPtr<SComboBox<OptionType>> ComboBox;
//TArray<OptionType>* OptionSource; //数据源指针
// FOnGenerateWidget OnGenerateWidgetDelegate;
// FOnSelectionChanged OnSelectionChangedDelegate;
};

View File

@ -25,6 +25,7 @@ public:
void Construct(const FArguments& InArgs)
{
InputValue = InArgs._MinNumber;
ChildSlot
[
SNew(SHorizontalBox)