Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lyrics analyzer prompt style creator #63

Merged
merged 13 commits into from
Jan 15, 2024
57 changes: 57 additions & 0 deletions src/App/Extensions/CosmosDbServiceActivityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,61 @@ public static class CosmosDbServiceActivityExtensions
parentId: parentActivityId
);
}

/// <summary>
/// Starts an activity for adding or updating a lyrics analyzer prompt style in the database.
/// </summary>
/// <param name="activitySource">The <see cref="ActivitySource"/>.</param>
/// <param name="promptStyle">The lyrics analyzer prompt style.</param>
/// <param name="parentActivityId">The parent activity ID.</param>
/// <returns>The started <see cref="Activity"/>.</returns>
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
);
}

/// <summary>
/// Starts an activity for getting a lyrics analyzer prompt style from the database.
/// </summary>
/// <param name="activitySource">The <see cref="ActivitySource"/>.</param>
/// <param name="shortName">The short name of the prompt style.</param>
/// <param name="parentActivityId">The parent activity ID.</param>
/// <returns>The started <see cref="Activity"/>.</returns>
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
);
}

/// <summary>
/// Starts an activity for getting all lyrics analyzer prompt styles from the database.
/// </summary>
/// <param name="activitySource">The <see cref="ActivitySource"/>.</param>
/// <param name="parentActivityId">The parent activity ID.</param>
/// <returns>The started <see cref="Activity"/>.</returns>
public static Activity? StartDbGetLyricsAnalyzerPromptStylesActivity(this ActivitySource activitySource, string? parentActivityId)
{
return activitySource.CreateActivity(
name: "Database:GetLyricsAnalyzerPromptStylesAsync",
kind: ActivityKind.Internal,
parentId: parentActivityId
);
}
}
48 changes: 36 additions & 12 deletions src/App/Handlers/LyricsAnalyzerPromptStyleAutoCompleteHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -10,29 +11,52 @@ namespace MuzakBot.App.Handlers;

public class LyricsAnalyzerPromptStyleAutoCompleteHandler : AutocompleteHandler
{
private readonly IReadOnlyList<AutocompleteResult> _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<LyricsAnalyzerPromptStyleAutoCompleteHandler> _logger;
private readonly ICosmosDbService _cosmosDbService;

public LyricsAnalyzerPromptStyleAutoCompleteHandler(ILogger<LyricsAnalyzerPromptStyleAutoCompleteHandler> logger, ICosmosDbService cosmosDbService)
{
_logger = logger;
_cosmosDbService = cosmosDbService;
}

public override async Task<AutocompletionResult> GenerateSuggestionsAsync(IInteractionContext context, IAutocompleteInteraction autocompleteInteraction, IParameterInfo parameter, IServiceProvider services)
{
List<AutocompleteResult> 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());
}
Expand Down
3 changes: 3 additions & 0 deletions src/App/JsonSourceGen/DatabaseJsonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SongLyricsItem>))]
[JsonSerializable(typeof(CosmosDbResponse<LyricsAnalyzerConfig>))]
[JsonSerializable(typeof(CosmosDbResponse<LyricsAnalyzerUserRateLimit>))]
[JsonSerializable(typeof(CosmosDbResponse<LyricsAnalyzerPromptStyle>))]
internal partial class DatabaseJsonContext : JsonSerializerContext
{}
5 changes: 5 additions & 0 deletions src/App/Logging/CosmosDb/CosmosDbServiceLoggingConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,10 @@ public static class ItemTypes
/// The lyrics analyzer config item type.
/// </summary>
public const string LyricsAnalyzerConfig = "lyrics analyzer config";

/// <summary>
/// The lyrics analyzer prompt style item type.
/// </summary>
public const string LyricsAnalyzerPromptStyle = "lyrics analyzer prompt style";
}
}
6 changes: 3 additions & 3 deletions src/App/Logging/OpenAi/OpenAiServiceLogging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ internal static partial class OpenAiServiceLogging
/// <param name="logger">The <see cref="ILogger"/> instance.</param>
/// <param name="artistName">The name of the artist.</param>
/// <param name="songName">The name of the song.</param>
/// <param name="promptMode">The prompt mode being used.</param>
/// <param name="promptStyle">The prompt style being used.</param>
[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);

/// <summary>
/// Logs a failed lyric analysis.
Expand Down
93 changes: 93 additions & 0 deletions src/App/Models/CommandModules/LyricsAnalyzerPromptStyleModal.cs
Original file line number Diff line number Diff line change
@@ -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";

/// <summary>
/// The name of the prompt style.
/// </summary>
[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!;

/// <summary>
/// The short name of the prompt style.
/// </summary>
[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!;

/// <summary>
/// The analysis type of the prompt style.
/// </summary>
[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!;

/// <summary>
/// The prompt used for the style.
/// </summary>
[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!;

/// <summary>
/// The notice text used for the prompt style.
/// </summary>
[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!;
}
Original file line number Diff line number Diff line change
@@ -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!;
}
Loading