diff --git a/.github/workflows/_test-integrations.yml b/.github/workflows/_test-integrations.yml index e2f7ef90..a9b9f102 100644 --- a/.github/workflows/_test-integrations.yml +++ b/.github/workflows/_test-integrations.yml @@ -19,6 +19,7 @@ env: MINDEE_V2_SE_TESTS_BLANK_PDF_URL: ${{ secrets.MINDEE_V2_SE_TESTS_BLANK_PDF_URL }} MINDEE_V2_CLASSIFICATION_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CLASSIFICATION_MODEL_ID }} MINDEE_V2_CROP_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CROP_MODEL_ID }} + MINDEE_V2_SE_TESTS_CROP_EXTRACTION_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CROP_EXTRACTION_MODEL_ID }} MINDEE_V2_OCR_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_OCR_MODEL_ID }} MINDEE_V2_SPLIT_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_SPLIT_MODEL_ID }} diff --git a/.github/workflows/_test-smoke.yml b/.github/workflows/_test-smoke.yml index 6d05b405..e7aa97d9 100644 --- a/.github/workflows/_test-smoke.yml +++ b/.github/workflows/_test-smoke.yml @@ -12,6 +12,7 @@ env: MINDEE_V2_SE_TESTS_FINDOC_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_FINDOC_MODEL_ID }} MINDEE_V2_SE_TESTS_CLASSIFICATION_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CLASSIFICATION_MODEL_ID }} MINDEE_V2_SE_TESTS_CROP_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CROP_MODEL_ID }} + MINDEE_V2_SE_TESTS_CROP_EXTRACTION_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_CROP_EXTRACTION_MODEL_ID }} MINDEE_V2_SE_TESTS_SPLIT_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_SPLIT_MODEL_ID }} MINDEE_V2_SE_TESTS_OCR_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_OCR_MODEL_ID }} MINDEE_V2_SE_TESTS_FAILURE_WEBHOOK_ID: ${{ secrets.MINDEE_V2_SE_TESTS_FAILURE_WEBHOOK_ID }} diff --git a/src/V2/Product/Classification/ClassificationClassifier.php b/src/V2/Product/Classification/ClassificationClassifier.php index 59913398..4e8d4be0 100644 --- a/src/V2/Product/Classification/ClassificationClassifier.php +++ b/src/V2/Product/Classification/ClassificationClassifier.php @@ -2,6 +2,8 @@ namespace Mindee\V2\Product\Classification; +use Mindee\Parsing\V2\InferenceResponse; + /** * Classification of document type from the source file. */ @@ -12,12 +14,19 @@ class ClassificationClassifier */ public string $documentType; + /** + * @var InferenceResponse|null $extractionResponse The extraction response associated with the classification. + */ + public ?InferenceResponse $extractionResponse; + /** * @param array $rawPrediction Raw prediction array. */ public function __construct(array $rawPrediction) { $this->documentType = $rawPrediction['document_type']; + $this->extractionResponse = isset($rawPrediction['extraction_response']) ? + new InferenceResponse($rawPrediction['extraction_response']) : null; } /** diff --git a/src/V2/Product/Crop/CropItem.php b/src/V2/Product/Crop/CropItem.php index d38a11fa..6a404012 100644 --- a/src/V2/Product/Crop/CropItem.php +++ b/src/V2/Product/Crop/CropItem.php @@ -3,6 +3,7 @@ namespace Mindee\V2\Product\Crop; use Mindee\Parsing\V2\Field\FieldLocation; +use Mindee\Parsing\V2\InferenceResponse; /** * Result of a cropped document region. @@ -19,6 +20,10 @@ class CropItem */ public string $objectType; + /** + * @var InferenceResponse|null $extractionResponse The extraction response associated with the crop. + */ + public ?InferenceResponse $extractionResponse; /** * @param array $rawResponse Raw server response array. */ @@ -26,6 +31,8 @@ public function __construct(array $rawResponse) { $this->location = new FieldLocation($rawResponse['location']); $this->objectType = $rawResponse['object_type']; + $this->extractionResponse = isset($rawResponse['extraction_response']) ? + new InferenceResponse($rawResponse['extraction_response']) : null; } /** diff --git a/src/V2/Product/Split/SplitRange.php b/src/V2/Product/Split/SplitRange.php index d1d12d27..284f1712 100644 --- a/src/V2/Product/Split/SplitRange.php +++ b/src/V2/Product/Split/SplitRange.php @@ -2,6 +2,8 @@ namespace Mindee\V2\Product\Split; +use Mindee\Parsing\V2\InferenceResponse; + /** * A single document as identified when splitting a multi-document source file. */ @@ -18,6 +20,12 @@ class SplitRange */ public string $documentType; + /** + * @var InferenceResponse|null $extractionResponse The extraction response associated with the split. + */ + public ?InferenceResponse $extractionResponse; + + /** * @param array $rawResponse Raw server response array. */ @@ -25,6 +33,8 @@ public function __construct(array $rawResponse) { $this->pageRange = $rawResponse['page_range']; $this->documentType = $rawResponse['document_type']; + $this->extractionResponse = isset($rawResponse['extraction_response']) ? + new InferenceResponse($rawResponse['extraction_response']) : null; } /** diff --git a/tests/V2/FileOperations/CropFunctional.php b/tests/V2/FileOperations/CropFunctional.php index 93878fb3..c7de38b2 100644 --- a/tests/V2/FileOperations/CropFunctional.php +++ b/tests/V2/FileOperations/CropFunctional.php @@ -80,12 +80,12 @@ public function testExtractCropsFromImageCorrectly(): void $extractedImages->saveAllToDisk($this->outputDir, quality: 50); $file1Info = filesize($this->outputDir . '/crop_001.jpg'); - $this->assertGreaterThanOrEqual(98000, $file1Info); - $this->assertLessThanOrEqual(110000, $file1Info); + $this->assertGreaterThanOrEqual(97000, $file1Info); + $this->assertLessThanOrEqual(100000, $file1Info); $file2Info = filesize($this->outputDir . '/crop_002.jpg'); - $this->assertGreaterThanOrEqual(98000, $file2Info); - $this->assertLessThanOrEqual(110000, $file2Info); + $this->assertGreaterThanOrEqual(97000, $file2Info); + $this->assertLessThanOrEqual(100000, $file2Info); } public function testExtractCropsFromEachPdfPageCorrectly(): void diff --git a/tests/V2/Product/ClassificationFunctional.php b/tests/V2/Product/ClassificationFunctional.php index a2279b3d..5d91bce7 100644 --- a/tests/V2/Product/ClassificationFunctional.php +++ b/tests/V2/Product/ClassificationFunctional.php @@ -33,7 +33,7 @@ protected function setUp(): void public function testClassificationDefaultSampleMustSucceed(): void { $inputSource = new PathInput( - TestingUtilities::getV2ProductDir() . '/classification/default_invoice.jpg' + TestingUtilities::getV2ProductDir() . '/classification/default_sample.jpg' ); $productParams = new ClassificationParameters($this->classificationModelId); @@ -44,7 +44,7 @@ public function testClassificationDefaultSampleMustSucceed(): void $file = $response->inference->file; $this->assertNotNull($file); - $this->assertSame("default_invoice.jpg", $file->name); + $this->assertSame("default_sample.jpg", $file->name); $result = $response->inference->result; $this->assertNotNull($result); diff --git a/tests/V2/Product/ClassificationTest.php b/tests/V2/Product/ClassificationTest.php index 64d13de0..4f6b9357 100644 --- a/tests/V2/Product/ClassificationTest.php +++ b/tests/V2/Product/ClassificationTest.php @@ -20,7 +20,7 @@ class ClassificationTest extends TestCase */ private static function getInference(): array { - $fullPath = TestingUtilities::getV2ProductDir() . "/classification/classification_single.json"; + $fullPath = TestingUtilities::getV2ProductDir() . "/classification/default_sample.json"; $content = file_get_contents($fullPath); return json_decode($content, true); } diff --git a/tests/V2/Product/CropFunctional.php b/tests/V2/Product/CropFunctional.php index df5a9e82..d509cb37 100644 --- a/tests/V2/Product/CropFunctional.php +++ b/tests/V2/Product/CropFunctional.php @@ -15,6 +15,7 @@ class CropFunctional extends TestCase { private ClientV2 $client; private string $cropModelId; + private string $cropExtractionModelId; protected function setUp(): void { @@ -22,6 +23,7 @@ protected function setUp(): void $this->client = new ClientV2($apiKey); $this->cropModelId = getenv('MINDEE_V2_CROP_MODEL_ID') ?: ''; + $this->cropExtractionModelId = getenv('MINDEE_V2_SE_TESTS_CROP_EXTRACTION_MODEL_ID') ?: ''; } /** @@ -57,4 +59,55 @@ public function testCropDefaultSampleMustSucceed(): void $this->assertNotNull($crop->location); } } + + /** + * Tests the success of the crop and extraction process. + * + * @return void + */ + public function testCropAndExtractionMustSucceed(): void + { + $inputSource = new PathInput( + TestingUtilities::getV2ProductDir() . '/crop/default_sample.jpg' + ); + + $productParams = new CropParameters( + $this->cropExtractionModelId, + "nodejs_integration-test_crop_multipage" + ); + + $response = $this->client->enqueueAndGetResult( + CropResponse::class, + $inputSource, + $productParams + ); + + $this->assertNotNull($response); + $inference = $response->inference; + $this->assertNotNull($inference); + + $file = $inference->file; + $this->assertNotNull($file); + $this->assertSame("default_sample.jpg", $file->name); + $this->assertSame(1, $file->pageCount); + + $this->assertNotNull($inference->model); + $this->assertSame($this->cropExtractionModelId, $inference->model->id); + + $result = $inference->result; + $this->assertNotNull($result); + $this->assertCount(2, $result->crops); + + $crop0 = $result->crops[0]; + $this->assertSame("receipt", $crop0->objectType); + $this->assertNotNull($crop0->location->polygon); + $this->assertSame(0, $crop0->location->page); + $extractionResponse0 = $crop0->extractionResponse; + $this->assertNotNull($extractionResponse0); + + $supplierName = $extractionResponse0->inference->result->fields + ->getSimpleField("supplier_name")->value; + + $this->assertSame("CHEZ ALAIN MIAM MIAM", $supplierName); + } } diff --git a/tests/V2/Product/CropTest.php b/tests/V2/Product/CropTest.php index dbfd3d67..eee10c35 100644 --- a/tests/V2/Product/CropTest.php +++ b/tests/V2/Product/CropTest.php @@ -60,7 +60,7 @@ private static function normalizeLineEndings(string $input): string */ public function testCropWhenSingleMustHaveValidProperties(): void { - $jsonSample = self::getInference("crop/crop_single.json"); + $jsonSample = self::getInference("crop/default_sample.json"); $response = new CropResponse($jsonSample); $this->assertInferenceResponse($response); @@ -77,20 +77,20 @@ public function testCropWhenSingleMustHaveValidProperties(): void $crops = $inference->result->crops; $this->assertNotNull($crops); - $this->assertCount(1, $crops); + $this->assertCount(2, $crops); $firstCrop = $crops[0]; - $this->assertSame("invoice", $firstCrop->objectType); + $this->assertSame("receipt", $firstCrop->objectType); $this->assertSame(0, $firstCrop->location->page); $polygon = $firstCrop->location->polygon; $this->assertCount(4, $polygon->getCoordinates()); // Note: Using assertEquals here instead of assertSame to allow for object value comparison - $this->assertEquals(new Point(0.15, 0.254), $polygon->getCoordinates()[0]); - $this->assertEquals(new Point(0.85, 0.254), $polygon->getCoordinates()[1]); - $this->assertEquals(new Point(0.85, 0.947), $polygon->getCoordinates()[2]); - $this->assertEquals(new Point(0.15, 0.947), $polygon->getCoordinates()[3]); + $this->assertEquals(new Point(0.214, 0.036), $polygon->getCoordinates()[0]); + $this->assertEquals(new Point(0.476, 0.036), $polygon->getCoordinates()[1]); + $this->assertEquals(new Point(0.476, 0.949), $polygon->getCoordinates()[2]); + $this->assertEquals(new Point(0.214, 0.949), $polygon->getCoordinates()[3]); } /** diff --git a/tests/resources b/tests/resources index 53f0efbc..315efcc3 160000 --- a/tests/resources +++ b/tests/resources @@ -1 +1 @@ -Subproject commit 53f0efbc08c77c2c085aadd27de9d2d6c359276e +Subproject commit 315efcc302efacfb75a6b101788058658e8c37e4