diff --git a/packages/@n8n/nodes-langchain/credentials/QdrantApi.credentials.ts b/packages/@n8n/nodes-langchain/credentials/QdrantApi.credentials.ts
new file mode 100644
index 0000000000..26bb3e9bac
--- /dev/null
+++ b/packages/@n8n/nodes-langchain/credentials/QdrantApi.credentials.ts
@@ -0,0 +1,50 @@
+import type {
+ IAuthenticateGeneric,
+ ICredentialTestRequest,
+ ICredentialType,
+ INodeProperties,
+} from 'n8n-workflow';
+
+export class QdrantApi implements ICredentialType {
+ name = 'qdrantApi';
+
+ displayName = 'QdrantApi';
+
+ documentationUrl = 'https://docs.n8n.io/integrations/builtin/credentials/qdrant/';
+
+ properties: INodeProperties[] = [
+ {
+ displayName: 'API Key',
+ name: 'apiKey',
+ type: 'string',
+ typeOptions: { password: true },
+ required: true,
+ default: '',
+ },
+ {
+ displayName: 'Qdrant URL',
+ name: 'qdrantUrl',
+ type: 'string',
+ required: true,
+ default: '',
+ },
+ ];
+
+ authenticate: IAuthenticateGeneric = {
+ type: 'generic',
+ properties: {
+ headers: {
+ 'api-key': '={{$credentials.apiKey}}',
+ },
+ },
+ };
+
+ test: ICredentialTestRequest = {
+ request: {
+ baseURL: '={{$credentials.qdrantUrl}}',
+ headers: {
+ accept: 'application/json; charset=utf-8',
+ },
+ },
+ };
+}
diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/VectorStoreQdrant.node.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/VectorStoreQdrant.node.ts
new file mode 100644
index 0000000000..759330539e
--- /dev/null
+++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/VectorStoreQdrant.node.ts
@@ -0,0 +1,85 @@
+import { type INodeProperties } from 'n8n-workflow';
+import type { QdrantLibArgs } from 'langchain/vectorstores/qdrant';
+import { QdrantVectorStore } from 'langchain/vectorstores/qdrant';
+import type { Schemas as QdrantSchemas } from '@qdrant/js-client-rest';
+import { createVectorStoreNode } from '../shared/createVectorStoreNode';
+import { qdrantCollectionRLC } from '../shared/descriptions';
+import { qdrantCollectionsSearch } from '../shared/methods/listSearch';
+
+const sharedFields: INodeProperties[] = [qdrantCollectionRLC];
+
+const insertFields: INodeProperties[] = [
+ {
+ displayName: 'Options',
+ name: 'options',
+ type: 'collection',
+ placeholder: 'Add Option',
+ default: {},
+ options: [
+ {
+ displayName: 'Collection Config',
+ name: 'collectionConfig',
+ type: 'json',
+ default: '',
+ description:
+ 'JSON options for creating a collection. Learn more.',
+ },
+ ],
+ },
+];
+
+export const VectorStoreQdrant = createVectorStoreNode({
+ meta: {
+ displayName: 'Qdrant Vector Store',
+ name: 'vectorStoreQdrant',
+ description: 'Work with your data in a Qdrant collection',
+ icon: 'file:qdrant.svg',
+ docsUrl:
+ 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreqdrant/',
+ credentials: [
+ {
+ name: 'qdrantApi',
+ required: true,
+ },
+ ],
+ },
+ methods: { listSearch: { qdrantCollectionsSearch } },
+ insertFields,
+ sharedFields,
+ async getVectorStoreClient(context, filter, embeddings, itemIndex) {
+ const collection = context.getNodeParameter('qdrantCollection', itemIndex, '', {
+ extractValue: true,
+ }) as string;
+
+ const credentials = await context.getCredentials('qdrantApi');
+
+ const config: QdrantLibArgs = {
+ url: credentials.qdrantUrl as string,
+ apiKey: credentials.apiKey as string,
+ collectionName: collection,
+ };
+
+ return QdrantVectorStore.fromExistingCollection(embeddings, config);
+ },
+ async populateVectorStore(context, embeddings, documents, itemIndex) {
+ const collectionName = context.getNodeParameter('qdrantCollection', itemIndex, '', {
+ extractValue: true,
+ }) as string;
+
+ // If collection config is not provided, the collection will be created with default settings
+ // i.e. with the size of the passed embeddings and "Cosine" distance metric
+ const { collectionConfig } = context.getNodeParameter('options', itemIndex, {}) as {
+ collectionConfig?: QdrantSchemas['CreateCollection'];
+ };
+ const credentials = await context.getCredentials('qdrantApi');
+
+ const config: QdrantLibArgs = {
+ url: credentials.qdrantUrl as string,
+ apiKey: credentials.apiKey as string,
+ collectionName,
+ collectionConfig,
+ };
+
+ await QdrantVectorStore.fromDocuments(documents, embeddings, config);
+ },
+});
diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/qdrant.svg b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/qdrant.svg
new file mode 100644
index 0000000000..be9350cd28
--- /dev/null
+++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/qdrant.svg
@@ -0,0 +1,21 @@
+
+
diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/descriptions.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/descriptions.ts
index 573044b922..483e73c1fe 100644
--- a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/descriptions.ts
+++ b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/descriptions.ts
@@ -45,3 +45,26 @@ export const supabaseTableNameRLC: INodeProperties = {
},
],
};
+
+export const qdrantCollectionRLC: INodeProperties = {
+ displayName: 'Qdrant Collection',
+ name: 'qdrantCollection',
+ type: 'resourceLocator',
+ default: { mode: 'list', value: '' },
+ required: true,
+ modes: [
+ {
+ displayName: 'From List',
+ name: 'list',
+ type: 'list',
+ typeOptions: {
+ searchListMethod: 'qdrantCollectionsSearch',
+ },
+ },
+ {
+ displayName: 'ID',
+ name: 'id',
+ type: 'string',
+ },
+ ],
+};
diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts
index 13ee71c273..d606a0db05 100644
--- a/packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts
+++ b/packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts
@@ -1,5 +1,6 @@
import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow';
import { Pinecone } from '@pinecone-database/pinecone';
+import { QdrantClient } from '@qdrant/js-client-rest';
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
const credentials = await this.getCredentials('pineconeApi');
@@ -49,3 +50,21 @@ export async function supabaseTableNameSearch(this: ILoadOptionsFunctions) {
return { results };
}
+
+export async function qdrantCollectionsSearch(this: ILoadOptionsFunctions) {
+ const credentials = await this.getCredentials('qdrantApi');
+
+ const client = new QdrantClient({
+ url: credentials.qdrantUrl as string,
+ apiKey: credentials.apiKey as string,
+ });
+
+ const response = await client.getCollections();
+
+ const results = response.collections.map((collection) => ({
+ name: collection.name,
+ value: collection.name,
+ }));
+
+ return { results };
+}
diff --git a/packages/@n8n/nodes-langchain/package.json b/packages/@n8n/nodes-langchain/package.json
index 12e4dceda9..a909021617 100644
--- a/packages/@n8n/nodes-langchain/package.json
+++ b/packages/@n8n/nodes-langchain/package.json
@@ -33,6 +33,7 @@
"dist/credentials/MotorheadApi.credentials.js",
"dist/credentials/OllamaApi.credentials.js",
"dist/credentials/PineconeApi.credentials.js",
+ "dist/credentials/QdrantApi.credentials.js",
"dist/credentials/SerpApi.credentials.js",
"dist/credentials/WolframAlphaApi.credentials.js",
"dist/credentials/XataApi.credentials.js",
@@ -93,6 +94,7 @@
"dist/nodes/vector_store/VectorStorePinecone/VectorStorePinecone.node.js",
"dist/nodes/vector_store/VectorStorePineconeInsert/VectorStorePineconeInsert.node.js",
"dist/nodes/vector_store/VectorStorePineconeLoad/VectorStorePineconeLoad.node.js",
+ "dist/nodes/vector_store/VectorStoreQdrant/VectorStoreQdrant.node.js",
"dist/nodes/vector_store/VectorStoreSupabase/VectorStoreSupabase.node.js",
"dist/nodes/vector_store/VectorStoreSupabaseInsert/VectorStoreSupabaseInsert.node.js",
"dist/nodes/vector_store/VectorStoreSupabaseLoad/VectorStoreSupabaseLoad.node.js",
@@ -118,6 +120,7 @@
"@huggingface/inference": "2.6.4",
"@n8n/vm2": "3.9.20",
"@pinecone-database/pinecone": "1.1.2",
+ "@qdrant/js-client-rest": "1.7.0",
"@supabase/supabase-js": "2.38.5",
"@xata.io/client": "0.25.3",
"cohere-ai": "6.2.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f1b794a418..34f857df0e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -192,6 +192,9 @@ importers:
'@pinecone-database/pinecone':
specifier: 1.1.2
version: 1.1.2
+ '@qdrant/js-client-rest':
+ specifier: 1.7.0
+ version: 1.7.0(typescript@5.3.2)
'@supabase/supabase-js':
specifier: 2.38.5
version: 2.38.5
@@ -215,7 +218,7 @@ importers:
version: 1.2.0
langchain:
specifier: 0.0.198
- version: 0.0.198(@aws-sdk/client-bedrock-runtime@3.454.0)(@getzep/zep-js@0.9.0)(@google-ai/generativelanguage@0.2.1)(@huggingface/inference@2.6.4)(@pinecone-database/pinecone@1.1.2)(@supabase/supabase-js@2.38.5)(@xata.io/client@0.25.3)(cohere-ai@6.2.2)(d3-dsv@2.0.0)(epub2@3.0.1)(html-to-text@9.0.5)(lodash@4.17.21)(mammoth@1.6.0)(pdf-parse@1.1.1)(pg@8.11.3)(redis@4.6.11)(typeorm@0.3.17)
+ version: 0.0.198(@aws-sdk/client-bedrock-runtime@3.454.0)(@getzep/zep-js@0.9.0)(@google-ai/generativelanguage@0.2.1)(@huggingface/inference@2.6.4)(@pinecone-database/pinecone@1.1.2)(@qdrant/js-client-rest@1.7.0)(@supabase/supabase-js@2.38.5)(@xata.io/client@0.25.3)(cohere-ai@6.2.2)(d3-dsv@2.0.0)(epub2@3.0.1)(html-to-text@9.0.5)(lodash@4.17.21)(mammoth@1.6.0)(pdf-parse@1.1.1)(pg@8.11.3)(redis@4.6.11)(typeorm@0.3.17)
lodash:
specifier: 4.17.21
version: 4.17.21
@@ -6544,6 +6547,23 @@ packages:
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
dev: false
+ /@qdrant/js-client-rest@1.7.0(typescript@5.3.2):
+ resolution: {integrity: sha512-16O0EQfrrybcPVipodxykr6dMUlBzKW7a63cSDUFVgc5a1AWESwERykwjuvW5KqvKdkPcxZ2NssrvgUO1W3MgA==}
+ engines: {node: '>=18.0.0', pnpm: '>=8'}
+ peerDependencies:
+ typescript: ^5.3.0
+ dependencies:
+ '@qdrant/openapi-typescript-fetch': 1.2.1
+ '@sevinf/maybe': 0.5.0
+ typescript: 5.3.2
+ undici: 5.26.4
+ dev: false
+
+ /@qdrant/openapi-typescript-fetch@1.2.1:
+ resolution: {integrity: sha512-oiBJRN1ME7orFZocgE25jrM3knIF/OKJfMsZPBbtMMKfgNVYfps0MokGvSJkBmecj6bf8QoLXWIGlIoaTM4Zmw==}
+ engines: {node: '>=12.0.0', pnpm: '>=8'}
+ dev: false
+
/@radix-ui/number@1.0.1:
resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==}
dependencies:
@@ -7391,6 +7411,10 @@ packages:
- supports-color
dev: true
+ /@sevinf/maybe@0.5.0:
+ resolution: {integrity: sha512-ARhyoYDnY1LES3vYI0fiG6e9esWfTNcXcO6+MPJJXcnyMV3bim4lnFt45VXouV7y82F4x3YH8nOQ6VztuvUiWg==}
+ dev: false
+
/@sideway/address@4.1.4:
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
dependencies:
@@ -18585,7 +18609,7 @@ packages:
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
dev: false
- /langchain@0.0.198(@aws-sdk/client-bedrock-runtime@3.454.0)(@getzep/zep-js@0.9.0)(@google-ai/generativelanguage@0.2.1)(@huggingface/inference@2.6.4)(@pinecone-database/pinecone@1.1.2)(@supabase/supabase-js@2.38.5)(@xata.io/client@0.25.3)(cohere-ai@6.2.2)(d3-dsv@2.0.0)(epub2@3.0.1)(html-to-text@9.0.5)(lodash@4.17.21)(mammoth@1.6.0)(pdf-parse@1.1.1)(pg@8.11.3)(redis@4.6.11)(typeorm@0.3.17):
+ /langchain@0.0.198(@aws-sdk/client-bedrock-runtime@3.454.0)(@getzep/zep-js@0.9.0)(@google-ai/generativelanguage@0.2.1)(@huggingface/inference@2.6.4)(@pinecone-database/pinecone@1.1.2)(@qdrant/js-client-rest@1.7.0)(@supabase/supabase-js@2.38.5)(@xata.io/client@0.25.3)(cohere-ai@6.2.2)(d3-dsv@2.0.0)(epub2@3.0.1)(html-to-text@9.0.5)(lodash@4.17.21)(mammoth@1.6.0)(pdf-parse@1.1.1)(pg@8.11.3)(redis@4.6.11)(typeorm@0.3.17):
resolution: {integrity: sha512-YC0O1g8r61InCWyF5NmiQjdghdq6LKcgMrDZtqLbgDxAe4RoSldonm+5oNXS3yjCISG0j3s5Cty+yB7klqvUpg==}
engines: {node: '>=18'}
peerDependencies:
@@ -18898,6 +18922,7 @@ packages:
'@huggingface/inference': 2.6.4
'@langchain/core': 0.0.2
'@pinecone-database/pinecone': 1.1.2
+ '@qdrant/js-client-rest': 1.7.0(typescript@5.3.2)
'@supabase/supabase-js': 2.38.5
'@xata.io/client': 0.25.3(typescript@5.3.2)
binary-extensions: 2.2.0