Files
UE5-cyberHuman/Plugins/OpenAi/Source/OpenAI/Public/Provider/OpenAIProvider.h
2025-04-07 18:31:41 -07:00

423 lines
20 KiB
C++

// OpenAI, Copyright LifeEXE. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "HTTP.h"
#include "ResponseTypes.h"
#include "RequestTypes.h"
#include "Types/AudioTypes.h"
#include "Delegates.h"
#include "FuncLib/OpenAIFuncLib.h"
#include "OpenAIProvider.generated.h"
class FJsonObject;
namespace OpenAI
{
class IAPI;
}
UCLASS()
class OPENAI_API UOpenAIProvider : public UObject
{
GENERATED_BODY()
public:
UOpenAIProvider();
void SetAPI(const TSharedPtr<OpenAI::IAPI>& API);
public:
/**
Lists the currently available models, and provides basic information about each one such as the owner and availability.
https://platform.openai.com/docs/api-reference/models/list
*/
void ListModels(const FOpenAIAuth& Auth);
/**
Retrieves a model instance, providing basic information about the model such as the owner and permissioning.
https://platform.openai.com/docs/api-reference/models/retrieve
*/
void RetrieveModel(const FString& ModelName, const FOpenAIAuth& Auth);
/**
Creates a completion for the provided prompt and parameters.
https://platform.openai.com/docs/api-reference/completions/create
*/
void CreateCompletion(const FCompletion& Completion, const FOpenAIAuth& Auth);
/**
Creates a completion for the chat message.
https://platform.openai.com/docs/api-reference/chat/create
*/
void CreateChatCompletion(const FChatCompletion& Completion, const FOpenAIAuth& Auth);
/**
Creates an image given a prompt.
https://platform.openai.com/docs/api-reference/images/create
*/
void CreateImage(const FOpenAIImage& Image, const FOpenAIAuth& Auth);
/**
Creates an edited or extended image given an original image and a prompt.
https://platform.openai.com/docs/api-reference/images/create-edit
*/
void CreateImageEdit(const FOpenAIImageEdit& ImageEdit, const FOpenAIAuth& Auth);
/**
Creates a variation of a given image.
https://platform.openai.com/docs/api-reference/images/create-variation
*/
void CreateImageVariation(const FOpenAIImageVariation& ImageVariation, const FOpenAIAuth& Auth);
/**
Creates an embedding vector representing the input text.
https://platform.openai.com/docs/api-reference/embeddings/create
*/
void CreateEmbeddings(const FEmbeddings& Embeddings, const FOpenAIAuth& Auth);
/**
Generates audio from the input text.
https://platform.openai.com/docs/api-reference/audio/createSpeech
*/
void CreateSpeech(const FSpeech& Speech, const FOpenAIAuth& Auth);
/**
Transcribes audio into the input language.
https://platform.openai.com/docs/api-reference/audio/create
*/
void CreateAudioTranscription(const FAudioTranscription& AudioTranscription, const FOpenAIAuth& Auth);
/**
Translates audio into into English.
https://platform.openai.com/docs/api-reference/audio/create
*/
void CreateAudioTranslation(const FAudioTranslation& AudioTranslation, const FOpenAIAuth& Auth);
/**
Returns a list of files that belong to the user's organization.
https://platform.openai.com/docs/api-reference/files/list
*/
void ListFiles(const FOpenAIAuth& Auth);
/**
Upload a file that contains document(s) to be used across various endpoints/features.
Currently, the size of all the files uploaded by one organization can be up to 1 GB.
Please contact us if you need to increase the storage limit.
https://platform.openai.com/docs/api-reference/files/upload
*/
void UploadFile(const FUploadFile& UploadFile, const FOpenAIAuth& Auth);
/**
Delete a file.
https://platform.openai.com/docs/api-reference/files/delete
*/
void DeleteFile(const FString& FileID, const FOpenAIAuth& Auth);
/**
Returns information about a specific file.
https://platform.openai.com/docs/api-reference/files/retrieve
*/
void RetrieveFile(const FString& FileID, const FOpenAIAuth& Auth);
/**
Returns the contents of the specified file.
https://platform.openai.com/docs/api-reference/files/retrieve-content
*/
void RetrieveFileContent(const FString& FileID, const FOpenAIAuth& Auth);
/**
Delete a fine-tuned model. You must have the Owner role in your organization.
https://platform.openai.com/docs/api-reference/fine-tunes/delete-model
*/
void DeleteFineTunedModel(const FString& ModelID, const FOpenAIAuth& Auth);
/**
Classifies if text violates OpenAI's Content Policy
https://platform.openai.com/docs/api-reference/moderations/create
*/
void CreateModerations(const FModerations& Moderations, const FOpenAIAuth& Auth);
/**
List your organization's fine-tuning jobs.
https://platform.openai.com/docs/api-reference/fine-tuning/list
*/
void ListFineTuningJobs(const FOpenAIAuth& Auth, const FFineTuningQueryParameters& FineTuningQueryParameters = {});
/**
Creates a job that fine-tunes a specified model from a given dataset.
Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete.
https://platform.openai.com/docs/api-reference/fine-tuning/create
*/
void CreateFineTuningJob(const FFineTuningJob& FineTuningJob, const FOpenAIAuth& Auth);
/**
Get info about a fine-tuning job.
https://platform.openai.com/docs/api-reference/fine-tuning/retrieve
*/
void RetrieveFineTuningJob(const FString& FineTuningJobID, const FOpenAIAuth& Auth);
/**
Immediately cancel a fine-tune job.
https://platform.openai.com/docs/api-reference/fine-tuning/cancel
*/
void CancelFineTuningJob(const FString& FineTuneID, const FOpenAIAuth& Auth);
/**
Get status updates for a fine-tuning job.
https://platform.openai.com/docs/api-reference/fine-tuning/list-events
*/
void ListFineTuningEvents(
const FString& FineTuningJobID, const FOpenAIAuth& Auth, const FFineTuningQueryParameters& FineTuningQueryParameters = {});
/**
Print response to console
*/
void SetLogEnabled(bool LogEnabled) { bLogEnabled = LogEnabled; }
public:
FOnRequestError& OnRequestError() { return RequestError; };
FOnListModelsCompleted& OnListModelsCompleted() { return ListModelsCompleted; }
FOnRetrieveModelCompleted& OnRetrieveModelCompleted() { return RetrieveModelCompleted; }
FOnCreateCompletionCompleted& OnCreateCompletionCompleted() { return CreateCompletionCompleted; }
FOnCreateCompletionStreamCompleted& OnCreateCompletionStreamCompleted() { return CreateCompletionStreamCompleted; }
FOnCreateCompletionStreamProgresses& OnCreateCompletionStreamProgresses() { return CreateCompletionStreamProgresses; }
FOnCreateChatCompletionCompleted& OnCreateChatCompletionCompleted() { return CreateChatCompletionCompleted; }
FOnCreateChatCompletionStreamCompleted& OnCreateChatCompletionStreamCompleted() { return CreateChatCompletionStreamCompleted; }
FOnCreateChatCompletionStreamCompleted& OnCreateChatCompletionStreamProgresses() { return CreateChatCompletionStreamProgresses; }
FOnCreateImageCompleted& OnCreateImageCompleted() { return CreateImageCompleted; }
FOnCreateImageEditCompleted& OnCreateImageEditCompleted() { return CreateImageEditCompleted; }
FOnCreateImageVariationCompleted& OnCreateImageVariationCompleted() { return CreateImageVariationCompleted; }
FOnCreateEmbeddingsCompleted& OnCreateEmbeddingsCompleted() { return CreateEmbeddingsCompleted; }
FOnCreateSpeechCompleted& OnCreateSpeechCompleted() { return CreateSpeechCompleted; }
FOnCreateAudioTranscriptionCompleted& OnCreateAudioTranscriptionCompleted() { return CreateAudioTranscriptionCompleted; }
FOnCreateAudioTranslationCompleted& OnCreateAudioTranslationCompleted() { return CreateAudioTranslationCompleted; }
FOnListFilesCompleted& OnListFilesCompleted() { return ListFilesCompleted; }
FOnUploadFileCompleted& OnUploadFileCompleted() { return UploadFileCompleted; }
FOnDeleteFileCompleted& OnDeleteFileCompleted() { return DeleteFileCompleted; }
FOnRetrieveFileCompleted& OnRetrieveFileCompleted() { return RetrieveFileCompleted; }
FOnRetrieveFileContentCompleted& OnRetrieveFileContentCompleted() { return RetrieveFileContentCompleted; }
FOnListFineTuneEventsCompleted& OnListFineTuneEventsCompleted() { return ListFineTuneEventsCompleted; }
FOnDeleteFineTunedModelCompleted& OnDeleteFineTunedModelCompleted() { return DeleteFineTunedModelCompleted; }
FOnCreateModerationsCompleted& OnCreateModerationsCompleted() { return CreateModerationsCompleted; }
FOnListFineTuningJobsCompleted& OnListFineTuningJobsCompleted() { return ListFineTuningJobsCompleted; }
FOnCreateFineTuningJobCompleted& OnCreateFineTuningJobCompleted() { return CreateFineTuningJobCompleted; }
FOnRetrieveFineTuningJobCompleted& OnRetrieveFineTuningJobCompleted() { return RetrieveFineTuningJobCompleted; }
FOnCancelFineTuningJobCompleted& OnCancelFineTuningJobCompleted() { return CancelFineTuningJobCompleted; }
FOnListFineTuningEventsCompleted& OnListFineTuningEventsCompleted() { return ListFineTuningEventsCompleted; }
private:
TSharedPtr<OpenAI::IAPI> API;
bool bLogEnabled{true};
FOnRequestError RequestError;
FOnListModelsCompleted ListModelsCompleted;
FOnRetrieveModelCompleted RetrieveModelCompleted;
FOnCreateCompletionCompleted CreateCompletionCompleted;
FOnCreateCompletionStreamCompleted CreateCompletionStreamCompleted;
FOnCreateCompletionStreamProgresses CreateCompletionStreamProgresses;
FOnCreateChatCompletionCompleted CreateChatCompletionCompleted;
FOnCreateChatCompletionStreamCompleted CreateChatCompletionStreamCompleted;
FOnCreateChatCompletionStreamProgresses CreateChatCompletionStreamProgresses;
FOnCreateImageCompleted CreateImageCompleted;
FOnCreateImageEditCompleted CreateImageEditCompleted;
FOnCreateImageVariationCompleted CreateImageVariationCompleted;
FOnCreateEmbeddingsCompleted CreateEmbeddingsCompleted;
FOnCreateSpeechCompleted CreateSpeechCompleted;
FOnCreateAudioTranscriptionCompleted CreateAudioTranscriptionCompleted;
FOnCreateAudioTranslationCompleted CreateAudioTranslationCompleted;
FOnListFilesCompleted ListFilesCompleted;
FOnUploadFileCompleted UploadFileCompleted;
FOnDeleteFileCompleted DeleteFileCompleted;
FOnRetrieveFileCompleted RetrieveFileCompleted;
FOnRetrieveFileContentCompleted RetrieveFileContentCompleted;
FOnListFineTuneEventsCompleted ListFineTuneEventsCompleted;
FOnDeleteFineTunedModelCompleted DeleteFineTunedModelCompleted;
FOnCreateModerationsCompleted CreateModerationsCompleted;
FOnListFineTuningJobsCompleted ListFineTuningJobsCompleted;
FOnCreateFineTuningJobCompleted CreateFineTuningJobCompleted;
FOnRetrieveFineTuningJobCompleted RetrieveFineTuningJobCompleted;
FOnCancelFineTuningJobCompleted CancelFineTuningJobCompleted;
FOnListFineTuningEventsCompleted ListFineTuningEventsCompleted;
virtual void OnListModelsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnRetrieveModelCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateCompletionCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateCompletionStreamCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateCompletionStreamProgress(FHttpRequestPtr Request, int32 BytesSent, int32 BytesReceived);
virtual void OnCreateChatCompletionCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateChatCompletionStreamCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateChatCompletionStreamProgress(FHttpRequestPtr Request, int32 BytesSent, int32 BytesReceived);
virtual void OnCreateImageCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateImageEditCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateImageVariationCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateEmbeddingsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateSpeechCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateAudioTranscriptionCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateAudioTranslationCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnListFilesCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnUploadFileCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnDeleteFileCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnRetrieveFileCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnRetrieveFileContentCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnListFineTuneEventsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnDeleteFineTunedModelCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateModerationsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnListFineTuningJobsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCreateFineTuningJobCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnRetrieveFineTuningJobCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnCancelFineTuningJobCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
virtual void OnListFineTuningEventsCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful);
void ProcessRequest(FHttpRequestRef HttpRequest);
bool ParseImageRequest(FHttpResponsePtr Response, FImageResponse& ImageResponse);
bool Success(FHttpResponsePtr Response, bool WasSuccessful);
void LogResponse(FHttpResponsePtr Response);
void LogError(const FString& ErrorText);
template <typename OutStructType>
FString SerializeRequest(const OutStructType& OutStruct) const
{
TSharedPtr<FJsonObject> Json = FJsonObjectConverter::UStructToJsonObject(OutStruct);
FString RequestBodyStr;
UOpenAIFuncLib::JsonToString(Json, RequestBodyStr);
return RequestBodyStr;
}
template <typename OutStructType>
FHttpRequestRef MakeRequest(const OutStructType& OutStruct, const FString& URL, const FString& Method, const FOpenAIAuth& Auth) const
{
auto HttpRequest = CreateRequest();
HttpRequest->SetHeader("Content-Type", "application/json");
HttpRequest->SetHeader("Authorization", FString("Bearer ").Append(Auth.APIKey));
HttpRequest->SetHeader("OpenAI-Organization", Auth.OrganizationID);
HttpRequest->SetHeader("OpenAI-Project", Auth.ProjectID);
HttpRequest->SetURL(URL);
HttpRequest->SetVerb(Method);
HttpRequest->SetContentAsString(SerializeRequest(OutStruct));
return HttpRequest;
}
// specializations
FHttpRequestRef MakeRequest(const FString& URL, const FString& Method, const FOpenAIAuth& Auth) const;
FHttpRequestRef MakeRequest(
const FChatCompletion& ChatCompletion, const FString& URL, const FString& Method, const FOpenAIAuth& Auth) const;
template <typename ParsedResponseType, typename DelegateType>
void HandleResponse(FHttpResponsePtr Response, bool WasSuccessful, DelegateType& Delegate)
{
if (!Success(Response, WasSuccessful)) return;
ParsedResponseType ParsedResponse;
if (UOpenAIFuncLib::ParseJSONToStruct(Response->GetContentAsString(), &ParsedResponse))
{
Delegate.Broadcast(ParsedResponse);
}
else
{
LogError("JSON deserialization error");
RequestError.Broadcast(Response->GetURL(), Response->GetContentAsString());
}
}
virtual TSharedRef<IHttpRequest, ESPMode::ThreadSafe> CreateRequest() const { return FHttpModule::Get().CreateRequest(); }
private:
void SetOptional(TSharedPtr<FJsonObject> RequestBody, const TOptional<FString>& Param, const FString& ParamName);
void SetOptional(TSharedPtr<FJsonObject> RequestBody, const TOptional<bool>& Param, const FString& ParamName);
void SetOptional(TSharedPtr<FJsonObject> RequestBody, const TOptional<TArray<float>>& Param, const FString& ParamName);
template <typename NumberType>
void SetOptional(TSharedPtr<FJsonObject> RequestBody, const TOptional<NumberType>& Param, const FString& ParamName)
{
if (!Param.IsSet()) return;
RequestBody->SetNumberField(ParamName, Param.GetValue());
}
private:
TTuple<FString, FString> GetErrorData(FHttpRequestPtr Request, FHttpResponsePtr Response) const;
bool HandleString(FString& IncomeString, bool& LastString) const;
template <typename ResponseType>
bool ParseStreamRequest(FHttpResponsePtr Response, TArray<ResponseType>& Responses)
{
if (!Response) return false;
TArray<FString> StringArray;
Response->GetContentAsString().ParseIntoArrayLines(StringArray);
for (auto& String : StringArray)
{
bool LastString{false};
if (HandleString(String, LastString))
{
if (LastString)
{
break;
}
ResponseType ParsedResponse;
if (!UOpenAIFuncLib::ParseJSONToStruct(String, &ParsedResponse)) continue;
Responses.Add(ParsedResponse);
}
}
return true;
}
template <typename ResponseType, typename DelegateType>
void OnStreamProgress(FHttpRequestPtr Request, int32 BytesSent, int32 BytesReceived, DelegateType& Delegate)
{
const auto& Response = Request->GetResponse();
TArray<ResponseType> ParsedResponses;
if (ParseStreamRequest(Response, ParsedResponses))
{
LogResponse(Response);
Delegate.Broadcast(ParsedResponses);
}
else if (Response)
{
LogError(Response->GetContentAsString());
// RequestError.Broadcast(Response->GetURL(), Response->GetContentAsString());
}
else if (BytesReceived == 0)
{
// UE_5.3: on some reason OnRequestProgress() sends first time with Request = nullptr
// BytesReceived = 0 in this case, empty initial call ?
// Remove error message from log because nothing bad happened
}
else
{
LogError(FString::Format(TEXT("JSON deserialization error BytesSent:{0} BytesReceived:{1}"), {BytesSent, BytesReceived}));
}
}
template <typename ResponseType, typename DelegateType>
void OnStreamCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool WasSuccessful, DelegateType& Delegate)
{
if (!WasSuccessful)
{
const auto& [URL, Content] = GetErrorData(Request, Response);
LogError(Content);
RequestError.Broadcast(URL, Content);
return;
}
TArray<ResponseType> ParsedResponses;
if (ParseStreamRequest(Response, ParsedResponses))
{
LogResponse(Response);
Delegate.Broadcast(ParsedResponses);
}
else
{
LogError("JSON deserialization error");
LogError(Response->GetContentAsString());
RequestError.Broadcast(Response->GetURL(), Response->GetContentAsString());
}
}
void CleanChatCompletionFieldsThatCantBeEmpty(const FChatCompletion& ChatCompletion, TSharedPtr<FJsonObject>& Json) const;
};