Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/clientV2.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { InputSource } from "./input";
import { DataSchema, InputSource } from "./input";
import { errorHandler } from "./errors/handler";
import { LOG_LEVELS, logger } from "./logger";

import { setTimeout } from "node:timers/promises";
import { ErrorResponse, InferenceResponse, JobResponse } from "./parsing/v2";
import { MindeeApiV2 } from "./http/mindeeApiV2";
import { MindeeHttpErrorV2 } from "./errors/mindeeError";
import { StringDict } from "./parsing/common";

/**
* Parameters for the internal polling loop in {@link ClientV2.enqueueAndGetInference | enqueueAndGetInference()} .
Expand Down Expand Up @@ -102,6 +103,11 @@ export interface InferenceParameters {
/** By default, the file is closed once the upload is finished.
* Set to `false` to keep it open. */
closeFile?: boolean;
/**
* Dynamic changes to the data schema of the model for this inference.
* Not recommended, for specific use only.
*/
dataSchema?: DataSchema|StringDict|string;
}

/**
Expand Down Expand Up @@ -152,6 +158,18 @@ export class ClientV2 {
logger.debug("ClientV2 initialized");
}

/**
* Checks the Data Schema.
* @param params Input Inference parameters.
*/
validateDataSchema(params: InferenceParameters): void {
if (params.dataSchema !== undefined && params.dataSchema !== null){
if (!(params.dataSchema instanceof DataSchema)){
params.dataSchema = new DataSchema(params.dataSchema);
}
}
}

/**
* Send the document to an asynchronous endpoint and return its ID in the queue.
* @param inputSource file or URL to parse.
Expand All @@ -166,7 +184,9 @@ export class ClientV2 {
if (inputSource === undefined) {
throw new Error("The 'enqueue' function requires an input document.");
}
this.validateDataSchema(params);
await inputSource.init();

return await this.mindeeApi.reqPostInferenceEnqueue(inputSource, params);
}

Expand Down
3 changes: 3 additions & 0 deletions src/http/mindeeApiV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ export class MindeeApiV2 {
if (params.textContext !== undefined && params.textContext !== null) {
form.append("text_context", params.textContext);
}
if (params.dataSchema !== undefined && params.dataSchema !== null) {
form.append("data_schema", params.dataSchema.toString());
}
if (params.webhookIds && params.webhookIds.length > 0) {
form.append("webhook_ids", params.webhookIds.join(","));
}
Expand Down
142 changes: 142 additions & 0 deletions src/input/dataSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { StringDict } from "../parsing/common";
import { MindeeError } from "../errors";

export class DataSchemaField {
/**
* Display name for the field, also impacts inference results.
*/
public title: string;

/**
* Name of the field in the data schema.
*/
public name: string;

/**
* Whether this field can contain multiple values.
*/
public isArray: boolean;

/**
* Data type of the field.
*/
public type: string;

/**
* Allowed values when type is `classification`. Leave empty for other types.
*/
public classificationValues?: Array<string>;

/**
* Whether to remove duplicate values in the array.
* Only applicable if `is_array` is True.
*/
public uniqueValues?: boolean;

/**
* Detailed description of what this field represents.
*/
public description?: string;

/**
* Optional extraction guidelines.
*/
public guidelines?: string;

/**
* Subfields when type is `nested_object`. Leave empty for other types.
*/
public nestedFields?: StringDict;

constructor(fields: StringDict) {
this.name = fields["name"];
this.title = fields["title"];
this.isArray = fields["is_array"];
this.type = fields["type"];
this.classificationValues = fields["classification_values"];
this.uniqueValues = fields["unique_values"];
this.description = fields["description"];
this.guidelines = fields["guidelines"];
this.nestedFields = fields["nested_fields"];
}

toJSON() {
const out: Record<string, unknown> = {
name: this.name,
title: this.title,
// eslint-disable-next-line @typescript-eslint/naming-convention,camelcase
is_array: this.isArray,
type: this.type,
};

// eslint-disable-next-line camelcase
if (this.classificationValues !== undefined) out.classification_values = this.classificationValues;
// eslint-disable-next-line camelcase
if (this.uniqueValues !== undefined) out.unique_values = this.uniqueValues;
if (this.description !== undefined) out.description = this.description;
if (this.guidelines !== undefined) out.guidelines = this.guidelines;
// eslint-disable-next-line camelcase
if (this.nestedFields !== undefined) out.nested_fields = this.nestedFields;

return out;
}

