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

[Text Analytics] Analyze design update #18406

Merged
merged 25 commits into from
Feb 8, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions sdk/textanalytics/Azure.AI.TextAnalytics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,25 +493,25 @@ The Analyze functionality allows to choose which of the supported Text Analytics

var batchDocuments = new List<string> { document };

AnalyzeOperationOptions operationOptions = new AnalyzeOperationOptions()
TextAnalyticsActions batchActions = new TextAnalyticsActions()
{
KeyPhrasesTaskParameters = new KeyPhrasesTaskParameters(),
EntitiesTaskParameters = new EntitiesTaskParameters(),
PiiTaskParameters = new PiiTaskParameters(),
ExtractKeyPhrasesOptions = new List<ExtractKeyPhrasesOptions>() { new ExtractKeyPhrasesOptions() },
RecognizeEntitiesOptions = new List<RecognizeEntitiesOptions>() { new RecognizeEntitiesOptions() },
RecognizePiiEntitiesOptions = new List<RecognizePiiEntitiesOptions>() { new RecognizePiiEntitiesOptions() },
DisplayName = "AnalyzeOperationSample"
};

AnalyzeOperation operation = client.StartAnalyzeOperationBatch(batchDocuments, operationOptions);
AnalyzeBatchActionsOperation operation = client.StartAnalyzeBatchActions(batchDocuments, batchActions);

await operation.WaitForCompletionAsync();
operation.WaitForCompletionAsync();

