diff --git a/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs b/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs index b8e34f15..913a0ea2 100644 --- a/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs +++ b/AIDevGallery.SourceGenerator/SamplesSourceGenerator.cs @@ -188,6 +188,7 @@ private void ExecuteSharedCodeEnumGeneration(SourceProductionContext context, Im context.AddSource("SharedCodeEnum.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); } + private static readonly Regex UsingAIDevGalleryTelemetryNamespace = new(@"using AIDevGallery.Telemetry\S*;\r?\n", RegexOptions.Multiline | RegexOptions.Compiled); private static readonly Regex GallerySampleAttributeRemovalRegex = new(@"\n(\s)*\[GallerySample\((?>[^()]+|\((?)|\)(?<-DEPTH>))*(?(DEPTH)(?!))\)\]", RegexOptions.Compiled); private static readonly Regex ExcludedElementXamlRemovalRegex = new(@")|(.*<\/EXCLUDE:[a-zA-Z]*>))", RegexOptions.Singleline | RegexOptions.Compiled); private static readonly Regex ExcludedAttrbitueXamlRemovalRegex = new(@"EXCLUDE:[^""]*""[^""]*""", RegexOptions.Singleline | RegexOptions.Compiled); @@ -203,6 +204,7 @@ private static string SampleSourceCleanUp(string input, string filePath) .TrimStart(); } + input = UsingAIDevGalleryTelemetryNamespace.Replace(input, string.Empty); input = GallerySampleAttributeRemovalRegex.Replace(input, string.Empty); input = RemoveExcludedLinesCs(input, filePath); @@ -248,7 +250,7 @@ private static string RemoveExcludedLinesCs(string input, string filePath) lines.RemoveAt(i); } - else if (lines[i].Contains("// ") || lines[i].Contains("//")) + else if (lines[i].Contains("// ") || lines[i].Contains("//") || lines[i].Contains("SendSampleInteractedEvent")) { lines.RemoveAt(i); } diff --git a/AIDevGallery/ProjectGenerator/Generator.cs b/AIDevGallery/ProjectGenerator/Generator.cs index 0c1f115b..26f590af 100644 --- a/AIDevGallery/ProjectGenerator/Generator.cs +++ b/AIDevGallery/ProjectGenerator/Generator.cs @@ -698,24 +698,24 @@ private string CleanXamlSource(string xamlCode, string newNamespace, out string } [GeneratedRegex(@"using AIDevGallery\S*;\r?\n", RegexOptions.Multiline)] - private static partial Regex UsingAIDevGalleryGNamespace(); + private static partial Regex UsingAIDevGalleryNamespace(); [GeneratedRegex(@"namespace AIDevGallery(?:[^;\r\n])*(;?)\r\n", RegexOptions.Multiline)] - private static partial Regex AIDevGalleryGNamespace(); + private static partial Regex AIDevGalleryNamespace(); private static string CleanCsSource(string source, string newNamespace, bool addSharedSourceNamespace) { // Remove the using statements for the AIDevGallery.* namespaces - source = UsingAIDevGalleryGNamespace().Replace(source, string.Empty); + source = UsingAIDevGalleryNamespace().Replace(source, string.Empty); source = source.Replace("\r\r", "\r"); // Replace the AIDevGallery namespace with the namespace of the new project // consider the 1st capture group to add the ; or not - var match = AIDevGalleryGNamespace().Match(source); + var match = AIDevGalleryNamespace().Match(source); if (match.Success) { - source = AIDevGalleryGNamespace().Replace(source, $"namespace {newNamespace}{match.Groups[1].Value}{Environment.NewLine}"); + source = AIDevGalleryNamespace().Replace(source, $"namespace {newNamespace}{match.Groups[1].Value}{Environment.NewLine}"); } if (addSharedSourceNamespace) diff --git a/AIDevGallery/Samples/Open Source Models/Embeddings/SemanticSearch.xaml.cs b/AIDevGallery/Samples/Open Source Models/Embeddings/SemanticSearch.xaml.cs index e743b1f6..a5a29d84 100644 --- a/AIDevGallery/Samples/Open Source Models/Embeddings/SemanticSearch.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Embeddings/SemanticSearch.xaml.cs @@ -129,6 +129,8 @@ public void Search(string sourceText, string searchText) return; } + SendSampleInteractedEvent("Search"); // + Task.Run( async () => { diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/ESRGAN/SuperResolution.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/ESRGAN/SuperResolution.xaml.cs index c2c9e07d..1262ea6c 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/ESRGAN/SuperResolution.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/ESRGAN/SuperResolution.xaml.cs @@ -113,6 +113,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) { // Call function to run inference and classify image UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await EnhanceImage(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/FFNet/SegmentStreets.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/FFNet/SegmentStreets.xaml.cs index 6dee6240..d74551a6 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/FFNet/SegmentStreets.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/FFNet/SegmentStreets.xaml.cs @@ -113,6 +113,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) if (file != null) { UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await Segment(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/Faster RCNN/ObjectDetection.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/Faster RCNN/ObjectDetection.xaml.cs index 93242ad7..a9a569c5 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/Faster RCNN/ObjectDetection.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/Faster RCNN/ObjectDetection.xaml.cs @@ -99,6 +99,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) if (file != null) { UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await DetectObjects(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/HRNetPose/PoseDetection.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/HRNetPose/PoseDetection.xaml.cs index 29bd675f..fc3a7830 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/HRNetPose/PoseDetection.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/HRNetPose/PoseDetection.xaml.cs @@ -111,6 +111,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) if (file != null) { UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await DetectPose(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/ImageNet/ImageClassification.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/ImageNet/ImageClassification.xaml.cs index 1ba79639..3016300c 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/ImageNet/ImageClassification.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/ImageNet/ImageClassification.xaml.cs @@ -115,6 +115,7 @@ private async void UploadImageButton_Click(object sender, RoutedEventArgs e) if (file != null) { UploadImageButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await ClassifyImage(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/MultiHRNetPose/Multipose.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/MultiHRNetPose/Multipose.xaml.cs index 35ef7756..3025e3c9 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/MultiHRNetPose/Multipose.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/MultiHRNetPose/Multipose.xaml.cs @@ -138,6 +138,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) { // Call function to run inference and classify image UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await RunPipeline(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Image Models/YOLOv4/YOLOObjectionDetection.xaml.cs b/AIDevGallery/Samples/Open Source Models/Image Models/YOLOv4/YOLOObjectionDetection.xaml.cs index ca65c370..5301c39d 100644 --- a/AIDevGallery/Samples/Open Source Models/Image Models/YOLOv4/YOLOObjectionDetection.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Image Models/YOLOv4/YOLOObjectionDetection.xaml.cs @@ -112,6 +112,7 @@ private async void UploadButton_Click(object sender, RoutedEventArgs e) { // Call function to run inference and classify image UploadButton.Focus(FocusState.Programmatic); + SendSampleInteractedEvent("FileSelected"); // await DetectObjects(file.Path); } } diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/ContentModeration.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/ContentModeration.xaml.cs index dd5f32c5..cb242d2d 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/ContentModeration.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/ContentModeration.xaml.cs @@ -72,6 +72,7 @@ public void GenerateText(string prompt) InputTextBox.IsEnabled = false; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Moderating content, please wait.", "ContentModerationWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("GenerateText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/CustomSystemPrompt.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/CustomSystemPrompt.xaml.cs index bf35ce08..f6768c38 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/CustomSystemPrompt.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/CustomSystemPrompt.xaml.cs @@ -160,6 +160,7 @@ public void GenerateText(string query, string systemPrompt) InputTextBox.IsEnabled = false; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Generating content, please wait.", "CustomPromptWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("GenerateText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/ExplainCode.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/ExplainCode.xaml.cs index 5079d6a7..904790b1 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/ExplainCode.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/ExplainCode.xaml.cs @@ -89,6 +89,7 @@ public void Explain(string code) ExplainButton.Visibility = Visibility.Collapsed; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Analyzing code, please wait.", "ExplainCodeWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("Explain"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/Generate.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/Generate.xaml.cs index dbcf2af4..6804dc6d 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/Generate.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/Generate.xaml.cs @@ -87,6 +87,7 @@ public void GenerateText(string topic) InputTextBox.IsEnabled = false; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Generating content, please wait.", "GenerateTextWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("GenerateText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/GenerateCode.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/GenerateCode.xaml.cs index 0fc151ea..13775507 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/GenerateCode.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/GenerateCode.xaml.cs @@ -91,6 +91,8 @@ public void GenerateSolution(string problem, string currentLanguage) return; } + SendSampleInteractedEvent("GenerateSolution"); // + string generatedCode = string.Empty; this.GenerateRichTextBlock.Blocks.Clear(); GenerateButton.Visibility = Visibility.Collapsed; diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/GrammarCheck.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/GrammarCheck.xaml.cs index 204ee3e7..e81ba415 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/GrammarCheck.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/GrammarCheck.xaml.cs @@ -84,6 +84,7 @@ public void GrammarCheckText(string text) CheckGrammarButton.Visibility = Visibility.Collapsed; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Checking grammar, please wait.", "GrammarCheckWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("GrammarCheckText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/Paraphrase.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/Paraphrase.xaml.cs index 40c794c8..ce833dd6 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/Paraphrase.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/Paraphrase.xaml.cs @@ -83,6 +83,7 @@ public void ParaphraseText(string text) ParaphraseButton.Visibility = Visibility.Collapsed; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Paraphrasing text, please wait.", "ParaphraseWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("ParaphraseText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/SentimentAnalysis.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/SentimentAnalysis.xaml.cs index 46bfd698..c0558255 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/SentimentAnalysis.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/SentimentAnalysis.xaml.cs @@ -84,6 +84,7 @@ public void AnalyzeSentiment(string text) SentimentTextBlock.Text = string.Empty; SentimentButton.Visibility = Visibility.Collapsed; NarratorHelper.Announce(InputTextBox, "Checking sentiment, please wait.", "SentimentCheckWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("AnalyzeSentiment"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/Summarize.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/Summarize.xaml.cs index d8d15095..d590e5e0 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/Summarize.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/Summarize.xaml.cs @@ -81,6 +81,7 @@ public void SummarizeText(string text) SummarizeButton.Visibility = Visibility.Collapsed; var contentStartedBeingGenerated = false; // NarratorHelper.Announce(InputTextBox, "Summarizing content, please wait.", "SummarizeTextWaitAnnouncementActivityId"); // + SendSampleInteractedEvent("SummarizeText"); // Task.Run( async () => diff --git a/AIDevGallery/Samples/Open Source Models/Language Models/Translate.xaml.cs b/AIDevGallery/Samples/Open Source Models/Language Models/Translate.xaml.cs index 8b5d1dcc..80270590 100644 --- a/AIDevGallery/Samples/Open Source Models/Language Models/Translate.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Language Models/Translate.xaml.cs @@ -82,6 +82,7 @@ public void TranslateText(string text) // var contentStartedBeingGenerated = false; NarratorHelper.Announce(InputTextBox, "Translating content, please wait.", "TranslateTextWaitAnnouncementActivityId"); + SendSampleInteractedEvent("TranslateText"); // // if (LanguageBox.SelectedItem is string language) diff --git a/AIDevGallery/Samples/Open Source Models/Multimodal Models/DescribeImage.xaml.cs b/AIDevGallery/Samples/Open Source Models/Multimodal Models/DescribeImage.xaml.cs index bec22b45..3e1268d7 100644 --- a/AIDevGallery/Samples/Open Source Models/Multimodal Models/DescribeImage.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Multimodal Models/DescribeImage.xaml.cs @@ -216,6 +216,7 @@ private async Task DescribeTheImage() Loader.Visibility = Visibility.Visible; _cts.Token.ThrowIfCancellationRequested(); + SendSampleInteractedEvent("DescribeTheImage"); // await Task.Run(async () => { diff --git a/AIDevGallery/Samples/Open Source Models/Stable Diffusion/GenerateImage.xaml.cs b/AIDevGallery/Samples/Open Source Models/Stable Diffusion/GenerateImage.xaml.cs index 418737b5..045c1c51 100644 --- a/AIDevGallery/Samples/Open Source Models/Stable Diffusion/GenerateImage.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Stable Diffusion/GenerateImage.xaml.cs @@ -137,6 +137,7 @@ private async Task DoStableDiffusion() InputBox.IsEnabled = false; CancellationToken token = CancelGenerationAndGetNewToken(); + SendSampleInteractedEvent("GenerateImage"); // inferenceTask = Task.Run( () => @@ -217,6 +218,7 @@ private async void SaveButton_Click(object sender, RoutedEventArgs e) if(file != null && DefaultImage.Source != null) { + SendSampleInteractedEvent("SaveFile"); // RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(); await renderTargetBitmap.RenderAsync(DefaultImage); diff --git a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranscription.xaml.cs b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranscription.xaml.cs index 6614c388..16286b28 100644 --- a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranscription.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranscription.xaml.cs @@ -165,6 +165,7 @@ private async Task TranscribeAudio() return "Invalid language selected"; } + SendSampleInteractedEvent("TranscribeAudio"); // cts = new CancellationTokenSource(); var transcribedChunks = await whisper.TranscribeAsync(audioData, sourceLanguage, WhisperWrapper.TaskType.Transcribe, (bool)TimeStampsToggle.IsChecked!, cts.Token); diff --git a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranslation.xaml.cs b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranslation.xaml.cs index dcd1ea48..7df229ce 100644 --- a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranslation.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperAudioTranslation.xaml.cs @@ -113,6 +113,7 @@ private async Task TranslateAudioAsync() return; } + SendSampleInteractedEvent("TranslateAudio"); // try { var audioData = audioStream.ToArray(); diff --git a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperLiveTranscription.xaml.cs b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperLiveTranscription.xaml.cs index dd026e7f..719412e8 100644 --- a/AIDevGallery/Samples/Open Source Models/Whisper/WhisperLiveTranscription.xaml.cs +++ b/AIDevGallery/Samples/Open Source Models/Whisper/WhisperLiveTranscription.xaml.cs @@ -72,6 +72,7 @@ private void StartStopButton_Click(object sender, RoutedEventArgs e) { audioRecorder.StopRecording(); StartStopButton.Content = "Start Recording"; + SendSampleInteractedEvent("StartRecording"); // } else { diff --git a/AIDevGallery/Samples/SharedCode/SemanticComboBox.cs b/AIDevGallery/Samples/SharedCode/SemanticComboBox.cs index 68c7f9e5..51ea28c7 100644 --- a/AIDevGallery/Samples/SharedCode/SemanticComboBox.cs +++ b/AIDevGallery/Samples/SharedCode/SemanticComboBox.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using AIDevGallery.Telemetry.Events; using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Connectors.InMemory; @@ -74,6 +75,7 @@ public async Task> Search(string searchTerm) return []; } + SampleInteractionEvent.SendSampleInteractedEvent(EmbeddingGenerator.Metadata, Models.ScenarioType.SmartControlsSemanticComboBox, "Search"); // GeneratedEmbeddings> results = []; var searchVectors = await EmbeddingGenerator.GenerateAsync([searchTerm]); diff --git a/AIDevGallery/Samples/SharedCode/SmartPasteForm.cs b/AIDevGallery/Samples/SharedCode/SmartPasteForm.cs index d46e3f14..744af2eb 100644 --- a/AIDevGallery/Samples/SharedCode/SmartPasteForm.cs +++ b/AIDevGallery/Samples/SharedCode/SmartPasteForm.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using AIDevGallery.Telemetry.Events; using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.Extensions.AI; using Microsoft.UI.Xaml; @@ -99,6 +100,7 @@ private async Task> InferPasteValues(string clipboard return []; } + SampleInteractionEvent.SendSampleInteractedEvent(model, Models.ScenarioType.SmartControlsSmartPaste, "InferPasteValues"); // string outputMessage = string.Empty; PromptInput input = new() { diff --git a/AIDevGallery/Samples/SharedCode/SmartTextBox.cs b/AIDevGallery/Samples/SharedCode/SmartTextBox.cs index 7e1eff79..78d20f24 100644 --- a/AIDevGallery/Samples/SharedCode/SmartTextBox.cs +++ b/AIDevGallery/Samples/SharedCode/SmartTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using AIDevGallery.Models; +using AIDevGallery.Telemetry.Events; using Microsoft.Extensions.AI; using Microsoft.UI.Input; using Microsoft.UI.Text; @@ -98,6 +100,7 @@ private async Task Infer(string systemPrompt, string query, ChatOptions? private async Task ChangeToneProfessional(string textToChange) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "ChangeToneProfessional"); // string systemPrompt = "You rewrite user-provided writing to adjust the tone of the text. In this case, you will rewrite whatever is provided to sound more \"professional\". When provided with text, respond with only the tone-adjusted version of the text and nothing else. Keep the underlying meaning of the text the same and of around the same length as the source material. Do NOT be overly formal but be polite, succinct, and you MUST USE command MODERN American English. Respond with ONLY the tone-adjusted text and DO NOT provide an explanation, note, or any sort of justification of your changes."; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + textToChange.Length; @@ -106,6 +109,7 @@ private async Task ChangeToneProfessional(string textToChange) private async Task ChangeToneCasual(string textToChange) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "ChangeToneCasual"); // string systemPrompt = "You rewrite user-provided writing to adjust the tone of the text. In this case, you will rewrite whatever is provided to sound more \"casual\". When provided with text, respond with only the tone-adjusted version of the text and nothing else. Keep the underlying meaning of the text the same and of around the same length as the source material. Do not be inappropriate but be friendly, succinct, and use every day American English. Respond with ONLY the tone-adjusted text and DO NOT provide an explanation, note, or any sort of justification of your changes."; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + textToChange.Length; @@ -114,6 +118,7 @@ private async Task ChangeToneCasual(string textToChange) private async Task Shorten(string textToChange) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "Shorten"); // string systemPrompt = "You change the length of user-provided text to be shorter. When provided with text, respond with only shortened version of the text and nothing else. Maintain the original meaning as much as possible. Respond with ONLY the shortened text and DO NOT provide an explanation, note, or any sort of justification of your changes."; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + textToChange.Length; @@ -122,6 +127,7 @@ private async Task Shorten(string textToChange) private async Task Lengthen(string textToChange) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "Lengthen"); // string systemPrompt = "You change the length of user-provided text to be longer. When provided with text, respond with only lengthened version of the text and nothing else. Maintain the original meaning as much as possible. Respond with ONLY the lengthened text and DO NOT provide an explanation, note, or any sort of justification of your changes."; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + 2 * textToChange.Length; @@ -130,6 +136,7 @@ private async Task Lengthen(string textToChange) private async Task Proofread(string textToChange) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "Proofread"); // string systemPrompt = "You proofread user-provided text to remove spelling mistakes and grammar mistakes. When provided with text, respond with only spelling and grammar corrected text and nothing else. Maintain the original meaning as much as possible. Respond with ONLY the corrected text and DO NOT provide an explanation, note, or any sort of justification of your changes."; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + textToChange.Length; @@ -138,6 +145,7 @@ private async Task Proofread(string textToChange) private async Task DescribeChanges(string textToChange, string changes) { + SampleInteractionEvent.SendSampleInteractedEvent(_chatClient, ScenarioType.SmartControlsSmartTextBox, "DescribeChanges"); // string systemPrompt = "You apply user-defined changes to text. When provided with text, apply the described changes to the text. Respond with only the changed text. Respond with ONLY the changed text and DO NOT provide an explanation, note, any sort of justification of your changes. The changes are: " + changes + ". The provided text is: " + textToChange; ChatOptions chatOptions = GenAIModel.GetDefaultChatOptions(); chatOptions.MaxOutputTokens = systemPrompt.Length + textToChange.Length; diff --git a/AIDevGallery/Telemetry/Events/SampleInteractionEvent.cs b/AIDevGallery/Telemetry/Events/SampleInteractionEvent.cs index d7206f87..b4bf5dea 100644 --- a/AIDevGallery/Telemetry/Events/SampleInteractionEvent.cs +++ b/AIDevGallery/Telemetry/Events/SampleInteractionEvent.cs @@ -4,8 +4,10 @@ using AIDevGallery.Models; using Microsoft.Diagnostics.Telemetry; using Microsoft.Diagnostics.Telemetry.Internal; +using Microsoft.Extensions.AI; using System; using System.Diagnostics.Tracing; +using System.Linq; namespace AIDevGallery.Telemetry.Events; @@ -40,4 +42,34 @@ public static void Log(string sampleId, string model1Id, HardwareAccelerator har { TelemetryFactory.Get().Log("SampleInteraction_Event", LogLevel.Critical, new SampleInteractionEvent(sampleId, model1Id, hardwareAccelerator1, model2Id, hardwareAccelerator2, customInfo)); } + + public static void SendSampleInteractedEvent(IChatClient? chatClient, ScenarioType scenario, string? customInfo = null) + { + SendSampleInteractedEvent(chatClient?.Metadata.ProviderUri, scenario, customInfo); + } + + public static void SendSampleInteractedEvent(EmbeddingGeneratorMetadata embeddingGeneratorMetadata, ScenarioType scenario, string? customInfo = null) + { + SendSampleInteractedEvent(embeddingGeneratorMetadata.ProviderUri, scenario, customInfo); + } + + private static void SendSampleInteractedEvent(Uri? providerUri, ScenarioType scenario, string? customInfo = null) + { + var modelPath = providerUri?.ToString(); + + if (modelPath != null && modelPath.StartsWith("file:///", StringComparison.OrdinalIgnoreCase)) + { + modelPath = modelPath + .Substring(8) // Remove "file:///" + .Replace('/', '\\'); // Convert to Windows path + + var cachedModel = App.ModelCache.GetCachedModelByPath(modelPath); + if (cachedModel != null) + { + var modelDetails = cachedModel.Details; + var sample = Samples.SampleDetails.Samples.First(s => s.Scenario == scenario); + Log(sample.Id, modelDetails.Id, modelDetails.HardwareAccelerators.First(), null, null, customInfo); + } + } + } } \ No newline at end of file diff --git a/AIDevGallery/Utils/ModelCache.cs b/AIDevGallery/Utils/ModelCache.cs index 1effbd6c..e66a4748 100644 --- a/AIDevGallery/Utils/ModelCache.cs +++ b/AIDevGallery/Utils/ModelCache.cs @@ -88,6 +88,11 @@ public async Task SetCacheFolderPath(string newPath, List? models = return CacheStore.Models.FirstOrDefault(m => m.Url == url); } + public CachedModel? GetCachedModelByPath(string path) + { + return CacheStore.Models.FirstOrDefault(m => m.Path == path); + } + public bool IsModelCached(string url) { url = UrlHelpers.GetFullUrl(url);