diff --git a/src/App/Extensions/CosmosDbServiceActivityExtensions.cs b/src/App/Extensions/CosmosDbServiceActivityExtensions.cs index 62fc396b..73d6142b 100644 --- a/src/App/Extensions/CosmosDbServiceActivityExtensions.cs +++ b/src/App/Extensions/CosmosDbServiceActivityExtensions.cs @@ -179,4 +179,61 @@ public static class CosmosDbServiceActivityExtensions parentId: parentActivityId ); } + + /// + /// Starts an activity for adding or updating a lyrics analyzer prompt style in the database. + /// + /// The . + /// The lyrics analyzer prompt style. + /// The parent activity ID. + /// The started . + public static Activity? StartDbAddOrUpdateLyricsAnalyzerPromptStyleActivity(this ActivitySource activitySource, LyricsAnalyzerPromptStyle promptStyle, string? parentActivityId) + { + return activitySource.CreateActivity( + name: "Database:AddOrUpdateLyricsAnalyzerPromptStyleAsync", + kind: ActivityKind.Internal, + tags: new ActivityTagsCollection + { + { "db_Id", promptStyle.Id }, + { "name", promptStyle.Name }, + { "shortName", promptStyle.ShortName } + }, + parentId: parentActivityId + ); + } + + /// + /// Starts an activity for getting a lyrics analyzer prompt style from the database. + /// + /// The . + /// The short name of the prompt style. + /// The parent activity ID. + /// The started . + public static Activity? StartDbGetLyricsAnalyzerPromptStyleActivity(this ActivitySource activitySource, string shortName, string? parentActivityId) + { + return activitySource.CreateActivity( + name: "Database:GetLyricsAnalyzerPromptStyleAsync", + kind: ActivityKind.Internal, + tags: new ActivityTagsCollection + { + { "shortName", shortName } + }, + parentId: parentActivityId + ); + } + + /// + /// Starts an activity for getting all lyrics analyzer prompt styles from the database. + /// + /// The . + /// The parent activity ID. + /// The started . + public static Activity? StartDbGetLyricsAnalyzerPromptStylesActivity(this ActivitySource activitySource, string? parentActivityId) + { + return activitySource.CreateActivity( + name: "Database:GetLyricsAnalyzerPromptStylesAsync", + kind: ActivityKind.Internal, + parentId: parentActivityId + ); + } } \ No newline at end of file diff --git a/src/App/Handlers/LyricsAnalyzerPromptStyleAutoCompleteHandler.cs b/src/App/Handlers/LyricsAnalyzerPromptStyleAutoCompleteHandler.cs index 2cab9909..08ab9639 100644 --- a/src/App/Handlers/LyricsAnalyzerPromptStyleAutoCompleteHandler.cs +++ b/src/App/Handlers/LyricsAnalyzerPromptStyleAutoCompleteHandler.cs @@ -2,6 +2,7 @@ using Discord.Interactions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using MuzakBot.App.Models.Database.LyricsAnalyzer; using MuzakBot.App.Models.Itunes; using MuzakBot.App.Models.MusicBrainz; using MuzakBot.App.Services; @@ -10,29 +11,52 @@ namespace MuzakBot.App.Handlers; public class LyricsAnalyzerPromptStyleAutoCompleteHandler : AutocompleteHandler { - private readonly IReadOnlyList _promptStyleOptions = [ - new("Normal", "normal"), - new("Meme: Tame", "tame-meme"), - new("Meme: Insane", "insane-meme"), - new("Meme: Roast", "roast-meme"), - new("Snobby Music Critic", "snobby-music-critic") - ]; + private readonly ILogger _logger; + private readonly ICosmosDbService _cosmosDbService; + + public LyricsAnalyzerPromptStyleAutoCompleteHandler(ILogger logger, ICosmosDbService cosmosDbService) + { + _logger = logger; + _cosmosDbService = cosmosDbService; + } public override async Task GenerateSuggestionsAsync(IInteractionContext context, IAutocompleteInteraction autocompleteInteraction, IParameterInfo parameter, IServiceProvider services) { List results = new(); - AutocompleteOption? promptStyleInput = autocompleteInteraction.Data.Options.FirstOrDefault(item => item.Name == "prompt-style"); + LyricsAnalyzerPromptStyle[] promptStyles = await _cosmosDbService.GetLyricsAnalyzerPromptStylesAsync(); + Array.Sort(promptStyles, (item1, item2) => item1.Name.CompareTo(item2.Name)); + + _logger.LogInformation("Returned {Count} prompt styles from the database.", promptStyles.Length); + + AutocompleteOption? promptStyleInput = autocompleteInteraction.Data.Options.FirstOrDefault(item => item.Name == "style"); if (promptStyleInput is null || promptStyleInput.Value is null || string.IsNullOrWhiteSpace(promptStyleInput.Value.ToString())) { - return AutocompletionResult.FromSuccess(_promptStyleOptions); + _logger.LogInformation("Prompt style input was null or empty, returning all prompt styles."); + + foreach (LyricsAnalyzerPromptStyle promptStyle in promptStyles) + { + results.Add(new AutocompleteResult + { + Name = promptStyle.Name, + Value = promptStyle.ShortName + }); + } + + return AutocompletionResult.FromSuccess(results.AsEnumerable()); } - _promptStyleOptions - .Where(item => item.Value.ToString()!.Contains(promptStyleInput.Value.ToString()!, StringComparison.OrdinalIgnoreCase)) + promptStyles + .Where(item => item.ShortName.Contains(promptStyleInput.Value.ToString()!, StringComparison.OrdinalIgnoreCase)) .ToList() - .ForEach(item => results.Add(item)); + .ForEach(item => results.Add(new AutocompleteResult + { + Name = item.Name, + Value = item.ShortName + })); + + _logger.LogInformation("Filtered down to {Count} prompt styles based off the input {input}.", results.Count, promptStyleInput.Value.ToString()!); return AutocompletionResult.FromSuccess(results.AsEnumerable()); } diff --git a/src/App/JsonSourceGen/DatabaseJsonContext.cs b/src/App/JsonSourceGen/DatabaseJsonContext.cs index 9284bf35..1eb368db 100644 --- a/src/App/JsonSourceGen/DatabaseJsonContext.cs +++ b/src/App/JsonSourceGen/DatabaseJsonContext.cs @@ -19,8 +19,11 @@ namespace MuzakBot.App; [JsonSerializable(typeof(LyricsAnalyzerConfig))] [JsonSerializable(typeof(LyricsAnalyzerUserRateLimit))] [JsonSerializable(typeof(LyricsAnalyzerUserRateLimit[]))] +[JsonSerializable(typeof(LyricsAnalyzerPromptStyle))] +[JsonSerializable(typeof(LyricsAnalyzerPromptStyle[]))] [JsonSerializable(typeof(CosmosDbResponse))] [JsonSerializable(typeof(CosmosDbResponse))] [JsonSerializable(typeof(CosmosDbResponse))] +[JsonSerializable(typeof(CosmosDbResponse))] internal partial class DatabaseJsonContext : JsonSerializerContext {} \ No newline at end of file diff --git a/src/App/Logging/CosmosDb/CosmosDbServiceLoggingConstants.cs b/src/App/Logging/CosmosDb/CosmosDbServiceLoggingConstants.cs index 6350e38a..3ff855b7 100644 --- a/src/App/Logging/CosmosDb/CosmosDbServiceLoggingConstants.cs +++ b/src/App/Logging/CosmosDb/CosmosDbServiceLoggingConstants.cs @@ -45,5 +45,10 @@ public static class ItemTypes /// The lyrics analyzer config item type. /// public const string LyricsAnalyzerConfig = "lyrics analyzer config"; + + /// + /// The lyrics analyzer prompt style item type. + /// + public const string LyricsAnalyzerPromptStyle = "lyrics analyzer prompt style"; } } \ No newline at end of file diff --git a/src/App/Logging/OpenAi/OpenAiServiceLogging.cs b/src/App/Logging/OpenAi/OpenAiServiceLogging.cs index 95149c77..8e3365a0 100644 --- a/src/App/Logging/OpenAi/OpenAiServiceLogging.cs +++ b/src/App/Logging/OpenAi/OpenAiServiceLogging.cs @@ -13,13 +13,13 @@ internal static partial class OpenAiServiceLogging /// The instance. /// The name of the artist. /// The name of the song. - /// The prompt mode being used. + /// The prompt style being used. [LoggerMessage( EventName = "OpenAiApiService.LyricAnalysis.Start", Level = LogLevel.Information, - Message = "Starting lyric analysis for '{artistName} - {songName}' using the '{promptMode}' style." + Message = "Starting lyric analysis for '{artistName} - {songName}' using the '{promptStyle}' style." )] - public static partial void LogOpenAiApiServiceLyricAnalysisStart(this ILogger logger, string artistName, string songName, string promptMode); + public static partial void LogOpenAiApiServiceLyricAnalysisStart(this ILogger logger, string artistName, string songName, string promptStyle); /// /// Logs a failed lyric analysis. diff --git a/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleModal.cs b/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleModal.cs new file mode 100644 index 00000000..bf8b5de5 --- /dev/null +++ b/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleModal.cs @@ -0,0 +1,93 @@ +using Discord; +using Discord.Interactions; +using MuzakBot.App.Models.Database; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Models.CommandModules; + +public class LyricsAnalyzerPromptStyleModal : IModal +{ + public LyricsAnalyzerPromptStyleModal() + {} + + public LyricsAnalyzerPromptStyleModal(LyricsAnalyzerPromptStyle promptStyle) + { + Name = promptStyle.Name; + ShortName = promptStyle.ShortName; + AnalysisType = promptStyle.AnalysisType; + Prompt = promptStyle.Prompt; + NoticeText = promptStyle.NoticeText; + } + + public string Title => "Lyrics Analyzer Prompt Style"; + + /// + /// The name of the prompt style. + /// + [JsonPropertyName("name")] + [InputLabel("Name")] + [ModalTextInput( + customId: "prompt-style-name", + placeholder: "Enter the name of the prompt style", + minLength: 1, + maxLength: 100, + style: TextInputStyle.Short + )] + public string Name { get; set; } = null!; + + /// + /// The short name of the prompt style. + /// + [JsonPropertyName("shortName")] + [InputLabel("Short Name")] + [ModalTextInput( + customId: "prompt-style-short-name", + placeholder: "Enter the short name of the prompt style", + minLength: 1, + maxLength: 50, + style: TextInputStyle.Short + )] + public string ShortName { get; set; } = null!; + + /// + /// The analysis type of the prompt style. + /// + [JsonPropertyName("analysisType")] + [InputLabel("Analysis Type")] + [ModalTextInput( + customId: "prompt-style-analysis-type", + placeholder: "Enter the analysis type of the prompt style", + minLength: 1, + maxLength: 100, + style: TextInputStyle.Short + )] + public string AnalysisType { get; set; } = null!; + + /// + /// The prompt used for the style. + /// + [JsonPropertyName("prompt")] + [InputLabel("Prompt")] + [ModalTextInput( + customId: "prompt-style-prompt", + placeholder: "Enter the prompt used for the style", + minLength: 1, + maxLength: 4000, + style: TextInputStyle.Paragraph + )] + public string Prompt { get; set; } = null!; + + /// + /// The notice text used for the prompt style. + /// + [JsonPropertyName("noticeText")] + [InputLabel("Notice Text")] + [ModalTextInput( + customId: "prompt-style-notice-text", + placeholder: "Enter the notice text used for the prompt style", + minLength: 1, + maxLength: 4000, + style: TextInputStyle.Paragraph + )] + public string NoticeText { get; set; } = null!; +} \ No newline at end of file diff --git a/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleUserPromptModal.cs b/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleUserPromptModal.cs new file mode 100644 index 00000000..b7e9319b --- /dev/null +++ b/src/App/Models/CommandModules/LyricsAnalyzerPromptStyleUserPromptModal.cs @@ -0,0 +1,40 @@ +using Discord; +using Discord.Interactions; + +namespace MuzakBot.App.Models.Database.LyricsAnalyzer; + +public class LyricsAnalyzerPromptStyleUserPromptModal : IModal +{ + public LyricsAnalyzerPromptStyleUserPromptModal() + { } + + public LyricsAnalyzerPromptStyleUserPromptModal(LyricsAnalyzerPromptStyle promptStyle) + { + ShortName = promptStyle.ShortName; + UserPrompt = promptStyle.UserPrompt; + } + + public string Title => "Lyrics Analyzer Prompt Style"; + + [JsonPropertyName("shortName")] + [InputLabel("Short name")] + [ModalTextInput( + customId: "prompt-style-short-name", + placeholder: "Enter the short name of the prompt style", + minLength: 1, + maxLength: 50, + style: TextInputStyle.Short + )] + public string ShortName { get; set; } = null!; + + [JsonPropertyName("userPrompt")] + [InputLabel("User prompt")] + [ModalTextInput( + customId: "prompt-style-user-prompt", + placeholder: "Enter the user prompt of the prompt style", + minLength: 1, + maxLength: 4000, + style: TextInputStyle.Paragraph + )] + public string UserPrompt { get; set; } = null!; +} \ No newline at end of file diff --git a/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerPromptStyle.cs b/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerPromptStyle.cs new file mode 100644 index 00000000..0ff3d279 --- /dev/null +++ b/src/App/Models/Database/LyricsAnalyzer/LyricsAnalyzerPromptStyle.cs @@ -0,0 +1,113 @@ +using MuzakBot.App.Models.CommandModules; + +namespace MuzakBot.App.Models.Database.LyricsAnalyzer; + +/// +/// Holds data for a prompt style for the lyrics analyzer. +/// +public class LyricsAnalyzerPromptStyle : DatabaseItem, ILyricsAnalyzerPromptStyle +{ + /// + /// Initializes a new instance of the class. + /// + [JsonConstructor()] + public LyricsAnalyzerPromptStyle() { } + + /// + /// Initializes a new instance of the class. + /// + /// The to initialize from. + public LyricsAnalyzerPromptStyle(LyricsAnalyzerPromptStyleModal inputModal) + { + Id = Guid.NewGuid().ToString(); + PartitionKey = "prompt-style"; + UpdateFromModalInput(inputModal); + CreatedOn = DateTimeOffset.UtcNow; + LastUpdated = DateTimeOffset.UtcNow; + } + + /// + /// Initializes a new instance of the class. + /// + /// The name of the prompt style. + /// The short name of the prompt style. + /// The description of the prompt style. + /// The analysis type of the prompt style. + /// The prompt used for the style. + /// The notice text used for the prompt style. + public LyricsAnalyzerPromptStyle(string name, string shortName, string analysisType, string prompt, string noticeText) + { + Name = name; + ShortName = shortName; + AnalysisType = analysisType; + Prompt = prompt; + NoticeText = noticeText; + CreatedOn = DateTimeOffset.UtcNow; + LastUpdated = DateTimeOffset.UtcNow; + } + + /// + /// The name of the prompt style. + /// + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + /// + /// The short name of the prompt style. + /// + [JsonPropertyName("shortName")] + public string ShortName { get; set; } = null!; + + /// + /// The analysis type of the prompt style. + /// + [JsonPropertyName("analysisType")] + public string AnalysisType { get; set; } = null!; + + /// + /// The prompt used for the style. + /// + [JsonPropertyName("prompt")] + public string Prompt { get; set; } = null!; + + /// + /// The prompt used as a user prompt for the style. + /// + public string UserPrompt { get; set; } = "Briefly explain the lyrics for the song \"{{songName}}\" by {{artistName}}. Format the response in Markdown syntax."; + + /// + /// The notice text used for the prompt style. + /// + [JsonPropertyName("noticeText")] + public string NoticeText { get; set; } = null!; + + /// + /// The date and time the prompt style was created. + /// + [JsonPropertyName("createdOn")] + public DateTimeOffset CreatedOn { get; set; } + + /// + /// The date and time the prompt style was last updated. + /// + [JsonPropertyName("lastUpdated")] + public DateTimeOffset LastUpdated { get; set; } + + /// + /// Updates the prompt style from . + /// + /// The to update from. + public void UpdateFromModalInput(LyricsAnalyzerPromptStyleModal inputModal) + { + Name = inputModal.Name; + ShortName = inputModal.ShortName; + AnalysisType = inputModal.AnalysisType; + Prompt = inputModal.Prompt; + NoticeText = inputModal.NoticeText; + } + + /// + /// Updates the last updated time to the current date and time. + /// + public void UpdateLastUpdateTime() => LastUpdated = DateTimeOffset.UtcNow; +} diff --git a/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerPromptStyle.cs b/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerPromptStyle.cs new file mode 100644 index 00000000..89f16d29 --- /dev/null +++ b/src/App/Models/Database/LyricsAnalyzer/interface/ILyricsAnalyzerPromptStyle.cs @@ -0,0 +1,20 @@ +using MuzakBot.App.Models.CommandModules; + +namespace MuzakBot.App.Models.Database.LyricsAnalyzer; + +public interface ILyricsAnalyzerPromptStyle +{ + string Id { get; set; } + string PartitionKey { get; set; } + string Name { get; set; } + string ShortName { get; set; } + string AnalysisType { get; set; } + string Prompt { get; set; } + string UserPrompt { get; set; } + string NoticeText { get; set; } + DateTimeOffset CreatedOn { get; set; } + DateTimeOffset LastUpdated { get; set; } + + void UpdateFromModalInput(LyricsAnalyzerPromptStyleModal inputModal); + void UpdateLastUpdateTime(); +} diff --git a/src/App/Modules/AdminCommandModule/Commands/HandleCreateLyricsAnalyzerPromptStyleAsync.cs b/src/App/Modules/AdminCommandModule/Commands/HandleCreateLyricsAnalyzerPromptStyleAsync.cs new file mode 100644 index 00000000..7eb66de4 --- /dev/null +++ b/src/App/Modules/AdminCommandModule/Commands/HandleCreateLyricsAnalyzerPromptStyleAsync.cs @@ -0,0 +1,36 @@ +using Discord; +using Discord.Interactions; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Models.CommandModules; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Modules; + +public partial class AdminCommandModule +{ + [SlashCommand(name: "create-prompt-style", description: "Create a new prompt style.")] + [RequireOwner] + public async Task HandleCreateLyricsAnalyzerPromptStyleAsync() + { + try + { + await RespondWithModalAsync( + customId: "prompt-style-create" + ); + } + catch (Exception ex) + { + await RespondAsync( + embeds: [ + new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"An error occurred while creating the prompt style:\n\n{ex.Message}") + .WithColor(Color.Red) + .Build() + ] + ); + + _logger.LogError(ex, "An error occurred while creating the prompt style: {Message}", ex.Message); + } + } +} \ No newline at end of file diff --git a/src/App/Modules/AdminCommandModule/Commands/HandleUpdateLyricsAnalyzerPromptStyleAsync.cs b/src/App/Modules/AdminCommandModule/Commands/HandleUpdateLyricsAnalyzerPromptStyleAsync.cs new file mode 100644 index 00000000..e2c6ec93 --- /dev/null +++ b/src/App/Modules/AdminCommandModule/Commands/HandleUpdateLyricsAnalyzerPromptStyleAsync.cs @@ -0,0 +1,65 @@ +using Discord; +using Discord.Interactions; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Handlers; +using MuzakBot.App.Models.CommandModules; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Modules; + +public partial class AdminCommandModule +{ + [SlashCommand(name: "update-prompt-style", description: "Update a lyrics analyzer prompt style.")] + [RequireOwner] + public async Task HandleUpdateLyricsAnalyzerPromptStyleAsync( + [Summary(name: "style", description: "The prompt style to edit."), + Autocomplete(typeof(LyricsAnalyzerPromptStyleAutoCompleteHandler))] + string style, + [Summary(name: "configType", description: "The configuration type to edit."), + Choice(name: "Core", value: "core"), + Choice(name: "User prompt", value: "user-prompt")] + string configType = "core" + ) + { + LyricsAnalyzerPromptStyle? promptStyle = await _cosmosDbService.GetLyricsAnalyzerPromptStyleAsync(style); + + if (promptStyle is null) + { + EmbedBuilder embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"A prompt style with the short name `{style}` does not exist.") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + return; + } + + if (configType == "core") + { + LyricsAnalyzerPromptStyleModal promptStyleModal = new(promptStyle); + + await RespondWithModalAsync( + customId: $"prompt-style-edit", + modal: promptStyleModal + ); + + return; + } + + if (configType == "user-prompt") + { + LyricsAnalyzerPromptStyleUserPromptModal promptStyleUserPromptModal = new(promptStyle); + await RespondWithModalAsync( + customId: $"prompt-style-edit-user-prompt", + modal: promptStyleUserPromptModal + ); + + return; + } + } +} \ No newline at end of file diff --git a/src/App/Modules/AdminCommandModule/ModalInteractions/HandleCreatePromptStyleModalAsync.cs b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleCreatePromptStyleModalAsync.cs new file mode 100644 index 00000000..bcbcdf60 --- /dev/null +++ b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleCreatePromptStyleModalAsync.cs @@ -0,0 +1,73 @@ +using Discord; +using Discord.Interactions; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Models.CommandModules; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Modules; + +public partial class AdminCommandModule +{ + [ModalInteraction("prompt-style-create")] + public async Task HandleCreatePromptStyleModalAsync(LyricsAnalyzerPromptStyleModal promptStyleModal) + { + await Context.Interaction.DeferAsync( + ephemeral: true + ); + + LyricsAnalyzerPromptStyle promptStyle = new(promptStyleModal); + + EmbedBuilder embed; + + bool promptStyleExists = await _cosmosDbService.GetLyricsAnalyzerPromptStyleAsync(promptStyle.ShortName) is not null; + + if (promptStyleExists) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"A prompt style with the short name `{promptStyle.ShortName}` already exists.") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + return; + } + + try + { + await _cosmosDbService.AddOrUpdateLyricsAnalyzerPromptStyleAsync(promptStyle); + } + catch (Exception ex) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"An error occurred while creating the prompt style:\n\n{ex.Message}") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + _logger.LogError(ex, "An error occurred while creating the prompt style: {Message}", ex.Message); + + return; + } + + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"Successfully created prompt style **{promptStyle.Name}**.") + .WithColor(Color.Green); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + } +} \ No newline at end of file diff --git a/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditPromptStyleModalAsync.cs b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditPromptStyleModalAsync.cs new file mode 100644 index 00000000..27a02ac8 --- /dev/null +++ b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditPromptStyleModalAsync.cs @@ -0,0 +1,80 @@ +using Discord; +using Discord.Interactions; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Handlers; +using MuzakBot.App.Models.CommandModules; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Modules; + +public partial class AdminCommandModule +{ + [ModalInteraction("prompt-style-edit")] + public async Task HandleEditPromptStyleModalAsync(LyricsAnalyzerPromptStyleModal promptStyleModal) + { + await Context.Interaction.DeferAsync( + ephemeral: true + ); + + EmbedBuilder embed; + + LyricsAnalyzerPromptStyle promptStyle = new(promptStyleModal); + + LyricsAnalyzerPromptStyle? existingPromptStyle = await _cosmosDbService.GetLyricsAnalyzerPromptStyleAsync(promptStyle.ShortName); + + if (existingPromptStyle is null) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription("The prompt style short name appears to have been changed.\n\n**Prompt style short names cannot be changed!**") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + return; + } + + promptStyle.Id = existingPromptStyle.Id; + promptStyle.PartitionKey = existingPromptStyle.PartitionKey; + promptStyle.UserPrompt = existingPromptStyle.UserPrompt; + + promptStyle.UpdateLastUpdateTime(); + + try + { + await _cosmosDbService.AddOrUpdateLyricsAnalyzerPromptStyleAsync(promptStyle); + } + catch (Exception ex) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"An error occurred while updating the prompt style:\n\n{ex.Message}") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + _logger.LogError(ex, "An error occurred while updating the prompt style: {Message}", ex.Message); + + return; + } + + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"Successfully updated prompt style **{promptStyle.Name}**.") + .WithColor(Color.Green); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + } +} \ No newline at end of file diff --git a/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditUserPromptStyleModalAsync.cs b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditUserPromptStyleModalAsync.cs new file mode 100644 index 00000000..8c815180 --- /dev/null +++ b/src/App/Modules/AdminCommandModule/ModalInteractions/HandleEditUserPromptStyleModalAsync.cs @@ -0,0 +1,76 @@ +using Discord; +using Discord.Interactions; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Handlers; +using MuzakBot.App.Models.CommandModules; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Modules; + +public partial class AdminCommandModule +{ + [ModalInteraction("prompt-style-edit-user-prompt")] + public async Task HandleEditUserPromptStyleModalAsync(LyricsAnalyzerPromptStyleUserPromptModal userPromptModal) + { + await Context.Interaction.DeferAsync( + ephemeral: true + ); + + EmbedBuilder embed; + + LyricsAnalyzerPromptStyle? promptStyle = await _cosmosDbService.GetLyricsAnalyzerPromptStyleAsync(userPromptModal.ShortName); + + if (promptStyle is null) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription("The prompt style short name appears to have been changed.\n\n**Prompt style short names cannot be changed!**") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + return; + } + + promptStyle.UserPrompt = userPromptModal.UserPrompt; + + promptStyle.UpdateLastUpdateTime(); + + try + { + await _cosmosDbService.AddOrUpdateLyricsAnalyzerPromptStyleAsync(promptStyle); + } + catch (Exception ex) + { + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"An error occurred while updating the prompt style:\n\n{ex.Message}") + .WithColor(Color.Red); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + + _logger.LogError(ex, "An error occurred while updating the prompt style: {Message}", ex.Message); + + return; + } + + embed = new EmbedBuilder() + .WithTitle("Lyrics Analyzer Prompt Style") + .WithDescription($"Successfully updated prompt style **{promptStyle.Name}**.") + .WithColor(Color.Green); + + await Context.Interaction.FollowupAsync( + embeds: [ + embed.Build() + ] + ); + } +} \ No newline at end of file diff --git a/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs b/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs index 0ea7e213..510de530 100644 --- a/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs +++ b/src/App/Modules/LyricsAnalyzerCommandModule/Commands/HandleLyricsAnalyzerAsync.cs @@ -40,12 +40,8 @@ private async Task HandleLyricsAnalyzerAsync( ] string songName, [Summary(name: "style", description: "The style of the response"), - Choice("Normal", "normal"), - Choice("Snobby Music Critic", "snobby"), - Choice("Meme - Tame", "tame-meme"), - Choice("Meme - Insane", "insane-meme"), - Choice("Meme - Roast", "roast-meme")] - string promptMode = "noraml", + Autocomplete(typeof(LyricsAnalyzerPromptStyleAutoCompleteHandler))] + string promptMode = "normal", [Summary(name: "private", description: "Whether or not to send the response privately")] bool isPrivateResponse = false ) @@ -127,6 +123,39 @@ await FollowupAsync( } } + LyricsAnalyzerPromptStyle? promptStyle; + + try + { + promptStyle = await _cosmosDbService.GetLyricsAnalyzerPromptStyleAsync(promptMode, activity?.Id); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error getting prompt style from database."); + await FollowupAsync( + embed: GenerateErrorEmbed("An error occurred while getting the prompt style. 😥").Build(), + components: GenerateRemoveComponent().Build(), + ephemeral: isPrivateResponse + ); + + activity?.SetStatus(ActivityStatusCode.Error); + + return; + } + + if (promptStyle is null) + { + await FollowupAsync( + embed: GenerateErrorEmbed("An error occurred while getting the prompt style. 😥").Build(), + components: GenerateRemoveComponent().Build(), + ephemeral: isPrivateResponse + ); + + activity?.SetStatus(ActivityStatusCode.Error); + + return; + } + string lyrics = string.Empty; bool isSongLyricsItemInDb = false; try @@ -221,7 +250,7 @@ await FollowupAsync( artistName: artistName, songName: songName, lyrics: lyrics, - promptMode: promptMode, + promptStyle: promptStyle, parentActivityId: activity?.Id ); @@ -246,18 +275,7 @@ await FollowupAsync( StringBuilder lyricsResponseBuilder = new($"# \"{songName}\" by _{artistName}_\n\n"); - if (promptMode == "snobby") - { - lyricsResponseBuilder.AppendLine("## Lyrics review\n\n"); - } - else if (promptMode == "roast-meme") - { - lyricsResponseBuilder.AppendLine("## Lyrics roast\n\n"); - } - else - { - lyricsResponseBuilder.AppendLine("## Lyrics analysis\n\n"); - } + lyricsResponseBuilder.AppendLine($"## {promptStyle.AnalysisType}\n\n"); string[] analysisLines = openAiChatCompletion.Choices[0].Message.Content.Split(Environment.NewLine); @@ -271,17 +289,9 @@ await FollowupAsync( lyricsResponseBuilder.AppendLine($"> {analysisLines[i]}"); } - string embedDescription = promptMode switch - { - "snobby" => "These results were generated by an \"AI\"\nand **are not guaranteed** to be accurate.", - "roast-meme" => "These results were generated by an \"AI\",\n**are not guaranteed** to be accurate,\nand is not intended to be taken seriously", - "tame-meme" or "insane-meme" => "These results were generated by an \"AI\"\nand **are definitely not** accurate\nbecause haha meme mode go brrrrr 😳", - _ => "These results were generated by an \"AI\"\nand **are not guaranteed** to be accurate." - }; - EmbedBuilder embedBuilder = new EmbedBuilder() .WithTitle("⚠️ Note") - .WithDescription(embedDescription) + .WithDescription(promptStyle.NoticeText) .WithColor(Color.DarkTeal) .WithFooter("(Powered by OpenAI's GPT-4)"); diff --git a/src/App/Services/CosmosDbService/LyricsAnalyzer/AddOrUpdateLyricsAnalyzerPromptStyleAsync.cs b/src/App/Services/CosmosDbService/LyricsAnalyzer/AddOrUpdateLyricsAnalyzerPromptStyleAsync.cs new file mode 100644 index 00000000..2232a107 --- /dev/null +++ b/src/App/Services/CosmosDbService/LyricsAnalyzer/AddOrUpdateLyricsAnalyzerPromptStyleAsync.cs @@ -0,0 +1,82 @@ +using System.Net; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Extensions; +using MuzakBot.App.Logging.CosmosDb; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Services; + +public partial class CosmosDbService +{ + /// + /// Adds or updates the lyrics analyzer prompt style in the database. + /// + /// The prompt style to add or update. + /// + public async Task AddOrUpdateLyricsAnalyzerPromptStyleAsync(LyricsAnalyzerPromptStyle promptStyle) => await AddOrUpdateLyricsAnalyzerPromptStyleAsync(promptStyle, null); + + /// + /// Adds or updates the lyrics analyzer prompt style in the database. + /// + /// The prompt style to add or update. + /// The parent activity ID. + /// + public async Task AddOrUpdateLyricsAnalyzerPromptStyleAsync(LyricsAnalyzerPromptStyle promptStyle, string? parentActivityId) + { + using var activity = _activitySource.StartDbAddOrUpdateLyricsAnalyzerPromptStyleActivity( + promptStyle: promptStyle, + parentActivityId: parentActivityId + ); + + _logger.LogAddOrUpdateOperationStart( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: promptStyle.Id + ); + + Container container = _cosmosDbClient.GetContainer( + databaseId: _options.DatabaseName, + containerId: "prompt-styles" + ); + + string promptStyleJson = JsonSerializer.Serialize( + value: promptStyle, + jsonTypeInfo: DatabaseJsonContext.Default.LyricsAnalyzerPromptStyle + ); + + using MemoryStream itemPayload = new(); + await JsonSerializer.SerializeAsync( + utf8Json: itemPayload, + value: promptStyle, + jsonTypeInfo: DatabaseJsonContext.Default.LyricsAnalyzerPromptStyle + ); + + try + { + await container.UpsertItemStreamAsync( + streamPayload: itemPayload, + partitionKey: new PartitionKey(promptStyle.PartitionKey) + ); + + _logger.LogAddOrUpdateOperationAdded( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: promptStyle.Id, + state: CosmosDbServiceLoggingConstants.OperationTypes.Added + ); + } + catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.Conflict) + { + await container.ReplaceItemStreamAsync( + streamPayload: itemPayload, + id: promptStyle.Id, + partitionKey: new PartitionKey(promptStyle.PartitionKey) + ); + + _logger.LogAddOrUpdateOperationAdded( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: promptStyle.Id, + state: CosmosDbServiceLoggingConstants.OperationTypes.Updated + ); + } + } +} diff --git a/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStyleAsync.cs b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStyleAsync.cs new file mode 100644 index 00000000..d869db22 --- /dev/null +++ b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStyleAsync.cs @@ -0,0 +1,89 @@ +using System.Diagnostics; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Extensions; +using MuzakBot.App.Logging.CosmosDb; +using MuzakBot.App.Models.CosmosDb; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Services; + +public partial class CosmosDbService +{ + /// + /// Gets a specific lyrics analyzer prompt style from the database. + /// + /// The short name of the prompt style. + /// The retrieved lyrics analyzer prompt style. + /// + public async Task GetLyricsAnalyzerPromptStyleAsync(string shortName) => await GetLyricsAnalyzerPromptStyleAsync(shortName, null); + + /// + /// Gets a specific lyrics analyzer prompt style from the database. + /// + /// The short name of the prompt style. + /// The parent activity ID. + /// The retrieved lyrics analyzer prompt style. + /// + public async Task GetLyricsAnalyzerPromptStyleAsync(string shortName, string? parentActivityId) + { + using var activity = _activitySource.StartDbGetLyricsAnalyzerPromptStyleActivity( + shortName: shortName, + parentActivityId: parentActivityId + ); + + _logger.LogGetOperationStart( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: shortName + ); + + Container container = _cosmosDbClient.GetContainer( + databaseId: _options.DatabaseName, + containerId: "prompt-styles" + ); + + var query = new QueryDefinition( + query: "SELECT * FROM c WHERE c.partitionKey = 'prompt-style' AND c.shortName = @shortName" + ) + .WithParameter("@shortName", shortName); + + CosmosDbResponse? cosmosDbResponse; + + try + { + using FeedIterator feedIterator = container.GetItemQueryStreamIterator( + queryDefinition: query, + requestOptions: new() + { + PartitionKey = new PartitionKey("prompt-style") + } + ); + + using ResponseMessage response = await feedIterator.ReadNextAsync(); + + cosmosDbResponse = await JsonSerializer.DeserializeAsync( + utf8Json: response.Content, + jsonTypeInfo: DatabaseJsonContext.Default.CosmosDbResponseLyricsAnalyzerPromptStyle + ); + } + catch (Exception ex) + { + _logger.LogGetOperationFailed( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: shortName, + exception: ex + ); + + activity?.SetStatus(ActivityStatusCode.Error); + + throw; + } + + if (cosmosDbResponse is null || cosmosDbResponse.Documents is null) + { + return null; + } + + return cosmosDbResponse.Documents.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStylesAsync.cs b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStylesAsync.cs new file mode 100644 index 00000000..3cc1deff --- /dev/null +++ b/src/App/Services/CosmosDbService/LyricsAnalyzer/GetLyricsAnalyzerPromptStylesAsync.cs @@ -0,0 +1,103 @@ +using System.Diagnostics; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Logging; +using MuzakBot.App.Extensions; +using MuzakBot.App.Logging.CosmosDb; +using MuzakBot.App.Models.CosmosDb; +using MuzakBot.App.Models.Database.LyricsAnalyzer; + +namespace MuzakBot.App.Services; + +public partial class CosmosDbService +{ + /// + /// Gets all lyrics analyzer prompt styles from the database. + /// + /// The retrieved lyrics analyzer prompt styles. + public async Task GetLyricsAnalyzerPromptStylesAsync() => await GetLyricsAnalyzerPromptStylesAsync(null); + + /// + /// Gets all lyrics analyzer prompt styles from the database. + /// + /// The parent activity ID. + /// The retrieved lyrics analyzer prompt styles. + public async Task GetLyricsAnalyzerPromptStylesAsync(string? parentActivityId) + { + using var activity = _activitySource.StartDbGetLyricsAnalyzerPromptStylesActivity( + parentActivityId: parentActivityId + ); + + _logger.LogGetOperationStart( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: "all" + ); + + Container container = _cosmosDbClient.GetContainer( + databaseId: _options.DatabaseName, + containerId: "prompt-styles" + ); + + var query = new QueryDefinition( + query: "SELECT * FROM c WHERE c.partitionKey = 'prompt-style'" + ); + + int resultCount = await GetResultCountAsync( + container: container, + coreQuery: "WHERE c.partitionKey = 'prompt-style'" + ); + + _logger.LogInformation("Found {Count} prompt styles in the database.", resultCount); + + LyricsAnalyzerPromptStyle[] promptStyles = new LyricsAnalyzerPromptStyle[resultCount]; + + using FeedIterator feedIterator = container.GetItemQueryStreamIterator( + queryDefinition: query, + requestOptions: new() + { + PartitionKey = new PartitionKey("prompt-style") + } + ); + + + while (feedIterator.HasMoreResults) + { + using ResponseMessage response = await feedIterator.ReadNextAsync(); + + CosmosDbResponse? cosmosDbResponse = await JsonSerializer.DeserializeAsync( + utf8Json: response.Content, + jsonTypeInfo: DatabaseJsonContext.Default.CosmosDbResponseLyricsAnalyzerPromptStyle + ); + + if (cosmosDbResponse is null || cosmosDbResponse.Documents is null) + { + NullReferenceException nullResponseException = new( + message: "The Cosmos DB response or its documents were null." + ); + + _logger.LogGetOperationFailed( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: "all", + exception: nullResponseException + ); + + activity?.SetStatus(ActivityStatusCode.Error); + + throw nullResponseException; + } + + int i = 0; + foreach (var promptStyleItem in cosmosDbResponse!.Documents!) + { + promptStyles[i] = promptStyleItem; + i++; + } + } + + _logger.LogGetOperationFound( + itemType: CosmosDbServiceLoggingConstants.ItemTypes.LyricsAnalyzerPromptStyle, + id: "all" + ); + + return promptStyles; + } +} \ No newline at end of file diff --git a/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs b/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs index c2333ccb..e435b5df 100644 --- a/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs +++ b/src/App/Services/CosmosDbService/interfaces/ICosmosDbService.cs @@ -21,4 +21,13 @@ public interface ICosmosDbService : IDisposable Task GetSongLyricsItemAsync(string artistName, string songName); Task GetSongLyricsItemAsync(string artistName, string songName, string? parentActivityId); + + Task AddOrUpdateLyricsAnalyzerPromptStyleAsync(LyricsAnalyzerPromptStyle promptStyle); + Task AddOrUpdateLyricsAnalyzerPromptStyleAsync(LyricsAnalyzerPromptStyle promptStyle, string? parentActivityId); + + Task GetLyricsAnalyzerPromptStyleAsync(string shortName); + Task GetLyricsAnalyzerPromptStyleAsync(string shortName, string? parentActivityId); + + Task GetLyricsAnalyzerPromptStylesAsync(); + Task GetLyricsAnalyzerPromptStylesAsync(string? parentActivityId); } \ No newline at end of file diff --git a/src/App/Services/OpenAiService/OpenAiService.cs b/src/App/Services/OpenAiService/OpenAiService.cs index 85805e02..18c8f5e7 100644 --- a/src/App/Services/OpenAiService/OpenAiService.cs +++ b/src/App/Services/OpenAiService/OpenAiService.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Options; using MuzakBot.App.Extensions; using MuzakBot.App.Logging.OpenAi; +using MuzakBot.App.Models.Database.LyricsAnalyzer; using MuzakBot.App.Models.OpenAi; namespace MuzakBot.App.Services; @@ -40,7 +41,7 @@ public OpenAiService(IOptions options, IHttpClientFactory /// The lyrics of the song. /// The lyric analysis from the API. /// The response from the OpenAI API was null. - public async Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, string promptMode) => await GetLyricAnalysisAsync(artistName, songName, lyrics, promptMode, null); + public async Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, LyricsAnalyzerPromptStyle promptStyle) => await GetLyricAnalysisAsync(artistName, songName, lyrics, promptStyle, null); /// /// Gets the lyric analysis for a song using the OpenAI API. @@ -51,11 +52,11 @@ public OpenAiService(IOptions options, IHttpClientFactory /// The ID of the parent activity (optional). /// The lyric analysis from the API. /// The response from the OpenAI API was null. - public async Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, string promptMode, string? parentActivityId) + public async Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, LyricsAnalyzerPromptStyle promptStyle, string? parentActivityId) { using var activity = _activitySource.StartGetLyricAnalysisAsyncActivity(artistName, songName, parentActivityId); - _logger.LogOpenAiApiServiceLyricAnalysisStart(artistName, songName, promptMode); + _logger.LogOpenAiApiServiceLyricAnalysisStart(artistName, songName, promptStyle.ShortName); using var client = _httpClientFactory.CreateClient("OpenAiApiClient"); @@ -66,22 +67,6 @@ public OpenAiService(IOptions options, IHttpClientFactory requestMessage.Headers.Authorization = new("Bearer", _apiKey); - string systemPrompt = promptMode switch - { - "snobby" => LyricsAnalysisPromptConstants.SnobbyMusicCriticPrompt, - "roast-meme" => LyricsAnalysisPromptConstants.RoastMemePrompt, - "tame-meme" => LyricsAnalysisPromptConstants.TameMemePrompt, - "insane-meme" => LyricsAnalysisPromptConstants.InsaneMemePrompt, - _ => LyricsAnalysisPromptConstants.NormalPrompt - }; - - string userPrompt = promptMode switch - { - "snobby" => $"Briefly review and scathingly critique the lyrics for the song \"{songName}\" by {artistName}. Format the response in Markdown syntax.", - "roast-meme" => $"Briefly roast the lyrics for the song \"{songName}\" by {artistName}. Format the response in Markdown syntax.", - _ => $"Briefly explain the lyrics for the song \"{songName}\" by {artistName}. Format the response in Markdown syntax." - }; - OpenAiChatCompletionRequest request = new() { Model = "gpt-4-1106-preview", @@ -95,7 +80,7 @@ public OpenAiService(IOptions options, IHttpClientFactory new() { Role = "system", - Content = systemPrompt + Content = promptStyle.Prompt }, new() { @@ -105,7 +90,7 @@ public OpenAiService(IOptions options, IHttpClientFactory new() { Role = "user", - Content = userPrompt + Content = promptStyle.UserPrompt.Replace("{{songName}}", songName).Replace("{{artistName}}", artistName) } ] }; diff --git a/src/App/Services/OpenAiService/interfaces/IOpenAiService.cs b/src/App/Services/OpenAiService/interfaces/IOpenAiService.cs index bc22edf9..0c83b89e 100644 --- a/src/App/Services/OpenAiService/interfaces/IOpenAiService.cs +++ b/src/App/Services/OpenAiService/interfaces/IOpenAiService.cs @@ -1,3 +1,4 @@ +using MuzakBot.App.Models.Database.LyricsAnalyzer; using MuzakBot.App.Models.OpenAi; namespace MuzakBot.App.Services; @@ -7,6 +8,6 @@ namespace MuzakBot.App.Services; /// public interface IOpenAiService : IDisposable { - Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, string promptMode); - Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, string promptMode, string? parentActivityId); + Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, LyricsAnalyzerPromptStyle promptStyle); + Task GetLyricAnalysisAsync(string artistName, string songName, string lyrics, LyricsAnalyzerPromptStyle promptStyle, string? parentActivityId); } \ No newline at end of file