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

✨ add support for workflow execution file send & workflow response loading #277

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
25 changes: 25 additions & 0 deletions docs/code_samples/workflow_execution.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Mindee;
using Mindee.Input;

string apiKey = "my-api-key";
string filePath = "/path/to/the/file.ext";
string workflowId = "workflow-id";

// Construct a new client
MindeeClient mindeeClient = new MindeeClient(apiKey);

// Load an input source as a path string
// Other input types can be used, as mentioned in the docs
var inputSource = new LocalInputSource(filePath);

// Send the document to a workflow execution
var response = await mindeeClient.ExecuteWorkflowAsync(workflowId, inputSource);

// Alternatively, give it an alias:
// var response = await mindeeClient.ExecuteWorkflowAsync(workflowId, inputSource, new WorkflowOptions(alias: "my-alias"));

// Print the execution ID to make sure it worked.
System.Console.WriteLine(response.Execution.Id);

// Print the inference result.
// System.Console.WriteLine(response.Execution.Inference);
52 changes: 52 additions & 0 deletions src/Mindee/Http/GenericParameter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Mindee.Exceptions;
using Mindee.Input;

namespace Mindee.Http
{
/// <summary>
/// G
/// </summary>
public class GenericParameter
{

/// <summary>
/// A local input source.
/// </summary>
public LocalInputSource LocalSource { get; }

/// <summary>
/// A URL input source.
/// </summary>
public UrlInputSource UrlSource { get; }

/// <summary>
/// Whether to include the full text data for async APIs.
/// This performs a full OCR operation on the server and will increase response time and payload size.
/// </summary>
/// <remarks>It is not available on all API.</remarks>
public bool FullText { get; }

/// <summary>
///
/// </summary>
/// <param name="localSource"></param>
/// <param name="urlSource"></param>
/// <param name="fullText"></param>
/// <exception cref="MindeeException"></exception>
public GenericParameter(LocalInputSource localSource, UrlInputSource urlSource, bool fullText)
{

if (localSource != null && urlSource != null)
{
throw new MindeeException("localSource and urlSource may not both be specified.");
}
if (localSource == null && urlSource == null)
{
throw new MindeeException("One of localSource or urlSource must be specified.");
}
LocalSource = localSource;
UrlSource = urlSource;
FullText = fullText;
}
}
}
11 changes: 11 additions & 0 deletions src/Mindee/Http/IHttpApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,16 @@ Task<AsyncPredictResponse<TModel>> DocumentQueueGetAsync<TModel>(
string jobId
, CustomEndpoint endpoint = null)
where TModel : class, new();

/// <summary>
/// Send a document to a workflow.
/// </summary>
/// <param name="workflowId">The ID of the workflow.</param>
/// <param name="workflowParameter"><see cref="PredictParameter"/></param>
/// <typeparam name="TModel">Document type.</typeparam>
Task<WorkflowResponse<TModel>> PostWorkflowExecution<TModel>(
string workflowId,
WorkflowParameter workflowParameter)
where TModel : class, new();
}
}
52 changes: 52 additions & 0 deletions src/Mindee/Http/MindeeApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,58 @@ string jobId
return handledResponse;
}

public async Task<WorkflowResponse<TModel>> PostWorkflowExecution<TModel>(
string workflowId,
WorkflowParameter workflowParameter)
where TModel : class, new()
{
var request = new RestRequest(
$"v1/workflows/{workflowId}/executions"
, Method.Post);

AddWorkflowRequestParameters(workflowParameter, request);

_logger?.LogInformation($"HTTP POST to {_baseUrl + request.Resource} ...");

var response = await _httpClient.ExecutePostAsync(request);
return ResponseHandler<WorkflowResponse<TModel>>(response);
}

private static void AddWorkflowRequestParameters(WorkflowParameter workflowParameter, RestRequest request)
{
if (workflowParameter.LocalSource != null)
{
request.AddFile(
"document",
workflowParameter.LocalSource.FileBytes,
workflowParameter.LocalSource.Filename);
}
else if (workflowParameter.UrlSource != null)
{
request.AddParameter(
"document",
workflowParameter.UrlSource.FileUrl.ToString());
}
if (workflowParameter.FullText)
{
request.AddQueryParameter(name: "full_text_ocr", value: "true");
}

if (workflowParameter.Alias != null)
{
request.AddParameter(name: "alias", value: workflowParameter.Alias);
}

if (workflowParameter.Priority != null)
{
request.AddParameter(
name: "priority",
value: workflowParameter.Priority != null ?
workflowParameter.Priority.ToString()?.ToLower() : null);
}

}

