From dc04c8700c1f1eac98162eada664cce7a274a3c3 Mon Sep 17 00:00:00 2001 From: Luciana Regina Lino Date: Mon, 28 Jul 2025 18:03:15 -0300 Subject: [PATCH] feat: Refactor LiquidChatMessage and update project references - Changed `Role` property in `LiquidChatMessage` to use the new `LiquidMessageRole` enum for better structure. - Added constructor for `LiquidChatMessage` and initialized `Content` to an empty array by default. - Introduced `AddContent(string text)` and `AddContent(Uri imageUri)` methods for adding content with validation. - Added `AddMessage(LiquidChatMessage message)` method in `LiquidChatMessages` to ensure null messages are not added. - Updated project version in `Liquid.Core.csproj` from `8.0.0` to `8.1.0`. - Changed `Liquid.Core` reference in `Liquid.GenAi.OpenAi.csproj` from a package reference to a project reference. - Updated `MapChatRequestMessage` method to use the new `LiquidMessageRole` enum. - Created `LiquidMessageRole.cs` to define the `LiquidMessageRole` enum for message participant roles. --- .../GenAi/Entities/LiquidChatMessage.cs | 78 ++++++++++++++++++- .../GenAi/Entities/LiquidChatMessages.cs | 15 ++++ .../GenAi/Enums/LiquidMessageRole.cs | 27 +++++++ src/Liquid.Core/Liquid.Core.csproj | 2 +- .../Liquid.GenAi.OpenAi.csproj | 5 +- src/Liquid.GenAi.OpenAi/OpenAiAdapter.cs | 8 +- 6 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 src/Liquid.Core/GenAi/Enums/LiquidMessageRole.cs diff --git a/src/Liquid.Core/GenAi/Entities/LiquidChatMessage.cs b/src/Liquid.Core/GenAi/Entities/LiquidChatMessage.cs index 0944d27..76f5340 100644 --- a/src/Liquid.Core/GenAi/Entities/LiquidChatMessage.cs +++ b/src/Liquid.Core/GenAi/Entities/LiquidChatMessage.cs @@ -1,4 +1,7 @@ -using System.Diagnostics.CodeAnalysis; +using Liquid.Core.GenAi.Enums; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Liquid.Core.GenAi.Entities { @@ -11,11 +14,80 @@ public class LiquidChatMessage /// /// The chat role associated with this message. /// - public string Role { get; set; } + public LiquidMessageRole Role { get; set; } + + /// + /// Initializes a new instance of the class with the specified role. + /// + /// The role associated with the chat message. This value cannot be null or empty. + public LiquidChatMessage(LiquidMessageRole role) + { + Role = role; + } /// /// The contents of the message. /// - public LiquidChatContent[] Content { get; set; } + public LiquidChatContent[] Content { get; set; } = Array.Empty(); + + + /// + /// Adds a text content item to the current collection of chat contents. + /// + /// This method appends the specified text as a new content item to the existing + /// collection. If the collection is initially null, it initializes the collection with the new content + /// item. + /// The text content to add. Cannot be null, empty, or consist solely of whitespace. + /// Thrown if is null, empty, or consists only of whitespace. + public void AddContent(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + throw new ArgumentException("Text content cannot be null or empty.", nameof(text)); + } + var content = new LiquidChatContent + { + Kind = LiquidContentKind.Text, + Text = text + }; + if (Content == null) + { + Content = new[] { content }; + } + else + { + var contentList = new List(Content) { content }; + Content = contentList.ToArray(); + } + } + + /// + /// Adds an image content to the current collection of chat contents. + /// + /// If the content collection is initially empty, this method initializes it with the new + /// image content. Otherwise, it appends the image content to the existing collection. + /// The URI of the image to be added. Cannot be . + /// Thrown if is . + public void AddContent(Uri imageUri) + { + if (imageUri == null) + { + throw new ArgumentNullException(nameof(imageUri), "Image URI cannot be null."); + } + var content = new LiquidChatContent + { + Kind = LiquidContentKind.Image, + ImageUri = imageUri + }; + if (Content == null) + { + Content = new[] { content }; + } + else + { + var contentList = new List(Content) { content }; + Content = contentList.ToArray(); + } + } } } \ No newline at end of file diff --git a/src/Liquid.Core/GenAi/Entities/LiquidChatMessages.cs b/src/Liquid.Core/GenAi/Entities/LiquidChatMessages.cs index a7d8ea2..602985a 100644 --- a/src/Liquid.Core/GenAi/Entities/LiquidChatMessages.cs +++ b/src/Liquid.Core/GenAi/Entities/LiquidChatMessages.cs @@ -13,5 +13,20 @@ public class LiquidChatMessages /// The collection of context messages associated with a chat completions request. /// public List Messages { get; set; } = new List(); + + /// + /// Adds a message to the collection of chat messages. + /// + /// The chat message to add. Cannot be . + /// Thrown if is . + public void AddMessage(LiquidChatMessage message) + { + if (message == null) + { + throw new System.ArgumentNullException(nameof(message), "Message cannot be null"); + } + Messages.Add(message); + } + } } \ No newline at end of file diff --git a/src/Liquid.Core/GenAi/Enums/LiquidMessageRole.cs b/src/Liquid.Core/GenAi/Enums/LiquidMessageRole.cs new file mode 100644 index 0000000..4eeeda0 --- /dev/null +++ b/src/Liquid.Core/GenAi/Enums/LiquidMessageRole.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Liquid.Core.GenAi.Enums +{ + /// + /// Specifies the role of a participant in a message exchange, such as a user, assistant, or system. + /// + public enum LiquidMessageRole + { + /// + /// The user role, typically representing the end user or client. + /// + User, + /// + /// The assistant role, typically representing the AI or system responding to the user. + /// + Assistant, + /// + /// The system role, typically used for system-level messages or instructions. + /// + System + } +} diff --git a/src/Liquid.Core/Liquid.Core.csproj b/src/Liquid.Core/Liquid.Core.csproj index 112951a..f7b390c 100644 --- a/src/Liquid.Core/Liquid.Core.csproj +++ b/src/Liquid.Core/Liquid.Core.csproj @@ -10,7 +10,7 @@ Avanade 2019 https://github.com/Avanade/Liquid-Application-Framework logo.png - 8.0.0 + 8.1.0 true {C33A89FC-4F4D-4274-8D0F-29456BA8F76B} true diff --git a/src/Liquid.GenAi.OpenAi/Liquid.GenAi.OpenAi.csproj b/src/Liquid.GenAi.OpenAi/Liquid.GenAi.OpenAi.csproj index 9215ce8..3ec47b5 100644 --- a/src/Liquid.GenAi.OpenAi/Liquid.GenAi.OpenAi.csproj +++ b/src/Liquid.GenAi.OpenAi/Liquid.GenAi.OpenAi.csproj @@ -32,8 +32,11 @@ - + + + + diff --git a/src/Liquid.GenAi.OpenAi/OpenAiAdapter.cs b/src/Liquid.GenAi.OpenAi/OpenAiAdapter.cs index 3098118..0ecf46e 100644 --- a/src/Liquid.GenAi.OpenAi/OpenAiAdapter.cs +++ b/src/Liquid.GenAi.OpenAi/OpenAiAdapter.cs @@ -150,15 +150,15 @@ private static List GetChatMessagesAsync(string content, string pro private static ChatMessage MapChatRequestMessage(LiquidChatMessage message) { ChatMessage? chatRequestMessage = null; - switch (message.Role.ToLower()) + switch (message.Role) { - case "system": + case LiquidMessageRole.System: chatRequestMessage = new SystemChatMessage(CreateContent(message)); break; - case "assistant": + case LiquidMessageRole.Assistant: chatRequestMessage = new AssistantChatMessage(CreateContent(message)); break; - case "user": + case LiquidMessageRole.User: chatRequestMessage = new UserChatMessage(CreateContent(message)); break; default: