n8n-nodes-rag
Version:
Advanced RAG (Retrieval-Augmented Generation) knowledge base nodes for n8n
279 lines • 10.8 kB
JavaScript
;
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