From 7b0afd585d2e68b624b9e54232090e96c09c34f1 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Thu, 22 Jul 2021 14:10:07 -0700 Subject: [PATCH] [TextAnalytics] Implemented ExtractiveSummarization input (#22791) Co-authored-by: Mariana Rios Flores --- .../Azure.AI.TextAnalytics.netstandard2.0.cs | 16 +++++- .../src/ExtractSummaryAction.cs | 46 +++++++++++++++++ ...mmarizationTaskParameters.Serialization.cs | 3 +- .../ExtractiveSummarizationTaskParameters.cs | 4 +- ...activeSummarizationTaskParametersSortBy.cs | 51 ------------------- .../SummarySentencesOrder.Serialization.cs | 28 ++++++++++ ...activeSummarizationTaskParametersSortBy.cs | 9 ---- .../src/SummarySentencesOrder.cs | 24 +++++++++ .../src/TextAnalyticsActions.cs | 9 ++++ .../src/TextAnalyticsClient.cs | 7 ++- .../src/TextAnalyticsClientOptions.cs | 8 ++- .../Azure.AI.TextAnalytics/src/Transforms.cs | 26 ++++++++++ .../tests/AnalyzeOperationMockTests.cs | 34 +++++++++++++ 13 files changed, 200 insertions(+), 65 deletions(-) create mode 100644 sdk/textanalytics/Azure.AI.TextAnalytics/src/ExtractSummaryAction.cs delete mode 100644 sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParametersSortBy.cs create mode 100644 sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/SummarySentencesOrder.Serialization.cs delete mode 100644 sdk/textanalytics/Azure.AI.TextAnalytics/src/Internal/ExtractiveSummarizationTaskParametersSortBy.cs create mode 100644 sdk/textanalytics/Azure.AI.TextAnalytics/src/SummarySentencesOrder.cs diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/api/Azure.AI.TextAnalytics.netstandard2.0.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/api/Azure.AI.TextAnalytics.netstandard2.0.cs index 41944658eab5d..d50f9f3d26170 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/api/Azure.AI.TextAnalytics.netstandard2.0.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/api/Azure.AI.TextAnalytics.netstandard2.0.cs @@ -250,6 +250,13 @@ internal ExtractKeyPhrasesResultCollection() : base (default(System.Collections. public string ModelVersion { get { throw null; } } public Azure.AI.TextAnalytics.TextDocumentBatchStatistics Statistics { get { throw null; } } } + public partial class ExtractSummaryAction + { + public ExtractSummaryAction() { } + public int? MaxSentenceCount { get { throw null; } set { } } + public string ModelVersion { get { throw null; } set { } } + public Azure.AI.TextAnalytics.SummarySentencesOrder? OrderBy { get { throw null; } set { } } + } public partial class HealthcareEntity { internal HealthcareEntity() { } @@ -711,6 +718,11 @@ internal SentimentConfidenceScores() { } public double Neutral { get { throw null; } } public double Positive { get { throw null; } } } + public enum SummarySentencesOrder + { + Offset = 0, + Rank = 1, + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct TargetSentiment { @@ -735,6 +747,7 @@ public TextAnalyticsActions() { } public System.Collections.Generic.IReadOnlyCollection AnalyzeSentimentActions { get { throw null; } set { } } public string DisplayName { get { throw null; } set { } } public System.Collections.Generic.IReadOnlyCollection ExtractKeyPhrasesActions { get { throw null; } set { } } + public System.Collections.Generic.IReadOnlyCollection ExtractSummaryActions { get { throw null; } set { } } public System.Collections.Generic.IReadOnlyCollection RecognizeEntitiesActions { get { throw null; } set { } } public System.Collections.Generic.IReadOnlyCollection RecognizeLinkedEntitiesActions { get { throw null; } set { } } public System.Collections.Generic.IReadOnlyCollection RecognizePiiEntitiesActions { get { throw null; } set { } } @@ -811,13 +824,14 @@ public TextAnalyticsClient(System.Uri endpoint, Azure.Core.TokenCredential crede } public partial class TextAnalyticsClientOptions : Azure.Core.ClientOptions { - public TextAnalyticsClientOptions(Azure.AI.TextAnalytics.TextAnalyticsClientOptions.ServiceVersion version = Azure.AI.TextAnalytics.TextAnalyticsClientOptions.ServiceVersion.V3_1) { } + public TextAnalyticsClientOptions(Azure.AI.TextAnalytics.TextAnalyticsClientOptions.ServiceVersion version = Azure.AI.TextAnalytics.TextAnalyticsClientOptions.ServiceVersion.V3_2_Preview_1) { } public string DefaultCountryHint { get { throw null; } set { } } public string DefaultLanguage { get { throw null; } set { } } public enum ServiceVersion { V3_0 = 1, V3_1 = 2, + V3_2_Preview_1 = 3, } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/ExtractSummaryAction.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/ExtractSummaryAction.cs new file mode 100644 index 0000000000000..ea757490a541f --- /dev/null +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/ExtractSummaryAction.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.AI.TextAnalytics +{ + /// + /// Configurations that allow callers to specify details about how to execute + /// an Extractive Text Summarization action in a set of documents. + /// For example, set the model version, specify the order in which extracted + /// sentences are returned, and more. + /// + public class ExtractSummaryAction + { + /// + /// Initializes a new instance of the + /// class which allows callers to specify details about how to execute + /// an Extractive Text Summarization action in a set of documents. + /// For example, set the model version, specify the order in which extracted + /// sentences are returned, and more. + /// + public ExtractSummaryAction() + { + } + + /// + /// Gets or sets a value that, if set, indicates the version of the text + /// analytics model that will be used to generate the result. For supported + /// model versions, see operation-specific documentation, for example: + /// . + /// + public string ModelVersion { get; set; } + + /// + /// If set, specifies the maximum limit of sentences returned in the result. Defaults to 3. + /// + public int? MaxSentenceCount { get; set; } + + /// + /// If set, specifies the order in which the extracted sentences will be returned in the result. Use + /// to keep the original order in which the sentences appear + /// in the input. Use to order them according to their relevance + /// to the document input, as decided by the service. Defaults to . + /// + public SummarySentencesOrder? OrderBy { get; set; } + } +} diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.Serialization.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.Serialization.cs index 42aec87620862..d937d93e591a3 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.Serialization.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.Serialization.cs @@ -6,6 +6,7 @@ #nullable disable using System.Text.Json; +using Azure.AI.TextAnalytics; using Azure.Core; namespace Azure.AI.TextAnalytics.Models @@ -33,7 +34,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) if (Optional.IsDefined(SortBy)) { writer.WritePropertyName("sortBy"); - writer.WriteStringValue(SortBy.Value.ToString()); + writer.WriteStringValue(SortBy.Value.ToSerialString()); } writer.WriteEndObject(); } diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.cs index 8e0e979ed9b02..ee2afa43794bf 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParameters.cs @@ -5,6 +5,8 @@ #nullable disable +using Azure.AI.TextAnalytics; + namespace Azure.AI.TextAnalytics.Models { /// The ExtractiveSummarizationTaskParameters. @@ -18,6 +20,6 @@ public ExtractiveSummarizationTaskParameters() public string ModelVersion { get; set; } public StringIndexType? StringIndexType { get; set; } public int? SentenceCount { get; set; } - public ExtractiveSummarizationTaskParametersSortBy? SortBy { get; set; } + public SummarySentencesOrder? SortBy { get; set; } } } diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParametersSortBy.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParametersSortBy.cs deleted file mode 100644 index 076efc6e60740..0000000000000 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/ExtractiveSummarizationTaskParametersSortBy.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// - -#nullable disable - -using System; -using System.ComponentModel; - -namespace Azure.AI.TextAnalytics.Models -{ - /// The ExtractiveSummarizationTaskParametersSortBy. - internal readonly partial struct ExtractiveSummarizationTaskParametersSortBy : IEquatable - { - private readonly string _value; - - /// Determines if two values are the same. - /// is null. - public ExtractiveSummarizationTaskParametersSortBy(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string OffsetValue = "offset"; - private const string RankValue = "rank"; - - /// offset. - public static ExtractiveSummarizationTaskParametersSortBy Offset { get; } = new ExtractiveSummarizationTaskParametersSortBy(OffsetValue); - /// rank. - public static ExtractiveSummarizationTaskParametersSortBy Rank { get; } = new ExtractiveSummarizationTaskParametersSortBy(RankValue); - /// Determines if two values are the same. - public static bool operator ==(ExtractiveSummarizationTaskParametersSortBy left, ExtractiveSummarizationTaskParametersSortBy right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(ExtractiveSummarizationTaskParametersSortBy left, ExtractiveSummarizationTaskParametersSortBy right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator ExtractiveSummarizationTaskParametersSortBy(string value) => new ExtractiveSummarizationTaskParametersSortBy(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is ExtractiveSummarizationTaskParametersSortBy other && Equals(other); - /// - public bool Equals(ExtractiveSummarizationTaskParametersSortBy other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/SummarySentencesOrder.Serialization.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/SummarySentencesOrder.Serialization.cs new file mode 100644 index 0000000000000..8a2276fdc3427 --- /dev/null +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Generated/Models/SummarySentencesOrder.Serialization.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.AI.TextAnalytics +{ + internal static partial class SummarySentencesOrderExtensions + { + public static string ToSerialString(this SummarySentencesOrder value) => value switch + { + SummarySentencesOrder.Offset => "offset", + SummarySentencesOrder.Rank => "rank", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown SummarySentencesOrder value.") + }; + + public static SummarySentencesOrder ToSummarySentencesOrder(this string value) + { + if (string.Equals(value, "offset", StringComparison.InvariantCultureIgnoreCase)) return SummarySentencesOrder.Offset; + if (string.Equals(value, "rank", StringComparison.InvariantCultureIgnoreCase)) return SummarySentencesOrder.Rank; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown SummarySentencesOrder value."); + } + } +} diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Internal/ExtractiveSummarizationTaskParametersSortBy.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Internal/ExtractiveSummarizationTaskParametersSortBy.cs deleted file mode 100644 index 321155d8396f4..0000000000000 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Internal/ExtractiveSummarizationTaskParametersSortBy.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Azure.AI.TextAnalytics.Models -{ - internal readonly partial struct ExtractiveSummarizationTaskParametersSortBy - { - } -} diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/SummarySentencesOrder.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/SummarySentencesOrder.cs new file mode 100644 index 0000000000000..e97628699e4e3 --- /dev/null +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/SummarySentencesOrder.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Azure.AI.TextAnalytics +{ + /// + /// The order in which extracted sentences will be returned on extractive text summarization. + /// + [CodeGenModel("ExtractiveSummarizationTaskParametersSortBy")] + public enum SummarySentencesOrder + { + /// + /// Keeps the original order in which the sentences appear in the input. + /// + Offset, + + /// + /// Orders sentences according to their relevance to the document input, as decided by the service. + /// + Rank + } +} diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsActions.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsActions.cs index ce4f84691b2e8..7b0eb87778e36 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsActions.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsActions.cs @@ -51,5 +51,14 @@ public TextAnalyticsActions() /// Note that currently only one is supported. /// public IReadOnlyCollection AnalyzeSentimentActions { get; set; } + + /// + /// The set of that will get executed on the input documents. + /// Note that currently only one is supported. + /// + /// + /// This property only applies for and up. + /// + public IReadOnlyCollection ExtractSummaryActions { get; set; } } } diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClient.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClient.cs index 57bcd899f2a29..4cd50b4fd4f67 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClient.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClient.cs @@ -2470,6 +2470,10 @@ private static JobManifestTasks CreateTasks(TextAnalyticsActions actions) { tasks.SentimentAnalysisTasks = Transforms.ConvertFromAnalyzeSentimentActionsToTasks(actions.AnalyzeSentimentActions); } + if (actions.ExtractSummaryActions != null) + { + tasks.ExtractiveSummarizationTasks = Transforms.ConvertFromExtractSummaryActionsToTasks(actions.ExtractSummaryActions); + } return tasks; } @@ -2479,7 +2483,8 @@ private static void ValidateActions(TextAnalyticsActions actions) actions.RecognizeEntitiesActions?.Count > 1 || actions.RecognizeLinkedEntitiesActions?.Count > 1 || actions.ExtractKeyPhrasesActions?.Count > 1 || - actions.AnalyzeSentimentActions?.Count > 1) + actions.AnalyzeSentimentActions?.Count > 1 || + actions.ExtractSummaryActions?.Count > 1) { throw new ArgumentException("Multiple of the same action is not currently supported."); } diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClientOptions.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClientOptions.cs index 91d2028941d94..a7392ce61e009 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClientOptions.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/TextAnalyticsClientOptions.cs @@ -16,7 +16,7 @@ public class TextAnalyticsClientOptions : ClientOptions /// /// The latest service version supported by this client library. /// - internal const ServiceVersion LatestVersion = ServiceVersion.V3_1; + internal const ServiceVersion LatestVersion = ServiceVersion.V3_2_Preview_1; /// /// The versions of the Text Analytics service supported by this client library. @@ -33,6 +33,11 @@ public enum ServiceVersion /// Version 3.1 /// V3_1 = 2, + + /// + /// Version 3.2-preview.1 + /// + V3_2_Preview_1 = 3 #pragma warning restore CA1707 // Identifiers should not contain underscores } @@ -75,6 +80,7 @@ internal static string GetVersionString(ServiceVersion version) { ServiceVersion.V3_0 => "v3.0", ServiceVersion.V3_1 => "v3.1", + ServiceVersion.V3_2_Preview_1 => "v3.1", _ => throw new ArgumentException($"Version {version} not supported."), }; diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Transforms.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Transforms.cs index 8084f2c8702f5..57432ff2c26df 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/src/Transforms.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/src/Transforms.cs @@ -393,6 +393,20 @@ internal static SentimentAnalysisTask ConvertToSentimentAnalysisTask(AnalyzeSent }; } + internal static ExtractiveSummarizationTask ConvertToExtractiveSummarizationTask(ExtractSummaryAction action) + { + return new ExtractiveSummarizationTask() + { + Parameters = new ExtractiveSummarizationTaskParameters() + { + ModelVersion = action.ModelVersion, + StringIndexType = Constants.DefaultStringIndexType, + SentenceCount = action.MaxSentenceCount, + SortBy = action.OrderBy + } + }; + } + internal static IList ConvertFromRecognizeLinkedEntitiesActionsToTasks(IReadOnlyCollection recognizeLinkedEntitiesActions) { List list = new List(); @@ -453,6 +467,18 @@ internal static IList ConvertFromAnalyzeSentimentActionsT return list; } + internal static IList ConvertFromExtractSummaryActionsToTasks(IReadOnlyCollection extractSummaryActions) + { + List list = new List(); + + foreach (ExtractSummaryAction action in extractSummaryActions) + { + list.Add(ConvertToExtractiveSummarizationTask(action)); + } + + return list; + } + private static string[] parseActionErrorTarget(string targetReference) { if (string.IsNullOrEmpty(targetReference)) diff --git a/sdk/textanalytics/Azure.AI.TextAnalytics/tests/AnalyzeOperationMockTests.cs b/sdk/textanalytics/Azure.AI.TextAnalytics/tests/AnalyzeOperationMockTests.cs index e78a4b0bfc49f..2eb457cca3860 100644 --- a/sdk/textanalytics/Azure.AI.TextAnalytics/tests/AnalyzeOperationMockTests.cs +++ b/sdk/textanalytics/Azure.AI.TextAnalytics/tests/AnalyzeOperationMockTests.cs @@ -707,6 +707,40 @@ public void AnalyzeOperationAnalyzeSentimentWithTwoActions() #endregion Analyze sentiment + #region Extract summary + + [Test] + public void AnalyzeOperationExtractsSummaryWithTwoActions() + { + var mockResponse = new MockResponse(202); + mockResponse.AddHeader(new HttpHeader("Operation-Location", "something/jobs/2a96a91f-7edf-4931-a880-3fdee1d56f15")); + + var mockTransport = new MockTransport(new[] { mockResponse, mockResponse }); + var client = CreateTestClient(mockTransport); + + var documents = new List + { + "Elon Musk is the CEO of SpaceX and Tesla." + }; + + TextAnalyticsActions batchActions = new() + { + ExtractSummaryActions = new List() + { + new ExtractSummaryAction(), + new ExtractSummaryAction() + { + ModelVersion = "InvalidVersion" + } + }, + }; + + ArgumentException ex = Assert.ThrowsAsync(async () => await client.StartAnalyzeActionsAsync(documents, batchActions)); + Assert.AreEqual("Multiple of the same action is not currently supported.", ex.Message); + } + + #endregion Extract summary + [Test] public async Task AnalyzeOperationWithActionsError() {