From ea1552fcc1386ef030198e236f70b172b6dadaf2 Mon Sep 17 00:00:00 2001 From: Takashi Shinohara Date: Tue, 15 Oct 2024 14:01:44 +0900 Subject: [PATCH] 3.1.0 release --- .../Bots/ActivityBot.cs | 28 ++++++------------- .../Dialogs/EndMeetingDialog.cs | 1 + .../Dialogs/InMeetingDialog.cs | 1 + .../Dialogs/StartMeetingDialog.cs | 1 + .../Extensions/BlobClientExtension.cs | 4 +-- .../Serialization/JsonSerializer.cs | 10 ++----- .../Services/OpenAIService.cs | 14 ++++++++-- .../Commands/EndMeetingCommand.cs | 15 ++++++---- .../Commands/InMeetingCommand.cs | 15 ++++++---- .../Commands/StartMeetingCommand.cs | 15 ++++++---- 10 files changed, 56 insertions(+), 48 deletions(-) diff --git a/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs b/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs index f355dd6..22f3e0c 100644 --- a/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs +++ b/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs @@ -104,27 +104,15 @@ protected override async Task OnMessageActivityAsync(ITurnContext>(async () => + var arguments = await this.openAIService.GetArgumentsAsync(command, cancellationToken: cancellationToken); + var result = arguments?.Type switch { - var message = await this.openAIService.ChatCompletionAsync(command, cancellationToken: cancellationToken); - if (message.FinishReason == ChatFinishReason.ToolCalls) - { - var arguments = message.ToolCalls.Select(item => item.FunctionArguments).First(); - var content = JsonSerializer.Deserialize(arguments?.ToString()); - return content?.Type switch - { - "会議開始後" => await dc.BeginDialogAsync(nameof(StartMeetingDialog), content, cancellationToken: cancellationToken), - "会議終了前" => await dc.BeginDialogAsync(nameof(EndMeetingDialog), content, cancellationToken: cancellationToken), - "会議中" => await dc.BeginDialogAsync(nameof(InMeetingDialog), content, cancellationToken: cancellationToken), - "初期化" => await dc.BeginDialogAsync(nameof(ResetDialog), cancellationToken: cancellationToken), - _ => null, - }; - } - else - { - return null; - } - })(); + "会議開始後" => await dc.BeginDialogAsync(nameof(StartMeetingDialog), arguments, cancellationToken: cancellationToken), + "会議終了前" => await dc.BeginDialogAsync(nameof(EndMeetingDialog), arguments, cancellationToken: cancellationToken), + "会議中" => await dc.BeginDialogAsync(nameof(InMeetingDialog), arguments, cancellationToken: cancellationToken), + "初期化" => await dc.BeginDialogAsync(nameof(ResetDialog), cancellationToken: cancellationToken), + _ => null, + }; if (result is null) { _ = await turnContext.SendActivityAsync( diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs index c339b25..9bd9e22 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs @@ -105,6 +105,7 @@ private async Task BeforeConfirmAsync(WaterfallStepContext ste new AdaptiveTextInput() { Id = "Message", + IsMultiline = true, Label = "メッセージ", Placeholder = "会議後に表示されるメッセージ", Style = AdaptiveTextInputStyle.Text, diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs index de5e7ae..7fbe443 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs @@ -110,6 +110,7 @@ private async Task BeforeConfirmAsync(WaterfallStepContext ste new AdaptiveTextInput() { Id = "Message", + IsMultiline = true, Label = "メッセージ", Placeholder = "会議中に表示されるメッセージ", Style = AdaptiveTextInputStyle.Text, diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs index 5594a77..3ac2b0c 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs @@ -105,6 +105,7 @@ private async Task BeforeConfirmAsync(WaterfallStepContext ste new AdaptiveTextInput() { Id = "Message", + IsMultiline = true, Label = "メッセージ", Placeholder = "開始後に表示されるメッセージ", Style = AdaptiveTextInputStyle.Text, diff --git a/source/server/Karamem0.Commistant.Common/Extensions/BlobClientExtension.cs b/source/server/Karamem0.Commistant.Common/Extensions/BlobClientExtension.cs index d6e2d46..5919a4f 100644 --- a/source/server/Karamem0.Commistant.Common/Extensions/BlobClientExtension.cs +++ b/source/server/Karamem0.Commistant.Common/Extensions/BlobClientExtension.cs @@ -37,9 +37,9 @@ public static async Task> GetObjectAsync(this BlobClient targe public static async Task SetObjectAsync(this BlobClient target, BlobContent value) { - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value.Data))); + var content = BinaryData.FromString(JsonSerializer.Serialize(value.Data)); _ = await target.UploadAsync( - stream, + content, new BlobUploadOptions() { Conditions = new BlobRequestConditions() diff --git a/source/server/Karamem0.Commistant.Common/Serialization/JsonSerializer.cs b/source/server/Karamem0.Commistant.Common/Serialization/JsonSerializer.cs index 9c6f4ca..cbbb636 100644 --- a/source/server/Karamem0.Commistant.Common/Serialization/JsonSerializer.cs +++ b/source/server/Karamem0.Commistant.Common/Serialization/JsonSerializer.cs @@ -25,19 +25,13 @@ public static class JsonSerializer public static T? Deserialize(string? value) { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } + _ = value ?? throw new ArgumentNullException(nameof(value)); return JsonConvert.DeserializeObject(value, settings); } public static string Serialize(T? value) { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } + _ = value ?? throw new ArgumentNullException(nameof(value)); return JsonConvert.SerializeObject(value, settings); } diff --git a/source/server/Karamem0.Commistant.Common/Services/OpenAIService.cs b/source/server/Karamem0.Commistant.Common/Services/OpenAIService.cs index b0d91be..d852010 100644 --- a/source/server/Karamem0.Commistant.Common/Services/OpenAIService.cs +++ b/source/server/Karamem0.Commistant.Common/Services/OpenAIService.cs @@ -7,6 +7,7 @@ // using Azure.AI.OpenAI; +using Karamem0.Commistant.Models; using Karamem0.Commistant.Resources; using OpenAI; using OpenAI.Chat; @@ -22,7 +23,7 @@ namespace Karamem0.Commistant.Services; public interface IOpenAIService { - Task ChatCompletionAsync(string text, CancellationToken cancellationToken = default); + Task GetArgumentsAsync(string text, CancellationToken cancellationToken = default); } @@ -33,7 +34,7 @@ public class OpenAIService(OpenAIClient openAIClient, string openAIModelName) : private readonly string openAIModelName = openAIModelName; - public async Task ChatCompletionAsync(string text, CancellationToken cancellationToken = default) + public async Task GetArgumentsAsync(string text, CancellationToken cancellationToken = default) { var chatCompletionsOptions = new ChatCompletionOptions() { @@ -69,7 +70,14 @@ public async Task ChatCompletionAsync(string text, CancellationT chatCompletionsOptions, cancellationToken ); - return chatCompletion.Value; + if (chatCompletion.Value.FinishReason == ChatFinishReason.ToolCalls) + { + return chatCompletion.Value.ToolCalls + .Select(item => item.FunctionArguments) + .First() + .ToObjectFromJson(); + } + return null; } } diff --git a/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs index 6d00d89..b689e44 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs @@ -48,7 +48,7 @@ public override async Task ExecuteAsync( CancellationToken cancellationToken = default ) { - if (property.InMeeting is not true) + if (property.InMeeting is false) { return; } @@ -79,7 +79,7 @@ public override async Task ExecuteAsync( { this.logger.EndMeetingMessageNotifying(reference, property); var card = new AdaptiveCard("1.3"); - if (string.IsNullOrEmpty(property.EndMeetingMessage) is not true) + if (string.IsNullOrEmpty(property.EndMeetingMessage) is false) { card.Body.Add(new AdaptiveTextBlock() { @@ -87,16 +87,21 @@ public override async Task ExecuteAsync( Wrap = true }); } - if (string.IsNullOrEmpty(property.EndMeetingUrl) is not true) + if (Uri.TryCreate(property.EndMeetingUrl, UriKind.Absolute, out var url)) { - var bytes = await this.qrCodeService.CreateAsync(property.EndMeetingUrl, cancellationToken); + var bytes = await this.qrCodeService.CreateAsync(url.ToString(), cancellationToken); var base64 = Convert.ToBase64String(bytes); card.Body.Add(new AdaptiveImage() { - AltText = property.InMeetingUrl, + AltText = url.ToString(), Size = AdaptiveImageSize.Stretch, Url = new Uri($"data:image/png;base64,{base64}") }); + card.Actions.Add(new AdaptiveOpenUrlAction() + { + Title = "URL を開く", + Url = url, + }); } var activity = MessageFactory.Attachment(new Attachment() { diff --git a/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs index c5cf7cf..b394eb6 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs @@ -48,7 +48,7 @@ public override async Task ExecuteAsync( CancellationToken cancellationToken = default ) { - if (property.InMeeting is not true) + if (property.InMeeting is false) { return; } @@ -75,7 +75,7 @@ public override async Task ExecuteAsync( { this.logger.InMeetingMessageNotifying(reference, property); var card = new AdaptiveCard("1.3"); - if (string.IsNullOrEmpty(property.InMeetingMessage) is not true) + if (string.IsNullOrEmpty(property.InMeetingMessage) is false) { card.Body.Add(new AdaptiveTextBlock() { @@ -83,16 +83,21 @@ public override async Task ExecuteAsync( Wrap = true }); } - if (string.IsNullOrEmpty(property.InMeetingUrl) is not true) + if (Uri.TryCreate(property.InMeetingUrl, UriKind.Absolute, out var url)) { - var bytes = await this.qrCodeService.CreateAsync(property.InMeetingUrl); + var bytes = await this.qrCodeService.CreateAsync(url.ToString(), cancellationToken); var base64 = Convert.ToBase64String(bytes); card.Body.Add(new AdaptiveImage() { - AltText = property.InMeetingUrl, + AltText = url.ToString(), Size = AdaptiveImageSize.Stretch, Url = new Uri($"data:image/png;base64,{base64}") }); + card.Actions.Add(new AdaptiveOpenUrlAction() + { + Title = "URL を開く", + Url = url, + }); } var activity = MessageFactory.Attachment(new Attachment() { diff --git a/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs index b946203..f1a7de6 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs @@ -48,7 +48,7 @@ public override async Task ExecuteAsync( CancellationToken cancellationToken = default ) { - if (property.InMeeting is not true) + if (property.InMeeting is false) { return; } @@ -79,7 +79,7 @@ public override async Task ExecuteAsync( { this.logger.StartMeetingMessageNotifying(reference, property); var card = new AdaptiveCard("1.3"); - if (string.IsNullOrEmpty(property.StartMeetingMessage) is not true) + if (string.IsNullOrEmpty(property.StartMeetingMessage) is false) { card.Body.Add(new AdaptiveTextBlock() { @@ -87,16 +87,21 @@ public override async Task ExecuteAsync( Wrap = true }); } - if (string.IsNullOrEmpty(property.StartMeetingUrl) is not true) + if (Uri.TryCreate(property.StartMeetingUrl, UriKind.Absolute, out var url)) { - var bytes = await this.qrCodeService.CreateAsync(property.StartMeetingUrl); + var bytes = await this.qrCodeService.CreateAsync(url.ToString(), cancellationToken); var base64 = Convert.ToBase64String(bytes); card.Body.Add(new AdaptiveImage() { - AltText = property.InMeetingUrl, + AltText = url.ToString(), Size = AdaptiveImageSize.Stretch, Url = new Uri($"data:image/png;base64,{base64}") }); + card.Actions.Add(new AdaptiveOpenUrlAction() + { + Title = "URL を開く", + Url = url, + }); } var activity = MessageFactory.Attachment(new Attachment() {