UNPKG

n8n-nodes-rag

Version:

Advanced RAG (Retrieval-Augmented Generation) knowledge base nodes for n8n

279 lines 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RagRetrieval = void 0; const n8n_workflow_1 = require("n8n-workflow"); const EmbeddingGenerator_1 = require("../shared/EmbeddingGenerator"); const VectorStoreAdapter_1 = require("../shared/VectorStoreAdapter"); class RagRetrieval { constructor() { this.description = { displayName: 'RAG Retrieval', name: 'ragRetrieval', icon: 'file:ragRetrieval.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["searchType"]}}', description: 'Search and retrieve relevant information from knowledge base', defaults: { name: 'RAG Retrieval', }, inputs: [], outputs: [], properties: [ { displayName: 'Query', name: 'query', type: 'string', default: '', required: true, description: 'The search query text', }, { displayName: 'Search Type', name: 'searchType', type: 'options', options: [ { name: 'Vector Search', value: 'vector', description: 'Semantic search using vector embeddings', }, { name: 'Full-Text Search', value: 'fulltext', description: 'Keyword-based full-text search', }, { name: 'Hybrid Search', value: 'hybrid', description: 'Combination of vector and full-text search', }, ], default: 'vector', }, { displayName: 'Limit', name: 'limit', type: 'number', typeOptions: { minValue: 1, }, default: 50, description: 'Max number of results to return', }, { displayName: 'Score Threshold', name: 'threshold', type: 'number', default: 0.7, displayOptions: { show: { searchType: ['vector', 'hybrid'], }, }, description: 'Minimum similarity score for results (0.0-1.0)', }, { displayName: 'Hybrid Alpha', name: 'alpha', type: 'number', default: 0.5, displayOptions: { show: { searchType: ['hybrid'], }, }, description: 'Weight for vector vs full-text search (0.0=full-text only, 1.0=vector only)', }, { displayName: 'Embedding Provider', name: 'embeddingProvider', type: 'options', displayOptions: { show: { searchType: ['vector', 'hybrid'], }, }, options: [ { name: 'OpenAI', value: 'openai', }, { name: 'Hugging Face', value: 'huggingface', }, { name: 'Custom API', value: 'custom', }, ], default: 'openai', }, { displayName: 'Embedding Model', name: 'embeddingModel', type: 'string', displayOptions: { show: { searchType: ['vector', 'hybrid'], }, }, default: 'text-embedding-ada-002', description: 'Embedding model to use', }, { displayName: 'API Key', name: 'apiKey', type: 'string', typeOptions: { password: true, }, displayOptions: { show: { searchType: ['vector', 'hybrid'], }, }, default: '', description: 'API key for the embedding service', }, { displayName: 'Vector Store Provider', name: 'vectorStoreProvider', type: 'options', options: [ { name: 'Qdrant', value: 'qdrant', }, { name: 'Milvus', value: 'milvus', }, ], default: 'qdrant', }, { displayName: 'Vector Store Endpoint', name: 'vectorStoreEndpoint', type: 'string', default: 'http://localhost:6333', description: 'Vector database endpoint URL', }, { displayName: 'Vector Store API Key', name: 'vectorStoreApiKey', type: 'string', typeOptions: { password: true, }, default: '', description: 'API key for vector database (if required)', }, { displayName: 'Collection Name', name: 'collectionName', type: 'string', default: 'knowledge_base', description: 'Name of the collection or index to search', }, { displayName: 'Include Metadata', name: 'includeMetadata', type: 'boolean', default: true, description: 'Whether to include metadata in search results', }, { displayName: 'Metadata Filter', name: 'metadataFilter', type: 'string', default: '', description: 'JSON string for metadata filtering (optional)', }, ], }; } async execute() { var _a, _b; const query = this.getNodeParameter('query', 0); const searchType = this.getNodeParameter('searchType', 0); const limit = this.getNodeParameter('limit', 0); const threshold = this.getNodeParameter('threshold', 0); const alpha = this.getNodeParameter('alpha', 0); const includeMetadata = this.getNodeParameter('includeMetadata', 0); const metadataFilter = this.getNodeParameter('metadataFilter', 0); const vectorStoreConfig = { provider: this.getNodeParameter('vectorStoreProvider', 0), endpoint: this.getNodeParameter('vectorStoreEndpoint', 0), apiKey: this.getNodeParameter('vectorStoreApiKey', 0), collection: this.getNodeParameter('collectionName', 0), }; const vectorStore = (0, VectorStoreAdapter_1.createVectorStoreAdapter)(vectorStoreConfig); let queryEmbedding = null; if (searchType === 'vector' || searchType === 'hybrid') { const embeddingOptions = { enabled: true, provider: this.getNodeParameter('embeddingProvider', 0), model: this.getNodeParameter('embeddingModel', 0), apiKey: this.getNodeParameter('apiKey', 0), }; const queryChunks = await EmbeddingGenerator_1.EmbeddingGenerator.generateEmbeddings([{ id: 'query', text: query, metadata: {}, }], embeddingOptions); queryEmbedding = ((_a = queryChunks[0]) === null || _a === void 0 ? void 0 : _a.embedding) || null; } const searchOptions = { type: searchType, limit, threshold, alpha, includeMetadata, }; if (metadataFilter) { try { searchOptions.filter = JSON.parse(metadataFilter); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid metadata filter JSON: ${error}`); } } const results = await vectorStore.search(query, queryEmbedding, searchOptions); const returnData = results.map((result, index) => ({ json: { id: result.id, text: result.text, score: result.score, source: result.source, metadata: includeMetadata ? result.metadata : undefined, rank: index + 1, }, })); if (returnData.length === 0) { returnData.push({ json: { message: 'No results found', query, searchType, resultsCount: 0, }, }); } else { returnData.unshift({ json: { message: `Found ${results.length} results`, query, searchType, resultsCount: results.length, topScore: ((_b = results[0]) === null || _b === void 0 ? void 0 : _b.score) || 0, }, }); } return [returnData]; } } exports.RagRetrieval = RagRetrieval; //# sourceMappingURL=RagRetrieval.node.js.map