fix: Fix issue with Qdrant not always connecting (#14328)

Co-authored-by: Yiorgis Gozadinos <ggozadinos@gmail.com>
This commit is contained in:
Jon
2025-04-14 11:58:29 +01:00
committed by GitHub
parent b568caa209
commit 6748db9c3b
4 changed files with 52 additions and 13 deletions

View File

@@ -42,9 +42,7 @@ export class QdrantApi implements ICredentialType {
test: ICredentialTestRequest = { test: ICredentialTestRequest = {
request: { request: {
baseURL: '={{$credentials.qdrantUrl}}', baseURL: '={{$credentials.qdrantUrl}}',
headers: { url: '/collections',
accept: 'application/json; charset=utf-8',
},
}, },
}; };
} }

View File

@@ -0,0 +1,39 @@
import { QdrantClient } from '@qdrant/js-client-rest';
import { UserError } from 'n8n-workflow';
export type QdrantCredential = {
qdrantUrl: string;
apiKey: string;
};
function parseQdrantUrl(url: string): { protocol: string; host: string; port: number } {
try {
const parsedUrl = new URL(url);
return {
protocol: parsedUrl.protocol,
host: parsedUrl.hostname,
port: parsedUrl.port
? parseInt(parsedUrl.port, 10)
: parsedUrl.protocol === 'https:'
? 443
: 80,
};
} catch (error) {
throw new UserError(
`Invalid Qdrant URL: ${url}. Please provide a valid URL with protocol (http/https)`,
);
}
}
export function createQdrantClient(credentials: QdrantCredential): QdrantClient {
const { protocol, host, port } = parseQdrantUrl(credentials.qdrantUrl);
const qdrantClient = new QdrantClient({
host,
apiKey: credentials.apiKey,
https: protocol === 'https:',
port,
});
return qdrantClient;
}

View File

@@ -2,9 +2,10 @@ import type { Callbacks } from '@langchain/core/callbacks/manager';
import type { Embeddings } from '@langchain/core/embeddings'; import type { Embeddings } from '@langchain/core/embeddings';
import type { QdrantLibArgs } from '@langchain/qdrant'; import type { QdrantLibArgs } from '@langchain/qdrant';
import { QdrantVectorStore } from '@langchain/qdrant'; import { QdrantVectorStore } from '@langchain/qdrant';
import type { Schemas as QdrantSchemas } from '@qdrant/js-client-rest'; import { type Schemas as QdrantSchemas } from '@qdrant/js-client-rest';
import type { IDataObject, INodeProperties } from 'n8n-workflow'; import type { IDataObject, INodeProperties } from 'n8n-workflow';
import { createQdrantClient, type QdrantCredential } from './Qdrant.utils';
import { createVectorStoreNode } from '../shared/createVectorStoreNode/createVectorStoreNode'; import { createVectorStoreNode } from '../shared/createVectorStoreNode/createVectorStoreNode';
import { qdrantCollectionsSearch } from '../shared/createVectorStoreNode/methods/listSearch'; import { qdrantCollectionsSearch } from '../shared/createVectorStoreNode/methods/listSearch';
import { qdrantCollectionRLC } from '../shared/descriptions'; import { qdrantCollectionRLC } from '../shared/descriptions';
@@ -106,9 +107,10 @@ export class VectorStoreQdrant extends createVectorStoreNode<ExtendedQdrantVecto
const credentials = await context.getCredentials('qdrantApi'); const credentials = await context.getCredentials('qdrantApi');
const client = createQdrantClient(credentials as QdrantCredential);
const config: QdrantLibArgs = { const config: QdrantLibArgs = {
url: credentials.qdrantUrl as string, client,
apiKey: credentials.apiKey as string,
collectionName: collection, collectionName: collection,
}; };
@@ -126,9 +128,10 @@ export class VectorStoreQdrant extends createVectorStoreNode<ExtendedQdrantVecto
}; };
const credentials = await context.getCredentials('qdrantApi'); const credentials = await context.getCredentials('qdrantApi');
const client = createQdrantClient(credentials as QdrantCredential);
const config: QdrantLibArgs = { const config: QdrantLibArgs = {
url: credentials.qdrantUrl as string, client,
apiKey: credentials.apiKey as string,
collectionName, collectionName,
collectionConfig, collectionConfig,
}; };

View File

@@ -1,8 +1,10 @@
import { Pinecone } from '@pinecone-database/pinecone'; import { Pinecone } from '@pinecone-database/pinecone';
import { QdrantClient } from '@qdrant/js-client-rest';
import { MilvusClient } from '@zilliz/milvus2-sdk-node'; import { MilvusClient } from '@zilliz/milvus2-sdk-node';
import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow'; import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow';
import type { QdrantCredential } from '../../../VectorStoreQdrant/Qdrant.utils';
import { createQdrantClient } from '../../../VectorStoreQdrant/Qdrant.utils';
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) { export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
const credentials = await this.getCredentials('pineconeApi'); const credentials = await this.getCredentials('pineconeApi');
@@ -54,10 +56,7 @@ export async function supabaseTableNameSearch(this: ILoadOptionsFunctions) {
export async function qdrantCollectionsSearch(this: ILoadOptionsFunctions) { export async function qdrantCollectionsSearch(this: ILoadOptionsFunctions) {
const credentials = await this.getCredentials('qdrantApi'); const credentials = await this.getCredentials('qdrantApi');
const client = new QdrantClient({ const client = createQdrantClient(credentials as QdrantCredential);
url: credentials.qdrantUrl as string,
apiKey: credentials.apiKey as string,
});
const response = await client.getCollections(); const response = await client.getCollections();