toString() {
return JSON.stringify(this.toJSON());
}
}

/**
* The structure to completely replace the data schema of the model.
*/
export class DataSchemaReplace {
/**
* List of fields in the Data Schema.
*/
fields: Array<DataSchemaField>;

constructor(dataSchemaReplace: StringDict) {
if (!dataSchemaReplace || !dataSchemaReplace.fields ) {
throw new MindeeError("Invalid Data Schema provided.");
}
if (dataSchemaReplace["fields"].length === 0) {
throw new TypeError("Data Schema replacement fields cannot be empty.");
}
this.fields = dataSchemaReplace["fields"].map((field: StringDict) => (new DataSchemaField(field)));
}

toJSON() {
return { fields: this.fields.map(e => e.toJSON()) };
}

toString() {
return JSON.stringify(this.toJSON());
}
}

/**
* Modify the Data Schema.
*/
export class DataSchema {
/**
* If set, completely replaces the data schema of the model.
*/
replace?: DataSchemaReplace;

constructor(dataSchema: StringDict | string) {
if (typeof dataSchema === "string") {
this.replace = new DataSchemaReplace(JSON.parse(dataSchema)["replace"]);
} else if (dataSchema["replace"] instanceof DataSchemaReplace) {
this.replace = dataSchema["replace"];
} else {
this.replace = new DataSchemaReplace(dataSchema["replace"] as StringDict);
}
}

toJSON() {
return { replace: this.replace?.toJSON() };
}
toString() {
return JSON.stringify(this.toJSON());
}
}
3 changes: 2 additions & 1 deletion src/input/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { PageOptions, PageOptionsOperation } from "./pageOptions";
export { DataSchema, DataSchemaField, DataSchemaReplace } from "./dataSchema";
export * from "./sources";
export { LocalResponse } from "./localResponse";
export { PageOptions, PageOptionsOperation } from "./pageOptions";
19 changes: 19 additions & 0 deletions src/parsing/v2/dataSchemaActiveOption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { StringDict } from "../common";

/**
* Data schema options activated during the inference.
*/
export class DataSchemaActiveOption {
/**
* Whether to replace the data schema.
*/
replace: boolean;

constructor(serverResponse: StringDict) {
this.replace = serverResponse["replace"];
}

toString() {
return `Data Schema\n-----------\n:Replace: ${this.replace? "True" : "False"}`;
}
}
11 changes: 10 additions & 1 deletion src/parsing/v2/inferenceActiveOptions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { StringDict } from "../common";
import { DataSchemaActiveOption } from "./dataSchemaActiveOption";

export class InferenceActiveOptions {
/**
Expand All @@ -23,12 +24,18 @@ export class InferenceActiveOptions {
*/
public textContext: boolean;

/**
* Data schema options provided for the inference.
*/
public dataSchema: DataSchemaActiveOption;

constructor(serverResponse: StringDict) {
this.rag = serverResponse["rag"];
this.rawText = serverResponse["raw_text"];
this.polygon = serverResponse["polygon"];
this.confidence = serverResponse["confidence"];
this.textContext = serverResponse["text_context"];
this.dataSchema = new DataSchemaActiveOption(serverResponse["data_schema"]);
}

toString(): string {
Expand All @@ -37,6 +44,8 @@ export class InferenceActiveOptions {
`:Raw Text: ${this.rawText ? "True" : "False"}\n` +
`:Polygon: ${this.polygon ? "True" : "False"}\n` +
`:Confidence: ${this.confidence ? "True" : "False"}\n` +
`:RAG: ${this.rag ? "True" : "False"}\n`;
`:RAG: ${this.rag ? "True" : "False"}\n` +
`:Text Context: ${this.textContext ? "True" : "False"}\n\n` +
`${this.dataSchema}\n`;
}
}
Loading