@retrivora-ai/rag-engine 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ChromaDBProvider-QNI7UCX4.mjs +8 -0
- package/dist/DocumentChunker-cfaMidtA.d.mts +93 -0
- package/dist/DocumentChunker-cfaMidtA.d.ts +93 -0
- package/dist/LLMFactory-JFOY2V4X.mjs +8 -0
- package/dist/MilvusProvider-OO6QGZDZ.mjs +8 -0
- package/dist/MongoDBProvider-WWVJG3WT.mjs +8 -0
- package/dist/PineconeProvider-NJ675H7U.mjs +8 -0
- package/dist/PostgreSQLProvider-ISNMD3BE.mjs +8 -0
- package/dist/QdrantProvider-LJWOIGES.mjs +8 -0
- package/dist/RagConfig-DG_0f8ka.d.mts +145 -0
- package/dist/RagConfig-DG_0f8ka.d.ts +145 -0
- package/dist/RedisProvider-ASONNYBI.mjs +8 -0
- package/dist/WeaviateProvider-PSDCUGC7.mjs +8 -0
- package/dist/chunk-6FODXNUF.mjs +91 -0
- package/dist/chunk-7NXI6ZWX.mjs +89 -0
- package/dist/chunk-AALIF3AL.mjs +91 -0
- package/dist/chunk-BP4U4TT5.mjs +548 -0
- package/dist/chunk-HUGLYKD6.mjs +84 -0
- package/dist/chunk-I4E63NIC.mjs +24 -0
- package/dist/chunk-JI6VD5TJ.mjs +387 -0
- package/dist/chunk-QEYVWVT5.mjs +102 -0
- package/dist/chunk-S5DRHETN.mjs +110 -0
- package/dist/{chunk-ZPXLQR5Q.mjs → chunk-UKDXCXW7.mjs} +5 -23
- package/dist/chunk-V75V7BT2.mjs +117 -0
- package/dist/chunk-VOIWNO5O.mjs +11 -0
- package/dist/chunk-VPNRDXIA.mjs +74 -0
- package/dist/handlers/index.d.mts +9 -33
- package/dist/handlers/index.d.ts +9 -33
- package/dist/handlers/index.js +1477 -962
- package/dist/handlers/index.mjs +4 -2
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -2
- package/dist/index.mjs +4 -2
- package/dist/server.d.mts +220 -53
- package/dist/server.d.ts +220 -53
- package/dist/server.js +1531 -1099
- package/dist/server.mjs +55 -131
- package/package.json +19 -2
- package/src/app/page.tsx +1 -1
- package/src/components/MessageBubble.tsx +1 -1
- package/src/components/SourceCard.tsx +1 -1
- package/src/config/RagConfig.ts +1 -1
- package/src/config/serverConfig.ts +2 -2
- package/src/core/ConfigResolver.ts +69 -0
- package/src/core/Pipeline.ts +101 -0
- package/src/core/ProviderRegistry.ts +71 -0
- package/src/core/VectorPlugin.ts +52 -0
- package/src/handlers/index.ts +21 -100
- package/src/hooks/useRagChat.ts +1 -1
- package/src/index.ts +2 -6
- package/src/providers/vectordb/BaseVectorProvider.ts +61 -0
- package/src/providers/vectordb/ChromaDBProvider.ts +94 -0
- package/src/providers/vectordb/MilvusProvider.ts +100 -0
- package/src/providers/vectordb/MongoDBProvider.ts +118 -0
- package/src/{vectordb/adapters/PineconeAdapter.ts → providers/vectordb/PineconeProvider.ts} +21 -56
- package/src/{vectordb/adapters/PgVectorAdapter.ts → providers/vectordb/PostgreSQLProvider.ts} +23 -58
- package/src/providers/vectordb/QdrantProvider.ts +95 -0
- package/src/providers/vectordb/RedisProvider.ts +84 -0
- package/src/providers/vectordb/WeaviateProvider.ts +124 -0
- package/src/server.ts +16 -8
- package/src/test-refactor.ts +59 -0
- package/src/types/index.ts +24 -0
- package/src/utils/templateUtils.ts +6 -6
- package/dist/DocumentChunker-BUrIrcPk.d.mts +0 -43
- package/dist/DocumentChunker-BUrIrcPk.d.ts +0 -43
- package/dist/RAGPipeline-BmkIv1HD.d.mts +0 -298
- package/dist/RAGPipeline-BmkIv1HD.d.ts +0 -298
- package/dist/chunk-NVOMLHXW.mjs +0 -1259
- package/src/rag/RAGPipeline.ts +0 -200
- package/src/vectordb/IVectorDB.ts +0 -75
- package/src/vectordb/VectorDBFactory.ts +0 -41
- package/src/vectordb/adapters/MongoDbAdapter.ts +0 -175
- package/src/vectordb/adapters/UniversalVectorDBAdapter.ts +0 -177
|
@@ -1,37 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pinecone Vector DB Adapter
|
|
3
|
-
*
|
|
4
|
-
* Required options in VectorDBConfig.options:
|
|
5
|
-
* - apiKey: string – Pinecone API key
|
|
6
|
-
* - environment?: string – Pinecone environment (legacy, optional for new projects)
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
1
|
import { Pinecone, RecordMetadata } from '@pinecone-database/pinecone';
|
|
10
|
-
import { IVectorDB, VectorMatch, UpsertDocument } from '../IVectorDB';
|
|
11
2
|
import { VectorDBConfig } from '../../config/RagConfig';
|
|
3
|
+
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
4
|
+
import { VectorMatch, UpsertDocument } from '../../types';
|
|
12
5
|
|
|
13
|
-
export class
|
|
6
|
+
export class PineconeProvider extends BaseVectorProvider {
|
|
14
7
|
private client!: Pinecone;
|
|
15
|
-
private readonly indexName: string;
|
|
16
8
|
private readonly apiKey: string;
|
|
17
9
|
|
|
18
10
|
constructor(config: VectorDBConfig) {
|
|
19
|
-
|
|
11
|
+
super(config);
|
|
20
12
|
const opts = config.options as Record<string, string>;
|
|
21
|
-
if (!opts.apiKey) throw new Error('[
|
|
13
|
+
if (!opts.apiKey) throw new Error('[PineconeProvider] options.apiKey is required');
|
|
22
14
|
this.apiKey = opts.apiKey;
|
|
23
15
|
}
|
|
24
16
|
|
|
25
17
|
async initialize(): Promise<void> {
|
|
26
18
|
this.client = new Pinecone({ apiKey: this.apiKey });
|
|
27
|
-
// Verify index exists
|
|
28
19
|
const indexes = await this.client.listIndexes();
|
|
29
20
|
const names = indexes.indexes?.map((i) => i.name) ?? [];
|
|
30
21
|
if (!names.includes(this.indexName)) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`[PineconeAdapter] Index "${this.indexName}" not found. ` +
|
|
33
|
-
`Available: ${names.join(', ')}`
|
|
34
|
-
);
|
|
22
|
+
throw new Error(`[PineconeProvider] Index "${this.indexName}" not found.`);
|
|
35
23
|
}
|
|
36
24
|
}
|
|
37
25
|
|
|
@@ -42,16 +30,11 @@ export class PineconeAdapter implements IVectorDB {
|
|
|
42
30
|
|
|
43
31
|
async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
|
|
44
32
|
await this.index(namespace).upsert({
|
|
45
|
-
records: [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
content: doc.content,
|
|
51
|
-
...(doc.metadata ?? {}),
|
|
52
|
-
} as RecordMetadata,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
33
|
+
records: [{
|
|
34
|
+
id: doc.id,
|
|
35
|
+
values: doc.vector,
|
|
36
|
+
metadata: { content: doc.content, ...(doc.metadata ?? {}) } as RecordMetadata,
|
|
37
|
+
}],
|
|
55
38
|
});
|
|
56
39
|
}
|
|
57
40
|
|
|
@@ -61,40 +44,25 @@ export class PineconeAdapter implements IVectorDB {
|
|
|
61
44
|
const records = docs.slice(i, i + BATCH).map((d) => ({
|
|
62
45
|
id: d.id,
|
|
63
46
|
values: d.vector,
|
|
64
|
-
metadata: {
|
|
65
|
-
content: d.content,
|
|
66
|
-
...(d.metadata ?? {}),
|
|
67
|
-
} as RecordMetadata,
|
|
47
|
+
metadata: { content: d.content, ...(d.metadata ?? {}) } as RecordMetadata,
|
|
68
48
|
}));
|
|
69
49
|
await this.index(namespace).upsert({ records });
|
|
70
50
|
}
|
|
71
51
|
}
|
|
72
52
|
|
|
73
|
-
async query(
|
|
74
|
-
vector: number[],
|
|
75
|
-
topK: number,
|
|
76
|
-
namespace?: string,
|
|
77
|
-
filter?: Record<string, unknown>
|
|
78
|
-
): Promise<VectorMatch[]> {
|
|
53
|
+
async query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]> {
|
|
79
54
|
const result = await this.index(namespace).query({
|
|
80
55
|
vector,
|
|
81
56
|
topK,
|
|
82
57
|
includeMetadata: true,
|
|
83
58
|
...(filter ? { filter } : {}),
|
|
84
59
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
id: m.id,
|
|
93
|
-
score: m.score ?? 0,
|
|
94
|
-
content,
|
|
95
|
-
metadata,
|
|
96
|
-
};
|
|
97
|
-
});
|
|
60
|
+
return (result.matches ?? []).map((m) => ({
|
|
61
|
+
id: m.id,
|
|
62
|
+
score: m.score ?? 0,
|
|
63
|
+
content: (m.metadata?.content || '') as string,
|
|
64
|
+
metadata: m.metadata as Record<string, unknown>,
|
|
65
|
+
}));
|
|
98
66
|
}
|
|
99
67
|
|
|
100
68
|
async delete(id: string, namespace?: string): Promise<void> {
|
|
@@ -109,13 +77,10 @@ export class PineconeAdapter implements IVectorDB {
|
|
|
109
77
|
try {
|
|
110
78
|
await this.client.listIndexes();
|
|
111
79
|
return true;
|
|
112
|
-
} catch
|
|
113
|
-
console.error('[PineconeAdapter] Ping failed:', err);
|
|
80
|
+
} catch {
|
|
114
81
|
return false;
|
|
115
82
|
}
|
|
116
83
|
}
|
|
117
84
|
|
|
118
|
-
async disconnect(): Promise<void> {
|
|
119
|
-
// Pinecone SDK is stateless REST, no persistent connection to close.
|
|
120
|
-
}
|
|
85
|
+
async disconnect(): Promise<void> {}
|
|
121
86
|
}
|
package/src/{vectordb/adapters/PgVectorAdapter.ts → providers/vectordb/PostgreSQLProvider.ts}
RENAMED
|
@@ -1,43 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pgVector Adapter
|
|
3
|
-
*
|
|
4
|
-
* Stores embeddings in a PostgreSQL table using the pgvector extension.
|
|
5
|
-
* Required options in VectorDBConfig.options:
|
|
6
|
-
* - connectionString: string – PostgreSQL connection string
|
|
7
|
-
* - dimensions?: number – vector dimensions (default 1536 for OpenAI ada-002)
|
|
8
|
-
*
|
|
9
|
-
* The adapter auto-creates the table and index on initialize().
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
1
|
import { Pool, PoolClient } from 'pg';
|
|
13
|
-
import { IVectorDB, VectorMatch, UpsertDocument } from '../IVectorDB';
|
|
14
2
|
import { VectorDBConfig } from '../../config/RagConfig';
|
|
3
|
+
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
4
|
+
import { VectorMatch, UpsertDocument } from '../../types';
|
|
15
5
|
|
|
16
|
-
|
|
6
|
+
/**
|
|
7
|
+
* PostgreSQLProvider — PostgreSQL implementation using the pgvector extension.
|
|
8
|
+
*/
|
|
9
|
+
export class PostgreSQLProvider extends BaseVectorProvider {
|
|
17
10
|
private pool!: Pool;
|
|
18
|
-
private readonly tableName: string;
|
|
19
11
|
private readonly dimensions: number;
|
|
20
12
|
private readonly connectionString: string;
|
|
13
|
+
private readonly tableName: string;
|
|
21
14
|
|
|
22
15
|
constructor(config: VectorDBConfig) {
|
|
23
|
-
|
|
16
|
+
super(config);
|
|
17
|
+
this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, '_');
|
|
24
18
|
const opts = config.options as Record<string, unknown>;
|
|
25
|
-
if (!opts.connectionString)
|
|
26
|
-
throw new Error('[PgVectorAdapter] options.connectionString is required');
|
|
27
|
-
}
|
|
19
|
+
if (!opts.connectionString) throw new Error('[PostgreSQLProvider] options.connectionString is required');
|
|
28
20
|
this.connectionString = opts.connectionString as string;
|
|
29
21
|
this.dimensions = (opts.dimensions as number) ?? 1536;
|
|
30
22
|
}
|
|
31
23
|
|
|
32
24
|
async initialize(): Promise<void> {
|
|
33
25
|
this.pool = new Pool({ connectionString: this.connectionString });
|
|
34
|
-
|
|
35
26
|
const client: PoolClient = await this.pool.connect();
|
|
36
27
|
try {
|
|
37
|
-
// Enable pgvector extension
|
|
38
28
|
await client.query('CREATE EXTENSION IF NOT EXISTS vector');
|
|
39
|
-
|
|
40
|
-
// Create the chunks table if it doesn't exist
|
|
41
29
|
await client.query(`
|
|
42
30
|
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
43
31
|
id TEXT PRIMARY KEY,
|
|
@@ -47,8 +35,6 @@ export class PgVectorAdapter implements IVectorDB {
|
|
|
47
35
|
embedding VECTOR(${this.dimensions})
|
|
48
36
|
)
|
|
49
37
|
`);
|
|
50
|
-
|
|
51
|
-
// Create HNSW index for fast approximate nearest-neighbour search
|
|
52
38
|
await client.query(`
|
|
53
39
|
CREATE INDEX IF NOT EXISTS ${this.tableName}_embedding_idx
|
|
54
40
|
ON ${this.tableName}
|
|
@@ -74,25 +60,17 @@ export class PgVectorAdapter implements IVectorDB {
|
|
|
74
60
|
}
|
|
75
61
|
|
|
76
62
|
async batchUpsert(docs: UpsertDocument[], namespace = ''): Promise<void> {
|
|
77
|
-
// Sequential for simplicity; swap for COPY or multi-row INSERT for perf
|
|
78
63
|
for (const doc of docs) {
|
|
79
64
|
await this.upsert(doc, namespace);
|
|
80
65
|
}
|
|
81
66
|
}
|
|
82
67
|
|
|
83
|
-
async query(
|
|
84
|
-
vector: number[],
|
|
85
|
-
topK: number,
|
|
86
|
-
namespace?: string,
|
|
87
|
-
filter?: Record<string, unknown>
|
|
88
|
-
): Promise<VectorMatch[]> {
|
|
68
|
+
async query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]> {
|
|
89
69
|
const vectorLiteral = `[${vector.join(',')}]`;
|
|
90
|
-
|
|
91
70
|
let whereClause = namespace ? `WHERE namespace = $3` : '';
|
|
92
71
|
const params: unknown[] = [vectorLiteral, topK];
|
|
93
72
|
if (namespace) params.push(namespace);
|
|
94
73
|
|
|
95
|
-
// Append metadata filter conditions if provided
|
|
96
74
|
if (filter && Object.keys(filter).length > 0) {
|
|
97
75
|
const filterConditions = Object.entries(filter)
|
|
98
76
|
.map(([key, val]) => {
|
|
@@ -101,28 +79,23 @@ export class PgVectorAdapter implements IVectorDB {
|
|
|
101
79
|
return `metadata->>'${key}' = $${paramIdx}`;
|
|
102
80
|
})
|
|
103
81
|
.join(' AND ');
|
|
104
|
-
whereClause = whereClause
|
|
105
|
-
? `${whereClause} AND ${filterConditions}`
|
|
106
|
-
: `WHERE ${filterConditions}`;
|
|
82
|
+
whereClause = whereClause ? `${whereClause} AND ${filterConditions}` : `WHERE ${filterConditions}`;
|
|
107
83
|
}
|
|
108
84
|
|
|
109
85
|
const result = await this.pool.query(
|
|
110
|
-
`SELECT id,
|
|
111
|
-
|
|
112
|
-
metadata,
|
|
113
|
-
1 - (embedding <=> $1::vector) AS score
|
|
114
|
-
FROM ${this.tableName}
|
|
86
|
+
`SELECT id, content, metadata, 1 - (embedding <=> $1::vector) AS score
|
|
87
|
+
FROM ${this.tableName}
|
|
115
88
|
${whereClause}
|
|
116
|
-
ORDER
|
|
117
|
-
LIMIT
|
|
89
|
+
ORDER BY embedding <=> $1::vector
|
|
90
|
+
LIMIT $2`,
|
|
118
91
|
params
|
|
119
92
|
);
|
|
120
93
|
|
|
121
94
|
return result.rows.map((row: Record<string, unknown>) => ({
|
|
122
|
-
id: String(row
|
|
123
|
-
score: parseFloat(String(row
|
|
124
|
-
content: String(row
|
|
125
|
-
metadata: row
|
|
95
|
+
id: String(row['id']),
|
|
96
|
+
score: parseFloat(String(row['score'])),
|
|
97
|
+
content: String(row['content']),
|
|
98
|
+
metadata: row['metadata'] as Record<string, unknown>,
|
|
126
99
|
}));
|
|
127
100
|
}
|
|
128
101
|
|
|
@@ -133,27 +106,19 @@ export class PgVectorAdapter implements IVectorDB {
|
|
|
133
106
|
}
|
|
134
107
|
|
|
135
108
|
async deleteNamespace(namespace: string): Promise<void> {
|
|
136
|
-
await this.pool.query(
|
|
137
|
-
`DELETE FROM ${this.tableName} WHERE namespace = $1`,
|
|
138
|
-
[namespace]
|
|
139
|
-
);
|
|
109
|
+
await this.pool.query(`DELETE FROM ${this.tableName} WHERE namespace = $1`, [namespace]);
|
|
140
110
|
}
|
|
141
111
|
|
|
142
112
|
async ping(): Promise<boolean> {
|
|
143
113
|
try {
|
|
144
114
|
await this.pool.query('SELECT 1');
|
|
145
115
|
return true;
|
|
146
|
-
} catch
|
|
147
|
-
console.error('[PgVectorAdapter] Ping failed:', err);
|
|
116
|
+
} catch {
|
|
148
117
|
return false;
|
|
149
118
|
}
|
|
150
119
|
}
|
|
151
120
|
|
|
152
121
|
async disconnect(): Promise<void> {
|
|
153
|
-
|
|
154
|
-
await this.pool.end();
|
|
155
|
-
} catch (err) {
|
|
156
|
-
console.error('[PgVectorAdapter] Failed to disconnect:', err);
|
|
157
|
-
}
|
|
122
|
+
await this.pool.end();
|
|
158
123
|
}
|
|
159
124
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import { VectorDBConfig } from '../../config/RagConfig';
|
|
3
|
+
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
4
|
+
import { VectorMatch, UpsertDocument } from '../../types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* QdrantProvider — implementation for Qdrant using its REST API.
|
|
8
|
+
*/
|
|
9
|
+
export class QdrantProvider extends BaseVectorProvider {
|
|
10
|
+
private http: AxiosInstance;
|
|
11
|
+
|
|
12
|
+
constructor(config: VectorDBConfig) {
|
|
13
|
+
super(config);
|
|
14
|
+
const opts = config.options as Record<string, unknown>;
|
|
15
|
+
const baseUrl = opts.baseUrl as string;
|
|
16
|
+
if (!baseUrl) throw new Error('[QdrantProvider] baseUrl is required');
|
|
17
|
+
|
|
18
|
+
this.http = axios.create({
|
|
19
|
+
baseURL: baseUrl,
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
...(opts.apiKey ? { 'api-key': opts.apiKey as string } : {}),
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async initialize(): Promise<void> {
|
|
28
|
+
await this.ping();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
|
|
32
|
+
await this.batchUpsert([doc], namespace);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void> {
|
|
36
|
+
const payload = {
|
|
37
|
+
points: docs.map(doc => ({
|
|
38
|
+
id: doc.id,
|
|
39
|
+
vector: doc.vector,
|
|
40
|
+
payload: {
|
|
41
|
+
content: doc.content,
|
|
42
|
+
metadata: doc.metadata || {},
|
|
43
|
+
...(namespace ? { namespace } : {}),
|
|
44
|
+
},
|
|
45
|
+
})),
|
|
46
|
+
};
|
|
47
|
+
await this.http.put(`/collections/${this.indexName}/points`, payload);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
|
+
async query(vector: number[], topK: number, namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]> {
|
|
52
|
+
const payload = {
|
|
53
|
+
vector: vector,
|
|
54
|
+
limit: topK,
|
|
55
|
+
with_payload: true,
|
|
56
|
+
filter: namespace ? {
|
|
57
|
+
must: [{ key: 'namespace', match: { value: namespace } }]
|
|
58
|
+
} : undefined,
|
|
59
|
+
};
|
|
60
|
+
const { data } = await this.http.post(`/collections/${this.indexName}/points/search`, payload);
|
|
61
|
+
return (data.result || []).map((res: Record<string, unknown>) => ({
|
|
62
|
+
id: res['id'] as string,
|
|
63
|
+
score: res['score'] as number,
|
|
64
|
+
content: (res['payload'] as Record<string, unknown>)?.content as string || '',
|
|
65
|
+
metadata: (res['payload'] as Record<string, unknown>)?.metadata as Record<string, unknown> || {},
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
70
|
+
async delete(id: string, _namespace?: string): Promise<void> {
|
|
71
|
+
await this.http.post(`/collections/${this.indexName}/points/delete`, {
|
|
72
|
+
points: [id],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
async deleteNamespace(_namespace: string): Promise<void> {
|
|
78
|
+
await this.http.post(`/collections/${this.indexName}/points/delete`, {
|
|
79
|
+
filter: {
|
|
80
|
+
must: [{ key: 'namespace', match: { value: _namespace } }]
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async ping(): Promise<boolean> {
|
|
86
|
+
try {
|
|
87
|
+
await this.http.get('/healthz');
|
|
88
|
+
return true;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async disconnect(): Promise<void> {}
|
|
95
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import { VectorDBConfig } from '../../config/RagConfig';
|
|
3
|
+
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
4
|
+
import { VectorMatch, UpsertDocument } from '../../types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* RedisProvider — implementation for Redis (e.g. Upstash) using its REST API.
|
|
8
|
+
*/
|
|
9
|
+
export class RedisProvider extends BaseVectorProvider {
|
|
10
|
+
private http: AxiosInstance;
|
|
11
|
+
|
|
12
|
+
constructor(config: VectorDBConfig) {
|
|
13
|
+
super(config);
|
|
14
|
+
const opts = config.options as Record<string, unknown>;
|
|
15
|
+
const baseUrl = opts.baseUrl as string;
|
|
16
|
+
if (!baseUrl) throw new Error('[RedisProvider] baseUrl is required');
|
|
17
|
+
|
|
18
|
+
this.http = axios.create({
|
|
19
|
+
baseURL: baseUrl,
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async initialize(): Promise<void> {
|
|
28
|
+
await this.ping();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
|
|
32
|
+
const key = namespace ? `${namespace}:${doc.id}` : doc.id;
|
|
33
|
+
await this.http.post('/', ['JSON.SET', key, '$', JSON.stringify({
|
|
34
|
+
vector: doc.vector,
|
|
35
|
+
content: doc.content,
|
|
36
|
+
metadata: doc.metadata || {},
|
|
37
|
+
})]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void> {
|
|
41
|
+
for (const doc of docs) {
|
|
42
|
+
await this.upsert(doc, namespace);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
47
|
+
async query(vector: number[], topK: number, namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]> {
|
|
48
|
+
// This is a simplified representation of FT.SEARCH in Redis Vector
|
|
49
|
+
const payload = {
|
|
50
|
+
index: this.indexName,
|
|
51
|
+
vector: vector,
|
|
52
|
+
topK: topK,
|
|
53
|
+
namespace: namespace,
|
|
54
|
+
};
|
|
55
|
+
const { data } = await this.http.post('/search', payload);
|
|
56
|
+
return (data.results || []).map((res: Record<string, unknown>) => ({
|
|
57
|
+
id: res['id'] as string,
|
|
58
|
+
score: res['score'] as number,
|
|
59
|
+
content: res['content'] as string,
|
|
60
|
+
metadata: res['metadata'] as Record<string, unknown>,
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async delete(id: string, namespace?: string): Promise<void> {
|
|
65
|
+
const key = namespace ? `${namespace}:${id}` : id;
|
|
66
|
+
await this.http.post('/', ['DEL', key]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
70
|
+
async deleteNamespace(_namespace: string): Promise<void> {
|
|
71
|
+
// Redis doesn't have a direct "delete namespace" easily without SCAN
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async ping(): Promise<boolean> {
|
|
75
|
+
try {
|
|
76
|
+
await this.http.post('/', ['PING']);
|
|
77
|
+
return true;
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async disconnect(): Promise<void> {}
|
|
84
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import { VectorDBConfig } from '../../config/RagConfig';
|
|
3
|
+
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
4
|
+
import { VectorMatch, UpsertDocument } from '../../types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WeaviateProvider — implementation for Weaviate using its REST/GraphQL API.
|
|
8
|
+
*/
|
|
9
|
+
export class WeaviateProvider extends BaseVectorProvider {
|
|
10
|
+
private http: AxiosInstance;
|
|
11
|
+
|
|
12
|
+
constructor(config: VectorDBConfig) {
|
|
13
|
+
super(config);
|
|
14
|
+
const opts = config.options as Record<string, unknown>;
|
|
15
|
+
const baseUrl = opts.baseUrl as string;
|
|
16
|
+
if (!baseUrl) throw new Error('[WeaviateProvider] baseUrl is required');
|
|
17
|
+
|
|
18
|
+
this.http = axios.create({
|
|
19
|
+
baseURL: baseUrl,
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
...(opts.apiKey ? {
|
|
23
|
+
'X-OpenAI-Api-Key': opts.apiKey as string,
|
|
24
|
+
'Authorization': `Bearer ${opts.apiKey as string}`
|
|
25
|
+
} : {}),
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async initialize(): Promise<void> {
|
|
31
|
+
await this.ping();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
|
|
35
|
+
const payload = {
|
|
36
|
+
class: this.indexName,
|
|
37
|
+
id: doc.id,
|
|
38
|
+
vector: doc.vector,
|
|
39
|
+
properties: {
|
|
40
|
+
content: doc.content,
|
|
41
|
+
metadata: JSON.stringify(doc.metadata || {}),
|
|
42
|
+
namespace: namespace || '',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
await this.http.post('/v1/objects', payload);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void> {
|
|
49
|
+
const payload = {
|
|
50
|
+
objects: docs.map(doc => ({
|
|
51
|
+
class: this.indexName,
|
|
52
|
+
id: doc.id,
|
|
53
|
+
vector: doc.vector,
|
|
54
|
+
properties: {
|
|
55
|
+
content: doc.content,
|
|
56
|
+
metadata: JSON.stringify(doc.metadata || {}),
|
|
57
|
+
namespace: namespace || '',
|
|
58
|
+
},
|
|
59
|
+
})),
|
|
60
|
+
};
|
|
61
|
+
await this.http.post('/v1/batch/objects', payload);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
65
|
+
async query(vector: number[], topK: number, namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]> {
|
|
66
|
+
const graphqlQuery = {
|
|
67
|
+
query: `
|
|
68
|
+
{
|
|
69
|
+
Get {
|
|
70
|
+
${this.indexName}(
|
|
71
|
+
nearVector: {
|
|
72
|
+
vector: ${JSON.stringify(vector)}
|
|
73
|
+
}
|
|
74
|
+
limit: ${topK}
|
|
75
|
+
${namespace ? `where: { path: ["namespace"], operator: Equal, valueString: "${namespace}" }` : ''}
|
|
76
|
+
) {
|
|
77
|
+
content
|
|
78
|
+
metadata
|
|
79
|
+
_additional {
|
|
80
|
+
id
|
|
81
|
+
distance
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
`
|
|
87
|
+
};
|
|
88
|
+
const { data } = await this.http.post('/v1/graphql', graphqlQuery);
|
|
89
|
+
const results = data.data?.Get?.[this.indexName] || [];
|
|
90
|
+
|
|
91
|
+
return results.map((res: Record<string, unknown>) => ({
|
|
92
|
+
id: (res['_additional'] as Record<string, unknown>).id as string,
|
|
93
|
+
score: 1 - ((res['_additional'] as Record<string, unknown>).distance as number),
|
|
94
|
+
content: res['content'] as string,
|
|
95
|
+
metadata: res['metadata'] ? JSON.parse(res['metadata'] as string) : {},
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
100
|
+
async delete(id: string, _namespace?: string): Promise<void> {
|
|
101
|
+
await this.http.delete(`/v1/objects/${this.indexName}/${id}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async deleteNamespace(namespace: string): Promise<void> {
|
|
105
|
+
// Weaviate batch delete
|
|
106
|
+
await this.http.post('/v1/batch/objects', {
|
|
107
|
+
match: {
|
|
108
|
+
class: this.indexName,
|
|
109
|
+
where: { path: ['namespace'], operator: 'Equal', valueString: namespace }
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async ping(): Promise<boolean> {
|
|
115
|
+
try {
|
|
116
|
+
await this.http.get('/v1/.well-known/live');
|
|
117
|
+
return true;
|
|
118
|
+
} catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async disconnect(): Promise<void> {}
|
|
124
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -5,21 +5,29 @@
|
|
|
5
5
|
|
|
6
6
|
// ── Shared Types (Safe for both) ──────────────────────────────
|
|
7
7
|
export type { RagConfig, VectorDBConfig, LLMConfig, EmbeddingConfig, UIConfig, RAGConfig } from './config/RagConfig';
|
|
8
|
-
export type {
|
|
8
|
+
export type { VectorMatch, UpsertDocument } from './types';
|
|
9
9
|
export type { ILLMProvider, ChatMessage, ChatOptions, EmbedOptions } from './llm/ILLMProvider';
|
|
10
|
-
export type { IngestDocument, ChatResponse } from './
|
|
10
|
+
export type { IngestDocument, ChatResponse } from './types';
|
|
11
11
|
export type { Chunk, ChunkOptions } from './rag/DocumentChunker';
|
|
12
12
|
|
|
13
13
|
// ── Server-Only Logic (Node.js dependent) ─────────────────────
|
|
14
|
-
export {
|
|
14
|
+
export { VectorPlugin } from './core/VectorPlugin';
|
|
15
|
+
export { Pipeline } from './core/Pipeline';
|
|
16
|
+
export { ConfigResolver } from './core/ConfigResolver';
|
|
17
|
+
export { ProviderRegistry } from './core/ProviderRegistry';
|
|
15
18
|
export { DocumentChunker } from './rag/DocumentChunker';
|
|
16
19
|
export { getRagConfig } from './config/serverConfig';
|
|
17
20
|
|
|
18
|
-
// ──
|
|
19
|
-
export {
|
|
20
|
-
export {
|
|
21
|
-
export {
|
|
22
|
-
export {
|
|
21
|
+
// ── Providers (Node.js dependent) ─────────────────────────────
|
|
22
|
+
export { BaseVectorProvider } from './providers/vectordb/BaseVectorProvider';
|
|
23
|
+
export { PineconeProvider } from './providers/vectordb/PineconeProvider';
|
|
24
|
+
export { PostgreSQLProvider } from './providers/vectordb/PostgreSQLProvider';
|
|
25
|
+
export { MongoDBProvider } from './providers/vectordb/MongoDBProvider';
|
|
26
|
+
export { MilvusProvider } from './providers/vectordb/MilvusProvider';
|
|
27
|
+
export { QdrantProvider } from './providers/vectordb/QdrantProvider';
|
|
28
|
+
export { ChromaDBProvider } from './providers/vectordb/ChromaDBProvider';
|
|
29
|
+
export { RedisProvider } from './providers/vectordb/RedisProvider';
|
|
30
|
+
export { WeaviateProvider } from './providers/vectordb/WeaviateProvider';
|
|
23
31
|
|
|
24
32
|
export { LLMFactory } from './llm/LLMFactory';
|
|
25
33
|
export { OpenAIProvider } from './llm/providers/OpenAIProvider';
|