@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.
Files changed (74) hide show
  1. package/dist/ChromaDBProvider-QNI7UCX4.mjs +8 -0
  2. package/dist/DocumentChunker-cfaMidtA.d.mts +93 -0
  3. package/dist/DocumentChunker-cfaMidtA.d.ts +93 -0
  4. package/dist/LLMFactory-JFOY2V4X.mjs +8 -0
  5. package/dist/MilvusProvider-OO6QGZDZ.mjs +8 -0
  6. package/dist/MongoDBProvider-WWVJG3WT.mjs +8 -0
  7. package/dist/PineconeProvider-NJ675H7U.mjs +8 -0
  8. package/dist/PostgreSQLProvider-ISNMD3BE.mjs +8 -0
  9. package/dist/QdrantProvider-LJWOIGES.mjs +8 -0
  10. package/dist/RagConfig-DG_0f8ka.d.mts +145 -0
  11. package/dist/RagConfig-DG_0f8ka.d.ts +145 -0
  12. package/dist/RedisProvider-ASONNYBI.mjs +8 -0
  13. package/dist/WeaviateProvider-PSDCUGC7.mjs +8 -0
  14. package/dist/chunk-6FODXNUF.mjs +91 -0
  15. package/dist/chunk-7NXI6ZWX.mjs +89 -0
  16. package/dist/chunk-AALIF3AL.mjs +91 -0
  17. package/dist/chunk-BP4U4TT5.mjs +548 -0
  18. package/dist/chunk-HUGLYKD6.mjs +84 -0
  19. package/dist/chunk-I4E63NIC.mjs +24 -0
  20. package/dist/chunk-JI6VD5TJ.mjs +387 -0
  21. package/dist/chunk-QEYVWVT5.mjs +102 -0
  22. package/dist/chunk-S5DRHETN.mjs +110 -0
  23. package/dist/{chunk-ZPXLQR5Q.mjs → chunk-UKDXCXW7.mjs} +5 -23
  24. package/dist/chunk-V75V7BT2.mjs +117 -0
  25. package/dist/chunk-VOIWNO5O.mjs +11 -0
  26. package/dist/chunk-VPNRDXIA.mjs +74 -0
  27. package/dist/handlers/index.d.mts +9 -33
  28. package/dist/handlers/index.d.ts +9 -33
  29. package/dist/handlers/index.js +1477 -962
  30. package/dist/handlers/index.mjs +4 -2
  31. package/dist/index.d.mts +4 -3
  32. package/dist/index.d.ts +4 -3
  33. package/dist/index.js +2 -2
  34. package/dist/index.mjs +4 -2
  35. package/dist/server.d.mts +220 -53
  36. package/dist/server.d.ts +220 -53
  37. package/dist/server.js +1531 -1099
  38. package/dist/server.mjs +55 -131
  39. package/package.json +19 -2
  40. package/src/app/page.tsx +1 -1
  41. package/src/components/MessageBubble.tsx +1 -1
  42. package/src/components/SourceCard.tsx +1 -1
  43. package/src/config/RagConfig.ts +1 -1
  44. package/src/config/serverConfig.ts +2 -2
  45. package/src/core/ConfigResolver.ts +69 -0
  46. package/src/core/Pipeline.ts +101 -0
  47. package/src/core/ProviderRegistry.ts +71 -0
  48. package/src/core/VectorPlugin.ts +52 -0
  49. package/src/handlers/index.ts +21 -100
  50. package/src/hooks/useRagChat.ts +1 -1
  51. package/src/index.ts +2 -6
  52. package/src/providers/vectordb/BaseVectorProvider.ts +61 -0
  53. package/src/providers/vectordb/ChromaDBProvider.ts +94 -0
  54. package/src/providers/vectordb/MilvusProvider.ts +100 -0
  55. package/src/providers/vectordb/MongoDBProvider.ts +118 -0
  56. package/src/{vectordb/adapters/PineconeAdapter.ts → providers/vectordb/PineconeProvider.ts} +21 -56
  57. package/src/{vectordb/adapters/PgVectorAdapter.ts → providers/vectordb/PostgreSQLProvider.ts} +23 -58
  58. package/src/providers/vectordb/QdrantProvider.ts +95 -0
  59. package/src/providers/vectordb/RedisProvider.ts +84 -0
  60. package/src/providers/vectordb/WeaviateProvider.ts +124 -0
  61. package/src/server.ts +16 -8
  62. package/src/test-refactor.ts +59 -0
  63. package/src/types/index.ts +24 -0
  64. package/src/utils/templateUtils.ts +6 -6
  65. package/dist/DocumentChunker-BUrIrcPk.d.mts +0 -43
  66. package/dist/DocumentChunker-BUrIrcPk.d.ts +0 -43
  67. package/dist/RAGPipeline-BmkIv1HD.d.mts +0 -298
  68. package/dist/RAGPipeline-BmkIv1HD.d.ts +0 -298
  69. package/dist/chunk-NVOMLHXW.mjs +0 -1259
  70. package/src/rag/RAGPipeline.ts +0 -200
  71. package/src/vectordb/IVectorDB.ts +0 -75
  72. package/src/vectordb/VectorDBFactory.ts +0 -41
  73. package/src/vectordb/adapters/MongoDbAdapter.ts +0 -175
  74. package/src/vectordb/adapters/UniversalVectorDBAdapter.ts +0 -177
