Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#nullable enable

using System.CommandLine;

namespace tryAGI.OpenAI.Cli.GeneratedApi.Commands;

internal sealed record ChatCompletionStreamOptionsVariant1OptionSet(
Option<bool?> IncludeUsage,
Option<bool?> IncludeObfuscation)
{
public static ChatCompletionStreamOptionsVariant1OptionSet Create(string? prefix = null)
{
var normalizedPrefix = string.IsNullOrWhiteSpace(prefix)
? string.Empty
: prefix.Trim().Trim('-') + "-";
return new ChatCompletionStreamOptionsVariant1OptionSet(
IncludeUsage: CliRuntime.CreateNullableBoolOption(name: $"--{normalizedPrefix}include-usage", description: @"If set, an additional chunk will be streamed before the `data: [DONE]`
message. The `usage` field on this chunk shows the token usage statistics
for the entire request, and the `choices` field will always be an empty
array.

All other chunks will also include a `usage` field, but with a null
value. **NOTE:** If the stream is interrupted, you may not receive the
final usage chunk which contains the total token usage for the request.
"),
IncludeObfuscation: CliRuntime.CreateNullableBoolOption(name: $"--{normalizedPrefix}include-obfuscation", description: @"When true, stream obfuscation will be enabled. Stream obfuscation adds
random characters to an `obfuscation` field on streaming delta events to
normalize payload sizes as a mitigation to certain side-channel attacks.
These obfuscation fields are included by default, but add a small amount
of overhead to the data stream. You can set `include_obfuscation` to
false to optimize for bandwidth if you trust the network links between
your application and the OpenAI API.
")
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public static Command Create()
{
var command = new Command(@"completions", @"Completions endpoint commands.");
command.Subcommands.Add(CompletionsCreateCompletionCommandApiCommand.Create());
command.Subcommands.Add(CompletionsCreateCompletionAsStreamCommandApiCommand.Create());
CustomizeCommand(ref command);
return command;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#nullable enable
#pragma warning disable CS0618

using System.CommandLine;

namespace tryAGI.OpenAI.Cli.GeneratedApi.Commands;

internal static partial class CompletionsCreateCompletionAsStreamCommandApiCommand
{
private static Option<global::tryAGI.OpenAI.AnyOf<string, global::tryAGI.OpenAI.CreateCompletionRequestModel?>> Model { get; } = new(
name: @"--model")
{
Description = @"ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.
",
Required = true,
};

private static Option<global::tryAGI.OpenAI.OneOf<string, global::System.Collections.Generic.IList<string>, global::System.Collections.Generic.IList<int>, global::System.Collections.Generic.IList<global::System.Collections.Generic.IList<int>>>?> Prompt { get; } = new(
name: @"--prompt")
{
Description = @"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.
",
};

private static Option<global::System.Collections.Generic.Dictionary<string, int>?> LogitBias { get; } = new(
name: @"--logit-bias")
{
Description = @"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](https://platform.openai.com/tokenizer?view=bpe) 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.
",
};

private static Option<global::tryAGI.OpenAI.StopConfiguration?> Stop { get; } = new(
name: @"--stop")
{
Description = @"Not supported with latest reasoning models `o3` and `o4-mini`.

Up to 4 sequences where the API will stop generating further tokens. The
returned text will not contain the stop sequence.
",
};
private static readonly CreateCompletionRequestOptionSet CreateCompletionRequestOptionSetOptions = CreateCompletionRequestOptionSet.Create();

private static readonly ChatCompletionStreamOptionsVariant1OptionSet StreamOptionsOptions = ChatCompletionStreamOptionsVariant1OptionSet.Create(@"stream");
private static Option<string?> Input { get; } = new(@"--input")
{
Description = "Load request JSON from a file path, '-' for stdin, or an inline JSON object/array string.",
};

private static Option<string?> RequestJson { get; } = new(@"--request-json")
{
Description = "Request body as JSON.",
Hidden = true,
};

private static Option<string?> RequestFile { get; } = new(@"--request-file")
{
Description = "Path to a JSON request file, or '-' for stdin.",
Hidden = true,
};

static partial void CustomizeCommand(ref Command command);

public static Command Create(string? commandName = null)
{
var command = new Command(commandName ?? @"create-completion-as-stream", @"Create completion
Creates a completion for the provided prompt and parameters.

Returns a completion object, or a sequence of completion objects if the request is streamed.
");
command.Options.Add(Model);
command.Options.Add(Prompt);
command.Options.Add(LogitBias);
command.Options.Add(Stop); command.Options.Add(CreateCompletionRequestOptionSetOptions.BestOf);
command.Options.Add(CreateCompletionRequestOptionSetOptions.Echo);
command.Options.Add(CreateCompletionRequestOptionSetOptions.FrequencyPenalty);
command.Options.Add(CreateCompletionRequestOptionSetOptions.Logprobs);
command.Options.Add(CreateCompletionRequestOptionSetOptions.MaxTokens);
command.Options.Add(CreateCompletionRequestOptionSetOptions.N);
command.Options.Add(CreateCompletionRequestOptionSetOptions.PresencePenalty);
command.Options.Add(CreateCompletionRequestOptionSetOptions.Seed);
command.Options.Add(CreateCompletionRequestOptionSetOptions.Suffix);
command.Options.Add(CreateCompletionRequestOptionSetOptions.Temperature);
command.Options.Add(CreateCompletionRequestOptionSetOptions.TopP);
command.Options.Add(CreateCompletionRequestOptionSetOptions.User); command.Options.Add(StreamOptionsOptions.IncludeUsage);
command.Options.Add(StreamOptionsOptions.IncludeObfuscation);
command.Options.Add(Input);
command.Options.Add(RequestJson);
command.Options.Add(RequestFile);
command.Validators.Add(result =>
{
var hasInput = result.GetResult(Input) is not null;
var hasRequestJson = result.GetResult(RequestJson) is not null;
var hasRequestFile = result.GetResult(RequestFile) is not null;
var specifiedCount = (hasInput ? 1 : 0) + (hasRequestJson ? 1 : 0) + (hasRequestFile ? 1 : 0);
if (specifiedCount > 1)
{
result.AddError(@"Specify at most one of --input, --request-json, or --request-file.");
}
});

command.SetAction(async (ParseResult parseResult, CancellationToken cancellationToken) =>
await CliRuntime.RunAsync(async () =>
{
var __requestBase = await CliRuntime.ReadRequestOrDefaultAsync<global::tryAGI.OpenAI.CreateCompletionRequest>(
parseResult,
Input,
RequestJson,
RequestFile,
global::tryAGI.OpenAI.SourceGenerationContext.Default,
cancellationToken).ConfigureAwait(false);
var model = parseResult.GetRequiredValue(Model);
var prompt = CliRuntime.WasSpecified(parseResult, Prompt) ? parseResult.GetValue(Prompt) : (__requestBase is { } __PromptBaseValue ? __PromptBaseValue.Prompt : default);
var logitBias = CliRuntime.WasSpecified(parseResult, LogitBias) ? parseResult.GetValue(LogitBias) : (__requestBase is { } __LogitBiasBaseValue ? __LogitBiasBaseValue.LogitBias : default);
var stop = CliRuntime.WasSpecified(parseResult, Stop) ? parseResult.GetValue(Stop) : (__requestBase is { } __StopBaseValue ? __StopBaseValue.Stop : default); var bestOf = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.BestOf) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.BestOf) : (__requestBase is { } __BestOfBaseValue ? __BestOfBaseValue.BestOf : default);
var echo = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.Echo) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.Echo) : (__requestBase is { } __EchoBaseValue ? __EchoBaseValue.Echo : default);
var frequencyPenalty = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.FrequencyPenalty) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.FrequencyPenalty) : (__requestBase is { } __FrequencyPenaltyBaseValue ? __FrequencyPenaltyBaseValue.FrequencyPenalty : default);
var logprobs = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.Logprobs) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.Logprobs) : (__requestBase is { } __LogprobsBaseValue ? __LogprobsBaseValue.Logprobs : default);
var maxTokens = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.MaxTokens) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.MaxTokens) : (__requestBase is { } __MaxTokensBaseValue ? __MaxTokensBaseValue.MaxTokens : default);
var n = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.N) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.N) : (__requestBase is { } __NBaseValue ? __NBaseValue.N : default);
var presencePenalty = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.PresencePenalty) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.PresencePenalty) : (__requestBase is { } __PresencePenaltyBaseValue ? __PresencePenaltyBaseValue.PresencePenalty : default);
var seed = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.Seed) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.Seed) : (__requestBase is { } __SeedBaseValue ? __SeedBaseValue.Seed : default);
var suffix = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.Suffix) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.Suffix) : (__requestBase is { } __SuffixBaseValue ? __SuffixBaseValue.Suffix : default);
var temperature = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.Temperature) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.Temperature) : (__requestBase is { } __TemperatureBaseValue ? __TemperatureBaseValue.Temperature : default);
var topP = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.TopP) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.TopP) : (__requestBase is { } __TopPBaseValue ? __TopPBaseValue.TopP : default);
var user = CliRuntime.WasSpecified(parseResult, CreateCompletionRequestOptionSetOptions.User) ? parseResult.GetValue(CreateCompletionRequestOptionSetOptions.User) : (__requestBase is { } __UserBaseValue ? __UserBaseValue.User : default);

