unit OpenAI.Completions; interface uses System.SysUtils, System.Classes, OpenAI.API.Params, OpenAI.API, System.JSON; type TCompletionParams = class(TJSONParam) /// /// ID of the model to use. You can use the List models API to see all of your available models, /// or see our Model overview for descriptions of them. /// function Model(const Value: string): TCompletionParams; /// /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. /// Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. /// function Prompt(const Value: string): TCompletionParams; overload; /// /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. /// Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. /// function Prompt(const Value: TArray): TCompletionParams; overload; /// /// The suffix that comes after a completion of inserted text. /// function Suffix(const Value: string = ''): TCompletionParams; overload; /// /// The maximum number of tokens to generate in the completion. /// The token count of your prompt plus max_tokens cannot exceed the model's context length. /// Most models have a context length of 2048 tokens (except for the newest models, which support 4096). /// function MaxTokens(const Value: Integer = 16): TCompletionParams; /// /// What sampling temperature to use. Higher values means the model will take more risks. /// Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer. /// We generally recommend altering this or top_p but not both. /// function Temperature(const Value: Single = 1): TCompletionParams; /// /// An alternative to sampling with temperature, called nucleus sampling, /// where the model considers the results of the tokens with top_p probability mass. /// So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or temperature but not both. /// function TopP(const Value: Single = 1): TCompletionParams; /// /// How many completions to generate for each prompt. /// Note: Because this parameter generates many completions, it can quickly consume your token quota. /// Use carefully and ensure that you have reasonable settings for max_tokens and stop. /// function N(const Value: Integer = 1): TCompletionParams; /// /// Whether to stream back partial progress. /// If set, tokens will be sent as data-only server-sent events as they become available, /// with the stream terminated by a data: [DONE] message. /// function Stream(const Value: Boolean = True): TCompletionParams; /// /// Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. /// For example, if logprobs is 5, the API will return a list of the 5 most likely tokens. /// The API will always return the logprob of the sampled token, so there may be up to logprobs+1 elements in the response. /// The maximum value for logprobs is 5. If you need more than this, please contact us through our Help center and /// describe your use case. /// function LogProbs(const Value: Integer): TCompletionParams; /// /// Echo back the prompt in addition to the completion /// function Echo(const Value: Boolean = True): TCompletionParams; /// /// Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. /// function Stop(const Value: string): TCompletionParams; overload; /// /// Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. /// function Stop(const Value: TArray): TCompletionParams; overload; /// /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, /// increasing the model's likelihood to talk about new topics. /// function PresencePenalty(const Value: Single = 0): TCompletionParams; /// /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, /// decreasing the model's likelihood to repeat the same line verbatim. /// function FrequencyPenalty(const Value: Single = 0): TCompletionParams; /// /// Generates best_of completions server-side and returns the "best" (the one with the highest log probability per token). /// Results cannot be streamed. /// When used with n, best_of controls the number of candidate completions and n specifies how many to return – best_of must be greater than n. /// Note: Because this parameter generates many completions, it can quickly consume your token quota. /// Use carefully and ensure that you have reasonable settings for max_tokens and stop /// function BestOf(const Value: Integer = 1): TCompletionParams; /// /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse /// function User(const Value: string): TCompletionParams; /// /// Modify the likelihood of specified tokens appearing in the completion. /// /// Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias /// value from -100 to 100. You can use this tokenizer tool (which works for both GPT-2 and GPT-3) to convert text to /// token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. /// The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; /// values like -100 or 100 should result in a ban or exclusive selection of the relevant token. /// /// As an example, you can pass {"50256": -100} to prevent the <|endoftext|> token from being generated. /// function LogitBias(const Value: TJSONObject): TCompletionParams; constructor Create; override; end; TCompletionUsage = class private FCompletion_tokens: Int64; FPrompt_tokens: Int64; FTotal_tokens: Int64; public property CompletionTokens: Int64 read FCompletion_tokens write FCompletion_tokens; property PromptTokens: Int64 read FPrompt_tokens write FPrompt_tokens; property TotalTokens: Int64 read FTotal_tokens write FTotal_tokens; end; TCompletionChoices = class private FFinish_reason: string; FIndex: Int64; FText: string; public property FinishReason: string read FFinish_reason write FFinish_reason; //property Logprobs: string read FFinish_reason write FFinish_reason; property Index: Int64 read FIndex write FIndex; property Text: string read FText write FText; end; TCompletions = class private FChoices: TArray; FCreated: Int64; FId: string; FModel: string; FObject: string; FUsage: TCompletionUsage; public property Choices: TArray read FChoices write FChoices; property Created: Int64 read FCreated write FCreated; property Id: string read FId write FId; property Model: string read FModel write FModel; property &Object: string read FObject write FObject; property Usage: TCompletionUsage read FUsage write FUsage; destructor Destroy; override; end; TCompletionEvent = reference to procedure(Completions: TCompletions; IsDone: Boolean; var Cancel: Boolean); TCompletionsRoute = class(TOpenAIAPIRoute) public /// /// Creates a completion for the provided prompt and parameters /// function Create(ParamProc: TProc): TCompletions; /// /// Creates a completion for the provided prompt and parameters (for Stream is true parameter) /// function CreateStream(ParamProc: TProc; Event: TCompletionEvent): Boolean; end; implementation uses REST.Json, System.Net.HttpClient; { TCompletionsRoute } function TCompletionsRoute.Create(ParamProc: TProc): TCompletions; begin Result := API.Post('completions', ParamProc); end; function TCompletionsRoute.CreateStream(ParamProc: TProc; Event: TCompletionEvent): Boolean; var Response: TStringStream; RetPos: Integer; begin Response := TStringStream.Create('', TEncoding.UTF8); try RetPos := 0; Result := API.Post('completions', ParamProc, Response, TReceiveDataCallback(procedure(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var AAbort: Boolean) var IsDone: Boolean; Data: string; Completions: TCompletions; TextBuffer: string; Line: string; Ret: Integer; begin TextBuffer := Response.DataString; repeat Ret := TextBuffer.IndexOf(#10, RetPos); if Ret >= 0 then begin Line := TextBuffer.Substring(RetPos, Ret - RetPos); RetPos := Ret + 1; if Line.IsEmpty or (Line.StartsWith(#10)) then Continue; Completions := nil; Data := Line.Replace('data: ', '').Trim([' ', #13, #10]); IsDone := Data = '[DONE]'; if not IsDone then begin try Completions := TJson.JsonToObject(Data); except Completions := nil; end; end; try Event(Completions, IsDone, AAbort); finally if Assigned(Completions) then Completions.Free; end; end; until Ret < 0; end)); finally Response.Free; end; end; { TCompletions } destructor TCompletions.Destroy; var Item: TCompletionChoices; begin if Assigned(FUsage) then FUsage.Free; for Item in FChoices do if Assigned(Item) then Item.Free; inherited; end; { TCompletionParams } function TCompletionParams.BestOf(const Value: Integer): TCompletionParams; begin Result := TCompletionParams(Add('best_of', Value)); end; constructor TCompletionParams.Create; begin inherited; Model('text-davinci-003'); Temperature(0); end; function TCompletionParams.Echo(const Value: Boolean): TCompletionParams; begin Result := TCompletionParams(Add('echo', Value)); end; function TCompletionParams.FrequencyPenalty(const Value: Single): TCompletionParams; begin Result := TCompletionParams(Add('frequency_penalty', Value)); end; function TCompletionParams.LogitBias(const Value: TJSONObject): TCompletionParams; begin Result := TCompletionParams(Add('logit_bias', Value)); end; function TCompletionParams.LogProbs(const Value: Integer): TCompletionParams; begin Result := TCompletionParams(Add('logprobs', Value)); end; function TCompletionParams.MaxTokens(const Value: Integer): TCompletionParams; begin Result := TCompletionParams(Add('max_tokens', Value)); end; function TCompletionParams.Model(const Value: string): TCompletionParams; begin Result := TCompletionParams(Add('model', Value)); end; function TCompletionParams.N(const Value: Integer): TCompletionParams; begin Result := TCompletionParams(Add('n', Value)); end; function TCompletionParams.PresencePenalty(const Value: Single): TCompletionParams; begin Result := TCompletionParams(Add('presence_penalty', Value)); end; function TCompletionParams.Prompt(const Value: string): TCompletionParams; begin Result := TCompletionParams(Add('prompt', Value)); end; function TCompletionParams.Prompt(const Value: TArray): TCompletionParams; begin Result := TCompletionParams(Add('prompt', Value)); end; function TCompletionParams.Stop(const Value: TArray): TCompletionParams; begin Result := TCompletionParams(Add('stop', Value)); end; function TCompletionParams.Stop(const Value: string): TCompletionParams; begin Result := TCompletionParams(Add('stop', Value)); end; function TCompletionParams.Stream(const Value: Boolean): TCompletionParams; begin Result := TCompletionParams(Add('stream', Value)); end; function TCompletionParams.Suffix(const Value: string): TCompletionParams; begin Result := TCompletionParams(Add('suffix', Value)); end; function TCompletionParams.Temperature(const Value: Single): TCompletionParams; begin Result := TCompletionParams(Add('temperature', Value)); end; function TCompletionParams.TopP(const Value: Single): TCompletionParams; begin Result := TCompletionParams(Add('top_p', Value)); end; function TCompletionParams.User(const Value: string): TCompletionParams; begin Result := TCompletionParams(Add('user', Value)); end; end.