diff --git a/libs/langchain-qdrant/src/tests/vectorstores.test.ts b/libs/langchain-qdrant/src/tests/vectorstores.test.ts index 2fb12e767617..40eaa1ab8008 100644 --- a/libs/langchain-qdrant/src/tests/vectorstores.test.ts +++ b/libs/langchain-qdrant/src/tests/vectorstores.test.ts @@ -54,14 +54,12 @@ test("QdrantVectorStore adds vectors with custom payload", async () => { }); // Define a custom payload - const customPayload = { - customPayload: [ + const customPayload = [ { customField1: "value1", customField2: "value2", }, - ], - }; + ]; // Add documents with custom payload await qdrantVectorStore.addDocuments( @@ -83,7 +81,7 @@ test("QdrantVectorStore adds vectors with custom payload", async () => { payload: expect.objectContaining({ content: "hello", metadata: {}, - customPayload: customPayload.customPayload[0], + customPayload: customPayload[0], }), }), ], @@ -109,8 +107,7 @@ test("QdrantVectorStore adds vectors with multiple custom payload", async () => }); // Define a custom payload - const customPayload = { - customPayload: [ + const customPayload = [ { customField1: "value1", customField2: "value2", @@ -118,8 +115,7 @@ test("QdrantVectorStore adds vectors with multiple custom payload", async () => { customField3: "value3", }, - ], - }; + ]; // Add documents with custom payload await qdrantVectorStore.addDocuments( @@ -149,14 +145,14 @@ test("QdrantVectorStore adds vectors with multiple custom payload", async () => payload: expect.objectContaining({ content: "hello", metadata: {}, - customPayload: customPayload.customPayload[0], + customPayload: customPayload[0], }), }), expect.objectContaining({ payload: expect.objectContaining({ content: "Goodbye", metadata: {}, - customPayload: customPayload.customPayload[1], + customPayload: customPayload[1], }), }), expect.objectContaining({ diff --git a/libs/langchain-qdrant/src/vectorstores.ts b/libs/langchain-qdrant/src/vectorstores.ts index 4e48421f71f2..07b2922a05d3 100644 --- a/libs/langchain-qdrant/src/vectorstores.ts +++ b/libs/langchain-qdrant/src/vectorstores.ts @@ -25,15 +25,16 @@ export interface QdrantLibArgs { apiKey?: string; collectionName?: string; collectionConfig?: QdrantSchemas["CreateCollection"]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - customPayload?: Record[]; + customPayload?: QdrantCustomPayload; contentPayloadKey?: string; metadataPayloadKey?: string; } +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type QdrantCustomPayload = Record; + export type QdrantAddDocumentOptions = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - customPayload: Record[]; + customPayload: QdrantCustomPayload[]; }; export type QdrantFilter = QdrantSchemas["Filter"]; @@ -78,6 +79,8 @@ export class QdrantVectorStore extends VectorStore { metadataPayloadKey: string; + customPayload?: QdrantCustomPayload; + _vectorstoreType(): string { return "qdrant"; } @@ -103,6 +106,8 @@ export class QdrantVectorStore extends VectorStore { this.collectionConfig = args.collectionConfig; + this.customPayload = args.customPayload; + this.contentPayloadKey = args.contentPayloadKey ?? CONTENT_KEY; this.metadataPayloadKey = args.metadataPayloadKey ?? METADATA_KEY; @@ -113,18 +118,18 @@ export class QdrantVectorStore extends VectorStore { * from the documents using the `Embeddings` instance and then adds the * vectors to the database. * @param documents Array of `Document` instances to be added to the Qdrant database. - * @param documentOptions Optional `QdrantAddDocumentOptions` which has a list of JSON objects for extra querying + * @param customPayloads Optional `QdrantCustomPayload` array which has a list of JSON objects for extra querying. * @returns Promise that resolves when the documents have been added to the database. */ async addDocuments( documents: Document[], - documentOptions?: QdrantAddDocumentOptions + customPayloads?: QdrantCustomPayload[], ): Promise { const texts = documents.map(({ pageContent }) => pageContent); await this.addVectors( await this.embeddings.embedDocuments(texts), documents, - documentOptions + customPayloads ); } @@ -134,13 +139,13 @@ export class QdrantVectorStore extends VectorStore { * database. * @param vectors Array of vectors to be added to the Qdrant database. * @param documents Array of `Document` instances associated with the vectors. - * @param documentOptions Optional `QdrantAddDocumentOptions` which has a list of JSON objects for extra querying + * @param customPayloads Optional `QdrantCustomPayload` array which has a list of JSON objects for extra querying. Will be merged with custom payload of dbConfig. * @returns Promise that resolves when the vectors have been added to the database. */ async addVectors( vectors: number[][], documents: Document[], - documentOptions?: QdrantAddDocumentOptions + customPayloads?: QdrantCustomPayload[], ): Promise { if (vectors.length === 0) { return; @@ -148,15 +153,21 @@ export class QdrantVectorStore extends VectorStore { await this.ensureCollection(); - const points = vectors.map((embedding, idx) => ({ - id: documents[idx].id ?? uuid(), - vector: embedding, - payload: { - [this.contentPayloadKey]: documents[idx].pageContent, - [this.metadataPayloadKey]: documents[idx].metadata, - customPayload: documentOptions?.customPayload[idx], - }, - })); + const points = vectors.map((embedding, idx) => { + const customPayload = { + ...this.customPayload, + ...customPayloads?.[idx], + } + return { + id: documents[idx].id ?? uuid(), + vector: embedding, + payload: { + [this.contentPayloadKey]: documents[idx].pageContent, + [this.metadataPayloadKey]: documents[idx].metadata, + customPayload: Object.keys(customPayload).length > 0 ? customPayload : undefined, + }, + } + }); try { await this.client.upsert(this.collectionName, { @@ -332,22 +343,17 @@ export class QdrantVectorStore extends VectorStore { * @param docs Array of `Document` instances to be added to the Qdrant database. * @param embeddings `Embeddings` instance used to generate vectors from the documents. * @param dbConfig `QdrantLibArgs` instance specifying the configuration for the Qdrant database. + * @param customPayloads Optional `QdrantCustomPayload` array which has a list of JSON objects for extra querying. * @returns Promise that resolves with a new `QdrantVectorStore` instance. */ static async fromDocuments( docs: Document[], embeddings: EmbeddingsInterface, - dbConfig: QdrantLibArgs + dbConfig: QdrantLibArgs, + customPayloads?: QdrantCustomPayload[] ): Promise { const instance = new this(embeddings, dbConfig); - if (dbConfig.customPayload) { - const documentOptions = { - customPayload: dbConfig?.customPayload, - }; - await instance.addDocuments(docs, documentOptions); - } else { - await instance.addDocuments(docs); - } + await instance.addDocuments(docs, customPayloads); return instance; }