mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat: Weaviate Vector Store Node for Langchain (#16856)
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
import type { ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export class WeaviateApi implements ICredentialType {
|
||||
name = 'weaviateApi';
|
||||
|
||||
displayName = 'Weaviate Credentials';
|
||||
|
||||
documentationUrl = 'https://docs.n8n.io/integrations/builtin/credentials/weaviate/';
|
||||
|
||||
properties: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Connection Type',
|
||||
name: 'connection_type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Weaviate Cloud',
|
||||
value: 'weaviate_cloud',
|
||||
},
|
||||
{
|
||||
name: 'Custom Connection',
|
||||
value: 'custom_connection',
|
||||
},
|
||||
],
|
||||
default: 'weaviate_cloud',
|
||||
description:
|
||||
'Choose whether to connect to a Weaviate Cloud instance or a custom Weaviate instance.',
|
||||
},
|
||||
{
|
||||
displayName: 'Weaviate Cloud Endpoint',
|
||||
name: 'weaviate_cloud_endpoint',
|
||||
description: 'The Endpoint of a Weaviate Cloud instance.',
|
||||
placeholder: 'https://your-cluster.weaviate.cloud',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['weaviate_cloud'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Weaviate Api Key',
|
||||
name: 'weaviate_api_key',
|
||||
description: 'The API key for the Weaviate instance.',
|
||||
type: 'string',
|
||||
typeOptions: { password: true },
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection HTTP Host',
|
||||
name: 'custom_connection_http_host',
|
||||
description: 'The host of your Weaviate instance.',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: 'weaviate',
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection HTTP Port',
|
||||
name: 'custom_connection_http_port',
|
||||
description: 'The port of your Weaviate instance.',
|
||||
type: 'number',
|
||||
required: true,
|
||||
default: 8080,
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection HTTP Secure',
|
||||
name: 'custom_connection_http_secure',
|
||||
description: 'Whether to use a secure connection for HTTP.',
|
||||
type: 'boolean',
|
||||
required: true,
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection gRPC Host',
|
||||
name: 'custom_connection_grpc_host',
|
||||
description: 'The gRPC host of your Weaviate instance.',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: 'weaviate',
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection gRPC Port',
|
||||
name: 'custom_connection_grpc_port',
|
||||
description: 'The gRPC port of your Weaviate instance.',
|
||||
type: 'number',
|
||||
required: true,
|
||||
default: 50051,
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Connection gRPC Secure',
|
||||
name: 'custom_connection_grpc_secure',
|
||||
description: 'Whether to use a secure connection for gRPC.',
|
||||
type: 'boolean',
|
||||
required: true,
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
connection_type: ['custom_connection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
test: ICredentialTestRequest = {
|
||||
request: {
|
||||
baseURL:
|
||||
'={{$credentials.weaviate_cloud_endpoint?$credentials.weaviate_cloud_endpoint.startsWith("http://") || $credentials.weaviate_cloud_endpoint.startsWith("https://")?$credentials.weaviate_cloud_endpoint:"https://" + $credentials.weaviate_cloud_endpoint:($credentials.custom_connection_http_secure ? "https" : "http") + "://" + $credentials.custom_connection_http_host + ":" + $credentials.custom_connection_http_port }}',
|
||||
url: '/v1/nodes',
|
||||
disableFollowRedirect: false,
|
||||
headers: {
|
||||
Authorization:
|
||||
'={{$if($credentials.weaviate_api_key, "Bearer " + $credentials.weaviate_api_key, undefined)}}',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
import type { Embeddings } from '@langchain/core/embeddings';
|
||||
import { WeaviateStore } from '@langchain/weaviate';
|
||||
import type { WeaviateLibArgs } from '@langchain/weaviate';
|
||||
import type {
|
||||
IDataObject,
|
||||
INodeProperties,
|
||||
INodePropertyCollection,
|
||||
INodePropertyOptions,
|
||||
} from 'n8n-workflow';
|
||||
import { type ProxiesParams, type TimeoutParams } from 'weaviate-client';
|
||||
|
||||
import type { WeaviateCompositeFilter, WeaviateCredential } from './Weaviate.utils';
|
||||
import { createWeaviateClient, parseCompositeFilter } from './Weaviate.utils';
|
||||
import { createVectorStoreNode } from '../shared/createVectorStoreNode/createVectorStoreNode';
|
||||
import { weaviateCollectionsSearch } from '../shared/createVectorStoreNode/methods/listSearch';
|
||||
import { weaviateCollectionRLC } from '../shared/descriptions';
|
||||
|
||||
class ExtendedWeaviateVectorStore extends WeaviateStore {
|
||||
private static defaultFilter: WeaviateCompositeFilter;
|
||||
|
||||
static async fromExistingCollection(
|
||||
embeddings: Embeddings,
|
||||
args: WeaviateLibArgs,
|
||||
defaultFilter?: WeaviateCompositeFilter,
|
||||
): Promise<WeaviateStore> {
|
||||
if (defaultFilter) {
|
||||
ExtendedWeaviateVectorStore.defaultFilter = defaultFilter;
|
||||
}
|
||||
return await super.fromExistingIndex(embeddings, args);
|
||||
}
|
||||
|
||||
async similaritySearchVectorWithScore(query: number[], k: number, filter?: IDataObject) {
|
||||
filter = filter ?? ExtendedWeaviateVectorStore.defaultFilter;
|
||||
if (filter) {
|
||||
const composedFilter = parseCompositeFilter(filter as WeaviateCompositeFilter);
|
||||
return await super.similaritySearchVectorWithScore(query, k, composedFilter);
|
||||
} else {
|
||||
return await super.similaritySearchVectorWithScore(query, k, undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sharedFields: INodeProperties[] = [weaviateCollectionRLC];
|
||||
|
||||
const shared_options: Array<INodePropertyOptions | INodeProperties | INodePropertyCollection> = [
|
||||
{
|
||||
displayName: 'Tenant Name',
|
||||
name: 'tenant',
|
||||
type: 'string',
|
||||
default: undefined,
|
||||
validateType: 'string',
|
||||
description: 'Tenant Name. Collection must have been created with tenant support enabled.',
|
||||
},
|
||||
{
|
||||
displayName: 'Text Key',
|
||||
name: 'textKey',
|
||||
type: 'string',
|
||||
default: 'text',
|
||||
validateType: 'string',
|
||||
description: 'The key in the document that contains the embedded text',
|
||||
},
|
||||
{
|
||||
displayName: 'Skip Init Checks',
|
||||
name: 'skip_init_checks',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
validateType: 'boolean',
|
||||
description: 'Whether to skip init checks while instantiating the client',
|
||||
},
|
||||
{
|
||||
displayName: 'Init Timeout',
|
||||
name: 'timeout_init',
|
||||
type: 'number',
|
||||
default: 2,
|
||||
validateType: 'number',
|
||||
description: 'Number of timeout seconds for initial checks',
|
||||
},
|
||||
{
|
||||
displayName: 'Insert Timeout',
|
||||
name: 'timeout_insert',
|
||||
type: 'number',
|
||||
default: 90,
|
||||
validateType: 'number',
|
||||
description: 'Number of timeout seconds for inserts',
|
||||
},
|
||||
{
|
||||
displayName: 'Query Timeout',
|
||||
name: 'timeout_query',
|
||||
type: 'number',
|
||||
default: 30,
|
||||
validateType: 'number',
|
||||
description: 'Number of timeout seconds for queries',
|
||||
},
|
||||
{
|
||||
displayName: 'GRPC Proxy',
|
||||
name: 'proxy_grpc',
|
||||
type: 'string',
|
||||
default: undefined,
|
||||
validateType: 'string',
|
||||
description: 'Proxy to use for GRPC',
|
||||
},
|
||||
];
|
||||
|
||||
const insertFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
options: [
|
||||
...shared_options,
|
||||
{
|
||||
displayName: 'Clear Data',
|
||||
name: 'clearStore',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to clear the Collection/Tenant before inserting new data',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const retrieveFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Search Filters',
|
||||
name: 'searchFilterJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
rows: 5,
|
||||
},
|
||||
default:
|
||||
'{\n "OR": [\n {\n "path": ["pdf_info_Author"],\n "operator": "Equal",\n "valueString": "Elis"\n },\n {\n "path": ["pdf_info_Author"],\n "operator": "Equal",\n "valueString": "Pinnacle"\n } \n ]\n}',
|
||||
validateType: 'object',
|
||||
description:
|
||||
'Filter pageContent or metadata using this <a href="https://weaviate.io/" target="_blank">filtering syntax</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Metadata Keys',
|
||||
name: 'metadataKeys',
|
||||
type: 'string',
|
||||
default: 'source,page',
|
||||
validateType: 'string',
|
||||
description: 'Select the metadata to retrieve along the content',
|
||||
},
|
||||
...shared_options,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export class VectorStoreWeaviate extends createVectorStoreNode<ExtendedWeaviateVectorStore>({
|
||||
meta: {
|
||||
displayName: 'Weaviate Vector Store',
|
||||
name: 'vectorStoreWeaviate',
|
||||
description: 'Work with your data in a Weaviate Cluster',
|
||||
icon: 'file:weaviate.svg',
|
||||
docsUrl:
|
||||
'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreweaviate/',
|
||||
credentials: [
|
||||
{
|
||||
name: 'weaviateApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
methods: {
|
||||
listSearch: { weaviateCollectionsSearch },
|
||||
},
|
||||
loadFields: retrieveFields,
|
||||
insertFields,
|
||||
sharedFields,
|
||||
retrieveFields,
|
||||
async getVectorStoreClient(context, filter, embeddings, itemIndex) {
|
||||
const collection = context.getNodeParameter('weaviateCollection', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const options = context.getNodeParameter('options', itemIndex, {}) as {
|
||||
tenant?: string;
|
||||
textKey?: string;
|
||||
timeout_init: number;
|
||||
timeout_insert: number;
|
||||
timeout_query: number;
|
||||
skip_init_checks: boolean;
|
||||
proxy_grpc: string;
|
||||
metadataKeys?: string;
|
||||
};
|
||||
// check if textKey is valid
|
||||
|
||||
const credentials = await context.getCredentials('weaviateApi');
|
||||
|
||||
const timeout = {
|
||||
query: options.timeout_query,
|
||||
init: options.timeout_init,
|
||||
insert: options.timeout_insert,
|
||||
};
|
||||
|
||||
const proxies = {
|
||||
grpc: options.proxy_grpc,
|
||||
};
|
||||
|
||||
const client = await createWeaviateClient(
|
||||
credentials as WeaviateCredential,
|
||||
timeout as TimeoutParams,
|
||||
proxies as ProxiesParams,
|
||||
options.skip_init_checks as boolean,
|
||||
);
|
||||
|
||||
const metadataKeys = options.metadataKeys ? options.metadataKeys.split(',') : [];
|
||||
const config: WeaviateLibArgs = {
|
||||
client,
|
||||
indexName: collection,
|
||||
tenant: options.tenant ? options.tenant : undefined,
|
||||
textKey: options.textKey ? options.textKey : 'text',
|
||||
metadataKeys: metadataKeys as string[] | undefined,
|
||||
};
|
||||
|
||||
const validFilter = (filter && Object.keys(filter).length > 0 ? filter : undefined) as
|
||||
| WeaviateCompositeFilter
|
||||
| undefined;
|
||||
return await ExtendedWeaviateVectorStore.fromExistingCollection(
|
||||
embeddings,
|
||||
config,
|
||||
validFilter,
|
||||
);
|
||||
},
|
||||
async populateVectorStore(context, embeddings, documents, itemIndex) {
|
||||
const collectionName = context.getNodeParameter('weaviateCollection', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const options = context.getNodeParameter('options', itemIndex, {}) as {
|
||||
tenant?: string;
|
||||
textKey?: string;
|
||||
clearStore?: boolean;
|
||||
metadataKeys?: string;
|
||||
};
|
||||
|
||||
const credentials = await context.getCredentials('weaviateApi');
|
||||
|
||||
const metadataKeys = options.metadataKeys ? options.metadataKeys.split(',') : [];
|
||||
|
||||
const client = await createWeaviateClient(credentials as WeaviateCredential);
|
||||
|
||||
const config: WeaviateLibArgs = {
|
||||
client,
|
||||
indexName: collectionName,
|
||||
tenant: options.tenant ? options.tenant : undefined,
|
||||
textKey: options.textKey ? options.textKey : 'text',
|
||||
metadataKeys: metadataKeys as string[] | undefined,
|
||||
};
|
||||
|
||||
if (options.clearStore) {
|
||||
if (!options.tenant) {
|
||||
await client.collections.delete(collectionName);
|
||||
} else {
|
||||
const collection = client.collections.get(collectionName);
|
||||
await collection.tenants.remove([{ name: options.tenant }]);
|
||||
}
|
||||
}
|
||||
|
||||
await WeaviateStore.fromDocuments(documents, embeddings, config);
|
||||
},
|
||||
}) {}
|
||||
@@ -0,0 +1,141 @@
|
||||
import { OperationalError } from 'n8n-workflow';
|
||||
import type {
|
||||
FilterValue,
|
||||
GeoRangeFilter,
|
||||
ProxiesParams,
|
||||
TimeoutParams,
|
||||
WeaviateClient,
|
||||
} from 'weaviate-client';
|
||||
import weaviate, { Filters } from 'weaviate-client';
|
||||
|
||||
export type WeaviateCredential = {
|
||||
weaviate_cloud_endpoint: string;
|
||||
weaviate_api_key: string;
|
||||
custom_connection_http_host: string;
|
||||
custom_connection_http_port: number;
|
||||
custom_connection_http_secure: boolean;
|
||||
custom_connection_grpc_host: string;
|
||||
custom_connection_grpc_port: number;
|
||||
custom_connection_grpc_secure: boolean;
|
||||
};
|
||||
|
||||
export async function createWeaviateClient(
|
||||
credentials: WeaviateCredential,
|
||||
timeout?: TimeoutParams,
|
||||
proxies?: ProxiesParams,
|
||||
skipInitChecks: boolean = false,
|
||||
): Promise<WeaviateClient> {
|
||||
if (credentials.weaviate_cloud_endpoint) {
|
||||
const weaviateClient: WeaviateClient = await weaviate.connectToWeaviateCloud(
|
||||
credentials.weaviate_cloud_endpoint,
|
||||
{
|
||||
authCredentials: new weaviate.ApiKey(credentials.weaviate_api_key),
|
||||
timeout,
|
||||
skipInitChecks,
|
||||
},
|
||||
);
|
||||
return weaviateClient;
|
||||
} else {
|
||||
const weaviateClient: WeaviateClient = await weaviate.connectToCustom({
|
||||
httpHost: credentials.custom_connection_http_host,
|
||||
httpPort: credentials.custom_connection_http_port,
|
||||
grpcHost: credentials.custom_connection_grpc_host,
|
||||
grpcPort: credentials.custom_connection_grpc_port,
|
||||
grpcSecure: credentials.custom_connection_grpc_secure,
|
||||
httpSecure: credentials.custom_connection_http_secure,
|
||||
authCredentials: credentials.weaviate_api_key
|
||||
? new weaviate.ApiKey(credentials.weaviate_api_key)
|
||||
: undefined,
|
||||
timeout,
|
||||
proxies,
|
||||
skipInitChecks,
|
||||
});
|
||||
return weaviateClient;
|
||||
}
|
||||
}
|
||||
type WeaviateFilterUnit = {
|
||||
path: string[];
|
||||
operator: string;
|
||||
valueString?: string;
|
||||
valueTextArray?: string[];
|
||||
valueBoolean?: boolean;
|
||||
valueNumber?: number;
|
||||
valueGeoCoordinates?: GeoRangeFilter;
|
||||
};
|
||||
|
||||
export type WeaviateCompositeFilter = { AND: WeaviateFilterUnit[] } | { OR: WeaviateFilterUnit[] };
|
||||
|
||||
function buildFilter(filter: WeaviateFilterUnit): FilterValue {
|
||||
const { path, operator } = filter;
|
||||
const property = weaviate.filter.byProperty(path[0]);
|
||||
|
||||
switch (operator.toLowerCase()) {
|
||||
case 'equal':
|
||||
if (filter.valueString !== undefined) return property.equal(filter.valueString);
|
||||
if (filter.valueNumber !== undefined) return property.equal(filter.valueNumber);
|
||||
break;
|
||||
|
||||
case 'like':
|
||||
if (filter.valueString === undefined) {
|
||||
throw new OperationalError("Missing 'valueString' for 'like' operator.");
|
||||
}
|
||||
return property.like(filter.valueString);
|
||||
|
||||
case 'containsany':
|
||||
if (filter.valueTextArray === undefined) {
|
||||
throw new OperationalError("Missing 'valueTextArray' for 'containsAny' operator.");
|
||||
}
|
||||
return property.containsAny(filter.valueTextArray);
|
||||
|
||||
case 'containsall':
|
||||
if (filter.valueTextArray === undefined) {
|
||||
throw new OperationalError("Missing 'valueTextArray' for 'containsAll' operator.");
|
||||
}
|
||||
return property.containsAll(filter.valueTextArray);
|
||||
|
||||
case 'greaterthan':
|
||||
if (filter.valueNumber === undefined) {
|
||||
throw new OperationalError("Missing 'valueNumber' for 'greaterThan' operator.");
|
||||
}
|
||||
return property.greaterThan(filter.valueNumber);
|
||||
|
||||
case 'lessthan':
|
||||
if (filter.valueNumber === undefined) {
|
||||
throw new OperationalError("Missing 'valueNumber' for 'lessThan' operator.");
|
||||
}
|
||||
return property.lessThan(filter.valueNumber);
|
||||
|
||||
case 'isnull':
|
||||
if (filter.valueBoolean === undefined) {
|
||||
throw new OperationalError("Missing 'valueBoolean' for 'isNull' operator.");
|
||||
}
|
||||
return property.isNull(filter.valueBoolean);
|
||||
|
||||
case 'withingeorange':
|
||||
if (!filter.valueGeoCoordinates) {
|
||||
throw new OperationalError("Missing 'valueGeoCoordinates' for 'withinGeoRange' operator.");
|
||||
}
|
||||
return property.withinGeoRange(filter.valueGeoCoordinates);
|
||||
|
||||
default:
|
||||
throw new OperationalError(`Unsupported operator: ${operator}`);
|
||||
}
|
||||
|
||||
throw new OperationalError(`No valid filter value provided for operator: ${operator}`);
|
||||
}
|
||||
|
||||
export function parseCompositeFilter(
|
||||
filter: WeaviateCompositeFilter | WeaviateFilterUnit,
|
||||
): FilterValue {
|
||||
// Handle composite filters (AND/OR)
|
||||
if (typeof filter === 'object' && ('AND' in filter || 'OR' in filter)) {
|
||||
if ('AND' in filter) {
|
||||
return Filters.and(...filter.AND.map(buildFilter));
|
||||
} else if ('OR' in filter) {
|
||||
return Filters.or(...filter.OR.map(buildFilter));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle individual filter units
|
||||
return buildFilter(filter);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?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" preserveAspectRatio="xMidYMid" xmlns:bx="https://boxy-svg.com"><title>qdrant</title><defs><linearGradient id="linear-gradient" x1="39.84" y1="-2385.28" x2="34.01" y2="-2442.48" gradientTransform="translate(0 2433.92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#75be2c"/><stop offset="0.86" stop-color="#9dc03b"/></linearGradient><linearGradient id="linear-gradient-2" x1="37.06" y1="-2409.12" x2="37.06" y2="-2390.37" gradientTransform="translate(0 2433.92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#238d37"/><stop offset="0.94" stop-color="#35537f"/></linearGradient><linearGradient id="linear-gradient-3" x1="35.07" y1="-2418.83" x2="37.98" y2="-2399.75" gradientTransform="translate(0 2433.92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#67d84d"/><stop offset="1" stop-color="#348522"/></linearGradient><linearGradient id="linear-gradient-4" x1="64.03" y1="-2433.87" x2="64.03" y2="-2400.61" gradientTransform="translate(0 2433.92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e4d00a"/><stop offset="0.56" stop-color="#c4d132"/></linearGradient><linearGradient id="linear-gradient-5" x1="10.04" y1="-2433.87" x2="10.04" href="#linear-gradient-4"/><linearGradient id="linear-gradient-6" x1="56.43" y1="-2400.25" x2="56.43" y2="-2389.16" gradientTransform="translate(0 2433.92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#8ab11b"/><stop offset="1" stop-color="#6eaf02"/></linearGradient><linearGradient id="linear-gradient-7" x1="64.51" y1="-2413.64" x2="62.18" y2="-2394.97" href="#linear-gradient"/><linearGradient id="linear-gradient-8" x1="17.64" y1="-2400.21" x2="17.64" y2="-2389.17" href="#linear-gradient-6"/><linearGradient id="linear-gradient-9" x1="11.82" y1="-2413.55" x2="9.53" y2="-2391.1" href="#linear-gradient"/><bx:export><bx:file format="svg" path="qdrant.svg"/></bx:export></defs><g transform="matrix(3.331938, 0, 0, 3.331938, 3.665985, 60.223675)" style=""><path class="cls-1" d="M71.67,7.95L58.85.5c-2.15-1.25-4.85.31-4.85,2.79v18.84l-9.1-5.24c-4.88-2.81-10.88-2.8-15.74.02l-9.06,5.24V3.28c0-2.49-2.69-4.04-4.85-2.79L2.4,7.94c-1.49.86-2.4,2.46-2.4,4.18v17.71c0,1.24.31,2.42.88,3.46h0c.58,1.07,1.42,1.98,2.48,2.66l6.61,4.22,5.06,3.22c3.04,1.93,6.95,1.78,9.83-.39l.38-.3s.07-.06.11-.08l7.63-5.82c2.23-1.71,5.88-1.71,8.12,0l7.61,5.8s.03.02.04.03l.47.37c2.87,2.17,6.79,2.32,9.83.39l5.06-3.23,6.63-4.22c1.04-.67,1.88-1.59,2.46-2.64s.89-2.23.89-3.47V12.13h0c0-1.72-.91-3.32-2.4-4.18h.01Z" style="fill: url("#linear-gradient"); stroke-width: 0px;"/><path class="cls-3" d="M54.1,33.62v6.36c0,1.96-1.41,3.56-3.11,3.56-.67,0-1.51-.34-2.29-.93l-7.61-5.8c-2.23-1.71-5.88-1.71-8.12,0l-7.63,5.82c-.76.57-1.25.74-1.97.74-1.77.02-3.35-1.31-3.35-3.39v-6.34l10.9-7.04c3.74-2.41,8.52-2.41,12.25,0l10.92,6.88v.13h0Z" style="fill: url("#linear-gradient-2"); stroke-width: 0px;"/><path class="cls-4" d="M54,22.13l.03,11.59-10.84-6.93c-3.73-2.39-8.51-2.39-12.25,0l-10.87,6.94.02-11.58,9.07-5.25c4.86-2.82,10.86-2.82,15.74-.02l9.1,5.24h0Z" style="fill: url("#linear-gradient-3"); stroke-width: 0px;"/><path class="cls-2" d="M74.07,12.13v17.7c0,1.25-.31,2.42-.89,3.47l-19.19-11.17V3.28c0-2.49,2.7-4.04,4.85-2.79l12.82,7.46c1.49.86,2.4,2.46,2.4,4.18h0Z" style="fill: url("#linear-gradient-4"); stroke-width: 0px;"/><path class="cls-8" d="M20.08,3.28v18.87L.88,33.31C.31,32.26,0,31.08,0,29.84V12.13C0,10.41.91,8.81,2.4,7.95L15.23.49c2.15-1.25,4.85.31,4.85,2.79h0Z" style="fill: url("#linear-gradient-5"); stroke-width: 0px;"/><path class="cls-9" d="M50.72,43.32c1.7,0,3.3-1.34,3.3-3.28v-6.36s10.13,6.47,10.13,6.47l-5.12,3.26c-3.04,1.93-6.95,1.79-9.83-.39l-.48-.38c.72.49,1.33.68,2,.68h0Z" style="fill: url("#linear-gradient-6"); stroke-width: 0px;"/><path class="cls-7" d="M73.18,33.31c-.58,1.05-1.42,1.97-2.46,2.64l-6.63,4.22-10.08-6.45-.03-11.59,19.19,11.18h0Z" style="fill: url("#linear-gradient-7"); stroke-width: 0px;"/><path class="cls-5" d="M20.08,40.03c0,1.94,1.61,3.47,3.3,3.28.75-.09,1.34-.2,1.94-.66l-.46.36c-2.87,2.16-6.79,2.32-9.83.39l-5.06-3.23h0s10.11-6.46,10.11-6.46v6.31h0Z" style="fill: url("#linear-gradient-8"); stroke-width: 0px;"/><path class="cls-6" d="M20.08,22.15v11.57l-10.11,6.45h0s-6.61-4.2-6.61-4.2c-1.05-.67-1.9-1.59-2.48-2.66l19.19-11.16h0Z" style="fill: url("#linear-gradient-9"); stroke-width: 0px;"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -4,6 +4,8 @@ import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from '
|
||||
|
||||
import type { QdrantCredential } from '../../../VectorStoreQdrant/Qdrant.utils';
|
||||
import { createQdrantClient } from '../../../VectorStoreQdrant/Qdrant.utils';
|
||||
import type { WeaviateCredential } from '../../../VectorStoreWeaviate/Weaviate.utils';
|
||||
import { createWeaviateClient } from '../../../VectorStoreWeaviate/Weaviate.utils';
|
||||
|
||||
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
|
||||
const credentials = await this.getCredentials('pineconeApi');
|
||||
@@ -89,3 +91,18 @@ export async function milvusCollectionsSearch(this: ILoadOptionsFunctions) {
|
||||
|
||||
return { results };
|
||||
}
|
||||
|
||||
export async function weaviateCollectionsSearch(this: ILoadOptionsFunctions) {
|
||||
const credentials = await this.getCredentials('weaviateApi');
|
||||
|
||||
const client = await createWeaviateClient(credentials as WeaviateCredential);
|
||||
|
||||
const collections = await client.collections.listAll();
|
||||
|
||||
const results = collections.map((collection: { name: string }) => ({
|
||||
name: collection.name,
|
||||
value: collection.name,
|
||||
}));
|
||||
|
||||
return { results };
|
||||
}
|
||||
|
||||
@@ -91,3 +91,26 @@ export const milvusCollectionRLC: INodeProperties = {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const weaviateCollectionRLC: INodeProperties = {
|
||||
displayName: 'Weaviate Collection',
|
||||
name: 'weaviateCollection',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'From List',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
typeOptions: {
|
||||
searchListMethod: 'weaviateCollectionsSearch',
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"dist/credentials/QdrantApi.credentials.js",
|
||||
"dist/credentials/SearXngApi.credentials.js",
|
||||
"dist/credentials/SerpApi.credentials.js",
|
||||
"dist/credentials/WeaviateApi.credentials.js",
|
||||
"dist/credentials/WolframAlphaApi.credentials.js",
|
||||
"dist/credentials/XAiApi.credentials.js",
|
||||
"dist/credentials/XataApi.credentials.js",
|
||||
@@ -133,6 +134,7 @@
|
||||
"dist/nodes/vector_store/VectorStoreSupabase/VectorStoreSupabase.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreSupabaseInsert/VectorStoreSupabaseInsert.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreSupabaseLoad/VectorStoreSupabaseLoad.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreWeaviate/VectorStoreWeaviate.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreZep/VectorStoreZep.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreZepInsert/VectorStoreZepInsert.node.js",
|
||||
"dist/nodes/vector_store/VectorStoreZepLoad/VectorStoreZepLoad.node.js",
|
||||
@@ -178,6 +180,7 @@
|
||||
"@langchain/qdrant": "0.1.2",
|
||||
"@langchain/redis": "0.1.1",
|
||||
"@langchain/textsplitters": "0.1.0",
|
||||
"@langchain/weaviate": "0.2.0",
|
||||
"@modelcontextprotocol/sdk": "1.12.0",
|
||||
"@mozilla/readability": "0.6.0",
|
||||
"@n8n/client-oauth2": "workspace:*",
|
||||
@@ -216,6 +219,7 @@
|
||||
"sqlite3": "5.1.7",
|
||||
"temp": "0.9.4",
|
||||
"tmp-promise": "3.0.3",
|
||||
"weaviate-client": "3.6.2",
|
||||
"zod": "catalog:",
|
||||
"zod-to-json-schema": "3.23.3"
|
||||
}
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -912,6 +912,9 @@ importers:
|
||||
'@langchain/textsplitters':
|
||||
specifier: 0.1.0
|
||||
version: 0.1.0(@langchain/core@0.3.59(openai@4.103.0(encoding@0.1.13)(ws@8.18.2)(zod@3.25.67)))
|
||||
'@langchain/weaviate':
|
||||
specifier: 0.2.0
|
||||
version: 0.2.0(@langchain/core@0.3.59(openai@4.103.0(encoding@0.1.13)(ws@8.18.2)(zod@3.25.67)))(encoding@0.1.13)
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 1.12.0
|
||||
version: 1.12.0
|
||||
@@ -1026,6 +1029,9 @@ importers:
|
||||
tmp-promise:
|
||||
specifier: 3.0.3
|
||||
version: 3.0.3
|
||||
weaviate-client:
|
||||
specifier: 3.6.2
|
||||
version: 3.6.2(encoding@0.1.13)
|
||||
zod:
|
||||
specifier: 3.25.67
|
||||
version: 3.25.67
|
||||
|
||||
Reference in New Issue
Block a user