@@ -0,0 +1,387 @@
1
+ import {
2
+ buildPayload,
3
+ resolvePath
4
+ } from "./chunk-UKDXCXW7.mjs";
5
+ import {
6
+ __spreadProps,
7
+ __spreadValues
8
+ } from "./chunk-I4E63NIC.mjs";
9
+
10
+ // src/llm/providers/OpenAIProvider.ts
11
+ import OpenAI from "openai";
12
+ var OpenAIProvider = class {
13
+ constructor(llmConfig, embeddingConfig) {
14
+ if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
15
+ this.client = new OpenAI({ apiKey: llmConfig.apiKey });
16
+ this.llmConfig = llmConfig;
17
+ this.embeddingConfig = embeddingConfig;
18
+ }
19
+ async chat(messages, context, options) {
20
+ var _a, _b, _c, _d, _e, _f, _g, _h;
21
+ const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
22
+
23
+ Context:
24
+ ${context}`;
25
+ const systemMessage = {
26
+ role: "system",
27
+ content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
28
+
29
+ Context:
30
+ ${context}`
31
+ };
32
+ const formattedMessages = [
33
+ systemMessage,
34
+ ...messages.map((m) => ({
35
+ role: m.role,
36
+ content: m.content
37
+ }))
38
+ ];
39
+ const completion = await this.client.chat.completions.create({
40
+ model: this.llmConfig.model,
41
+ messages: formattedMessages,
42
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
43
+ temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
44
+ stop: options == null ? void 0 : options.stop
45
+ });
46
+ return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
47
+ }
48
+ async embed(text, options) {
49
+ const results = await this.batchEmbed([text], options);
50
+ return results[0];
51
+ }
52
+ async batchEmbed(texts, options) {
53
+ var _a, _b, _c, _d, _e;
54
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-3-small";
55
+ const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
56
+ const client = apiKey !== this.llmConfig.apiKey ? new OpenAI({ apiKey }) : this.client;
57
+ const response = await client.embeddings.create({ model, input: texts });
58
+ return response.data.map((d) => d.embedding);
59
+ }
60
+ async ping() {
61
+ try {
62
+ await this.client.models.list();
63
+ return true;
64
+ } catch (err) {
65
+ console.error("[OpenAIProvider] Ping failed:", err);
66
+ return false;
67
+ }
68
+ }
69
+ };
70
+
71
+ // src/llm/providers/AnthropicProvider.ts
72
+ import Anthropic from "@anthropic-ai/sdk";
73
+ var AnthropicProvider = class {
74
+ constructor(llmConfig, embeddingConfig) {
75
+ if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
76
+ this.client = new Anthropic({ apiKey: llmConfig.apiKey });
77
+ this.llmConfig = llmConfig;
78
+ this.embeddingConfig = embeddingConfig;
79
+ }
80
+ async chat(messages, context, options) {
81
+ var _a, _b, _c;
82
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
83
+
84
+ Context:
85
+ ${context}`;
86
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
87
+
88
+ Context:
89
+ ${context}`;
90
+ const anthropicMessages = messages.map((m) => ({
91
+ role: m.role === "assistant" ? "assistant" : "user",
92
+ content: m.content
93
+ }));
94
+ const response = await this.client.messages.create({
95
+ model: this.llmConfig.model,
96
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
97
+ system,
98
+ messages: anthropicMessages
99
+ });
100
+ const block = response.content[0];
101
+ return block.type === "text" ? block.text : "";
102
+ }
103
+ /**
104
+ * Anthropic does not offer an embedding API.
105
+ * This method throws with a clear error so developers know to configure
106
+ * a separate embedding provider (OpenAI or Ollama).
107
+ */
108
+ async embed(text, options) {
109
+ void text;
110
+ void options;
111
+ throw new Error(
112
+ '[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
113
+ );
114
+ }
115
+ async batchEmbed(texts, options) {
116
+ void texts;
117
+ void options;
118
+ throw new Error(
119
+ "[AnthropicProvider] Anthropic does not provide an embedding API."
120
+ );
121
+ }
122
+ async ping() {
123
+ try {
124
+ await this.client.models.list();
125
+ return true;
126
+ } catch (err) {
127
+ console.error("[AnthropicProvider] Ping failed:", err);
128
+ return false;
129
+ }
130
+ }
131
+ };
132
+
133
+ // src/llm/providers/OllamaProvider.ts
134
+ import axios from "axios";
135
+ var OllamaProvider = class {
136
+ constructor(llmConfig, embeddingConfig) {
137
+ var _a;
138
+ const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
139
+ this.http = axios.create({ baseURL, timeout: 12e4 });
140
+ this.llmConfig = llmConfig;
141
+ this.embeddingConfig = embeddingConfig;
142
+ }
143
+ async chat(messages, context, options) {
144
+ var _a, _b, _c, _d, _e;
145
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
146
+
147
+ Context:
148
+ ${context}`;
149
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
150
+
151
+ Context:
152
+ ${context}`;
153
+ const { data } = await this.http.post("/api/chat", {
154
+ model: this.llmConfig.model,
155
+ stream: false,
156
+ options: {
157
+ temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
158
+ num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
159
+ },
160
+ messages: [
161
+ { role: "system", content: system },
162
+ ...messages.map((m) => ({ role: m.role, content: m.content }))
163
+ ]
164
+ });
165
+ return data.message.content;
166
+ }
167
+ async embed(text, options) {
168
+ var _a, _b, _c, _d, _e, _f, _g;
169
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "nomic-embed-text";
170
+ const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
171
+ const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? axios.create({ baseURL, timeout: 6e4 }) : this.http;
172
+ const { data } = await client.post("/api/embeddings", {
173
+ model,
174
+ prompt: text
175
+ });
176
+ return data.embedding;
177
+ }
178
+ async batchEmbed(texts, options) {
179
+ const vectors = [];
180
+ for (const text of texts) {
181
+ vectors.push(await this.embed(text, options));
182
+ }
183
+ return vectors;
184
+ }
185
+ async ping() {
186
+ try {
187
+ await this.http.get("/api/tags");
188
+ return true;
189
+ } catch (err) {
190
+ console.error("[OllamaProvider] Ping failed:", err);
191
+ return false;
192
+ }
193
+ }
194
+ };
195
+
196
+ // src/llm/providers/UniversalLLMAdapter.ts
197
+ import axios2 from "axios";
198
+
199
+ // src/config/UniversalProfiles.ts
200
+ var OPENAI_BASE = {
201
+ chatPath: "/chat/completions",
202
+ embedPath: "/embeddings",
203
+ responseExtractPath: "choices[0].message.content",
204
+ embedExtractPath: "data[0].embedding",
205
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
206
+ };
207
+ var LLM_PROFILES = {
208
+ "openai-compatible": OPENAI_BASE,
209
+ "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
210
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
211
+ }),
212
+ "anthropic-claude": {
213
+ chatPath: "/v1/messages",
214
+ responseExtractPath: "content[0].text",
215
+ headers: { "anthropic-version": "2023-06-01" },
216
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
217
+ },
218
+ "google-gemini": {
219
+ chatPath: "/v1beta/models/{{model}}:generateContent",
220
+ responseExtractPath: "candidates[0].content.parts[0].text",
221
+ chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
222
+ },
223
+ "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
224
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
225
+ }),
226
+ "ollama-standard": {
227
+ chatPath: "/api/chat",
228
+ embedPath: "/api/embeddings",
229
+ responseExtractPath: "message.content",
230
+ embedExtractPath: "embedding",
231
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
232
+ embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
233
+ }
234
+ };
235
+
236
+ // src/llm/providers/UniversalLLMAdapter.ts
237
+ var UniversalLLMAdapter = class {
238
+ constructor(config) {
239
+ var _a, _b, _c, _d, _e, _f, _g;
240
+ this.model = config.model;
241
+ const llmConfig = config;
242
+ const options = (_a = llmConfig.options) != null ? _a : {};
243
+ let profile = {};
244
+ if (typeof options.profile === "string") {
245
+ profile = LLM_PROFILES[options.profile] || {};
246
+ } else if (typeof options.profile === "object" && options.profile !== null) {
247
+ profile = options.profile;
248
+ }
249
+ this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
250
+ this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
251
+ this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
252
+ this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
253
+ const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
254
+ if (!baseUrl) {
255
+ throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
256
+ }
257
+ this.http = axios2.create({
258
+ baseURL: baseUrl,
259
+ headers: __spreadValues(__spreadValues({
260
+ "Content-Type": "application/json"
261
+ }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
262
+ timeout: (_g = this.opts.timeout) != null ? _g : 6e4
263
+ });
264
+ }
265
+ async chat(messages, context) {
266
+ var _a, _b;
267
+ const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
268
+ const formattedMessages = [
269
+ { role: "system", content: `${this.systemPrompt}
270
+
271
+ Context:
272
+ ${context != null ? context : "None"}` },
273
+ ...messages
274
+ ];
275
+ let payload;
276
+ if (this.opts.chatPayloadTemplate) {
277
+ payload = buildPayload(this.opts.chatPayloadTemplate, {
278
+ model: this.model,
279
+ messages: formattedMessages,
280
+ maxTokens: this.maxTokens,
281
+ temperature: this.temperature
282
+ });
283
+ } else {
284
+ payload = {
285
+ model: this.model,
286
+ messages: formattedMessages,
287
+ max_tokens: this.maxTokens,
288
+ temperature: this.temperature
289
+ };
290
+ }
291
+ const { data } = await this.http.post(path, payload);
292
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
293
+ const result = resolvePath(data, extractPath);
294
+ if (result === void 0) {
295
+ throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
296
+ }
297
+ return String(result);
298
+ }
299
+ async embed(text) {
300
+ var _a, _b;
301
+ const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
302
+ let payload;
303
+ if (this.opts.embedPayloadTemplate) {
304
+ payload = buildPayload(this.opts.embedPayloadTemplate, {
305
+ model: this.model,
306
+ input: text
307
+ });
308
+ } else {
309
+ payload = {
310
+ model: this.model,
311
+ input: text
312
+ };
313
+ }
314
+ const { data } = await this.http.post(path, payload);
315
+ const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
316
+ const vector = resolvePath(data, extractPath);
317
+ if (!Array.isArray(vector)) {
318
+ throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
319
+ }
320
+ return vector;
321
+ }
322
+ async batchEmbed(texts) {
323
+ const vectors = [];
324
+ for (const text of texts) {
325
+ vectors.push(await this.embed(text));
326
+ }
327
+ return vectors;
328
+ }
329
+ async ping() {
330
+ try {
331
+ if (this.opts.pingPath) {
332
+ await this.http.get(this.opts.pingPath);
333
+ }
334
+ return true;
335
+ } catch (err) {
336
+ console.error("[UniversalLLMAdapter] Ping failed:", err);
337
+ return false;
338
+ }
339
+ }
340
+ };
341
+
342
+ // src/llm/LLMFactory.ts
343
+ var LLMFactory = class _LLMFactory {
344
+ static create(llmConfig, embeddingConfig) {
345
+ var _a;
346
+ switch (llmConfig.provider) {
347
+ case "openai":
348
+ return new OpenAIProvider(llmConfig, embeddingConfig);
349
+ case "anthropic":
350
+ return new AnthropicProvider(llmConfig, embeddingConfig);
351
+ case "ollama":
352
+ return new OllamaProvider(llmConfig, embeddingConfig);
353
+ case "rest":
354
+ case "universal_rest":
355
+ case "custom":
356
+ return new UniversalLLMAdapter(llmConfig);
357
+ default:
358
+ if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
359
+ return new UniversalLLMAdapter(llmConfig);
360
+ }
361
+ throw new Error(
362
+ `[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
363
+ );
364
+ }
365
+ }
366
+ /**
367
+ * Creates a dedicated embedding-only provider.
368
+ * Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
369
+ */
370
+ static createEmbeddingProvider(embeddingConfig) {
371
+ const fakeLLMConfig = {
372
+ provider: embeddingConfig.provider,
373
+ model: embeddingConfig.model,
374
+ apiKey: embeddingConfig.apiKey,
375
+ baseUrl: embeddingConfig.baseUrl,
376
+ options: embeddingConfig.options
377
+ };
378
+ return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
379
+ }
380
+ };
381
+
382
+ export {
383
+ OpenAIProvider,
384
+ AnthropicProvider,
385
+ OllamaProvider,
386
+ LLMFactory
387
+ };
@@ -0,0 +1,102 @@
1
+ import {
2
+ BaseVectorProvider
3
+ } from "./chunk-VOIWNO5O.mjs";
4
+ import {
5
+ __spreadValues
6
+ } from "./chunk-I4E63NIC.mjs";
7
+
8
+ // src/providers/vectordb/MongoDBProvider.ts
9
+ import { MongoClient } from "mongodb";
10
+ var MongoDBProvider = class extends BaseVectorProvider {
11
+ constructor(config) {
12
+ super(config);
13
+ const opts = config.options;
14
+ if (!opts.uri || !opts.database || !opts.collection) {
15
+ throw new Error("[MongoDBProvider] options uri, database, and collection are required.");
16
+ }
17
+ this.client = new MongoClient(opts.uri);
18
+ this.dbName = opts.database;
19
+ this.collectionName = opts.collection;
20
+ this.embeddingKey = opts.embeddingKey || "embedding";
21
+ this.contentKey = opts.contentKey || "content";
22
+ this.metadataKey = opts.metadataKey || "metadata";
23
+ }
24
+ async initialize() {
25
+ await this.client.connect();
26
+ this.db = this.client.db(this.dbName);
27
+ this.collection = this.db.collection(this.collectionName);
28
+ }
29
+ async upsert(doc, namespace) {
30
+ const document = __spreadValues({
31
+ _id: doc.id,
32
+ [this.embeddingKey]: doc.vector,
33
+ [this.contentKey]: doc.content,
34
+ [this.metadataKey]: doc.metadata || {}
35
+ }, namespace ? { namespace } : {});
36
+ await this.collection.updateOne({ _id: doc.id }, { $set: document }, { upsert: true });
37
+ }
38
+ async batchUpsert(docs, namespace) {
39
+ const operations = docs.map((doc) => ({
40
+ updateOne: {
41
+ filter: { _id: doc.id },
42
+ update: {
43
+ $set: __spreadValues({
44
+ [this.embeddingKey]: doc.vector,
45
+ [this.contentKey]: doc.content,
46
+ [this.metadataKey]: doc.metadata || {}
47
+ }, namespace ? { namespace } : {})
48
+ },
49
+ upsert: true
50
+ }
51
+ }));
52
+ await this.collection.bulkWrite(operations);
53
+ }
54
+ async query(vector, topK, namespace, filter) {
55
+ const pipeline = [
56
+ {
57
+ $vectorSearch: __spreadValues({
58
+ index: this.config.options.indexName || "vector_index",
59
+ path: this.embeddingKey,
60
+ queryVector: vector,
61
+ numCandidates: Math.max(topK * 10, 100),
62
+ limit: topK
63
+ }, filter || namespace ? { filter: __spreadValues(__spreadValues({}, filter || {}), namespace ? { namespace } : {}) } : {})
64
+ },
65
+ {
66
+ $project: {
67
+ score: { $meta: "vectorSearchScore" },
68
+ content: `$${this.contentKey}`,
69
+ metadata: `$${this.metadataKey}`
70
+ }
71
+ }
72
+ ];
73
+ const results = await this.collection.aggregate(pipeline).toArray();
74
+ return results.map((res) => ({
75
+ id: res["_id"].toString(),
76
+ score: res["score"],
77
+ content: res["content"],
78
+ metadata: res["metadata"]
79
+ }));
80
+ }
81
+ async delete(id, namespace) {
82
+ await this.collection.deleteOne(__spreadValues({ _id: id }, namespace ? { namespace } : {}));
83
+ }
84
+ async deleteNamespace(namespace) {
85
+ await this.collection.deleteMany({ namespace });
86
+ }
87
+ async ping() {
88
+ try {
89
+ await this.db.command({ ping: 1 });
90
+ return true;
91
+ } catch (e) {
92
+ return false;
93
+ }
94
+ }
95
+ async disconnect() {
96
+ await this.client.close();
97
+ }
98
+ };
99
+
100
+ export {
101
+ MongoDBProvider
102
+ };
@@ -0,0 +1,110 @@
1
+ import {
2
+ BaseVectorProvider
3
+ } from "./chunk-VOIWNO5O.mjs";
4
+
5
+ // src/providers/vectordb/PostgreSQLProvider.ts
6
+ import { Pool } from "pg";
7
+ var PostgreSQLProvider = class extends BaseVectorProvider {
8
+ constructor(config) {
9
+ var _a;
10
+ super(config);
11
+ this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
12
+ const opts = config.options;
13
+ if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
14
+ this.connectionString = opts.connectionString;
15
+ this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
16
+ }
17
+ async initialize() {
18
+ this.pool = new Pool({ connectionString: this.connectionString });
19
+ const client = await this.pool.connect();
20
+ try {
21
+ await client.query("CREATE EXTENSION IF NOT EXISTS vector");
22
+ await client.query(`
23
+ CREATE TABLE IF NOT EXISTS ${this.tableName} (
24
+ id TEXT PRIMARY KEY,
25
+ namespace TEXT NOT NULL DEFAULT '',
26
+ content TEXT NOT NULL,
27
+ metadata JSONB,
28
+ embedding VECTOR(${this.dimensions})
29
+ )
30
+ `);
31
+ await client.query(`
32
+ CREATE INDEX IF NOT EXISTS ${this.tableName}_embedding_idx
33
+ ON ${this.tableName}
34
+ USING hnsw (embedding vector_cosine_ops)
35
+ `);
36
+ } finally {
37
+ client.release();
38
+ }
39
+ }
40
+ async upsert(doc, namespace = "") {
41
+ var _a;
42
+ const vectorLiteral = `[${doc.vector.join(",")}]`;
43
+ await this.pool.query(
44
+ `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
45
+ VALUES ($1, $2, $3, $4, $5::vector)
46
+ ON CONFLICT (id) DO UPDATE
47
+ SET namespace = EXCLUDED.namespace,
48
+ content = EXCLUDED.content,
49
+ metadata = EXCLUDED.metadata,
50
+ embedding = EXCLUDED.embedding`,
51
+ [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
52
+ );
53
+ }
54
+ async batchUpsert(docs, namespace = "") {
55
+ for (const doc of docs) {
56
+ await this.upsert(doc, namespace);
57
+ }
58
+ }
59
+ async query(vector, topK, namespace, filter) {
60
+ const vectorLiteral = `[${vector.join(",")}]`;
61
+ let whereClause = namespace ? `WHERE namespace = $3` : "";
62
+ const params = [vectorLiteral, topK];
63
+ if (namespace) params.push(namespace);
64
+ if (filter && Object.keys(filter).length > 0) {
65
+ const filterConditions = Object.entries(filter).map(([key, val]) => {
66
+ const paramIdx = params.length + 1;
67
+ params.push(JSON.stringify(val));
68
+ return `metadata->>'${key}' = $${paramIdx}`;
69
+ }).join(" AND ");
70
+ whereClause = whereClause ? `${whereClause} AND ${filterConditions}` : `WHERE ${filterConditions}`;
71
+ }
72
+ const result = await this.pool.query(
73
+ `SELECT id, content, metadata, 1 - (embedding <=> $1::vector) AS score
74
+ FROM ${this.tableName}
75
+ ${whereClause}
76
+ ORDER BY embedding <=> $1::vector
77
+ LIMIT $2`,
78
+ params
79
+ );
80
+ return result.rows.map((row) => ({
81
+ id: String(row["id"]),
82
+ score: parseFloat(String(row["score"])),
83
+ content: String(row["content"]),
84
+ metadata: row["metadata"]
85
+ }));
86
+ }
87
+ async delete(id, namespace) {
88
+ const where = namespace ? "WHERE id = $1 AND namespace = $2" : "WHERE id = $1";
89
+ const params = namespace ? [id, namespace] : [id];
90
+ await this.pool.query(`DELETE FROM ${this.tableName} ${where}`, params);
91
+ }
92
+ async deleteNamespace(namespace) {
93
+ await this.pool.query(`DELETE FROM ${this.tableName} WHERE namespace = $1`, [namespace]);
94
+ }
95
+ async ping() {
96
+ try {
97
+ await this.pool.query("SELECT 1");
98
+ return true;
99
+ } catch (e) {
100
+ return false;
101
+ }
102
+ }
103
+ async disconnect() {
104
+ await this.pool.end();
105
+ }
106
+ };
107
+
108
+ export {
109
+ PostgreSQLProvider
110
+ };
@@ -1,22 +1,6 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1
+ import {
2
+ __spreadValues
3
+ } from "./chunk-I4E63NIC.mjs";
20
4
 
21
5
  // src/utils/templateUtils.ts
22
6
  function isRecord(value) {
@@ -46,10 +30,10 @@ Raw payload: ${raw}`);
46
30
  }
47
31
  }
48
32
  function mergeDefined(base, override) {
33
+ const merged = __spreadValues({}, base || {});
49
34
  if (!override) {
50
- return __spreadValues({}, base);
35
+ return merged;
51
36
  }
52
- const merged = __spreadValues({}, base);
53
37
  for (const [key, value] of Object.entries(override)) {
54
38
  if (value !== void 0 && value !== null && value !== "") {
55
39
  merged[key] = value;
@@ -59,8 +43,6 @@ function mergeDefined(base, override) {
59
43
  }
60
44
 
61
45
  export {
62
- __spreadValues,
63
- __spreadProps,
64
46
  resolvePath,
65
47
  buildPayload,
66
48
  mergeDefined