var __StreamOptionsBase = __requestBase is { } __StreamOptionsBaseValue ? __StreamOptionsBaseValue.StreamOptions : default; var streamOptionsIncludeUsage = CliRuntime.WasSpecified(parseResult, StreamOptionsOptions.IncludeUsage) ? parseResult.GetValue(StreamOptionsOptions.IncludeUsage) : (__StreamOptionsBase is { } __StreamOptionsincludeUsageBaseValue ? __StreamOptionsincludeUsageBaseValue.IncludeUsage : default);
var streamOptionsIncludeObfuscation = CliRuntime.WasSpecified(parseResult, StreamOptionsOptions.IncludeObfuscation) ? parseResult.GetValue(StreamOptionsOptions.IncludeObfuscation) : (__StreamOptionsBase is { } __StreamOptionsincludeObfuscationBaseValue ? __StreamOptionsincludeObfuscationBaseValue.IncludeObfuscation : default);
var __StreamOptionsSpecified = CliRuntime.WasSpecified(parseResult, StreamOptionsOptions.IncludeUsage) || CliRuntime.WasSpecified(parseResult, StreamOptionsOptions.IncludeObfuscation);
var streamOptions =
__StreamOptionsSpecified || __StreamOptionsBase is not null
? new global::tryAGI.OpenAI.ChatCompletionStreamOptionsVariant1
{
IncludeUsage = streamOptionsIncludeUsage,
IncludeObfuscation = streamOptionsIncludeObfuscation,

}
: __StreamOptionsBase;
using var client = await CliRuntime.CreateClientAsync(parseResult, cancellationToken).ConfigureAwait(false);


var response = client.Completions.CreateCompletionAsStreamAsync(
model: model,
prompt: prompt,
logitBias: logitBias,
stop: stop,
bestOf: bestOf,
echo: echo,
frequencyPenalty: frequencyPenalty,
logprobs: logprobs,
maxTokens: maxTokens,
n: n,
presencePenalty: presencePenalty,
seed: seed,
suffix: suffix,
temperature: temperature,
topP: topP,
user: user,
streamOptions: streamOptions,
cancellationToken: cancellationToken);

await foreach (var item in response.WithCancellation(cancellationToken).ConfigureAwait(false))
{
await CliRuntime.WriteResponseLineAsync(
parseResult,
item,
global::tryAGI.OpenAI.SourceGenerationContext.Default,
cancellationToken: cancellationToken).ConfigureAwait(false);
}
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Loading
Loading