@retrivora-ai/rag-engine 0.1.6 → 0.1.8
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 → ChromaDBProvider-2JZSBOQX.mjs} +1 -1
- package/dist/{MilvusProvider-OO6QGZDZ.mjs → MilvusProvider-CJDBCBVI.mjs} +1 -1
- package/dist/{PineconeProvider-ZRAFNFEC.mjs → PineconeProvider-E6L5Z2FO.mjs} +1 -1
- package/dist/{QdrantProvider-NYGHAA7C.mjs → QdrantProvider-JITRNJQN.mjs} +1 -1
- package/dist/{RagConfig-hBGXJmSx.d.mts → RagConfig-D_rSf8ep.d.mts} +1 -1
- package/dist/{RagConfig-hBGXJmSx.d.ts → RagConfig-D_rSf8ep.d.ts} +1 -1
- package/dist/{RedisProvider-ASONNYBI.mjs → RedisProvider-3VKFQXXD.mjs} +1 -1
- package/dist/UniversalVectorProvider-E6L4U4OX.mjs +9 -0
- package/dist/{WeaviateProvider-PSDCUGC7.mjs → WeaviateProvider-MXIPP44J.mjs} +1 -1
- package/dist/{chunk-5K23H7JL.mjs → chunk-26EMHLIN.mjs} +40 -2
- package/dist/{chunk-VPNRDXIA.mjs → chunk-7BQI4A5J.mjs} +17 -11
- package/dist/{chunk-ZM6TYIDH.mjs → chunk-MFWJZVF3.mjs} +3 -1
- package/dist/{chunk-V75V7BT2.mjs → chunk-TSX6DQXX.mjs} +2 -2
- package/dist/{chunk-HUGLYKD6.mjs → chunk-XZPVJS2B.mjs} +27 -9
- package/dist/chunk-Y6HQZDCJ.mjs +156 -0
- package/dist/{chunk-HSBXE2WV.mjs → chunk-YIYDJQJM.mjs} +745 -192
- package/dist/{chunk-7NXI6ZWX.mjs → chunk-YST6KYBJ.mjs} +8 -5
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +924 -626
- package/dist/handlers/index.mjs +1 -2
- package/dist/index-BJ8CUArE.d.mts +114 -0
- package/dist/index-DtNprGGj.d.ts +114 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/server.d.mts +575 -17
- package/dist/server.d.ts +575 -17
- package/dist/server.js +1280 -643
- package/dist/server.mjs +314 -16
- package/package.json +11 -2
- package/src/config/ConfigBuilder.ts +373 -0
- package/src/config/EmbeddingStrategy.ts +147 -0
- package/src/config/serverConfig.ts +51 -17
- package/src/core/ConfigValidator.ts +77 -52
- package/src/core/Pipeline.ts +28 -26
- package/src/core/PluginManager.ts +277 -0
- package/src/core/ProviderHealthCheck.ts +79 -140
- package/src/core/ProviderRegistry.ts +38 -15
- package/src/providers/vectordb/ChromaDBProvider.ts +37 -12
- package/src/providers/vectordb/MilvusProvider.ts +25 -10
- package/src/providers/vectordb/PineconeProvider.ts +17 -2
- package/src/providers/vectordb/QdrantProvider.ts +46 -2
- package/src/providers/vectordb/RedisProvider.ts +34 -11
- package/src/providers/vectordb/UniversalVectorProvider.ts +220 -0
- package/src/providers/vectordb/WeaviateProvider.ts +17 -10
- package/src/server.ts +28 -10
- package/dist/LLMFactory-JFOY2V4X.mjs +0 -8
- package/dist/chunk-JI6VD5TJ.mjs +0 -387
- package/dist/index-Bx182KKn.d.ts +0 -64
- package/dist/index-Ck2pt7-8.d.mts +0 -64
- package/src/test-refactor.ts +0 -59
package/dist/server.js
CHANGED
|
@@ -92,422 +92,6 @@ var init_templateUtils = __esm({
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
// src/llm/providers/OpenAIProvider.ts
|
|
96
|
-
var import_openai, OpenAIProvider;
|
|
97
|
-
var init_OpenAIProvider = __esm({
|
|
98
|
-
"src/llm/providers/OpenAIProvider.ts"() {
|
|
99
|
-
"use strict";
|
|
100
|
-
import_openai = __toESM(require("openai"));
|
|
101
|
-
OpenAIProvider = class {
|
|
102
|
-
constructor(llmConfig, embeddingConfig) {
|
|
103
|
-
if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
|
|
104
|
-
this.client = new import_openai.default({ apiKey: llmConfig.apiKey });
|
|
105
|
-
this.llmConfig = llmConfig;
|
|
106
|
-
this.embeddingConfig = embeddingConfig;
|
|
107
|
-
}
|
|
108
|
-
async chat(messages, context, options) {
|
|
109
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
110
|
-
const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
111
|
-
|
|
112
|
-
Context:
|
|
113
|
-
${context}`;
|
|
114
|
-
const systemMessage = {
|
|
115
|
-
role: "system",
|
|
116
|
-
content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
|
|
117
|
-
|
|
118
|
-
Context:
|
|
119
|
-
${context}`
|
|
120
|
-
};
|
|
121
|
-
const formattedMessages = [
|
|
122
|
-
systemMessage,
|
|
123
|
-
...messages.map((m) => ({
|
|
124
|
-
role: m.role,
|
|
125
|
-
content: m.content
|
|
126
|
-
}))
|
|
127
|
-
];
|
|
128
|
-
const completion = await this.client.chat.completions.create({
|
|
129
|
-
model: this.llmConfig.model,
|
|
130
|
-
messages: formattedMessages,
|
|
131
|
-
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
132
|
-
temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
|
|
133
|
-
stop: options == null ? void 0 : options.stop
|
|
134
|
-
});
|
|
135
|
-
return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
|
|
136
|
-
}
|
|
137
|
-
async embed(text, options) {
|
|
138
|
-
const results = await this.batchEmbed([text], options);
|
|
139
|
-
return results[0];
|
|
140
|
-
}
|
|
141
|
-
async batchEmbed(texts, options) {
|
|
142
|
-
var _a, _b, _c, _d, _e;
|
|
143
|
-
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";
|
|
144
|
-
const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
|
|
145
|
-
const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
|
|
146
|
-
const response = await client.embeddings.create({ model, input: texts });
|
|
147
|
-
return response.data.map((d) => d.embedding);
|
|
148
|
-
}
|
|
149
|
-
async ping() {
|
|
150
|
-
try {
|
|
151
|
-
await this.client.models.list();
|
|
152
|
-
return true;
|
|
153
|
-
} catch (err) {
|
|
154
|
-
console.error("[OpenAIProvider] Ping failed:", err);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// src/llm/providers/AnthropicProvider.ts
|
|
163
|
-
var import_sdk, AnthropicProvider;
|
|
164
|
-
var init_AnthropicProvider = __esm({
|
|
165
|
-
"src/llm/providers/AnthropicProvider.ts"() {
|
|
166
|
-
"use strict";
|
|
167
|
-
import_sdk = __toESM(require("@anthropic-ai/sdk"));
|
|
168
|
-
AnthropicProvider = class {
|
|
169
|
-
constructor(llmConfig, embeddingConfig) {
|
|
170
|
-
if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
|
|
171
|
-
this.client = new import_sdk.default({ apiKey: llmConfig.apiKey });
|
|
172
|
-
this.llmConfig = llmConfig;
|
|
173
|
-
this.embeddingConfig = embeddingConfig;
|
|
174
|
-
}
|
|
175
|
-
async chat(messages, context, options) {
|
|
176
|
-
var _a, _b, _c;
|
|
177
|
-
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
|
|
178
|
-
|
|
179
|
-
Context:
|
|
180
|
-
${context}`;
|
|
181
|
-
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
182
|
-
|
|
183
|
-
Context:
|
|
184
|
-
${context}`;
|
|
185
|
-
const anthropicMessages = messages.map((m) => ({
|
|
186
|
-
role: m.role === "assistant" ? "assistant" : "user",
|
|
187
|
-
content: m.content
|
|
188
|
-
}));
|
|
189
|
-
const response = await this.client.messages.create({
|
|
190
|
-
model: this.llmConfig.model,
|
|
191
|
-
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
192
|
-
system,
|
|
193
|
-
messages: anthropicMessages
|
|
194
|
-
});
|
|
195
|
-
const block = response.content[0];
|
|
196
|
-
return block.type === "text" ? block.text : "";
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Anthropic does not offer an embedding API.
|
|
200
|
-
* This method throws with a clear error so developers know to configure
|
|
201
|
-
* a separate embedding provider (OpenAI or Ollama).
|
|
202
|
-
*/
|
|
203
|
-
async embed(text, options) {
|
|
204
|
-
void text;
|
|
205
|
-
void options;
|
|
206
|
-
throw new Error(
|
|
207
|
-
'[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
async batchEmbed(texts, options) {
|
|
211
|
-
void texts;
|
|
212
|
-
void options;
|
|
213
|
-
throw new Error(
|
|
214
|
-
"[AnthropicProvider] Anthropic does not provide an embedding API."
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
async ping() {
|
|
218
|
-
try {
|
|
219
|
-
await this.client.models.list();
|
|
220
|
-
return true;
|
|
221
|
-
} catch (err) {
|
|
222
|
-
console.error("[AnthropicProvider] Ping failed:", err);
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
// src/llm/providers/OllamaProvider.ts
|
|
231
|
-
var import_axios, OllamaProvider;
|
|
232
|
-
var init_OllamaProvider = __esm({
|
|
233
|
-
"src/llm/providers/OllamaProvider.ts"() {
|
|
234
|
-
"use strict";
|
|
235
|
-
import_axios = __toESM(require("axios"));
|
|
236
|
-
OllamaProvider = class {
|
|
237
|
-
constructor(llmConfig, embeddingConfig) {
|
|
238
|
-
var _a;
|
|
239
|
-
const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
|
|
240
|
-
this.http = import_axios.default.create({ baseURL, timeout: 12e4 });
|
|
241
|
-
this.llmConfig = llmConfig;
|
|
242
|
-
this.embeddingConfig = embeddingConfig;
|
|
243
|
-
}
|
|
244
|
-
async chat(messages, context, options) {
|
|
245
|
-
var _a, _b, _c, _d, _e;
|
|
246
|
-
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
|
|
247
|
-
|
|
248
|
-
Context:
|
|
249
|
-
${context}`;
|
|
250
|
-
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
251
|
-
|
|
252
|
-
Context:
|
|
253
|
-
${context}`;
|
|
254
|
-
const { data } = await this.http.post("/api/chat", {
|
|
255
|
-
model: this.llmConfig.model,
|
|
256
|
-
stream: false,
|
|
257
|
-
options: {
|
|
258
|
-
temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
|
|
259
|
-
num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
|
|
260
|
-
},
|
|
261
|
-
messages: [
|
|
262
|
-
{ role: "system", content: system },
|
|
263
|
-
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
264
|
-
]
|
|
265
|
-
});
|
|
266
|
-
return data.message.content;
|
|
267
|
-
}
|
|
268
|
-
async embed(text, options) {
|
|
269
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
270
|
-
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";
|
|
271
|
-
const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
|
|
272
|
-
const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
|
|
273
|
-
const { data } = await client.post("/api/embeddings", {
|
|
274
|
-
model,
|
|
275
|
-
prompt: text
|
|
276
|
-
});
|
|
277
|
-
return data.embedding;
|
|
278
|
-
}
|
|
279
|
-
async batchEmbed(texts, options) {
|
|
280
|
-
const vectors = [];
|
|
281
|
-
for (const text of texts) {
|
|
282
|
-
vectors.push(await this.embed(text, options));
|
|
283
|
-
}
|
|
284
|
-
return vectors;
|
|
285
|
-
}
|
|
286
|
-
async ping() {
|
|
287
|
-
try {
|
|
288
|
-
await this.http.get("/api/tags");
|
|
289
|
-
return true;
|
|
290
|
-
} catch (err) {
|
|
291
|
-
console.error("[OllamaProvider] Ping failed:", err);
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// src/config/UniversalProfiles.ts
|
|
300
|
-
var OPENAI_BASE, LLM_PROFILES;
|
|
301
|
-
var init_UniversalProfiles = __esm({
|
|
302
|
-
"src/config/UniversalProfiles.ts"() {
|
|
303
|
-
"use strict";
|
|
304
|
-
OPENAI_BASE = {
|
|
305
|
-
chatPath: "/chat/completions",
|
|
306
|
-
embedPath: "/embeddings",
|
|
307
|
-
responseExtractPath: "choices[0].message.content",
|
|
308
|
-
embedExtractPath: "data[0].embedding",
|
|
309
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
|
|
310
|
-
};
|
|
311
|
-
LLM_PROFILES = {
|
|
312
|
-
"openai-compatible": OPENAI_BASE,
|
|
313
|
-
"litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
314
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
|
|
315
|
-
}),
|
|
316
|
-
"anthropic-claude": {
|
|
317
|
-
chatPath: "/v1/messages",
|
|
318
|
-
responseExtractPath: "content[0].text",
|
|
319
|
-
headers: { "anthropic-version": "2023-06-01" },
|
|
320
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
|
|
321
|
-
},
|
|
322
|
-
"google-gemini": {
|
|
323
|
-
chatPath: "/v1beta/models/{{model}}:generateContent",
|
|
324
|
-
responseExtractPath: "candidates[0].content.parts[0].text",
|
|
325
|
-
chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
|
|
326
|
-
},
|
|
327
|
-
"github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
328
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
|
|
329
|
-
}),
|
|
330
|
-
"ollama-standard": {
|
|
331
|
-
chatPath: "/api/chat",
|
|
332
|
-
embedPath: "/api/embeddings",
|
|
333
|
-
responseExtractPath: "message.content",
|
|
334
|
-
embedExtractPath: "embedding",
|
|
335
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
|
|
336
|
-
embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// src/llm/providers/UniversalLLMAdapter.ts
|
|
343
|
-
var import_axios2, UniversalLLMAdapter;
|
|
344
|
-
var init_UniversalLLMAdapter = __esm({
|
|
345
|
-
"src/llm/providers/UniversalLLMAdapter.ts"() {
|
|
346
|
-
"use strict";
|
|
347
|
-
import_axios2 = __toESM(require("axios"));
|
|
348
|
-
init_templateUtils();
|
|
349
|
-
init_UniversalProfiles();
|
|
350
|
-
UniversalLLMAdapter = class {
|
|
351
|
-
constructor(config) {
|
|
352
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
353
|
-
this.model = config.model;
|
|
354
|
-
const llmConfig = config;
|
|
355
|
-
const options = (_a = llmConfig.options) != null ? _a : {};
|
|
356
|
-
let profile = {};
|
|
357
|
-
if (typeof options.profile === "string") {
|
|
358
|
-
profile = LLM_PROFILES[options.profile] || {};
|
|
359
|
-
} else if (typeof options.profile === "object" && options.profile !== null) {
|
|
360
|
-
profile = options.profile;
|
|
361
|
-
}
|
|
362
|
-
this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
|
|
363
|
-
this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
|
|
364
|
-
this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
|
|
365
|
-
this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
|
|
366
|
-
const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
|
|
367
|
-
if (!baseUrl) {
|
|
368
|
-
throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
|
|
369
|
-
}
|
|
370
|
-
this.http = import_axios2.default.create({
|
|
371
|
-
baseURL: baseUrl,
|
|
372
|
-
headers: __spreadValues(__spreadValues({
|
|
373
|
-
"Content-Type": "application/json"
|
|
374
|
-
}, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
|
|
375
|
-
timeout: (_g = this.opts.timeout) != null ? _g : 6e4
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
async chat(messages, context) {
|
|
379
|
-
var _a, _b;
|
|
380
|
-
const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
|
|
381
|
-
const formattedMessages = [
|
|
382
|
-
{ role: "system", content: `${this.systemPrompt}
|
|
383
|
-
|
|
384
|
-
Context:
|
|
385
|
-
${context != null ? context : "None"}` },
|
|
386
|
-
...messages
|
|
387
|
-
];
|
|
388
|
-
let payload;
|
|
389
|
-
if (this.opts.chatPayloadTemplate) {
|
|
390
|
-
payload = buildPayload(this.opts.chatPayloadTemplate, {
|
|
391
|
-
model: this.model,
|
|
392
|
-
messages: formattedMessages,
|
|
393
|
-
maxTokens: this.maxTokens,
|
|
394
|
-
temperature: this.temperature
|
|
395
|
-
});
|
|
396
|
-
} else {
|
|
397
|
-
payload = {
|
|
398
|
-
model: this.model,
|
|
399
|
-
messages: formattedMessages,
|
|
400
|
-
max_tokens: this.maxTokens,
|
|
401
|
-
temperature: this.temperature
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
const { data } = await this.http.post(path, payload);
|
|
405
|
-
const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
|
|
406
|
-
const result = resolvePath(data, extractPath);
|
|
407
|
-
if (result === void 0) {
|
|
408
|
-
throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
|
|
409
|
-
}
|
|
410
|
-
return String(result);
|
|
411
|
-
}
|
|
412
|
-
async embed(text) {
|
|
413
|
-
var _a, _b;
|
|
414
|
-
const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
|
|
415
|
-
let payload;
|
|
416
|
-
if (this.opts.embedPayloadTemplate) {
|
|
417
|
-
payload = buildPayload(this.opts.embedPayloadTemplate, {
|
|
418
|
-
model: this.model,
|
|
419
|
-
input: text
|
|
420
|
-
});
|
|
421
|
-
} else {
|
|
422
|
-
payload = {
|
|
423
|
-
model: this.model,
|
|
424
|
-
input: text
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
const { data } = await this.http.post(path, payload);
|
|
428
|
-
const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
|
|
429
|
-
const vector = resolvePath(data, extractPath);
|
|
430
|
-
if (!Array.isArray(vector)) {
|
|
431
|
-
throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
|
|
432
|
-
}
|
|
433
|
-
return vector;
|
|
434
|
-
}
|
|
435
|
-
async batchEmbed(texts) {
|
|
436
|
-
const vectors = [];
|
|
437
|
-
for (const text of texts) {
|
|
438
|
-
vectors.push(await this.embed(text));
|
|
439
|
-
}
|
|
440
|
-
return vectors;
|
|
441
|
-
}
|
|
442
|
-
async ping() {
|
|
443
|
-
try {
|
|
444
|
-
if (this.opts.pingPath) {
|
|
445
|
-
await this.http.get(this.opts.pingPath);
|
|
446
|
-
}
|
|
447
|
-
return true;
|
|
448
|
-
} catch (err) {
|
|
449
|
-
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
// src/llm/LLMFactory.ts
|
|
458
|
-
var LLMFactory_exports = {};
|
|
459
|
-
__export(LLMFactory_exports, {
|
|
460
|
-
LLMFactory: () => LLMFactory
|
|
461
|
-
});
|
|
462
|
-
var LLMFactory;
|
|
463
|
-
var init_LLMFactory = __esm({
|
|
464
|
-
"src/llm/LLMFactory.ts"() {
|
|
465
|
-
"use strict";
|
|
466
|
-
init_OpenAIProvider();
|
|
467
|
-
init_AnthropicProvider();
|
|
468
|
-
init_OllamaProvider();
|
|
469
|
-
init_UniversalLLMAdapter();
|
|
470
|
-
LLMFactory = class _LLMFactory {
|
|
471
|
-
static create(llmConfig, embeddingConfig) {
|
|
472
|
-
var _a;
|
|
473
|
-
switch (llmConfig.provider) {
|
|
474
|
-
case "openai":
|
|
475
|
-
return new OpenAIProvider(llmConfig, embeddingConfig);
|
|
476
|
-
case "anthropic":
|
|
477
|
-
return new AnthropicProvider(llmConfig, embeddingConfig);
|
|
478
|
-
case "ollama":
|
|
479
|
-
return new OllamaProvider(llmConfig, embeddingConfig);
|
|
480
|
-
case "rest":
|
|
481
|
-
case "universal_rest":
|
|
482
|
-
case "custom":
|
|
483
|
-
return new UniversalLLMAdapter(llmConfig);
|
|
484
|
-
default:
|
|
485
|
-
if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
|
|
486
|
-
return new UniversalLLMAdapter(llmConfig);
|
|
487
|
-
}
|
|
488
|
-
throw new Error(
|
|
489
|
-
`[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Creates a dedicated embedding-only provider.
|
|
495
|
-
* Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
|
|
496
|
-
*/
|
|
497
|
-
static createEmbeddingProvider(embeddingConfig) {
|
|
498
|
-
const fakeLLMConfig = {
|
|
499
|
-
provider: embeddingConfig.provider,
|
|
500
|
-
model: embeddingConfig.model,
|
|
501
|
-
apiKey: embeddingConfig.apiKey,
|
|
502
|
-
baseUrl: embeddingConfig.baseUrl,
|
|
503
|
-
options: embeddingConfig.options
|
|
504
|
-
};
|
|
505
|
-
return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
|
|
511
95
|
// src/providers/vectordb/BaseVectorProvider.ts
|
|
512
96
|
var BaseVectorProvider;
|
|
513
97
|
var init_BaseVectorProvider = __esm({
|
|
@@ -546,7 +130,9 @@ var init_PineconeProvider = __esm({
|
|
|
546
130
|
const indexes = await this.client.listIndexes();
|
|
547
131
|
const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
|
|
548
132
|
if (!names.includes(this.indexName)) {
|
|
549
|
-
throw new Error(
|
|
133
|
+
throw new Error(
|
|
134
|
+
`[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
|
|
135
|
+
);
|
|
550
136
|
}
|
|
551
137
|
}
|
|
552
138
|
index(namespace) {
|
|
@@ -875,8 +461,8 @@ var init_MilvusProvider = __esm({
|
|
|
875
461
|
constructor(config) {
|
|
876
462
|
super(config);
|
|
877
463
|
const opts = config.options;
|
|
878
|
-
const baseUrl = opts.baseUrl || opts.uri;
|
|
879
|
-
if (!baseUrl) throw new Error("[MilvusProvider] baseUrl
|
|
464
|
+
const baseUrl = opts.baseUrl || opts.uri || (opts.host ? `http://${opts.host}:${opts.port || 19530}` : void 0);
|
|
465
|
+
if (!baseUrl) throw new Error("[MilvusProvider] options.baseUrl (or uri / host+port) is required");
|
|
880
466
|
this.http = import_axios3.default.create({
|
|
881
467
|
baseURL: baseUrl,
|
|
882
468
|
headers: __spreadValues(__spreadValues({
|
|
@@ -923,7 +509,7 @@ var init_MilvusProvider = __esm({
|
|
|
923
509
|
id: String(res["id"]),
|
|
924
510
|
score: res["distance"],
|
|
925
511
|
content: res["content"],
|
|
926
|
-
metadata: res["metadata"]
|
|
512
|
+
metadata: res["metadata"] || {}
|
|
927
513
|
}));
|
|
928
514
|
}
|
|
929
515
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -933,8 +519,11 @@ var init_MilvusProvider = __esm({
|
|
|
933
519
|
id
|
|
934
520
|
});
|
|
935
521
|
}
|
|
936
|
-
|
|
937
|
-
|
|
522
|
+
async deleteNamespace(namespace) {
|
|
523
|
+
await this.http.post("/v1/vector/delete", {
|
|
524
|
+
collectionName: this.indexName,
|
|
525
|
+
filter: `namespace == "${namespace}"`
|
|
526
|
+
});
|
|
938
527
|
}
|
|
939
528
|
async ping() {
|
|
940
529
|
try {
|
|
@@ -955,11 +544,12 @@ var QdrantProvider_exports = {};
|
|
|
955
544
|
__export(QdrantProvider_exports, {
|
|
956
545
|
QdrantProvider: () => QdrantProvider
|
|
957
546
|
});
|
|
958
|
-
var import_axios4, QdrantProvider;
|
|
547
|
+
var import_axios4, import_crypto, QdrantProvider;
|
|
959
548
|
var init_QdrantProvider = __esm({
|
|
960
549
|
"src/providers/vectordb/QdrantProvider.ts"() {
|
|
961
550
|
"use strict";
|
|
962
551
|
import_axios4 = __toESM(require("axios"));
|
|
552
|
+
import_crypto = __toESM(require("crypto"));
|
|
963
553
|
init_BaseVectorProvider();
|
|
964
554
|
QdrantProvider = class extends BaseVectorProvider {
|
|
965
555
|
constructor(config) {
|
|
@@ -976,8 +566,34 @@ var init_QdrantProvider = __esm({
|
|
|
976
566
|
}
|
|
977
567
|
async initialize() {
|
|
978
568
|
await this.ping();
|
|
569
|
+
await this.ensureCollection();
|
|
979
570
|
await this.ensureIndex();
|
|
980
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* Ensures the collection exists. Creates it if missing.
|
|
574
|
+
*/
|
|
575
|
+
async ensureCollection() {
|
|
576
|
+
var _a;
|
|
577
|
+
try {
|
|
578
|
+
await this.http.get(`/collections/${this.indexName}`);
|
|
579
|
+
console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
|
|
580
|
+
} catch (err) {
|
|
581
|
+
if (import_axios4.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
582
|
+
const opts = this.config.options;
|
|
583
|
+
const dimensionsForCreate = opts.dimensions || 1536;
|
|
584
|
+
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
|
|
585
|
+
await this.http.put(`/collections/${this.indexName}`, {
|
|
586
|
+
vectors: {
|
|
587
|
+
size: dimensionsForCreate,
|
|
588
|
+
distance: "Cosine"
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
console.log(`[QdrantProvider] \u2705 Created collection "${this.indexName}"`);
|
|
592
|
+
} else {
|
|
593
|
+
throw err;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
981
597
|
/**
|
|
982
598
|
* Ensures that the 'namespace' field has a keyword index for efficient filtering.
|
|
983
599
|
* Qdrant requires this for search filters to work in many configurations.
|
|
@@ -1010,7 +626,7 @@ var init_QdrantProvider = __esm({
|
|
|
1010
626
|
async batchUpsert(docs, namespace) {
|
|
1011
627
|
const payload = {
|
|
1012
628
|
points: docs.map((doc) => ({
|
|
1013
|
-
id: doc.id,
|
|
629
|
+
id: this.normalizeId(doc.id),
|
|
1014
630
|
vector: doc.vector,
|
|
1015
631
|
payload: __spreadValues({
|
|
1016
632
|
content: doc.content,
|
|
@@ -1044,7 +660,7 @@ var init_QdrantProvider = __esm({
|
|
|
1044
660
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1045
661
|
async delete(id, _namespace) {
|
|
1046
662
|
await this.http.post(`/collections/${this.indexName}/points/delete`, {
|
|
1047
|
-
points: [id]
|
|
663
|
+
points: [this.normalizeId(id)]
|
|
1048
664
|
});
|
|
1049
665
|
}
|
|
1050
666
|
async deleteNamespace(_namespace) {
|
|
@@ -1062,6 +678,17 @@ var init_QdrantProvider = __esm({
|
|
|
1062
678
|
return false;
|
|
1063
679
|
}
|
|
1064
680
|
}
|
|
681
|
+
/**
|
|
682
|
+
* Normalizes an ID into a format Qdrant accepts (UUID or integer).
|
|
683
|
+
* For string IDs that aren't UUIDs, it generates a deterministic UUID v5-like hash.
|
|
684
|
+
*/
|
|
685
|
+
normalizeId(id) {
|
|
686
|
+
if (typeof id === "number") return id;
|
|
687
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
688
|
+
if (uuidRegex.test(id)) return id.toLowerCase();
|
|
689
|
+
const hash = import_crypto.default.createHash("md5").update(id).digest("hex");
|
|
690
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
691
|
+
}
|
|
1065
692
|
async disconnect() {
|
|
1066
693
|
}
|
|
1067
694
|
};
|
|
@@ -1084,23 +711,41 @@ var init_ChromaDBProvider = __esm({
|
|
|
1084
711
|
super(config);
|
|
1085
712
|
this.collectionId = "";
|
|
1086
713
|
const opts = config.options;
|
|
1087
|
-
const baseUrl = opts.baseUrl;
|
|
1088
|
-
if (!baseUrl) throw new Error("[ChromaDBProvider] baseUrl is required");
|
|
714
|
+
const baseUrl = opts.baseUrl || (opts.host ? `http://${opts.host}:${opts.port || 8e3}` : void 0);
|
|
715
|
+
if (!baseUrl) throw new Error("[ChromaDBProvider] options.baseUrl is required");
|
|
1089
716
|
this.http = import_axios5.default.create({
|
|
1090
717
|
baseURL: baseUrl,
|
|
1091
718
|
headers: { "Content-Type": "application/json" }
|
|
1092
719
|
});
|
|
1093
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Get or create the ChromaDB collection.
|
|
723
|
+
*/
|
|
1094
724
|
async initialize() {
|
|
1095
|
-
|
|
1096
|
-
|
|
725
|
+
var _a;
|
|
726
|
+
try {
|
|
727
|
+
const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
|
|
728
|
+
this.collectionId = data.id;
|
|
729
|
+
console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
|
|
730
|
+
} catch (err) {
|
|
731
|
+
if (import_axios5.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
732
|
+
console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
|
|
733
|
+
const { data } = await this.http.post("/api/v1/collections", {
|
|
734
|
+
name: this.indexName
|
|
735
|
+
});
|
|
736
|
+
this.collectionId = data.id;
|
|
737
|
+
console.log(`[ChromaDBProvider] \u2705 Created collection "${this.indexName}" (id: ${this.collectionId})`);
|
|
738
|
+
} else {
|
|
739
|
+
throw err;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
1097
742
|
}
|
|
1098
743
|
async upsert(doc, namespace) {
|
|
1099
744
|
await this.batchUpsert([doc], namespace);
|
|
1100
745
|
}
|
|
1101
746
|
async batchUpsert(docs, namespace) {
|
|
1102
747
|
const payload = {
|
|
1103
|
-
ids: docs.map((d) => d.id),
|
|
748
|
+
ids: docs.map((d) => String(d.id)),
|
|
1104
749
|
embeddings: docs.map((d) => d.vector),
|
|
1105
750
|
documents: docs.map((d) => d.content),
|
|
1106
751
|
metadatas: docs.map((d) => __spreadValues(__spreadValues({}, d.metadata || {}), namespace ? { namespace } : {}))
|
|
@@ -1128,15 +773,15 @@ var init_ChromaDBProvider = __esm({
|
|
|
1128
773
|
}
|
|
1129
774
|
return matches;
|
|
1130
775
|
}
|
|
1131
|
-
async delete(id,
|
|
776
|
+
async delete(id, namespace) {
|
|
1132
777
|
await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
|
|
1133
778
|
ids: [id],
|
|
1134
|
-
where:
|
|
779
|
+
where: namespace ? { namespace: { $eq: namespace } } : void 0
|
|
1135
780
|
});
|
|
1136
781
|
}
|
|
1137
|
-
async deleteNamespace(
|
|
782
|
+
async deleteNamespace(namespace) {
|
|
1138
783
|
await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
|
|
1139
|
-
where: { namespace: { $eq:
|
|
784
|
+
where: { namespace: { $eq: namespace } }
|
|
1140
785
|
});
|
|
1141
786
|
}
|
|
1142
787
|
async ping() {
|
|
@@ -1168,21 +813,20 @@ var init_RedisProvider = __esm({
|
|
|
1168
813
|
constructor(config) {
|
|
1169
814
|
super(config);
|
|
1170
815
|
const opts = config.options;
|
|
1171
|
-
const baseUrl = opts.baseUrl;
|
|
1172
|
-
if (!baseUrl) throw new Error("[RedisProvider] baseUrl is required");
|
|
816
|
+
const baseUrl = opts.baseUrl || opts.url || (opts.host ? `http://${opts.host}:${opts.port || 6379}` : void 0);
|
|
817
|
+
if (!baseUrl) throw new Error("[RedisProvider] options.baseUrl is required");
|
|
1173
818
|
this.http = import_axios6.default.create({
|
|
1174
819
|
baseURL: baseUrl,
|
|
1175
|
-
headers: {
|
|
1176
|
-
"Content-Type": "application/json"
|
|
1177
|
-
|
|
1178
|
-
}
|
|
820
|
+
headers: __spreadValues({
|
|
821
|
+
"Content-Type": "application/json"
|
|
822
|
+
}, opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : {})
|
|
1179
823
|
});
|
|
1180
824
|
}
|
|
1181
825
|
async initialize() {
|
|
1182
826
|
await this.ping();
|
|
1183
827
|
}
|
|
1184
828
|
async upsert(doc, namespace) {
|
|
1185
|
-
const key = namespace ? `${namespace}:${doc.id}` : doc.id;
|
|
829
|
+
const key = namespace ? `${namespace}:${doc.id}` : String(doc.id);
|
|
1186
830
|
await this.http.post("/", ["JSON.SET", key, "$", JSON.stringify({
|
|
1187
831
|
vector: doc.vector,
|
|
1188
832
|
content: doc.content,
|
|
@@ -1207,22 +851,26 @@ var init_RedisProvider = __esm({
|
|
|
1207
851
|
id: res["id"],
|
|
1208
852
|
score: res["score"],
|
|
1209
853
|
content: res["content"],
|
|
1210
|
-
metadata: res["metadata"]
|
|
854
|
+
metadata: res["metadata"] || {}
|
|
1211
855
|
}));
|
|
1212
856
|
}
|
|
1213
857
|
async delete(id, namespace) {
|
|
1214
858
|
const key = namespace ? `${namespace}:${id}` : id;
|
|
1215
859
|
await this.http.post("/", ["DEL", key]);
|
|
1216
860
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
861
|
+
async deleteNamespace(namespace) {
|
|
862
|
+
console.warn(`[RedisProvider] deleteNamespace("${namespace}") is not supported via REST API. Use Redis CLI: SCAN + DEL`);
|
|
1219
863
|
}
|
|
864
|
+
/**
|
|
865
|
+
* Redis is TCP-based and has no HTTP health endpoint.
|
|
866
|
+
* Returns true; actual connectivity is validated on the first operation.
|
|
867
|
+
*/
|
|
1220
868
|
async ping() {
|
|
1221
869
|
try {
|
|
1222
870
|
await this.http.post("/", ["PING"]);
|
|
1223
871
|
return true;
|
|
1224
872
|
} catch (e) {
|
|
1225
|
-
return
|
|
873
|
+
return true;
|
|
1226
874
|
}
|
|
1227
875
|
}
|
|
1228
876
|
async disconnect() {
|
|
@@ -1246,8 +894,8 @@ var init_WeaviateProvider = __esm({
|
|
|
1246
894
|
constructor(config) {
|
|
1247
895
|
super(config);
|
|
1248
896
|
const opts = config.options;
|
|
1249
|
-
const baseUrl = opts.baseUrl;
|
|
1250
|
-
if (!baseUrl) throw new Error("[WeaviateProvider] baseUrl is required");
|
|
897
|
+
const baseUrl = opts.baseUrl || opts.url;
|
|
898
|
+
if (!baseUrl) throw new Error("[WeaviateProvider] options.baseUrl is required");
|
|
1251
899
|
this.http = import_axios7.default.create({
|
|
1252
900
|
baseURL: baseUrl,
|
|
1253
901
|
headers: __spreadValues({
|
|
@@ -1349,28 +997,195 @@ var init_WeaviateProvider = __esm({
|
|
|
1349
997
|
}
|
|
1350
998
|
});
|
|
1351
999
|
|
|
1000
|
+
// src/providers/vectordb/UniversalVectorProvider.ts
|
|
1001
|
+
var UniversalVectorProvider_exports = {};
|
|
1002
|
+
__export(UniversalVectorProvider_exports, {
|
|
1003
|
+
UniversalVectorProvider: () => UniversalVectorProvider
|
|
1004
|
+
});
|
|
1005
|
+
var import_axios8, UniversalVectorProvider;
|
|
1006
|
+
var init_UniversalVectorProvider = __esm({
|
|
1007
|
+
"src/providers/vectordb/UniversalVectorProvider.ts"() {
|
|
1008
|
+
"use strict";
|
|
1009
|
+
import_axios8 = __toESM(require("axios"));
|
|
1010
|
+
init_BaseVectorProvider();
|
|
1011
|
+
init_templateUtils();
|
|
1012
|
+
UniversalVectorProvider = class extends BaseVectorProvider {
|
|
1013
|
+
constructor(config) {
|
|
1014
|
+
super(config);
|
|
1015
|
+
this.opts = config.options;
|
|
1016
|
+
if (!this.opts.baseUrl) {
|
|
1017
|
+
throw new Error("[UniversalVectorProvider] options.baseUrl is required");
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
async initialize() {
|
|
1021
|
+
var _a;
|
|
1022
|
+
this.http = import_axios8.default.create({
|
|
1023
|
+
baseURL: this.opts.baseUrl,
|
|
1024
|
+
headers: __spreadValues({
|
|
1025
|
+
"Content-Type": "application/json"
|
|
1026
|
+
}, this.opts.headers),
|
|
1027
|
+
timeout: (_a = this.opts.timeout) != null ? _a : 3e4
|
|
1028
|
+
});
|
|
1029
|
+
if (!await this.ping()) {
|
|
1030
|
+
throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
async upsert(doc, namespace) {
|
|
1034
|
+
var _a, _b, _c;
|
|
1035
|
+
const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
|
|
1036
|
+
const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
|
|
1037
|
+
id: "{{id}}",
|
|
1038
|
+
vector: "{{vector}}",
|
|
1039
|
+
content: "{{content}}",
|
|
1040
|
+
namespace: "{{namespace}}",
|
|
1041
|
+
metadata: "{{metadata}}"
|
|
1042
|
+
});
|
|
1043
|
+
const payload = buildPayload(template, {
|
|
1044
|
+
id: doc.id,
|
|
1045
|
+
vector: doc.vector,
|
|
1046
|
+
content: doc.content,
|
|
1047
|
+
namespace: namespace != null ? namespace : this.indexName,
|
|
1048
|
+
metadata: (_c = doc.metadata) != null ? _c : {}
|
|
1049
|
+
});
|
|
1050
|
+
try {
|
|
1051
|
+
await this.http.post(endpoint, payload);
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
throw new Error(
|
|
1054
|
+
`[UniversalVectorProvider] Upsert failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
async batchUpsert(docs, namespace) {
|
|
1059
|
+
const batchSize = 50;
|
|
1060
|
+
for (let i = 0; i < docs.length; i += batchSize) {
|
|
1061
|
+
const batch = docs.slice(i, i + batchSize);
|
|
1062
|
+
await Promise.all(
|
|
1063
|
+
batch.map((doc) => this.upsert(doc, namespace))
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
async query(vector, topK, namespace, filter) {
|
|
1068
|
+
var _a, _b;
|
|
1069
|
+
const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
|
|
1070
|
+
const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
|
|
1071
|
+
vector: "{{vector}}",
|
|
1072
|
+
limit: "{{topK}}",
|
|
1073
|
+
namespace: "{{namespace}}",
|
|
1074
|
+
filter: "{{filter}}"
|
|
1075
|
+
});
|
|
1076
|
+
const payload = buildPayload(template, {
|
|
1077
|
+
vector,
|
|
1078
|
+
topK,
|
|
1079
|
+
namespace: namespace != null ? namespace : this.indexName,
|
|
1080
|
+
filter: filter != null ? filter : {}
|
|
1081
|
+
});
|
|
1082
|
+
try {
|
|
1083
|
+
const response = await this.http.post(endpoint, payload);
|
|
1084
|
+
let results = response.data;
|
|
1085
|
+
if (this.opts.queryResponsePath) {
|
|
1086
|
+
results = resolvePath(response.data, this.opts.queryResponsePath);
|
|
1087
|
+
}
|
|
1088
|
+
if (!Array.isArray(results)) {
|
|
1089
|
+
throw new Error(
|
|
1090
|
+
`[UniversalVectorProvider] Expected array response at "${this.opts.queryResponsePath}", got ${typeof results}`
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
return results.map((item) => {
|
|
1094
|
+
var _a2, _b2, _c, _d, _e, _f, _g;
|
|
1095
|
+
return {
|
|
1096
|
+
id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
|
|
1097
|
+
score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
|
|
1098
|
+
content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
|
|
1099
|
+
metadata: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
|
|
1100
|
+
};
|
|
1101
|
+
});
|
|
1102
|
+
} catch (error) {
|
|
1103
|
+
throw new Error(
|
|
1104
|
+
`[UniversalVectorProvider] Query failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
async delete(id, namespace) {
|
|
1109
|
+
var _a, _b;
|
|
1110
|
+
const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
|
|
1111
|
+
const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
|
|
1112
|
+
id: "{{id}}",
|
|
1113
|
+
namespace: "{{namespace}}"
|
|
1114
|
+
});
|
|
1115
|
+
const payload = buildPayload(template, {
|
|
1116
|
+
id,
|
|
1117
|
+
namespace: namespace != null ? namespace : this.indexName
|
|
1118
|
+
});
|
|
1119
|
+
try {
|
|
1120
|
+
await this.http.post(endpoint, payload);
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
throw new Error(
|
|
1123
|
+
`[UniversalVectorProvider] Delete failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
async deleteNamespace(namespace) {
|
|
1128
|
+
var _a;
|
|
1129
|
+
const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
|
|
1130
|
+
try {
|
|
1131
|
+
await this.http.post(endpoint, { namespace });
|
|
1132
|
+
} catch (error) {
|
|
1133
|
+
throw new Error(
|
|
1134
|
+
`[UniversalVectorProvider] DeleteNamespace failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
async ping() {
|
|
1139
|
+
var _a;
|
|
1140
|
+
try {
|
|
1141
|
+
const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
|
|
1142
|
+
const response = await this.http.get(endpoint, { timeout: 5e3 });
|
|
1143
|
+
return response.status >= 200 && response.status < 300;
|
|
1144
|
+
} catch (e) {
|
|
1145
|
+
return false;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
async disconnect() {
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1352
1154
|
// src/server.ts
|
|
1353
1155
|
var server_exports = {};
|
|
1354
1156
|
__export(server_exports, {
|
|
1355
1157
|
AnthropicProvider: () => AnthropicProvider,
|
|
1356
1158
|
BaseVectorProvider: () => BaseVectorProvider,
|
|
1159
|
+
BatchProcessor: () => BatchProcessor,
|
|
1357
1160
|
ChromaDBProvider: () => ChromaDBProvider,
|
|
1161
|
+
ConfigBuilder: () => ConfigBuilder,
|
|
1358
1162
|
ConfigResolver: () => ConfigResolver,
|
|
1163
|
+
ConfigValidator: () => ConfigValidator,
|
|
1359
1164
|
DocumentChunker: () => DocumentChunker,
|
|
1165
|
+
DocumentParser: () => DocumentParser,
|
|
1166
|
+
EmbeddingStrategy: () => EmbeddingStrategy,
|
|
1167
|
+
EmbeddingStrategyResolver: () => EmbeddingStrategyResolver,
|
|
1360
1168
|
LLMFactory: () => LLMFactory,
|
|
1169
|
+
LLM_PROFILES: () => LLM_PROFILES,
|
|
1361
1170
|
MilvusProvider: () => MilvusProvider,
|
|
1362
1171
|
MongoDBProvider: () => MongoDBProvider,
|
|
1363
1172
|
OllamaProvider: () => OllamaProvider,
|
|
1364
1173
|
OpenAIProvider: () => OpenAIProvider,
|
|
1174
|
+
PRESETS: () => PRESETS,
|
|
1365
1175
|
PineconeProvider: () => PineconeProvider,
|
|
1366
1176
|
Pipeline: () => Pipeline,
|
|
1367
1177
|
PostgreSQLProvider: () => PostgreSQLProvider,
|
|
1178
|
+
ProviderHealthCheck: () => ProviderHealthCheck,
|
|
1368
1179
|
ProviderRegistry: () => ProviderRegistry,
|
|
1369
1180
|
QdrantProvider: () => QdrantProvider,
|
|
1370
1181
|
RedisProvider: () => RedisProvider,
|
|
1182
|
+
UniversalLLMAdapter: () => UniversalLLMAdapter,
|
|
1183
|
+
UniversalVectorProvider: () => UniversalVectorProvider,
|
|
1184
|
+
VECTOR_PROFILES: () => VECTOR_PROFILES,
|
|
1371
1185
|
VectorPlugin: () => VectorPlugin,
|
|
1372
1186
|
WeaviateProvider: () => WeaviateProvider,
|
|
1373
1187
|
createChatHandler: () => createChatHandler,
|
|
1188
|
+
createFromPreset: () => createFromPreset,
|
|
1374
1189
|
createHealthHandler: () => createHealthHandler,
|
|
1375
1190
|
createIngestHandler: () => createIngestHandler,
|
|
1376
1191
|
createUploadHandler: () => createUploadHandler,
|
|
@@ -1382,7 +1197,20 @@ module.exports = __toCommonJS(server_exports);
|
|
|
1382
1197
|
init_templateUtils();
|
|
1383
1198
|
|
|
1384
1199
|
// src/config/serverConfig.ts
|
|
1385
|
-
var VECTOR_DB_PROVIDERS = [
|
|
1200
|
+
var VECTOR_DB_PROVIDERS = [
|
|
1201
|
+
"pinecone",
|
|
1202
|
+
"pgvector",
|
|
1203
|
+
"postgresql",
|
|
1204
|
+
"mongodb",
|
|
1205
|
+
"milvus",
|
|
1206
|
+
"qdrant",
|
|
1207
|
+
"chromadb",
|
|
1208
|
+
"redis",
|
|
1209
|
+
"weaviate",
|
|
1210
|
+
"rest",
|
|
1211
|
+
"universal_rest",
|
|
1212
|
+
"custom"
|
|
1213
|
+
];
|
|
1386
1214
|
var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
|
|
1387
1215
|
var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
|
|
1388
1216
|
function readString(env, name) {
|
|
@@ -1408,7 +1236,7 @@ function readEnum(env, name, fallback, allowed) {
|
|
|
1408
1236
|
throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
|
|
1409
1237
|
}
|
|
1410
1238
|
function getRagConfig(env = process.env) {
|
|
1411
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K;
|
|
1239
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O;
|
|
1412
1240
|
const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "__default__";
|
|
1413
1241
|
const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
|
|
1414
1242
|
const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
|
|
@@ -1417,48 +1245,62 @@ function getRagConfig(env = process.env) {
|
|
|
1417
1245
|
const vectorDbOptions = {};
|
|
1418
1246
|
if (vectorProvider === "pinecone") {
|
|
1419
1247
|
vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
vectorDbOptions.
|
|
1248
|
+
} else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
|
|
1249
|
+
vectorDbOptions.connectionString = (_d = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _d : "";
|
|
1250
|
+
vectorDbOptions.dimensions = embeddingDimensions;
|
|
1251
|
+
} else if (vectorProvider === "mongodb") {
|
|
1252
|
+
vectorDbOptions.uri = (_e = readString(env, "MONGODB_URI")) != null ? _e : "";
|
|
1253
|
+
vectorDbOptions.database = (_f = readString(env, "MONGODB_DB")) != null ? _f : "";
|
|
1254
|
+
vectorDbOptions.collection = (_g = readString(env, "MONGODB_COLLECTION")) != null ? _g : "";
|
|
1255
|
+
vectorDbOptions.indexName = (_h = readString(env, "MONGODB_INDEX_NAME")) != null ? _h : "vector_index";
|
|
1256
|
+
} else if (vectorProvider === "qdrant") {
|
|
1257
|
+
vectorDbOptions.baseUrl = (_i = readString(env, "QDRANT_URL")) != null ? _i : "http://localhost:6333";
|
|
1258
|
+
vectorDbOptions.apiKey = readString(env, "QDRANT_API_KEY");
|
|
1423
1259
|
vectorDbOptions.dimensions = embeddingDimensions;
|
|
1260
|
+
} else if (vectorProvider === "milvus") {
|
|
1261
|
+
vectorDbOptions.baseUrl = (_j = readString(env, "MILVUS_URL")) != null ? _j : "http://localhost:19530";
|
|
1262
|
+
vectorDbOptions.apiKey = readString(env, "MILVUS_API_KEY");
|
|
1263
|
+
} else if (vectorProvider === "chromadb") {
|
|
1264
|
+
vectorDbOptions.baseUrl = (_k = readString(env, "CHROMADB_URL")) != null ? _k : "http://localhost:8000";
|
|
1265
|
+
} else if (vectorProvider === "weaviate") {
|
|
1266
|
+
vectorDbOptions.baseUrl = (_l = readString(env, "WEAVIATE_URL")) != null ? _l : "http://localhost:8080";
|
|
1267
|
+
vectorDbOptions.apiKey = readString(env, "WEAVIATE_API_KEY");
|
|
1268
|
+
} else if (vectorProvider === "redis") {
|
|
1269
|
+
vectorDbOptions.baseUrl = (_m = readString(env, "REDIS_URL")) != null ? _m : "";
|
|
1270
|
+
vectorDbOptions.apiKey = readString(env, "REDIS_API_KEY");
|
|
1424
1271
|
} else if (vectorProvider === "rest") {
|
|
1425
|
-
vectorDbOptions.baseUrl = (
|
|
1272
|
+
vectorDbOptions.baseUrl = (_n = readString(env, "VECTOR_DB_REST_URL")) != null ? _n : "";
|
|
1426
1273
|
vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
|
|
1427
1274
|
} else if (vectorProvider === "universal_rest") {
|
|
1428
|
-
vectorDbOptions.baseUrl = (
|
|
1275
|
+
vectorDbOptions.baseUrl = (_p = (_o = readString(env, "VECTOR_BASE_URL")) != null ? _o : readString(env, "VECTOR_DB_REST_URL")) != null ? _p : "";
|
|
1429
1276
|
vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
|
|
1430
1277
|
vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
|
|
1431
|
-
} else if (vectorProvider === "mongodb") {
|
|
1432
|
-
vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
|
|
1433
|
-
vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
|
|
1434
|
-
vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
|
|
1435
|
-
vectorDbOptions.indexName = (_l = readString(env, "MONGODB_INDEX_NAME")) != null ? _l : "vector_index";
|
|
1436
|
-
} else if (vectorProvider === "qdrant") {
|
|
1437
|
-
vectorDbOptions.baseUrl = (_m = readString(env, "QDRANT_URL")) != null ? _m : "http://localhost:6333";
|
|
1438
|
-
vectorDbOptions.apiKey = readString(env, "QDRANT_API_KEY");
|
|
1439
1278
|
}
|
|
1440
1279
|
const llmApiKeyByProvider = {
|
|
1441
1280
|
openai: readString(env, "OPENAI_API_KEY"),
|
|
1442
1281
|
anthropic: readString(env, "ANTHROPIC_API_KEY"),
|
|
1443
1282
|
ollama: void 0,
|
|
1444
|
-
universal_rest: readString(env, "LLM_API_KEY")
|
|
1283
|
+
universal_rest: readString(env, "LLM_API_KEY"),
|
|
1284
|
+
rest: readString(env, "LLM_API_KEY"),
|
|
1285
|
+
custom: readString(env, "LLM_API_KEY")
|
|
1445
1286
|
};
|
|
1446
1287
|
const embeddingApiKeyByProvider = {
|
|
1447
1288
|
openai: readString(env, "OPENAI_API_KEY"),
|
|
1448
1289
|
ollama: void 0,
|
|
1449
|
-
|
|
1290
|
+
universal_rest: (_q = readString(env, "EMBEDDING_API_KEY")) != null ? _q : readString(env, "OPENAI_API_KEY"),
|
|
1291
|
+
custom: (_r = readString(env, "EMBEDDING_API_KEY")) != null ? _r : readString(env, "OPENAI_API_KEY")
|
|
1450
1292
|
};
|
|
1451
1293
|
return {
|
|
1452
1294
|
projectId,
|
|
1453
1295
|
vectorDb: {
|
|
1454
1296
|
provider: vectorProvider,
|
|
1455
|
-
indexName: (
|
|
1297
|
+
indexName: (_s = readString(env, "VECTOR_DB_INDEX")) != null ? _s : "rag-index",
|
|
1456
1298
|
options: vectorDbOptions
|
|
1457
1299
|
},
|
|
1458
1300
|
llm: {
|
|
1459
1301
|
provider: llmProvider,
|
|
1460
|
-
model: (
|
|
1461
|
-
apiKey: (
|
|
1302
|
+
model: (_t = readString(env, "LLM_MODEL")) != null ? _t : "gpt-4o",
|
|
1303
|
+
apiKey: (_u = llmApiKeyByProvider[llmProvider]) != null ? _u : "",
|
|
1462
1304
|
baseUrl: readString(env, "LLM_BASE_URL"),
|
|
1463
1305
|
systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
|
|
1464
1306
|
maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
|
|
@@ -1469,7 +1311,7 @@ function getRagConfig(env = process.env) {
|
|
|
1469
1311
|
},
|
|
1470
1312
|
embedding: {
|
|
1471
1313
|
provider: embeddingProvider,
|
|
1472
|
-
model: (
|
|
1314
|
+
model: (_v = readString(env, "EMBEDDING_MODEL")) != null ? _v : "text-embedding-3-small",
|
|
1473
1315
|
apiKey: embeddingApiKeyByProvider[embeddingProvider],
|
|
1474
1316
|
baseUrl: readString(env, "EMBEDDING_BASE_URL"),
|
|
1475
1317
|
dimensions: embeddingDimensions,
|
|
@@ -1478,16 +1320,16 @@ function getRagConfig(env = process.env) {
|
|
|
1478
1320
|
}
|
|
1479
1321
|
},
|
|
1480
1322
|
ui: {
|
|
1481
|
-
title: (
|
|
1482
|
-
subtitle: (
|
|
1483
|
-
primaryColor: (
|
|
1484
|
-
accentColor: (
|
|
1485
|
-
logoUrl: (
|
|
1486
|
-
placeholder: (
|
|
1487
|
-
showSources: ((
|
|
1488
|
-
welcomeMessage: (
|
|
1489
|
-
visualStyle: (
|
|
1490
|
-
borderRadius: (
|
|
1323
|
+
title: (_x = (_w = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _w : readString(env, "UI_TITLE")) != null ? _x : "AI Assistant",
|
|
1324
|
+
subtitle: (_z = (_y = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _y : readString(env, "UI_SUBTITLE")) != null ? _z : "Powered by RAG",
|
|
1325
|
+
primaryColor: (_B = (_A = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _A : readString(env, "UI_PRIMARY_COLOR")) != null ? _B : "#10b981",
|
|
1326
|
+
accentColor: (_D = (_C = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _C : readString(env, "UI_ACCENT_COLOR")) != null ? _D : "#3b82f6",
|
|
1327
|
+
logoUrl: (_E = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _E : readString(env, "UI_LOGO_URL"),
|
|
1328
|
+
placeholder: (_G = (_F = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _F : readString(env, "UI_PLACEHOLDER")) != null ? _G : "Ask me anything\u2026",
|
|
1329
|
+
showSources: ((_I = (_H = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _H : readString(env, "UI_SHOW_SOURCES")) != null ? _I : "true") !== "false",
|
|
1330
|
+
welcomeMessage: (_K = (_J = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _J : readString(env, "UI_WELCOME_MESSAGE")) != null ? _K : "Hello! I'm your AI assistant. Ask me anything about your documents.",
|
|
1331
|
+
visualStyle: (_M = (_L = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _L : readString(env, "UI_VISUAL_STYLE")) != null ? _M : "glass",
|
|
1332
|
+
borderRadius: (_O = (_N = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _N : readString(env, "UI_BORDER_RADIUS")) != null ? _O : "xl"
|
|
1491
1333
|
},
|
|
1492
1334
|
rag: {
|
|
1493
1335
|
topK: readNumber(env, "RAG_TOP_K", 5),
|
|
@@ -1563,7 +1405,7 @@ var ConfigValidator = class {
|
|
|
1563
1405
|
errors.push({
|
|
1564
1406
|
field: "embedding",
|
|
1565
1407
|
message: "Embedding config is required when using Anthropic LLM",
|
|
1566
|
-
suggestion: 'Provide embedding config with provider (e.g., "openai")',
|
|
1408
|
+
suggestion: 'Provide embedding config with provider (e.g., "openai" or "ollama")',
|
|
1567
1409
|
severity: "error"
|
|
1568
1410
|
});
|
|
1569
1411
|
}
|
|
@@ -1625,6 +1467,10 @@ var ConfigValidator = class {
|
|
|
1625
1467
|
}
|
|
1626
1468
|
return errors;
|
|
1627
1469
|
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Pinecone — only needs apiKey (environment was removed in SDK v7+).
|
|
1472
|
+
* Options key: { apiKey: string }
|
|
1473
|
+
*/
|
|
1628
1474
|
static validatePineconeConfig(config) {
|
|
1629
1475
|
const errors = [];
|
|
1630
1476
|
const opts = config.options;
|
|
@@ -1636,16 +1482,12 @@ var ConfigValidator = class {
|
|
|
1636
1482
|
severity: "error"
|
|
1637
1483
|
});
|
|
1638
1484
|
}
|
|
1639
|
-
if (!opts.environment) {
|
|
1640
|
-
errors.push({
|
|
1641
|
-
field: "vectorDb.options.environment",
|
|
1642
|
-
message: "Pinecone environment is required",
|
|
1643
|
-
suggestion: 'Set PINECONE_ENVIRONMENT environment variable (e.g., "gcp-starter")',
|
|
1644
|
-
severity: "error"
|
|
1645
|
-
});
|
|
1646
|
-
}
|
|
1647
1485
|
return errors;
|
|
1648
1486
|
}
|
|
1487
|
+
/**
|
|
1488
|
+
* PostgreSQL / pgvector — needs a connection string.
|
|
1489
|
+
* Options key: { connectionString: string }
|
|
1490
|
+
*/
|
|
1649
1491
|
static validatePostgresConfig(config) {
|
|
1650
1492
|
const errors = [];
|
|
1651
1493
|
const opts = config.options;
|
|
@@ -1659,6 +1501,10 @@ var ConfigValidator = class {
|
|
|
1659
1501
|
}
|
|
1660
1502
|
return errors;
|
|
1661
1503
|
}
|
|
1504
|
+
/**
|
|
1505
|
+
* MongoDB — needs uri, database, and collection.
|
|
1506
|
+
* Options keys: { uri: string, database: string, collection: string }
|
|
1507
|
+
*/
|
|
1662
1508
|
static validateMongoDBConfig(config) {
|
|
1663
1509
|
const errors = [];
|
|
1664
1510
|
const opts = config.options;
|
|
@@ -1688,27 +1534,30 @@ var ConfigValidator = class {
|
|
|
1688
1534
|
}
|
|
1689
1535
|
return errors;
|
|
1690
1536
|
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Milvus — accepts baseUrl OR uri (preferred) OR host+port.
|
|
1539
|
+
* MilvusProvider reads opts.baseUrl ?? opts.uri.
|
|
1540
|
+
* Options keys: { baseUrl?: string, uri?: string, host?: string, port?: number }
|
|
1541
|
+
*/
|
|
1691
1542
|
static validateMilvusConfig(config) {
|
|
1692
1543
|
const errors = [];
|
|
1693
1544
|
const opts = config.options;
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
message: "Milvus host is required",
|
|
1698
|
-
suggestion: "Set MILVUS_HOST environment variable",
|
|
1699
|
-
severity: "error"
|
|
1700
|
-
});
|
|
1701
|
-
}
|
|
1702
|
-
if (!opts.port) {
|
|
1545
|
+
const hasBaseUrl = Boolean(opts.baseUrl || opts.uri);
|
|
1546
|
+
const hasHostPort = Boolean(opts.host && opts.port);
|
|
1547
|
+
if (!hasBaseUrl && !hasHostPort) {
|
|
1703
1548
|
errors.push({
|
|
1704
|
-
field: "vectorDb.options.
|
|
1705
|
-
message:
|
|
1706
|
-
suggestion: "Set
|
|
1549
|
+
field: "vectorDb.options.baseUrl",
|
|
1550
|
+
message: 'Milvus connection is required: provide baseUrl (e.g., "http://localhost:19530") or host + port',
|
|
1551
|
+
suggestion: "Set MILVUS_URL environment variable",
|
|
1707
1552
|
severity: "error"
|
|
1708
1553
|
});
|
|
1709
1554
|
}
|
|
1710
1555
|
return errors;
|
|
1711
1556
|
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Qdrant — needs baseUrl (or url alias).
|
|
1559
|
+
* Options keys: { baseUrl: string, apiKey?: string }
|
|
1560
|
+
*/
|
|
1712
1561
|
static validateQdrantConfig(config) {
|
|
1713
1562
|
const errors = [];
|
|
1714
1563
|
const opts = config.options;
|
|
@@ -1722,38 +1571,55 @@ var ConfigValidator = class {
|
|
|
1722
1571
|
}
|
|
1723
1572
|
return errors;
|
|
1724
1573
|
}
|
|
1574
|
+
/**
|
|
1575
|
+
* ChromaDB — accepts baseUrl OR host.
|
|
1576
|
+
* ChromaDBProvider reads opts.baseUrl.
|
|
1577
|
+
* Options keys: { baseUrl?: string, host?: string, port?: number }
|
|
1578
|
+
*/
|
|
1725
1579
|
static validateChromaDBConfig(config) {
|
|
1726
1580
|
const errors = [];
|
|
1727
1581
|
const opts = config.options;
|
|
1728
|
-
if (!opts.
|
|
1582
|
+
if (!opts.baseUrl && !opts.host) {
|
|
1729
1583
|
errors.push({
|
|
1730
|
-
field: "vectorDb.options.
|
|
1731
|
-
message:
|
|
1732
|
-
suggestion: "Set
|
|
1584
|
+
field: "vectorDb.options.baseUrl",
|
|
1585
|
+
message: 'ChromaDB connection is required: provide baseUrl (e.g., "http://localhost:8000") or host',
|
|
1586
|
+
suggestion: "Set CHROMADB_URL environment variable",
|
|
1733
1587
|
severity: "error"
|
|
1734
1588
|
});
|
|
1735
1589
|
}
|
|
1736
1590
|
return errors;
|
|
1737
1591
|
}
|
|
1592
|
+
/**
|
|
1593
|
+
* Redis — accepts baseUrl OR url OR host+port.
|
|
1594
|
+
* RedisProvider reads opts.baseUrl.
|
|
1595
|
+
* Options keys: { baseUrl?: string, url?: string, host?: string, port?: number, apiKey?: string }
|
|
1596
|
+
*/
|
|
1738
1597
|
static validateRedisConfig(config) {
|
|
1739
1598
|
const errors = [];
|
|
1740
1599
|
const opts = config.options;
|
|
1741
|
-
|
|
1600
|
+
const hasUrl = Boolean(opts.baseUrl || opts.url);
|
|
1601
|
+
const hasHostPort = Boolean(opts.host && opts.port);
|
|
1602
|
+
if (!hasUrl && !hasHostPort) {
|
|
1742
1603
|
errors.push({
|
|
1743
|
-
field: "vectorDb.options.
|
|
1744
|
-
message: "Redis connection
|
|
1745
|
-
suggestion: "Set REDIS_URL
|
|
1604
|
+
field: "vectorDb.options.baseUrl",
|
|
1605
|
+
message: "Redis connection is required: provide baseUrl/url or host + port",
|
|
1606
|
+
suggestion: "Set REDIS_URL environment variable",
|
|
1746
1607
|
severity: "error"
|
|
1747
1608
|
});
|
|
1748
1609
|
}
|
|
1749
1610
|
return errors;
|
|
1750
1611
|
}
|
|
1612
|
+
/**
|
|
1613
|
+
* Weaviate — accepts baseUrl OR url.
|
|
1614
|
+
* WeaviateProvider reads opts.baseUrl.
|
|
1615
|
+
* Options keys: { baseUrl?: string, url?: string, apiKey?: string }
|
|
1616
|
+
*/
|
|
1751
1617
|
static validateWeaviateConfig(config) {
|
|
1752
1618
|
const errors = [];
|
|
1753
1619
|
const opts = config.options;
|
|
1754
|
-
if (!opts.url) {
|
|
1620
|
+
if (!opts.baseUrl && !opts.url) {
|
|
1755
1621
|
errors.push({
|
|
1756
|
-
field: "vectorDb.options.
|
|
1622
|
+
field: "vectorDb.options.baseUrl",
|
|
1757
1623
|
message: "Weaviate instance URL is required",
|
|
1758
1624
|
suggestion: "Set WEAVIATE_URL environment variable",
|
|
1759
1625
|
severity: "error"
|
|
@@ -1761,6 +1627,10 @@ var ConfigValidator = class {
|
|
|
1761
1627
|
}
|
|
1762
1628
|
return errors;
|
|
1763
1629
|
}
|
|
1630
|
+
/**
|
|
1631
|
+
* Universal REST / custom REST adapter.
|
|
1632
|
+
* Options key: { baseUrl: string }
|
|
1633
|
+
*/
|
|
1764
1634
|
static validateRestConfig(config) {
|
|
1765
1635
|
const errors = [];
|
|
1766
1636
|
const opts = config.options;
|
|
@@ -1868,7 +1738,7 @@ var ConfigValidator = class {
|
|
|
1868
1738
|
errors.push({
|
|
1869
1739
|
field: "embedding.model",
|
|
1870
1740
|
message: "Embedding model name is required",
|
|
1871
|
-
suggestion: 'e.g., "text-embedding-3-small" for OpenAI',
|
|
1741
|
+
suggestion: 'e.g., "text-embedding-3-small" for OpenAI, "nomic-embed-text" for Ollama',
|
|
1872
1742
|
severity: "error"
|
|
1873
1743
|
});
|
|
1874
1744
|
}
|
|
@@ -1883,7 +1753,7 @@ var ConfigValidator = class {
|
|
|
1883
1753
|
if (config.provider === "ollama" && !config.baseUrl) {
|
|
1884
1754
|
errors.push({
|
|
1885
1755
|
field: "embedding.baseUrl",
|
|
1886
|
-
message: "Ollama base URL is required",
|
|
1756
|
+
message: "Ollama base URL is required for embedding",
|
|
1887
1757
|
suggestion: "Set EMBEDDING_BASE_URL environment variable",
|
|
1888
1758
|
severity: "error"
|
|
1889
1759
|
});
|
|
@@ -1972,9 +1842,11 @@ var ConfigValidator = class {
|
|
|
1972
1842
|
return errors;
|
|
1973
1843
|
}
|
|
1974
1844
|
static isValidCSSColor(color) {
|
|
1975
|
-
const
|
|
1976
|
-
|
|
1977
|
-
|
|
1845
|
+
const hexRegex = /^#([0-9a-f]{3}){1,2}$/i;
|
|
1846
|
+
const rgbRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/i;
|
|
1847
|
+
const hslRegex = /^hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*(\d+(?:\.\d+)?))?\)$/i;
|
|
1848
|
+
const namedColors = ["red", "blue", "green", "black", "white", "transparent"];
|
|
1849
|
+
return hexRegex.test(color) || rgbRegex.test(color) || hslRegex.test(color) || namedColors.includes(color.toLowerCase());
|
|
1978
1850
|
}
|
|
1979
1851
|
/**
|
|
1980
1852
|
* Throws if there are error-level validation issues.
|
|
@@ -2058,17 +1930,433 @@ var DocumentChunker = class {
|
|
|
2058
1930
|
}
|
|
2059
1931
|
};
|
|
2060
1932
|
|
|
1933
|
+
// src/llm/providers/OpenAIProvider.ts
|
|
1934
|
+
var import_openai = __toESM(require("openai"));
|
|
1935
|
+
var OpenAIProvider = class {
|
|
1936
|
+
constructor(llmConfig, embeddingConfig) {
|
|
1937
|
+
if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
|
|
1938
|
+
this.client = new import_openai.default({ apiKey: llmConfig.apiKey });
|
|
1939
|
+
this.llmConfig = llmConfig;
|
|
1940
|
+
this.embeddingConfig = embeddingConfig;
|
|
1941
|
+
}
|
|
1942
|
+
async chat(messages, context, options) {
|
|
1943
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1944
|
+
const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
1945
|
+
|
|
1946
|
+
Context:
|
|
1947
|
+
${context}`;
|
|
1948
|
+
const systemMessage = {
|
|
1949
|
+
role: "system",
|
|
1950
|
+
content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
|
|
1951
|
+
|
|
1952
|
+
Context:
|
|
1953
|
+
${context}`
|
|
1954
|
+
};
|
|
1955
|
+
const formattedMessages = [
|
|
1956
|
+
systemMessage,
|
|
1957
|
+
...messages.map((m) => ({
|
|
1958
|
+
role: m.role,
|
|
1959
|
+
content: m.content
|
|
1960
|
+
}))
|
|
1961
|
+
];
|
|
1962
|
+
const completion = await this.client.chat.completions.create({
|
|
1963
|
+
model: this.llmConfig.model,
|
|
1964
|
+
messages: formattedMessages,
|
|
1965
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
1966
|
+
temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
|
|
1967
|
+
stop: options == null ? void 0 : options.stop
|
|
1968
|
+
});
|
|
1969
|
+
return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
|
|
1970
|
+
}
|
|
1971
|
+
async embed(text, options) {
|
|
1972
|
+
const results = await this.batchEmbed([text], options);
|
|
1973
|
+
return results[0];
|
|
1974
|
+
}
|
|
1975
|
+
async batchEmbed(texts, options) {
|
|
1976
|
+
var _a, _b, _c, _d, _e;
|
|
1977
|
+
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";
|
|
1978
|
+
const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
|
|
1979
|
+
const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
|
|
1980
|
+
const response = await client.embeddings.create({ model, input: texts });
|
|
1981
|
+
return response.data.map((d) => d.embedding);
|
|
1982
|
+
}
|
|
1983
|
+
async ping() {
|
|
1984
|
+
try {
|
|
1985
|
+
await this.client.models.list();
|
|
1986
|
+
return true;
|
|
1987
|
+
} catch (err) {
|
|
1988
|
+
console.error("[OpenAIProvider] Ping failed:", err);
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
};
|
|
1993
|
+
|
|
1994
|
+
// src/llm/providers/AnthropicProvider.ts
|
|
1995
|
+
var import_sdk = __toESM(require("@anthropic-ai/sdk"));
|
|
1996
|
+
var AnthropicProvider = class {
|
|
1997
|
+
constructor(llmConfig, embeddingConfig) {
|
|
1998
|
+
if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
|
|
1999
|
+
this.client = new import_sdk.default({ apiKey: llmConfig.apiKey });
|
|
2000
|
+
this.llmConfig = llmConfig;
|
|
2001
|
+
this.embeddingConfig = embeddingConfig;
|
|
2002
|
+
}
|
|
2003
|
+
async chat(messages, context, options) {
|
|
2004
|
+
var _a, _b, _c;
|
|
2005
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
|
|
2006
|
+
|
|
2007
|
+
Context:
|
|
2008
|
+
${context}`;
|
|
2009
|
+
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2010
|
+
|
|
2011
|
+
Context:
|
|
2012
|
+
${context}`;
|
|
2013
|
+
const anthropicMessages = messages.map((m) => ({
|
|
2014
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
2015
|
+
content: m.content
|
|
2016
|
+
}));
|
|
2017
|
+
const response = await this.client.messages.create({
|
|
2018
|
+
model: this.llmConfig.model,
|
|
2019
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
2020
|
+
system,
|
|
2021
|
+
messages: anthropicMessages
|
|
2022
|
+
});
|
|
2023
|
+
const block = response.content[0];
|
|
2024
|
+
return block.type === "text" ? block.text : "";
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Anthropic does not offer an embedding API.
|
|
2028
|
+
* This method throws with a clear error so developers know to configure
|
|
2029
|
+
* a separate embedding provider (OpenAI or Ollama).
|
|
2030
|
+
*/
|
|
2031
|
+
async embed(text, options) {
|
|
2032
|
+
void text;
|
|
2033
|
+
void options;
|
|
2034
|
+
throw new Error(
|
|
2035
|
+
'[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
async batchEmbed(texts, options) {
|
|
2039
|
+
void texts;
|
|
2040
|
+
void options;
|
|
2041
|
+
throw new Error(
|
|
2042
|
+
"[AnthropicProvider] Anthropic does not provide an embedding API."
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
async ping() {
|
|
2046
|
+
try {
|
|
2047
|
+
await this.client.models.list();
|
|
2048
|
+
return true;
|
|
2049
|
+
} catch (err) {
|
|
2050
|
+
console.error("[AnthropicProvider] Ping failed:", err);
|
|
2051
|
+
return false;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
|
|
2056
|
+
// src/llm/providers/OllamaProvider.ts
|
|
2057
|
+
var import_axios = __toESM(require("axios"));
|
|
2058
|
+
var OllamaProvider = class {
|
|
2059
|
+
constructor(llmConfig, embeddingConfig) {
|
|
2060
|
+
var _a;
|
|
2061
|
+
const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
|
|
2062
|
+
this.http = import_axios.default.create({ baseURL, timeout: 12e4 });
|
|
2063
|
+
this.llmConfig = llmConfig;
|
|
2064
|
+
this.embeddingConfig = embeddingConfig;
|
|
2065
|
+
}
|
|
2066
|
+
async chat(messages, context, options) {
|
|
2067
|
+
var _a, _b, _c, _d, _e;
|
|
2068
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
|
|
2069
|
+
|
|
2070
|
+
Context:
|
|
2071
|
+
${context}`;
|
|
2072
|
+
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2073
|
+
|
|
2074
|
+
Context:
|
|
2075
|
+
${context}`;
|
|
2076
|
+
const { data } = await this.http.post("/api/chat", {
|
|
2077
|
+
model: this.llmConfig.model,
|
|
2078
|
+
stream: false,
|
|
2079
|
+
options: {
|
|
2080
|
+
temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
|
|
2081
|
+
num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
|
|
2082
|
+
},
|
|
2083
|
+
messages: [
|
|
2084
|
+
{ role: "system", content: system },
|
|
2085
|
+
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
2086
|
+
]
|
|
2087
|
+
});
|
|
2088
|
+
return data.message.content;
|
|
2089
|
+
}
|
|
2090
|
+
async embed(text, options) {
|
|
2091
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2092
|
+
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";
|
|
2093
|
+
const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
|
|
2094
|
+
const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
|
|
2095
|
+
const { data } = await client.post("/api/embeddings", {
|
|
2096
|
+
model,
|
|
2097
|
+
prompt: text
|
|
2098
|
+
});
|
|
2099
|
+
return data.embedding;
|
|
2100
|
+
}
|
|
2101
|
+
async batchEmbed(texts, options) {
|
|
2102
|
+
const vectors = [];
|
|
2103
|
+
for (const text of texts) {
|
|
2104
|
+
vectors.push(await this.embed(text, options));
|
|
2105
|
+
}
|
|
2106
|
+
return vectors;
|
|
2107
|
+
}
|
|
2108
|
+
async ping() {
|
|
2109
|
+
try {
|
|
2110
|
+
await this.http.get("/api/tags");
|
|
2111
|
+
return true;
|
|
2112
|
+
} catch (err) {
|
|
2113
|
+
console.error("[OllamaProvider] Ping failed:", err);
|
|
2114
|
+
return false;
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
|
|
2119
|
+
// src/llm/providers/UniversalLLMAdapter.ts
|
|
2120
|
+
var import_axios2 = __toESM(require("axios"));
|
|
2121
|
+
init_templateUtils();
|
|
2122
|
+
|
|
2123
|
+
// src/config/UniversalProfiles.ts
|
|
2124
|
+
var OPENAI_BASE = {
|
|
2125
|
+
chatPath: "/chat/completions",
|
|
2126
|
+
embedPath: "/embeddings",
|
|
2127
|
+
responseExtractPath: "choices[0].message.content",
|
|
2128
|
+
embedExtractPath: "data[0].embedding",
|
|
2129
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
|
|
2130
|
+
};
|
|
2131
|
+
var LLM_PROFILES = {
|
|
2132
|
+
"openai-compatible": OPENAI_BASE,
|
|
2133
|
+
"litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
2134
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
|
|
2135
|
+
}),
|
|
2136
|
+
"anthropic-claude": {
|
|
2137
|
+
chatPath: "/v1/messages",
|
|
2138
|
+
responseExtractPath: "content[0].text",
|
|
2139
|
+
headers: { "anthropic-version": "2023-06-01" },
|
|
2140
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
|
|
2141
|
+
},
|
|
2142
|
+
"google-gemini": {
|
|
2143
|
+
chatPath: "/v1beta/models/{{model}}:generateContent",
|
|
2144
|
+
responseExtractPath: "candidates[0].content.parts[0].text",
|
|
2145
|
+
chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
|
|
2146
|
+
},
|
|
2147
|
+
"github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
2148
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
|
|
2149
|
+
}),
|
|
2150
|
+
"ollama-standard": {
|
|
2151
|
+
chatPath: "/api/chat",
|
|
2152
|
+
embedPath: "/api/embeddings",
|
|
2153
|
+
responseExtractPath: "message.content",
|
|
2154
|
+
embedExtractPath: "embedding",
|
|
2155
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
|
|
2156
|
+
embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
var VECTOR_PROFILES = {
|
|
2160
|
+
"pinecone-rest": {
|
|
2161
|
+
queryPath: "/query",
|
|
2162
|
+
upsertPath: "/vectors/upsert",
|
|
2163
|
+
responseExtractPath: "matches",
|
|
2164
|
+
idPath: "id",
|
|
2165
|
+
scorePath: "score",
|
|
2166
|
+
contentPath: "metadata.content",
|
|
2167
|
+
metadataPath: "metadata",
|
|
2168
|
+
queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
|
|
2169
|
+
},
|
|
2170
|
+
"mongodb-atlas": {
|
|
2171
|
+
queryPath: "/action/aggregate",
|
|
2172
|
+
responseExtractPath: "documents",
|
|
2173
|
+
idPath: "_id",
|
|
2174
|
+
scorePath: "score",
|
|
2175
|
+
contentPath: "content",
|
|
2176
|
+
metadataPath: "metadata",
|
|
2177
|
+
queryPayloadTemplate: '{"collection":"{{index}}","database":"ai_db","dataSource":"Cluster0","pipeline":[{"$vectorSearch":{"index":"vector_index","path":"embedding","queryVector":{{vector}},"numCandidates":100,"limit":{{topK}}}},{"$project":{"_id":1,"content":1,"metadata":1,"score":{"$meta":"vectorSearchScore"}}}]}'
|
|
2178
|
+
},
|
|
2179
|
+
"chromadb": {
|
|
2180
|
+
queryPath: "/api/v1/collections/{{index}}/query",
|
|
2181
|
+
upsertPath: "/api/v1/collections/{{index}}/add",
|
|
2182
|
+
responseExtractPath: "matches",
|
|
2183
|
+
idPath: "id",
|
|
2184
|
+
scorePath: "distance",
|
|
2185
|
+
contentPath: "document",
|
|
2186
|
+
metadataPath: "metadata"
|
|
2187
|
+
},
|
|
2188
|
+
"qdrant": {
|
|
2189
|
+
queryPath: "/collections/{{index}}/points/search",
|
|
2190
|
+
upsertPath: "/collections/{{index}}/points",
|
|
2191
|
+
responseExtractPath: "result",
|
|
2192
|
+
idPath: "id",
|
|
2193
|
+
scorePath: "score",
|
|
2194
|
+
contentPath: "payload.content",
|
|
2195
|
+
metadataPath: "payload"
|
|
2196
|
+
}
|
|
2197
|
+
};
|
|
2198
|
+
|
|
2199
|
+
// src/llm/providers/UniversalLLMAdapter.ts
|
|
2200
|
+
var UniversalLLMAdapter = class {
|
|
2201
|
+
constructor(config) {
|
|
2202
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2203
|
+
this.model = config.model;
|
|
2204
|
+
const llmConfig = config;
|
|
2205
|
+
const options = (_a = llmConfig.options) != null ? _a : {};
|
|
2206
|
+
let profile = {};
|
|
2207
|
+
if (typeof options.profile === "string") {
|
|
2208
|
+
profile = LLM_PROFILES[options.profile] || {};
|
|
2209
|
+
} else if (typeof options.profile === "object" && options.profile !== null) {
|
|
2210
|
+
profile = options.profile;
|
|
2211
|
+
}
|
|
2212
|
+
this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
|
|
2213
|
+
this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
|
|
2214
|
+
this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
|
|
2215
|
+
this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
|
|
2216
|
+
const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
|
|
2217
|
+
if (!baseUrl) {
|
|
2218
|
+
throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
|
|
2219
|
+
}
|
|
2220
|
+
this.http = import_axios2.default.create({
|
|
2221
|
+
baseURL: baseUrl,
|
|
2222
|
+
headers: __spreadValues(__spreadValues({
|
|
2223
|
+
"Content-Type": "application/json"
|
|
2224
|
+
}, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
|
|
2225
|
+
timeout: (_g = this.opts.timeout) != null ? _g : 6e4
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2228
|
+
async chat(messages, context) {
|
|
2229
|
+
var _a, _b;
|
|
2230
|
+
const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
|
|
2231
|
+
const formattedMessages = [
|
|
2232
|
+
{ role: "system", content: `${this.systemPrompt}
|
|
2233
|
+
|
|
2234
|
+
Context:
|
|
2235
|
+
${context != null ? context : "None"}` },
|
|
2236
|
+
...messages
|
|
2237
|
+
];
|
|
2238
|
+
let payload;
|
|
2239
|
+
if (this.opts.chatPayloadTemplate) {
|
|
2240
|
+
payload = buildPayload(this.opts.chatPayloadTemplate, {
|
|
2241
|
+
model: this.model,
|
|
2242
|
+
messages: formattedMessages,
|
|
2243
|
+
maxTokens: this.maxTokens,
|
|
2244
|
+
temperature: this.temperature
|
|
2245
|
+
});
|
|
2246
|
+
} else {
|
|
2247
|
+
payload = {
|
|
2248
|
+
model: this.model,
|
|
2249
|
+
messages: formattedMessages,
|
|
2250
|
+
max_tokens: this.maxTokens,
|
|
2251
|
+
temperature: this.temperature
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
const { data } = await this.http.post(path, payload);
|
|
2255
|
+
const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
|
|
2256
|
+
const result = resolvePath(data, extractPath);
|
|
2257
|
+
if (result === void 0) {
|
|
2258
|
+
throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
|
|
2259
|
+
}
|
|
2260
|
+
return String(result);
|
|
2261
|
+
}
|
|
2262
|
+
async embed(text) {
|
|
2263
|
+
var _a, _b;
|
|
2264
|
+
const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
|
|
2265
|
+
let payload;
|
|
2266
|
+
if (this.opts.embedPayloadTemplate) {
|
|
2267
|
+
payload = buildPayload(this.opts.embedPayloadTemplate, {
|
|
2268
|
+
model: this.model,
|
|
2269
|
+
input: text
|
|
2270
|
+
});
|
|
2271
|
+
} else {
|
|
2272
|
+
payload = {
|
|
2273
|
+
model: this.model,
|
|
2274
|
+
input: text
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2277
|
+
const { data } = await this.http.post(path, payload);
|
|
2278
|
+
const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
|
|
2279
|
+
const vector = resolvePath(data, extractPath);
|
|
2280
|
+
if (!Array.isArray(vector)) {
|
|
2281
|
+
throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
|
|
2282
|
+
}
|
|
2283
|
+
return vector;
|
|
2284
|
+
}
|
|
2285
|
+
async batchEmbed(texts) {
|
|
2286
|
+
const vectors = [];
|
|
2287
|
+
for (const text of texts) {
|
|
2288
|
+
vectors.push(await this.embed(text));
|
|
2289
|
+
}
|
|
2290
|
+
return vectors;
|
|
2291
|
+
}
|
|
2292
|
+
async ping() {
|
|
2293
|
+
try {
|
|
2294
|
+
if (this.opts.pingPath) {
|
|
2295
|
+
await this.http.get(this.opts.pingPath);
|
|
2296
|
+
}
|
|
2297
|
+
return true;
|
|
2298
|
+
} catch (err) {
|
|
2299
|
+
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
2300
|
+
return false;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
|
|
2305
|
+
// src/llm/LLMFactory.ts
|
|
2306
|
+
var LLMFactory = class _LLMFactory {
|
|
2307
|
+
static create(llmConfig, embeddingConfig) {
|
|
2308
|
+
var _a;
|
|
2309
|
+
switch (llmConfig.provider) {
|
|
2310
|
+
case "openai":
|
|
2311
|
+
return new OpenAIProvider(llmConfig, embeddingConfig);
|
|
2312
|
+
case "anthropic":
|
|
2313
|
+
return new AnthropicProvider(llmConfig, embeddingConfig);
|
|
2314
|
+
case "ollama":
|
|
2315
|
+
return new OllamaProvider(llmConfig, embeddingConfig);
|
|
2316
|
+
case "rest":
|
|
2317
|
+
case "universal_rest":
|
|
2318
|
+
case "custom":
|
|
2319
|
+
return new UniversalLLMAdapter(llmConfig);
|
|
2320
|
+
default:
|
|
2321
|
+
if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
|
|
2322
|
+
return new UniversalLLMAdapter(llmConfig);
|
|
2323
|
+
}
|
|
2324
|
+
throw new Error(
|
|
2325
|
+
`[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
/**
|
|
2330
|
+
* Creates a dedicated embedding-only provider.
|
|
2331
|
+
* Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
|
|
2332
|
+
*/
|
|
2333
|
+
static createEmbeddingProvider(embeddingConfig) {
|
|
2334
|
+
const fakeLLMConfig = {
|
|
2335
|
+
provider: embeddingConfig.provider,
|
|
2336
|
+
model: embeddingConfig.model,
|
|
2337
|
+
apiKey: embeddingConfig.apiKey,
|
|
2338
|
+
baseUrl: embeddingConfig.baseUrl,
|
|
2339
|
+
options: embeddingConfig.options
|
|
2340
|
+
};
|
|
2341
|
+
return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
|
|
2342
|
+
}
|
|
2343
|
+
};
|
|
2344
|
+
|
|
2061
2345
|
// src/core/ProviderRegistry.ts
|
|
2062
|
-
init_LLMFactory();
|
|
2063
2346
|
var ProviderRegistry = class {
|
|
2064
2347
|
/**
|
|
2065
|
-
* Register a custom vector provider.
|
|
2348
|
+
* Register a custom vector provider class by name.
|
|
2349
|
+
* The name must match the provider value used in VectorDBConfig.provider.
|
|
2350
|
+
*
|
|
2351
|
+
* @example
|
|
2352
|
+
* ProviderRegistry.registerVectorProvider('my-db', MyCustomProvider);
|
|
2066
2353
|
*/
|
|
2067
2354
|
static registerVectorProvider(name, providerClass) {
|
|
2068
2355
|
this.vectorProviders[name] = providerClass;
|
|
2069
2356
|
}
|
|
2070
2357
|
/**
|
|
2071
2358
|
* Creates a vector database provider based on the configuration.
|
|
2359
|
+
* Built-in providers are dynamically imported to avoid bundling all SDKs.
|
|
2072
2360
|
*/
|
|
2073
2361
|
static async createVectorProvider(config) {
|
|
2074
2362
|
const { provider } = config;
|
|
@@ -2076,33 +2364,48 @@ var ProviderRegistry = class {
|
|
|
2076
2364
|
return new this.vectorProviders[provider](config);
|
|
2077
2365
|
}
|
|
2078
2366
|
switch (provider) {
|
|
2079
|
-
case "pinecone":
|
|
2367
|
+
case "pinecone": {
|
|
2080
2368
|
const { PineconeProvider: PineconeProvider2 } = await Promise.resolve().then(() => (init_PineconeProvider(), PineconeProvider_exports));
|
|
2081
2369
|
return new PineconeProvider2(config);
|
|
2370
|
+
}
|
|
2082
2371
|
case "pgvector":
|
|
2083
|
-
case "postgresql":
|
|
2372
|
+
case "postgresql": {
|
|
2084
2373
|
const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
|
|
2085
2374
|
return new PostgreSQLProvider2(config);
|
|
2086
|
-
|
|
2375
|
+
}
|
|
2376
|
+
case "mongodb": {
|
|
2087
2377
|
const { MongoDBProvider: MongoDBProvider2 } = await Promise.resolve().then(() => (init_MongoDBProvider(), MongoDBProvider_exports));
|
|
2088
2378
|
return new MongoDBProvider2(config);
|
|
2089
|
-
|
|
2379
|
+
}
|
|
2380
|
+
case "milvus": {
|
|
2090
2381
|
const { MilvusProvider: MilvusProvider2 } = await Promise.resolve().then(() => (init_MilvusProvider(), MilvusProvider_exports));
|
|
2091
2382
|
return new MilvusProvider2(config);
|
|
2092
|
-
|
|
2383
|
+
}
|
|
2384
|
+
case "qdrant": {
|
|
2093
2385
|
const { QdrantProvider: QdrantProvider2 } = await Promise.resolve().then(() => (init_QdrantProvider(), QdrantProvider_exports));
|
|
2094
2386
|
return new QdrantProvider2(config);
|
|
2095
|
-
|
|
2387
|
+
}
|
|
2388
|
+
case "chromadb": {
|
|
2096
2389
|
const { ChromaDBProvider: ChromaDBProvider2 } = await Promise.resolve().then(() => (init_ChromaDBProvider(), ChromaDBProvider_exports));
|
|
2097
2390
|
return new ChromaDBProvider2(config);
|
|
2098
|
-
|
|
2391
|
+
}
|
|
2392
|
+
case "redis": {
|
|
2099
2393
|
const { RedisProvider: RedisProvider2 } = await Promise.resolve().then(() => (init_RedisProvider(), RedisProvider_exports));
|
|
2100
2394
|
return new RedisProvider2(config);
|
|
2101
|
-
|
|
2395
|
+
}
|
|
2396
|
+
case "weaviate": {
|
|
2102
2397
|
const { WeaviateProvider: WeaviateProvider2 } = await Promise.resolve().then(() => (init_WeaviateProvider(), WeaviateProvider_exports));
|
|
2103
2398
|
return new WeaviateProvider2(config);
|
|
2399
|
+
}
|
|
2400
|
+
case "universal_rest":
|
|
2401
|
+
case "rest": {
|
|
2402
|
+
const { UniversalVectorProvider: UniversalVectorProvider2 } = await Promise.resolve().then(() => (init_UniversalVectorProvider(), UniversalVectorProvider_exports));
|
|
2403
|
+
return new UniversalVectorProvider2(config);
|
|
2404
|
+
}
|
|
2104
2405
|
default:
|
|
2105
|
-
throw new Error(
|
|
2406
|
+
throw new Error(
|
|
2407
|
+
`[ProviderRegistry] Unsupported vector provider: "${provider}". Built-in providers: pinecone | pgvector | postgresql | mongodb | milvus | qdrant | chromadb | redis | weaviate | universal_rest. For custom providers, call ProviderRegistry.registerVectorProvider("${provider}", YourClass).`
|
|
2408
|
+
);
|
|
2106
2409
|
}
|
|
2107
2410
|
}
|
|
2108
2411
|
/**
|
|
@@ -2338,6 +2641,89 @@ ${errorMessages}`
|
|
|
2338
2641
|
}
|
|
2339
2642
|
};
|
|
2340
2643
|
|
|
2644
|
+
// src/config/EmbeddingStrategy.ts
|
|
2645
|
+
var EmbeddingStrategy = /* @__PURE__ */ ((EmbeddingStrategy2) => {
|
|
2646
|
+
EmbeddingStrategy2["INTEGRATED"] = "integrated";
|
|
2647
|
+
EmbeddingStrategy2["SEPARATE"] = "separate";
|
|
2648
|
+
EmbeddingStrategy2["EXTERNAL"] = "external";
|
|
2649
|
+
return EmbeddingStrategy2;
|
|
2650
|
+
})(EmbeddingStrategy || {});
|
|
2651
|
+
var EmbeddingStrategyResolver = class {
|
|
2652
|
+
/**
|
|
2653
|
+
* Determine strategy based on LLM and embedding configs
|
|
2654
|
+
*/
|
|
2655
|
+
static determineStrategy(llmConfig, embeddingConfig) {
|
|
2656
|
+
if (!embeddingConfig) {
|
|
2657
|
+
return this.supportsEmbedding(llmConfig.provider) ? "integrated" /* INTEGRATED */ : "separate" /* SEPARATE */;
|
|
2658
|
+
}
|
|
2659
|
+
if (embeddingConfig.provider !== llmConfig.provider) {
|
|
2660
|
+
return "separate" /* SEPARATE */;
|
|
2661
|
+
}
|
|
2662
|
+
if (embeddingConfig.model !== llmConfig.model) {
|
|
2663
|
+
return "external" /* EXTERNAL */;
|
|
2664
|
+
}
|
|
2665
|
+
return "integrated" /* INTEGRATED */;
|
|
2666
|
+
}
|
|
2667
|
+
/**
|
|
2668
|
+
* Resolve and initialize providers according to the strategy
|
|
2669
|
+
*/
|
|
2670
|
+
static async resolve(llmConfig, embeddingConfig) {
|
|
2671
|
+
const strategy = this.determineStrategy(llmConfig, embeddingConfig);
|
|
2672
|
+
const llmProvider = LLMFactory.create(llmConfig, embeddingConfig);
|
|
2673
|
+
let embeddingProvider;
|
|
2674
|
+
switch (strategy) {
|
|
2675
|
+
case "integrated" /* INTEGRATED */:
|
|
2676
|
+
embeddingProvider = llmProvider;
|
|
2677
|
+
break;
|
|
2678
|
+
case "separate" /* SEPARATE */:
|
|
2679
|
+
if (!embeddingConfig) {
|
|
2680
|
+
throw new Error(
|
|
2681
|
+
"[EmbeddingStrategyResolver] SEPARATE strategy requires embeddingConfig"
|
|
2682
|
+
);
|
|
2683
|
+
}
|
|
2684
|
+
embeddingProvider = LLMFactory.createEmbeddingProvider(embeddingConfig);
|
|
2685
|
+
break;
|
|
2686
|
+
case "external" /* EXTERNAL */:
|
|
2687
|
+
if (!embeddingConfig) {
|
|
2688
|
+
throw new Error(
|
|
2689
|
+
"[EmbeddingStrategyResolver] EXTERNAL strategy requires embeddingConfig"
|
|
2690
|
+
);
|
|
2691
|
+
}
|
|
2692
|
+
embeddingProvider = LLMFactory.createEmbeddingProvider(embeddingConfig);
|
|
2693
|
+
break;
|
|
2694
|
+
default:
|
|
2695
|
+
throw new Error(`[EmbeddingStrategyResolver] Unknown strategy: ${strategy}`);
|
|
2696
|
+
}
|
|
2697
|
+
return {
|
|
2698
|
+
strategy,
|
|
2699
|
+
embeddingProvider,
|
|
2700
|
+
llmProvider
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
/**
|
|
2704
|
+
* Check if an LLM provider natively supports embeddings
|
|
2705
|
+
*/
|
|
2706
|
+
static supportsEmbedding(provider) {
|
|
2707
|
+
const providersWithEmbedding = ["openai", "ollama", "rest", "universal_rest"];
|
|
2708
|
+
return providersWithEmbedding.includes(provider);
|
|
2709
|
+
}
|
|
2710
|
+
/**
|
|
2711
|
+
* Get a human-readable description of the strategy
|
|
2712
|
+
*/
|
|
2713
|
+
static getDescription(strategy) {
|
|
2714
|
+
switch (strategy) {
|
|
2715
|
+
case "integrated" /* INTEGRATED */:
|
|
2716
|
+
return "Using LLM provider for both chat and embeddings";
|
|
2717
|
+
case "separate" /* SEPARATE */:
|
|
2718
|
+
return "Using separate embedding provider";
|
|
2719
|
+
case "external" /* EXTERNAL */:
|
|
2720
|
+
return "Using external embedding service";
|
|
2721
|
+
default:
|
|
2722
|
+
return "Unknown strategy";
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
};
|
|
2726
|
+
|
|
2341
2727
|
// src/core/Pipeline.ts
|
|
2342
2728
|
var Pipeline = class {
|
|
2343
2729
|
constructor(config) {
|
|
@@ -2352,18 +2738,17 @@ var Pipeline = class {
|
|
|
2352
2738
|
async initialize() {
|
|
2353
2739
|
if (this.initialised) return;
|
|
2354
2740
|
this.vectorDB = await ProviderRegistry.createVectorProvider(this.config.vectorDb);
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
}
|
|
2741
|
+
const { llmProvider, embeddingProvider } = await EmbeddingStrategyResolver.resolve(
|
|
2742
|
+
this.config.llm,
|
|
2743
|
+
this.config.embedding
|
|
2744
|
+
);
|
|
2745
|
+
this.llmProvider = llmProvider;
|
|
2746
|
+
this.embeddingProvider = embeddingProvider;
|
|
2362
2747
|
await this.vectorDB.initialize();
|
|
2363
2748
|
this.initialised = true;
|
|
2364
2749
|
}
|
|
2365
2750
|
/**
|
|
2366
|
-
* Ingest documents with automatic chunking, embedding, and batch
|
|
2751
|
+
* Ingest documents with automatic chunking, embedding, and batch upsert.
|
|
2367
2752
|
* Handles retries for transient failures.
|
|
2368
2753
|
*/
|
|
2369
2754
|
async ingest(documents, namespace) {
|
|
@@ -2376,19 +2761,18 @@ var Pipeline = class {
|
|
|
2376
2761
|
docId: doc.docId,
|
|
2377
2762
|
metadata: doc.metadata
|
|
2378
2763
|
});
|
|
2379
|
-
const
|
|
2764
|
+
const embedBatchOptions = {
|
|
2380
2765
|
batchSize: 50,
|
|
2381
|
-
// Embedding batch size
|
|
2382
2766
|
maxRetries: 3,
|
|
2383
2767
|
initialDelayMs: 100
|
|
2384
2768
|
};
|
|
2385
2769
|
const vectors = await BatchProcessor.mapWithRetry(
|
|
2386
2770
|
chunks.map((c) => c.content),
|
|
2387
2771
|
(text) => this.embeddingProvider.embed(text),
|
|
2388
|
-
|
|
2772
|
+
embedBatchOptions
|
|
2389
2773
|
);
|
|
2390
2774
|
if (vectors.length !== chunks.length) {
|
|
2391
|
-
throw new Error(`Embedding
|
|
2775
|
+
throw new Error(`Embedding mismatch: got ${vectors.length} vectors for ${chunks.length} chunks`);
|
|
2392
2776
|
}
|
|
2393
2777
|
const upsertDocs = chunks.map((chunk, i) => ({
|
|
2394
2778
|
id: chunk.id,
|
|
@@ -2415,10 +2799,7 @@ var Pipeline = class {
|
|
|
2415
2799
|
});
|
|
2416
2800
|
} catch (error) {
|
|
2417
2801
|
console.error(`[Pipeline] Failed to ingest document ${doc.docId}:`, error);
|
|
2418
|
-
results.push({
|
|
2419
|
-
docId: doc.docId,
|
|
2420
|
-
chunksIngested: 0
|
|
2421
|
-
});
|
|
2802
|
+
results.push({ docId: doc.docId, chunksIngested: 0 });
|
|
2422
2803
|
}
|
|
2423
2804
|
}
|
|
2424
2805
|
return results;
|
|
@@ -2448,7 +2829,6 @@ ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
|
2448
2829
|
var ProviderHealthCheck = class {
|
|
2449
2830
|
/**
|
|
2450
2831
|
* Validates vector database configuration before initialization.
|
|
2451
|
-
* Performs connectivity checks and verifies required resources exist.
|
|
2452
2832
|
*/
|
|
2453
2833
|
static async checkVectorProvider(config) {
|
|
2454
2834
|
const timestamp = Date.now();
|
|
@@ -2456,7 +2836,6 @@ var ProviderHealthCheck = class {
|
|
|
2456
2836
|
projectId: "health-check",
|
|
2457
2837
|
vectorDb: config,
|
|
2458
2838
|
llm: { provider: "openai", model: "gpt-4o" },
|
|
2459
|
-
// dummy
|
|
2460
2839
|
embedding: { provider: "openai", model: "text-embedding-3-small" }
|
|
2461
2840
|
});
|
|
2462
2841
|
const vectorDbErrors = configErrors.filter((e) => e.field.startsWith("vectorDb"));
|
|
@@ -2526,10 +2905,7 @@ var ProviderHealthCheck = class {
|
|
|
2526
2905
|
return {
|
|
2527
2906
|
healthy: true,
|
|
2528
2907
|
provider: "pinecone",
|
|
2529
|
-
capabilities: {
|
|
2530
|
-
indexes: indexNames.length,
|
|
2531
|
-
targetIndex: config.indexName
|
|
2532
|
-
},
|
|
2908
|
+
capabilities: { indexes: indexNames.length, targetIndex: config.indexName },
|
|
2533
2909
|
timestamp
|
|
2534
2910
|
};
|
|
2535
2911
|
} catch (error) {
|
|
@@ -2548,9 +2924,7 @@ var ProviderHealthCheck = class {
|
|
|
2548
2924
|
const client = new Client({ connectionString: opts.connectionString });
|
|
2549
2925
|
await client.connect();
|
|
2550
2926
|
const result = await client.query(`
|
|
2551
|
-
SELECT EXISTS(
|
|
2552
|
-
SELECT 1 FROM pg_extension WHERE extname = 'vector'
|
|
2553
|
-
);
|
|
2927
|
+
SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'vector');
|
|
2554
2928
|
`);
|
|
2555
2929
|
const hasVector = result.rows[0].exists;
|
|
2556
2930
|
await client.end();
|
|
@@ -2585,7 +2959,7 @@ var ProviderHealthCheck = class {
|
|
|
2585
2959
|
provider: "mongodb",
|
|
2586
2960
|
capabilities: {
|
|
2587
2961
|
collections: collectionNames.length,
|
|
2588
|
-
targetCollection: hasCollection ? opts.collection : "NOT FOUND"
|
|
2962
|
+
targetCollection: hasCollection ? opts.collection : "NOT FOUND (will be created on first insert)"
|
|
2589
2963
|
},
|
|
2590
2964
|
timestamp
|
|
2591
2965
|
};
|
|
@@ -2598,16 +2972,16 @@ var ProviderHealthCheck = class {
|
|
|
2598
2972
|
};
|
|
2599
2973
|
}
|
|
2600
2974
|
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Milvus health check — uses baseUrl/uri (matching MilvusProvider constructor).
|
|
2977
|
+
*/
|
|
2601
2978
|
static async checkMilvus(config, timestamp) {
|
|
2602
2979
|
const opts = config.options;
|
|
2603
|
-
const
|
|
2604
|
-
const port = opts.port || 19530;
|
|
2980
|
+
const baseUrl = opts.baseUrl || opts.uri || (opts.host ? `http://${opts.host}:${opts.port || 19530}` : "http://localhost:19530");
|
|
2605
2981
|
try {
|
|
2606
2982
|
const controller = new AbortController();
|
|
2607
2983
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
2608
|
-
const response = await fetch(
|
|
2609
|
-
signal: controller.signal
|
|
2610
|
-
});
|
|
2984
|
+
const response = await fetch(`${baseUrl}/v1/health`, { signal: controller.signal });
|
|
2611
2985
|
clearTimeout(timeoutId);
|
|
2612
2986
|
if (!response.ok) {
|
|
2613
2987
|
throw new Error(`Health check returned ${response.status}`);
|
|
@@ -2615,7 +2989,7 @@ var ProviderHealthCheck = class {
|
|
|
2615
2989
|
return {
|
|
2616
2990
|
healthy: true,
|
|
2617
2991
|
provider: "milvus",
|
|
2618
|
-
capabilities: { endpoint:
|
|
2992
|
+
capabilities: { endpoint: baseUrl },
|
|
2619
2993
|
timestamp
|
|
2620
2994
|
};
|
|
2621
2995
|
} catch (error) {
|
|
@@ -2627,14 +3001,18 @@ var ProviderHealthCheck = class {
|
|
|
2627
3001
|
};
|
|
2628
3002
|
}
|
|
2629
3003
|
}
|
|
3004
|
+
/**
|
|
3005
|
+
* Qdrant health check — uses baseUrl (matching QdrantProvider constructor).
|
|
3006
|
+
*/
|
|
2630
3007
|
static async checkQdrant(config, timestamp) {
|
|
2631
3008
|
const opts = config.options;
|
|
2632
|
-
const baseUrl = opts.baseUrl || opts.url || "http://localhost:6333";
|
|
3009
|
+
const baseUrl = (opts.baseUrl || opts.url || "http://localhost:6333").replace(/\/$/, "");
|
|
2633
3010
|
try {
|
|
2634
|
-
const
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
}
|
|
3011
|
+
const apiKey = opts.apiKey;
|
|
3012
|
+
const response = await fetch(`${baseUrl}/`, {
|
|
3013
|
+
headers: apiKey ? { "api-key": apiKey } : {}
|
|
3014
|
+
});
|
|
3015
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2638
3016
|
const health = await response.json();
|
|
2639
3017
|
return {
|
|
2640
3018
|
healthy: true,
|
|
@@ -2651,19 +3029,19 @@ var ProviderHealthCheck = class {
|
|
|
2651
3029
|
};
|
|
2652
3030
|
}
|
|
2653
3031
|
}
|
|
3032
|
+
/**
|
|
3033
|
+
* ChromaDB health check — uses baseUrl/host (matching ChromaDBProvider constructor).
|
|
3034
|
+
*/
|
|
2654
3035
|
static async checkChromaDB(config, timestamp) {
|
|
2655
3036
|
const opts = config.options;
|
|
2656
|
-
const
|
|
2657
|
-
const port = opts.port || 8e3;
|
|
3037
|
+
const baseUrl = opts.baseUrl || (opts.host ? `http://${opts.host}:${opts.port || 8e3}` : "http://localhost:8000");
|
|
2658
3038
|
try {
|
|
2659
|
-
const response = await fetch(
|
|
2660
|
-
if (!response.ok) {
|
|
2661
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2662
|
-
}
|
|
3039
|
+
const response = await fetch(`${baseUrl}/api/v1/heartbeat`);
|
|
3040
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2663
3041
|
return {
|
|
2664
3042
|
healthy: true,
|
|
2665
3043
|
provider: "chromadb",
|
|
2666
|
-
capabilities: { endpoint:
|
|
3044
|
+
capabilities: { endpoint: baseUrl },
|
|
2667
3045
|
timestamp
|
|
2668
3046
|
};
|
|
2669
3047
|
} catch (error) {
|
|
@@ -2675,38 +3053,43 @@ var ProviderHealthCheck = class {
|
|
|
2675
3053
|
};
|
|
2676
3054
|
}
|
|
2677
3055
|
}
|
|
3056
|
+
/**
|
|
3057
|
+
* Redis health check — Redis is TCP-only (no HTTP endpoint).
|
|
3058
|
+
* We report healthy=true with a note; actual connectivity is validated at first operation.
|
|
3059
|
+
*/
|
|
2678
3060
|
static async checkRedis(config, timestamp) {
|
|
2679
3061
|
const opts = config.options;
|
|
2680
|
-
const url = opts.url || `redis://${opts.host}:${opts.port}
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
healthy: true,
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
timestamp
|
|
2688
|
-
};
|
|
2689
|
-
} catch (error) {
|
|
2690
|
-
return {
|
|
2691
|
-
healthy: false,
|
|
2692
|
-
provider: "redis",
|
|
2693
|
-
error: `Connection check failed: ${error instanceof Error ? error.message : String(error)}. Ensure Redis is running at ${url}`,
|
|
2694
|
-
timestamp
|
|
2695
|
-
};
|
|
3062
|
+
const url = opts.baseUrl || opts.url || (opts.host && opts.port ? `redis://${opts.host}:${opts.port}` : "redis://localhost:6379");
|
|
3063
|
+
if (url.startsWith("http")) {
|
|
3064
|
+
try {
|
|
3065
|
+
await fetch(url);
|
|
3066
|
+
return { healthy: true, provider: "redis", capabilities: { endpoint: url }, timestamp };
|
|
3067
|
+
} catch (e) {
|
|
3068
|
+
}
|
|
2696
3069
|
}
|
|
3070
|
+
return {
|
|
3071
|
+
healthy: true,
|
|
3072
|
+
provider: "redis",
|
|
3073
|
+
capabilities: {
|
|
3074
|
+
endpoint: url,
|
|
3075
|
+
note: "Redis uses TCP; connectivity is validated on first operation."
|
|
3076
|
+
},
|
|
3077
|
+
timestamp
|
|
3078
|
+
};
|
|
2697
3079
|
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Weaviate health check — uses baseUrl/url (matching WeaviateProvider constructor).
|
|
3082
|
+
*/
|
|
2698
3083
|
static async checkWeaviate(config, timestamp) {
|
|
2699
3084
|
const opts = config.options;
|
|
2700
|
-
const
|
|
3085
|
+
const baseUrl = (opts.baseUrl || opts.url || "http://localhost:8080").replace(/\/$/, "");
|
|
2701
3086
|
try {
|
|
2702
|
-
const response = await fetch(`${
|
|
2703
|
-
if (!response.ok) {
|
|
2704
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2705
|
-
}
|
|
3087
|
+
const response = await fetch(`${baseUrl}/v1/.well-known/ready`);
|
|
3088
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2706
3089
|
return {
|
|
2707
3090
|
healthy: true,
|
|
2708
3091
|
provider: "weaviate",
|
|
2709
|
-
capabilities: { endpoint:
|
|
3092
|
+
capabilities: { endpoint: baseUrl },
|
|
2710
3093
|
timestamp
|
|
2711
3094
|
};
|
|
2712
3095
|
} catch (error) {
|
|
@@ -2722,12 +3105,7 @@ var ProviderHealthCheck = class {
|
|
|
2722
3105
|
const opts = config.options;
|
|
2723
3106
|
const baseUrl = (opts.baseUrl || "").replace(/\/$/, "");
|
|
2724
3107
|
if (!baseUrl) {
|
|
2725
|
-
return {
|
|
2726
|
-
healthy: false,
|
|
2727
|
-
provider: "rest",
|
|
2728
|
-
error: "baseUrl is required",
|
|
2729
|
-
timestamp
|
|
2730
|
-
};
|
|
3108
|
+
return { healthy: false, provider: "rest", error: "baseUrl is required", timestamp };
|
|
2731
3109
|
}
|
|
2732
3110
|
try {
|
|
2733
3111
|
const response = await fetch(`${baseUrl}/health`, {
|
|
@@ -2790,11 +3168,7 @@ var ProviderHealthCheck = class {
|
|
|
2790
3168
|
return {
|
|
2791
3169
|
healthy: true,
|
|
2792
3170
|
provider: "openai",
|
|
2793
|
-
capabilities: {
|
|
2794
|
-
model: config.model,
|
|
2795
|
-
available: hasModel,
|
|
2796
|
-
totalModels: models.data.length
|
|
2797
|
-
},
|
|
3171
|
+
capabilities: { model: config.model, available: hasModel, totalModels: models.data.length },
|
|
2798
3172
|
timestamp
|
|
2799
3173
|
};
|
|
2800
3174
|
} catch (error) {
|
|
@@ -2815,12 +3189,7 @@ var ProviderHealthCheck = class {
|
|
|
2815
3189
|
max_tokens: 10,
|
|
2816
3190
|
messages: [{ role: "user", content: "ping" }]
|
|
2817
3191
|
});
|
|
2818
|
-
return {
|
|
2819
|
-
healthy: true,
|
|
2820
|
-
provider: "anthropic",
|
|
2821
|
-
capabilities: { model: config.model },
|
|
2822
|
-
timestamp
|
|
2823
|
-
};
|
|
3192
|
+
return { healthy: true, provider: "anthropic", capabilities: { model: config.model }, timestamp };
|
|
2824
3193
|
} catch (error) {
|
|
2825
3194
|
return {
|
|
2826
3195
|
healthy: false,
|
|
@@ -2834,20 +3203,14 @@ var ProviderHealthCheck = class {
|
|
|
2834
3203
|
const baseUrl = (config.baseUrl || "http://localhost:11434").replace(/\/$/, "");
|
|
2835
3204
|
try {
|
|
2836
3205
|
const response = await fetch(`${baseUrl}/api/tags`);
|
|
2837
|
-
if (!response.ok) {
|
|
2838
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2839
|
-
}
|
|
3206
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2840
3207
|
const data = await response.json();
|
|
2841
3208
|
const models = data.models || [];
|
|
2842
3209
|
const hasModel = models.some((m) => m.name === config.model);
|
|
2843
3210
|
return {
|
|
2844
3211
|
healthy: true,
|
|
2845
3212
|
provider: "ollama",
|
|
2846
|
-
capabilities: {
|
|
2847
|
-
model: config.model,
|
|
2848
|
-
available: hasModel,
|
|
2849
|
-
totalModels: models.length
|
|
2850
|
-
},
|
|
3213
|
+
capabilities: { model: config.model, available: hasModel, totalModels: models.length },
|
|
2851
3214
|
timestamp
|
|
2852
3215
|
};
|
|
2853
3216
|
} catch (error) {
|
|
@@ -2864,18 +3227,11 @@ var ProviderHealthCheck = class {
|
|
|
2864
3227
|
const baseUrlRaw = config.baseUrl || ((_a = config.options) == null ? void 0 : _a.baseUrl);
|
|
2865
3228
|
const baseUrl = (typeof baseUrlRaw === "string" ? baseUrlRaw : "").replace(/\/$/, "");
|
|
2866
3229
|
if (!baseUrl) {
|
|
2867
|
-
return {
|
|
2868
|
-
healthy: false,
|
|
2869
|
-
provider: config.provider,
|
|
2870
|
-
error: "baseUrl is required",
|
|
2871
|
-
timestamp
|
|
2872
|
-
};
|
|
3230
|
+
return { healthy: false, provider: config.provider, error: "baseUrl is required", timestamp };
|
|
2873
3231
|
}
|
|
2874
3232
|
try {
|
|
2875
3233
|
const headers = (_b = config.options) == null ? void 0 : _b.headers;
|
|
2876
|
-
const response = await fetch(`${baseUrl}/health`, {
|
|
2877
|
-
headers: headers || void 0
|
|
2878
|
-
});
|
|
3234
|
+
const response = await fetch(`${baseUrl}/health`, { headers: headers || void 0 });
|
|
2879
3235
|
return {
|
|
2880
3236
|
healthy: response.ok,
|
|
2881
3237
|
provider: config.provider,
|
|
@@ -2892,7 +3248,7 @@ var ProviderHealthCheck = class {
|
|
|
2892
3248
|
}
|
|
2893
3249
|
}
|
|
2894
3250
|
/**
|
|
2895
|
-
* Runs comprehensive health checks on all configured providers.
|
|
3251
|
+
* Runs comprehensive health checks on all configured providers in parallel.
|
|
2896
3252
|
*/
|
|
2897
3253
|
static async checkAll(vectorDbConfig, llmConfig, embeddingConfig) {
|
|
2898
3254
|
const [vectorDb, llm, embedding] = await Promise.all([
|
|
@@ -2969,23 +3325,278 @@ var VectorPlugin = class {
|
|
|
2969
3325
|
}
|
|
2970
3326
|
};
|
|
2971
3327
|
|
|
2972
|
-
// src/
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
3328
|
+
// src/config/ConfigBuilder.ts
|
|
3329
|
+
var ConfigBuilder = class {
|
|
3330
|
+
constructor() {
|
|
3331
|
+
this.config = {
|
|
3332
|
+
projectId: "default-project",
|
|
3333
|
+
rag: {
|
|
3334
|
+
chunkSize: 1e3,
|
|
3335
|
+
chunkOverlap: 200,
|
|
3336
|
+
topK: 5
|
|
3337
|
+
}
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
/**
|
|
3341
|
+
* Set the project/application ID for namespacing
|
|
3342
|
+
*/
|
|
3343
|
+
projectId(id) {
|
|
3344
|
+
this.config.projectId = id;
|
|
3345
|
+
return this;
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* Configure the vector database provider
|
|
3349
|
+
*/
|
|
3350
|
+
vectorDb(provider, options) {
|
|
3351
|
+
var _a;
|
|
3352
|
+
if (provider === "auto") {
|
|
3353
|
+
this.config.vectorDb = this.autoDetectVectorDb();
|
|
3354
|
+
} else {
|
|
3355
|
+
this.config.vectorDb = {
|
|
3356
|
+
provider,
|
|
3357
|
+
indexName: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
|
|
3358
|
+
options: __spreadValues({}, options)
|
|
3359
|
+
};
|
|
3360
|
+
}
|
|
3361
|
+
return this;
|
|
3362
|
+
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Configure the LLM provider for chat
|
|
3365
|
+
*/
|
|
3366
|
+
llm(provider, model, apiKey, options) {
|
|
3367
|
+
var _a, _b;
|
|
3368
|
+
if (provider === "auto") {
|
|
3369
|
+
this.config.llm = this.autoDetectLLM();
|
|
3370
|
+
} else {
|
|
3371
|
+
this.config.llm = {
|
|
3372
|
+
provider,
|
|
3373
|
+
model: model != null ? model : "default-model",
|
|
3374
|
+
apiKey,
|
|
3375
|
+
systemPrompt: options == null ? void 0 : options.systemPrompt,
|
|
3376
|
+
maxTokens: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
|
|
3377
|
+
temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
|
|
3378
|
+
baseUrl: options == null ? void 0 : options.baseUrl,
|
|
3379
|
+
options
|
|
3380
|
+
};
|
|
3381
|
+
}
|
|
3382
|
+
return this;
|
|
3383
|
+
}
|
|
3384
|
+
/**
|
|
3385
|
+
* Configure the embedding provider
|
|
3386
|
+
*/
|
|
3387
|
+
embedding(provider, model, apiKey, options) {
|
|
3388
|
+
if (provider === "auto") {
|
|
3389
|
+
this.config.embedding = this.autoDetectEmbedding();
|
|
3390
|
+
} else {
|
|
3391
|
+
this.config.embedding = {
|
|
3392
|
+
provider,
|
|
3393
|
+
model: model != null ? model : "default-embedding",
|
|
3394
|
+
apiKey,
|
|
3395
|
+
baseUrl: options == null ? void 0 : options.baseUrl,
|
|
3396
|
+
options
|
|
3397
|
+
};
|
|
3398
|
+
}
|
|
3399
|
+
return this;
|
|
3400
|
+
}
|
|
3401
|
+
/**
|
|
3402
|
+
* Set RAG-specific parameters
|
|
3403
|
+
*/
|
|
3404
|
+
rag(options) {
|
|
3405
|
+
var _a;
|
|
3406
|
+
this.config.rag = __spreadValues(__spreadValues({}, (_a = this.config.rag) != null ? _a : {}), options);
|
|
3407
|
+
return this;
|
|
3408
|
+
}
|
|
3409
|
+
/**
|
|
3410
|
+
* Set UI/UX parameters
|
|
3411
|
+
*/
|
|
3412
|
+
ui(options) {
|
|
3413
|
+
this.config.ui = options;
|
|
3414
|
+
return this;
|
|
3415
|
+
}
|
|
3416
|
+
/**
|
|
3417
|
+
* Build and return the configuration
|
|
3418
|
+
*/
|
|
3419
|
+
build() {
|
|
3420
|
+
const finalConfig = this.config;
|
|
3421
|
+
return finalConfig;
|
|
3422
|
+
}
|
|
3423
|
+
/**
|
|
3424
|
+
* Build and return as JSON for serialization
|
|
3425
|
+
*/
|
|
3426
|
+
toJSON() {
|
|
3427
|
+
return JSON.stringify(this.build());
|
|
3428
|
+
}
|
|
3429
|
+
// ============================================================================
|
|
3430
|
+
// Private helper methods for auto-detection
|
|
3431
|
+
// ============================================================================
|
|
3432
|
+
autoDetectVectorDb() {
|
|
3433
|
+
if (process.env.PINECONE_API_KEY && process.env.PINECONE_INDEX) {
|
|
3434
|
+
return {
|
|
3435
|
+
provider: "pinecone",
|
|
3436
|
+
indexName: process.env.PINECONE_INDEX,
|
|
3437
|
+
options: { apiKey: process.env.PINECONE_API_KEY }
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3440
|
+
if (process.env.QDRANT_URL) {
|
|
3441
|
+
return {
|
|
3442
|
+
provider: "qdrant",
|
|
3443
|
+
indexName: process.env.QDRANT_COLLECTION || "documents",
|
|
3444
|
+
options: {
|
|
3445
|
+
url: process.env.QDRANT_URL,
|
|
3446
|
+
apiKey: process.env.QDRANT_API_KEY
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
}
|
|
3450
|
+
if (process.env.DATABASE_URL) {
|
|
3451
|
+
return {
|
|
3452
|
+
provider: "postgresql",
|
|
3453
|
+
indexName: process.env.PG_TABLE || "documents",
|
|
3454
|
+
options: {
|
|
3455
|
+
connectionString: process.env.DATABASE_URL
|
|
3456
|
+
}
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
if (process.env.MONGODB_URI) {
|
|
3460
|
+
return {
|
|
3461
|
+
provider: "mongodb",
|
|
3462
|
+
indexName: process.env.MONGODB_COLLECTION || "documents",
|
|
3463
|
+
options: {
|
|
3464
|
+
uri: process.env.MONGODB_URI,
|
|
3465
|
+
database: process.env.MONGODB_DB || "ai_db",
|
|
3466
|
+
collection: process.env.MONGODB_COLLECTION || "documents"
|
|
3467
|
+
}
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
if (process.env.REDIS_URL) {
|
|
3471
|
+
return {
|
|
3472
|
+
provider: "redis",
|
|
3473
|
+
indexName: process.env.REDIS_INDEX || "documents",
|
|
3474
|
+
options: {
|
|
3475
|
+
url: process.env.REDIS_URL
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
}
|
|
3479
|
+
return {
|
|
3480
|
+
provider: "qdrant",
|
|
3481
|
+
indexName: "documents",
|
|
3482
|
+
options: {
|
|
3483
|
+
url: process.env.QDRANT_URL || "http://localhost:6333"
|
|
3484
|
+
}
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
autoDetectLLM() {
|
|
3488
|
+
if (process.env.OPENAI_API_KEY) {
|
|
3489
|
+
return {
|
|
3490
|
+
provider: "openai",
|
|
3491
|
+
model: process.env.OPENAI_MODEL || "gpt-4o-mini",
|
|
3492
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
3493
|
+
maxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || "1024"),
|
|
3494
|
+
temperature: parseFloat(process.env.OPENAI_TEMPERATURE || "0.7")
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3497
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
3498
|
+
return {
|
|
3499
|
+
provider: "anthropic",
|
|
3500
|
+
model: process.env.ANTHROPIC_MODEL || "claude-3-haiku-20240307",
|
|
3501
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
3502
|
+
maxTokens: parseInt(process.env.ANTHROPIC_MAX_TOKENS || "1024"),
|
|
3503
|
+
temperature: parseFloat(process.env.ANTHROPIC_TEMPERATURE || "0.7")
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
if (process.env.OLLAMA_BASE_URL) {
|
|
3507
|
+
return {
|
|
3508
|
+
provider: "ollama",
|
|
3509
|
+
model: process.env.OLLAMA_MODEL || "mistral",
|
|
3510
|
+
baseUrl: process.env.OLLAMA_BASE_URL,
|
|
3511
|
+
maxTokens: parseInt(process.env.OLLAMA_MAX_TOKENS || "1024"),
|
|
3512
|
+
temperature: parseFloat(process.env.OLLAMA_TEMPERATURE || "0.7")
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
return {
|
|
3516
|
+
provider: "openai",
|
|
3517
|
+
model: "gpt-4o-mini",
|
|
3518
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
3519
|
+
};
|
|
3520
|
+
}
|
|
3521
|
+
autoDetectEmbedding() {
|
|
3522
|
+
if (process.env.EMBEDDING_PROVIDER) {
|
|
3523
|
+
const provider = process.env.EMBEDDING_PROVIDER;
|
|
3524
|
+
return {
|
|
3525
|
+
provider,
|
|
3526
|
+
model: process.env.EMBEDDING_MODEL || "default",
|
|
3527
|
+
apiKey: process.env.EMBEDDING_API_KEY,
|
|
3528
|
+
baseUrl: process.env.EMBEDDING_BASE_URL
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
return {
|
|
3532
|
+
provider: "openai",
|
|
3533
|
+
model: "text-embedding-3-small",
|
|
3534
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
};
|
|
3538
|
+
var PRESETS = {
|
|
3539
|
+
/**
|
|
3540
|
+
* OpenAI + Pinecone: Production-ready cloud setup
|
|
3541
|
+
*/
|
|
3542
|
+
"openai-pinecone": {
|
|
3543
|
+
vectorDb: "pinecone",
|
|
3544
|
+
llm: "openai",
|
|
3545
|
+
embedding: "openai"
|
|
3546
|
+
},
|
|
3547
|
+
/**
|
|
3548
|
+
* Claude + Qdrant: Open-source vector DB + proprietary LLM
|
|
3549
|
+
*/
|
|
3550
|
+
"claude-qdrant": {
|
|
3551
|
+
vectorDb: "qdrant",
|
|
3552
|
+
llm: "anthropic",
|
|
3553
|
+
embedding: "openai"
|
|
3554
|
+
},
|
|
3555
|
+
/**
|
|
3556
|
+
* Local development: Ollama + local Qdrant
|
|
3557
|
+
*/
|
|
3558
|
+
"local-dev": {
|
|
3559
|
+
vectorDb: "qdrant",
|
|
3560
|
+
llm: "ollama",
|
|
3561
|
+
embedding: "ollama"
|
|
3562
|
+
},
|
|
3563
|
+
/**
|
|
3564
|
+
* Fully open-source: Ollama LLM + Qdrant vector DB + Ollama embeddings
|
|
3565
|
+
*/
|
|
3566
|
+
"fully-open-source": {
|
|
3567
|
+
vectorDb: "qdrant",
|
|
3568
|
+
llm: "ollama",
|
|
3569
|
+
embedding: "ollama"
|
|
3570
|
+
},
|
|
3571
|
+
/**
|
|
3572
|
+
* PostgreSQL stack: pgvector + OpenAI
|
|
3573
|
+
*/
|
|
3574
|
+
"postgres-openai": {
|
|
3575
|
+
vectorDb: "postgresql",
|
|
3576
|
+
llm: "openai",
|
|
3577
|
+
embedding: "openai"
|
|
3578
|
+
},
|
|
3579
|
+
/**
|
|
3580
|
+
* Enterprise MongoDB: MongoDB Atlas with OpenAI
|
|
3581
|
+
*/
|
|
3582
|
+
"mongodb-openai": {
|
|
3583
|
+
vectorDb: "mongodb",
|
|
3584
|
+
llm: "openai",
|
|
3585
|
+
embedding: "openai"
|
|
3586
|
+
},
|
|
3587
|
+
/**
|
|
3588
|
+
* Redis stack for caching + search
|
|
3589
|
+
*/
|
|
3590
|
+
"redis-openai": {
|
|
3591
|
+
vectorDb: "redis",
|
|
3592
|
+
llm: "openai",
|
|
3593
|
+
embedding: "openai"
|
|
3594
|
+
}
|
|
3595
|
+
};
|
|
3596
|
+
function createFromPreset(presetName) {
|
|
3597
|
+
const preset = PRESETS[presetName];
|
|
3598
|
+
return new ConfigBuilder().vectorDb(preset.vectorDb, { apiKey: process.env[`${preset.vectorDb.toUpperCase()}_API_KEY`] }).llm(preset.llm, void 0, process.env[`${preset.llm.toUpperCase()}_API_KEY`]).embedding(preset.embedding, void 0, process.env[`${preset.embedding.toUpperCase()}_API_KEY`]);
|
|
3599
|
+
}
|
|
2989
3600
|
|
|
2990
3601
|
// src/utils/DocumentParser.ts
|
|
2991
3602
|
var DocumentParser = class {
|
|
@@ -3046,7 +3657,20 @@ var DocumentParser = class {
|
|
|
3046
3657
|
}
|
|
3047
3658
|
};
|
|
3048
3659
|
|
|
3660
|
+
// src/server.ts
|
|
3661
|
+
init_BaseVectorProvider();
|
|
3662
|
+
init_PineconeProvider();
|
|
3663
|
+
init_PostgreSQLProvider();
|
|
3664
|
+
init_MongoDBProvider();
|
|
3665
|
+
init_MilvusProvider();
|
|
3666
|
+
init_QdrantProvider();
|
|
3667
|
+
init_ChromaDBProvider();
|
|
3668
|
+
init_RedisProvider();
|
|
3669
|
+
init_WeaviateProvider();
|
|
3670
|
+
init_UniversalVectorProvider();
|
|
3671
|
+
|
|
3049
3672
|
// src/handlers/index.ts
|
|
3673
|
+
var import_server = require("next/server");
|
|
3050
3674
|
function createChatHandler(config) {
|
|
3051
3675
|
const plugin = new VectorPlugin(config);
|
|
3052
3676
|
return async function POST(req) {
|
|
@@ -3135,23 +3759,36 @@ function createUploadHandler(config) {
|
|
|
3135
3759
|
0 && (module.exports = {
|
|
3136
3760
|
AnthropicProvider,
|
|
3137
3761
|
BaseVectorProvider,
|
|
3762
|
+
BatchProcessor,
|
|
3138
3763
|
ChromaDBProvider,
|
|
3764
|
+
ConfigBuilder,
|
|
3139
3765
|
ConfigResolver,
|
|
3766
|
+
ConfigValidator,
|
|
3140
3767
|
DocumentChunker,
|
|
3768
|
+
DocumentParser,
|
|
3769
|
+
EmbeddingStrategy,
|
|
3770
|
+
EmbeddingStrategyResolver,
|
|
3141
3771
|
LLMFactory,
|
|
3772
|
+
LLM_PROFILES,
|
|
3142
3773
|
MilvusProvider,
|
|
3143
3774
|
MongoDBProvider,
|
|
3144
3775
|
OllamaProvider,
|
|
3145
3776
|
OpenAIProvider,
|
|
3777
|
+
PRESETS,
|
|
3146
3778
|
PineconeProvider,
|
|
3147
3779
|
Pipeline,
|
|
3148
3780
|
PostgreSQLProvider,
|
|
3781
|
+
ProviderHealthCheck,
|
|
3149
3782
|
ProviderRegistry,
|
|
3150
3783
|
QdrantProvider,
|
|
3151
3784
|
RedisProvider,
|
|
3785
|
+
UniversalLLMAdapter,
|
|
3786
|
+
UniversalVectorProvider,
|
|
3787
|
+
VECTOR_PROFILES,
|
|
3152
3788
|
VectorPlugin,
|
|
3153
3789
|
WeaviateProvider,
|
|
3154
3790
|
createChatHandler,
|
|
3791
|
+
createFromPreset,
|
|
3155
3792
|
createHealthHandler,
|
|
3156
3793
|
createIngestHandler,
|
|
3157
3794
|
createUploadHandler,
|