@retrivora-ai/rag-engine 0.1.5 → 0.1.7
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/{DocumentChunker-cfaMidtA.d.mts → DocumentChunker-BEyzadsv.d.mts} +2 -2
- package/dist/{DocumentChunker-cfaMidtA.d.ts → DocumentChunker-BEyzadsv.d.ts} +2 -2
- package/dist/{PineconeProvider-NJ675H7U.mjs → PineconeProvider-ZRAFNFEC.mjs} +1 -1
- package/dist/{PostgreSQLProvider-ISNMD3BE.mjs → PostgreSQLProvider-ZNXA67IM.mjs} +1 -1
- package/dist/{QdrantProvider-LJWOIGES.mjs → QdrantProvider-VAED5VA7.mjs} +1 -1
- package/dist/{RagConfig-DG_0f8ka.d.mts → RagConfig-hBGXJmSx.d.mts} +3 -3
- package/dist/{RagConfig-DG_0f8ka.d.ts → RagConfig-hBGXJmSx.d.ts} +3 -3
- package/dist/chunk-7YQWGERZ.mjs +1764 -0
- package/dist/chunk-CWQQHAF6.mjs +157 -0
- package/dist/{chunk-S5DRHETN.mjs → chunk-IUTAZ7QR.mjs} +31 -2
- package/dist/{chunk-AALIF3AL.mjs → chunk-ZM6TYIDH.mjs} +3 -3
- package/dist/handlers/index.d.mts +3 -44
- package/dist/handlers/index.d.ts +3 -44
- package/dist/handlers/index.js +1371 -60
- package/dist/handlers/index.mjs +1 -1
- package/dist/index-Bx182KKn.d.ts +64 -0
- package/dist/index-Ck2pt7-8.d.mts +64 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/server.d.mts +74 -18
- package/dist/server.d.ts +74 -18
- package/dist/server.js +1371 -60
- package/dist/server.mjs +4 -4
- package/package.json +2 -1
- package/src/config/serverConfig.ts +4 -0
- package/src/core/BatchProcessor.ts +347 -0
- package/src/core/ConfigValidator.ts +568 -0
- package/src/core/Pipeline.ts +89 -39
- package/src/core/ProviderHealthCheck.ts +568 -0
- package/src/core/VectorPlugin.ts +49 -8
- package/src/handlers/index.ts +2 -2
- package/src/providers/vectordb/BaseVectorProvider.ts +1 -1
- package/src/providers/vectordb/MilvusProvider.ts +1 -1
- package/src/providers/vectordb/MongoDBProvider.ts +1 -1
- package/src/providers/vectordb/PineconeProvider.ts +4 -4
- package/src/providers/vectordb/PostgreSQLProvider.ts +35 -3
- package/src/providers/vectordb/QdrantProvider.ts +81 -4
- package/src/rag/DocumentChunker.ts +2 -2
- package/src/types/index.ts +3 -3
- package/dist/chunk-6FODXNUF.mjs +0 -91
- package/dist/chunk-BP4U4TT5.mjs +0 -548
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseVectorProvider
|
|
3
|
+
} from "./chunk-VOIWNO5O.mjs";
|
|
4
|
+
import {
|
|
5
|
+
__spreadValues
|
|
6
|
+
} from "./chunk-I4E63NIC.mjs";
|
|
7
|
+
|
|
8
|
+
// src/providers/vectordb/QdrantProvider.ts
|
|
9
|
+
import axios from "axios";
|
|
10
|
+
import crypto from "crypto";
|
|
11
|
+
var QdrantProvider = class extends BaseVectorProvider {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super(config);
|
|
14
|
+
const opts = config.options;
|
|
15
|
+
const baseUrl = opts.baseUrl;
|
|
16
|
+
if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
|
|
17
|
+
this.http = axios.create({
|
|
18
|
+
baseURL: baseUrl,
|
|
19
|
+
headers: __spreadValues({
|
|
20
|
+
"Content-Type": "application/json"
|
|
21
|
+
}, opts.apiKey ? { "api-key": opts.apiKey } : {})
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async initialize() {
|
|
25
|
+
await this.ping();
|
|
26
|
+
await this.ensureCollection();
|
|
27
|
+
await this.ensureIndex();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ensures the collection exists. Creates it if missing.
|
|
31
|
+
*/
|
|
32
|
+
async ensureCollection() {
|
|
33
|
+
var _a;
|
|
34
|
+
try {
|
|
35
|
+
const opts = this.config.options;
|
|
36
|
+
const dimensions = opts.dimensions || 1536;
|
|
37
|
+
await this.http.get(`/collections/${this.indexName}`);
|
|
38
|
+
console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (axios.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
41
|
+
const opts = this.config.options;
|
|
42
|
+
const dimensions = opts.dimensions || 1536;
|
|
43
|
+
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensions})...`);
|
|
44
|
+
await this.http.put(`/collections/${this.indexName}`, {
|
|
45
|
+
vectors: {
|
|
46
|
+
size: dimensions,
|
|
47
|
+
distance: "Cosine"
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
console.log(`[QdrantProvider] \u2705 Created collection "${this.indexName}"`);
|
|
51
|
+
} else {
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Ensures that the 'namespace' field has a keyword index for efficient filtering.
|
|
58
|
+
* Qdrant requires this for search filters to work in many configurations.
|
|
59
|
+
*/
|
|
60
|
+
async ensureIndex() {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
try {
|
|
63
|
+
await this.http.put(`/collections/${this.indexName}/index`, {
|
|
64
|
+
field_name: "namespace",
|
|
65
|
+
field_schema: "keyword"
|
|
66
|
+
});
|
|
67
|
+
console.log(`[QdrantProvider] \u2705 Ensured keyword index for "namespace" on collection "${this.indexName}"`);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
let status;
|
|
70
|
+
let data;
|
|
71
|
+
if (axios.isAxiosError(err)) {
|
|
72
|
+
status = (_a = err.response) == null ? void 0 : _a.status;
|
|
73
|
+
data = (_b = err.response) == null ? void 0 : _b.data;
|
|
74
|
+
}
|
|
75
|
+
if (status === 409) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
79
|
+
console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure namespace index (Status: ${status}):`, JSON.stringify(data || errorMessage));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async upsert(doc, namespace) {
|
|
83
|
+
await this.batchUpsert([doc], namespace);
|
|
84
|
+
}
|
|
85
|
+
async batchUpsert(docs, namespace) {
|
|
86
|
+
const payload = {
|
|
87
|
+
points: docs.map((doc) => ({
|
|
88
|
+
id: this.normalizeId(doc.id),
|
|
89
|
+
vector: doc.vector,
|
|
90
|
+
payload: __spreadValues({
|
|
91
|
+
content: doc.content,
|
|
92
|
+
metadata: doc.metadata || {}
|
|
93
|
+
}, namespace ? { namespace } : {})
|
|
94
|
+
}))
|
|
95
|
+
};
|
|
96
|
+
await this.http.put(`/collections/${this.indexName}/points`, payload);
|
|
97
|
+
}
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
99
|
+
async query(vector, topK, namespace, _filter) {
|
|
100
|
+
const payload = {
|
|
101
|
+
vector,
|
|
102
|
+
limit: topK,
|
|
103
|
+
with_payload: true,
|
|
104
|
+
filter: namespace ? {
|
|
105
|
+
must: [{ key: "namespace", match: { value: namespace } }]
|
|
106
|
+
} : void 0
|
|
107
|
+
};
|
|
108
|
+
const { data } = await this.http.post(`/collections/${this.indexName}/points/search`, payload);
|
|
109
|
+
return (data.result || []).map((res) => {
|
|
110
|
+
var _a, _b;
|
|
111
|
+
return {
|
|
112
|
+
id: res["id"],
|
|
113
|
+
score: res["score"],
|
|
114
|
+
content: ((_a = res["payload"]) == null ? void 0 : _a.content) || "",
|
|
115
|
+
metadata: ((_b = res["payload"]) == null ? void 0 : _b.metadata) || {}
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
120
|
+
async delete(id, _namespace) {
|
|
121
|
+
await this.http.post(`/collections/${this.indexName}/points/delete`, {
|
|
122
|
+
points: [this.normalizeId(id)]
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async deleteNamespace(_namespace) {
|
|
126
|
+
await this.http.post(`/collections/${this.indexName}/points/delete`, {
|
|
127
|
+
filter: {
|
|
128
|
+
must: [{ key: "namespace", match: { value: _namespace } }]
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async ping() {
|
|
133
|
+
try {
|
|
134
|
+
await this.http.get("/healthz");
|
|
135
|
+
return true;
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Normalizes an ID into a format Qdrant accepts (UUID or integer).
|
|
142
|
+
* For string IDs that aren't UUIDs, it generates a deterministic UUID v5-like hash.
|
|
143
|
+
*/
|
|
144
|
+
normalizeId(id) {
|
|
145
|
+
if (typeof id === "number") return id;
|
|
146
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
147
|
+
if (uuidRegex.test(id)) return id.toLowerCase();
|
|
148
|
+
const hash = crypto.createHash("md5").update(id).digest("hex");
|
|
149
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
150
|
+
}
|
|
151
|
+
async disconnect() {
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export {
|
|
156
|
+
QdrantProvider
|
|
157
|
+
};
|
|
@@ -52,8 +52,37 @@ var PostgreSQLProvider = class extends BaseVectorProvider {
|
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
async batchUpsert(docs, namespace = "") {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
if (docs.length === 0) return;
|
|
56
|
+
const client = await this.pool.connect();
|
|
57
|
+
try {
|
|
58
|
+
await client.query("BEGIN");
|
|
59
|
+
const BATCH_SIZE = 50;
|
|
60
|
+
for (let i = 0; i < docs.length; i += BATCH_SIZE) {
|
|
61
|
+
const batch = docs.slice(i, i + BATCH_SIZE);
|
|
62
|
+
const values = [];
|
|
63
|
+
const valuePlaceholders = batch.map((doc, idx) => {
|
|
64
|
+
var _a;
|
|
65
|
+
const offset = idx * 5;
|
|
66
|
+
values.push(doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), `[${doc.vector.join(",")}]`);
|
|
67
|
+
return `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}::vector)`;
|
|
68
|
+
}).join(", ");
|
|
69
|
+
const query = `
|
|
70
|
+
INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
|
|
71
|
+
VALUES ${valuePlaceholders}
|
|
72
|
+
ON CONFLICT (id) DO UPDATE
|
|
73
|
+
SET namespace = EXCLUDED.namespace,
|
|
74
|
+
content = EXCLUDED.content,
|
|
75
|
+
metadata = EXCLUDED.metadata,
|
|
76
|
+
embedding = EXCLUDED.embedding
|
|
77
|
+
`;
|
|
78
|
+
await client.query(query, values);
|
|
79
|
+
}
|
|
80
|
+
await client.query("COMMIT");
|
|
81
|
+
} catch (error) {
|
|
82
|
+
await client.query("ROLLBACK");
|
|
83
|
+
throw error;
|
|
84
|
+
} finally {
|
|
85
|
+
client.release();
|
|
57
86
|
}
|
|
58
87
|
}
|
|
59
88
|
async query(vector, topK, namespace, filter) {
|
|
@@ -31,7 +31,7 @@ var PineconeProvider = class extends BaseVectorProvider {
|
|
|
31
31
|
var _a;
|
|
32
32
|
await this.index(namespace).upsert({
|
|
33
33
|
records: [{
|
|
34
|
-
id: doc.id,
|
|
34
|
+
id: String(doc.id),
|
|
35
35
|
values: doc.vector,
|
|
36
36
|
metadata: __spreadValues({ content: doc.content }, (_a = doc.metadata) != null ? _a : {})
|
|
37
37
|
}]
|
|
@@ -43,7 +43,7 @@ var PineconeProvider = class extends BaseVectorProvider {
|
|
|
43
43
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
44
44
|
var _a;
|
|
45
45
|
return {
|
|
46
|
-
id: d.id,
|
|
46
|
+
id: String(d.id),
|
|
47
47
|
values: d.vector,
|
|
48
48
|
metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
|
|
49
49
|
};
|
|
@@ -69,7 +69,7 @@ var PineconeProvider = class extends BaseVectorProvider {
|
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
async delete(id, namespace) {
|
|
72
|
-
await this.index(namespace).deleteOne({ id });
|
|
72
|
+
await this.index(namespace).deleteOne({ id: String(id) });
|
|
73
73
|
}
|
|
74
74
|
async deleteNamespace(namespace) {
|
|
75
75
|
await this.client.index(this.indexName).namespace(namespace).deleteAll();
|
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* createChatHandler — factory that returns a Next.js App Router POST handler
|
|
6
|
-
*/
|
|
7
|
-
declare function createChatHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
8
|
-
error: string;
|
|
9
|
-
}> | NextResponse<ChatResponse>>;
|
|
10
|
-
/**
|
|
11
|
-
* createIngestHandler — factory for the document ingestion endpoint.
|
|
12
|
-
*/
|
|
13
|
-
declare function createIngestHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
14
|
-
error: string;
|
|
15
|
-
}> | NextResponse<{
|
|
16
|
-
results: {
|
|
17
|
-
docId: string;
|
|
18
|
-
chunksIngested: number;
|
|
19
|
-
}[];
|
|
20
|
-
}>>;
|
|
21
|
-
/**
|
|
22
|
-
* createHealthHandler — factory for the health-check endpoint.
|
|
23
|
-
*/
|
|
24
|
-
declare function createHealthHandler(config?: Partial<RagConfig>): () => Promise<NextResponse<{
|
|
25
|
-
timestamp: string;
|
|
26
|
-
status: string;
|
|
27
|
-
}> | NextResponse<{
|
|
28
|
-
status: string;
|
|
29
|
-
error: string;
|
|
30
|
-
}>>;
|
|
31
|
-
/**
|
|
32
|
-
* createUploadHandler — factory for the file upload ingestion endpoint.
|
|
33
|
-
*/
|
|
34
|
-
declare function createUploadHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
35
|
-
error: string;
|
|
36
|
-
}> | NextResponse<{
|
|
37
|
-
message: string;
|
|
38
|
-
results: {
|
|
39
|
-
docId: string;
|
|
40
|
-
chunksIngested: number;
|
|
41
|
-
}[];
|
|
42
|
-
}>>;
|
|
43
|
-
|
|
44
|
-
export { createChatHandler, createHealthHandler, createIngestHandler, createUploadHandler };
|
|
1
|
+
export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-Ck2pt7-8.mjs';
|
|
2
|
+
import '../RagConfig-hBGXJmSx.mjs';
|
|
3
|
+
import 'next/server';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* createChatHandler — factory that returns a Next.js App Router POST handler
|
|
6
|
-
*/
|
|
7
|
-
declare function createChatHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
8
|
-
error: string;
|
|
9
|
-
}> | NextResponse<ChatResponse>>;
|
|
10
|
-
/**
|
|
11
|
-
* createIngestHandler — factory for the document ingestion endpoint.
|
|
12
|
-
*/
|
|
13
|
-
declare function createIngestHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
14
|
-
error: string;
|
|
15
|
-
}> | NextResponse<{
|
|
16
|
-
results: {
|
|
17
|
-
docId: string;
|
|
18
|
-
chunksIngested: number;
|
|
19
|
-
}[];
|
|
20
|
-
}>>;
|
|
21
|
-
/**
|
|
22
|
-
* createHealthHandler — factory for the health-check endpoint.
|
|
23
|
-
*/
|
|
24
|
-
declare function createHealthHandler(config?: Partial<RagConfig>): () => Promise<NextResponse<{
|
|
25
|
-
timestamp: string;
|
|
26
|
-
status: string;
|
|
27
|
-
}> | NextResponse<{
|
|
28
|
-
status: string;
|
|
29
|
-
error: string;
|
|
30
|
-
}>>;
|
|
31
|
-
/**
|
|
32
|
-
* createUploadHandler — factory for the file upload ingestion endpoint.
|
|
33
|
-
*/
|
|
34
|
-
declare function createUploadHandler(config?: Partial<RagConfig>): (req: NextRequest) => Promise<NextResponse<{
|
|
35
|
-
error: string;
|
|
36
|
-
}> | NextResponse<{
|
|
37
|
-
message: string;
|
|
38
|
-
results: {
|
|
39
|
-
docId: string;
|
|
40
|
-
chunksIngested: number;
|
|
41
|
-
}[];
|
|
42
|
-
}>>;
|
|
43
|
-
|
|
44
|
-
export { createChatHandler, createHealthHandler, createIngestHandler, createUploadHandler };
|
|
1
|
+
export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-Bx182KKn.js';
|
|
2
|
+
import '../RagConfig-hBGXJmSx.js';
|
|
3
|
+
import 'next/server';
|