Skip to content

Commit b98e92c

Browse files
authored
✨ add job information to inference object (#169)
1 parent 557b17d commit b98e92c

7 files changed

Lines changed: 171 additions & 32 deletions

File tree

src/Parsing/V2/Inference.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
*/
88
class Inference
99
{
10+
/**
11+
* @var string ID of the inference.
12+
*/
13+
public string $id;
14+
15+
/**
16+
* @var InferenceJob Job the inference belongs to.
17+
*/
18+
public InferenceJob $job;
19+
1020
/**
1121
* @var InferenceModel Model info for the inference.
1222
*/
@@ -27,21 +37,17 @@ class Inference
2737
*/
2838
public InferenceResult $result;
2939

30-
/**
31-
* @var string|null ID of the inference.
32-
*/
33-
public ?string $id;
34-
3540
/**
3641
* @param array $serverResponse Raw server response array.
3742
*/
3843
public function __construct(array $serverResponse)
3944
{
45+
$this->id = $serverResponse['id'];
46+
$this->job = new InferenceJob($serverResponse['job']);
4047
$this->model = new InferenceModel($serverResponse['model']);
4148
$this->file = new InferenceFile($serverResponse['file']);
4249
$this->activeOptions = new InferenceActiveOptions($serverResponse['active_options']);
4350
$this->result = new InferenceResult($serverResponse['result']);
44-
$this->id = $serverResponse['id'] ?? null;
4551
}
4652

4753
/**
@@ -50,6 +56,7 @@ public function __construct(array $serverResponse)
5056
public function __toString(): string
5157
{
5258
return "Inference\n#########\n"
59+
. "{$this->job}\n"
5360
. "{$this->model}\n"
5461
. "{$this->file}\n"
5562
. "{$this->activeOptions}\n"

src/Parsing/V2/InferenceJob.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Mindee\Parsing\V2;
4+
5+
/**
6+
* Information on the Job associated to a given Inference.
7+
*/
8+
class InferenceJob
9+
{
10+
/**
11+
* @var string UUID of the job.
12+
*/
13+
public string $id;
14+
15+
/**
16+
* @param array $serverResponse Raw server response array.
17+
*/
18+
public function __construct(array $serverResponse)
19+
{
20+
$this->id = $serverResponse['id'];
21+
}
22+
23+
/**
24+
* @return string String representation.
25+
*/
26+
public function __toString(): string
27+
{
28+
return "Job\n===\n"
29+
. ":ID: {$this->id}\n" ;
30+
}
31+
}

src/Parsing/V2/Job.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ class Job
2121
public ?ErrorResponse $error;
2222

2323
/**
24-
* @var DateTime|null Timestamp of the job creation.
24+
* @var DateTime Date and time of the Job creation.
2525
*/
26-
public ?DateTime $createdAt;
26+
public DateTime $createdAt;
27+
28+
/**
29+
* @var DateTime|null Date and time of the Job completion. Filled once processing is finished.
30+
*/
31+
public ?DateTime $completedAt;
2732

2833
/**
2934
* @var string ID of the model.
@@ -76,8 +81,9 @@ public function __construct(array $serverResponse)
7681
$this->error = new ErrorResponse($serverResponse['error']);
7782
}
7883

79-
$this->createdAt = isset($serverResponse['created_at'])
80-
? $this->parseDate($serverResponse['created_at'])
84+
$this->createdAt = $this->parseDate($serverResponse['created_at']);
85+
$this->completedAt = isset($serverResponse['completed_at'])
86+
? $this->parseDate($serverResponse['completed_at'])
8187
: null;
8288

8389
$this->modelId = $serverResponse['model_id'];

tests/TestingUtilities.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public static function getV2DataDir(): string
2929
return TestingUtilities::getRootDataDir() . "/v2";
3030
}
3131

32+
/**
33+
* @return string Return the root of the v2 products directory.
34+
*/
35+
public static function getV2ProductDir(): string
36+
{
37+
return TestingUtilities::getV2DataDir() . "/products";
38+
}
39+
3240
/**
3341
* @return string Return the root of the file types directory.
3442
*/

tests/V2/Parsing/InferenceResponseTest.php

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace V2\parsing;
3+
namespace V2\Parsing;
44

55
use Mindee\Error\ErrorItem;
66
use Mindee\Geometry\Point;
@@ -24,7 +24,7 @@ class InferenceResponseTest extends TestCase
2424
{
2525
private function loadFromResource(string $resourcePath): InferenceResponse
2626
{
27-
$fullPath = TestingUtilities::getRootDataDir() . "/$resourcePath";
27+
$fullPath = TestingUtilities::getV2ProductDir() . "/$resourcePath";
2828
$this->assertFileExists($fullPath, "Resource file must exist: $resourcePath");
2929

3030
$localResponse = new LocalResponse($fullPath);
@@ -39,11 +39,12 @@ private function readFileAsString(string $path): string
3939
}
4040

4141
/**
42-
* When the async prediction is blank - all properties must be valid
42+
* When the async prediction is blank - all properties must be valid.
43+
* @return void
4344
*/
4445
public function testAsyncPredictWhenEmptyMustHaveValidProperties(): void
4546
{
46-
$response = $this->loadFromResource('v2/products/extraction/financial_document/blank.json');
47+
$response = $this->loadFromResource('extraction/financial_document/blank.json');
4748
$fields = $response->inference->result->fields;
4849

4950
$this->assertCount(21, $fields, 'Expected 21 fields');
@@ -91,11 +92,12 @@ public function testAsyncPredictWhenEmptyMustHaveValidProperties(): void
9192
}
9293

9394
/**
94-
* When the async prediction is complete - every exposed property must be valid and consistent
95+
* When the async prediction is complete - every exposed property must be valid and consistent.
96+
* @return void
9597
*/
9698
public function testAsyncPredictWhenCompleteMustExposeAllProperties(): void
9799
{
98-
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete.json');
100+
$response = $this->loadFromResource('extraction/financial_document/complete.json');
99101
$inference = $response->inference;
100102

101103
$this->assertNotNull($inference, 'Inference must not be null');
@@ -154,11 +156,12 @@ public function testAsyncPredictWhenCompleteMustExposeAllProperties(): void
154156
}
155157

156158
/**
157-
* Deep nested fields - all nested structures must be typed correctly
159+
* Deep nested fields - all nested structures must be typed correctly.
160+
* @return void
158161
*/
159162
public function testDeepNestedFieldsMustExposeCorrectTypes(): void
160163
{
161-
$response = $this->loadFromResource('v2/products/extraction/deep_nested_fields.json');
164+
$response = $this->loadFromResource('extraction/deep_nested_fields.json');
162165
$inference = $response->inference;
163166
$this->assertNotNull($inference);
164167

@@ -198,11 +201,12 @@ public function testDeepNestedFieldsMustExposeCorrectTypes(): void
198201
}
199202

200203
/**
201-
* Standard field types - simple / object / list variants must be recognised
204+
* Standard field types - simple / object / list variants must be recognised.
205+
* @return void
202206
*/
203207
public function testStandardFieldTypesMustExposeCorrectTypes(): void
204208
{
205-
$response = $this->loadFromResource('v2/products/extraction/standard_field_types.json');
209+
$response = $this->loadFromResource('extraction/standard_field_types.json');
206210
$inference = $response->inference;
207211
$this->assertNotNull($inference);
208212

@@ -279,11 +283,12 @@ public function testStandardFieldTypesMustExposeCorrectTypes(): void
279283
}
280284

281285
/**
282-
* Raw texts option must be parsed and exposed
286+
* Raw texts option must be parsed and exposed.
287+
* @return void
283288
*/
284289
public function testRawTextsMustBeAccessible(): void
285290
{
286-
$response = $this->loadFromResource('v2/products/extraction/raw_texts.json');
291+
$response = $this->loadFromResource('extraction/raw_texts.json');
287292
$inference = $response->inference;
288293
$this->assertNotNull($inference);
289294

@@ -306,13 +311,14 @@ public function testRawTextsMustBeAccessible(): void
306311
}
307312

308313
/**
309-
* RST display must be parsed and exposed
314+
* RST display must be parsed and exposed.
315+
* @return void
310316
*/
311317
public function testRstDisplayMustBeAccessible(): void
312318
{
313-
$response = $this->loadFromResource('v2/products/extraction/standard_field_types.json');
319+
$response = $this->loadFromResource('extraction/standard_field_types.json');
314320
$expectedRst = $this->readFileAsString(
315-
\TestingUtilities::getV2DataDir() . '/products/extraction/standard_field_types.rst'
321+
\TestingUtilities::getV2ProductDir() . '/extraction/standard_field_types.rst'
316322
);
317323
$inference = $response->inference;
318324
$this->assertNotNull($inference);
@@ -321,10 +327,11 @@ public function testRstDisplayMustBeAccessible(): void
321327

322328
/**
323329
* Coordinates & location data must be parsed and exposed.
330+
* @return void
324331
*/
325332
public function testCoordinatesAndLocationDataMustBeAccessible(): void
326333
{
327-
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete_with_coordinates.json');
334+
$response = $this->loadFromResource('extraction/financial_document/complete_with_coordinates.json');
328335
$inference = $response->inference;
329336
$this->assertNotNull($inference);
330337

@@ -383,23 +390,25 @@ public function testCoordinatesAndLocationDataMustBeAccessible(): void
383390

384391
public function testRagMetadataWhenMatched()
385392
{
386-
$response = $this->loadFromResource('v2/products/extraction/rag_matched.json');
393+
$response = $this->loadFromResource('extraction/rag_matched.json');
387394
$inference = $response->inference;
388395
$this->assertNotNull($inference);
389396
$this->assertEquals('12345abc-1234-1234-1234-123456789abc', $inference->result->rag->retrievedDocumentId);
390397
}
391398

392399
public function testRagMetadataWhenNotMatched()
393400
{
394-
$response = $this->loadFromResource('v2/products/extraction/rag_not_matched.json');
401+
$response = $this->loadFromResource('extraction/rag_not_matched.json');
395402
$inference = $response->inference;
396403
$this->assertNotNull($inference);
397404
$this->assertNull($inference->result->rag->retrievedDocumentId);
398405
}
399406

400407
public function testShouldLoadWith422Error()
401408
{
402-
$jsonResponse = json_decode(file_get_contents(\TestingUtilities::getV2DataDir() . '/job/fail_422.json'), true);
409+
$jsonResponse = json_decode(
410+
file_get_contents(\TestingUtilities::getV2DataDir() . '/job/fail_422.json'), true
411+
);
403412
$response = new JobResponse($jsonResponse);
404413
$this->assertNotNull($response->job);
405414
$this->assertInstanceOf(ErrorResponse::class, $response->job->error);
@@ -411,7 +420,7 @@ public function testShouldLoadWith422Error()
411420

412421
public function testTextContextIsTrue(): void
413422
{
414-
$response = $this->loadFromResource('v2/products/extraction/text_context_enabled.json');
423+
$response = $this->loadFromResource('extraction/text_context_enabled.json');
415424
$inference = $response->inference;
416425
$this->assertNotNull($inference);
417426
$activeOptions = $inference->activeOptions;
@@ -424,7 +433,7 @@ public function testTextContextIsTrue(): void
424433

425434
public function testTextContextIsFalse(): void
426435
{
427-
$response = $this->loadFromResource('v2/products/extraction/financial_document/complete.json');
436+
$response = $this->loadFromResource('extraction/financial_document/complete.json');
428437
$inference = $response->inference;
429438
$this->assertNotNull($inference);
430439
$activeOptions = $inference->activeOptions;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,79 @@
11
<?php
2+
3+
namespace V2\Parsing;
4+
5+
use DateTime;
6+
use Mindee\Error\ErrorItem;
7+
use Mindee\Parsing\V2\ErrorResponse;
8+
use Mindee\Parsing\V2\JobResponse;
9+
use PHPUnit\Framework\TestCase;
10+
use TestingUtilities;
11+
12+
require_once(__DIR__ . "/../../TestingUtilities.php");
13+
14+
class TestJobResponse extends TestCase
15+
{
16+
/**
17+
* Load a job sample JSON file and return its decoded contents.
18+
*
19+
* @param string $jsonFile Name of the JSON file to load.
20+
* @return array Decoded JSON data.
21+
*/
22+
private static function getJobSamples(string $jsonFile): array
23+
{
24+
$fullPath = TestingUtilities::getV2DataDir() . "/job/$jsonFile";
25+
$content = file_get_contents($fullPath);
26+
return json_decode($content, true);
27+
}
28+
29+
/**
30+
* Should load when status is Processing.
31+
* @return void
32+
*/
33+
public function testShouldLoadWhenStatusIsProcessing(): void
34+
{
35+
$jsonSample = self::getJobSamples('ok_processing.json');
36+
$response = new JobResponse($jsonSample);
37+
38+
$this->assertNotNull($response->job);
39+
$this->assertSame('Processing', $response->job->status);
40+
$this->assertNull($response->job->completedAt);
41+
$this->assertNull($response->job->error);
42+
}
43+
44+
/**
45+
* Should load when status is Processed.
46+
* @return void
47+
*/
48+
public function testShouldLoadWhenStatusIsProcessed(): void
49+
{
50+
$jsonSample = self::getJobSamples('ok_processed_webhooks_ok.json');
51+
$response = new JobResponse($jsonSample);
52+
53+
$this->assertNotNull($response->job);
54+
$this->assertSame('Processed', $response->job->status);
55+
$this->assertInstanceOf(DateTime::class, $response->job->completedAt);
56+
$this->assertNull($response->job->error);
57+
}
58+
59+
/**
60+
* Should load with 422 error.
61+
* @return void
62+
*/
63+
public function testShouldLoadWith422Error(): void
64+
{
65+
$jsonSample = self::getJobSamples('fail_422.json');
66+
$response = new JobResponse($jsonSample);
67+
68+
$this->assertNotNull($response->job);
69+
$this->assertSame('Failed', $response->job->status);
70+
$this->assertInstanceOf(DateTime::class, $response->job->completedAt);
71+
72+
$this->assertInstanceOf(ErrorResponse::class, $response->job->error);
73+
$this->assertSame(422, $response->job->error->status);
74+
$this->assertStringStartsWith('422-', $response->job->error->code);
75+
$this->assertIsArray($response->job->error->errors);
76+
$this->assertCount(1, $response->job->error->errors);
77+
$this->assertInstanceOf(ErrorItem::class, $response->job->error->errors[0]);
78+
}
79+
}

0 commit comments

Comments
 (0)