private static void AddPredictRequestParameters(PredictParameter predictParameter, RestRequest request)
{
if (predictParameter.LocalSource != null)
Expand Down
45 changes: 8 additions & 37 deletions src/Mindee/Http/PredictParameter.cs
Original file line number Diff line number Diff line change
@@ -1,69 +1,40 @@
using Mindee.Exceptions;
using Mindee.Input;

namespace Mindee.Http
{
/// <summary>
/// Parameter required to use the predict feature.
/// </summary>
public sealed class PredictParameter
public sealed class PredictParameter : GenericParameter
{
/// <summary>
/// A local input source.
/// </summary>
public LocalInputSource LocalSource { get; }

/// <summary>
/// A URL input source.
/// </summary>
public UrlInputSource UrlSource { get; }

/// <summary>
/// Want an OCR result ?
/// </summary>
/// <remarks>It is not available on all API.</remarks>
public bool AllWords { get; }

/// <summary>
/// Whether to include the full text data for async APIs.
/// This performs a full OCR operation on the server and will increase response time and payload size.
/// </summary>
/// <remarks>It is not available on all API.</remarks>
public bool FullText { get; }

/// <summary>
/// Want the cropping result about the document?
/// </summary>
/// <remarks>It is not available in API builder.</remarks>
public bool Cropper { get; }

/// <summary>
///
/// Prediction parameters for requests.
/// </summary>
/// <param name="localSource"><see cref="LocalSource"/></param>
/// <param name="urlSource"><see cref="UrlSource"/></param>
/// <param name="allWords"><see cref="AllWords"/></param>
/// <param name="fullText"><see cref="FullText"/></param>
/// <param name="cropper"><see cref="Cropper"/></param>
/// <param name="localSource">Local input source containing the file.<see cref="GenericParameter.LocalSource"/></param>
/// <param name="urlSource">Source URL to use.<see cref="GenericParameter.UrlSource"/></param>
/// <param name="allWords">Whether to include the full OCR response in the payload (compatible APIs only).<see cref="AllWords"/></param>
/// <param name="fullText">Whether to include the full text in the payload (compatible APIs only)<see cref="GenericParameter.FullText"/></param>
/// <param name="cropper">Whether to crop the document before enqueuing on the API.<see cref="Cropper"/></param>
public PredictParameter(
LocalInputSource localSource,
UrlInputSource urlSource,
bool allWords,
bool fullText,
bool cropper)
bool cropper) : base(localSource, urlSource, fullText)
{
if (localSource != null && urlSource != null)
{
throw new MindeeException("localSource and urlSource may not both be specified.");
}
if (localSource == null && urlSource == null)
{
throw new MindeeException("One of localSource or urlSource must be specified.");
}
LocalSource = localSource;
UrlSource = urlSource;
AllWords = allWords;
FullText = fullText;
Cropper = cropper;
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/Mindee/Http/WorkflowParameter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using Mindee.Input;

namespace Mindee.Http
{
/// <summary>
/// Parameter required to use the workflow feature.
/// </summary>
public class WorkflowParameter : GenericParameter
{
/// <summary>
/// Alias to give to the file.
/// </summary>
public string Alias { get; }


/// <summary>
/// Priority to give to the execution.
/// </summary>
public ExecutionPriority? Priority { get; }

/// <summary>
/// Workflow parameters.
/// </summary>
/// <param name="localSource">Local input source containing the file.<see cref="GenericParameter.LocalSource"/></param>
/// <param name="urlSource">Source URL to use.<see cref="GenericParameter.UrlSource"/></param>
/// <param name="fullText">Whether to include the full text in the payload (compatible APIs only)<see cref="GenericParameter.FullText"/></param>
/// <param name="alias">Alias to give to the document.<see cref="Alias"/></param>
/// <param name="priority">Priority to give to the document.<see cref="Priority"/></param>
public WorkflowParameter(
LocalInputSource localSource,
UrlInputSource urlSource, bool fullText,
string alias, ExecutionPriority? priority) : base(localSource, urlSource,
fullText)
{
Alias = alias;
Priority = priority;
}
}
}
65 changes: 65 additions & 0 deletions src/Mindee/MindeeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,71 @@ LocalInputSource inputSource
throw new MindeeException($"Could not complete after {retryCount} attempts.");
}

/// <summary>
/// Send a local file to a workflow execution.
/// </summary>
/// <param name="workflowId">The workflow id.</param>
/// <param name="inputSource"><see cref="LocalInputSource"/></param>
/// <param name="workflowOptions"><see cref="PageOptions"/></param>
/// <param name="pageOptions"><see cref="PageOptions"/></param>
/// <returns><see cref="WorkflowResponse{TInferenceModel}"/></returns>
public async Task<WorkflowResponse<GeneratedV1>> ExecuteWorkflowAsync(
string workflowId,
LocalInputSource inputSource,
WorkflowOptions workflowOptions = null,
PageOptions pageOptions = null)
{
_logger?.LogInformation("Sending '{}' to workflow '{}'...", inputSource.Filename, workflowId);

if (pageOptions != null && inputSource.IsPdf())
{
inputSource.FileBytes = _pdfOperation.Split(
new SplitQuery(inputSource.FileBytes, pageOptions)).File;
}

workflowOptions ??= new WorkflowOptions();

return await _mindeeApi.PostWorkflowExecution<GeneratedV1>(
workflowId,
new WorkflowParameter(
localSource: inputSource,
urlSource: null,
alias: workflowOptions.Alias,
priority: workflowOptions.Priority,
fullText: workflowOptions.FullText
));
}

/// <summary>
/// Send a remote file to a workflow execution.
/// </summary>
/// <param name="workflowId">The workflow id.</param>
/// <param name="inputSource"><see cref="LocalInputSource"/></param>
/// <param name="workflowOptions"><see cref="PageOptions"/></param>
/// <returns><see cref="WorkflowResponse{TInferenceModel}"/></returns>
public async Task<WorkflowResponse<GeneratedV1>> ExecuteWorkflowAsync(
string workflowId,
UrlInputSource inputSource,
WorkflowOptions workflowOptions = null)
{
_logger?.LogInformation("Asynchronous parsing of {} ...", inputSource.FileUrl);

if (workflowOptions == null)
{
workflowOptions = new WorkflowOptions();
}

return await _mindeeApi.PostWorkflowExecution<GeneratedV1>(
workflowId,
new WorkflowParameter(
localSource: null,
urlSource: inputSource,
alias: workflowOptions.Alias,
priority: workflowOptions.Priority,
fullText: workflowOptions.FullText
));
}

/// <summary>
/// Load a local prediction.
/// Typically used when wanting to load from a webhook callback.
Expand Down
39 changes: 39 additions & 0 deletions src/Mindee/MindeeClientOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Mindee.Exceptions;
using Mindee.Input;

namespace Mindee
{
Expand Down Expand Up @@ -102,4 +103,42 @@ public AsyncPollingOptions(double initialDelaySec = 2.0, double intervalSec = 1.
IntervalMilliSec = (int)Math.Floor(IntervalSec * 1000);
}
}

/// <summary>
/// Options for workflow executions.
/// </summary>
public sealed class WorkflowOptions
{

/// <summary>
/// Alias to give to the file.
/// </summary>
public string Alias { get; }


/// <summary>
/// Priority to give to the execution.
/// </summary>
public ExecutionPriority? Priority { get; }


/// <summary>
/// Whether to include the full text data for async APIs.
/// This performs a full OCR operation on the server and will increase response time and payload size.
/// </summary>
public bool FullText { get; }

/// <summary>
/// Options for workflow executions.
/// </summary>
/// <param name="alias"></param>
/// <param name="priority"></param>
/// <param name="fullText"></param>
public WorkflowOptions(string alias = null, ExecutionPriority? priority = null, bool fullText = false)
{
Alias = alias;
Priority = priority;
FullText = fullText;
}
}
}
Loading
Loading