foreach (AnalyzeOperationResult documentsInPage in operation.GetValues())
foreach (AnalyzeBatchActionsResult documentsInPage in operation.GetValues())
{
RecognizeEntitiesResultCollection entitiesResult = documentsInPage.Tasks.EntityRecognitionTasks[0].Results;
RecognizeEntitiesResultCollection entitiesResult = documentsInPage.RecognizeEntitiesActionsResults.FirstOrDefault().Result;

ExtractKeyPhrasesResultCollection keyPhrasesResult = documentsInPage.Tasks.KeyPhraseExtractionTasks[0].Results;
ExtractKeyPhrasesResultCollection keyPhrasesResult = documentsInPage.ExtractKeyPhrasesActionsResults.FirstOrDefault().Result;

RecognizePiiEntitiesResultCollection piiResult = documentsInPage.Tasks.EntityRecognitionPiiTasks[0].Results;
RecognizePiiEntitiesResultCollection piiResult = documentsInPage.RecognizePiiEntitiesActionsResults.FirstOrDefault().Result;

Console.WriteLine("Recognized Entities");

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,25 @@ To run analyze operation in multiple documents, call `StartAnalyzeOperationBatch

var batchDocuments = new List<string> { document };

AnalyzeOperationOptions operationOptions = new AnalyzeOperationOptions()
TextAnalyticsActions batchActions = new TextAnalyticsActions()
{
KeyPhrasesTaskParameters = new KeyPhrasesTaskParameters(),
EntitiesTaskParameters = new EntitiesTaskParameters(),
PiiTaskParameters = new PiiTaskParameters(),
ExtractKeyPhrasesOptions = new List<ExtractKeyPhrasesOptions>() { new ExtractKeyPhrasesOptions() },
RecognizeEntitiesOptions = new List<RecognizeEntitiesOptions>() { new RecognizeEntitiesOptions() },
RecognizePiiEntitiesOptions = new List<RecognizePiiEntitiesOptions>() { new RecognizePiiEntitiesOptions() },
DisplayName = "AnalyzeOperationSample"
};

AnalyzeOperation operation = client.StartAnalyzeOperationBatch(batchDocuments, operationOptions);
AnalyzeBatchActionsOperation operation = client.StartAnalyzeBatchActions(batchDocuments, batchActions);

await operation.WaitForCompletionAsync();
operation.WaitForCompletionAsync();

foreach (AnalyzeOperationResult documentsInPage in operation.GetValues())
foreach (AnalyzeBatchActionsResult documentsInPage in operation.GetValues())
{
RecognizeEntitiesResultCollection entitiesResult = documentsInPage.Tasks.EntityRecognitionTasks[0].Results;
RecognizeEntitiesResultCollection entitiesResult = documentsInPage.RecognizeEntitiesActionsResults.FirstOrDefault().Result;

ExtractKeyPhrasesResultCollection keyPhrasesResult = documentsInPage.Tasks.KeyPhraseExtractionTasks[0].Results;
ExtractKeyPhrasesResultCollection keyPhrasesResult = documentsInPage.ExtractKeyPhrasesActionsResults.FirstOrDefault().Result;

RecognizePiiEntitiesResultCollection piiResult = documentsInPage.Tasks.EntityRecognitionPiiTasks[0].Results;
RecognizePiiEntitiesResultCollection piiResult = documentsInPage.RecognizePiiEntitiesActionsResults.FirstOrDefault().Result;

Console.WriteLine("Recognized Entities");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,60 @@

namespace Azure.AI.TextAnalytics
{
/// <summary> The AnalyzeOperation class for LRO. </summary>
public class AnalyzeOperation : PageableOperation<AnalyzeOperationResult>
/// <summary> Pageable operation class for analyzing multiple actions using long running operation. </summary>
public class AnalyzeBatchActionsOperation : PageableOperation<AnalyzeBatchActionsResult>
{
/// <summary>Provides communication with the Form Recognizer Azure Cognitive Service through its REST API.</summary>
private readonly TextAnalyticsRestClient _serviceClient;

/// <summary>Provides tools for exception creation in case of failure.</summary>
private readonly ClientDiagnostics _diagnostics;

/// <summary>
/// Total actions failed in the operation
/// </summary>
public int ActionsFailed => _actionsFailed;

/// <summary>
/// Total actions in progress in the operation
/// </summary>
public int ActionsInProgress => _actionsInProgress;

/// <summary>
/// Total actions succeeded in the operation
/// </summary>
public int ActionsSucceeded => _actionSucceeded;

/// <summary>
/// Time when the operation was created on.
/// </summary>
public DateTimeOffset CreatedOn => _createdOn;

/// <summary>
/// Display Name of the operation
/// </summary>
public string DisplayName => _displayName;

/// <summary>
/// Time when the operation will expire.
/// </summary>
public DateTimeOffset? ExpiresOn => _expiresOn;

/// <summary>
/// Time when the operation was last modified on.
/// </summary>
public DateTimeOffset LastModified => _lastModified;

/// <summary>
/// The current status of the operation.
/// </summary>
public TextAnalyticsOperationStatus Status => _status;

/// <summary>
/// Total actions executed in the operation
/// </summary>
public int TotalActions => _totalActions;

/// <summary>
/// Gets an ID representing the operation that can be used to poll for the status
/// of the long-running operation.
Expand All @@ -38,13 +83,23 @@ public class AnalyzeOperation : PageableOperation<AnalyzeOperationResult>
/// <remarks>
/// This property can be accessed only after the operation completes successfully (HasValue is true).
/// </remarks>
public override AsyncPageable<AnalyzeOperationResult> Value => GetValuesAsync();
public override AsyncPageable<AnalyzeBatchActionsResult> Value => GetValuesAsync();

/// <summary>
/// <c>true</c> if the long-running operation has completed. Otherwise, <c>false</c>.
/// </summary>
private bool _hasCompleted;

private int _totalActions;
private int _actionsFailed;
private int _actionSucceeded;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: _actionsSucceeded

private int _actionsInProgress;
private DateTimeOffset _createdOn;
private DateTimeOffset? _expiresOn;
private DateTimeOffset _lastModified;
suhas92 marked this conversation as resolved.
Show resolved Hide resolved
private TextAnalyticsOperationStatus _status;
private string _displayName;

/// <summary>
/// Returns true if the long-running operation completed.
/// </summary>
Expand All @@ -63,7 +118,7 @@ public class AnalyzeOperation : PageableOperation<AnalyzeOperationResult>
/// <summary>
/// Provides the results for the first page.
/// </summary>
private Page<AnalyzeOperationResult> _firstPage;
private Page<AnalyzeBatchActionsResult> _firstPage;

/// <summary>
/// Represents the desire of the user to request statistics.
Expand All @@ -82,11 +137,11 @@ public class AnalyzeOperation : PageableOperation<AnalyzeOperationResult>
public override bool HasValue => _firstPage != null;

/// <summary>
/// Initializes a new instance of the <see cref="AnalyzeOperation"/> class.
/// Initializes a new instance of the <see cref="AnalyzeBatchActionsOperation"/> class.
/// </summary>
/// <param name="operationId">The ID of this operation.</param>
/// <param name="client">The client used to check for completion.</param>
public AnalyzeOperation(string operationId, TextAnalyticsClient client)
public AnalyzeBatchActionsOperation(string operationId, TextAnalyticsClient client)
{
// TODO: Add argument validation here.

Expand All @@ -96,15 +151,15 @@ public AnalyzeOperation(string operationId, TextAnalyticsClient client)
}

/// <summary>
/// Initializes a new instance of the <see cref="AnalyzeOperation"/> class.
/// Initializes a new instance of the <see cref="AnalyzeBatchActionsOperation"/> class.
/// </summary>
/// <param name="serviceClient">The client for communicating with the Form Recognizer Azure Cognitive Service through its REST API.</param>
/// <param name="diagnostics">The client diagnostics for exception creation in case of failure.</param>
/// <param name="apiversion">The specific api version to use.</param>
/// <param name="operationLocation">The address of the long-running operation. It can be obtained from the response headers upon starting the operation.</param>
/// <param name="idToIndexMap"></param>
/// <param name="showStats"></param>
internal AnalyzeOperation(TextAnalyticsRestClient serviceClient, ClientDiagnostics diagnostics, string apiversion, string operationLocation, IDictionary<string, int> idToIndexMap, bool? showStats = default)
internal AnalyzeBatchActionsOperation(TextAnalyticsRestClient serviceClient, ClientDiagnostics diagnostics, string apiversion, string operationLocation, IDictionary<string, int> idToIndexMap, bool? showStats = default)
{
_serviceClient = serviceClient;
_diagnostics = diagnostics;
Expand All @@ -122,7 +177,7 @@ internal AnalyzeOperation(TextAnalyticsRestClient serviceClient, ClientDiagnosti
/// </summary>
/// <remarks>
/// The last response returned from the server during the lifecycle of this instance.
/// An instance of <see cref="AnalyzeOperation"/> sends requests to a server in UpdateStatusAsync, UpdateStatus, and other methods.
/// An instance of <see cref="AnalyzeBatchActionsOperation"/> sends requests to a server in UpdateStatusAsync, UpdateStatus, and other methods.
/// Responses from these requests can be accessed using GetRawResponse.
/// </remarks>
public override Response GetRawResponse() => _response;
Expand Down Expand Up @@ -157,7 +212,7 @@ public override async ValueTask<Response> UpdateStatusAsync(CancellationToken ca
/// <remarks>
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
/// </remarks>
public override ValueTask<Response<AsyncPageable<AnalyzeOperationResult>>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
public override ValueTask<Response<AsyncPageable<AnalyzeBatchActionsResult>>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
this.DefaultWaitForCompletionAsync(cancellationToken);

/// <summary>
Expand All @@ -173,7 +228,7 @@ public override ValueTask<Response<AsyncPageable<AnalyzeOperationResult>>> WaitF
/// <remarks>
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
/// </remarks>
public override ValueTask<Response<AsyncPageable<AnalyzeOperationResult>>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
public override ValueTask<Response<AsyncPageable<AnalyzeBatchActionsResult>>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);

/// <summary>
Expand All @@ -186,7 +241,7 @@ private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToke
{
if (!_hasCompleted)
{
using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(AnalyzeOperation)}.{nameof(UpdateStatus)}");
using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(AnalyzeBatchActionsOperation)}.{nameof(UpdateStatus)}");
scope.Start();

try
Expand All @@ -197,12 +252,22 @@ private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToke

_response = update.GetRawResponse();

_displayName = update.Value.DisplayName;
_createdOn = update.Value.CreatedDateTime;
_expiresOn = update.Value.ExpirationDateTime;
_lastModified = update.Value.LastUpdateDateTime;
_status = update.Value.Status;
_actionsFailed = update.Value.Tasks.Failed;
_actionsInProgress = update.Value.Tasks.InProgress;
_actionSucceeded = update.Value.Tasks.Completed;
_totalActions = update.Value.Tasks.Total;

if (update.Value.Status == TextAnalyticsOperationStatus.Succeeded)
{
// we need to first assign a value and then mark the operation as completed to avoid race conditions
var nextLink = update.Value.NextLink;
var value = Transforms.ConvertToAnalyzeOperationResult(update.Value, _idToIndexMap);
_firstPage = Page.FromValues(new List<AnalyzeOperationResult>() { value }, nextLink, _response);
_firstPage = Page.FromValues(new List<AnalyzeBatchActionsResult>() { value }, nextLink, _response);
_hasCompleted = true;
}
else if (update.Value.Status == TextAnalyticsOperationStatus.Failed)
Expand All @@ -228,19 +293,19 @@ private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToke
/// <remarks>
/// Operation must complete successfully (HasValue is true) for it to provide values.
/// </remarks>
public override AsyncPageable<AnalyzeOperationResult> GetValuesAsync()
public override AsyncPageable<AnalyzeBatchActionsResult> GetValuesAsync()
{
ValidateOperationStatus();

async Task<Page<AnalyzeOperationResult>> NextPageFunc(string nextLink, int? pageSizeHint)
async Task<Page<AnalyzeBatchActionsResult>> NextPageFunc(string nextLink, int? pageSizeHint)
{
//diagnostics scope?
try
{
Response<AnalyzeJobState> jobState = await _serviceClient.AnalyzeStatusNextPageAsync(_apiVersion, nextLink, _showStats).ConfigureAwait(false);

AnalyzeOperationResult result = Transforms.ConvertToAnalyzeOperationResult(jobState.Value, _idToIndexMap);
return Page.FromValues(new List<AnalyzeOperationResult>() { result }, jobState.Value.NextLink, jobState.GetRawResponse());
AnalyzeBatchActionsResult result = Transforms.ConvertToAnalyzeOperationResult(jobState.Value, _idToIndexMap);
return Page.FromValues(new List<AnalyzeBatchActionsResult>() { result }, jobState.Value.NextLink, jobState.GetRawResponse());
}
catch (Exception)
{
Expand All @@ -257,19 +322,19 @@ async Task<Page<AnalyzeOperationResult>> NextPageFunc(string nextLink, int? page
/// <remarks>
/// Operation must complete successfully (HasValue is true) for it to provide values.
/// </remarks>
public override Pageable<AnalyzeOperationResult> GetValues()
public override Pageable<AnalyzeBatchActionsResult> GetValues()
{
ValidateOperationStatus();

Page<AnalyzeOperationResult> NextPageFunc(string nextLink, int? pageSizeHint)
Page<AnalyzeBatchActionsResult> NextPageFunc(string nextLink, int? pageSizeHint)
{
//diagnostics scope?
try
{
Response<AnalyzeJobState> jobState = _serviceClient.AnalyzeStatusNextPage(_apiVersion, nextLink, _showStats);

AnalyzeOperationResult result = Transforms.ConvertToAnalyzeOperationResult(jobState.Value, _idToIndexMap);
return Page.FromValues(new List<AnalyzeOperationResult>() { result }, jobState.Value.NextLink, jobState.GetRawResponse());
AnalyzeBatchActionsResult result = Transforms.ConvertToAnalyzeOperationResult(jobState.Value, _idToIndexMap);
return Page.FromValues(new List<AnalyzeBatchActionsResult>() { result }, jobState.Value.NextLink, jobState.GetRawResponse());
}
catch (Exception)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Azure.AI.TextAnalytics
{
/// <summary>
/// Options that allow callers to specify details about how the operation
/// is run and what information is returned from it by the service.
/// <para>For example set model version, and whether to include statistics.</para>
suhas92 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public class AnalyzeBatchActionsOptions
{
/// <summary>
/// Gets or sets a value that, if set to true, indicates that the service
/// should return document and document batch statistics with the results
/// of the operation.
/// Returns data for batch document methods only.
suhas92 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public bool IncludeStatistics { get; set; }
}
}
Loading