From 0badd7937202422b569307a42e3e1862891eda4d Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 8 Apr 2024 18:14:48 +0530 Subject: [PATCH 01/41] feat: setup basic dataset versions --- src/client/dataset.ts | 134 ++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 1 + 2 files changed, 135 insertions(+) create mode 100644 src/client/dataset.ts diff --git a/src/client/dataset.ts b/src/client/dataset.ts new file mode 100644 index 0000000..b0e704a --- /dev/null +++ b/src/client/dataset.ts @@ -0,0 +1,134 @@ +import { + DatasetVersion, + Dataset as GrpcDataset, +} from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import { UserError } from "../errors"; +import { ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; +import { AuthConfig } from "../utils/types"; +import { Lister } from "./lister"; +import os from "os"; +import { Input } from "./input"; +import { + DeleteDatasetVersionsRequest, + ListDatasetVersionsRequest, + PostDatasetVersionsRequest, +} from "clarifai-nodejs-grpc/proto/clarifai/api/service_pb"; +import { + JavaScriptValue, + Struct, +} from "google-protobuf/google/protobuf/struct_pb"; +import { promisifyGrpcCall } from "../utils/misc"; +import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; + +type DatasetConfig = + | { + authConfig?: AuthConfig; + datasetId: string; + datasetVersionId?: string; + url?: undefined; + } + | { + authConfig?: AuthConfig; + datasetId?: undefined; + datasetVersionId?: undefined; + url: ClarifaiUrl; + }; + +export class Dataset extends Lister { + private info: GrpcDataset = new GrpcDataset(); + private numOfWorkers: number = os.cpus().length; + private annotNumOfWorkers: number = 4; + private maxRetries: number = 10; + private batchSize: number = 128; + private task; + private inputObject: Input; + + constructor({ authConfig, datasetId, url, datasetVersionId }: DatasetConfig) { + if (url && datasetId) { + throw new UserError("You can only specify one of url or dataset_id."); + } + if (url) { + const [userId, appId, , _datasetId, _datasetVersionId] = + ClarifaiUrlHelper.splitClarifaiUrl(url); + if (authConfig) authConfig.userId = userId; + if (authConfig) authConfig.appId = appId; + datasetId = _datasetId; + datasetVersionId = _datasetVersionId; + } + + super({ authConfig }); + this.info.setId(datasetId!); + this.info.setVersion(new DatasetVersion().setId(datasetVersionId!)); + this.inputObject = new Input({ authConfig }); + } + + async createVersion( + description: string, + metadata: Record, + ): Promise { + const request = new PostDatasetVersionsRequest(); + request.setUserAppId(this.userAppId); + request.setDatasetId(this.info.getId()); + const datasetVersion = new DatasetVersion(); + datasetVersion.setDescription(description); + datasetVersion.setMetadata(Struct.fromJavaScript(metadata)); + request.setDatasetVersionsList([datasetVersion]); + + const postDatasetVersions = promisifyGrpcCall( + this.STUB.client.postDatasetVersions, + this.STUB.client, + ); + + const response = await this.grpcRequest(postDatasetVersions, request); + const responseObject = response.toObject(); + if (responseObject.status?.code !== StatusCode.SUCCESS) { + throw new Error(responseObject.status?.description); + } + console.info("\nDataset Version created\n%s", response.getStatus()); + + return responseObject.datasetVersionsList[0]; + } + + async deleteVersion(versionId: string): Promise { + const request = new DeleteDatasetVersionsRequest(); + request.setUserAppId(this.userAppId); + request.setDatasetId(this.info.getId()); + request.setDatasetVersionIdsList([versionId]); + + const deleteDatasetVersions = promisifyGrpcCall( + this.STUB.client.deleteDatasetVersions, + this.STUB.client, + ); + const response = await this.grpcRequest(deleteDatasetVersions, request); + const responseObject = response.toObject(); + if (responseObject.status?.code !== StatusCode.SUCCESS) { + throw new Error(responseObject.status?.description); + } + console.info("\nDataset Version Deleted\n%s", response.getStatus()); + } + + async *listVersions( + pageNo?: number, + perPage?: number, + ): AsyncGenerator { + const request = new ListDatasetVersionsRequest(); + request.setUserAppId(this.userAppId); + request.setDatasetId(this.info.getId()); + + const listDatasetVersions = promisifyGrpcCall( + this.STUB.client.listDatasetVersions, + this.STUB.client, + ); + + const listDatasetVersionsGenerator = this.listPagesGenerator( + listDatasetVersions, + request, + pageNo, + perPage, + ); + + for await (const versions of listDatasetVersionsGenerator) { + yield versions.toObject().datasetVersionsList; + } + } +} diff --git a/src/index.ts b/src/index.ts index 537b368..d42ce7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,3 +4,4 @@ export * from "./client/input"; export * from "./client/model"; export * from "./client/search"; export * from "./client/workflow"; +export * from "./client/dataset"; From e5bced7341775b485ebd7dcf20a1019fc5cceaab Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 9 Apr 2024 18:51:32 +0530 Subject: [PATCH 02/41] feat: setup concurrent annotation upload --- package-lock.json | 14 ++++++++++++++ package.json | 3 +++ src/client/dataset.ts | 44 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e68248c..87bbeb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,14 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", + "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.0.9", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "safe-flat": "^2.1.0", "uuidv4": "^6.2.13", "winston": "^3.11.0", @@ -25,6 +27,7 @@ "devDependencies": { "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", + "@types/async": "^3.2.24", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/node": "^20.11.16", @@ -3258,6 +3261,12 @@ "node": ">=10.13.0" } }, + "node_modules/@types/async": { + "version": "3.2.24", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.24.tgz", + "integrity": "sha512-8iHVLHsCCOBKjCF2KwFe0p9Z3rfM9mL+sSP8btyR5vTjJRAqpBYD28/ZLgXPf0pjG1VxOvtCV/BgXkQbpSe8Hw==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -5688,6 +5697,11 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", diff --git a/package.json b/package.json index 3f8f2fb..770bad0 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", + "@types/async": "^3.2.24", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/node": "^20.11.16", @@ -60,12 +61,14 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", + "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.0.9", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "safe-flat": "^2.1.0", "uuidv4": "^6.2.13", "winston": "^3.11.0", diff --git a/src/client/dataset.ts b/src/client/dataset.ts index b0e704a..d1d7646 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -1,4 +1,5 @@ import { + Annotation, DatasetVersion, Dataset as GrpcDataset, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; @@ -19,6 +20,8 @@ import { } from "google-protobuf/google/protobuf/struct_pb"; import { promisifyGrpcCall } from "../utils/misc"; import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; +import { parallelLimit } from "async"; +import compact from "lodash/compact"; type DatasetConfig = | { @@ -36,12 +39,12 @@ type DatasetConfig = export class Dataset extends Lister { private info: GrpcDataset = new GrpcDataset(); - private numOfWorkers: number = os.cpus().length; + private numOfWorkers: number = Math.min(os.cpus().length, 10); private annotNumOfWorkers: number = 4; private maxRetries: number = 10; private batchSize: number = 128; private task; - private inputObject: Input; + private input: Input; constructor({ authConfig, datasetId, url, datasetVersionId }: DatasetConfig) { if (url && datasetId) { @@ -59,7 +62,7 @@ export class Dataset extends Lister { super({ authConfig }); this.info.setId(datasetId!); this.info.setVersion(new DatasetVersion().setId(datasetVersionId!)); - this.inputObject = new Input({ authConfig }); + this.input = new Input({ authConfig }); } async createVersion( @@ -131,4 +134,39 @@ export class Dataset extends Lister { yield versions.toObject().datasetVersionsList; } } + + private async concurrentAnnotUpload( + annots: Annotation[][], + ): Promise>> { + const retryAnnotUpload: Array | null> = []; + + const uploadAnnotations = async ( + inpBatch: Annotation[], + ): Promise => { + try { + return await this.input.uploadAnnotations({ + batchAnnot: inpBatch, + showLog: false, + }); + } catch { + return null; + } + }; + + const maxWorkers = Math.min(this.annotNumOfWorkers, this.numOfWorkers); + + const uploadTasks = annots.map((annotBatch) => { + return async () => { + const uploadedAnnotation = await uploadAnnotations(annotBatch); + if (!uploadedAnnotation) { + retryAnnotUpload.push(annotBatch); + } + return uploadedAnnotation; + }; + }); + + await parallelLimit(uploadTasks, maxWorkers); + + return compact(retryAnnotUpload); + } } From 31d1827550e1269b93831cbdec398599eaf2b25e Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 9 Apr 2024 18:58:13 +0530 Subject: [PATCH 03/41] feat: setup datasets base class --- src/datasets/upload/base.ts | 49 +++++++++++++++++++++++++++++++++ src/datasets/upload/features.ts | 37 +++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/datasets/upload/base.ts create mode 100644 src/datasets/upload/features.ts diff --git a/src/datasets/upload/base.ts b/src/datasets/upload/base.ts new file mode 100644 index 0000000..36978f5 --- /dev/null +++ b/src/datasets/upload/base.ts @@ -0,0 +1,49 @@ +import { + Annotation, + Input, +} from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import { + TextFeatures, + VisualClassificationFeatures, + VisualDetectionFeatures, + VisualSegmentationFeatures, +} from "./features"; + +type OutputFeaturesType = + | TextFeatures + | VisualClassificationFeatures + | VisualDetectionFeatures + | VisualSegmentationFeatures; + +export abstract class ClarifaiDataLoader { + abstract get task(): string; + abstract loadData(): void; + abstract get length(): number; + abstract getItem(index: number): OutputFeaturesType; +} + +export abstract class ClarifaiDataset { + protected dataGenerator: ClarifaiDataLoader; + protected datasetId: string; + + constructor({ + dataGenerator, + datasetId, + }: { + dataGenerator: ClarifaiDataLoader; + datasetId: string; + }) { + this.dataGenerator = dataGenerator; + this.datasetId = datasetId; + } + + abstract get length(): number; + + protected abstract toList(inputProtos: Iterable): unknown[]; + + protected abstract extractProtos(_args: { + batchInputIds: string[]; + }): [Input[], Annotation[]]; + + abstract getProtos(_inputIds: number[]): [Input[], Annotation[]]; +} diff --git a/src/datasets/upload/features.ts b/src/datasets/upload/features.ts new file mode 100644 index 0000000..85103bf --- /dev/null +++ b/src/datasets/upload/features.ts @@ -0,0 +1,37 @@ +import { JavaScriptValue } from "google-protobuf/google/protobuf/struct_pb"; + +export interface TextFeatures { + text: string; + labels: Array; + id?: number; + metadata?: Record; +} + +export interface VisualClassificationFeatures { + image_path: string; + labels: Array; + geo_info?: [number, number]; + id?: number; + metadata?: Record; + image_bytes?: Buffer; +} + +export interface VisualDetectionFeatures { + image_path: string; + labels: Array; + bboxes: Array>; + geo_info?: [number, number]; + id?: number; + metadata?: Record; + image_bytes?: Buffer; +} + +export interface VisualSegmentationFeatures { + image_path: string; + labels: Array; + polygons: Array>>; + geo_info?: [number, number]; + id?: number; + metadata?: Record; + image_bytes?: Buffer; +} From 3a192c5079609b9e39e4321aeb001b8eb410db23 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 10 Apr 2024 17:56:41 +0530 Subject: [PATCH 04/41] feat: setup image classification dataset classes --- package-lock.json | 7 + package.json | 1 + src/client/input.ts | 14 +- src/datasets/upload/base.ts | 17 ++- src/datasets/upload/features.ts | 22 +-- src/datasets/upload/image.ts | 241 ++++++++++++++++++++++++++++++++ 6 files changed, 282 insertions(+), 20 deletions(-) create mode 100644 src/datasets/upload/image.ts diff --git a/package-lock.json b/package-lock.json index 87bbeb8..c4d62a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "@types/async": "^3.2.24", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", @@ -3297,6 +3298,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, "node_modules/@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", diff --git a/package.json b/package.json index 770bad0..3f7a2f2 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/async": "^3.2.24", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", diff --git a/src/client/input.ts b/src/client/input.ts index bcc8f73..bbcd76b 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -717,11 +717,15 @@ export class Input extends Lister { return inputAnnotProto; } - static getMaskProto( - inputId: string, - label: string, - polygons: number[][][], - ): Annotation { + static getMaskProto({ + inputId, + label, + polygons, + }: { + inputId: string; + label: string; + polygons: number[][][]; + }): Annotation { const polygonsSchema = z.array(z.array(z.array(z.number()))); try { polygonsSchema.parse(polygons); diff --git a/src/datasets/upload/base.ts b/src/datasets/upload/base.ts index 36978f5..30bc8b4 100644 --- a/src/datasets/upload/base.ts +++ b/src/datasets/upload/base.ts @@ -22,28 +22,33 @@ export abstract class ClarifaiDataLoader { abstract getItem(index: number): OutputFeaturesType; } -export abstract class ClarifaiDataset { - protected dataGenerator: ClarifaiDataLoader; +export abstract class ClarifaiDataset { + protected dataGenerator: T; protected datasetId: string; + protected allInputIds: Record = {}; constructor({ dataGenerator, datasetId, }: { - dataGenerator: ClarifaiDataLoader; + dataGenerator: T; datasetId: string; }) { this.dataGenerator = dataGenerator; this.datasetId = datasetId; } - abstract get length(): number; + get length(): number { + return this.dataGenerator.length; + } - protected abstract toList(inputProtos: Iterable): unknown[]; + // TODO: Plan for implementation + // protected abstract toList(inputProtos: Iterable): unknown[]; protected abstract extractProtos(_args: { batchInputIds: string[]; }): [Input[], Annotation[]]; - abstract getProtos(_inputIds: number[]): [Input[], Annotation[]]; + // TODO: Plan for implementation + // abstract getProtos(_inputIds: number[]): [Input[], Annotation[]]; } diff --git a/src/datasets/upload/features.ts b/src/datasets/upload/features.ts index 85103bf..1583ac2 100644 --- a/src/datasets/upload/features.ts +++ b/src/datasets/upload/features.ts @@ -1,37 +1,41 @@ import { JavaScriptValue } from "google-protobuf/google/protobuf/struct_pb"; export interface TextFeatures { + imagePath?: undefined; + geoInfo?: undefined; + imageBytes?: undefined; text: string; labels: Array; id?: number; metadata?: Record; + bboxes?: undefined; } export interface VisualClassificationFeatures { - image_path: string; + imagePath: string; labels: Array; - geo_info?: [number, number]; + geoInfo?: [number, number]; id?: number; metadata?: Record; - image_bytes?: Buffer; + imageBytes?: Buffer; } export interface VisualDetectionFeatures { - image_path: string; + imagePath: string; labels: Array; bboxes: Array>; - geo_info?: [number, number]; + geoInfo?: [number, number]; id?: number; metadata?: Record; - image_bytes?: Buffer; + imageBytes?: Buffer; } export interface VisualSegmentationFeatures { - image_path: string; + imagePath: string; labels: Array; polygons: Array>>; - geo_info?: [number, number]; + geoInfo?: [number, number]; id?: number; metadata?: Record; - image_bytes?: Buffer; + imageBytes?: Buffer; } diff --git a/src/datasets/upload/image.ts b/src/datasets/upload/image.ts new file mode 100644 index 0000000..caeb68b --- /dev/null +++ b/src/datasets/upload/image.ts @@ -0,0 +1,241 @@ +import { + Input as GrpcInput, + Annotation, +} from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import { ClarifaiDataLoader, ClarifaiDataset } from "./base"; +import path from "path"; +import { uuid } from "uuidv4"; +import { Input } from "../../client/input"; +import { + VisualClassificationFeatures, + VisualDetectionFeatures, + VisualSegmentationFeatures, +} from "./features"; +import { JavaScriptValue } from "google-protobuf/google/protobuf/struct_pb"; + +export class VisualClassificationDataset extends ClarifaiDataset { + constructor(args: { dataGenerator: ClarifaiDataLoader; datasetId: string }) { + super(args); + } + + protected extractProtos({ + batchInputIds, + }: { + batchInputIds: string[]; + }): [GrpcInput[], Annotation[]] { + const inputProtos: GrpcInput[] = []; + const annotationProtos: Annotation[] = []; + + const processDataItem = (id: string) => { + const dataItem = this.dataGenerator.getItem( + Number(id), + ) as VisualClassificationFeatures; + let metadata: Record = {}; + const imagePath = dataItem.imagePath; + const labels = Array.isArray(dataItem.labels) + ? dataItem.labels.map((label) => label.toString()) + : [(dataItem.labels as string).toString()]; // clarifai concept expects labels to be an array + const inputId = `${this.datasetId}-${String(dataItem.id)}`; + const geoInfo = dataItem.geoInfo; + + if (dataItem.metadata) { + metadata = dataItem.metadata; + } else if (imagePath) { + metadata = { + filename: path.basename(imagePath), + }; + } + + this.allInputIds[id] = inputId; + + if (dataItem.imageBytes) { + inputProtos.push( + Input.getInputFromBytes({ + inputId, + imageBytes: dataItem.imageBytes, + datasetId: this.datasetId, + labels, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } else { + inputProtos.push( + Input.getInputFromFile({ + inputId, + imageFile: imagePath as string, + datasetId: this.datasetId, + labels, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } + }; + + batchInputIds.forEach((id) => processDataItem(id)); + + return [inputProtos, annotationProtos]; + } +} + +export class VisualDetectionDataset extends ClarifaiDataset { + constructor(args: { dataGenerator: ClarifaiDataLoader; datasetId: string }) { + super(args); + } + + protected extractProtos({ + batchInputIds, + }: { + batchInputIds: string[]; + }): [GrpcInput[], Annotation[]] { + const inputProtos: GrpcInput[] = []; + const annotationProtos: Annotation[] = []; + + const processDataItem = (id: string) => { + const dataItem = this.dataGenerator.getItem( + Number(id), + ) as VisualDetectionFeatures; + let metadata: Record = {}; + const image = dataItem.imagePath; + const labels = dataItem.labels.map((label) => label.toString()); + const bboxes = dataItem.bboxes; + const inputId = `${this.datasetId}-${dataItem.id ? dataItem.id.toString() : uuid().replace(/-/g, "").slice(0, 8)}`; + if (dataItem.metadata) { + metadata = dataItem.metadata; + } else if (image) { + metadata = { + filename: path.basename(image), + }; + } + const geoInfo = dataItem.geoInfo; + + this.allInputIds[id] = inputId; + + if (dataItem.imageBytes) { + inputProtos.push( + Input.getInputFromBytes({ + inputId, + imageBytes: dataItem.imageBytes, + datasetId: this.datasetId, + labels, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } else { + inputProtos.push( + Input.getInputFromFile({ + inputId, + imageFile: image, + datasetId: this.datasetId, + labels, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } + + for (let i = 0; i < bboxes.length; i++) { + annotationProtos.push( + Input.getBboxProto({ + inputId, + label: labels[i], + bbox: bboxes[i], + }), + ); + } + }; + + batchInputIds.forEach((id) => processDataItem(id)); + + return [inputProtos, annotationProtos]; + } +} + +export class VisualSegmentationDataset extends ClarifaiDataset { + constructor(args: { dataGenerator: ClarifaiDataLoader; datasetId: string }) { + super(args); + } + + protected extractProtos({ + batchInputIds, + }: { + batchInputIds: string[]; + }): [GrpcInput[], Annotation[]] { + const inputProtos: GrpcInput[] = []; + const annotationProtos: Annotation[] = []; + + const processDataItem = (id: string) => { + const dataItem = this.dataGenerator.getItem( + Number(id), + ) as VisualSegmentationFeatures; + let metadata: Record = {}; + const image = dataItem.imagePath; + const labels = dataItem.labels.map((label) => label.toString()); + const polygons = dataItem.polygons; + const inputId = `${this.datasetId}-${dataItem.id ? dataItem.id.toString() : uuid().replace(/-/g, "").slice(0, 8)}`; + if (dataItem.metadata) { + metadata = dataItem.metadata; + } else if (image) { + metadata = { + filename: path.basename(image), + }; + } + const geoInfo = dataItem.geoInfo; + this.allInputIds[id] = inputId; + if (dataItem.imageBytes) { + inputProtos.push( + Input.getInputFromBytes({ + inputId, + imageBytes: dataItem.imageBytes, + datasetId: this.datasetId, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } else { + inputProtos.push( + Input.getInputFromFile({ + inputId, + imageFile: image, + datasetId: this.datasetId, + geoInfo: { + latitude: geoInfo?.[0] as number, + longitude: geoInfo?.[1] as number, + }, + metadata, + }), + ); + } + for (let i = 0; i < polygons.length; i++) { + annotationProtos.push( + Input.getMaskProto({ + inputId, + label: labels[i], + polygons: [polygons[i]], + }), + ); + } + }; + + batchInputIds.forEach((id) => processDataItem(id)); + + return [inputProtos, annotationProtos]; + } +} From ce8e305ca60303230a7b07556dab5b2c72b70a79 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 12 Apr 2024 15:21:11 +0530 Subject: [PATCH 05/41] feat: setup bulk upload utils --- src/client/input.ts | 139 +++++++++++++++++++++++++++++++++++++++++++- src/utils/misc.ts | 4 +- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/src/client/input.ts b/src/client/input.ts index bbcd76b..ba8a4b5 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -29,12 +29,19 @@ import { parse } from "csv-parse"; import { finished } from "stream/promises"; import { uuid } from "uuidv4"; import { + CancelInputsAddJobRequest, + DeleteInputsRequest, + GetInputsAddJobRequest, + ListInputsRequest, PatchInputsRequest, PostAnnotationsRequest, PostInputsRequest, } from "clarifai-nodejs-grpc/proto/clarifai/api/service_pb"; -import { promisifyGrpcCall } from "../utils/misc"; +import { BackoffIterator, promisifyGrpcCall } from "../utils/misc"; import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; +import os from "os"; +import chunk from "lodash/chunk"; +import { Status } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_pb"; interface CSVRecord { inputid: string; @@ -49,6 +56,8 @@ interface CSVRecord { * @noInheritDoc */ export class Input extends Lister { + private numOfWorkers: number = Math.min(os.cpus().length, 10); + /** * Initializes an input object. * @@ -480,6 +489,7 @@ export class Input extends Lister { imageUrl = null, imageBytes = null, datasetId = null, + labels = null, }: { inputId: string; rawText?: string | null; @@ -487,6 +497,7 @@ export class Input extends Lister { imageUrl?: string | null; imageBytes?: Uint8Array | null; datasetId?: string | null; + labels?: string[] | null; }): GrpcInput { if ((imageBytes && imageUrl) || (!imageBytes && !imageUrl)) { throw new Error( @@ -515,6 +526,7 @@ export class Input extends Lister { datasetId, imagePb, textPb, + labels, }); } @@ -991,4 +1003,129 @@ export class Input extends Lister { } return retryUpload; } + + bulkUpload({ + inputs, + batchSize: providedBatchSize = 128, + }: { + inputs: GrpcInput[]; + batchSize: number; + }) { + const batchSize = Math.min(128, providedBatchSize); + const chunkedInputs = chunk(inputs, batchSize); + } + + private async uploadBatch({ inputs }: { inputs: GrpcInput[] }): GrpcInput[] { + const inputJobId = await this.uploadInputs({ inputs, showLog: false }); + await this.waitForInputs({ inputJobId }); + const failedInputs = await this.deleteFailedInputs({ inputs }); + return failedInputs; + } + + private async waitForInputs({ + inputJobId, + }: { + inputJobId: string; + }): Promise { + const backoffIterator = new BackoffIterator({ + count: 10, + }); + let maxRetries = 10; + const startTime = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + const getInputsAddJobRequest = new GetInputsAddJobRequest() + .setUserAppId(this.userAppId) + .setId(inputJobId); + + const getInputsAddJob = promisifyGrpcCall( + this.STUB.client.getInputsAddJob, + this.STUB.client, + ); + + const response = await this.grpcRequest( + getInputsAddJob, + getInputsAddJobRequest, + ); + + if (Date.now() - startTime > 60 * 30 || maxRetries === 0) { + const cancelInputsAddJobRequest = new CancelInputsAddJobRequest() + .setUserAppId(this.userAppId) + .setId(inputJobId); + + const cancelInputsAddJob = promisifyGrpcCall( + this.STUB.client.cancelInputsAddJob, + this.STUB.client, + ); + + // 30 minutes timeout + await this.grpcRequest(cancelInputsAddJob, cancelInputsAddJobRequest); // Cancel Job + return false; + } + + const responseObject = response.toObject(); + + if (responseObject.status?.code !== StatusCode.SUCCESS) { + maxRetries -= 1; + console.warn( + `Get input job failed, status: ${responseObject.status?.description}\n`, + ); + continue; + } + if ( + responseObject.inputsAddJob?.progress?.inProgressCount === 0 && + responseObject.inputsAddJob.progress.pendingCount === 0 + ) { + return true; + } else { + await new Promise((resolve) => + setTimeout(resolve, backoffIterator.next().value), + ); + } + } + } + + private async deleteFailedInputs({ + inputs, + }: { + inputs: GrpcInput[]; + }): Promise { + const inputIds = inputs.map((input) => input.getId()); + const successStatus = new Status().setCode( + StatusCode.INPUT_DOWNLOAD_SUCCESS, // Status code for successful download + ); + const request = new ListInputsRequest(); + request.setIdsList(inputIds); + request.setPerPage(inputIds.length); + request.setUserAppId(this.userAppId); + request.setStatus(successStatus); + + const listInputs = promisifyGrpcCall( + this.STUB.client.listInputs, + this.STUB.client, + ); + + const response = await this.grpcRequest(listInputs, request); + const responseObject = response.toObject(); + const successInputs = responseObject.inputsList || []; + + const successInputIds = successInputs.map((input) => input.id); + const failedInputs = inputs.filter( + (input) => !successInputIds.includes(input.getId()), + ); + + const deleteInputs = promisifyGrpcCall( + this.STUB.client.deleteInputs, + this.STUB.client, + ); + + const deleteInputsRequest = new DeleteInputsRequest() + .setUserAppId(this.userAppId) + .setIdsList(failedInputs.map((input) => input.getId())); + + // Delete failed inputs + await this.grpcRequest(deleteInputs, deleteInputsRequest); + + return failedInputs; + } } diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 32c9431..7373bd8 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -71,8 +71,8 @@ export function mergeObjects(obj1: AuthConfig, obj2: AuthConfig): AuthConfig { export class BackoffIterator { private count: number; - constructor() { - this.count = 0; + constructor({ count = 0 }: { count?: number } = { count: 0 }) { + this.count = count; } [Symbol.iterator]() { From 4ddc80bc10490f6bf90ad12282a322561c7cfad1 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 12 Apr 2024 16:32:50 +0530 Subject: [PATCH 06/41] feat: setup bulkupload --- package-lock.json | 12 +++++++- package.json | 2 ++ src/client/input.ts | 59 +++++++++++++++++++++++++++++++++++++++- src/constants/dataset.ts | 27 ++++++++++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/constants/dataset.ts diff --git a/package-lock.json b/package-lock.json index c4d62a9..3c54529 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.0.9", + "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", @@ -28,6 +29,7 @@ "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", "@types/async": "^3.2.24", + "@types/cli-progress": "^3.11.5", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", @@ -3268,6 +3270,15 @@ "integrity": "sha512-8iHVLHsCCOBKjCF2KwFe0p9Z3rfM9mL+sSP8btyR5vTjJRAqpBYD28/ZLgXPf0pjG1VxOvtCV/BgXkQbpSe8Hw==", "dev": true }, + "node_modules/@types/cli-progress": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.5.tgz", + "integrity": "sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3983,7 +3994,6 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "dev": true, "dependencies": { "string-width": "^4.2.3" }, diff --git a/package.json b/package.json index 3f7a2f2..40d1c00 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", "@types/async": "^3.2.24", + "@types/cli-progress": "^3.11.5", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", @@ -65,6 +66,7 @@ "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.0.9", + "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", diff --git a/src/client/input.ts b/src/client/input.ts index ba8a4b5..1a70399 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -42,6 +42,9 @@ import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/statu import os from "os"; import chunk from "lodash/chunk"; import { Status } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_pb"; +import cliProgress from "cli-progress"; +import async from "async"; +import { MAX_RETRIES } from "../constants/dataset"; interface CSVRecord { inputid: string; @@ -1013,9 +1016,47 @@ export class Input extends Lister { }) { const batchSize = Math.min(128, providedBatchSize); const chunkedInputs = chunk(inputs, batchSize); + + const progressBar = new cliProgress.SingleBar( + {}, + cliProgress.Presets.shades_classic, + ); + + progressBar.start(chunkedInputs.length, 0); + + async.mapLimit( + chunkedInputs, + this.numOfWorkers, + (batchInputs, callback) => { + this.uploadBatch({ inputs: batchInputs }) + .then((failedInputs) => { + this.retryUploads({ + failedInputs, + }).finally(() => { + progressBar.increment(); + callback(null, failedInputs); + }); + }) + .catch((err) => { + callback(err); + }); + }, + (err) => { + if (err) { + console.error("Error processing batches", err); + return; + } + progressBar.stop(); + console.log("All inputs processed"); + }, + ); } - private async uploadBatch({ inputs }: { inputs: GrpcInput[] }): GrpcInput[] { + private async uploadBatch({ + inputs, + }: { + inputs: GrpcInput[]; + }): Promise { const inputJobId = await this.uploadInputs({ inputs, showLog: false }); await this.waitForInputs({ inputJobId }); const failedInputs = await this.deleteFailedInputs({ inputs }); @@ -1128,4 +1169,20 @@ export class Input extends Lister { return failedInputs; } + + private async retryUploads({ + failedInputs, + }: { + failedInputs: GrpcInput[]; + }): Promise { + for (let retry = 0; retry < MAX_RETRIES; retry++) { + if (failedInputs.length > 0) { + console.log( + `Retrying upload for ${failedInputs.length} Failed inputs..\n`, + ); + failedInputs = await this.uploadBatch({ inputs: failedInputs }); + } + } + console.log(`Failed to upload ${failedInputs.length} inputs..\n`); + } } diff --git a/src/constants/dataset.ts b/src/constants/dataset.ts new file mode 100644 index 0000000..ebd57fb --- /dev/null +++ b/src/constants/dataset.ts @@ -0,0 +1,27 @@ +export const DATASET_UPLOAD_TASKS = [ + "visual_classification", + "text_classification", + "visual_detection", + "visual_segmentation", + "visual_captioning", +]; + +export const TASK_TO_ANNOTATION_TYPE = { + visual_classification: { + concepts: "labels", + }, + text_classification: { + concepts: "labels", + }, + visual_captioning: { + concepts: "labels", + }, + visual_detection: { + bboxes: "bboxes", + }, + visual_segmentation: { + polygons: "polygons", + }, +}; + +export const MAX_RETRIES = 2; From 1daefde22be9ab627c16368664d734a812d8e255 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 12 Apr 2024 16:41:24 +0530 Subject: [PATCH 07/41] feat: upload from folder method --- src/client/dataset.ts | 36 ++++++++++++++++++++++++++++++++++++ src/client/input.ts | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/client/dataset.ts b/src/client/dataset.ts index d1d7646..2a874f9 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -2,6 +2,7 @@ import { Annotation, DatasetVersion, Dataset as GrpcDataset, + Input as GrpcInput, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; import { UserError } from "../errors"; import { ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; @@ -169,4 +170,39 @@ export class Dataset extends Lister { return compact(retryAnnotUpload); } + + uploadFromFolder({ + folderPath, + inputType, + labels = false, + batchSize = this.batchSize, + }: { + folderPath: string; + inputType: "image" | "text"; + labels: boolean; + batchSize?: number; + }): void { + if (["image", "text"].indexOf(inputType) === -1) { + throw new UserError("Invalid input type"); + } + let inputProtos: GrpcInput[] = []; + if (inputType === "image") { + inputProtos = Input.getImageInputsFromFolder({ + folderPath: folderPath, + datasetId: this.info.getId(), + labels: labels, + }); + } + if (inputType === "text") { + inputProtos = Input.getTextInputsFromFolder({ + folderPath: folderPath, + datasetId: this.info.getId(), + labels: labels, + }); + } + this.input.bulkUpload({ + inputs: inputProtos, + batchSize: batchSize, + }); + } } diff --git a/src/client/input.ts b/src/client/input.ts index 1a70399..9b60e80 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -1012,7 +1012,7 @@ export class Input extends Lister { batchSize: providedBatchSize = 128, }: { inputs: GrpcInput[]; - batchSize: number; + batchSize?: number; }) { const batchSize = Math.min(128, providedBatchSize); const chunkedInputs = chunk(inputs, batchSize); From 911ea524dd532bb1a3de725c3c98aa7752a14c73 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 12 Apr 2024 19:10:57 +0530 Subject: [PATCH 08/41] feat: upload from csv --- src/client/dataset.ts | 57 ++++++++++++++++++++++++++++++++++++++++--- src/client/input.ts | 55 +++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/client/dataset.ts b/src/client/dataset.ts index 2a874f9..cb1f3e4 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -66,14 +66,20 @@ export class Dataset extends Lister { this.input = new Input({ authConfig }); } - async createVersion( - description: string, - metadata: Record, - ): Promise { + async createVersion({ + id, + description, + metadata = {}, + }: { + id: string; + description: string; + metadata?: Record; + }): Promise { const request = new PostDatasetVersionsRequest(); request.setUserAppId(this.userAppId); request.setDatasetId(this.info.getId()); const datasetVersion = new DatasetVersion(); + datasetVersion.setId(id); datasetVersion.setDescription(description); datasetVersion.setMetadata(Struct.fromJavaScript(metadata)); request.setDatasetVersionsList([datasetVersion]); @@ -205,4 +211,47 @@ export class Dataset extends Lister { batchSize: batchSize, }); } + + async uploadFromCSV({ + csvPath, + inputType = "text", + csvType, + labels = true, + batchSize = 128, + }: { + csvPath: string; + inputType?: "image" | "text" | "video" | "audio"; + csvType: "raw" | "url" | "file"; + labels?: boolean; + batchSize?: number; + }): Promise { + if (!["image", "text", "video", "audio"].includes(inputType)) { + throw new UserError( + "Invalid input type, it should be image, text, audio, or video", + ); + } + if (!["raw", "url", "file"].includes(csvType)) { + throw new UserError( + "Invalid csv type, it should be raw, url, or file_path", + ); + } + if (!csvPath.endsWith(".csv")) { + throw new UserError("csvPath should be a csv file"); + } + if (csvType === "raw" && inputType !== "text") { + throw new UserError("Only text input type is supported for raw csv type"); + } + batchSize = Math.min(128, batchSize); + const inputProtos = await Input.getInputsFromCsv({ + csvPath: csvPath, + inputType: inputType, + csvType: csvType, + datasetId: this.info.getId(), + labels: labels, + }); + await this.input.bulkUpload({ + inputs: inputProtos, + batchSize: batchSize, + }); + } } diff --git a/src/client/input.ts b/src/client/input.ts index 9b60e80..cefe678 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -1013,7 +1013,7 @@ export class Input extends Lister { }: { inputs: GrpcInput[]; batchSize?: number; - }) { + }): Promise { const batchSize = Math.min(128, providedBatchSize); const chunkedInputs = chunk(inputs, batchSize); @@ -1024,32 +1024,35 @@ export class Input extends Lister { progressBar.start(chunkedInputs.length, 0); - async.mapLimit( - chunkedInputs, - this.numOfWorkers, - (batchInputs, callback) => { - this.uploadBatch({ inputs: batchInputs }) - .then((failedInputs) => { - this.retryUploads({ - failedInputs, - }).finally(() => { - progressBar.increment(); - callback(null, failedInputs); + return new Promise((resolve, reject) => { + async.mapLimit( + chunkedInputs, + this.numOfWorkers, + (batchInputs, callback) => { + this.uploadBatch({ inputs: batchInputs }) + .then((failedInputs) => { + this.retryUploads({ + failedInputs, + }).finally(() => { + progressBar.increment(); + callback(null, failedInputs); + }); + }) + .catch((err) => { + callback(err); }); - }) - .catch((err) => { - callback(err); - }); - }, - (err) => { - if (err) { - console.error("Error processing batches", err); - return; - } - progressBar.stop(); - console.log("All inputs processed"); - }, - ); + }, + (err) => { + if (err) { + console.error("Error processing batches", err); + reject(err); + } + progressBar.stop(); + console.log("All inputs processed"); + resolve(); + }, + ); + }); } private async uploadBatch({ From 1f3eb9a2407fbbaaca649b15828a74316a723a64 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 15 Apr 2024 15:48:17 +0530 Subject: [PATCH 09/41] fix: search test cases --- src/client/dataset.ts | 6 +- src/client/input.ts | 9 +- src/client/search.ts | 20 +-- tests/client/search.integration.test.ts | 214 ++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 tests/client/search.integration.test.ts diff --git a/src/client/dataset.ts b/src/client/dataset.ts index cb1f3e4..544e2eb 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -177,7 +177,7 @@ export class Dataset extends Lister { return compact(retryAnnotUpload); } - uploadFromFolder({ + async uploadFromFolder({ folderPath, inputType, labels = false, @@ -187,7 +187,7 @@ export class Dataset extends Lister { inputType: "image" | "text"; labels: boolean; batchSize?: number; - }): void { + }): Promise { if (["image", "text"].indexOf(inputType) === -1) { throw new UserError("Invalid input type"); } @@ -206,7 +206,7 @@ export class Dataset extends Lister { labels: labels, }); } - this.input.bulkUpload({ + await this.input.bulkUpload({ inputs: inputProtos, batchSize: batchSize, }); diff --git a/src/client/input.ts b/src/client/input.ts index cefe678..29299e5 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -1076,6 +1076,7 @@ export class Input extends Lister { }); let maxRetries = 10; const startTime = Date.now(); + const thirtyMinutes = 60 * 30 * 1000; // eslint-disable-next-line no-constant-condition while (true) { const getInputsAddJobRequest = new GetInputsAddJobRequest() @@ -1092,7 +1093,7 @@ export class Input extends Lister { getInputsAddJobRequest, ); - if (Date.now() - startTime > 60 * 30 || maxRetries === 0) { + if (Date.now() - startTime > thirtyMinutes || maxRetries === 0) { const cancelInputsAddJobRequest = new CancelInputsAddJobRequest() .setUserAppId(this.userAppId) .setId(inputJobId); @@ -1122,9 +1123,9 @@ export class Input extends Lister { ) { return true; } else { - await new Promise((resolve) => - setTimeout(resolve, backoffIterator.next().value), - ); + await new Promise((resolve) => { + setTimeout(resolve, backoffIterator.next().value * 1000); + }); } } } diff --git a/src/client/search.ts b/src/client/search.ts index c7efa76..e366b51 100644 --- a/src/client/search.ts +++ b/src/client/search.ts @@ -138,7 +138,9 @@ export class Search extends Lister { this.dataProto.setGeo(geoPointProto); } } else { - throw new UserError(`kwargs contain key that is not supported: ${key}`); + throw new UserError( + `arguments contain key that is not supported: ${key}`, + ); } } const annotation = new Annotation(); @@ -208,11 +210,7 @@ export class Search extends Lister { options: Partial, ) => Promise, requestData: T, - ): AsyncGenerator< - MultiSearchResponse.AsObject & Record<"hits", unknown>, - void, - void - > { + ): AsyncGenerator { const maxPages = Math.ceil(this.topK / this.defaultPageSize); let totalHits = 0; let page = 1; @@ -247,7 +245,7 @@ export class Search extends Lister { } } - if (!("hits" in responseObject)) { + if (!("hitsList" in responseObject)) { break; } page += 1; @@ -262,11 +260,7 @@ export class Search extends Lister { }: { ranks?: FilterType; filters?: FilterType; - }): AsyncGenerator< - MultiSearchResponse.AsObject & Record<"hits", unknown>, - void, - void - > { + }): AsyncGenerator { try { getSchema().parse(ranks); getSchema().parse(filters); @@ -286,7 +280,7 @@ export class Search extends Lister { if ( filters.length && - Object.prototype.hasOwnProperty.call(filters[0], "input") + Object.keys(filters[0]).some((k) => k.includes("input")) ) { const filtersInputProto: GrpcInput[] = []; for (const filterDict of filters) { diff --git a/tests/client/search.integration.test.ts b/tests/client/search.integration.test.ts new file mode 100644 index 0000000..33ce68b --- /dev/null +++ b/tests/client/search.integration.test.ts @@ -0,0 +1,214 @@ +import path from "path"; +import { getSchema } from "../../src/schema/search"; +import { z } from "zod"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { App, Dataset, Input, Search, User } from "../../src/index"; +import { Hit } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; + +const NOW = "search_integration"; //Date.now().toString(); +const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; +const CREATE_APP_ID = `ci_test_app_${NOW}`; +const CREATE_DATASET_ID = `ci_test_dataset_${NOW}`; +const DOG_IMG_URL = "https://samples.clarifai.com/dog.tiff"; +const DATASET_IMAGES_DIR = path.resolve(__dirname, "../assets/voc/images"); + +function getFiltersForTest(): [ + z.infer>, + number, +][] { + return [ + [ + [ + { + geoPoint: { + longitude: -29.0, + latitude: 40.0, + geoLimit: 10, + }, + }, + ], + 1, + ], + [ + [ + { + concepts: [ + { + name: "dog", + value: 1, + }, + ], + }, + ], + 1, + ], + [ + [ + { + concepts: [ + { + name: "deer", + value: 1, + }, + { + name: "dog", + value: 1, + }, + ], + }, + ], + 1, + ], + [ + [ + { + concepts: [ + { + name: "dog", + value: 1, + }, + ], + }, + { + concepts: [ + { + name: "deer", + value: 1, + }, + ], + }, + ], + 0, + ], + [ + [ + { + metadata: { + Breed: "Saint Bernard", + }, + }, + ], + 1, + ], + [ + [ + { + inputTypes: ["image"], + }, + { + inputStatusCode: 30000, + }, + ], + 1, + ], + [ + [ + { + inputTypes: ["text", "audio", "video"], + }, + ], + 0, + ], + [ + [ + { + inputTypes: ["text", "audio", "video"], + inputStatusCode: 30000, + }, + ], + 1, + ], + [ + [ + { + inputDatasetIds: ["random_dataset"], + }, + ], + 0, + ], + ]; +} + +describe("Search", () => { + const client = new User({ + userId: CREATE_APP_USER_ID, + appId: CREATE_APP_ID, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }); + const search = new Search({ + authConfig: { + userId: CREATE_APP_USER_ID, + appId: CREATE_APP_ID, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }, + metric: "euclidean", + }); + let app: App; + + beforeAll(async () => { + const appObj = await client.createApp({ + appId: CREATE_APP_ID, + baseWorkflow: "General", + }); + app = new App({ + authConfig: { + userId: CREATE_APP_USER_ID, + appId: appObj.id, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }, + }); + const datasetObj = await app.createDataset({ + datasetId: CREATE_DATASET_ID, + }); + const metadata = { + Breed: "Saint Bernard", + }; + const inputProto = Input.getInputFromUrl({ + imageUrl: DOG_IMG_URL, + metadata, + datasetId: datasetObj.id, + inputId: "dog-tiff", + labels: ["dog"], + geoInfo: { longitude: -30.0, latitude: 40.0 }, + }); + const input = new Input({ + authConfig: { + userId: CREATE_APP_USER_ID, + appId: appObj.id, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }, + }); + await input.uploadInputs({ inputs: [inputProto] }); + const dataset = new Dataset({ + authConfig: { + userId: CREATE_APP_USER_ID, + appId: appObj.id, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }, + datasetId: datasetObj.id, + }); + await dataset.uploadFromFolder({ + folderPath: DATASET_IMAGES_DIR, + inputType: "image", + labels: false, + }); + }, 50000); + + it("should get expected hits for filters", async () => { + const filtersWithHits = getFiltersForTest(); + for (const [filters, expectedHits] of filtersWithHits) { + const searchResponseGenerator = search.query({ + filters, + }); + let hitsList: Hit.AsObject[] = []; + for await (const response of searchResponseGenerator) { + hitsList = hitsList.concat(response.hitsList); + } + expect(hitsList.length).toBe(expectedHits); + } + }); + + afterAll(async () => { + await client.deleteApp({ appId: CREATE_APP_ID }); + }); +}); From bb12468ab33b3a2674348ef8ddf5017cc5e1bff6 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 18 Apr 2024 18:46:32 +0530 Subject: [PATCH 10/41] fix: lint issues --- src/client/dataset.ts | 2 +- src/client/input.ts | 6 ++++-- tests/client/search.integration.test.ts | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/client/dataset.ts b/src/client/dataset.ts index 544e2eb..10db493 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -44,7 +44,7 @@ export class Dataset extends Lister { private annotNumOfWorkers: number = 4; private maxRetries: number = 10; private batchSize: number = 128; - private task; + private task: unknown; private input: Input; constructor({ authConfig, datasetId, url, datasetVersionId }: DatasetConfig) { diff --git a/src/client/input.ts b/src/client/input.ts index 29299e5..066a678 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -1124,7 +1124,7 @@ export class Input extends Lister { return true; } else { await new Promise((resolve) => { - setTimeout(resolve, backoffIterator.next().value * 1000); + setTimeout(resolve, backoffIterator.next().value * 300); }); } } @@ -1187,6 +1187,8 @@ export class Input extends Lister { failedInputs = await this.uploadBatch({ inputs: failedInputs }); } } - console.log(`Failed to upload ${failedInputs.length} inputs..\n`); + if (failedInputs.length > 0) { + console.log(`Failed to upload ${failedInputs.length} inputs..\n`); + } } } diff --git a/tests/client/search.integration.test.ts b/tests/client/search.integration.test.ts index 33ce68b..d7e6de0 100644 --- a/tests/client/search.integration.test.ts +++ b/tests/client/search.integration.test.ts @@ -208,7 +208,23 @@ describe("Search", () => { } }); + // it("should get expected hits for ranks", async () => { + // const searchResponseGenerator = search.query({ + // ranks: [ + // { + // imageUrl: DOG_IMG_URL, + // }, + // ], + // }); + // let hitsList: Hit.AsObject[] = []; + // for await (const response of searchResponseGenerator) { + // hitsList = hitsList.concat(response.hitsList); + // } + // expect(hitsList.length).toBe(1); + // expect(hitsList[0].input?.id).toBe("dog-tiff"); + // }); + afterAll(async () => { - await client.deleteApp({ appId: CREATE_APP_ID }); + // await client.deleteApp({ appId: CREATE_APP_ID }); }); }); From 07c1474de01c67e081abf127cbee535394dda078 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 19 Apr 2024 10:33:22 +0530 Subject: [PATCH 11/41] feat: added algorithm to search --- src/client/search.ts | 22 ++++++++++++++++++++-- src/constants/search.ts | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/client/search.ts b/src/client/search.ts index e366b51..10e3071 100644 --- a/src/client/search.ts +++ b/src/client/search.ts @@ -1,4 +1,8 @@ -import { DEFAULT_SEARCH_METRIC, DEFAULT_TOP_K } from "../constants/search"; +import { + DEFAULT_SEARCH_ALGORITHM, + DEFAULT_SEARCH_METRIC, + DEFAULT_TOP_K, +} from "../constants/search"; import { Lister } from "./lister"; import { AuthConfig } from "../utils/types"; import { @@ -38,6 +42,8 @@ import { import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; type FilterType = z.infer>; +type SupportedAlgorithm = "nearest_neighbor" | "brute_force"; +type SupportedMetric = "cosine" | "euclidean"; /** * @noInheritDoc @@ -47,15 +53,18 @@ export class Search extends Lister { private metricDistance: "COSINE_DISTANCE" | "EUCLIDEAN_DISTANCE"; private dataProto: Data; private inputProto: GrpcInput; + private algorithm: SupportedAlgorithm; constructor({ topK = DEFAULT_TOP_K, metric = DEFAULT_SEARCH_METRIC, authConfig, + algorithm = DEFAULT_SEARCH_ALGORITHM, }: { topK?: number; - metric?: string; + metric?: SupportedMetric; authConfig?: AuthConfig; + algorithm?: SupportedAlgorithm; }) { super({ pageSize: 1000, authConfig }); @@ -63,7 +72,14 @@ export class Search extends Lister { throw new UserError("Metric should be either cosine or euclidean"); } + if (algorithm !== "nearest_neighbor" && algorithm !== "brute_force") { + throw new UserError( + "Algorithm should be either nearest_neighbor or brute_force", + ); + } + this.topK = topK; + this.algorithm = algorithm; this.metricDistance = ( { cosine: "COSINE_DISTANCE", @@ -298,6 +314,7 @@ export class Search extends Lister { const search = new GrpcSearch(); search.setQuery(query); + search.setAlgorithm(this.algorithm); search.setMetric(GrpcSearch["Metric"][this.metricDistance]); const postInputsSearches = promisifyGrpcCall( @@ -327,6 +344,7 @@ export class Search extends Lister { const search = new GrpcSearch(); search.setQuery(query); + search.setAlgorithm(this.algorithm); search.setMetric(GrpcSearch["Metric"][this.metricDistance]); const postAnnotationsSearches = promisifyGrpcCall( diff --git a/src/constants/search.ts b/src/constants/search.ts index f96471e..0f5d68d 100644 --- a/src/constants/search.ts +++ b/src/constants/search.ts @@ -1,2 +1,3 @@ export const DEFAULT_TOP_K = 10; export const DEFAULT_SEARCH_METRIC = "cosine"; +export const DEFAULT_SEARCH_ALGORITHM = "nearest_neighbor"; From dfa96557b945f3decbdca5ca836b50ba0a2b4359 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 22 Apr 2024 19:11:26 +0530 Subject: [PATCH 12/41] fix: test cases --- tests/client/search.integration.test.ts | 65 ++++++++++++++++--------- vitest.config.ts => vitest.config.mjs | 1 + 2 files changed, 44 insertions(+), 22 deletions(-) rename vitest.config.ts => vitest.config.mjs (78%) diff --git a/tests/client/search.integration.test.ts b/tests/client/search.integration.test.ts index d7e6de0..a4de071 100644 --- a/tests/client/search.integration.test.ts +++ b/tests/client/search.integration.test.ts @@ -3,7 +3,6 @@ import { getSchema } from "../../src/schema/search"; import { z } from "zod"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { App, Dataset, Input, Search, User } from "../../src/index"; -import { Hit } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; const NOW = "search_integration"; //Date.now().toString(); const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; @@ -23,7 +22,7 @@ function getFiltersForTest(): [ geoPoint: { longitude: -29.0, latitude: 40.0, - geoLimit: 10, + geoLimit: 100, }, }, ], @@ -141,6 +140,7 @@ describe("Search", () => { appId: CREATE_APP_ID, pat: import.meta.env.VITE_CLARIFAI_PAT, }, + topK: 1, metric: "euclidean", }); let app: App; @@ -200,31 +200,52 @@ describe("Search", () => { const searchResponseGenerator = search.query({ filters, }); - let hitsList: Hit.AsObject[] = []; - for await (const response of searchResponseGenerator) { - hitsList = hitsList.concat(response.hitsList); + const result = (await searchResponseGenerator.next())?.value ?? null; + expect(result).not.toBeNull(); + if (result) { + expect(result.hitsList.length).toBe(expectedHits); } - expect(hitsList.length).toBe(expectedHits); + } + }, 10000); + + it("should get expected hits for ranks", async () => { + const searchResponseGenerator = search.query({ + ranks: [ + { + imageUrl: DOG_IMG_URL, + }, + ], + }); + const result = (await searchResponseGenerator.next())?.value ?? null; + expect(result).not.toBeNull(); + if (result) { + expect(result.hitsList.length).toBe(1); + expect(result.hitsList[0].input?.id).toBe("dog-tiff"); } }); - // it("should get expected hits for ranks", async () => { - // const searchResponseGenerator = search.query({ - // ranks: [ - // { - // imageUrl: DOG_IMG_URL, - // }, - // ], - // }); - // let hitsList: Hit.AsObject[] = []; - // for await (const response of searchResponseGenerator) { - // hitsList = hitsList.concat(response.hitsList); - // } - // expect(hitsList.length).toBe(1); - // expect(hitsList[0].input?.id).toBe("dog-tiff"); - // }); + it("should get expected hits for filters and ranks", async () => { + const searchResponseGenerator = search.query({ + ranks: [ + { + imageUrl: DOG_IMG_URL, + }, + ], + filters: [ + { + inputTypes: ["image"], + }, + ], + }); + const result = (await searchResponseGenerator.next())?.value ?? null; + expect(result).not.toBeNull(); + if (result) { + expect(result.hitsList.length).toBe(1); + expect(result.hitsList[0].input?.id).toBe("dog-tiff"); + } + }); afterAll(async () => { - // await client.deleteApp({ appId: CREATE_APP_ID }); + await client.deleteApp({ appId: CREATE_APP_ID }); }); }); diff --git a/vitest.config.ts b/vitest.config.mjs similarity index 78% rename from vitest.config.ts rename to vitest.config.mjs index 95d9434..2e5e974 100644 --- a/vitest.config.ts +++ b/vitest.config.mjs @@ -1,5 +1,6 @@ import { defineConfig } from "vitest/config"; +/** @type {import('vitest/config').defineConfig} */ export default defineConfig({ test: { coverage: { From cc27f480b0a7e1395c0722bafa207ded0203d00b Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 23 Apr 2024 16:16:51 +0530 Subject: [PATCH 13/41] feat: setup tests for search --- src/client/search.ts | 53 ++++++-- src/schema/search.ts | 63 +++++---- tests/client/app.integration.test.ts | 2 +- tests/client/search.integration.test.ts | 120 +++++++++++++++++- .../workflow/workflowCrud.integration.test.ts | 2 +- 5 files changed, 195 insertions(+), 45 deletions(-) diff --git a/src/client/search.ts b/src/client/search.ts index 10e3071..d998de0 100644 --- a/src/client/search.ts +++ b/src/client/search.ts @@ -219,23 +219,30 @@ export class Search extends Lister { private async *listAllPagesGenerator< T extends PostInputsSearchesRequest | PostAnnotationsSearchesRequest, - >( + >({ + endpoint, + requestData, + page = 1, + perPage, + }: { endpoint: ( request: T, metadata: grpc.Metadata, options: Partial, - ) => Promise, - requestData: T, - ): AsyncGenerator { + ) => Promise; + requestData: T; + page?: number; + perPage?: number; + }): AsyncGenerator { const maxPages = Math.ceil(this.topK / this.defaultPageSize); let totalHits = 0; - let page = 1; - while (page <= maxPages) { - let perPage; - if (page === maxPages) { - perPage = this.topK - totalHits; - } else { - perPage = this.defaultPageSize; + while (page) { + if (!perPage) { + if (page === maxPages) { + perPage = this.topK - totalHits; + } else { + perPage = this.defaultPageSize; + } } const pagination = new Pagination(); @@ -261,7 +268,11 @@ export class Search extends Lister { } } - if (!("hitsList" in responseObject)) { + if ( + !("hitsList" in responseObject) || + responseObject.hitsList.length === 0 + ) { + yield responseObject; break; } page += 1; @@ -273,9 +284,13 @@ export class Search extends Lister { query({ ranks = [{}], filters = [{}], + page, + perPage, }: { ranks?: FilterType; filters?: FilterType; + page?: number; + perPage?: number; }): AsyncGenerator { try { getSchema().parse(ranks); @@ -325,7 +340,12 @@ export class Search extends Lister { request.setUserAppId(this.userAppId); request.setSearchesList([search]); - return this.listAllPagesGenerator(postInputsSearches, request); + return this.listAllPagesGenerator({ + endpoint: postInputsSearches, + requestData: request, + page, + perPage, + }); } const filtersAnnotProto: Annotation[] = []; @@ -355,6 +375,11 @@ export class Search extends Lister { request.setUserAppId(this.userAppId); request.setSearchesList([search]); - return this.listAllPagesGenerator(postAnnotationsSearches, request); + return this.listAllPagesGenerator({ + endpoint: postAnnotationsSearches, + requestData: request, + page, + perPage, + }); } } diff --git a/src/schema/search.ts b/src/schema/search.ts index c17e530..2ac0684 100644 --- a/src/schema/search.ts +++ b/src/schema/search.ts @@ -46,37 +46,44 @@ export function getSchema(): z.ZodSchema< }> > { // Schema for a single concept - const conceptSchema = z.object({ - value: z.number().min(0).max(1).optional(), - id: z.string().min(1).optional(), - language: z.string().min(1).optional(), - name: z - .string() - .min(1) - .regex(/^[0-9A-Za-z]+([-_][0-9A-Za-z]+)*$/) // Non-empty string with dashes/underscores - .optional(), - }); + const conceptSchema = z + .object({ + value: z.number().min(0).max(1).optional(), + id: z.string().min(1).optional(), + language: z.string().min(1).optional(), + name: z + .string() + .min(1) + .regex(/^[0-9A-Za-z]+([-_][0-9A-Za-z]+)*$/) // Non-empty string with dashes/underscores + .optional(), + }) + .strict(); // Schema for a rank or filter item - const rankFilterItemSchema = z.object({ - imageUrl: z.string().url().optional(), - textRaw: z.string().min(1).optional(), - metadata: z.record(z.unknown()).optional(), - imageBytes: z.unknown().optional(), - geoPoint: z - .object({ - longitude: z.number(), - latitude: z.number(), - geoLimit: z.number().int(), - }) - .optional(), - concepts: z.array(conceptSchema).min(1).optional(), + const rankFilterItemSchema = z + .object({ + imageUrl: z.string().url().optional(), + textRaw: z.string().min(1).optional(), + metadata: z.record(z.unknown()).optional(), + imageBytes: z.unknown().optional(), + geoPoint: z + .object({ + longitude: z.number(), + latitude: z.number(), + geoLimit: z.number().int(), + }) + .strict() + .optional(), + concepts: z.array(conceptSchema).min(1).optional(), - // input filters - inputTypes: z.array(z.enum(["image", "video", "text", "audio"])).optional(), - inputDatasetIds: z.array(z.string()).optional(), - inputStatusCode: z.number().optional(), - }); + // input filters + inputTypes: z + .array(z.enum(["image", "video", "text", "audio"])) + .optional(), + inputDatasetIds: z.array(z.string()).optional(), + inputStatusCode: z.number().optional(), + }) + .strict(); // Schema for rank and filter args return z.array(rankFilterItemSchema); diff --git a/tests/client/app.integration.test.ts b/tests/client/app.integration.test.ts index 09362c5..cf7525c 100644 --- a/tests/client/app.integration.test.ts +++ b/tests/client/app.integration.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { App, User } from "../../src/index"; -const NOW = Date.now().toString(); +const NOW = Date.now().toString() + "-app"; const MAIN_APP_ID = "main"; const MAIN_APP_USER_ID = "clarifai"; const GENERAL_MODEL_ID = "general-image-recognition"; diff --git a/tests/client/search.integration.test.ts b/tests/client/search.integration.test.ts index a4de071..5865a37 100644 --- a/tests/client/search.integration.test.ts +++ b/tests/client/search.integration.test.ts @@ -3,8 +3,9 @@ import { getSchema } from "../../src/schema/search"; import { z } from "zod"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { App, Dataset, Input, Search, User } from "../../src/index"; +import { Hit } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; -const NOW = "search_integration"; //Date.now().toString(); +const NOW = Date.now().toString() + "-search"; const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; const CREATE_APP_ID = `ci_test_app_${NOW}`; const CREATE_DATASET_ID = `ci_test_dataset_${NOW}`; @@ -143,6 +144,15 @@ describe("Search", () => { topK: 1, metric: "euclidean", }); + // Initialize search without topK value for pagination with custom pages & page sizes + const searchWithPagination = new Search({ + authConfig: { + userId: CREATE_APP_USER_ID, + appId: CREATE_APP_ID, + pat: import.meta.env.VITE_CLARIFAI_PAT, + }, + metric: "euclidean", + }); let app: App; beforeAll(async () => { @@ -245,6 +255,114 @@ describe("Search", () => { } }); + it("should get expected hits with corresponding pagination info", async () => { + const searchResponseGenerator = searchWithPagination.query({ + filters: [ + { + inputTypes: ["image"], + }, + ], + page: 1, + perPage: 3, + }); + const result = (await searchResponseGenerator.next())?.value ?? null; + expect(result).not.toBeNull(); + if (result) { + expect(result.hitsList.length).toBe(3); + } + }); + + it("should paginate through search results", async () => { + const searchResponseGenerator = searchWithPagination.query({ + filters: [{ inputTypes: ["image"] }], + }); + const hitsList: Hit.AsObject[] = []; + for await (const searchResponse of searchResponseGenerator) { + hitsList.push(...searchResponse.hitsList); + } + expect(hitsList.length).toBe(11); + }); + + it("should throw appropriate error for invalid arguments", async () => { + const invalidGeoPointFilters = () => { + return search.query({ + filters: [ + { + geoPoint: { + longitude: -29.0, + latitude: 40.0, + geoLimit: 10, + // @ts-expect-error - Invalid key + extra: 1, + }, + }, + ], + }); + }; + expect(invalidGeoPointFilters).toThrowError(); + const invalidConceptKeys = () => { + return search.query({ + filters: [ + { + concepts: [ + { + value: 1, + // @ts-expect-error - Missing required key + conceptId: "deer", + }, + { + name: "dog", + value: 1, + }, + ], + }, + ], + }); + }; + expect(invalidConceptKeys).toThrowError(); + const invalidConceptValues = () => { + return search.query({ + filters: [ + { + concepts: [ + { + name: "deer", + value: 2, + }, + { + name: "dog", + value: 1, + }, + ], + }, + ], + }); + }; + expect(invalidConceptValues).toThrowError(); + const incorrectInputTypes = () => { + return search.query({ + filters: [ + { + // @ts-expect-error - Invalid input type + inputTypes: ["imaage"], + }, + ], + }); + }; + expect(incorrectInputTypes).toThrowError(); + const invalidSearchFilterKey = () => { + return search.query({ + filters: [ + { + // @ts-expect-error - Invalid key + inputId: "test", + }, + ], + }); + }; + expect(invalidSearchFilterKey).toThrowError(); + }); + afterAll(async () => { await client.deleteApp({ appId: CREATE_APP_ID }); }); diff --git a/tests/client/workflow/workflowCrud.integration.test.ts b/tests/client/workflow/workflowCrud.integration.test.ts index a67dea3..72541f6 100644 --- a/tests/client/workflow/workflowCrud.integration.test.ts +++ b/tests/client/workflow/workflowCrud.integration.test.ts @@ -4,7 +4,7 @@ import { Workflow as GrpcWorkflow } from "clarifai-nodejs-grpc/proto/clarifai/ap import path from "path"; import * as fs from "fs"; -const NOW = Date.now().toString(); +const NOW = Date.now().toString() + "-workflow"; const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; const CLARIFAI_PAT = import.meta.env.VITE_CLARIFAI_PAT; const CREATE_APP_ID = `test_workflow_create_delete_app_${NOW}`; From 4a3376ea7dab065579e5db1ab276f36347875771 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 23 Apr 2024 16:20:59 +0530 Subject: [PATCH 14/41] chore: fix lint issues --- src/client/dataset.ts | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/client/dataset.ts b/src/client/dataset.ts index 10db493..9b99098 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -1,5 +1,4 @@ import { - Annotation, DatasetVersion, Dataset as GrpcDataset, Input as GrpcInput, @@ -8,7 +7,6 @@ import { UserError } from "../errors"; import { ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; import { AuthConfig } from "../utils/types"; import { Lister } from "./lister"; -import os from "os"; import { Input } from "./input"; import { DeleteDatasetVersionsRequest, @@ -21,8 +19,6 @@ import { } from "google-protobuf/google/protobuf/struct_pb"; import { promisifyGrpcCall } from "../utils/misc"; import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; -import { parallelLimit } from "async"; -import compact from "lodash/compact"; type DatasetConfig = | { @@ -40,11 +36,7 @@ type DatasetConfig = export class Dataset extends Lister { private info: GrpcDataset = new GrpcDataset(); - private numOfWorkers: number = Math.min(os.cpus().length, 10); - private annotNumOfWorkers: number = 4; - private maxRetries: number = 10; private batchSize: number = 128; - private task: unknown; private input: Input; constructor({ authConfig, datasetId, url, datasetVersionId }: DatasetConfig) { @@ -142,41 +134,6 @@ export class Dataset extends Lister { } } - private async concurrentAnnotUpload( - annots: Annotation[][], - ): Promise>> { - const retryAnnotUpload: Array | null> = []; - - const uploadAnnotations = async ( - inpBatch: Annotation[], - ): Promise => { - try { - return await this.input.uploadAnnotations({ - batchAnnot: inpBatch, - showLog: false, - }); - } catch { - return null; - } - }; - - const maxWorkers = Math.min(this.annotNumOfWorkers, this.numOfWorkers); - - const uploadTasks = annots.map((annotBatch) => { - return async () => { - const uploadedAnnotation = await uploadAnnotations(annotBatch); - if (!uploadedAnnotation) { - retryAnnotUpload.push(annotBatch); - } - return uploadedAnnotation; - }; - }); - - await parallelLimit(uploadTasks, maxWorkers); - - return compact(retryAnnotUpload); - } - async uploadFromFolder({ folderPath, inputType, From b9b03fa49b2342da37100a82da7b371648a29d40 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 23 Apr 2024 16:24:35 +0530 Subject: [PATCH 15/41] fix: failing tests --- tests/client/workflow/workflowCrud.integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/workflow/workflowCrud.integration.test.ts b/tests/client/workflow/workflowCrud.integration.test.ts index 72541f6..930a7ac 100644 --- a/tests/client/workflow/workflowCrud.integration.test.ts +++ b/tests/client/workflow/workflowCrud.integration.test.ts @@ -7,7 +7,7 @@ import * as fs from "fs"; const NOW = Date.now().toString() + "-workflow"; const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; const CLARIFAI_PAT = import.meta.env.VITE_CLARIFAI_PAT; -const CREATE_APP_ID = `test_workflow_create_delete_app_${NOW}`; +const CREATE_APP_ID = `test_create_delete_app_${NOW}`; const MAIN_APP_ID = "main"; const workflowFile = path.resolve(__dirname, "./fixtures/general.yml"); From 7916a07725b373f41595119881ff0cd32ad69e36 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 23 Apr 2024 16:28:41 +0530 Subject: [PATCH 16/41] chore: upgrade grpc module --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3c54529..5eb3db4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@grpc/proto-loader": "^0.7.10", "async": "^3.2.5", "chalk": "^5.3.0", - "clarifai-nodejs-grpc": "^10.0.9", + "clarifai-nodejs-grpc": "^10.3.2", "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", @@ -3959,9 +3959,9 @@ } }, "node_modules/clarifai-nodejs-grpc": { - "version": "10.0.9", - "resolved": "https://registry.npmjs.org/clarifai-nodejs-grpc/-/clarifai-nodejs-grpc-10.0.9.tgz", - "integrity": "sha512-CufiPJBifKS3pdPcEXzmrNVzsga1hMCDvxcrVQ9uenLLK9NSo2FMTb3ef4QdiLnWw0gJii0AQWaFhAdQY/OmLQ==", + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/clarifai-nodejs-grpc/-/clarifai-nodejs-grpc-10.3.2.tgz", + "integrity": "sha512-uyC/ORz08hcEiW3AZ2VGmOU1saj1eMJE/W2zCu8zxVvbXsATdOMQSAawtgtnL4vTG6CxKItccuZqTpezYuX+dA==", "dependencies": { "@grpc/grpc-js": "^1.4.2", "@grpc/proto-loader": "^0.5.5", diff --git a/package.json b/package.json index 40d1c00..d821a80 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "@grpc/proto-loader": "^0.7.10", "async": "^3.2.5", "chalk": "^5.3.0", - "clarifai-nodejs-grpc": "^10.0.9", + "clarifai-nodejs-grpc": "^10.3.2", "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", From 2f732dc6634d56567d6e29cf9d9c0bc8810bf468 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 23 Apr 2024 16:38:44 +0530 Subject: [PATCH 17/41] chore: replace deprecated uuid package --- package-lock.json | 29 +++++++++++++---------------- package.json | 3 ++- src/client/app.ts | 2 +- src/client/input.ts | 2 +- src/datasets/upload/image.ts | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5eb3db4..e8fc8ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "safe-flat": "^2.1.0", - "uuidv4": "^6.2.13", + "uuid": "^9.0.1", "winston": "^3.11.0", "zod": "^3.22.4" }, @@ -34,6 +34,7 @@ "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", "@vitest/coverage-v8": "^1.3.1", @@ -3340,9 +3341,10 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, "node_modules/@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.19.1", @@ -7285,22 +7287,17 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/uuidv4": { - "version": "6.2.13", - "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", - "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", - "dependencies": { - "@types/uuid": "8.3.4", - "uuid": "8.3.2" - } - }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", diff --git a/package.json b/package.json index d821a80..075c79f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", "@vitest/coverage-v8": "^1.3.1", @@ -73,7 +74,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "safe-flat": "^2.1.0", - "uuidv4": "^6.2.13", + "uuid": "^9.0.1", "winston": "^3.11.0", "zod": "^3.22.4" } diff --git a/src/client/app.ts b/src/client/app.ts index 57a384b..f9f3b79 100644 --- a/src/client/app.ts +++ b/src/client/app.ts @@ -44,7 +44,7 @@ import * as yaml from "js-yaml"; import { validateWorkflow } from "../workflows/validate"; import { getYamlOutputInfoProto } from "../workflows/utils"; import { Model as ModelConstructor } from "./model"; -import { uuid } from "uuidv4"; +import { v4 as uuid } from "uuid"; import { fromProtobufObject } from "from-protobuf-object"; import { fromPartialProtobufObject } from "../utils/fromPartialProtobufObject"; import { flatten } from "safe-flat"; diff --git a/src/client/input.ts b/src/client/input.ts index 066a678..0aba10f 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -27,7 +27,7 @@ import { } from "google-protobuf/google/protobuf/struct_pb"; import { parse } from "csv-parse"; import { finished } from "stream/promises"; -import { uuid } from "uuidv4"; +import { v4 as uuid } from "uuid"; import { CancelInputsAddJobRequest, DeleteInputsRequest, diff --git a/src/datasets/upload/image.ts b/src/datasets/upload/image.ts index caeb68b..a85006d 100644 --- a/src/datasets/upload/image.ts +++ b/src/datasets/upload/image.ts @@ -4,7 +4,7 @@ import { } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; import { ClarifaiDataLoader, ClarifaiDataset } from "./base"; import path from "path"; -import { uuid } from "uuidv4"; +import { v4 as uuid } from "uuid"; import { Input } from "../../client/input"; import { VisualClassificationFeatures, From 7d7750df9b3bb3ab74064ff9c9ec3a521292f705 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 24 Apr 2024 12:01:21 +0530 Subject: [PATCH 18/41] chore: setup base rag class --- src/client/app.ts | 10 +- src/client/rag.ts | 397 +++++++++++++++++++++++++++++++++++++++++++ src/constants/rag.ts | 1 + src/index.ts | 1 + src/urls/helper.ts | 5 +- 5 files changed, 408 insertions(+), 6 deletions(-) create mode 100644 src/client/rag.ts create mode 100644 src/constants/rag.ts diff --git a/src/client/app.ts b/src/client/app.ts index f9f3b79..4ef27ca 100644 --- a/src/client/app.ts +++ b/src/client/app.ts @@ -49,13 +49,15 @@ import { fromProtobufObject } from "from-protobuf-object"; import { fromPartialProtobufObject } from "../utils/fromPartialProtobufObject"; import { flatten } from "safe-flat"; +export type AuthAppConfig = Omit & { + appId?: undefined; + userId?: undefined; +}; + export type AppConfig = | { url: ClarifaiAppUrl; - authConfig: Omit & { - appId?: undefined; - userId?: undefined; - }; + authConfig: AuthAppConfig; } | { url?: undefined; diff --git a/src/client/rag.ts b/src/client/rag.ts new file mode 100644 index 0000000..7292583 --- /dev/null +++ b/src/client/rag.ts @@ -0,0 +1,397 @@ +import { v4 as uuidv4 } from "uuid"; +import { App, AuthAppConfig } from "./app"; +import { Workflow } from "./workflow"; +import * as fs from "fs"; +import yaml from "js-yaml"; +import { resources_pb2 } from "clarifai_grpc"; +import { + JavaScriptValue, + Struct, +} from "google-protobuf/google/protobuf/struct_pb"; +import { Inputs } from "clarifai"; +import { Model } from "./model"; +import { User } from "./user"; +import { MAX_UPLOAD_BATCH_SIZE } from "../constants/rag"; +import { UserError } from "../errors"; +import { convert_messages_to_str } from "clarifai"; +import { format_assistant_message } from "clarifai"; +import { load_documents } from "clarifai"; +import { split_document } from "clarifai"; +import { AuthConfig } from "../utils/types"; +import { ClarifaiAppUrl, ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; +import { + ModelVersion, + OutputInfo, +} from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import { validateWorkflow } from "../workflows/validate"; + +const DEFAULT_RAG_PROMPT_TEMPLATE = + "Context information is below:\n{data.hits}\nGiven the context information and not prior knowledge, answer the query.\nQuery: {data.text.raw}\nAnswer: "; + +type UrlAuthConfig = Omit & { + appId?: undefined; + userId?: undefined; +}; + +type RAGConfig = + | { + workflowUrl: ClarifaiUrl; + workflow?: undefined; + authConfig?: UrlAuthConfig; + } + | { + workflowUrl?: undefined; + workflow: Workflow; + authConfig?: AuthConfig; + }; + +type workflowSchema = ReturnType; + +export class RAG { + private promptWorkflow: Workflow; + private app: App; + + private chatStateId: string; + + constructor({ workflowUrl, workflow, authConfig = {} }: RAGConfig) { + if (workflowUrl && workflow) { + throw new UserError( + "Only one of workflowUrl or workflow can be specified.", + ); + } + if (workflowUrl) { + if (authConfig.userId || authConfig.appId) { + throw UserError( + "userId and appId should not be specified in authConfig when using workflowUrl.", + ); + } + console.info("workflow_url:%s", workflowUrl); + const [userId, appId, , ,] = + ClarifaiUrlHelper.splitClarifaiUrl(workflowUrl); + const w = new Workflow({ + url: workflowUrl, + authConfig: authConfig as UrlAuthConfig, + }); + this.promptWorkflow = w; + this.app = new App({ + authConfig: { + ...authConfig, + userId, + appId, + } as AuthConfig, + }); + } else if (workflow) { + this.promptWorkflow = workflow; + this.app = new App({ + authConfig: authConfig as AuthConfig, + }); + } + } + + static async setup({ + authConfig, + appUrl, + llmUrl = "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct", + baseWorkflow = "Text", + workflowYamlFilename = "prompter_wf.yaml", + promptTemplate = DEFAULT_RAG_PROMPT_TEMPLATE, + workflowId, + minScore = 0.95, + maxResults = 5, + }: { + authConfig?: AuthConfig | AuthAppConfig; + appUrl?: ClarifaiAppUrl; + llmUrl?: ClarifaiUrl; + baseWorkflow?: string; + workflowYamlFilename?: string; + promptTemplate?: string; + workflowId?: string; + minScore?: number; + maxResults?: number; + }) { + const { userId, appId } = authConfig ?? {}; + const nowTs = Date.now().toString(); + const [, , resourceType, resourceId] = + ClarifaiUrlHelper.splitClarifaiUrl(llmUrl); + if (resourceType !== "models") { + throw new UserError("llmUrl must be a model URL."); + } + let app: App; + if (userId && !appUrl) { + const user = new User(authConfig as AuthConfig); + const appId = `rag_app_${nowTs}`; + const appObj = await user.createApp({ + appId: appId, + baseWorkflow: baseWorkflow, + }); + if (authConfig && !authConfig?.appId) authConfig.appId = appObj.id; + if (authConfig && !authConfig?.userId) authConfig.userId = userId; + app = new App({ + authConfig: authConfig as AuthConfig, + }); + } + + if (!userId && appUrl) { + app = new App({ + url: appUrl, + authConfig: authConfig as AuthAppConfig, + }); + const [userIdFromUrl, appIdFromUrl] = + ClarifaiUrlHelper.splitClarifaiAppUrl(appUrl); + if (authConfig && !authConfig?.appId) authConfig.appId = appIdFromUrl; + if (authConfig && !authConfig?.userId) authConfig.userId = userIdFromUrl; + // const user = new User({ + // ...(authConfig as AuthAppConfig), + // userId: userIdFromUrl, + // appId: appIdFromUrl, + // }); + } + + if (userId && appUrl) { + throw new UserError("Must provide one of userId or appUrl, not both."); + } + + if (appId && appUrl) { + throw new UserError("Must provide one of appId or appUrl, not both."); + } + + if (!userId && !appUrl) { + throw new UserError( + "userId or appUrl must be provided. The userId can be found at https://clarifai.com/settings.", + ); + } + + // @ts-expect-error - app has been assigned but not picked up by typescript + const llmObject = await app.model({ modelId: resourceId }); + + if (!llmObject) { + throw new UserError("LLM model not found."); + } + + const params = Struct.fromJavaScript({ + minScore, + maxResults, + promptTemplate, + }); + + const outputInfo = new OutputInfo().setParams(params); + + const modelId = + workflowId !== null + ? `prompter-${workflowId}-${nowTs}` + : `rag-prompter-${nowTs}`; + + // @ts-expect-error - app has been assigned but not picked up by typescript + const prompterModelObj = await app.createModel({ + modelId, + params: { + modelTypeId: "rag-prompter", + }, + }); + const prompterModel = new Model({ + authConfig: authConfig as AuthConfig, + modelId: prompterModelObj.id, + }); + const prompterModelVersion = await prompterModel.createVersion( + new ModelVersion().setOutputInfo(outputInfo), + ); + + if (!prompterModelVersion?.id) { + throw new Error("Prompter model version creation failed."); + } + + workflowId = workflowId ? workflowId : `rag-wf-${nowTs}`; + const workflowObject: workflowSchema = { + workflow: { + id: workflowId, + nodes: [ + { + id: "rag-prompter", + model: { + modelId: prompterModelObj.id, + modelVersionId: prompterModelVersion.id, + }, + }, + { + id: "llm", + model: { + modelId: llmObject.id, + userId: llmObject.userId, + appId: llmObject.appId, + }, + nodeInputs: [ + { + nodeId: "rag-prompter", + }, + ], + }, + ], + }, + }; + const workflowYaml = yaml.dump(workflowObject, { noRefs: true }); + fs.writeFileSync(workflowYamlFilename, workflowYaml); + // @ts-expect-error - app has been assigned but not picked up by typescript + const wf = await app.createWorkflow({ + configFilePath: workflowYamlFilename, + }); + const workflow = new Workflow({ + workflowId: wf.id, + authConfig: authConfig as AuthConfig, + }); + return new RAG({ workflow }); + } + + upload({ + filePath, + folderPath, + url, + batchSize = 128, + chunkSize = 1024, + chunkOverlap = 200, + datasetId, + metadata, + }: { + filePath?: string; + folderPath?: string; + url?: string; + batchSize?: number; + chunkSize?: number; + chunkOverlap?: number; + datasetId?: string; + metadata?: Record; + }): void { + if (batchSize > MAX_UPLOAD_BATCH_SIZE) { + throw new UserError( + `batch_size cannot be greater than ${MAX_UPLOAD_BATCH_SIZE}`, + ); + } + + if ( + (filePath && (folderPath || url)) || + (folderPath && (filePath || url)) || + (url && (filePath || folderPath)) + ) { + throw new UserError( + "Only one of file_path, folder_path, or url can be specified.", + ); + } + + const documents = load_documents({ + file_path: filePath, + folder_path: folderPath, + url, + }); + + const text_chunks: string[] = []; + const metadata_list: object[] = []; + + for (const doc of documents) { + let doc_i = 0; + const cur_text_chunks = split_document({ + text: doc.text, + chunk_size: chunkSize, + chunk_overlap: chunkOverlap, + ...kwargs, + }); + text_chunks.push(...cur_text_chunks); + metadata_list.push(...Array(cur_text_chunks.length).fill(doc.metadata)); + if (text_chunks.length > batchSize) { + for (let idx = 0; idx < text_chunks.length; idx += batchSize) { + if (idx + batchSize > text_chunks.length) { + continue; + } + const batch_texts = text_chunks.slice(idx, idx + batchSize); + const batch_ids = Array(batchSize) + .fill(null) + .map(() => uuidv4()); + const batch_metadatas = metadata_list.slice(idx, idx + batchSize); + const meta_list = batch_metadatas.map((meta: any) => { + const meta_struct = new Struct(); + meta_struct.update(meta); + meta_struct.update({ doc_chunk_no: doc_i }); + if (metadata && typeof metadata === "object") { + meta_struct.update(metadata); + } + doc_i += 1; + return meta_struct; + }); + const input_batch = batch_texts.map((text: string, i: number) => { + return this.app.inputs().get_text_input({ + input_id: batch_ids[i], + raw_text: text, + dataset_id: datasetId, + metadata: meta_list[i], + }); + }); + this.app.inputs().upload_inputs({ inputs: input_batch }); + text_chunks.splice(idx, batchSize); + metadata_list.splice(idx, batchSize); + } + } + } + + if (text_chunks.length > 0) { + const batch_size = text_chunks.length; + const batch_ids = Array(batch_size) + .fill(null) + .map(() => uuidv4()); + const batch_metadatas = metadata_list.slice(0, batch_size); + const meta_list = batch_metadatas.map((meta: any) => { + const meta_struct = new Struct(); + meta_struct.update(meta); + meta_struct.update({ doc_chunk_no: doc_i }); + if (metadata && typeof metadata === "object") { + meta_struct.update(metadata); + } + doc_i += 1; + return meta_struct; + }); + const input_batch = text_chunks.map((text: string, i: number) => { + return this.app.inputs().get_text_input({ + input_id: batch_ids[i], + raw_text: text, + dataset_id: datasetId, + metadata: meta_list[i], + }); + }); + this.app.inputs().upload_inputs({ inputs: input_batch }); + text_chunks.splice(0, batch_size); + metadata_list.splice(0, batch_size); + } + } + + chat( + messages: { role: string; content: string }[], + client_manage_state: boolean = false, + ): { role: string; content: string }[] { + if (client_manage_state) { + const single_prompt = convert_messages_to_str(messages); + const input_proto = Inputs._get_proto("", "", { + text_pb: new resources_pb2.Text({ raw: single_prompt }), + }); + const response = this.promptWorkflow.predict([input_proto]); + messages.push( + format_assistant_message(response.results[0].outputs[-1].data.text.raw), + ); + return messages; + } + + const message = messages[messages.length - 1].content; + if (message.length === 0) { + throw new UserError("Empty message supplied."); + } + + const chat_state_id = RAG.chatStateId !== null ? RAG.chatStateId : "init"; + const input_proto = Inputs._get_proto("", "", { + text_pb: new resources_pb2.Text({ raw: message }), + }); + const response = this.promptWorkflow.predict([input_proto], { + workflow_state_id: chat_state_id, + }); + + RAG.chatStateId = response.workflow_state.id; + return [ + format_assistant_message(response.results[0].outputs[-1].data.text.raw), + ]; + } +} diff --git a/src/constants/rag.ts b/src/constants/rag.ts new file mode 100644 index 0000000..981cbee --- /dev/null +++ b/src/constants/rag.ts @@ -0,0 +1 @@ +export const MAX_UPLOAD_BATCH_SIZE = 128; diff --git a/src/index.ts b/src/index.ts index d42ce7b..9c7ca1e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,3 +5,4 @@ export * from "./client/model"; export * from "./client/search"; export * from "./client/workflow"; export * from "./client/dataset"; +export * from "./client/rag"; diff --git a/src/urls/helper.ts b/src/urls/helper.ts index 094f650..d8d7675 100644 --- a/src/urls/helper.ts +++ b/src/urls/helper.ts @@ -131,13 +131,14 @@ export class ClarifaiUrlHelper { */ static splitClarifaiAppUrl(url: ClarifaiAppUrl): [string, string] { const o = new URL(url); - const parts = o.pathname.split("/").filter((part) => part.length > 0); + const [parts] = o.pathname.split("/").filter((part) => part.length > 0); if (parts.length !== 2) { throw new Error( `Provided url must have 2 parts after the domain name. The current parts are: ${parts}`, ); } - return [parts[0], parts[1]]; + const [userId, appId] = parts; + return [userId, appId]; } /** From 1cad4c654c549ccee0cefebed92ab95b4b65e1d9 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 24 Apr 2024 13:28:48 +0530 Subject: [PATCH 19/41] feat: setup llma powered utilities --- package-lock.json | 2921 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 + src/rag/utils.ts | 169 +++ tsconfig.json | 2 +- 4 files changed, 3059 insertions(+), 36 deletions(-) create mode 100644 src/rag/utils.ts diff --git a/package-lock.json b/package-lock.json index e8fc8ce..0243978 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", + "@llamaindex/edge": "^0.2.10", "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", @@ -21,6 +22,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "safe-flat": "^2.1.0", + "tmp": "^0.2.3", "uuid": "^9.0.1", "winston": "^3.11.0", "zod": "^3.22.4" @@ -34,6 +36,7 @@ "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", + "@types/tmp": "^0.2.6", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", @@ -74,6 +77,102 @@ "node": ">=6.0.0" } }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.20.6", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.20.6.tgz", + "integrity": "sha512-vpVWAol+Ih1UkZGUj8DYPuqWDGxBp6M/JYz4nvq2HBT0zKdvi24Z9oznA7tr+HDed78JZrw+nbxs2I8JbTAIiQ==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + } + }, + "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@anthropic-ai/sdk/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@anthropic-ai/sdk/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/@anthropic-ai/sdk/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/@anthropic-ai/sdk/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.535.0.tgz", + "integrity": "sha512-aY4MYfduNj+sRR37U7XxYR8wemfbKP6lx00ze2M2uubn7mZotuVrWYAafbMSXrdEMSToE5JDhr28vArSOoLcSg==", + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -311,6 +410,21 @@ "kuler": "^2.0.0" } }, + "node_modules/@datastax/astra-db-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@datastax/astra-db-ts/-/astra-db-ts-1.1.0.tgz", + "integrity": "sha512-MqXLbhd7JU30LVzytGl7sQUYKwMbV1nU3lnHLAZCy1XLQDlcEynRHh/mJrmVKQGNqezQnCwM4r2knq1sYLyMGw==", + "dependencies": { + "bson-objectid": "^2.0.4", + "fetch-h2": "^3.0.2", + "object-hash": "^3.0.0", + "typed-emitter": "^2.1.0", + "uuidv7": "^0.6.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", @@ -762,16 +876,24 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, "node_modules/@grpc/grpc-js": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", - "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", + "integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==", "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.10", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { @@ -819,6 +941,14 @@ "node": ">=12.0.0" } }, + "node_modules/@huggingface/jinja": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.2.2.tgz", + "integrity": "sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==", + "engines": { + "node": ">=18" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -921,6 +1051,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@lezer/common": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", @@ -936,6 +1075,132 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@llamaindex/cloud": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@llamaindex/cloud/-/cloud-0.0.5.tgz", + "integrity": "sha512-8HBSiAZkmX1RvpEM2czEVKqMUCKk7uvMSiDpMGWlEj3MUKBYCh+r8E2TtVhZfU4TunEI7nJRMcVBfXDyFz6Lpw==", + "dependencies": { + "@types/qs": "^6.9.12", + "form-data": "^4.0.0", + "js-base64": "^3.7.7", + "qs": "^6.12.0" + }, + "peerDependencies": { + "node-fetch": "^3.3.2" + }, + "peerDependenciesMeta": { + "node-fetch": { + "optional": true + } + } + }, + "node_modules/@llamaindex/edge": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@llamaindex/edge/-/edge-0.2.10.tgz", + "integrity": "sha512-Ur3MtUc03ba8Uhk+vmsyM/+MWknk40hGmjIoxXnrI85DXguNTg9qVnHyuZJMM66dNBu/lW+V6UmJGFABqN6dJQ==", + "dependencies": { + "@anthropic-ai/sdk": "^0.20.6", + "@aws-crypto/sha256-js": "^5.2.0", + "@datastax/astra-db-ts": "^1.0.1", + "@grpc/grpc-js": "^1.10.6", + "@llamaindex/cloud": "0.0.5", + "@llamaindex/env": "0.0.7", + "@mistralai/mistralai": "^0.1.3", + "@notionhq/client": "^2.2.15", + "@pinecone-database/pinecone": "^2.2.0", + "@qdrant/js-client-rest": "^1.8.2", + "@types/lodash": "^4.17.0", + "@types/node": "^20.12.7", + "@types/papaparse": "^5.3.14", + "@types/pg": "^8.11.5", + "@xenova/transformers": "^2.17.1", + "@zilliz/milvus2-sdk-node": "^2.4.1", + "ajv": "^8.12.0", + "assemblyai": "^4.4.1", + "chromadb": "~1.7.3", + "cohere-ai": "^7.9.5", + "js-tiktoken": "^1.0.11", + "lodash": "^4.17.21", + "magic-bytes.js": "^1.10.0", + "mammoth": "^1.7.1", + "md-utils-ts": "^2.0.0", + "mongodb": "^6.5.0", + "notion-md-crawler": "^0.0.2", + "openai": "^4.38.0", + "papaparse": "^5.4.1", + "pathe": "^1.1.2", + "pdf2json": "^3.0.5", + "pg": "^8.11.5", + "pgvector": "^0.1.8", + "portkey-ai": "^0.1.16", + "rake-modified": "^1.0.8", + "string-strip-html": "^13.4.8", + "wikipedia": "^2.1.2", + "wink-nlp": "^1.14.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@llamaindex/edge/node_modules/@llamaindex/env": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@llamaindex/env/-/env-0.0.7.tgz", + "integrity": "sha512-6j7eGXhSDspz33FzdWJRTbGlXa3osYP/aP9dm10Z7JCxaxyQZmGIWL149HNkGgV4lxiPmGPx7YWjBBj9nRdo2w==", + "dependencies": { + "@types/lodash": "^4.14.202", + "@types/node": "^20.11.20", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "pathe": "^1.1.2", + "readable-stream": "^4.5.2" + } + }, + "node_modules/@llamaindex/edge/node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@llamaindex/edge/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@llamaindex/edge/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@llamaindex/edge/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@lmdb/lmdb-darwin-arm64": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz", @@ -1028,6 +1293,60 @@ "node": ">=12.0.0" } }, + "node_modules/@mistralai/mistralai": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-0.1.3.tgz", + "integrity": "sha512-WUHxC2xdeqX9PTXJEqdiNY54vT2ir72WSJrZTTBKRnkfhX6zIfCYA24faRlWjUB5WTpn+wfdGsTMl3ArijlXFA==", + "dependencies": { + "node-fetch": "^2.6.7" + } + }, + "node_modules/@mistralai/mistralai/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@mistralai/mistralai/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/@mistralai/mistralai/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/@mistralai/mistralai/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", + "integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", @@ -1141,6 +1460,56 @@ "node": ">= 8" } }, + "node_modules/@notionhq/client": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-2.2.15.tgz", + "integrity": "sha512-XhdSY/4B1D34tSco/GION+23GMjaS9S2zszcqYkMHo8RcWInymF6L1x+Gk7EmHdrSxNFva2WM8orhC4BwQCwgw==", + "dependencies": { + "@types/node-fetch": "^2.5.10", + "node-fetch": "^2.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@notionhq/client/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@notionhq/client/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/@notionhq/client/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/@notionhq/client/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/@parcel/bundler-default": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.11.0.tgz", @@ -2796,6 +3165,50 @@ "@parcel/core": "^2.11.0" } }, + "node_modules/@petamoriken/float16": { + "version": "3.8.6", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.6.tgz", + "integrity": "sha512-GNJhABTtcmt9al/nqdJPycwFD46ww2+q2zwZzTjY0dFFwUAFRw9zszvEr9osyJRd9krRGy6hUDopWUg9fX7VVw==" + }, + "node_modules/@pinecone-database/pinecone": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@pinecone-database/pinecone/-/pinecone-2.2.0.tgz", + "integrity": "sha512-qfVs9n5YyTmerIV1GE1u89xF1W3oFSF53STW68Oqyxey0dGq4775cCw8G5pnwoy872uqfh+tMRDME9bcWfinUw==", + "dependencies": { + "@sinclair/typebox": "^0.29.0", + "ajv": "^8.12.0", + "cross-fetch": "^3.1.5", + "encoding": "^0.1.13" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@pinecone-database/pinecone/node_modules/@sinclair/typebox": { + "version": "0.29.6", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.29.6.tgz", + "integrity": "sha512-aX5IFYWlMa7tQ8xZr3b2gtVReCvg7f3LEhjir/JAjX2bJCMVJA5tIPv30wTD4KDfcwMd7DDYY3hFDeGmOgtrZQ==" + }, + "node_modules/@pinecone-database/pinecone/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@pinecone-database/pinecone/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -2862,6 +3275,32 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@qdrant/js-client-rest": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.9.0.tgz", + "integrity": "sha512-YiX/IskbRCoAY2ujyPDI6FBcO0ygAS4pgkGaJ7DcrJFh4SZV2XHs+u0KM7mO72RWJn1eJQFF2PQwxG+401xxJg==", + "dependencies": { + "@qdrant/openapi-typescript-fetch": "1.2.6", + "@sevinf/maybe": "0.5.0", + "undici": "~5.28.4" + }, + "engines": { + "node": ">=18.0.0", + "pnpm": ">=8" + }, + "peerDependencies": { + "typescript": ">=4.7" + } + }, + "node_modules/@qdrant/openapi-typescript-fetch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@qdrant/openapi-typescript-fetch/-/openapi-typescript-fetch-1.2.6.tgz", + "integrity": "sha512-oQG/FejNpItrxRHoyctYvT3rwGZOnK4jr3JdppO/c78ktDvkWiPXPHNsrDf33K9sZdRb6PR7gi4noIapu5q4HA==", + "engines": { + "node": ">=18.0.0", + "pnpm": ">=8" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", @@ -3031,12 +3470,63 @@ "win32" ] }, + "node_modules/@sevinf/maybe": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@sevinf/maybe/-/maybe-0.5.0.tgz", + "integrity": "sha512-ARhyoYDnY1LES3vYI0fiG6e9esWfTNcXcO6+MPJJXcnyMV3bim4lnFt45VXouV7y82F4x3YH8nOQ6VztuvUiWg==" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@swc/core": { "version": "1.3.106", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.106.tgz", @@ -3313,8 +3803,15 @@ "node_modules/@types/lodash": { "version": "4.17.0", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", - "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", - "dev": true + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dependencies": { + "@types/lodash": "*" + } }, "node_modules/@types/long": { "version": "4.0.2", @@ -3329,12 +3826,55 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/papaparse": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.14.tgz", + "integrity": "sha512-LxJ4iEFcpqc6METwp9f6BV6VVc43m6MfH0VqFosHvrUgfXiFe6ww7R3itkOQ+TCK6Y+Iv/+RnnvtRZnkc5Kc9g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/pg": { + "version": "8.11.5", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.5.tgz", + "integrity": "sha512-2xMjVviMxneZHDHX5p5S6tsRRs7TpDHeeK7kTTMe/kAC/mRRNjWHjZg0rkiY+e17jXSZV3zJYDxXV8Cy72/Vuw==", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + }, "node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", @@ -3346,6 +3886,19 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.19.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", @@ -3689,12 +4242,95 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", - "dev": true - }, + "node_modules/@xenova/transformers": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/@xenova/transformers/-/transformers-2.17.1.tgz", + "integrity": "sha512-zo702tQAFZXhzeD2GCYUNUqeqkoueOdiSbQWa4s0q7ZE4z8WBIwIsMMPGobpgdqjQ2u0Qulo08wuqVEUrBXjkQ==", + "dependencies": { + "@huggingface/jinja": "^0.2.2", + "onnxruntime-web": "1.14.0", + "sharp": "^0.32.0" + }, + "optionalDependencies": { + "onnxruntime-node": "1.14.0" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@zilliz/milvus2-sdk-node": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@zilliz/milvus2-sdk-node/-/milvus2-sdk-node-2.4.1.tgz", + "integrity": "sha512-j3vbMvaQyjnUhDA+Nk6AmEKroGJiA6qTW6lVkLMGYsPQd2WzDXjbEM4YCLUcfyh8xsngAzKFkPmM4YIpI3BdQQ==", + "dependencies": { + "@grpc/grpc-js": "^1.10.1", + "@grpc/proto-loader": "^0.7.10", + "@petamoriken/float16": "^3.8.6", + "dayjs": "^1.11.7", + "generic-pool": "^3.9.0", + "lru-cache": "^9.1.2", + "protobufjs": "^7.2.6", + "winston": "^3.9.0" + } + }, + "node_modules/@zilliz/milvus2-sdk-node/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/@zilliz/milvus2-sdk-node/node_modules/lru-cache": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@zilliz/milvus2-sdk-node/node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", + "dev": true + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3725,6 +4361,17 @@ "node": ">=0.4.0" } }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3741,6 +4388,11 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/already": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/already/-/already-2.2.1.tgz", + "integrity": "sha512-qk6RIVMS/R1yTvBzfIL1T76PsIL7DIVCINoLuFw2YXKLpLtsTobqdChMs8m3OhuPS3CEE3+Ra5ibYiqdyogbsQ==" + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3769,6 +4421,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3783,6 +4440,17 @@ "node": ">=8" } }, + "node_modules/assemblyai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/assemblyai/-/assemblyai-4.4.1.tgz", + "integrity": "sha512-GzpbSRhZ0VlHNTQTOKxOrod3Ckw4AZVQQlnE5sJeCuAhTXJLLi5SE6U4vOapTsxf3lO7+93tdNTlWBrkwYO4Nw==", + "dependencies": { + "ws": "^8.16.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -3797,12 +4465,64 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bare-events": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.2.tgz", + "integrity": "sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.3.tgz", + "integrity": "sha512-amG72llr9pstfXOBOHve1WjiuKKAMnebcmMbPWDZ7BCevAoJLpugjuAPRsDINEyjT0a6tbaVx3DctkXIRbLuJw==", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "streamx": "^2.13.0" + } + }, + "node_modules/bare-os": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.1.tgz", + "integrity": "sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.1.tgz", + "integrity": "sha512-OHM+iwRDRMDBsSW7kl3dO62JyHdBKO3B25FB9vNQBPcGHMo4+eA8Yj41Lfbk3pS/seDY+siNge0LdRTulAau/A==", + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, "node_modules/base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", @@ -3812,6 +4532,63 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -3872,6 +4649,43 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bson": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz", + "integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/bson-objectid": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-2.0.4.tgz", + "integrity": "sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -3881,6 +4695,29 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callguard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callguard/-/callguard-2.0.0.tgz", + "integrity": "sha512-I3nd+fuj20FK1qu00ImrbH+II+8ULS6ioYr9igqR1xyqySoqc3DiHEyUM0mkoAdKeLGg2CtGnO8R3VRQX5krpQ==" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3890,6 +4727,14 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", + "engines": { + "node": ">=4" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001580", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz", @@ -3951,6 +4796,39 @@ "node": "*" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/chromadb": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/chromadb/-/chromadb-1.7.3.tgz", + "integrity": "sha512-3GgvQjpqgk5C89x5EuTDaXKbfrdqYDJ5UVyLQ3ZmwxnpetNc+HhRDGjkvXa5KSvpQ3lmKoyDoqnN4tZepfFkbw==", + "dependencies": { + "cliui": "^8.0.1", + "isomorphic-fetch": "^3.0.0" + }, + "engines": { + "node": ">=14.17.0" + }, + "peerDependencies": { + "@google/generative-ai": "^0.1.1", + "cohere-ai": "^5.0.0 || ^6.0.0 || ^7.0.0", + "openai": "^3.0.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@google/generative-ai": { + "optional": true + }, + "cohere-ai": { + "optional": true + }, + "openai": { + "optional": true + } + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -4025,6 +4903,86 @@ "node": ">=0.8" } }, + "node_modules/codsen-utils": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/codsen-utils/-/codsen-utils-1.6.4.tgz", + "integrity": "sha512-PDyvQ5f2PValmqZZIJATimcokDt4JjIev8cKbZgEOoZm+U1IJDYuLeTcxZPQdep99R/X0RIlQ6ReQgPOVnPbNw==", + "dependencies": { + "rfdc": "^1.3.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/cohere-ai": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/cohere-ai/-/cohere-ai-7.9.5.tgz", + "integrity": "sha512-tr8LUR3Q46agFpfEwaYwzYO4qAuN0/R/8YroG4bc86LadOacBAabctZUq0zfCdLiL7gB4yWJs4QCzfpRH3rQuw==", + "dependencies": { + "form-data": "4.0.0", + "js-base64": "3.7.2", + "node-fetch": "2.7.0", + "qs": "6.11.2", + "url-join": "4.0.1" + } + }, + "node_modules/cohere-ai/node_modules/js-base64": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", + "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" + }, + "node_modules/cohere-ai/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cohere-ai/node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cohere-ai/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/cohere-ai/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/cohere-ai/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -4081,6 +5039,17 @@ "text-hex": "1.0.x" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -4102,6 +5071,11 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -4128,6 +5102,52 @@ } } }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/cross-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/cross-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4294,6 +5314,21 @@ "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.5.tgz", "integrity": "sha512-erCk7tyU3yLWAhk6wvKxnyPtftuy/6Ak622gOO7BCJ05+TYffnPCJF905wmOQm+BpkX54OdAl8pveJwUdpnCXQ==" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "optional": true, + "peer": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -4311,6 +5346,20 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -4323,12 +5372,44 @@ "node": ">=6" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -4350,6 +5431,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dingbat-to-unicode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", + "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4456,6 +5542,14 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, + "node_modules/duck": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz", + "integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==", + "dependencies": { + "underscore": "^1.13.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.645", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.645.tgz", @@ -4472,6 +5566,22 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/entities": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", @@ -4493,6 +5603,25 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", @@ -4833,11 +5962,35 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -4845,6 +5998,11 @@ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4899,6 +6057,47 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "optional": true, + "peer": true, + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/fetch-h2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fetch-h2/-/fetch-h2-3.0.2.tgz", + "integrity": "sha512-Lo6UPdMKKc9Ond7yjG2vq0mnocspOLh1oV6+XZdtfdexacvMSz5xm3WoQhTAdoR2+UqPlyMNqcqfecipoD+l/A==", + "dependencies": { + "@types/tough-cookie": "^4.0.0", + "already": "^2.2.1", + "callguard": "^2.0.0", + "get-stream": "^6.0.1", + "through2": "^4.0.2", + "to-arraybuffer": "^1.0.1", + "tough-cookie": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4937,6 +6136,11 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/flatbuffers": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz", + "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==" + }, "node_modules/flatted": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", @@ -4949,9 +6153,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -4967,6 +6171,57 @@ } } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/formdata-node/node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "optional": true, + "peer": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from-protobuf-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/from-protobuf-object/-/from-protobuf-object-1.0.2.tgz", @@ -4975,6 +6230,32 @@ "google-protobuf": "^3.21.2" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha512-9ztMtDZtSKC78V8mev+k31qaTabbmuH5jatdvPBMikrFHvw5BqlYnQIn/WGK3WHeRooSTkRvLa2IPlaHjPq5Sg==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + }, + "node_modules/fs-promise": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", + "integrity": "sha512-oDrTLBQAcRd+p/tSRWvqitKegLPsvqr7aehs5N9ILWFM9az5y5Uh71jKdZ/DTMC4Kel7+GNCQyFCx/IftRv8yg==", + "deprecated": "Use mz or fs-extra^3.0 with Promise Support", + "dependencies": { + "any-promise": "^1.3.0", + "fs-extra": "^2.0.0", + "mz": "^2.6.0", + "thenify-all": "^1.6.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4995,6 +6276,22 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "engines": { + "node": ">= 4" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5012,6 +6309,24 @@ "node": "*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-port": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", @@ -5021,6 +6336,22 @@ "node": ">=6" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -5078,12 +6409,33 @@ "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==" + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -5114,6 +6466,65 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -5186,6 +6597,44 @@ "entities": "^3.0.1" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -5195,6 +6644,11 @@ "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -5239,11 +6693,28 @@ "wrappy": "1" } }, + "node_modules/infobox-parser": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/infobox-parser/-/infobox-parser-3.6.4.tgz", + "integrity": "sha512-d2lTlxKZX7WsYxk9/UPt51nkmZv5tbC75SSw4hfHqZ3LpRAn6ug0oru9xI2X+S78va3aUAze3xl/UqMuwLmJUw==", + "dependencies": { + "camelcase": "^4.1.0" + }, + "funding": { + "type": "individual", + "url": "https://www.buymeacoffee.com/2tmRKi9" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5314,12 +6785,64 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/isomorphic-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/isomorphic-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/isomorphic-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/isomorphic-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -5370,6 +6893,19 @@ "node": ">=8" } }, + "node_modules/js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" + }, + "node_modules/js-tiktoken": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.11.tgz", + "integrity": "sha512-PajXFLq2vx7/8jllQZ43vzNpAai/0MOVdJjW/UrNyJorNQRTjHrqdGJG/mjHVy7h9M6dW6CaG43eNLMYFkTh6w==", + "dependencies": { + "base64-js": "^1.5.1" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5429,6 +6965,52 @@ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", "dev": true }, + "node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5456,6 +7038,14 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lightningcss": { "version": "1.23.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.23.0.tgz", @@ -5721,6 +7311,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -5753,6 +7348,16 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "node_modules/lop": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/lop/-/lop-0.4.1.tgz", + "integrity": "sha512-9xyho9why2A2tzm5aIcMWKvzqKsnxrf9B5I+8O30olh6lQU8PH978LqZoI4++37RBgS1Em5i54v1TFs/3wnmXQ==", + "dependencies": { + "duck": "^0.1.12", + "option": "~0.2.1", + "underscore": "^1.13.1" + } + }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -5766,7 +7371,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -5780,6 +7384,11 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, + "node_modules/magic-bytes.js": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" + }, "node_modules/magic-string": { "version": "0.30.8", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", @@ -5818,6 +7427,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mammoth": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.7.1.tgz", + "integrity": "sha512-ckxfvNH5sUaJh+SbYbxpvB7urZTGS02jA91rFCNiL928CgE9FXXMyXxcJBY0n+CpmKE/eWh7qaV0+v+Dbwun3Q==", + "dependencies": { + "@xmldom/xmldom": "^0.8.6", + "argparse": "~1.0.3", + "base64-js": "^1.5.1", + "bluebird": "~3.4.0", + "dingbat-to-unicode": "^1.0.1", + "jszip": "^3.7.1", + "lop": "^0.4.1", + "path-is-absolute": "^1.0.0", + "underscore": "^1.13.1", + "xmlbuilder": "^10.0.0" + }, + "bin": { + "mammoth": "bin/mammoth" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/mammoth/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -5830,6 +7470,11 @@ "node": ">= 12" } }, + "node_modules/md-utils-ts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/md-utils-ts/-/md-utils-ts-2.0.0.tgz", + "integrity": "sha512-sMG6JtX0ebcRMHxYTcmgsh0/m6o8hGdQHFE2OgjvflRZlQM51CGGj/uuk056D+12BlCiW0aTpt/AdlDNtgQiew==" + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -5838,6 +7483,11 @@ "optional": true, "peer": true }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5866,6 +7516,36 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5882,11 +7562,15 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/mlly": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", @@ -5899,6 +7583,60 @@ "ufo": "^1.3.2" } }, + "node_modules/mongodb": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", + "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.4.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5947,6 +7685,16 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -5965,6 +7713,11 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5977,6 +7730,17 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-abi": { + "version": "3.62.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz", + "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", @@ -5986,6 +7750,43 @@ "node": "^16 || ^18 || >= 20" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "optional": true, + "peer": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", @@ -6015,6 +7816,15 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/notion-md-crawler": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/notion-md-crawler/-/notion-md-crawler-0.0.2.tgz", + "integrity": "sha512-lE3/DFMrg7GSbl1sBfDuLVLyxw+yjdarPVm1JGfQ6eONEbNGgO+BdZxpwwZQ1uYeEJurAXMXb/AXT8GKYjKAyg==", + "dependencies": { + "@notionhq/client": "^2.2.12", + "md-utils-ts": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -6033,11 +7843,39 @@ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", "dev": true }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -6050,6 +7888,115 @@ "fn.name": "1.x.x" } }, + "node_modules/onnx-proto": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/onnx-proto/-/onnx-proto-4.0.4.tgz", + "integrity": "sha512-aldMOB3HRoo6q/phyB6QRQxSt895HNNw82BNyZ2CMh4bjeKv7g/c+VpAFtJuEMVfYLMbRx61hbuqnKceLeDcDA==", + "dependencies": { + "protobufjs": "^6.8.8" + } + }, + "node_modules/onnxruntime-common": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.14.0.tgz", + "integrity": "sha512-3LJpegM2iMNRX2wUmtYfeX/ytfOzNwAWKSq1HbRrKc9+uqG/FsEA0bbKZl1btQeZaXhC26l44NWpNUeXPII7Ew==" + }, + "node_modules/onnxruntime-node": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.14.0.tgz", + "integrity": "sha512-5ba7TWomIV/9b6NH/1x/8QEeowsb+jBEvFzU6z0T4mNsFwdPqXeFUM7uxC6QeSRkEbWu3qEB0VMjrvzN/0S9+w==", + "optional": true, + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "onnxruntime-common": "~1.14.0" + } + }, + "node_modules/onnxruntime-web": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.14.0.tgz", + "integrity": "sha512-Kcqf43UMfW8mCydVGcX9OMXI2VN17c0p6XvR7IPSZzBf/6lteBzXHvcEVWDPmCKuGombl997HgLqj91F11DzXw==", + "dependencies": { + "flatbuffers": "^1.12.0", + "guid-typescript": "^1.0.9", + "long": "^4.0.0", + "onnx-proto": "^4.0.4", + "onnxruntime-common": "~1.14.0", + "platform": "^1.3.6" + } + }, + "node_modules/openai": { + "version": "4.38.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.38.3.tgz", + "integrity": "sha512-mIL9WtrFNOanpx98mJ+X/wkoepcxdqqu0noWFoNQHl/yODQ47YM7NEYda7qp8JfjqpLFVxY9mQhshoS/Fqac0A==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + }, + "bin": { + "openai": "bin/cli" + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/openai/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/openai/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/openai/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/openai/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/option": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz", + "integrity": "sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==" + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -6088,6 +8035,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/papaparse": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", + "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + }, "node_modules/parcel": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.11.0.tgz", @@ -6179,7 +8136,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6205,8 +8161,7 @@ "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, "node_modules/pathval": { "version": "1.1.1", @@ -6217,6 +8172,181 @@ "node": "*" } }, + "node_modules/pdf2json": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/pdf2json/-/pdf2json-3.0.5.tgz", + "integrity": "sha512-Un1yLbSlk/zfwrltgguskExIioXZlFSFwsyXU0cnBorLywbTbcdzmJJEebh+U2cFCtR7y8nDs5lPHAe7ldxjZg==", + "bundleDependencies": [ + "@xmldom/xmldom" + ], + "dependencies": { + "@xmldom/xmldom": "^0.8.8" + }, + "bin": { + "pdf2json": "bin/pdf2json.js" + }, + "engines": { + "node": ">=18.12.1", + "npm": ">=8.19.2" + } + }, + "node_modules/pdf2json/node_modules/@xmldom/xmldom": { + "version": "0.8.8", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/pg": { + "version": "8.11.5", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz", + "integrity": "sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==", + "dependencies": { + "pg-connection-string": "^2.6.4", + "pg-pool": "^3.6.2", + "pg-protocol": "^1.6.1", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-pool": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz", + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" + }, + "node_modules/pg-types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.1.0", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pg/node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/pgvector": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/pgvector/-/pgvector-0.1.8.tgz", + "integrity": "sha512-mD6aw+XYJrsuLl3Y8s8gHDDfOZQ9ERtfQPdhvjOrC7eOTM7b6sNkxeZxBhHwUdXMfHmyGWIbwU0QbmSnn7pPmg==", + "engines": { + "node": ">= 12" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -6246,6 +8376,19 @@ "pathe": "^1.1.0" } }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "node_modules/portkey-ai": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/portkey-ai/-/portkey-ai-0.1.16.tgz", + "integrity": "sha512-EY4FRp6PZSD75Q1o1qc08DfPNTG9FnkUPN3Z1/lEvaq9iFpSO5UekcagUZaKSVhao311qjBjns+kF0rS9ht7iA==", + "dependencies": { + "agentkeepalive": "^4.5.0" + } + }, "node_modules/postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -6280,6 +8423,46 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postgres-date": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-range": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" + }, "node_modules/posthtml": { "version": "0.16.6", "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", @@ -6329,6 +8512,65 @@ "node": ">=12" } }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6391,6 +8633,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "peer": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/protobufjs": { "version": "6.11.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", @@ -6416,15 +8672,52 @@ "pbts": "bin/pbts" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } }, + "node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6445,6 +8738,88 @@ } ] }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/rake-modified": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/rake-modified/-/rake-modified-1.0.8.tgz", + "integrity": "sha512-rj/1t+EyI8Ly52eaCeSy5hoNpdNnDlNQ/+jll2DypR6nkuxotMbaupzwbuMSaXzuSL1I2pYVYy7oPus/Ls49ag==", + "dependencies": { + "fs-promise": "^2.0.0", + "lodash": "^4.17.4" + } + }, + "node_modules/ranges-apply": { + "version": "7.0.16", + "resolved": "https://registry.npmjs.org/ranges-apply/-/ranges-apply-7.0.16.tgz", + "integrity": "sha512-4rGJHOyA7qatiMDg3vcETkc/TVBPU86/xZRTXff6o7a2neYLmj0EXUUAlhLVuiWAzTPHDPHOQxtk8EDrIF4ohg==", + "dependencies": { + "ranges-merge": "^9.0.15", + "tiny-invariant": "^1.3.3" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ranges-merge": { + "version": "9.0.15", + "resolved": "https://registry.npmjs.org/ranges-merge/-/ranges-merge-9.0.15.tgz", + "integrity": "sha512-hvt4hx0FKIaVfjd1oKx0poL57ljxdL2KHC6bXBrAdsx2iCsH+x7nO/5J0k2veM/isnOcFZKp0ZKkiCjCtzy74Q==", + "dependencies": { + "ranges-push": "^7.0.15", + "ranges-sort": "^6.0.11" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ranges-push": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/ranges-push/-/ranges-push-7.0.15.tgz", + "integrity": "sha512-gXpBYQ5Umf3uG6jkJnw5ddok2Xfo5p22rAJBLrqzNKa7qkj3q5AOCoxfRPXEHUVaJutfXc9K9eGXdIzdyQKPkw==", + "dependencies": { + "codsen-utils": "^1.6.4", + "ranges-sort": "^6.0.11", + "string-collapse-leading-whitespace": "^7.0.7", + "string-trim-spaces-only": "^5.0.10" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ranges-sort": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/ranges-sort/-/ranges-sort-6.0.11.tgz", + "integrity": "sha512-fhNEG0vGi7bESitNNqNBAfYPdl2efB+1paFlI8BQDCNkruERKuuhG8LkQClDIVqUJLkrmKuOSPQ3xZHqVnVo3Q==", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-error-overlay": { "version": "6.0.9", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", @@ -6493,6 +8868,19 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6503,6 +8891,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6573,6 +8966,15 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "optional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6605,11 +9007,15 @@ "node": ">=10" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -6620,6 +9026,74 @@ "node": ">=10" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/sharp/node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/sharp/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sharp/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6653,12 +9127,72 @@ "vscode-textmate": "^8.0.0" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -6699,6 +9233,27 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/srcset": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", @@ -6738,6 +9293,18 @@ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "dev": true }, + "node_modules/streamx": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", + "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6746,6 +9313,51 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-collapse-leading-whitespace": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/string-collapse-leading-whitespace/-/string-collapse-leading-whitespace-7.0.7.tgz", + "integrity": "sha512-jF9eynJoE6ezTCdYI8Qb02/ij/DlU9ItG93Dty4SWfJeLFrotOr+wH9IRiWHTqO3mjCyqBWEiU3uSTIbxYbAEQ==", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/string-left-right": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/string-left-right/-/string-left-right-6.0.17.tgz", + "integrity": "sha512-nuyIV4D4ivnwT64E0TudmCRg52NfkumuEUilyoOrHb/Z2wEOF5I+9SI6P+veFKqWKZfGpAs6OqKe4nAjujARyw==", + "dependencies": { + "codsen-utils": "^1.6.4", + "rfdc": "^1.3.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/string-strip-html": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/string-strip-html/-/string-strip-html-13.4.8.tgz", + "integrity": "sha512-vlcRAtx5DN6zXGUx3EYGFg0/JOQWM65mqLgDaBHviQPP+ovUFzqZ30iQ+674JHWr9wNgnzFGxx9TGipPZMnZXg==", + "dependencies": { + "@types/lodash-es": "^4.17.12", + "codsen-utils": "^1.6.4", + "html-entities": "^2.5.2", + "lodash-es": "^4.17.21", + "ranges-apply": "^7.0.16", + "ranges-push": "^7.0.15", + "string-left-right": "^6.0.17" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/string-trim-spaces-only": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/string-trim-spaces-only/-/string-trim-spaces-only-5.0.10.tgz", + "integrity": "sha512-MhmjE5jNqb1Ylo+BARPRlsdChGLrnPpAUWrT1VOxo9WhWwKVUU6CbZTfjwKaQPYTGS/wsX/4Zek88FM2rEb5iA==", + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6855,6 +9467,29 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tar-fs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.5.tgz", + "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", @@ -6892,12 +9527,44 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/timsort": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", "dev": true }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, "node_modules/tinybench": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", @@ -6922,6 +9589,19 @@ "node": ">=14.0.0" } }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6943,6 +9623,31 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/triple-beam": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", @@ -6966,8 +9671,18 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } }, "node_modules/type-check": { "version": "0.4.0", @@ -6990,6 +9705,14 @@ "node": ">=4" } }, + "node_modules/typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "optionalDependencies": { + "rxjs": "*" + } + }, "node_modules/typedoc": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.12.tgz", @@ -7200,7 +9923,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7228,11 +9950,35 @@ "node": ">=0.8.0" } }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -7267,11 +10013,24 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7298,6 +10057,14 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/uuidv7": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/uuidv7/-/uuidv7-0.6.3.tgz", + "integrity": "sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==", + "bin": { + "uuidv7": "cli.js" + } + }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -7606,6 +10373,39 @@ "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", "dev": true }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7637,6 +10437,23 @@ "node": ">=8" } }, + "node_modules/wikipedia": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/wikipedia/-/wikipedia-2.1.2.tgz", + "integrity": "sha512-RAYaMpXC9/E873RaSEtlEa8dXK4e0p5k98GKOd210MtkE5emm6fcnwD+N6ZA4cuffjDWagvhaQKtp/mGp2BOVQ==", + "dependencies": { + "axios": "^1.4.0", + "infobox-parser": "^3.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wink-nlp": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/wink-nlp/-/wink-nlp-1.14.3.tgz", + "integrity": "sha512-lvY5iCs3T8I34F8WKS70+2P0U9dWLn3vdPf/Z+m2VK14N7OmqnPzmHfh3moHdusajoQ37Em39z0IZB9K4x/96A==" + }, "node_modules/winston": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", @@ -7696,8 +10513,43 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } }, "node_modules/y18n": { "version": "5.0.8", @@ -7710,8 +10562,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.7.2", diff --git a/package.json b/package.json index 075c79f..b14cb60 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", "@types/node": "^20.11.16", + "@types/tmp": "^0.2.6", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", @@ -64,6 +65,7 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", + "@llamaindex/edge": "^0.2.10", "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", @@ -74,6 +76,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "safe-flat": "^2.1.0", + "tmp": "^0.2.3", "uuid": "^9.0.1", "winston": "^3.11.0", "zod": "^3.22.4" diff --git a/src/rag/utils.ts b/src/rag/utils.ts new file mode 100644 index 0000000..0913c8b --- /dev/null +++ b/src/rag/utils.ts @@ -0,0 +1,169 @@ +import { SimpleDirectoryReader } from "@llamaindex/edge/readers/SimpleDirectoryReader"; +import { DocxReader } from "@llamaindex/edge/readers/DocxReader"; +import { PDFReader } from "@llamaindex/edge/readers/PdfReader"; +import { TextFileReader } from "@llamaindex/edge/readers/TextFileReader"; +import { SentenceSplitter } from "@llamaindex/edge"; +import axios from "axios"; +import tmp from "tmp"; +import * as fs from "fs"; + +interface Message { + role: string; + content: string; +} + +// Custom type for the function response +type DownloadResponse = { + filePath: string; + mimeType?: string; +}; + +// Function to download a file and store it in a temporary file, and return MIME type +async function downloadFileToTemp(url: string): Promise { + try { + // Create a temporary file + const tempFile = tmp.fileSync({ postfix: ".tmp" }); + console.log(`Temporary file created at: ${tempFile.name}`); + + // Fetch the file using axios + const response = await axios({ + method: "get", + url: url, + responseType: "stream", + }); + + const mimeType = response?.headers?.["Content-Type"] + ?.toString() + ?.toLowerCase(); + + // Stream the file content to the temporary file + response.data.pipe(fs.createWriteStream(tempFile.name)); + + return new Promise((resolve, reject) => { + response.data.on("end", () => { + resolve({ filePath: tempFile.name, mimeType }); + }); + + response.data.on("error", (err: Error) => { + // Clean up the temporary file in case of an error + tempFile.removeCallback(); + reject(err); + }); + }); + } catch (error) { + throw new Error(`Failed to download the file: ${error}`); + } +} + +export function convertMessagesToStr(messages: Message[]): string { + let finalStr = ""; + for (const msg of messages) { + if ("role" in msg && "content" in msg) { + const role = msg.role || ""; + const content = msg.content || ""; + finalStr += `\n\n${role}: ${content}`; + } + } + return finalStr; +} + +export function formatAssistantMessage(rawText: string): Message { + return { role: "assistant", content: rawText }; +} + +interface DocumentType { + text: string; +} + +export async function loadDocuments({ + filePath, + folderPath, + url, +}: { + filePath?: string; + folderPath?: string; + url?: string; +}): Promise { + if (!filePath && !folderPath && !url) { + throw new Error("No input source provided."); + } + + // Load document from file + if (filePath) { + const fileExtension = filePath.slice(filePath.lastIndexOf(".")); + switch (fileExtension) { + case ".pdf": + return await new PDFReader().loadData(filePath); + case ".docx": + return await new DocxReader().loadData(filePath); + case ".txt": + return await new TextFileReader().loadData(filePath); + default: + throw new Error( + "Unsupported file type. Only .pdf, .docx, and .txt files are supported.", + ); + } + } + + // Load all documents from a folder + if (folderPath) { + const reader = new SimpleDirectoryReader(); + return await reader.loadData({ + directoryPath: folderPath, + fileExtToReader: { + pdf: new PDFReader(), + docx: new DocxReader(), + txt: new TextFileReader(), + }, + }); + } + + // Load document from a URL + if (url) { + const downloadResponse = await downloadFileToTemp(url); + let { mimeType: contentType } = downloadResponse; + const { filePath } = downloadResponse; + + if (!contentType) { + contentType = url.split(".").pop()?.toLowerCase() ?? ""; + } + + if (contentType === "txt" || /text\/plain/.test(contentType)) { + return await new TextFileReader().loadData(filePath); + } else if ( + contentType === "docx" || + /application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document/.test( + contentType, + ) + ) { + return await new DocxReader().loadData(filePath); + } else if (contentType === "pdf" || /application\/pdf/.test(contentType)) { + return await new PDFReader().loadData(filePath); + } + } + + throw new Error("No documents loaded."); +} + +export function splitDocument({ + text, + chunkSize, + chunkOverlap, + options = {}, +}: { + text: string; + chunkSize: number; + chunkOverlap: number; + options?: Omit< + NonNullable[0]>, + "chunkSize" | "chunkOverlap" + >; +}): string[] { + const textParser = new SentenceSplitter({ + ...options, + chunkSize, + chunkOverlap, + }); + const textChunks = textParser.splitText(text); + return textChunks; +} diff --git a/tsconfig.json b/tsconfig.json index ce6c785..cf432ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,7 @@ "noUnusedParameters": true, // Report errors on unused parameters /* Module Resolution Options */ - "moduleResolution": "node", // Choose the module resolution strategy + "moduleResolution": "Bundler", // Choose the module resolution strategy "resolveJsonModule": true, // Include modules imported with '.json' extension "typeRoots": ["node_modules/@types", "tests/types"], // List of folders to include type definitions }, From 41ffd5e06a4285554eff6654e0ac7b2a80a2faad Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 24 Apr 2024 16:16:11 +0530 Subject: [PATCH 20/41] feat: setup chat method --- src/client/rag.ts | 201 +++++++++++++++++++++++++--------------------- src/rag/utils.ts | 8 +- 2 files changed, 110 insertions(+), 99 deletions(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index 7292583..b740852 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -3,20 +3,14 @@ import { App, AuthAppConfig } from "./app"; import { Workflow } from "./workflow"; import * as fs from "fs"; import yaml from "js-yaml"; -import { resources_pb2 } from "clarifai_grpc"; import { JavaScriptValue, Struct, } from "google-protobuf/google/protobuf/struct_pb"; -import { Inputs } from "clarifai"; import { Model } from "./model"; import { User } from "./user"; import { MAX_UPLOAD_BATCH_SIZE } from "../constants/rag"; import { UserError } from "../errors"; -import { convert_messages_to_str } from "clarifai"; -import { format_assistant_message } from "clarifai"; -import { load_documents } from "clarifai"; -import { split_document } from "clarifai"; import { AuthConfig } from "../utils/types"; import { ClarifaiAppUrl, ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; import { @@ -24,6 +18,14 @@ import { OutputInfo, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; import { validateWorkflow } from "../workflows/validate"; +import { + Message, + convertMessagesToStr, + formatAssistantMessage, + loadDocuments, + splitDocument, +} from "../rag/utils"; +import { Input } from "./input"; const DEFAULT_RAG_PROMPT_TEMPLATE = "Context information is below:\n{data.hits}\nGiven the context information and not prior knowledge, answer the query.\nQuery: {data.text.raw}\nAnswer: "; @@ -50,6 +52,7 @@ type workflowSchema = ReturnType; export class RAG { private promptWorkflow: Workflow; private app: App; + private authConfig: AuthConfig; private chatStateId: string; @@ -59,6 +62,9 @@ export class RAG { "Only one of workflowUrl or workflow can be specified.", ); } + if (!workflowUrl && !workflow) { + throw new UserError("One of workflowUrl or workflow must be specified."); + } if (workflowUrl) { if (authConfig.userId || authConfig.appId) { throw UserError( @@ -72,13 +78,11 @@ export class RAG { url: workflowUrl, authConfig: authConfig as UrlAuthConfig, }); + authConfig.appId = appId; + authConfig.userId = userId; this.promptWorkflow = w; this.app = new App({ - authConfig: { - ...authConfig, - userId, - appId, - } as AuthConfig, + authConfig: authConfig as AuthConfig, }); } else if (workflow) { this.promptWorkflow = workflow; @@ -86,6 +90,7 @@ export class RAG { authConfig: authConfig as AuthConfig, }); } + this.authConfig = authConfig as AuthConfig; } static async setup({ @@ -241,7 +246,7 @@ export class RAG { return new RAG({ workflow }); } - upload({ + async upload({ filePath, folderPath, url, @@ -259,7 +264,7 @@ export class RAG { chunkOverlap?: number; datasetId?: string; metadata?: Record; - }): void { + }): Promise { if (batchSize > MAX_UPLOAD_BATCH_SIZE) { throw new UserError( `batch_size cannot be greater than ${MAX_UPLOAD_BATCH_SIZE}`, @@ -276,122 +281,132 @@ export class RAG { ); } - const documents = load_documents({ - file_path: filePath, - folder_path: folderPath, + const documents = await loadDocuments({ + filePath, + folderPath, url, }); - const text_chunks: string[] = []; - const metadata_list: object[] = []; + const textChunks: string[] = []; + const metadataList: Array> = []; + let docI = 0; for (const doc of documents) { - let doc_i = 0; - const cur_text_chunks = split_document({ + const curTextChunks = splitDocument({ text: doc.text, - chunk_size: chunkSize, - chunk_overlap: chunkOverlap, - ...kwargs, + chunkSize, + chunkOverlap, }); - text_chunks.push(...cur_text_chunks); - metadata_list.push(...Array(cur_text_chunks.length).fill(doc.metadata)); - if (text_chunks.length > batchSize) { - for (let idx = 0; idx < text_chunks.length; idx += batchSize) { - if (idx + batchSize > text_chunks.length) { + textChunks.push(...curTextChunks); + metadataList.push(...Array(curTextChunks.length).fill(doc.metadata)); + if (textChunks.length > batchSize) { + for (let idx = 0; idx < textChunks.length; idx += batchSize) { + if (idx + batchSize > textChunks.length) { continue; } - const batch_texts = text_chunks.slice(idx, idx + batchSize); - const batch_ids = Array(batchSize) + const batchTexts = textChunks.slice(idx, idx + batchSize); + const batchIds = Array(batchSize) .fill(null) .map(() => uuidv4()); - const batch_metadatas = metadata_list.slice(idx, idx + batchSize); - const meta_list = batch_metadatas.map((meta: any) => { - const meta_struct = new Struct(); - meta_struct.update(meta); - meta_struct.update({ doc_chunk_no: doc_i }); - if (metadata && typeof metadata === "object") { - meta_struct.update(metadata); - } - doc_i += 1; - return meta_struct; + const batchMetadatas = metadataList.slice(idx, idx + batchSize); + const metaList = batchMetadatas.map((meta) => { + const metaStruct = { + ...(meta ? meta : {}), + ...(metadata && typeof metadata === "object" ? metadata : {}), + docChunkNo: docI, + }; + docI += 1; + return metaStruct; }); - const input_batch = batch_texts.map((text: string, i: number) => { - return this.app.inputs().get_text_input({ - input_id: batch_ids[i], - raw_text: text, - dataset_id: datasetId, - metadata: meta_list[i], + const inputBatch = batchTexts.map((text: string, i: number) => { + return Input.getTextInput({ + inputId: batchIds[i], + rawText: text, + datasetId: datasetId, + metadata: metaList[i], }); }); - this.app.inputs().upload_inputs({ inputs: input_batch }); - text_chunks.splice(idx, batchSize); - metadata_list.splice(idx, batchSize); + await new Input({ authConfig: this.authConfig }).uploadInputs({ + inputs: inputBatch, + }); + textChunks.splice(idx, batchSize); + metadataList.splice(idx, batchSize); } } } - if (text_chunks.length > 0) { - const batch_size = text_chunks.length; - const batch_ids = Array(batch_size) + if (textChunks.length > 0) { + const batchSize = textChunks.length; + const batchIds = Array(batchSize) .fill(null) .map(() => uuidv4()); - const batch_metadatas = metadata_list.slice(0, batch_size); - const meta_list = batch_metadatas.map((meta: any) => { - const meta_struct = new Struct(); - meta_struct.update(meta); - meta_struct.update({ doc_chunk_no: doc_i }); - if (metadata && typeof metadata === "object") { - meta_struct.update(metadata); - } - doc_i += 1; - return meta_struct; + const batchMetadatas = metadataList.slice(0, batchSize); + const metaList = batchMetadatas.map((meta) => { + const metaStruct = { + ...meta, + ...(metadata && typeof metadata === "object" ? metadata : {}), + docChunkNo: docI, + }; + docI += 1; + return metaStruct; }); - const input_batch = text_chunks.map((text: string, i: number) => { - return this.app.inputs().get_text_input({ - input_id: batch_ids[i], - raw_text: text, - dataset_id: datasetId, - metadata: meta_list[i], + const input_batch = textChunks.map((text: string, i: number) => { + return Input.getTextInput({ + inputId: batchIds[i], + rawText: text, + datasetId: datasetId, + metadata: metaList[i], }); }); - this.app.inputs().upload_inputs({ inputs: input_batch }); - text_chunks.splice(0, batch_size); - metadata_list.splice(0, batch_size); + await new Input({ authConfig: this.authConfig }).uploadInputs({ + inputs: input_batch, + }); + textChunks.splice(0, batchSize); + metadataList.splice(0, batchSize); } } - chat( - messages: { role: string; content: string }[], - client_manage_state: boolean = false, - ): { role: string; content: string }[] { - if (client_manage_state) { - const single_prompt = convert_messages_to_str(messages); - const input_proto = Inputs._get_proto("", "", { - text_pb: new resources_pb2.Text({ raw: single_prompt }), + async chat({ + messages, + clientManageState = false, + }: { + messages: Message[]; + clientManageState?: boolean; + }): Promise { + if (clientManageState) { + const singlePrompt = convertMessagesToStr(messages); + const inputProto = Input.getTextInput({ + inputId: uuidv4(), + rawText: singlePrompt, }); - const response = this.promptWorkflow.predict([input_proto]); - messages.push( - format_assistant_message(response.results[0].outputs[-1].data.text.raw), - ); + const response = await this.promptWorkflow.predict({ + inputs: [inputProto], + }); + const outputsList = response.resultsList?.[0]?.outputsList; + const output = outputsList[outputsList.length - 1]; + messages.push(formatAssistantMessage(output?.data?.text?.raw ?? "")); return messages; } + // Server side chat state management const message = messages[messages.length - 1].content; - if (message.length === 0) { + if (!message.length) { throw new UserError("Empty message supplied."); } - const chat_state_id = RAG.chatStateId !== null ? RAG.chatStateId : "init"; - const input_proto = Inputs._get_proto("", "", { - text_pb: new resources_pb2.Text({ raw: message }), + const chatStateId = this.chatStateId !== null ? this.chatStateId : "init"; + const inputProto = Input.getTextInput({ + inputId: uuidv4(), + rawText: message, }); - const response = this.promptWorkflow.predict([input_proto], { - workflow_state_id: chat_state_id, + const response = await this.promptWorkflow.predict({ + inputs: [inputProto], + workflowStateId: chatStateId, }); - RAG.chatStateId = response.workflow_state.id; - return [ - format_assistant_message(response.results[0].outputs[-1].data.text.raw), - ]; + this.chatStateId = response.workflowState?.id ?? ""; + const outputsList = response.resultsList?.[0]?.outputsList; + const output = outputsList[outputsList.length - 1]; + return [formatAssistantMessage(output?.data?.text?.raw ?? "")]; } } diff --git a/src/rag/utils.ts b/src/rag/utils.ts index 0913c8b..de78163 100644 --- a/src/rag/utils.ts +++ b/src/rag/utils.ts @@ -7,7 +7,7 @@ import axios from "axios"; import tmp from "tmp"; import * as fs from "fs"; -interface Message { +export interface Message { role: string; content: string; } @@ -71,10 +71,6 @@ export function formatAssistantMessage(rawText: string): Message { return { role: "assistant", content: rawText }; } -interface DocumentType { - text: string; -} - export async function loadDocuments({ filePath, folderPath, @@ -83,7 +79,7 @@ export async function loadDocuments({ filePath?: string; folderPath?: string; url?: string; -}): Promise { +}) { if (!filePath && !folderPath && !url) { throw new Error("No input source provided."); } From 0dad81b08e26291ec48a125c6b4e29b9fe1b9976 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 24 Apr 2024 16:18:05 +0530 Subject: [PATCH 21/41] fix: lint issues --- src/client/rag.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index b740852..2ab77d7 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -50,11 +50,12 @@ type RAGConfig = type workflowSchema = ReturnType; export class RAG { - private promptWorkflow: Workflow; - private app: App; private authConfig: AuthConfig; - private chatStateId: string; + private chatStateId: string = ""; + + // @ts-expect-error - prompt workflow is definitely assigned in the constructor + private promptWorkflow: Workflow; constructor({ workflowUrl, workflow, authConfig = {} }: RAGConfig) { if (workflowUrl && workflow) { @@ -67,7 +68,7 @@ export class RAG { } if (workflowUrl) { if (authConfig.userId || authConfig.appId) { - throw UserError( + throw new UserError( "userId and appId should not be specified in authConfig when using workflowUrl.", ); } @@ -81,14 +82,8 @@ export class RAG { authConfig.appId = appId; authConfig.userId = userId; this.promptWorkflow = w; - this.app = new App({ - authConfig: authConfig as AuthConfig, - }); } else if (workflow) { this.promptWorkflow = workflow; - this.app = new App({ - authConfig: authConfig as AuthConfig, - }); } this.authConfig = authConfig as AuthConfig; } From 23574af67c75402757b6f6117e3466fed11bfc5d Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 29 Apr 2024 20:18:43 +0530 Subject: [PATCH 22/41] feat: setup rag with tests --- .gitignore | 3 + src/client/app.ts | 46 +++++-- src/client/auth/helper.ts | 30 +++++ src/client/model.ts | 106 ++++++++++++---- src/client/rag.ts | 177 ++++++++++++++++----------- src/client/workflow.ts | 7 +- src/workflows/utils.ts | 4 +- tests/client/rag.integration.test.ts | 93 ++++++++++++++ 8 files changed, 353 insertions(+), 113 deletions(-) create mode 100644 tests/client/rag.integration.test.ts diff --git a/.gitignore b/.gitignore index 6589e97..bb94431 100644 --- a/.gitignore +++ b/.gitignore @@ -356,3 +356,6 @@ example/* # Test outputs tests/client/workflow/export_general.yml + +# Default workflow file path +prompter_wf.yaml diff --git a/src/client/app.ts b/src/client/app.ts index 4ef27ca..3002319 100644 --- a/src/client/app.ts +++ b/src/client/app.ts @@ -36,6 +36,7 @@ import { Dataset, WorkflowNode, ModelVersion, + UserAppIDSet, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; import { TRAINABLE_MODEL_TYPES } from "../constants/model"; import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; @@ -83,6 +84,7 @@ export type CreateModelParam = Omit, "id">; */ export class App extends Lister { private appInfo: GrpcApp; + public info: GrpcApp.AsObject; /** * Initializes an App object. @@ -115,6 +117,7 @@ export class App extends Lister { this.appInfo = new GrpcApp(); this.appInfo.setUserId(authConfig.userId!); this.appInfo.setId(authConfig.appId!); + this.info = this.appInfo.toObject(); } /** @@ -565,6 +568,13 @@ export class App extends Lister { const model = await this.model({ modelId: node.model.modelId, modelVersionId: node.model.modelVersionId ?? "", + modelUserAppId: + node.model.userId && node.model.appId + ? { + userId: node.model.userId, + appId: node.model.appId, + } + : undefined, }); modelObject = model; if (model) { @@ -573,10 +583,7 @@ export class App extends Lister { } catch (e) { // model doesn't exist, create a new model from yaml config if ( - (e as { message?: string })?.message?.includes( - "Model does not exist", - ) && - outputInfo + (e as { message?: string })?.message?.includes("Model does not exist") ) { const { modelId, ...otherParams } = node.model; modelObject = await this.createModel({ @@ -591,11 +598,16 @@ export class App extends Lister { userId: this.userAppId.getUserId(), }, }); - const modelVersion = new ModelVersion().setOutputInfo(outputInfo); - const modelWithVersion = await model.createVersion(modelVersion); - if (modelWithVersion) { - allModels.push(modelWithVersion); - continue; + if (outputInfo) { + const modelVersion = new ModelVersion().setOutputInfo(outputInfo); + const modelWithVersion = await model.createVersion(modelVersion); + if (modelWithVersion) { + allModels.push(modelWithVersion); + continue; + } + } else { + await model.loadInfo(); + allModels.push(model.modelInfo.toObject()); } } } @@ -661,6 +673,7 @@ export class App extends Lister { * * @param modelId - The model ID for the existing model. * @param modelVersionId - Specific version id of the model. + * @param modelUserAppId - The user app ID for the model. * @returns A model object for the specified model ID. * * @includeExample examples/app/model.ts @@ -668,12 +681,25 @@ export class App extends Lister { async model({ modelId, modelVersionId, + modelUserAppId, }: { modelId: string; modelVersionId?: string; + modelUserAppId?: { + userId: string; + appId: string; + }; }): Promise { const request = new GetModelRequest(); - request.setUserAppId(this.userAppId); + if (modelUserAppId) { + request.setUserAppId( + new UserAppIDSet() + .setAppId(modelUserAppId.appId) + .setUserId(modelUserAppId.userId), + ); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(modelId); if (modelVersionId) request.setVersionId(modelVersionId); diff --git a/src/client/auth/helper.ts b/src/client/auth/helper.ts index 5176d0c..68c6cb5 100644 --- a/src/client/auth/helper.ts +++ b/src/client/auth/helper.ts @@ -11,6 +11,16 @@ export interface Cache { const DEFAULT_BASE = "https://api.clarifai.com"; const DEFAULT_UI = "https://clarifai.com"; +const validResourceTypes = [ + "modules", + "models", + "concepts", + "inputs", + "workflows", + "tasks", + "installed_module_versions", +] as const; + // Map from base domain to True / False for whether the base has https or http. const baseHttpsCache: Cache = {}; const uiHttpsCache: Cache = {}; @@ -329,4 +339,24 @@ export class ClarifaiAuthHelper { // Assuming all non-present keys have non-empty values. return true; } + + clarifaiUrl({ + resourceType, + resourceId, + versionId, + }: { + resourceType: (typeof validResourceTypes)[number]; + resourceId: string; + versionId?: string; + }): string { + if (!validResourceTypes.includes(resourceType)) { + throw new Error( + `resourceType must be one of ${validResourceTypes.join(", ")} but was ${resourceType}`, + ); + } + if (!versionId) { + return `${this.base}/${this.userId}/${this.appId}/${resourceType}/${resourceId}`; + } + return `${this.base}/${this.userId}/${this.appId}/${resourceType}/${resourceId}/versions/${versionId}`; + } } diff --git a/src/client/model.ts b/src/client/model.ts index adcfa85..b89e79d 100644 --- a/src/client/model.ts +++ b/src/client/model.ts @@ -19,6 +19,7 @@ import { ModelVersion, OutputConfig, OutputInfo, + UserAppIDSet, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb"; import { @@ -39,6 +40,28 @@ import { Struct, } from "google-protobuf/google/protobuf/struct_pb"; +interface BaseModelConfig { + modelVersion?: { id: string }; + modelUserAppId?: { + userId: string; + appId: string; + }; +} + +interface ModelConfigWithUrl extends BaseModelConfig { + url: ClarifaiUrl; + modelId?: undefined; + authConfig?: Omit; +} + +interface ModelConfigWithModelId extends BaseModelConfig { + url?: undefined; + modelId: string; + authConfig?: AuthConfig; +} + +type ModelConfig = ModelConfigWithUrl | ModelConfigWithModelId; + /** * Model is a class that provides access to Clarifai API endpoints related to Model information. * @noInheritDoc @@ -46,8 +69,9 @@ import { export class Model extends Lister { private appId: string; private id: string; + private modelUserAppId: UserAppIDSet | undefined; private modelVersion: { id: string } | undefined; - private modelInfo: GrpcModel; + public modelInfo: GrpcModel; private trainingParams: Record; /** @@ -68,19 +92,8 @@ export class Model extends Lister { modelId, modelVersion, authConfig = {}, - }: - | { - url: ClarifaiUrl; - modelId?: undefined; - modelVersion?: { id: string }; - authConfig?: AuthConfig; - } - | { - url?: undefined; - modelId: string; - modelVersion?: { id: string }; - authConfig?: AuthConfig; - }) { + modelUserAppId, + }: ModelConfig) { if (url && modelId) { throw new UserError("You can only specify one of url or model_id."); } @@ -89,6 +102,7 @@ export class Model extends Lister { } let modelIdFromUrl; + let authConfigFromUrl: AuthConfig | undefined; if (url) { const [userId, appId, destructuredModelId, modelVersionId] = ClarifaiUrlHelper.splitClarifaiUrl(url); @@ -98,12 +112,15 @@ export class Model extends Lister { } else { modelVersion = { id: modelVersionId }; } - authConfig.userId = userId; - authConfig.appId = appId; + authConfigFromUrl = { + ...(authConfig as Omit), + userId, + appId, + }; } - super({ authConfig: authConfig }); - this.appId = authConfig.appId; + super({ authConfig: authConfigFromUrl || (authConfig as AuthConfig) }); + this.appId = authConfigFromUrl?.appId ?? (authConfig as AuthConfig)?.appId; this.modelVersion = modelVersion; this.id = (modelIdFromUrl || modelId) as string; this.modelInfo = new GrpcModel(); @@ -115,6 +132,11 @@ export class Model extends Lister { if (this.id) this.modelInfo.setId(this.id); if (this.modelVersion) this.modelInfo.setModelVersion(grpcModelVersion); this.trainingParams = {}; + if (modelUserAppId) { + this.modelUserAppId = new UserAppIDSet() + .setAppId(modelUserAppId.appId) + .setUserId(modelUserAppId.userId); + } } /** @@ -127,7 +149,11 @@ export class Model extends Lister { this.STUB.client, ); const request = new GetModelRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(this.id); if (this.modelVersion?.id) request.setVersionId(this.modelVersion.id); @@ -171,7 +197,11 @@ export class Model extends Lister { } const request = new ListModelTypesRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } const listModelTypes = promisifyGrpcCall( this.STUB.client.listModelTypes, @@ -236,7 +266,11 @@ export class Model extends Lister { } const request = new ListModelTypesRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } const listModelTypes = promisifyGrpcCall( this.STUB.client.listModelTypes, @@ -333,7 +367,11 @@ export class Model extends Lister { this.trainingParams?.["train_params"]?.["template"] ?? null; const request = new ListModelTypesRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } const listModelTypes = promisifyGrpcCall( this.STUB.client.listModelTypes, @@ -369,7 +407,11 @@ export class Model extends Lister { */ async deleteVersion(versionId: string): Promise { const request = new DeleteModelVersionRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(this.id); request.setVersionId(versionId); @@ -402,7 +444,11 @@ export class Model extends Lister { } const request = new PostModelVersionsRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(this.id); request.setModelVersionsList([modelVersion]); @@ -442,7 +488,11 @@ export class Model extends Lister { void > { const request = new ListModelVersionsRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(this.id); const listModelVersions = promisifyGrpcCall( @@ -502,7 +552,11 @@ export class Model extends Lister { } const request = new PostModelOutputsRequest(); - request.setUserAppId(this.userAppId); + if (this.modelUserAppId) { + request.setUserAppId(this.modelUserAppId); + } else { + request.setUserAppId(this.userAppId); + } request.setModelId(this.id); if (this.modelVersion && this.modelVersion.id) request.setVersionId(this.modelVersion.id); diff --git a/src/client/rag.ts b/src/client/rag.ts index 2ab77d7..51ce59f 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -26,6 +26,7 @@ import { splitDocument, } from "../rag/utils"; import { Input } from "./input"; +import compact from "lodash/compact"; const DEFAULT_RAG_PROMPT_TEMPLATE = "Context information is below:\n{data.hits}\nGiven the context information and not prior knowledge, answer the query.\nQuery: {data.text.raw}\nAnswer: "; @@ -54,10 +55,11 @@ export class RAG { private chatStateId: string = ""; - // @ts-expect-error - prompt workflow is definitely assigned in the constructor - private promptWorkflow: Workflow; + public promptWorkflow: Workflow; - constructor({ workflowUrl, workflow, authConfig = {} }: RAGConfig) { + public app: App; + + constructor({ workflowUrl, workflow, authConfig }: RAGConfig) { if (workflowUrl && workflow) { throw new UserError( "Only one of workflowUrl or workflow can be specified.", @@ -66,8 +68,9 @@ export class RAG { if (!workflowUrl && !workflow) { throw new UserError("One of workflowUrl or workflow must be specified."); } + const targetAuthConfig: AuthConfig = (authConfig as AuthConfig) ?? {}; if (workflowUrl) { - if (authConfig.userId || authConfig.appId) { + if (authConfig?.userId || authConfig?.appId) { throw new UserError( "userId and appId should not be specified in authConfig when using workflowUrl.", ); @@ -79,13 +82,14 @@ export class RAG { url: workflowUrl, authConfig: authConfig as UrlAuthConfig, }); - authConfig.appId = appId; - authConfig.userId = userId; + targetAuthConfig.appId = appId; + targetAuthConfig.userId = userId; this.promptWorkflow = w; - } else if (workflow) { + } else { this.promptWorkflow = workflow; } - this.authConfig = authConfig as AuthConfig; + this.authConfig = targetAuthConfig; + this.app = new App({ authConfig: this.authConfig }); } static async setup({ @@ -99,7 +103,9 @@ export class RAG { minScore = 0.95, maxResults = 5, }: { - authConfig?: AuthConfig | AuthAppConfig; + authConfig?: + | (Omit & { appId?: undefined }) + | AuthAppConfig; appUrl?: ClarifaiAppUrl; llmUrl?: ClarifaiUrl; baseWorkflow?: string; @@ -108,27 +114,58 @@ export class RAG { workflowId?: string; minScore?: number; maxResults?: number; - }) { - const { userId, appId } = authConfig ?? {}; - const nowTs = Date.now().toString(); - const [, , resourceType, resourceId] = + }): Promise { + const { userId, appId: appIdFromConfig } = authConfig ?? {}; + + // Since user ID & App ID can be generated in different ways, we need to keep track of the generated ones + let targetAppId: string = "", + targetUserId: string = ""; + + if (userId && appUrl) { + throw new UserError("Must provide one of userId or appUrl, not both."); + } + + if (appIdFromConfig && appUrl) { + throw new UserError("Must provide one of appId or appUrl, not both."); + } + + if (!userId && !appUrl) { + throw new UserError( + "userId or appUrl must be provided. The userId can be found at https://clarifai.com/settings.", + ); + } + + const [llmUserId, llmAppId, resourceType, llmId] = ClarifaiUrlHelper.splitClarifaiUrl(llmUrl); + if (resourceType !== "models") { throw new UserError("llmUrl must be a model URL."); } + + const nowTs = Date.now().toString(); + let app: App; + if (userId && !appUrl) { - const user = new User(authConfig as AuthConfig); - const appId = `rag_app_${nowTs}`; - const appObj = await user.createApp({ - appId: appId, + const generatedAppId = `rag_app_${nowTs}`; + + // User ID is present, construct the authconfig using the generated APP ID + const userAuthConfig: AuthConfig = { + ...(authConfig as Omit & { appId?: undefined }), + appId: generatedAppId, + }; + + const user = new User(userAuthConfig); + await user.createApp({ + appId: generatedAppId, baseWorkflow: baseWorkflow, }); - if (authConfig && !authConfig?.appId) authConfig.appId = appObj.id; - if (authConfig && !authConfig?.userId) authConfig.userId = userId; app = new App({ - authConfig: authConfig as AuthConfig, + authConfig: userAuthConfig, }); + + targetAppId = generatedAppId; + targetUserId = userId; } if (!userId && appUrl) { @@ -136,50 +173,39 @@ export class RAG { url: appUrl, authConfig: authConfig as AuthAppConfig, }); - const [userIdFromUrl, appIdFromUrl] = + const [userIdFromAppUrl, appIdFromAppUrl] = ClarifaiUrlHelper.splitClarifaiAppUrl(appUrl); - if (authConfig && !authConfig?.appId) authConfig.appId = appIdFromUrl; - if (authConfig && !authConfig?.userId) authConfig.userId = userIdFromUrl; - // const user = new User({ - // ...(authConfig as AuthAppConfig), - // userId: userIdFromUrl, - // appId: appIdFromUrl, - // }); - } - - if (userId && appUrl) { - throw new UserError("Must provide one of userId or appUrl, not both."); - } - - if (appId && appUrl) { - throw new UserError("Must provide one of appId or appUrl, not both."); - } - - if (!userId && !appUrl) { - throw new UserError( - "userId or appUrl must be provided. The userId can be found at https://clarifai.com/settings.", - ); + targetAppId = appIdFromAppUrl; + targetUserId = userIdFromAppUrl; } - // @ts-expect-error - app has been assigned but not picked up by typescript - const llmObject = await app.model({ modelId: resourceId }); + let targetAuthConfig: AuthConfig; - if (!llmObject) { - throw new UserError("LLM model not found."); + if (authConfig) { + targetAuthConfig = { + ...authConfig, + appId: targetAppId, + userId: targetUserId, + }; + } else { + targetAuthConfig = { + appId: targetAppId, + userId: targetUserId, + pat: process.env.CLARIFAI_PAT!, + }; } const params = Struct.fromJavaScript({ - minScore, - maxResults, - promptTemplate, + min_score: minScore, + max_results: maxResults, + prompt_template: promptTemplate, }); const outputInfo = new OutputInfo().setParams(params); - const modelId = - workflowId !== null - ? `prompter-${workflowId}-${nowTs}` - : `rag-prompter-${nowTs}`; + const modelId = workflowId + ? `prompter-${workflowId}-${nowTs}` + : `rag-prompter-${nowTs}`; // @ts-expect-error - app has been assigned but not picked up by typescript const prompterModelObj = await app.createModel({ @@ -189,14 +215,13 @@ export class RAG { }, }); const prompterModel = new Model({ - authConfig: authConfig as AuthConfig, + authConfig: targetAuthConfig, modelId: prompterModelObj.id, }); - const prompterModelVersion = await prompterModel.createVersion( + const prompterModelWithVersion = await prompterModel.createVersion( new ModelVersion().setOutputInfo(outputInfo), ); - - if (!prompterModelVersion?.id) { + if (!prompterModelWithVersion?.id) { throw new Error("Prompter model version creation failed."); } @@ -208,16 +233,16 @@ export class RAG { { id: "rag-prompter", model: { - modelId: prompterModelObj.id, - modelVersionId: prompterModelVersion.id, + modelId: prompterModelWithVersion.id, + modelVersionId: prompterModelWithVersion?.modelVersion?.id, }, }, { id: "llm", model: { - modelId: llmObject.id, - userId: llmObject.userId, - appId: llmObject.appId, + modelId: llmId, + userId: llmUserId, + appId: llmAppId, }, nodeInputs: [ { @@ -236,9 +261,9 @@ export class RAG { }); const workflow = new Workflow({ workflowId: wf.id, - authConfig: authConfig as AuthConfig, + authConfig: targetAuthConfig, }); - return new RAG({ workflow }); + return new RAG({ workflow, authConfig: targetAuthConfig }); } async upload({ @@ -287,11 +312,13 @@ export class RAG { let docI = 0; for (const doc of documents) { - const curTextChunks = splitDocument({ - text: doc.text, - chunkSize, - chunkOverlap, - }); + const curTextChunks = compact( + splitDocument({ + text: doc.text, + chunkSize, + chunkOverlap, + }), + ); textChunks.push(...curTextChunks); metadataList.push(...Array(curTextChunks.length).fill(doc.metadata)); if (textChunks.length > batchSize) { @@ -345,7 +372,7 @@ export class RAG { docI += 1; return metaStruct; }); - const input_batch = textChunks.map((text: string, i: number) => { + const inputBatch = textChunks.map((text: string, i: number) => { return Input.getTextInput({ inputId: batchIds[i], rawText: text, @@ -354,7 +381,7 @@ export class RAG { }); }); await new Input({ authConfig: this.authConfig }).uploadInputs({ - inputs: input_batch, + inputs: inputBatch, }); textChunks.splice(0, batchSize); metadataList.splice(0, batchSize); @@ -363,11 +390,17 @@ export class RAG { async chat({ messages, - clientManageState = false, + clientManageState = true, // TODO: change to false once Server Side state management is implemented }: { messages: Message[]; clientManageState?: boolean; }): Promise { + if (!clientManageState) { + throw new Error( + "Server side state management is not supported yet - work in progress", + ); + } + if (clientManageState) { const singlePrompt = convertMessagesToStr(messages); const inputProto = Input.getTextInput({ diff --git a/src/client/workflow.ts b/src/client/workflow.ts index 7e05ccc..c0db998 100644 --- a/src/client/workflow.ts +++ b/src/client/workflow.ts @@ -47,7 +47,8 @@ type WorkflowConfig = */ export class Workflow extends Lister { private versionId: string; - private id: string; + public id: string; + public appId: string; private outputConfig: OutputConfig; constructor({ @@ -73,10 +74,10 @@ export class Workflow extends Lister { } super({ authConfig: authConfig as AuthConfig }); - this.id = ""; - if (workflowId) this.id = workflowId; + this.id = workflowId || ""; this.versionId = workflowVersion.id; this.outputConfig = outputConfig; + this.appId = authConfig.appId || process.env.CLARIFAI_APP_ID!; } async predict({ diff --git a/src/workflows/utils.ts b/src/workflows/utils.ts index a05aeaa..a1e264b 100644 --- a/src/workflows/utils.ts +++ b/src/workflows/utils.ts @@ -15,9 +15,9 @@ type YamlModel = Record; export function getYamlOutputInfoProto( yamlModelOutputInfo: YamlModelOutputInfo, -): OutputInfo | null { +): OutputInfo | undefined { if (!yamlModelOutputInfo?.params) { - return null; + return undefined; } return new OutputInfo().setParams( diff --git a/tests/client/rag.integration.test.ts b/tests/client/rag.integration.test.ts new file mode 100644 index 0000000..f4e51e8 --- /dev/null +++ b/tests/client/rag.integration.test.ts @@ -0,0 +1,93 @@ +import { afterAll, beforeAll, describe, it, expect } from "vitest"; +import path from "path"; +import { App, RAG, User } from "../../src/index"; +import { Workflow } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import { ClarifaiAuthHelper } from "../../src/client/auth/helper"; +import { ClarifaiUrl } from "../../src/urls/helper"; + +const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; + +const TEXT_FILE_PATH = path.resolve(__dirname, "../assets/sample.txt"); + +const pat = import.meta.env.VITE_CLARIFAI_PAT; + +const PDF_URL = "https://samples.clarifai.com/test_doc.pdf"; + +describe("Rag", async () => { + let rag: RAG; + let app: App; + let workflow: Workflow.AsObject; + let workflowUrl: string; + beforeAll(async () => { + rag = await RAG.setup({ + authConfig: { + userId: CREATE_APP_USER_ID, + pat, + }, + }); + const promptWorkflowId = rag.promptWorkflow.id; + const promptAppId = rag.promptWorkflow.appId; + app = new App({ + authConfig: { + appId: promptAppId, + userId: CREATE_APP_USER_ID, + pat, + }, + }); + workflow = (await app.workflow({ workflowId: promptWorkflowId }))!; + workflowUrl = new ClarifaiAuthHelper( + workflow.userId, + workflow.appId, + pat, + ).clarifaiUrl({ + resourceId: workflow.id, + resourceType: "workflows", + versionId: workflow.version?.id, + }); + }); + + it("is Setup as expected", () => { + expect(workflow.nodesList.length).toBe(2); + }); + + it("should setup RAG from existing workflow", () => { + const agent = new RAG({ + workflowUrl: workflowUrl as ClarifaiUrl, + authConfig: { + pat, + }, + }); + expect(agent.app.info.id).toBe(app.info.id); + }); + + it("should predict & manage client state", async () => { + const messages = [{ role: "human", content: "What is 1 + 1?" }]; + const newMessages = await rag.chat({ messages, clientManageState: true }); + expect(newMessages.length).toBe(2); + }); + + // TODO: Server side state management is not supported yet - work in progress + it.skip("should predict & manage state on the server", async () => { + const messages = [{ role: "human", content: "What is 1 + 1?" }]; + const newMessages = await rag.chat({ messages }); + expect(newMessages.length).toBe(1); + }); + + it("should upload documents by file path", async () => { + const upload = async () => await rag.upload({ filePath: TEXT_FILE_PATH }); + await expect(upload()).resolves.not.toThrow(); + }); + + it("should upload documents by URL", async () => { + const upload = async () => await rag.upload({ url: PDF_URL }); + await expect(upload()).resolves.not.toThrow(); + }); + + afterAll(async () => { + await new User({ + userId: CREATE_APP_USER_ID, + appId: app.info.id, + pat, + }).deleteApp({ appId: app.info.id }); + }); +}); From d5a53d618a55a680f5261ff99e6fac6169d26780 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 29 Apr 2024 20:24:58 +0530 Subject: [PATCH 23/41] fix: failing tests with url helper --- src/urls/helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/urls/helper.ts b/src/urls/helper.ts index d8d7675..d8f1315 100644 --- a/src/urls/helper.ts +++ b/src/urls/helper.ts @@ -131,7 +131,7 @@ export class ClarifaiUrlHelper { */ static splitClarifaiAppUrl(url: ClarifaiAppUrl): [string, string] { const o = new URL(url); - const [parts] = o.pathname.split("/").filter((part) => part.length > 0); + const parts = o.pathname.split("/").filter((part) => part.length > 0); if (parts.length !== 2) { throw new Error( `Provided url must have 2 parts after the domain name. The current parts are: ${parts}`, From c08107984ad00843ed0d93e4c5c1b6d1bb865753 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 30 Apr 2024 14:01:55 +0530 Subject: [PATCH 24/41] fix: lint issues --- package-lock.json | 262 +++++++++++++++++++++++++--------------------- package.json | 2 +- src/rag/utils.ts | 12 ++- tsconfig.json | 2 +- 4 files changed, 151 insertions(+), 127 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0243978..ae6d573 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", - "@llamaindex/edge": "^0.2.10", "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", @@ -20,6 +19,7 @@ "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", "js-yaml": "^4.1.0", + "llamaindex": "^0.2.13", "lodash": "^4.17.21", "safe-flat": "^2.1.0", "tmp": "^0.2.3", @@ -884,6 +884,16 @@ "node": ">=14" } }, + "node_modules/@google/generative-ai": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.1.3.tgz", + "integrity": "sha512-Cm4uJX1sKarpm1mje/MiOIinM7zdUUrQp/5/qGPAgznbdd/B9zup5ehT6c1qGqycFcSopTA1J1HpqHS5kJR8hQ==", + "optional": true, + "peer": true, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.10.6", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", @@ -1094,113 +1104,6 @@ } } }, - "node_modules/@llamaindex/edge": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@llamaindex/edge/-/edge-0.2.10.tgz", - "integrity": "sha512-Ur3MtUc03ba8Uhk+vmsyM/+MWknk40hGmjIoxXnrI85DXguNTg9qVnHyuZJMM66dNBu/lW+V6UmJGFABqN6dJQ==", - "dependencies": { - "@anthropic-ai/sdk": "^0.20.6", - "@aws-crypto/sha256-js": "^5.2.0", - "@datastax/astra-db-ts": "^1.0.1", - "@grpc/grpc-js": "^1.10.6", - "@llamaindex/cloud": "0.0.5", - "@llamaindex/env": "0.0.7", - "@mistralai/mistralai": "^0.1.3", - "@notionhq/client": "^2.2.15", - "@pinecone-database/pinecone": "^2.2.0", - "@qdrant/js-client-rest": "^1.8.2", - "@types/lodash": "^4.17.0", - "@types/node": "^20.12.7", - "@types/papaparse": "^5.3.14", - "@types/pg": "^8.11.5", - "@xenova/transformers": "^2.17.1", - "@zilliz/milvus2-sdk-node": "^2.4.1", - "ajv": "^8.12.0", - "assemblyai": "^4.4.1", - "chromadb": "~1.7.3", - "cohere-ai": "^7.9.5", - "js-tiktoken": "^1.0.11", - "lodash": "^4.17.21", - "magic-bytes.js": "^1.10.0", - "mammoth": "^1.7.1", - "md-utils-ts": "^2.0.0", - "mongodb": "^6.5.0", - "notion-md-crawler": "^0.0.2", - "openai": "^4.38.0", - "papaparse": "^5.4.1", - "pathe": "^1.1.2", - "pdf2json": "^3.0.5", - "pg": "^8.11.5", - "pgvector": "^0.1.8", - "portkey-ai": "^0.1.16", - "rake-modified": "^1.0.8", - "string-strip-html": "^13.4.8", - "wikipedia": "^2.1.2", - "wink-nlp": "^1.14.3" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@llamaindex/edge/node_modules/@llamaindex/env": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@llamaindex/env/-/env-0.0.7.tgz", - "integrity": "sha512-6j7eGXhSDspz33FzdWJRTbGlXa3osYP/aP9dm10Z7JCxaxyQZmGIWL149HNkGgV4lxiPmGPx7YWjBBj9nRdo2w==", - "dependencies": { - "@types/lodash": "^4.14.202", - "@types/node": "^20.11.20", - "lodash": "^4.17.21" - }, - "peerDependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "pathe": "^1.1.2", - "readable-stream": "^4.5.2" - } - }, - "node_modules/@llamaindex/edge/node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@llamaindex/edge/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@llamaindex/edge/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/@llamaindex/edge/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "peer": true, - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@lmdb/lmdb-darwin-arm64": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz", @@ -3819,9 +3722,9 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dependencies": { "undici-types": "~5.26.4" } @@ -7259,6 +7162,126 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/llamaindex": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/llamaindex/-/llamaindex-0.2.13.tgz", + "integrity": "sha512-su10fCizI5uGjCPAV+J3TwrjuSxUoptmdN/KBv0aQejN/mPY0M4Bmz9Xw4pKRs8hHfwnFLqv6AM8n64H1GqMrg==", + "dependencies": { + "@anthropic-ai/sdk": "^0.20.6", + "@aws-crypto/sha256-js": "^5.2.0", + "@datastax/astra-db-ts": "^1.0.1", + "@google/generative-ai": "^0.8.0", + "@grpc/grpc-js": "^1.10.6", + "@llamaindex/cloud": "0.0.5", + "@llamaindex/env": "0.0.7", + "@mistralai/mistralai": "^0.1.3", + "@pinecone-database/pinecone": "^2.2.0", + "@qdrant/js-client-rest": "^1.8.2", + "@types/lodash": "^4.17.0", + "@types/node": "^20.12.7", + "@types/papaparse": "^5.3.14", + "@types/pg": "^8.11.5", + "@xenova/transformers": "^2.17.1", + "@zilliz/milvus2-sdk-node": "^2.4.1", + "ajv": "^8.12.0", + "assemblyai": "^4.4.1", + "chromadb": "~1.7.3", + "cohere-ai": "^7.9.5", + "js-tiktoken": "^1.0.11", + "lodash": "^4.17.21", + "magic-bytes.js": "^1.10.0", + "mammoth": "^1.7.1", + "md-utils-ts": "^2.0.0", + "mongodb": "^6.5.0", + "notion-md-crawler": "^1.0.0", + "ollama": "^0.5.0", + "openai": "^4.38.0", + "papaparse": "^5.4.1", + "pathe": "^1.1.2", + "pdf2json": "^3.0.5", + "pg": "^8.11.5", + "pgvector": "^0.1.8", + "portkey-ai": "^0.1.16", + "rake-modified": "^1.0.8", + "string-strip-html": "^13.4.8", + "wikipedia": "^2.1.2", + "wink-nlp": "^1.14.3" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@notionhq/client": "^2.2.15" + } + }, + "node_modules/llamaindex/node_modules/@google/generative-ai": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.8.0.tgz", + "integrity": "sha512-O55FgK1Jvl2JuJP1cnRHEAM8A4Lr3yKtjQrCn2QXOXVT+L5+o/nFQcx0/oIo3oq1Kq9TjjgewXyb9BBrK+Wd0A==", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/llamaindex/node_modules/@llamaindex/env": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@llamaindex/env/-/env-0.0.7.tgz", + "integrity": "sha512-6j7eGXhSDspz33FzdWJRTbGlXa3osYP/aP9dm10Z7JCxaxyQZmGIWL149HNkGgV4lxiPmGPx7YWjBBj9nRdo2w==", + "dependencies": { + "@types/lodash": "^4.14.202", + "@types/node": "^20.11.20", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "pathe": "^1.1.2", + "readable-stream": "^4.5.2" + } + }, + "node_modules/llamaindex/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/llamaindex/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/llamaindex/node_modules/notion-md-crawler": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/notion-md-crawler/-/notion-md-crawler-1.0.0.tgz", + "integrity": "sha512-mdB6zn/i32qO2C7X7wZLDpWvFryO3bPYMuBfFgmTPomnfEtIejdQJNVaZzw2GapM82lfWZ5dfsZp3s3UL4p1Fg==", + "dependencies": { + "@notionhq/client": "^2.2.12", + "md-utils-ts": "^2.0.0" + } + }, + "node_modules/llamaindex/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/lmdb": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.8.5.tgz", @@ -7816,15 +7839,6 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, - "node_modules/notion-md-crawler": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/notion-md-crawler/-/notion-md-crawler-0.0.2.tgz", - "integrity": "sha512-lE3/DFMrg7GSbl1sBfDuLVLyxw+yjdarPVm1JGfQ6eONEbNGgO+BdZxpwwZQ1uYeEJurAXMXb/AXT8GKYjKAyg==", - "dependencies": { - "@notionhq/client": "^2.2.12", - "md-utils-ts": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -7872,6 +7886,14 @@ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, + "node_modules/ollama": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.5.0.tgz", + "integrity": "sha512-CRtRzsho210EGdK52GrUMohA2pU+7NbgEaBG3DcYeRmvQthDO7E2LHOkLlUUeaYUlNmEd8icbjC02ug9meSYnw==", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", diff --git a/package.json b/package.json index b14cb60..87fdda3 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "dependencies": { "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", - "@llamaindex/edge": "^0.2.10", "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", @@ -74,6 +73,7 @@ "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", "js-yaml": "^4.1.0", + "llamaindex": "^0.2.13", "lodash": "^4.17.21", "safe-flat": "^2.1.0", "tmp": "^0.2.3", diff --git a/src/rag/utils.ts b/src/rag/utils.ts index de78163..c7ce260 100644 --- a/src/rag/utils.ts +++ b/src/rag/utils.ts @@ -1,8 +1,10 @@ -import { SimpleDirectoryReader } from "@llamaindex/edge/readers/SimpleDirectoryReader"; -import { DocxReader } from "@llamaindex/edge/readers/DocxReader"; -import { PDFReader } from "@llamaindex/edge/readers/PdfReader"; -import { TextFileReader } from "@llamaindex/edge/readers/TextFileReader"; -import { SentenceSplitter } from "@llamaindex/edge"; +import { + SimpleDirectoryReader, + DocxReader, + PDFReader, + TextFileReader, + SentenceSplitter, +} from "llamaindex"; import axios from "axios"; import tmp from "tmp"; import * as fs from "fs"; diff --git a/tsconfig.json b/tsconfig.json index cf432ee..ce6c785 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,7 @@ "noUnusedParameters": true, // Report errors on unused parameters /* Module Resolution Options */ - "moduleResolution": "Bundler", // Choose the module resolution strategy + "moduleResolution": "node", // Choose the module resolution strategy "resolveJsonModule": true, // Include modules imported with '.json' extension "typeRoots": ["node_modules/@types", "tests/types"], // List of folders to include type definitions }, From fd1c824543ae9df1d1b231183bcf0620bd612e77 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 2 May 2024 14:56:46 +0530 Subject: [PATCH 25/41] fix: addressed review comments --- src/client/input.ts | 7 +++---- src/datasets/upload/features.ts | 3 ++- src/utils/misc.ts | 2 +- src/utils/types.ts | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/client/input.ts b/src/client/input.ts index 0aba10f..fdd7f23 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -9,13 +9,12 @@ import { Input as GrpcInput, Image, Point, - Polygon, Region, RegionInfo, Text, Video, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; -import { AuthConfig } from "../utils/types"; +import { AuthConfig, Polygon } from "../utils/types"; import { Lister } from "./lister"; import { Buffer } from "buffer"; import fs from "fs"; @@ -739,9 +738,9 @@ export class Input extends Lister { }: { inputId: string; label: string; - polygons: number[][][]; + polygons: Polygon[]; }): Annotation { - const polygonsSchema = z.array(z.array(z.array(z.number()))); + const polygonsSchema = z.array(z.array(z.tuple([z.number(), z.number()]))); try { polygonsSchema.parse(polygons); } catch { diff --git a/src/datasets/upload/features.ts b/src/datasets/upload/features.ts index 1583ac2..7c5099d 100644 --- a/src/datasets/upload/features.ts +++ b/src/datasets/upload/features.ts @@ -1,4 +1,5 @@ import { JavaScriptValue } from "google-protobuf/google/protobuf/struct_pb"; +import { Polygon } from "../../utils/types"; export interface TextFeatures { imagePath?: undefined; @@ -33,7 +34,7 @@ export interface VisualDetectionFeatures { export interface VisualSegmentationFeatures { imagePath: string; labels: Array; - polygons: Array>>; + polygons: Polygon[]; geoInfo?: [number, number]; id?: number; metadata?: Record; diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 7373bd8..ce83181 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -71,7 +71,7 @@ export function mergeObjects(obj1: AuthConfig, obj2: AuthConfig): AuthConfig { export class BackoffIterator { private count: number; - constructor({ count = 0 }: { count?: number } = { count: 0 }) { + constructor({ count } = { count: 0 }) { this.count = count; } diff --git a/src/utils/types.ts b/src/utils/types.ts index 310a7cd..fb05dc9 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -21,3 +21,6 @@ export type GrpcWithCallback = ( export type PaginationRequestParams> = | Omit, "userAppId" | "pageNo" | "perPage"> | Record; + +export type Point = [number, number]; +export type Polygon = Array; From a95725d26f3e26b146f33bab7591847e88bbe9cf Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 2 May 2024 17:17:18 +0530 Subject: [PATCH 26/41] feat: use event emitter for bulk upload progress --- package-lock.json | 12 +----- package.json | 2 - src/client/dataset.ts | 8 +++- src/client/input.ts | 50 +++++++++++++++++++------ tests/client/search.integration.test.ts | 40 +++++++++++++++++++- vitest.config.mjs | 1 + 6 files changed, 87 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index e8fc8ce..57372ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", - "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", @@ -29,7 +28,6 @@ "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", "@types/async": "^3.2.24", - "@types/cli-progress": "^3.11.5", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", @@ -3271,15 +3269,6 @@ "integrity": "sha512-8iHVLHsCCOBKjCF2KwFe0p9Z3rfM9mL+sSP8btyR5vTjJRAqpBYD28/ZLgXPf0pjG1VxOvtCV/BgXkQbpSe8Hw==", "dev": true }, - "node_modules/@types/cli-progress": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.5.tgz", - "integrity": "sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3996,6 +3985,7 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dev": true, "dependencies": { "string-width": "^4.2.3" }, diff --git a/package.json b/package.json index 075c79f..fc9ab53 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "@parcel/packager-ts": "^2.11.0", "@parcel/transformer-typescript-types": "^2.11.0", "@types/async": "^3.2.24", - "@types/cli-progress": "^3.11.5", "@types/google-protobuf": "^3.15.12", "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.0", @@ -67,7 +66,6 @@ "async": "^3.2.5", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", - "cli-progress": "^3.12.0", "csv-parse": "^5.5.5", "from-protobuf-object": "^1.0.2", "google-protobuf": "^3.21.2", diff --git a/src/client/dataset.ts b/src/client/dataset.ts index 9b99098..80adf01 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -7,7 +7,7 @@ import { UserError } from "../errors"; import { ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper"; import { AuthConfig } from "../utils/types"; import { Lister } from "./lister"; -import { Input } from "./input"; +import { Input, InputBulkUpload } from "./input"; import { DeleteDatasetVersionsRequest, ListDatasetVersionsRequest, @@ -139,11 +139,13 @@ export class Dataset extends Lister { inputType, labels = false, batchSize = this.batchSize, + uploadProgressEmitter, }: { folderPath: string; inputType: "image" | "text"; labels: boolean; batchSize?: number; + uploadProgressEmitter?: InputBulkUpload; }): Promise { if (["image", "text"].indexOf(inputType) === -1) { throw new UserError("Invalid input type"); @@ -166,6 +168,7 @@ export class Dataset extends Lister { await this.input.bulkUpload({ inputs: inputProtos, batchSize: batchSize, + uploadProgressEmitter, }); } @@ -175,12 +178,14 @@ export class Dataset extends Lister { csvType, labels = true, batchSize = 128, + uploadProgressEmitter, }: { csvPath: string; inputType?: "image" | "text" | "video" | "audio"; csvType: "raw" | "url" | "file"; labels?: boolean; batchSize?: number; + uploadProgressEmitter?: InputBulkUpload; }): Promise { if (!["image", "text", "video", "audio"].includes(inputType)) { throw new UserError( @@ -209,6 +214,7 @@ export class Dataset extends Lister { await this.input.bulkUpload({ inputs: inputProtos, batchSize: batchSize, + uploadProgressEmitter, }); } } diff --git a/src/client/input.ts b/src/client/input.ts index fdd7f23..94072a8 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -9,12 +9,13 @@ import { Input as GrpcInput, Image, Point, + Polygon, Region, RegionInfo, Text, Video, } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; -import { AuthConfig, Polygon } from "../utils/types"; +import { AuthConfig, Polygon as PolygonType } from "../utils/types"; import { Lister } from "./lister"; import { Buffer } from "buffer"; import fs from "fs"; @@ -41,9 +42,9 @@ import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/statu import os from "os"; import chunk from "lodash/chunk"; import { Status } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_pb"; -import cliProgress from "cli-progress"; import async from "async"; import { MAX_RETRIES } from "../constants/dataset"; +import { EventEmitter } from "events"; interface CSVRecord { inputid: string; @@ -53,6 +54,29 @@ interface CSVRecord { geopoints: string; } +interface UploadEvents { + start: ProgressEvent; + progress: ProgressEvent; + error: ErrorEvent; + end: ProgressEvent; +} + +interface ProgressEvent { + current: number; + total: number; +} + +interface ErrorEvent { + error: Error; +} + +type BulkUploadEventEmitter = EventEmitter & { + emit(event: K, payload: T[K]): boolean; + on(event: K, listener: (payload: T[K]) => void): this; +}; + +export type InputBulkUpload = BulkUploadEventEmitter; + /** * Inputs is a class that provides access to Clarifai API endpoints related to Input information. * @noInheritDoc @@ -738,7 +762,7 @@ export class Input extends Lister { }: { inputId: string; label: string; - polygons: Polygon[]; + polygons: PolygonType[]; }): Annotation { const polygonsSchema = z.array(z.array(z.tuple([z.number(), z.number()]))); try { @@ -1009,19 +1033,18 @@ export class Input extends Lister { bulkUpload({ inputs, batchSize: providedBatchSize = 128, + uploadProgressEmitter, }: { inputs: GrpcInput[]; batchSize?: number; + uploadProgressEmitter?: InputBulkUpload; }): Promise { const batchSize = Math.min(128, providedBatchSize); const chunkedInputs = chunk(inputs, batchSize); - const progressBar = new cliProgress.SingleBar( - {}, - cliProgress.Presets.shades_classic, - ); - - progressBar.start(chunkedInputs.length, 0); + let currentProgress = 0; + const total = chunkedInputs.length; + uploadProgressEmitter?.emit("start", { current: currentProgress, total }); return new Promise((resolve, reject) => { async.mapLimit( @@ -1033,7 +1056,11 @@ export class Input extends Lister { this.retryUploads({ failedInputs, }).finally(() => { - progressBar.increment(); + currentProgress++; + uploadProgressEmitter?.emit("progress", { + current: currentProgress, + total, + }); callback(null, failedInputs); }); }) @@ -1044,9 +1071,10 @@ export class Input extends Lister { (err) => { if (err) { console.error("Error processing batches", err); + uploadProgressEmitter?.emit("error"); reject(err); } - progressBar.stop(); + uploadProgressEmitter?.emit("end", { current: total, total }); console.log("All inputs processed"); resolve(); }, diff --git a/tests/client/search.integration.test.ts b/tests/client/search.integration.test.ts index 5865a37..5d65274 100644 --- a/tests/client/search.integration.test.ts +++ b/tests/client/search.integration.test.ts @@ -1,9 +1,10 @@ import path from "path"; import { getSchema } from "../../src/schema/search"; import { z } from "zod"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; import { App, Dataset, Input, Search, User } from "../../src/index"; import { Hit } from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"; +import EventEmitter from "events"; const NOW = Date.now().toString() + "-search"; const CREATE_APP_USER_ID = import.meta.env.VITE_CLARIFAI_USER_ID; @@ -197,11 +198,48 @@ describe("Search", () => { }, datasetId: datasetObj.id, }); + const eventEmitter = new EventEmitter(); + const eventHandler = { + start: (...args: unknown[]) => console.log("start", args), + progress: (...args: unknown[]) => console.log("progress", args), + end: (...args: unknown[]) => console.log("end", args), + error: (...args: unknown[]) => console.log("error", args), + }; + const startSpy = vi.spyOn(eventHandler, "start"); + const progressSpy = vi.spyOn(eventHandler, "progress"); + const endSpy = vi.spyOn(eventHandler, "end"); + const errorSpy = vi.spyOn(eventHandler, "error"); + eventEmitter.on("start", (start) => { + eventHandler.start(start); + }); + eventEmitter.on("progress", (progress) => { + eventHandler.progress(progress); + }); + eventEmitter.on("end", (progress) => { + eventHandler.end(progress); + }); + eventEmitter.on("error", (error) => { + eventHandler.error(error); + }); await dataset.uploadFromFolder({ folderPath: DATASET_IMAGES_DIR, inputType: "image", labels: false, + uploadProgressEmitter: eventEmitter, }); + expect(startSpy).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ current: 0, total: 1 }), + ); + expect(progressSpy).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ current: 1, total: 1 }), + ); + expect(endSpy).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ current: 1, total: 1 }), + ); + expect(errorSpy).not.toHaveBeenCalled(); }, 50000); it("should get expected hits for filters", async () => { diff --git a/vitest.config.mjs b/vitest.config.mjs index 2e5e974..a642972 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -5,6 +5,7 @@ export default defineConfig({ test: { coverage: { reporter: ["text", "json", "html", "clover", "json-summary"], + include: ["src/**/*"], }, }, }); From 350171ad81af1f036032bf02159209af5c5aed32 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 2 May 2024 17:22:39 +0530 Subject: [PATCH 27/41] chore: fix lint issues --- src/client/input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/input.ts b/src/client/input.ts index 94072a8..d16e01d 100644 --- a/src/client/input.ts +++ b/src/client/input.ts @@ -72,7 +72,7 @@ interface ErrorEvent { type BulkUploadEventEmitter = EventEmitter & { emit(event: K, payload: T[K]): boolean; - on(event: K, listener: (payload: T[K]) => void): this; + on(event: K, listener: (payload: T[K]) => void): void; }; export type InputBulkUpload = BulkUploadEventEmitter; From 50c5905a3976a6c0461aa50267500ea4750de064 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 2 May 2024 21:45:53 +0530 Subject: [PATCH 28/41] refactor: use array notation for polygon type --- src/utils/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/types.ts b/src/utils/types.ts index fb05dc9..6023b39 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -23,4 +23,4 @@ export type PaginationRequestParams> = | Record; export type Point = [number, number]; -export type Polygon = Array; +export type Polygon = Point[]; From f2de443d80473c87c03ed7b26b9baca75aac2725 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 3 May 2024 13:34:10 +0530 Subject: [PATCH 29/41] chore: remove unused server state management code --- src/client/rag.ts | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index 51ce59f..82abfb0 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -401,40 +401,17 @@ export class RAG { ); } - if (clientManageState) { - const singlePrompt = convertMessagesToStr(messages); - const inputProto = Input.getTextInput({ - inputId: uuidv4(), - rawText: singlePrompt, - }); - const response = await this.promptWorkflow.predict({ - inputs: [inputProto], - }); - const outputsList = response.resultsList?.[0]?.outputsList; - const output = outputsList[outputsList.length - 1]; - messages.push(formatAssistantMessage(output?.data?.text?.raw ?? "")); - return messages; - } - - // Server side chat state management - const message = messages[messages.length - 1].content; - if (!message.length) { - throw new UserError("Empty message supplied."); - } - - const chatStateId = this.chatStateId !== null ? this.chatStateId : "init"; + const singlePrompt = convertMessagesToStr(messages); const inputProto = Input.getTextInput({ inputId: uuidv4(), - rawText: message, + rawText: singlePrompt, }); const response = await this.promptWorkflow.predict({ inputs: [inputProto], - workflowStateId: chatStateId, }); - - this.chatStateId = response.workflowState?.id ?? ""; const outputsList = response.resultsList?.[0]?.outputsList; const output = outputsList[outputsList.length - 1]; - return [formatAssistantMessage(output?.data?.text?.raw ?? "")]; + messages.push(formatAssistantMessage(output?.data?.text?.raw ?? "")); + return messages; } } From 1e598987dc3afafffe9458bc7d65fc930b0e847a Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 3 May 2024 13:35:49 +0530 Subject: [PATCH 30/41] fix: increase client state test timeout --- tests/client/rag.integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/rag.integration.test.ts b/tests/client/rag.integration.test.ts index f4e51e8..6b4838d 100644 --- a/tests/client/rag.integration.test.ts +++ b/tests/client/rag.integration.test.ts @@ -64,7 +64,7 @@ describe("Rag", async () => { const messages = [{ role: "human", content: "What is 1 + 1?" }]; const newMessages = await rag.chat({ messages, clientManageState: true }); expect(newMessages.length).toBe(2); - }); + }, 10000); // TODO: Server side state management is not supported yet - work in progress it.skip("should predict & manage state on the server", async () => { From 3948e4ed3d1f2b1fb2a4d0167b9a4df98479d589 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Fri, 3 May 2024 13:37:41 +0530 Subject: [PATCH 31/41] fix: lint issues --- src/client/rag.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index 82abfb0..da87b14 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -53,8 +53,6 @@ type workflowSchema = ReturnType; export class RAG { private authConfig: AuthConfig; - private chatStateId: string = ""; - public promptWorkflow: Workflow; public app: App; From 575d6fc564e8004cb96efc4e0505938cbe9885a8 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 13 May 2024 13:19:08 +0530 Subject: [PATCH 32/41] fix: based on doc examples --- src/client/dataset.ts | 2 +- src/client/model.ts | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/client/dataset.ts b/src/client/dataset.ts index 80adf01..b0ad659 100644 --- a/src/client/dataset.ts +++ b/src/client/dataset.ts @@ -143,7 +143,7 @@ export class Dataset extends Lister { }: { folderPath: string; inputType: "image" | "text"; - labels: boolean; + labels?: boolean; batchSize?: number; uploadProgressEmitter?: InputBulkUpload; }): Promise { diff --git a/src/client/model.ts b/src/client/model.ts index b89e79d..d01c889 100644 --- a/src/client/model.ts +++ b/src/client/model.ts @@ -42,22 +42,23 @@ import { interface BaseModelConfig { modelVersion?: { id: string }; - modelUserAppId?: { - userId: string; - appId: string; - }; } interface ModelConfigWithUrl extends BaseModelConfig { url: ClarifaiUrl; modelId?: undefined; authConfig?: Omit; + modelUserAppId?: undefined; } interface ModelConfigWithModelId extends BaseModelConfig { url?: undefined; modelId: string; authConfig?: AuthConfig; + modelUserAppId?: { + userId: string; + appId: string; + }; } type ModelConfig = ModelConfigWithUrl | ModelConfigWithModelId; @@ -137,6 +138,11 @@ export class Model extends Lister { .setAppId(modelUserAppId.appId) .setUserId(modelUserAppId.userId); } + if (url) { + this.modelUserAppId = new UserAppIDSet() + .setAppId(authConfigFromUrl?.appId ?? "") + .setUserId(authConfigFromUrl?.userId ?? ""); + } } /** From 5f7ef9123445dbe75e50a0f9943c48bbb18b55f8 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 13 May 2024 13:20:18 +0530 Subject: [PATCH 33/41] fix: add missing external dependency --- package-lock.json | 1 + package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index e668bc0..67bc60a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", "async": "^3.2.5", + "axios": "^1.6.8", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", "csv-parse": "^5.5.5", diff --git a/package.json b/package.json index b928ca5..85b821c 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@grpc/grpc-js": "^1.10.1", "@grpc/proto-loader": "^0.7.10", "async": "^3.2.5", + "axios": "^1.6.8", "chalk": "^5.3.0", "clarifai-nodejs-grpc": "^10.3.2", "csv-parse": "^5.5.5", From 0ce4489fb9490c5587b1a004f37f63dc1e94d525 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 13 May 2024 15:18:18 +0530 Subject: [PATCH 34/41] fix: updated model test cases --- src/client/model.ts | 26 +++++++++++++++----------- tests/client/model.integration.test.ts | 15 +++++++++++++++ tests/client/rag.integration.test.ts | 2 +- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/client/model.ts b/src/client/model.ts index d01c889..4711d6a 100644 --- a/src/client/model.ts +++ b/src/client/model.ts @@ -98,6 +98,9 @@ export class Model extends Lister { if (url && modelId) { throw new UserError("You can only specify one of url or model_id."); } + if (url && modelUserAppId) { + throw new UserError("You can only specify one of url or modelUserAppId."); + } if (!url && !modelId) { throw new UserError("You must specify one of url or model_id."); } @@ -105,13 +108,15 @@ export class Model extends Lister { let authConfigFromUrl: AuthConfig | undefined; if (url) { - const [userId, appId, destructuredModelId, modelVersionId] = + const [userId, appId, , destructuredModelId, modelVersionId] = ClarifaiUrlHelper.splitClarifaiUrl(url); modelIdFromUrl = destructuredModelId; - if (modelVersion) { - modelVersion.id = modelVersionId; - } else { - modelVersion = { id: modelVersionId }; + if (modelVersionId) { + if (modelVersion) { + modelVersion.id = modelVersionId; + } else { + modelVersion = { id: modelVersionId }; + } } authConfigFromUrl = { ...(authConfig as Omit), @@ -133,16 +138,15 @@ export class Model extends Lister { if (this.id) this.modelInfo.setId(this.id); if (this.modelVersion) this.modelInfo.setModelVersion(grpcModelVersion); this.trainingParams = {}; - if (modelUserAppId) { + if (authConfigFromUrl) { + this.modelUserAppId = new UserAppIDSet() + .setAppId(authConfigFromUrl.appId) + .setUserId(authConfigFromUrl.userId); + } else if (modelUserAppId) { this.modelUserAppId = new UserAppIDSet() .setAppId(modelUserAppId.appId) .setUserId(modelUserAppId.userId); } - if (url) { - this.modelUserAppId = new UserAppIDSet() - .setAppId(authConfigFromUrl?.appId ?? "") - .setUserId(authConfigFromUrl?.userId ?? ""); - } } /** diff --git a/tests/client/model.integration.test.ts b/tests/client/model.integration.test.ts index 001dd1e..27eb93f 100644 --- a/tests/client/model.integration.test.ts +++ b/tests/client/model.integration.test.ts @@ -255,5 +255,20 @@ describe( clipDim, ); }); + + it("should predict from a community model", async () => { + const model = new Model({ + url: "https://clarifai.com/clarifai/main/models/general-image-recognition", + authConfig: { + pat: CLARIFAI_PAT, + }, + }); + const imageUrl = "https://samples.clarifai.com/metro-north.jpg"; + const modelPrediction = await model.predictByUrl({ + url: imageUrl, + inputType: "image", + }); + expect(modelPrediction.length).toBeGreaterThan(0); + }); }, ); diff --git a/tests/client/rag.integration.test.ts b/tests/client/rag.integration.test.ts index 6b4838d..ea05363 100644 --- a/tests/client/rag.integration.test.ts +++ b/tests/client/rag.integration.test.ts @@ -64,7 +64,7 @@ describe("Rag", async () => { const messages = [{ role: "human", content: "What is 1 + 1?" }]; const newMessages = await rag.chat({ messages, clientManageState: true }); expect(newMessages.length).toBe(2); - }, 10000); + }, 15000); // TODO: Server side state management is not supported yet - work in progress it.skip("should predict & manage state on the server", async () => { From 9a0dd12b3362e71c1e331862aef48a1b9a5ff17f Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Mon, 13 May 2024 16:02:55 +0530 Subject: [PATCH 35/41] test: added more model test case --- tests/client/model.integration.test.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/client/model.integration.test.ts b/tests/client/model.integration.test.ts index 27eb93f..399bccf 100644 --- a/tests/client/model.integration.test.ts +++ b/tests/client/model.integration.test.ts @@ -256,7 +256,7 @@ describe( ); }); - it("should predict from a community model", async () => { + it("should predict from a model outside the app", async () => { const model = new Model({ url: "https://clarifai.com/clarifai/main/models/general-image-recognition", authConfig: { @@ -270,5 +270,24 @@ describe( }); expect(modelPrediction.length).toBeGreaterThan(0); }); + + it("should convert image to text", async () => { + const modelUrl = + "https://clarifai.com/salesforce/blip/models/general-english-image-caption-blip"; + const imageUrl = + "https://s3.amazonaws.com/samples.clarifai.com/featured-models/image-captioning-statue-of-liberty.jpeg"; + + const model = new Model({ + url: modelUrl, + authConfig: { + pat: CLARIFAI_PAT, + }, + }); + const modelPrediction = await model.predictByUrl({ + url: imageUrl, + inputType: "image", + }); + expect(modelPrediction?.[0]?.data?.text?.raw).toBeTruthy(); + }); }, ); From cdd8dab381e5e0a70761f9855f2b5d868c82a922 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 14 May 2024 16:03:25 +0530 Subject: [PATCH 36/41] feat: added test case for multimodal input --- tests/client/model.integration.test.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/client/model.integration.test.ts b/tests/client/model.integration.test.ts index 399bccf..5f33077 100644 --- a/tests/client/model.integration.test.ts +++ b/tests/client/model.integration.test.ts @@ -289,5 +289,29 @@ describe( }); expect(modelPrediction?.[0]?.data?.text?.raw).toBeTruthy(); }); + + it("should predict multimodal with image and text", async () => { + const prompt = "What time of day is it?"; + const imageUrl = "https://samples.clarifai.com/metro-north.jpg"; + const modelUrl = + "https://clarifai.com/openai/chat-completion/models/openai-gpt-4-vision"; + const inferenceParams = { temperature: 0.2, maxTokens: 100 }; + const multiInputs = Input.getMultimodalInput({ + inputId: "", + imageUrl, + rawText: prompt, + }); + const model = new Model({ + url: modelUrl, + authConfig: { pat: CLARIFAI_PAT }, + }); + + const modelPrediction = await model.predict({ + inputs: [multiInputs], + inferenceParams, + }); + + expect(modelPrediction?.[0]?.data?.text?.raw).toBeTruthy(); + }); }, ); From d87c0511a3246b6b099b8154613d2ec8f6902c67 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 15 May 2024 18:00:25 +0530 Subject: [PATCH 37/41] chore: set default search metric to euclidean --- src/constants/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/search.ts b/src/constants/search.ts index 0f5d68d..88ae358 100644 --- a/src/constants/search.ts +++ b/src/constants/search.ts @@ -1,3 +1,3 @@ export const DEFAULT_TOP_K = 10; -export const DEFAULT_SEARCH_METRIC = "cosine"; +export const DEFAULT_SEARCH_METRIC = "euclidean"; export const DEFAULT_SEARCH_ALGORITHM = "nearest_neighbor"; From 6384f071dba6cc4397147cee955c282c1a6e5e01 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Thu, 20 Jun 2024 15:12:50 +0530 Subject: [PATCH 38/41] fix: constructors --- src/client/model.ts | 77 +++++++++++++++---------- src/client/rag.ts | 84 +++++++++++++++++----------- tests/client/app.integration.test.ts | 6 +- 3 files changed, 103 insertions(+), 64 deletions(-) diff --git a/src/client/model.ts b/src/client/model.ts index b89e79d..dd1259b 100644 --- a/src/client/model.ts +++ b/src/client/model.ts @@ -62,6 +62,12 @@ interface ModelConfigWithModelId extends BaseModelConfig { type ModelConfig = ModelConfigWithUrl | ModelConfigWithModelId; +const isModelConfigWithUrl = ( + config: ModelConfig, +): config is ModelConfigWithUrl => { + return (config as ModelConfigWithUrl).url !== undefined; +}; + /** * Model is a class that provides access to Clarifai API endpoints related to Model information. * @noInheritDoc @@ -87,50 +93,61 @@ export class Model extends Lister { * * @includeExample examples/model/index.ts */ - constructor({ - url, - modelId, - modelVersion, - authConfig = {}, - modelUserAppId, - }: ModelConfig) { - if (url && modelId) { + constructor(config: ModelConfig) { + const { modelId, modelVersion, modelUserAppId } = config; + if (config.url && config.modelId) { throw new UserError("You can only specify one of url or model_id."); } - if (!url && !modelId) { + if (!config.url && !config.modelId) { throw new UserError("You must specify one of url or model_id."); } - let modelIdFromUrl; - let authConfigFromUrl: AuthConfig | undefined; - if (url) { - const [userId, appId, destructuredModelId, modelVersionId] = + let _authConfig: AuthConfig, + _destructuredModelId: string = "", + _destructuredModelVersionId: string | undefined = undefined; + if (isModelConfigWithUrl(config)) { + const { url } = config; + const [userId, appId] = ClarifaiUrlHelper.splitClarifaiUrl(url); + [, , _destructuredModelId, _destructuredModelVersionId] = ClarifaiUrlHelper.splitClarifaiUrl(url); - modelIdFromUrl = destructuredModelId; - if (modelVersion) { - modelVersion.id = modelVersionId; - } else { - modelVersion = { id: modelVersionId }; - } - authConfigFromUrl = { - ...(authConfig as Omit), - userId, - appId, + _authConfig = config.authConfig + ? { + ...config.authConfig, + userId, + appId, + } + : { + userId, + appId, + pat: process.env.CLARIFAI_PAT!, + }; + } else { + // if authconfig is undefined, we pick the values from env + _authConfig = config.authConfig || { + pat: process.env.CLARIFAI_PAT!, + userId: process.env.CLARIFAI_USER_ID!, + appId: process.env.CLARIFAI_APP_ID!, }; } - super({ authConfig: authConfigFromUrl || (authConfig as AuthConfig) }); - this.appId = authConfigFromUrl?.appId ?? (authConfig as AuthConfig)?.appId; - this.modelVersion = modelVersion; - this.id = (modelIdFromUrl || modelId) as string; + super({ authConfig: _authConfig }); + this.appId = _authConfig.appId; + this.modelVersion = + modelVersion || + (_destructuredModelVersionId + ? { id: _destructuredModelVersionId } + : undefined); + this.id = modelId || _destructuredModelId; this.modelInfo = new GrpcModel(); const grpcModelVersion = new ModelVersion(); if (this.modelVersion) { grpcModelVersion.setId(this.modelVersion.id); } - if (this.appId) this.modelInfo.setAppId(this.appId); - if (this.id) this.modelInfo.setId(this.id); - if (this.modelVersion) this.modelInfo.setModelVersion(grpcModelVersion); + this.modelInfo.setAppId(this.appId); + this.modelInfo.setId(this.id); + if (this.modelVersion) { + this.modelInfo.setModelVersion(grpcModelVersion); + } this.trainingParams = {}; if (modelUserAppId) { this.modelUserAppId = new UserAppIDSet() diff --git a/src/client/rag.ts b/src/client/rag.ts index da87b14..c4cdec6 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -36,20 +36,31 @@ type UrlAuthConfig = Omit & { userId?: undefined; }; -type RAGConfig = - | { - workflowUrl: ClarifaiUrl; - workflow?: undefined; - authConfig?: UrlAuthConfig; - } - | { - workflowUrl?: undefined; - workflow: Workflow; - authConfig?: AuthConfig; - }; +type RAGConfigWithURL = { + workflowUrl: ClarifaiUrl; + workflow?: undefined; + authConfig?: UrlAuthConfig; +}; + +type RAGConfigWithWorkflow = { + workflowUrl?: undefined; + workflow: Workflow; + authConfig?: AuthConfig; +}; + +type RAGConfig = RAGConfigWithURL | RAGConfigWithWorkflow; type workflowSchema = ReturnType; +const authConfigGuard = ( + authConfig: AuthConfig | UrlAuthConfig | undefined, +): authConfig is AuthConfig => { + if (authConfig?.appId && authConfig?.userId) { + return true; + } + return false; +}; + export class RAG { private authConfig: AuthConfig; @@ -58,6 +69,32 @@ export class RAG { public app: App; constructor({ workflowUrl, workflow, authConfig }: RAGConfig) { + this.validateInputs(workflowUrl, workflow, authConfig); + if (!authConfig || authConfigGuard(authConfig)) { + const targetAuthConfig: AuthConfig = authConfig ?? {}; + this.authConfig = targetAuthConfig; + this.promptWorkflow = workflow as Workflow; + } else { + console.info("workflow_url:%s", workflowUrl); + const [userId, appId, , ,] = ClarifaiUrlHelper.splitClarifaiUrl( + workflowUrl as ClarifaiUrl, + ); + const w = new Workflow({ + url: workflowUrl as ClarifaiUrl, + authConfig: authConfig, + }); + const targetAuthConfig: AuthConfig = { ...authConfig, appId, userId }; + this.authConfig = targetAuthConfig; + this.promptWorkflow = w; + } + this.app = new App({ authConfig: this.authConfig }); + } + + private validateInputs( + workflowUrl?: string, + workflow?: Workflow, + authConfig?: AuthConfig | UrlAuthConfig, + ) { if (workflowUrl && workflow) { throw new UserError( "Only one of workflowUrl or workflow can be specified.", @@ -66,28 +103,11 @@ export class RAG { if (!workflowUrl && !workflow) { throw new UserError("One of workflowUrl or workflow must be specified."); } - const targetAuthConfig: AuthConfig = (authConfig as AuthConfig) ?? {}; - if (workflowUrl) { - if (authConfig?.userId || authConfig?.appId) { - throw new UserError( - "userId and appId should not be specified in authConfig when using workflowUrl.", - ); - } - console.info("workflow_url:%s", workflowUrl); - const [userId, appId, , ,] = - ClarifaiUrlHelper.splitClarifaiUrl(workflowUrl); - const w = new Workflow({ - url: workflowUrl, - authConfig: authConfig as UrlAuthConfig, - }); - targetAuthConfig.appId = appId; - targetAuthConfig.userId = userId; - this.promptWorkflow = w; - } else { - this.promptWorkflow = workflow; + if (workflowUrl && (authConfig?.userId || authConfig?.appId)) { + throw new UserError( + "userId and appId should not be specified in authConfig when using workflowUrl.", + ); } - this.authConfig = targetAuthConfig; - this.app = new App({ authConfig: this.authConfig }); } static async setup({ diff --git a/tests/client/app.integration.test.ts b/tests/client/app.integration.test.ts index cf7525c..91eca95 100644 --- a/tests/client/app.integration.test.ts +++ b/tests/client/app.integration.test.ts @@ -150,7 +150,8 @@ describe("App", () => { expect(module.userId).toBe(CREATE_APP_USER_ID); }); - it("should create runner", async () => { + // TODO: To be addressed once runners API is stabilized + it.skip("should create runner", async () => { const user = new User({ pat: CLARIFAI_PAT, userId: CREATE_APP_USER_ID, @@ -230,7 +231,8 @@ describe("App", () => { ).resolves.not.toThrow(); }); - it("should delete runner", async () => { + // TODO: To be addressed once runners API is stabilized + it.skip("should delete runner", async () => { const user = new User({ pat: CLARIFAI_PAT, userId: CREATE_APP_USER_ID, From 942efdeced90e8839c08757adf5fee9249193da6 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Wed, 26 Jun 2024 17:17:31 +0530 Subject: [PATCH 39/41] feat: support custom root certificates path for authconfig --- src/client/auth/helper.ts | 33 ++++++++++++++++++++++++++- src/client/base.ts | 4 ++++ src/utils/types.ts | 1 + tests/client/auth/helper.unit.test.ts | 15 ++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/client/auth/helper.ts b/src/client/auth/helper.ts index 68c6cb5..bb82fde 100644 --- a/src/client/auth/helper.ts +++ b/src/client/auth/helper.ts @@ -2,6 +2,7 @@ import resources_pb2 from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb" import { grpc } from "clarifai-nodejs-grpc"; import { V2Client } from "clarifai-nodejs-grpc/proto/clarifai/api/service_grpc_pb"; import process from "process"; +import fs from "fs"; // TypeScript interface for the cache export interface Cache { @@ -75,6 +76,7 @@ export class ClarifaiAuthHelper { private token: string; private _base: string; private _ui: string; + private _rootCertificatesPath: string; /** * A helper to get the authorization information needed to make API calls with the grpc @@ -97,6 +99,7 @@ export class ClarifaiAuthHelper { * https://clarifai.com (default), https://host:port, http://host:port, * host:port (will be treated as http, not https). It's highly recommended to include * the http:// or https:// otherwise we need to check the endpoint to determine if it has SSL during this __init__. + * @param rootCertificatesPath - path to the root certificates file. This is only used for grpc secure channels. * @param validate - Whether to validate the inputs. This is useful for overriding vars then validating. */ constructor( @@ -106,12 +109,14 @@ export class ClarifaiAuthHelper { token: string = "", base: string = DEFAULT_BASE, ui: string = DEFAULT_UI, + rootCertificatesPath: string = "", validate: boolean = true, ) { this.userId = userId; this.appId = appId; this._pat = pat; this.token = token; + this._rootCertificatesPath = rootCertificatesPath; this._base = base; this._ui = ui; @@ -142,6 +147,13 @@ export class ClarifaiAuthHelper { throw new Error( "Need 'pat' or 'token' in the query params or use one of the CLARIFAI_PAT or CLARIFAI_SESSION_TOKEN env vars", ); + } else if ( + this._rootCertificatesPath && + !fs.existsSync(this._rootCertificatesPath) + ) { + throw new Error( + `Root certificates path ${this._rootCertificatesPath} does not exist`, + ); } } @@ -163,6 +175,8 @@ export class ClarifaiAuthHelper { const pat = process.env.CLARIFAI_PAT || ""; const base = process.env.CLARIFAI_API_BASE || DEFAULT_BASE; const ui = process.env.CLARIFAI_UI || DEFAULT_UI; + const rootCertificatesPath = + process.env.CLARIFAI_ROOT_CERTIFICATES_PATH || ""; return new ClarifaiAuthHelper( userId, @@ -171,6 +185,7 @@ export class ClarifaiAuthHelper { token, base, ui, + rootCertificatesPath, validate, ); } @@ -227,7 +242,16 @@ export class ClarifaiAuthHelper { let client: V2Client; if (https) { - client = new V2Client(this._base, grpc.ChannelCredentials.createSsl()); + if (this._rootCertificatesPath) { + client = new V2Client( + this._base, + grpc.ChannelCredentials.createSsl( + fs.readFileSync(this._rootCertificatesPath), + ), + ); + } else { + client = new V2Client(this._base, grpc.ChannelCredentials.createSsl()); + } } else { let host: string; let port: number = 80; @@ -282,6 +306,13 @@ export class ClarifaiAuthHelper { this._ui = httpsCache(uiHttpsCache, ui); } + /** + * Return the root certificates path. + */ + get rootCertificatesPath(): string { + return this._rootCertificatesPath; + } + /** * Return the base domain for the API. */ diff --git a/src/client/base.ts b/src/client/base.ts index 2461153..a2a5016 100644 --- a/src/client/base.ts +++ b/src/client/base.ts @@ -28,6 +28,7 @@ export class BaseClient { protected pat: string; protected userAppId: UserAppIDSet; protected base: string; + protected rootCertificatesPath: string; /** * Constructs a new BaseClient instance with specified configuration options. @@ -39,6 +40,7 @@ export class BaseClient { * @param {string} [authConfig.token] An optional token for authentication. * @param {string} [authConfig.base='https://api.clarifai.com'] The base URL for the API endpoint. Defaults to 'https://api.clarifai.com'. * @param {string} [authConfig.ui='https://clarifai.com'] The URL for the UI. Defaults to 'https://clarifai.com'. + * @param {string} [authConfig.rootCertificatesPath] Path to the SSL root certificates file, used to establish secure gRPC connections. */ constructor(authConfig: AuthConfig = {}) { const pat = getFromDictOrEnv("pat", "CLARIFAI_PAT", authConfig); @@ -52,6 +54,7 @@ export class BaseClient { authConfig.token, authConfig.base, authConfig.ui, + authConfig.rootCertificatesPath, false, ) : ClarifaiAuthHelper.fromEnv(false); // The validate parameter is set to false explicitly @@ -60,6 +63,7 @@ export class BaseClient { this.pat = this.authHelper.pat; this.userAppId = this.authHelper.getUserAppIdProto(); this.base = this.authHelper.base; + this.rootCertificatesPath = this.authHelper.rootCertificatesPath; } /** diff --git a/src/utils/types.ts b/src/utils/types.ts index 6023b39..39789b4 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -5,6 +5,7 @@ export type AuthConfig = userId: string; appId: string; pat: string; + rootCertificatesPath?: string; token?: string; base?: string; ui?: string; diff --git a/tests/client/auth/helper.unit.test.ts b/tests/client/auth/helper.unit.test.ts index 94a90d6..3f6e021 100644 --- a/tests/client/auth/helper.unit.test.ts +++ b/tests/client/auth/helper.unit.test.ts @@ -118,6 +118,21 @@ describe("ClarifaiAuthHelper", () => { expect(() => ClarifaiAuthHelper.validateSecretsDict(secrets)).toThrow(); }); + it("throws error for invalid root certificates path", () => { + expect( + () => + new ClarifaiAuthHelper( + "userId", + "appId", + "pat", + "", + "https://customdomain.com", + "https://customdomain.com/ui", + "invalid", + ), + ).toThrow(`Root certificates path invalid does not exist`); + }); + it("getUserAppIdProto returns correct UserAppIDSet proto object", () => { const helper = new ClarifaiAuthHelper("userId", "appId", "pat"); const userAppIdProto = helper.getUserAppIdProto(); From 5a2ce417067d4d644e6bde8b839922ec0ec89543 Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 2 Jul 2024 17:26:02 +0530 Subject: [PATCH 40/41] fix: change rag baseworkflow --- src/client/rag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index c4cdec6..ec23204 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -114,7 +114,7 @@ export class RAG { authConfig, appUrl, llmUrl = "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct", - baseWorkflow = "Text", + baseWorkflow = "Universal", workflowYamlFilename = "prompter_wf.yaml", promptTemplate = DEFAULT_RAG_PROMPT_TEMPLATE, workflowId, From d6ab3936409dbb4c12a94a07309b4db4b08baccf Mon Sep 17 00:00:00 2001 From: DaniAkash Date: Tue, 2 Jul 2024 18:18:24 +0530 Subject: [PATCH 41/41] fix: revert base workflow --- src/client/rag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/rag.ts b/src/client/rag.ts index ec23204..c4cdec6 100644 --- a/src/client/rag.ts +++ b/src/client/rag.ts @@ -114,7 +114,7 @@ export class RAG { authConfig, appUrl, llmUrl = "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct", - baseWorkflow = "Universal", + baseWorkflow = "Text", workflowYamlFilename = "prompter_wf.yaml", promptTemplate = DEFAULT_RAG_PROMPT_TEMPLATE, workflowId,