-
Notifications
You must be signed in to change notification settings - Fork 2
✨ add support for Mindee Client V2 #251
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
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
b39d3b7
[DRAFT] add support for Mindee Client V2
sebastianMindee c41ecb3
:sparkles: add support for V2 client
sebastianMindee b31cb2e
add sample code
sebastianMindee d34365e
fix lingering issues (NO TESTS)
sebastianMindee 52742d5
fix PR trigger target
sebastianMindee e15675b
fix display + add basic unit test
sebastianMindee df7ca94
add tests
sebastianMindee 4c00a35
fix permissions for workflows
sebastianMindee dc8e25e
fix perms again
sebastianMindee 40e3e9c
bump test lib, fix tests, add missing object
sebastianMindee 35f30cf
refactor v2 internals
sebastianMindee 5945983
apply fixes to match latest test syntaxes
sebastianMindee f496e4d
fix incorrect args, fix code sample & remove ugly comments that I hate
sebastianMindee 365f15f
remove invalid jsonproperty annotations
sebastianMindee 76b6eb6
tweak internal JobResponse syntax
sebastianMindee f159a96
rename InferenceOptions -> InferenceParameters
sebastianMindee 3f34ecf
fix valid response check
sebastianMindee f175489
apply naming fixes
sebastianMindee 6518b7a
tweak client calls to split up polling & inference retrieval
sebastianMindee 6a3ec0a
rework inference & page options
sebastianMindee c4dc4d4
fix test
sebastianMindee 90d7752
rework function syntaxes
sebastianMindee 5cd5da5
fix typos & rename enqueue() method on V2
sebastianMindee d34f587
add missing test
sebastianMindee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import com.mindee.MindeeClientV2; | ||
| import com.mindee.InferenceParameters; | ||
| import com.mindee.input.LocalInputSource; | ||
| import com.mindee.parsing.v2.InferenceResponse; | ||
| import java.io.File; | ||
| import java.io.IOException; | ||
|
|
||
| public class SimpleMindeeClient { | ||
|
|
||
| public static void main(String[] args) throws IOException, InterruptedException { | ||
| String apiKey = "MY_API_KEY"; | ||
| String filePath = "/path/to/the/file.ext"; | ||
| String modelId = "MY_MODEL_ID"; | ||
|
|
||
| // Init a new client | ||
| MindeeClientV2 mindeeClient = new MindeeClientV2(apiKey); | ||
|
|
||
| // Load a file from disk | ||
| LocalInputSource inputSource = new LocalInputSource(new File(filePath)); | ||
|
|
||
| // Prepare the enqueueing options | ||
| // Note: modelId is mandatory. | ||
| InferenceParameters options = InferenceParameters.builder(modelId).build(); | ||
|
|
||
| // Parse the file | ||
| InferenceResponse response = mindeeClient.enqueueAndGetInference( | ||
| inputSource, | ||
| options | ||
| ); | ||
|
|
||
| // Print a summary of the response | ||
| System.out.println(response.getInference().toString()); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| package com.mindee; | ||
|
|
||
| import com.mindee.input.PageOptions; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import lombok.Data; | ||
| import lombok.Getter; | ||
|
|
||
| /** | ||
| * Options to pass when calling methods using the API V2. | ||
| */ | ||
| @Getter | ||
| @Data | ||
| public final class InferenceParameters { | ||
| /** | ||
| * ID of the model (required). | ||
| */ | ||
| private final String modelId; | ||
| /** | ||
| * Enables Retrieval-Augmented Generation (optional, default: {@code false}). | ||
| */ | ||
| private final boolean rag; | ||
| /** | ||
| * Optional alias for the file. | ||
| */ | ||
| private final String alias; | ||
| /** | ||
| * IDs of webhooks to propagate the API response to (may be empty). | ||
| */ | ||
| private final List<String> webhookIds; | ||
| /* | ||
| * Asynchronous polling options. | ||
| */ | ||
| private final AsyncPollingOptions pollingOptions; | ||
|
|
||
| /** | ||
| * Create a new builder. | ||
| * | ||
| * @param modelId the mandatory model identifier | ||
| * @return a fresh {@link Builder} | ||
| */ | ||
| public static Builder builder(String modelId) { | ||
| return new Builder(modelId); | ||
| } | ||
|
|
||
| /** | ||
| * Fluent builder for {@link InferenceParameters}. | ||
| */ | ||
| public static final class Builder { | ||
|
|
||
| private final String modelId; | ||
| private boolean rag = false; | ||
| private String alias; | ||
| private List<String> webhookIds = Collections.emptyList(); | ||
| private AsyncPollingOptions pollingOptions = AsyncPollingOptions.builder().build(); | ||
|
|
||
| private Builder(String modelId) { | ||
| this.modelId = Objects.requireNonNull(modelId, "modelId must not be null"); | ||
| } | ||
|
|
||
| /** Enable / disable Retrieval-Augmented Generation. */ | ||
| public Builder rag(boolean rag) { | ||
| this.rag = rag; | ||
| return this; | ||
| } | ||
|
|
||
| /** Set an alias for the uploaded document. */ | ||
| public Builder alias(String alias) { | ||
| this.alias = alias; | ||
| return this; | ||
| } | ||
|
|
||
| /** Provide IDs of webhooks to forward the API response to. */ | ||
| public Builder webhookIds(List<String> webhookIds) { | ||
| this.webhookIds = webhookIds; | ||
| return this; | ||
| } | ||
|
|
||
|
|
||
| public Builder pollingOptions(AsyncPollingOptions pollingOptions) { | ||
| this.pollingOptions = pollingOptions; | ||
| return this; | ||
| } | ||
|
|
||
| /** Build an immutable {@link InferenceParameters} instance. */ | ||
| public InferenceParameters build() { | ||
| return new InferenceParameters( | ||
| modelId, | ||
| rag, | ||
| alias, | ||
| webhookIds, | ||
| pollingOptions | ||
| ); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| package com.mindee; | ||
|
|
||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import com.mindee.http.MindeeApiV2; | ||
| import com.mindee.http.MindeeHttpApiV2; | ||
| import com.mindee.http.MindeeHttpExceptionV2; | ||
| import com.mindee.input.LocalInputSource; | ||
| import com.mindee.input.LocalResponse; | ||
| import com.mindee.parsing.v2.ErrorResponse; | ||
| import com.mindee.parsing.v2.InferenceResponse; | ||
| import com.mindee.parsing.v2.JobResponse; | ||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Entry point for the Mindee **V2** API features. | ||
| */ | ||
| public class MindeeClientV2 { | ||
| private final MindeeApiV2 mindeeApi; | ||
|
|
||
| /** Uses an API-key read from the environment variables. */ | ||
| public MindeeClientV2() { | ||
| this(createDefaultApiV2("")); | ||
| } | ||
|
|
||
| /** Uses the supplied API-key. */ | ||
| public MindeeClientV2(String apiKey) { | ||
| this(createDefaultApiV2(apiKey)); | ||
| } | ||
|
|
||
|
|
||
| /** Inject both a PDF implementation and a HTTP implementation. */ | ||
| public MindeeClientV2(MindeeApiV2 mindeeApi) { | ||
| this.mindeeApi = mindeeApi; | ||
| } | ||
|
|
||
| /** | ||
| * Enqueue a document in the asynchronous queue. | ||
| */ | ||
| public JobResponse enqueueInference( | ||
| LocalInputSource inputSource, | ||
| InferenceParameters params) throws IOException { | ||
| return mindeeApi.reqPostInferenceEnqueue(inputSource, params); | ||
| } | ||
|
|
||
| /** | ||
| * Get the status of an inference that was previously enqueued. | ||
| * Can be used for polling. | ||
| */ | ||
| public JobResponse getJob(String jobId) { | ||
| if (jobId == null || jobId.trim().isEmpty()) { | ||
| throw new IllegalArgumentException("jobId must not be null or blank."); | ||
| } | ||
| return mindeeApi.reqGetJob(jobId); | ||
| } | ||
|
|
||
| /** | ||
| * Get the result of an inference that was previously enqueued. | ||
| * The inference will only be available after it has finished processing. | ||
| */ | ||
| public InferenceResponse getInference(String inferenceId) { | ||
| if (inferenceId == null || inferenceId.trim().isEmpty()) { | ||
| throw new IllegalArgumentException("inferenceId must not be null or blank."); | ||
| } | ||
|
|
||
| return mindeeApi.reqGetInference(inferenceId); | ||
| } | ||
|
|
||
| /** | ||
| * Send a local file to an async queue, poll, and parse when complete. | ||
| * @param inputSource The input source to send. | ||
| * @param options The options to send along with the file. | ||
| * @return an instance of {@link InferenceResponse}. | ||
| * @throws IOException Throws if the file can't be accessed. | ||
| * @throws InterruptedException Throws if the thread is interrupted. | ||
| */ | ||
| public InferenceResponse enqueueAndGetInference( | ||
| LocalInputSource inputSource, | ||
| InferenceParameters options) throws IOException, InterruptedException { | ||
|
|
||
| validatePollingOptions(options.getPollingOptions()); | ||
|
|
||
| JobResponse job = enqueueInference(inputSource, options); | ||
|
|
||
| Thread.sleep((long) (options.getPollingOptions().getInitialDelaySec() * 1000)); | ||
| JobResponse resp = job; | ||
| int attempts = 0; | ||
| int max = options.getPollingOptions().getMaxRetries(); | ||
| while (attempts < max) { | ||
| Thread.sleep((long) (options.getPollingOptions().getIntervalSec() * 1000)); | ||
| resp = getJob(job.getJob().getId()); | ||
| if (resp.getJob().getStatus().equals("Failed")) { | ||
| break; | ||
| } | ||
| else if (resp.getJob().getStatus().equals("Processed")) { | ||
| return getInference(resp.getJob().getId()); | ||
| } | ||
| attempts++; | ||
| } | ||
| ErrorResponse error = resp.getJob().getError(); | ||
| if (error != null) { | ||
| throw new MindeeHttpExceptionV2(error.getStatus(), error.getDetail()); | ||
| } | ||
| throw new RuntimeException("Max retries exceeded (" + max + ")."); | ||
| } | ||
|
|
||
| /** | ||
| * Deserialize a webhook payload (or any saved response) into an | ||
| * {@link InferenceResponse}. | ||
| */ | ||
| public InferenceResponse loadInference(LocalResponse localResponse) throws IOException { | ||
| ObjectMapper mapper = new ObjectMapper().findAndRegisterModules(); | ||
| InferenceResponse model = | ||
| mapper.readValue(localResponse.getFile(), InferenceResponse.class); | ||
| model.setRawResponse(localResponse.toString()); | ||
| return model; | ||
| } | ||
|
|
||
| private static MindeeApiV2 createDefaultApiV2(String apiKey) { | ||
| MindeeSettingsV2 settings = apiKey == null || apiKey.trim().isEmpty() | ||
| ? new MindeeSettingsV2() | ||
| : new MindeeSettingsV2(apiKey); | ||
| return MindeeHttpApiV2.builder() | ||
| .mindeeSettings(settings) | ||
| .build(); | ||
| } | ||
|
|
||
| private static void validatePollingOptions(AsyncPollingOptions p) { | ||
| if (p.getInitialDelaySec() < 1) { | ||
| throw new IllegalArgumentException("Initial delay must be ≥ 1 s"); | ||
| } | ||
| if (p.getIntervalSec() < 1) { | ||
| throw new IllegalArgumentException("Interval must be ≥ 1 s"); | ||
| } | ||
| if (p.getMaxRetries() < 2) { | ||
| throw new IllegalArgumentException("Max retries must be ≥ 2"); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.