diff --git a/Kattbot/Services/KattGpt/ChatGptModels.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionCreateRequest.cs similarity index 63% rename from Kattbot/Services/KattGpt/ChatGptModels.cs rename to Kattbot.Common/Models/KattGpt/ChatCompletionCreateRequest.cs index 3128a90..09ab7e5 100644 --- a/Kattbot/Services/KattGpt/ChatGptModels.cs +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionCreateRequest.cs @@ -1,13 +1,11 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; -namespace Kattbot.Services.KattGpt; +namespace Kattbot.Common.Models.KattGpt; -#pragma warning disable SA1402 // File may only contain a single type public record ChatCompletionCreateRequest { /// - /// Gets or sets iD of the model to use. + /// Gets or sets Id of the model to use. /// https://platform.openai.com/docs/api-reference/chat/create#chat/create-model. /// [JsonPropertyName("model")] @@ -21,7 +19,25 @@ public record ChatCompletionCreateRequest public ChatCompletionMessage[] Messages { get; set; } = null!; /// - /// Gets or sets what sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. + /// Gets or sets a list of functions the model may generate JSON inputs for. + /// https://platform.openai.com/docs/api-reference/chat/create#functions. + /// + [JsonPropertyName("functions")] + public ChatCompletionFunction[]? Functions { get; set; } + + /// + /// Gets or sets the mode for controlling the model responds to function calls. none means the model does not call a function, + /// and responds to the end-user. auto means the model can pick between an end-user or calling a function. + /// Specifying a particular function via {"name": "my_function"} forces the model to call that function. + /// Defaults to "none" when no functions are present and "auto" if functions are present. + /// https://platform.openai.com/docs/api-reference/chat/create#function_call. + /// + [JsonPropertyName("function_call")] + public string? FunctionCall { get; set; } + + /// + /// Gets or sets what sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, + /// while lower values like 0.2 will make it more focused and deterministic. /// We generally recommend altering this or top_p but not both. /// Defaults to 1. /// https://platform.openai.com/docs/api-reference/chat/create#chat/create-temperature. @@ -97,87 +113,3 @@ public record ChatCompletionCreateRequest [JsonPropertyName("user")] public string? User { get; set; } } - -public record ChatCompletionMessage -{ - /// - /// Gets or sets can be either “system”, “user”, or “assistant”. - /// - [JsonPropertyName("role")] - public string Role { get; set; } = null!; - - /// - /// Gets or sets the content of the message. - /// - [JsonPropertyName("content")] - public string Content { get; set; } = null!; - - public static ChatCompletionMessage AsSystem(string content) => new() { Role = "system", Content = content }; - - public static ChatCompletionMessage AsUser(string content) => new() { Role = "user", Content = content }; - - public static ChatCompletionMessage AsAssistant(string content) => new() { Role = "assistant", Content = content }; -} - -public record ChatCompletionCreateResponse -{ - [JsonPropertyName("id")] - public string Id { get; set; } = null!; - - [JsonPropertyName("object")] - public string Object { get; set; } = null!; - - [JsonPropertyName("created")] - public int Created { get; set; } - - [JsonPropertyName("choices")] - public List Choices { get; set; } = new List(); - - [JsonPropertyName("usage")] - public Usage Usage { get; set; } = null!; -} - -public record Usage -{ - [JsonPropertyName("prompt_tokens")] - public int PromptTokens { get; set; } - - [JsonPropertyName("completion_tokens")] - public int CompletionTokens { get; set; } - - [JsonPropertyName("total_tokens")] - public int TotalTokens { get; set; } -} - -public record Choice -{ - [JsonPropertyName("index")] - public int Index { get; set; } - - [JsonPropertyName("message")] - public ChatCompletionMessage Message { get; set; } = null!; - - [JsonPropertyName("finish_reason")] - public string FinishReason { get; set; } = null!; -} - -public record ChatCompletionResponseErrorWrapper -{ - [JsonPropertyName("error")] - public ChatCompletionResponseError Error { get; set; } = null!; -} - -public record ChatCompletionResponseError -{ - [JsonPropertyName("code")] - public string Code { get; set; } = null!; - - [JsonPropertyName("message")] - public string Message { get; set; } = null!; - - [JsonPropertyName("param")] - public string Param { get; set; } = null!; - - [JsonPropertyName("type")] - public string Type { get; set; } = null!; -} diff --git a/Kattbot.Common/Models/KattGpt/ChatCompletionCreateResponse.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionCreateResponse.cs new file mode 100644 index 0000000..411d36b --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionCreateResponse.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record ChatCompletionCreateResponse +{ + [JsonPropertyName("id")] + public string Id { get; set; } = null!; + + [JsonPropertyName("object")] + public string Object { get; set; } = null!; + + [JsonPropertyName("created")] + public int Created { get; set; } + + [JsonPropertyName("choices")] + public List Choices { get; set; } = new List(); + + [JsonPropertyName("usage")] + public Usage Usage { get; set; } = null!; +} diff --git a/Kattbot.Common/Models/KattGpt/ChatCompletionFunction.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionFunction.cs new file mode 100644 index 0000000..825b681 --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionFunction.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record ChatCompletionFunction +{ + /// + /// Gets or sets the name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. + /// https://platform.openai.com/docs/api-reference/chat/create#functions-name. + /// + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + /// + /// Gets or sets a description of what the function does, used by the model to choose when and how to call the function. + /// https://platform.openai.com/docs/api-reference/chat/create#functions-description. + /// + [JsonPropertyName("description")] + public string? Description { get; set; } + + /// + /// Gets or sets the parameters the functions accepts, described as a JSON Schema object. + /// https://platform.openai.com/docs/api-reference/chat/create#functions-parameters. + /// + [JsonPropertyName("parameters")] + public JsonObject Parameters { get; set; } = null!; +} diff --git a/Kattbot.Common/Models/KattGpt/ChatCompletionMessage.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionMessage.cs new file mode 100644 index 0000000..4a9c773 --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionMessage.cs @@ -0,0 +1,71 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record ChatCompletionMessage +{ + public ChatCompletionMessage(string role, string? content) + { + Role = role; + Content = content; + } + + public ChatCompletionMessage(string role, string name, string content) + { + Role = role; + Name = name; + Content = content; + } + + [JsonConstructor] + public ChatCompletionMessage(string role, string name, string? content, FunctionCall? functionCall) + : this(role, content) + { + FunctionCall = functionCall; + Name = name; + } + + /// + /// Gets the role of the messages author. One of system, user, assistant, or function. + /// https://platform.openai.com/docs/api-reference/chat/create#messages-role. + /// + [JsonPropertyName("role")] + public string Role { get; } = null!; + + /// + /// Gets or sets the contents of the message. content is required for all messages, and may be null for assistant messages with function calls. + /// https://platform.openai.com/docs/api-reference/chat/create#messages-content. + /// + [JsonPropertyName("content")] + public string? Content { get; set; } // This should be private but the api is being weird and doesn't allow nulls like it says it does + + /// + /// Gets the name of the author of this message. name is required if role is function, and it should be the name of the function whose response is in the content. + /// May contain a-z, A-Z, 0-9, and underscores, with a maximum length of 64 characters. + /// https://platform.openai.com/docs/api-reference/chat/create#messages-name. + /// + [JsonPropertyName("name")] + public string? Name { get; } + + /// + /// Gets the name and arguments of a function that should be called, as generated by the model. + /// https://platform.openai.com/docs/api-reference/chat/create#messages-function_call. + /// + [JsonPropertyName("function_call")] + public FunctionCall? FunctionCall { get; } + + public static ChatCompletionMessage AsSystem(string content) => new("system", content); + + public static ChatCompletionMessage AsUser(string content) => new("user", content); + + public static ChatCompletionMessage AsAssistant(string content) => new("assistant", content); + + /// + /// Builds a message as a function call which contains the function result to be added to the context. + /// + /// The name of the function. + /// The result of the function. + /// A . + public static ChatCompletionMessage AsFunctionCallResult(string name, string content) + => new("function", name, content); +} diff --git a/Kattbot.Common/Models/KattGpt/ChatCompletionResponseError.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionResponseError.cs new file mode 100644 index 0000000..088a56b --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionResponseError.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record ChatCompletionResponseError +{ + [JsonPropertyName("code")] + public string Code { get; set; } = null!; + + [JsonPropertyName("message")] + public string Message { get; set; } = null!; + + [JsonPropertyName("param")] + public string Param { get; set; } = null!; + + [JsonPropertyName("type")] + public string Type { get; set; } = null!; +} diff --git a/Kattbot.Common/Models/KattGpt/ChatCompletionResponseErrorWrapper.cs b/Kattbot.Common/Models/KattGpt/ChatCompletionResponseErrorWrapper.cs new file mode 100644 index 0000000..85ea519 --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/ChatCompletionResponseErrorWrapper.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record ChatCompletionResponseErrorWrapper +{ + [JsonPropertyName("error")] + public ChatCompletionResponseError Error { get; set; } = null!; +} diff --git a/Kattbot.Common/Models/KattGpt/Choice.cs b/Kattbot.Common/Models/KattGpt/Choice.cs new file mode 100644 index 0000000..3168aac --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/Choice.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record Choice +{ + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("message")] + public ChatCompletionMessage Message { get; set; } = null!; + + [JsonPropertyName("finish_reason")] + public string FinishReason { get; set; } = null!; +} diff --git a/Kattbot.Common/Models/KattGpt/FunctionCall.cs b/Kattbot.Common/Models/KattGpt/FunctionCall.cs new file mode 100644 index 0000000..5f0e068 --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/FunctionCall.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record FunctionCall +{ + public FunctionCall(string name, string arguments) + { + Name = name; + Arguments = arguments; + } + + [JsonPropertyName("name")] + public string Name { get; } + + [JsonPropertyName("arguments")] + public string Arguments { get; } +} diff --git a/Kattbot.Common/Models/KattGpt/Usage.cs b/Kattbot.Common/Models/KattGpt/Usage.cs new file mode 100644 index 0000000..78a6333 --- /dev/null +++ b/Kattbot.Common/Models/KattGpt/Usage.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace Kattbot.Common.Models.KattGpt; + +public record Usage +{ + [JsonPropertyName("prompt_tokens")] + public int PromptTokens { get; set; } + + [JsonPropertyName("completion_tokens")] + public int CompletionTokens { get; set; } + + [JsonPropertyName("total_tokens")] + public int TotalTokens { get; set; } +} diff --git a/Kattbot/Attributes/BaseCommandCheck.cs b/Kattbot/Attributes/BaseCommandCheck.cs index 4766d93..f8c1f52 100644 --- a/Kattbot/Attributes/BaseCommandCheck.cs +++ b/Kattbot/Attributes/BaseCommandCheck.cs @@ -1,36 +1,22 @@ -using DSharpPlus.CommandsNext; +using System.Threading.Tasks; +using DSharpPlus.CommandsNext; using DSharpPlus.CommandsNext.Attributes; using DSharpPlus.Entities; -using Kattbot; -using Kattbot.Services; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Kattbot.Attributes { /// - /// Reject commands coming from DM + /// Reject commands coming from DM. /// public class BaseCommandCheck : CheckBaseAttribute { public override Task ExecuteCheckAsync(CommandContext ctx, bool help) { - var message = ctx.Message; var channel = ctx.Channel; - if (IsPrivateMessageChannel(channel)) - return Task.FromResult(false); + bool allowCommand = !channel.IsPrivate; - return Task.FromResult(true); - } - - private bool IsPrivateMessageChannel(DiscordChannel channel) - { - return channel.IsPrivate; + return Task.FromResult(allowCommand); } } } diff --git a/Kattbot/BotOptions.cs b/Kattbot/BotOptions.cs deleted file mode 100644 index 8eaf7b5..0000000 --- a/Kattbot/BotOptions.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; - -namespace Kattbot; - -#pragma warning disable SA1402 // File may only contain a single type -public record BotOptions -{ - public const string OptionsKey = "Kattbot"; - - public string CommandPrefix { get; set; } = null!; - - public string AlternateCommandPrefix { get; set; } = null!; - - public string ConnectionString { get; set; } = null!; - - public string BotToken { get; set; } = null!; - - public ulong ErrorLogGuildId { get; set; } - - public ulong ErrorLogChannelId { get; set; } - - public string OpenAiApiKey { get; set; } = null!; -} - -public record KattGptOptions -{ - public const string OptionsKey = "KattGpt"; - - public string[] CoreSystemPrompts { get; set; } = Array.Empty(); - - public GuildOptions[] GuildOptions { get; set; } = Array.Empty(); - - public Template[] Templates { get; set; } = Array.Empty