mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat(Qdrant Vector Store Node): Qdrant vector store support (#8080)
## Summary This PR intends to add [Qdrant](https://qdrant.tech/) as a supported vectorstore node to load and retrieve documents from in a workflow. ## Review / Merge checklist - [x] PR title and summary are descriptive. - [x] Node/credentials documentation to be updated in https://github.com/n8n-io/n8n-docs/pull/1796. --------- Co-authored-by: oleg <me@olegivaniv.com> Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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. <a href="https://qdrant.tech/documentation/concepts/collections">Learn more</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
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);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="256px" height="296px" viewBox="0 0 256 296" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<title>qdrant</title>
|
||||
<defs>
|
||||
<linearGradient x1="81.5619048%" y1="44.8421053%" x2="-18.0857143%" y2="44.8421053%" id="linearGradient-1">
|
||||
<stop stop-color="#FF3364" offset="0%"></stop>
|
||||
<stop stop-color="#C91540" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g>
|
||||
<polygon fill="#24386C" points="201.31705 271.722427 195.422715 109.21267 184.747781 66.3682368 256 73.9112545 256 270.492509 212.474757 295.612626"></polygon>
|
||||
<polygon fill="#7589BE" points="255.995151 73.8998107 212.469908 99.037384 122.649634 79.3346471 17.5160008 122.140288 1.1370484e-14 73.8998107 63.9883137 36.9499053 127.996024 0 191.986277 36.9499053"></polygon>
|
||||
<polyline fill="#B2BFE8" points="0.00310340412 73.8998107 43.5283462 99.037384 68.7590217 174.073816 153.949405 242.236209 128.001067 295.599243 63.9933568 258.647398 0.00310340412 221.697492 0.00310340412 73.897871"></polyline>
|
||||
<polyline fill="#24386C" points="156.856906 202.807459 128.001067 245.347371 128.001067 295.603122 168.946605 271.978458 190.043934 240.475027"></polyline>
|
||||
<polygon fill="#7589BE" points="128.018523 195.107138 87.0555287 124.184656 95.8787005 100.678309 129.42068 84.4156955 168.946411 124.185819"></polygon>
|
||||
<polyline fill="#B2BFE8" points="87.0555287 124.178837 128.001067 147.803501 128.001067 195.091621 90.131778 196.720927 67.2247763 167.471344 87.0555287 124.178856"></polyline>
|
||||
<polygon fill="#24386C" points="128.001067 147.799621 168.946605 124.176897 196.813234 170.576668 163.090869 198.439418 128.001067 195.089293"></polygon>
|
||||
<path d="M168.946605,271.974579 L212.471848,295.601182 L212.471848,99.0393237 L170.226759,74.658205 L128.001067,50.2770864 L85.7559782,74.658205 L43.5302858,99.0393237 L43.5302858,196.581255 L85.7559782,220.962373 L128.001067,245.345432 L168.946605,221.699432 L168.946605,271.974579 Z M168.946605,171.443681 L128.001067,195.087742 L87.0555287,171.443681 L87.0555287,124.174957 L128.001067,100.530897 L168.946605,124.174957 L168.946605,171.443681" fill="#DC244C"></path>
|
||||
<polygon fill="url(#linearGradient-1)" points="128.018523 245.362888 128.018523 195.099379 87.2863443 171.657041 87.2863443 221.837146"></polygon>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -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',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user