|
29 | 29 | #if WITH_EDITOR
|
30 | 30 | UHttpGPTChatRequest* UHttpGPTChatRequest::EditorTask(const TArray<FHttpGPTChatMessage>& Messages, const FHttpGPTChatOptions Options)
|
31 | 31 | {
|
32 |
| - UHttpGPTChatRequest* const NewAsyncTask = SendMessages_CustomOptions(GEditor->GetEditorWorldContext().World(), Messages, FHttpGPTCommonOptions(), Options); |
| 32 | + UHttpGPTChatRequest* const NewAsyncTask = SendMessages_CustomOptions(GEditor->GetEditorWorldContext().World(), Messages, TArray<FHttpGPTFunction>(), FHttpGPTCommonOptions(), Options); |
33 | 33 | NewAsyncTask->bIsEditorTask = true;
|
34 | 34 |
|
35 | 35 | return NewAsyncTask;
|
36 | 36 | }
|
37 | 37 | #endif
|
38 | 38 |
|
39 |
| -UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessage_DefaultOptions(UObject* const WorldContextObject, const FString& Message) |
| 39 | +UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessage_DefaultOptions(UObject* const WorldContextObject, const FString& Message, const TArray<FHttpGPTFunction>& Functions) |
40 | 40 | {
|
41 |
| - return SendMessage_CustomOptions(WorldContextObject, Message, FHttpGPTCommonOptions(), FHttpGPTChatOptions()); |
| 41 | + return SendMessage_CustomOptions(WorldContextObject, Message, Functions, FHttpGPTCommonOptions(), FHttpGPTChatOptions()); |
42 | 42 | }
|
43 | 43 |
|
44 |
| -UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessages_DefaultOptions(UObject* const WorldContextObject, const TArray<FHttpGPTChatMessage>& Messages) |
| 44 | +UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessages_DefaultOptions(UObject* const WorldContextObject, const TArray<FHttpGPTChatMessage>& Messages, const TArray<FHttpGPTFunction>& Functions) |
45 | 45 | {
|
46 |
| - return SendMessages_CustomOptions(WorldContextObject, Messages, FHttpGPTCommonOptions(), FHttpGPTChatOptions()); |
| 46 | + return SendMessages_CustomOptions(WorldContextObject, Messages, Functions, FHttpGPTCommonOptions(), FHttpGPTChatOptions()); |
47 | 47 | }
|
48 | 48 |
|
49 |
| -UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessage_CustomOptions(UObject* const WorldContextObject, const FString& Message, const FHttpGPTCommonOptions CommonOptions, const FHttpGPTChatOptions ChatOptions) |
| 49 | +UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessage_CustomOptions(UObject* const WorldContextObject, const FString& Message, const TArray<FHttpGPTFunction>& Functions, const FHttpGPTCommonOptions CommonOptions, const FHttpGPTChatOptions ChatOptions) |
50 | 50 | {
|
51 |
| - return SendMessages_CustomOptions(WorldContextObject, { FHttpGPTChatMessage(EHttpGPTChatRole::User, Message) }, CommonOptions, ChatOptions); |
| 51 | + return SendMessages_CustomOptions(WorldContextObject, { FHttpGPTChatMessage(EHttpGPTChatRole::User, Message) }, Functions, CommonOptions, ChatOptions); |
52 | 52 | }
|
53 | 53 |
|
54 |
| -UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessages_CustomOptions(UObject* const WorldContextObject, const TArray<FHttpGPTChatMessage>& Messages, const FHttpGPTCommonOptions CommonOptions, const FHttpGPTChatOptions ChatOptions) |
| 54 | +UHttpGPTChatRequest* UHttpGPTChatRequest::SendMessages_CustomOptions(UObject* const WorldContextObject, const TArray<FHttpGPTChatMessage>& Messages, const TArray<FHttpGPTFunction>& Functions, const FHttpGPTCommonOptions CommonOptions, const FHttpGPTChatOptions ChatOptions) |
55 | 55 | {
|
56 | 56 | UHttpGPTChatRequest* const NewAsyncTask = NewObject<UHttpGPTChatRequest>();
|
57 | 57 | NewAsyncTask->Messages = Messages;
|
58 | 58 | NewAsyncTask->CommonOptions = CommonOptions;
|
59 | 59 | NewAsyncTask->ChatOptions = ChatOptions;
|
| 60 | + NewAsyncTask->Functions = Functions; |
60 | 61 |
|
61 | 62 | NewAsyncTask->RegisterWithGameInstance(WorldContextObject);
|
62 | 63 |
|
@@ -86,7 +87,7 @@ bool UHttpGPTChatRequest::CanBindProgress() const
|
86 | 87 |
|
87 | 88 | FString UHttpGPTChatRequest::GetEndpointURL() const
|
88 | 89 | {
|
89 |
| - return FString::Format(TEXT("https://api.openai.com/{0}"), { UHttpGPTHelper::GetEndpointForModel(GetChatOptions().Model).ToString() }); |
| 90 | + return FString::Format(TEXT("{0}/{1}"), { GetCommonOptions().Endpoint, UHttpGPTHelper::GetEndpointForModel(GetChatOptions().Model, GetCommonOptions().bIsAzureOpenAI, GetCommonOptions().AzureOpenAIAPIVersion) }); |
90 | 91 | }
|
91 | 92 |
|
92 | 93 | const FHttpGPTChatOptions UHttpGPTChatRequest::GetChatOptions() const
|
@@ -153,6 +154,17 @@ FString UHttpGPTChatRequest::SetRequestContent()
|
153 | 154 | }
|
154 | 155 |
|
155 | 156 | JsonRequest->SetArrayField("messages", MessagesJson);
|
| 157 | + |
| 158 | + if (!Functions.IsEmpty()) |
| 159 | + { |
| 160 | + TArray<TSharedPtr<FJsonValue>> FunctionsJson; |
| 161 | + for (const FHttpGPTFunction& Iterator : Functions) |
| 162 | + { |
| 163 | + FunctionsJson.Add(Iterator.GetFunction()); |
| 164 | + } |
| 165 | + |
| 166 | + JsonRequest->SetArrayField("functions", FunctionsJson); |
| 167 | + } |
156 | 168 | }
|
157 | 169 | else
|
158 | 170 | {
|
@@ -352,18 +364,50 @@ void UHttpGPTChatRequest::DeserializeSingleResponse(const FString& Content)
|
352 | 364 |
|
353 | 365 | if (const TSharedPtr<FJsonObject>* MessageObj; ChoiceObj->TryGetObjectField("message", MessageObj))
|
354 | 366 | {
|
355 |
| - Choice->Message = FHttpGPTChatMessage(*(*MessageObj)->GetStringField("role"), *(*MessageObj)->GetStringField("content")); |
| 367 | + if (FString RoleStr; (*MessageObj)->TryGetStringField("role", RoleStr)) |
| 368 | + { |
| 369 | + Choice->Message.Role = RoleStr == "user" ? EHttpGPTChatRole::User : EHttpGPTChatRole::Assistant; |
| 370 | + } |
| 371 | + |
| 372 | + if (FString ContentStr; (*MessageObj)->TryGetStringField("content", ContentStr)) |
| 373 | + { |
| 374 | + Choice->Message.Content = ContentStr; |
| 375 | + } |
| 376 | + |
| 377 | + if (const TSharedPtr<FJsonObject>* FunctionObj; (*MessageObj)->TryGetObjectField("function_call", FunctionObj)) |
| 378 | + { |
| 379 | + if (FString FunctionNameStr; (*FunctionObj)->TryGetStringField("name", FunctionNameStr)) |
| 380 | + { |
| 381 | + Choice->Message.FunctionCall.Name = *FunctionNameStr; |
| 382 | + } |
| 383 | + if (FString FunctionArgumentsStr; (*FunctionObj)->TryGetStringField("arguments", FunctionArgumentsStr)) |
| 384 | + { |
| 385 | + Choice->Message.FunctionCall.Arguments = FunctionArgumentsStr; |
| 386 | + } |
| 387 | + } |
356 | 388 | }
|
357 | 389 | else if (const TSharedPtr<FJsonObject>* DeltaObj; ChoiceObj->TryGetObjectField("delta", DeltaObj))
|
358 | 390 | {
|
359 | 391 | if (FString RoleStr; (*DeltaObj)->TryGetStringField("role", RoleStr))
|
360 | 392 | {
|
361 |
| - Choice->Message.Role = RoleStr == "user" ? EHttpGPTChatRole::User : EHttpGPTChatRole::Assistant; |
| 393 | + Choice->Message.Role = UHttpGPTHelper::NameToRole(*RoleStr); |
362 | 394 | }
|
363 | 395 | else if (FString ContentStr; (*DeltaObj)->TryGetStringField("content", ContentStr))
|
364 | 396 | {
|
365 | 397 | Choice->Message.Content += ContentStr;
|
366 | 398 | }
|
| 399 | + |
| 400 | + if (const TSharedPtr<FJsonObject>* FunctionObj; (*DeltaObj)->TryGetObjectField("function_call", FunctionObj)) |
| 401 | + { |
| 402 | + if (FString FunctionNameStr; (*FunctionObj)->TryGetStringField("name", FunctionNameStr)) |
| 403 | + { |
| 404 | + Choice->Message.FunctionCall.Name = *FunctionNameStr; |
| 405 | + } |
| 406 | + if (FString FunctionArgumentsStr; (*FunctionObj)->TryGetStringField("arguments", FunctionArgumentsStr)) |
| 407 | + { |
| 408 | + Choice->Message.FunctionCall.Arguments += FunctionArgumentsStr; |
| 409 | + } |
| 410 | + } |
367 | 411 | }
|
368 | 412 | else if (FString MessageText; ChoiceObj->TryGetStringField("text", MessageText))
|
369 | 413 | {
|
|
0 commit comments