From 7ae6515ce675720fc52991cea32d9d286d383515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Wed, 3 Sep 2025 16:39:50 +0200 Subject: [PATCH 1/2] :recycle: update raw text structure --- .../java/com/mindee/parsing/v2/Inference.java | 12 +++- .../parsing/v2/InferenceActiveOptions.java | 65 +++++++++++++++++++ .../com/mindee/parsing/v2/InferenceModel.java | 10 +++ .../mindee/parsing/v2/InferenceResult.java | 10 +-- .../parsing/v2/InferenceResultOptions.java | 15 ----- .../java/com/mindee/parsing/v2/RawText.java | 23 +++++-- .../com/mindee/parsing/v2/RawTextPage.java | 33 ++++++++++ .../java/com/mindee/MindeeClientV2IT.java | 9 ++- .../com/mindee/parsing/v2/InferenceTest.java | 34 +++++----- src/test/resources | 2 +- 10 files changed, 164 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/mindee/parsing/v2/InferenceActiveOptions.java delete mode 100644 src/main/java/com/mindee/parsing/v2/InferenceResultOptions.java create mode 100644 src/main/java/com/mindee/parsing/v2/RawTextPage.java diff --git a/src/main/java/com/mindee/parsing/v2/Inference.java b/src/main/java/com/mindee/parsing/v2/Inference.java index db37e638b..e8d53f313 100644 --- a/src/main/java/com/mindee/parsing/v2/Inference.java +++ b/src/main/java/com/mindee/parsing/v2/Inference.java @@ -35,6 +35,12 @@ public class Inference { @JsonProperty("file") private InferenceFile file; + /** + * Active options for the inference. + */ + @JsonProperty("active_options") + private InferenceActiveOptions activeOptions; + /** * Model result values. */ @@ -47,12 +53,12 @@ public String toString() { joiner .add("Inference") .add("#########") - .add("Model") - .add("=====") - .add(":ID: " + (model != null ? model.getId() : "")) + .add(model.toString()) .add("") .add(file.toString()) .add("") + .add(activeOptions.toString()) + .add("") .add(result != null ? result.toString() : ""); return joiner.toString().trim() + "\n"; } diff --git a/src/main/java/com/mindee/parsing/v2/InferenceActiveOptions.java b/src/main/java/com/mindee/parsing/v2/InferenceActiveOptions.java new file mode 100644 index 000000000..02a24cc6b --- /dev/null +++ b/src/main/java/com/mindee/parsing/v2/InferenceActiveOptions.java @@ -0,0 +1,65 @@ +package com.mindee.parsing.v2; + +import static com.mindee.parsing.SummaryHelper.formatForDisplay; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.StringJoiner; + +/** + * Option response for V2 API inference. + */ +public final class InferenceActiveOptions { + + @JsonProperty("rag") + private boolean rag; + + @JsonProperty("raw_text") + private boolean rawText; + + @JsonProperty("polygon") + private boolean polygon; + + @JsonProperty("confidence") + private boolean confidence; + + /** + * Whether the RAG feature was activated. + */ + public boolean getRag() { + return rag; + } + + /** + * Whether the Raw Text feature was activated. + */ + public boolean getRawText() { + return rawText; + } + + /** + * Whether the polygon feature was activated. + */ + public boolean getPolygon() { + return polygon; + } + + /** + * Whether the confidence feature was activated. + */ + public boolean getConfidence() { + return confidence; + } + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner("\n"); + return joiner + .add("Active Options") + .add("==============") + .add(":Raw Text: " + formatForDisplay(rawText, 5)) + .add(":Polygon: " + formatForDisplay(polygon, 5)) + .add(":Confidence: " + formatForDisplay(confidence, 5)) + .add(":RAG: " + formatForDisplay(rag, 5)) + .toString(); + } +} diff --git a/src/main/java/com/mindee/parsing/v2/InferenceModel.java b/src/main/java/com/mindee/parsing/v2/InferenceModel.java index 02c24f74f..6440df5f2 100644 --- a/src/main/java/com/mindee/parsing/v2/InferenceModel.java +++ b/src/main/java/com/mindee/parsing/v2/InferenceModel.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.StringJoiner; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -22,4 +23,13 @@ public class InferenceModel { */ @JsonProperty("id") private String id; + + public String toString() { + StringJoiner joiner = new StringJoiner("\n"); + return joiner + .add("Model") + .add("=====") + .add(":ID: " + id) + .toString(); + } } diff --git a/src/main/java/com/mindee/parsing/v2/InferenceResult.java b/src/main/java/com/mindee/parsing/v2/InferenceResult.java index d9e92ba74..7002897bf 100644 --- a/src/main/java/com/mindee/parsing/v2/InferenceResult.java +++ b/src/main/java/com/mindee/parsing/v2/InferenceResult.java @@ -28,8 +28,8 @@ public final class InferenceResult { /** * Options. */ - @JsonProperty("options") - private InferenceResultOptions options; + @JsonProperty("raw_text") + private RawText rawText; @Override public String toString() { @@ -37,11 +37,7 @@ public String toString() { joiner.add("Fields") .add("======"); joiner.add(fields.toString()); - if (this.getOptions() != null) { - joiner.add("Options") - .add("=======") - .add(this.getOptions().toString()); - } + return joiner.toString(); } } diff --git a/src/main/java/com/mindee/parsing/v2/InferenceResultOptions.java b/src/main/java/com/mindee/parsing/v2/InferenceResultOptions.java deleted file mode 100644 index 80d4cc349..000000000 --- a/src/main/java/com/mindee/parsing/v2/InferenceResultOptions.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mindee.parsing.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import lombok.Getter; - -/** - * Option response for V2 API inference. - */ -@Getter -public final class InferenceResultOptions { - - @JsonProperty("raw_texts") - private List rawTexts; -} diff --git a/src/main/java/com/mindee/parsing/v2/RawText.java b/src/main/java/com/mindee/parsing/v2/RawText.java index 3fe0a5140..5720d41ed 100644 --- a/src/main/java/com/mindee/parsing/v2/RawText.java +++ b/src/main/java/com/mindee/parsing/v2/RawText.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.StringJoiner; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -17,12 +19,19 @@ public class RawText { /* * Page Number the text was found on. */ - @JsonProperty("page") - private Integer page; + @JsonProperty("pages") + private List pages; - /* - * Content of the raw text. - */ - @JsonProperty("content") - private String content; + @Override + public String toString() { + if (pages == null || pages.isEmpty()) { + return ""; + } + StringJoiner joiner = new StringJoiner("\n\n"); + for (RawTextPage page : pages) { + joiner.add(page.toString()); + } + return joiner.toString(); + + } } diff --git a/src/main/java/com/mindee/parsing/v2/RawTextPage.java b/src/main/java/com/mindee/parsing/v2/RawTextPage.java new file mode 100644 index 000000000..072bd69fb --- /dev/null +++ b/src/main/java/com/mindee/parsing/v2/RawTextPage.java @@ -0,0 +1,33 @@ +package com.mindee.parsing.v2; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Raw text extracted from the page. + */ +@Getter +@JsonIgnoreProperties(ignoreUnknown = true) +@AllArgsConstructor +@NoArgsConstructor +public class RawTextPage { + /** + * Page content as a single string. + */ + @JsonProperty("content") + private String content; + + /** + * Page contents as a string. + */ + @Override + public String toString() { + if (content == null) { + return ""; + } + return content; + } +} diff --git a/src/test/java/com/mindee/MindeeClientV2IT.java b/src/test/java/com/mindee/MindeeClientV2IT.java index 9242b709d..676f9f7d0 100644 --- a/src/test/java/com/mindee/MindeeClientV2IT.java +++ b/src/test/java/com/mindee/MindeeClientV2IT.java @@ -3,6 +3,7 @@ import com.mindee.http.MindeeHttpExceptionV2; import com.mindee.input.LocalInputSource; import com.mindee.input.URLInputSource; +import com.mindee.parsing.v2.InferenceActiveOptions; import com.mindee.parsing.v2.InferenceResponse; import java.io.File; import java.io.IOException; @@ -55,7 +56,13 @@ void parseFile_emptyMultiPage_mustSucceed() throws IOException, InterruptedExcep assertEquals(modelId, response.getInference().getModel().getId()); assertNotNull(response.getInference().getResult()); - assertNull(response.getInference().getResult().getOptions()); + + InferenceActiveOptions activeOptions = response.getInference().getActiveOptions(); + assertNotNull(activeOptions); + assertFalse(activeOptions.getRag()); + assertFalse(activeOptions.getRawText()); + assertFalse(activeOptions.getPolygon()); + assertFalse(activeOptions.getConfidence()); } @Test diff --git a/src/test/java/com/mindee/parsing/v2/InferenceTest.java b/src/test/java/com/mindee/parsing/v2/InferenceTest.java index 03068199f..ada237a07 100644 --- a/src/test/java/com/mindee/parsing/v2/InferenceTest.java +++ b/src/test/java/com/mindee/parsing/v2/InferenceTest.java @@ -99,22 +99,22 @@ class CompletePrediction { @DisplayName("every exposed property must be valid and consistent") void asyncPredict_whenComplete_mustExposeAllProperties() throws IOException { InferenceResponse response = loadFromResource("v2/products/financial_document/complete.json"); - Inference inf = response.getInference(); - assertNotNull(inf, "Inference must not be null"); - assertEquals("12345678-1234-1234-1234-123456789abc", inf.getId(), "Inference ID mismatch"); + Inference inference = response.getInference(); + assertNotNull(inference, "Inference must not be null"); + assertEquals("12345678-1234-1234-1234-123456789abc", inference.getId(), "Inference ID mismatch"); - InferenceModel model = inf.getModel(); + InferenceModel model = inference.getModel(); assertNotNull(model, "Model must not be null"); assertEquals("12345678-1234-1234-1234-123456789abc", model.getId(), "Model ID mismatch"); - InferenceFile file = inf.getFile(); + InferenceFile file = inference.getFile(); assertNotNull(file, "File must not be null"); assertEquals("complete.jpg", file.getName(), "File name mismatch"); assertEquals(1, file.getPageCount(), "Page count mismatch"); assertEquals("image/jpeg", file.getMimeType(), "MIME type mismatch"); assertNull(file.getAlias(), "File alias must be null for this payload"); - InferenceFields fields = inf.getResult().getFields(); + InferenceFields fields = inference.getResult().getFields(); assertEquals(21, fields.size(), "Expected 21 fields in the payload"); SimpleField date = fields.get("date").getSimpleField(); @@ -146,7 +146,8 @@ void asyncPredict_whenComplete_mustExposeAllProperties() throws IOException { SimpleField city = customerAddr.getFields().get("city").getSimpleField(); assertEquals("New York", city.getValue(), "City mismatch"); - assertNull(inf.getResult().getOptions(), "Options must be null"); + InferenceActiveOptions activeOptions = inference.getActiveOptions(); + assertNotNull(activeOptions); } } @@ -451,17 +452,20 @@ class RawTexts { @DisplayName("raw texts option must be parsed and exposed") void rawTexts_mustBeAccessible() throws IOException { InferenceResponse resp = loadFromResource("v2/inference/raw_texts.json"); - Inference inf = resp.getInference(); - assertNotNull(inf); + Inference inference = resp.getInference(); + assertNotNull(inference); - InferenceResultOptions opts = inf.getResult().getOptions(); - assertNotNull(opts, "Options should not be null"); + InferenceActiveOptions activeOptions = inference.getActiveOptions(); + assertNotNull(activeOptions); + assertFalse(activeOptions.getRag()); + assertTrue(activeOptions.getRawText()); + assertFalse(activeOptions.getPolygon()); + assertFalse(activeOptions.getConfidence()); - List rawTexts = opts.getRawTexts(); - assertEquals(2, rawTexts.size()); + RawText rawText = inference.getResult().getRawText(); + assertEquals(2, rawText.getPages().size()); - RawText first = rawTexts.get(0); - assertEquals(0, first.getPage()); + RawTextPage first = rawText.getPages().get(0); assertEquals("This is the raw text of the first page...", first.getContent()); } } diff --git a/src/test/resources b/src/test/resources index f0175f0ee..bc8356c1c 160000 --- a/src/test/resources +++ b/src/test/resources @@ -1 +1 @@ -Subproject commit f0175f0ee644b57b409e6ad7e1c030f28fbe57ef +Subproject commit bc8356c1ce52d60351ed3430d336f33366025012 From ed57a451583cc58ef3468608dd46076e22d6789d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Thu, 4 Sep 2025 17:02:02 +0200 Subject: [PATCH 2/2] :sparkles: add new options to inference parameters --- docs/code_samples/default_v2.txt | 19 +++- .../java/com/mindee/InferenceParameters.java | 50 +++++++++- .../java/com/mindee/http/MindeeHttpApiV2.java | 13 ++- .../java/com/mindee/MindeeClientV2IT.java | 91 ++++++++++++------- .../com/mindee/parsing/v2/InferenceTest.java | 4 +- 5 files changed, 133 insertions(+), 44 deletions(-) diff --git a/docs/code_samples/default_v2.txt b/docs/code_samples/default_v2.txt index 8144e3540..bc395addb 100644 --- a/docs/code_samples/default_v2.txt +++ b/docs/code_samples/default_v2.txt @@ -19,9 +19,22 @@ public class SimpleMindeeClient { // Set inference parameters // Note: modelId is mandatory. - InferenceParameters inferenceParams = InferenceParameters.builder(modelId) - // If set to `true`, will enable Retrieval-Augmented Generation. - .rag(false) + InferenceParameters inferenceParams = InferenceParameters + // ID of the model, required. + .builder(modelId) + + // Options: set to `true` or `false` to override defaults + + // Enhance extraction accuracy with Retrieval-Augmented Generation. + .rag(null) + // Extract the full text content from the document as strings. + .rawText(null) + // Calculate bounding box polygons for all fields. + .polygon(null) + // Boost the precision and accuracy of all extractions. + // Calculate confidence scores for all fields. + .confidence(null) + .build(); // Load a file from disk diff --git a/src/main/java/com/mindee/InferenceParameters.java b/src/main/java/com/mindee/InferenceParameters.java index f1f8e5292..499f454c2 100644 --- a/src/main/java/com/mindee/InferenceParameters.java +++ b/src/main/java/com/mindee/InferenceParameters.java @@ -15,9 +15,22 @@ public final class InferenceParameters { */ private final String modelId; /** - * Enables Retrieval-Augmented Generation (optional, default: {@code false}). + * Enhance extraction accuracy with Retrieval-Augmented Generation. */ - private final boolean rag; + private final Boolean rag; + /** + * Extract the full text content from the document as strings. + */ + private final Boolean rawText; + /** + * Calculate bounding box polygons for all fields. + */ + private final Boolean polygon; + /** + * Boost the precision and accuracy of all extractions. + * Calculate confidence scores for all fields. + */ + private final Boolean confidence; /** * Optional alias for the file. */ @@ -47,7 +60,10 @@ public static Builder builder(String modelId) { public static final class Builder { private final String modelId; - private boolean rag = false; + private Boolean rag = null; + private Boolean rawText = null; + private Boolean polygon = null; + private Boolean confidence = null; private String alias; private String[] webhookIds = new String[]{}; private AsyncPollingOptions pollingOptions = AsyncPollingOptions.builder().build(); @@ -56,12 +72,33 @@ private Builder(String modelId) { this.modelId = Objects.requireNonNull(modelId, "modelId must not be null"); } - /** Enable / disable Retrieval-Augmented Generation. */ - public Builder rag(boolean rag) { + /** Enhance extraction accuracy with Retrieval-Augmented Generation. */ + public Builder rag(Boolean rag) { this.rag = rag; return this; } + /** Extract the full text content from the document as strings. */ + public Builder rawText(Boolean rawText) { + this.rawText = rawText; + return this; + } + + /** Calculate bounding box polygons for all fields. */ + public Builder polygon(Boolean polygon) { + this.polygon = polygon; + return this; + } + + /** + * Boost the precision and accuracy of all extractions. + * Calculate confidence scores for all fields. + */ + public Builder confidence(Boolean confidence) { + this.confidence = confidence; + return this; + } + /** Set an alias for the uploaded document. */ public Builder alias(String alias) { this.alias = alias; @@ -84,6 +121,9 @@ public InferenceParameters build() { return new InferenceParameters( modelId, rag, + rawText, + polygon, + confidence, alias, webhookIds, pollingOptions diff --git a/src/main/java/com/mindee/http/MindeeHttpApiV2.java b/src/main/java/com/mindee/http/MindeeHttpApiV2.java index 1589dea6f..724e37180 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApiV2.java +++ b/src/main/java/com/mindee/http/MindeeHttpApiV2.java @@ -259,8 +259,17 @@ private HttpEntity buildHttpBody( } builder.addTextBody("model_id", params.getModelId()); - if (params.isRag()) { - builder.addTextBody("rag", "true"); + if (params.getRag() != null) { + builder.addTextBody("rag", params.getRag().toString().toLowerCase()); + } + if (params.getRawText() != null) { + builder.addTextBody("raw_text", params.getRawText().toString().toLowerCase()); + } + if (params.getPolygon() != null) { + builder.addTextBody("polygon", params.getPolygon().toString().toLowerCase()); + } + if (params.getConfidence() != null) { + builder.addTextBody("confidence", params.getConfidence().toString().toLowerCase()); } if (params.getAlias() != null) { builder.addTextBody("alias", params.getAlias()); diff --git a/src/test/java/com/mindee/MindeeClientV2IT.java b/src/test/java/com/mindee/MindeeClientV2IT.java index 676f9f7d0..0a816dc5c 100644 --- a/src/test/java/com/mindee/MindeeClientV2IT.java +++ b/src/test/java/com/mindee/MindeeClientV2IT.java @@ -3,8 +3,14 @@ import com.mindee.http.MindeeHttpExceptionV2; import com.mindee.input.LocalInputSource; import com.mindee.input.URLInputSource; +import com.mindee.parsing.v2.Inference; import com.mindee.parsing.v2.InferenceActiveOptions; +import com.mindee.parsing.v2.InferenceFile; import com.mindee.parsing.v2.InferenceResponse; +import com.mindee.parsing.v2.InferenceResult; +import com.mindee.parsing.v2.RawText; +import com.mindee.parsing.v2.field.InferenceFields; +import com.mindee.parsing.v2.field.SimpleField; import java.io.File; import java.io.IOException; import org.junit.jupiter.api.*; @@ -34,6 +40,9 @@ void parseFile_emptyMultiPage_mustSucceed() throws IOException, InterruptedExcep InferenceParameters params = InferenceParameters .builder(modelId) .rag(false) + .rawText(true) + .polygon(null) + .confidence(null) .alias("java-integration-test") .pollingOptions( AsyncPollingOptions.builder() @@ -45,24 +54,33 @@ void parseFile_emptyMultiPage_mustSucceed() throws IOException, InterruptedExcep .build(); InferenceResponse response = mindeeClient.enqueueAndGetInference(source, params); - assertNotNull(response); - assertNotNull(response.getInference()); - - assertNotNull(response.getInference().getFile()); - assertEquals("multipage_cut-2.pdf", response.getInference().getFile().getName()); + Inference inference = response.getInference(); + assertNotNull(inference); - assertNotNull(response.getInference().getModel()); - assertEquals(modelId, response.getInference().getModel().getId()); + InferenceFile file = inference.getFile(); + assertNotNull(file); + assertEquals("multipage_cut-2.pdf", file.getName()); + assertEquals(2, file.getPageCount()); - assertNotNull(response.getInference().getResult()); + assertNotNull(inference.getModel()); + assertEquals(modelId, inference.getModel().getId()); - InferenceActiveOptions activeOptions = response.getInference().getActiveOptions(); + InferenceActiveOptions activeOptions = inference.getActiveOptions(); assertNotNull(activeOptions); assertFalse(activeOptions.getRag()); - assertFalse(activeOptions.getRawText()); + assertTrue(activeOptions.getRawText()); assertFalse(activeOptions.getPolygon()); assertFalse(activeOptions.getConfidence()); + + InferenceResult result = inference.getResult(); + assertNotNull(result); + + RawText rawText = result.getRawText(); + assertEquals(2, rawText.getPages().size()); + + InferenceFields fields = result.getFields(); + assertNotNull(fields); } @Test @@ -71,35 +89,44 @@ void parseFile_filledSinglePage_mustSucceed() throws IOException, InterruptedExc LocalInputSource source = new LocalInputSource( new File("src/test/resources/products/financial_document/default_sample.jpg")); - InferenceParameters options = InferenceParameters + InferenceParameters params = InferenceParameters .builder(modelId) .rag(false) .alias("java-integration-test") .build(); - InferenceResponse response = mindeeClient.enqueueAndGetInference(source, options); - + InferenceResponse response = mindeeClient.enqueueAndGetInference(source, params); assertNotNull(response); - assertNotNull(response.getInference()); + Inference inference = response.getInference(); + assertNotNull(inference); - assertNotNull(response.getInference().getFile()); - assertEquals("default_sample.jpg", response.getInference().getFile().getName()); - - assertNotNull(response.getInference().getModel()); - assertEquals(modelId, response.getInference().getModel().getId()); - - assertNotNull(response.getInference().getResult()); - assertNotNull(response.getInference().getResult().getFields()); - assertNotNull(response.getInference().getResult().getFields().get("supplier_name")); - assertEquals( - "John Smith", - response.getInference() - .getResult() - .getFields() - .get("supplier_name") - .getSimpleField() - .getValue() - ); + InferenceFile file = inference.getFile(); + assertNotNull(file); + assertEquals("default_sample.jpg", file.getName()); + assertEquals(1, file.getPageCount()); + + assertNotNull(inference.getModel()); + assertEquals(modelId, inference.getModel().getId()); + + InferenceActiveOptions activeOptions = inference.getActiveOptions(); + assertNotNull(activeOptions); + assertFalse(activeOptions.getRag()); + assertFalse(activeOptions.getRawText()); + assertFalse(activeOptions.getPolygon()); + assertFalse(activeOptions.getConfidence()); + + InferenceResult result = inference.getResult(); + assertNotNull(result); + + RawText rawText = result.getRawText(); + assertNull(rawText); + + InferenceFields fields = result.getFields(); + assertNotNull(fields); + + SimpleField supplierName = fields.getSimpleField("supplier_name"); + assertNotNull(supplierName); + assertEquals("John Smith", supplierName.getStringValue()); } diff --git a/src/test/java/com/mindee/parsing/v2/InferenceTest.java b/src/test/java/com/mindee/parsing/v2/InferenceTest.java index ada237a07..0a25123b6 100644 --- a/src/test/java/com/mindee/parsing/v2/InferenceTest.java +++ b/src/test/java/com/mindee/parsing/v2/InferenceTest.java @@ -451,8 +451,8 @@ class RawTexts { @Test @DisplayName("raw texts option must be parsed and exposed") void rawTexts_mustBeAccessible() throws IOException { - InferenceResponse resp = loadFromResource("v2/inference/raw_texts.json"); - Inference inference = resp.getInference(); + InferenceResponse response = loadFromResource("v2/inference/raw_texts.json"); + Inference inference = response.getInference(); assertNotNull(inference); InferenceActiveOptions activeOptions = inference.getActiveOptions();