@retrivora-ai/rag-engine 0.1.7 → 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-VAED5VA7.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-CWQQHAF6.mjs → chunk-26EMHLIN.mjs} +3 -5
- 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-7YQWGERZ.mjs → chunk-YIYDJQJM.mjs} +736 -189
- 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 +877 -625
- 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 +566 -17
- package/dist/server.d.ts +566 -17
- package/dist/server.js +1233 -642
- 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 -18
- package/src/core/ConfigValidator.ts +67 -50
- package/src/core/Pipeline.ts +28 -26
- package/src/core/PluginManager.ts +277 -0
- package/src/core/ProviderHealthCheck.ts +75 -139
- 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 +3 -6
- 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 {
|
|
@@ -986,18 +575,16 @@ var init_QdrantProvider = __esm({
|
|
|
986
575
|
async ensureCollection() {
|
|
987
576
|
var _a;
|
|
988
577
|
try {
|
|
989
|
-
const opts = this.config.options;
|
|
990
|
-
const dimensions = opts.dimensions || 1536;
|
|
991
578
|
await this.http.get(`/collections/${this.indexName}`);
|
|
992
579
|
console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
|
|
993
580
|
} catch (err) {
|
|
994
581
|
if (import_axios4.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
995
582
|
const opts = this.config.options;
|
|
996
|
-
const
|
|
997
|
-
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${
|
|
583
|
+
const dimensionsForCreate = opts.dimensions || 1536;
|
|
584
|
+
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
|
|
998
585
|
await this.http.put(`/collections/${this.indexName}`, {
|
|
999
586
|
vectors: {
|
|
1000
|
-
size:
|
|
587
|
+
size: dimensionsForCreate,
|
|
1001
588
|
distance: "Cosine"
|
|
1002
589
|
}
|
|
1003
590
|
});
|
|
@@ -1124,23 +711,41 @@ var init_ChromaDBProvider = __esm({
|
|
|
1124
711
|
super(config);
|
|
1125
712
|
this.collectionId = "";
|
|
1126
713
|
const opts = config.options;
|
|
1127
|
-
const baseUrl = opts.baseUrl;
|
|
1128
|
-
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");
|
|
1129
716
|
this.http = import_axios5.default.create({
|
|
1130
717
|
baseURL: baseUrl,
|
|
1131
718
|
headers: { "Content-Type": "application/json" }
|
|
1132
719
|
});
|
|
1133
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Get or create the ChromaDB collection.
|
|
723
|
+
*/
|
|
1134
724
|
async initialize() {
|
|
1135
|
-
|
|
1136
|
-
|
|
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
|
+
}
|
|
1137
742
|
}
|
|
1138
743
|
async upsert(doc, namespace) {
|
|
1139
744
|
await this.batchUpsert([doc], namespace);
|
|
1140
745
|
}
|
|
1141
746
|
async batchUpsert(docs, namespace) {
|
|
1142
747
|
const payload = {
|
|
1143
|
-
ids: docs.map((d) => d.id),
|
|
748
|
+
ids: docs.map((d) => String(d.id)),
|
|
1144
749
|
embeddings: docs.map((d) => d.vector),
|
|
1145
750
|
documents: docs.map((d) => d.content),
|
|
1146
751
|
metadatas: docs.map((d) => __spreadValues(__spreadValues({}, d.metadata || {}), namespace ? { namespace } : {}))
|
|
@@ -1168,15 +773,15 @@ var init_ChromaDBProvider = __esm({
|
|
|
1168
773
|
}
|
|
1169
774
|
return matches;
|
|
1170
775
|
}
|
|
1171
|
-
async delete(id,
|
|
776
|
+
async delete(id, namespace) {
|
|
1172
777
|
await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
|
|
1173
778
|
ids: [id],
|
|
1174
|
-
where:
|
|
779
|
+
where: namespace ? { namespace: { $eq: namespace } } : void 0
|
|
1175
780
|
});
|
|
1176
781
|
}
|
|
1177
|
-
async deleteNamespace(
|
|
782
|
+
async deleteNamespace(namespace) {
|
|
1178
783
|
await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
|
|
1179
|
-
where: { namespace: { $eq:
|
|
784
|
+
where: { namespace: { $eq: namespace } }
|
|
1180
785
|
});
|
|
1181
786
|
}
|
|
1182
787
|
async ping() {
|
|
@@ -1208,21 +813,20 @@ var init_RedisProvider = __esm({
|
|
|
1208
813
|
constructor(config) {
|
|
1209
814
|
super(config);
|
|
1210
815
|
const opts = config.options;
|
|
1211
|
-
const baseUrl = opts.baseUrl;
|
|
1212
|
-
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");
|
|
1213
818
|
this.http = import_axios6.default.create({
|
|
1214
819
|
baseURL: baseUrl,
|
|
1215
|
-
headers: {
|
|
1216
|
-
"Content-Type": "application/json"
|
|
1217
|
-
|
|
1218
|
-
}
|
|
820
|
+
headers: __spreadValues({
|
|
821
|
+
"Content-Type": "application/json"
|
|
822
|
+
}, opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : {})
|
|
1219
823
|
});
|
|
1220
824
|
}
|
|
1221
825
|
async initialize() {
|
|
1222
826
|
await this.ping();
|
|
1223
827
|
}
|
|
1224
828
|
async upsert(doc, namespace) {
|
|
1225
|
-
const key = namespace ? `${namespace}:${doc.id}` : doc.id;
|
|
829
|
+
const key = namespace ? `${namespace}:${doc.id}` : String(doc.id);
|
|
1226
830
|
await this.http.post("/", ["JSON.SET", key, "$", JSON.stringify({
|
|
1227
831
|
vector: doc.vector,
|
|
1228
832
|
content: doc.content,
|
|
@@ -1247,22 +851,26 @@ var init_RedisProvider = __esm({
|
|
|
1247
851
|
id: res["id"],
|
|
1248
852
|
score: res["score"],
|
|
1249
853
|
content: res["content"],
|
|
1250
|
-
metadata: res["metadata"]
|
|
854
|
+
metadata: res["metadata"] || {}
|
|
1251
855
|
}));
|
|
1252
856
|
}
|
|
1253
857
|
async delete(id, namespace) {
|
|
1254
858
|
const key = namespace ? `${namespace}:${id}` : id;
|
|
1255
859
|
await this.http.post("/", ["DEL", key]);
|
|
1256
860
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
861
|
+
async deleteNamespace(namespace) {
|
|
862
|
+
console.warn(`[RedisProvider] deleteNamespace("${namespace}") is not supported via REST API. Use Redis CLI: SCAN + DEL`);
|
|
1259
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
|
+
*/
|
|
1260
868
|
async ping() {
|
|
1261
869
|
try {
|
|
1262
870
|
await this.http.post("/", ["PING"]);
|
|
1263
871
|
return true;
|
|
1264
872
|
} catch (e) {
|
|
1265
|
-
return
|
|
873
|
+
return true;
|
|
1266
874
|
}
|
|
1267
875
|
}
|
|
1268
876
|
async disconnect() {
|
|
@@ -1286,8 +894,8 @@ var init_WeaviateProvider = __esm({
|
|
|
1286
894
|
constructor(config) {
|
|
1287
895
|
super(config);
|
|
1288
896
|
const opts = config.options;
|
|
1289
|
-
const baseUrl = opts.baseUrl;
|
|
1290
|
-
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");
|
|
1291
899
|
this.http = import_axios7.default.create({
|
|
1292
900
|
baseURL: baseUrl,
|
|
1293
901
|
headers: __spreadValues({
|
|
@@ -1389,28 +997,195 @@ var init_WeaviateProvider = __esm({
|
|
|
1389
997
|
}
|
|
1390
998
|
});
|
|
1391
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
|
+
|
|
1392
1154
|
// src/server.ts
|
|
1393
1155
|
var server_exports = {};
|
|
1394
1156
|
__export(server_exports, {
|
|
1395
1157
|
AnthropicProvider: () => AnthropicProvider,
|
|
1396
1158
|
BaseVectorProvider: () => BaseVectorProvider,
|
|
1159
|
+
BatchProcessor: () => BatchProcessor,
|
|
1397
1160
|
ChromaDBProvider: () => ChromaDBProvider,
|
|
1161
|
+
ConfigBuilder: () => ConfigBuilder,
|
|
1398
1162
|
ConfigResolver: () => ConfigResolver,
|
|
1163
|
+
ConfigValidator: () => ConfigValidator,
|
|
1399
1164
|
DocumentChunker: () => DocumentChunker,
|
|
1165
|
+
DocumentParser: () => DocumentParser,
|
|
1166
|
+
EmbeddingStrategy: () => EmbeddingStrategy,
|
|
1167
|
+
EmbeddingStrategyResolver: () => EmbeddingStrategyResolver,
|
|
1400
1168
|
LLMFactory: () => LLMFactory,
|
|
1169
|
+
LLM_PROFILES: () => LLM_PROFILES,
|
|
1401
1170
|
MilvusProvider: () => MilvusProvider,
|
|
1402
1171
|
MongoDBProvider: () => MongoDBProvider,
|
|
1403
1172
|
OllamaProvider: () => OllamaProvider,
|
|
1404
1173
|
OpenAIProvider: () => OpenAIProvider,
|
|
1174
|
+
PRESETS: () => PRESETS,
|
|
1405
1175
|
PineconeProvider: () => PineconeProvider,
|
|
1406
1176
|
Pipeline: () => Pipeline,
|
|
1407
1177
|
PostgreSQLProvider: () => PostgreSQLProvider,
|
|
1178
|
+
ProviderHealthCheck: () => ProviderHealthCheck,
|
|
1408
1179
|
ProviderRegistry: () => ProviderRegistry,
|
|
1409
1180
|
QdrantProvider: () => QdrantProvider,
|
|
1410
1181
|
RedisProvider: () => RedisProvider,
|
|
1182
|
+
UniversalLLMAdapter: () => UniversalLLMAdapter,
|
|
1183
|
+
UniversalVectorProvider: () => UniversalVectorProvider,
|
|
1184
|
+
VECTOR_PROFILES: () => VECTOR_PROFILES,
|
|
1411
1185
|
VectorPlugin: () => VectorPlugin,
|
|
1412
1186
|
WeaviateProvider: () => WeaviateProvider,
|
|
1413
1187
|
createChatHandler: () => createChatHandler,
|
|
1188
|
+
createFromPreset: () => createFromPreset,
|
|
1414
1189
|
createHealthHandler: () => createHealthHandler,
|
|
1415
1190
|
createIngestHandler: () => createIngestHandler,
|
|
1416
1191
|
createUploadHandler: () => createUploadHandler,
|
|
@@ -1422,7 +1197,20 @@ module.exports = __toCommonJS(server_exports);
|
|
|
1422
1197
|
init_templateUtils();
|
|
1423
1198
|
|
|
1424
1199
|
// src/config/serverConfig.ts
|
|
1425
|
-
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
|
+
];
|
|
1426
1214
|
var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
|
|
1427
1215
|
var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
|
|
1428
1216
|
function readString(env, name) {
|
|
@@ -1448,7 +1236,7 @@ function readEnum(env, name, fallback, allowed) {
|
|
|
1448
1236
|
throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
|
|
1449
1237
|
}
|
|
1450
1238
|
function getRagConfig(env = process.env) {
|
|
1451
|
-
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;
|
|
1452
1240
|
const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "__default__";
|
|
1453
1241
|
const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
|
|
1454
1242
|
const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
|
|
@@ -1457,49 +1245,62 @@ function getRagConfig(env = process.env) {
|
|
|
1457
1245
|
const vectorDbOptions = {};
|
|
1458
1246
|
if (vectorProvider === "pinecone") {
|
|
1459
1247
|
vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
vectorDbOptions.connectionString = (_e = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _e : "";
|
|
1248
|
+
} else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
|
|
1249
|
+
vectorDbOptions.connectionString = (_d = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _d : "";
|
|
1463
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");
|
|
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");
|
|
1464
1271
|
} else if (vectorProvider === "rest") {
|
|
1465
|
-
vectorDbOptions.baseUrl = (
|
|
1272
|
+
vectorDbOptions.baseUrl = (_n = readString(env, "VECTOR_DB_REST_URL")) != null ? _n : "";
|
|
1466
1273
|
vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
|
|
1467
1274
|
} else if (vectorProvider === "universal_rest") {
|
|
1468
|
-
vectorDbOptions.baseUrl = (
|
|
1275
|
+
vectorDbOptions.baseUrl = (_p = (_o = readString(env, "VECTOR_BASE_URL")) != null ? _o : readString(env, "VECTOR_DB_REST_URL")) != null ? _p : "";
|
|
1469
1276
|
vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
|
|
1470
1277
|
vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
|
|
1471
|
-
} else if (vectorProvider === "mongodb") {
|
|
1472
|
-
vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
|
|
1473
|
-
vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
|
|
1474
|
-
vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
|
|
1475
|
-
vectorDbOptions.indexName = (_l = readString(env, "MONGODB_INDEX_NAME")) != null ? _l : "vector_index";
|
|
1476
|
-
} else if (vectorProvider === "qdrant") {
|
|
1477
|
-
vectorDbOptions.baseUrl = (_m = readString(env, "QDRANT_URL")) != null ? _m : "http://localhost:6333";
|
|
1478
|
-
vectorDbOptions.apiKey = readString(env, "QDRANT_API_KEY");
|
|
1479
|
-
vectorDbOptions.dimensions = embeddingDimensions;
|
|
1480
1278
|
}
|
|
1481
1279
|
const llmApiKeyByProvider = {
|
|
1482
1280
|
openai: readString(env, "OPENAI_API_KEY"),
|
|
1483
1281
|
anthropic: readString(env, "ANTHROPIC_API_KEY"),
|
|
1484
1282
|
ollama: void 0,
|
|
1485
|
-
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")
|
|
1486
1286
|
};
|
|
1487
1287
|
const embeddingApiKeyByProvider = {
|
|
1488
1288
|
openai: readString(env, "OPENAI_API_KEY"),
|
|
1489
1289
|
ollama: void 0,
|
|
1490
|
-
|
|
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")
|
|
1491
1292
|
};
|
|
1492
1293
|
return {
|
|
1493
1294
|
projectId,
|
|
1494
1295
|
vectorDb: {
|
|
1495
1296
|
provider: vectorProvider,
|
|
1496
|
-
indexName: (
|
|
1297
|
+
indexName: (_s = readString(env, "VECTOR_DB_INDEX")) != null ? _s : "rag-index",
|
|
1497
1298
|
options: vectorDbOptions
|
|
1498
1299
|
},
|
|
1499
1300
|
llm: {
|
|
1500
1301
|
provider: llmProvider,
|
|
1501
|
-
model: (
|
|
1502
|
-
apiKey: (
|
|
1302
|
+
model: (_t = readString(env, "LLM_MODEL")) != null ? _t : "gpt-4o",
|
|
1303
|
+
apiKey: (_u = llmApiKeyByProvider[llmProvider]) != null ? _u : "",
|
|
1503
1304
|
baseUrl: readString(env, "LLM_BASE_URL"),
|
|
1504
1305
|
systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
|
|
1505
1306
|
maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
|
|
@@ -1510,7 +1311,7 @@ function getRagConfig(env = process.env) {
|
|
|
1510
1311
|
},
|
|
1511
1312
|
embedding: {
|
|
1512
1313
|
provider: embeddingProvider,
|
|
1513
|
-
model: (
|
|
1314
|
+
model: (_v = readString(env, "EMBEDDING_MODEL")) != null ? _v : "text-embedding-3-small",
|
|
1514
1315
|
apiKey: embeddingApiKeyByProvider[embeddingProvider],
|
|
1515
1316
|
baseUrl: readString(env, "EMBEDDING_BASE_URL"),
|
|
1516
1317
|
dimensions: embeddingDimensions,
|
|
@@ -1519,16 +1320,16 @@ function getRagConfig(env = process.env) {
|
|
|
1519
1320
|
}
|
|
1520
1321
|
},
|
|
1521
1322
|
ui: {
|
|
1522
|
-
title: (
|
|
1523
|
-
subtitle: (
|
|
1524
|
-
primaryColor: (
|
|
1525
|
-
accentColor: (
|
|
1526
|
-
logoUrl: (
|
|
1527
|
-
placeholder: (
|
|
1528
|
-
showSources: ((
|
|
1529
|
-
welcomeMessage: (
|
|
1530
|
-
visualStyle: (
|
|
1531
|
-
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"
|
|
1532
1333
|
},
|
|
1533
1334
|
rag: {
|
|
1534
1335
|
topK: readNumber(env, "RAG_TOP_K", 5),
|
|
@@ -1604,7 +1405,7 @@ var ConfigValidator = class {
|
|
|
1604
1405
|
errors.push({
|
|
1605
1406
|
field: "embedding",
|
|
1606
1407
|
message: "Embedding config is required when using Anthropic LLM",
|
|
1607
|
-
suggestion: 'Provide embedding config with provider (e.g., "openai")',
|
|
1408
|
+
suggestion: 'Provide embedding config with provider (e.g., "openai" or "ollama")',
|
|
1608
1409
|
severity: "error"
|
|
1609
1410
|
});
|
|
1610
1411
|
}
|
|
@@ -1666,6 +1467,10 @@ var ConfigValidator = class {
|
|
|
1666
1467
|
}
|
|
1667
1468
|
return errors;
|
|
1668
1469
|
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Pinecone — only needs apiKey (environment was removed in SDK v7+).
|
|
1472
|
+
* Options key: { apiKey: string }
|
|
1473
|
+
*/
|
|
1669
1474
|
static validatePineconeConfig(config) {
|
|
1670
1475
|
const errors = [];
|
|
1671
1476
|
const opts = config.options;
|
|
@@ -1677,16 +1482,12 @@ var ConfigValidator = class {
|
|
|
1677
1482
|
severity: "error"
|
|
1678
1483
|
});
|
|
1679
1484
|
}
|
|
1680
|
-
if (!opts.environment) {
|
|
1681
|
-
errors.push({
|
|
1682
|
-
field: "vectorDb.options.environment",
|
|
1683
|
-
message: "Pinecone environment is required",
|
|
1684
|
-
suggestion: 'Set PINECONE_ENVIRONMENT environment variable (e.g., "gcp-starter")',
|
|
1685
|
-
severity: "error"
|
|
1686
|
-
});
|
|
1687
|
-
}
|
|
1688
1485
|
return errors;
|
|
1689
1486
|
}
|
|
1487
|
+
/**
|
|
1488
|
+
* PostgreSQL / pgvector — needs a connection string.
|
|
1489
|
+
* Options key: { connectionString: string }
|
|
1490
|
+
*/
|
|
1690
1491
|
static validatePostgresConfig(config) {
|
|
1691
1492
|
const errors = [];
|
|
1692
1493
|
const opts = config.options;
|
|
@@ -1700,6 +1501,10 @@ var ConfigValidator = class {
|
|
|
1700
1501
|
}
|
|
1701
1502
|
return errors;
|
|
1702
1503
|
}
|
|
1504
|
+
/**
|
|
1505
|
+
* MongoDB — needs uri, database, and collection.
|
|
1506
|
+
* Options keys: { uri: string, database: string, collection: string }
|
|
1507
|
+
*/
|
|
1703
1508
|
static validateMongoDBConfig(config) {
|
|
1704
1509
|
const errors = [];
|
|
1705
1510
|
const opts = config.options;
|
|
@@ -1729,27 +1534,30 @@ var ConfigValidator = class {
|
|
|
1729
1534
|
}
|
|
1730
1535
|
return errors;
|
|
1731
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
|
+
*/
|
|
1732
1542
|
static validateMilvusConfig(config) {
|
|
1733
1543
|
const errors = [];
|
|
1734
1544
|
const opts = config.options;
|
|
1735
|
-
|
|
1545
|
+
const hasBaseUrl = Boolean(opts.baseUrl || opts.uri);
|
|
1546
|
+
const hasHostPort = Boolean(opts.host && opts.port);
|
|
1547
|
+
if (!hasBaseUrl && !hasHostPort) {
|
|
1736
1548
|
errors.push({
|
|
1737
|
-
field: "vectorDb.options.
|
|
1738
|
-
message:
|
|
1739
|
-
suggestion: "Set
|
|
1740
|
-
severity: "error"
|
|
1741
|
-
});
|
|
1742
|
-
}
|
|
1743
|
-
if (!opts.port) {
|
|
1744
|
-
errors.push({
|
|
1745
|
-
field: "vectorDb.options.port",
|
|
1746
|
-
message: "Milvus port is required",
|
|
1747
|
-
suggestion: "Set MILVUS_PORT environment variable (default: 19530)",
|
|
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",
|
|
1748
1552
|
severity: "error"
|
|
1749
1553
|
});
|
|
1750
1554
|
}
|
|
1751
1555
|
return errors;
|
|
1752
1556
|
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Qdrant — needs baseUrl (or url alias).
|
|
1559
|
+
* Options keys: { baseUrl: string, apiKey?: string }
|
|
1560
|
+
*/
|
|
1753
1561
|
static validateQdrantConfig(config) {
|
|
1754
1562
|
const errors = [];
|
|
1755
1563
|
const opts = config.options;
|
|
@@ -1763,38 +1571,55 @@ var ConfigValidator = class {
|
|
|
1763
1571
|
}
|
|
1764
1572
|
return errors;
|
|
1765
1573
|
}
|
|
1574
|
+
/**
|
|
1575
|
+
* ChromaDB — accepts baseUrl OR host.
|
|
1576
|
+
* ChromaDBProvider reads opts.baseUrl.
|
|
1577
|
+
* Options keys: { baseUrl?: string, host?: string, port?: number }
|
|
1578
|
+
*/
|
|
1766
1579
|
static validateChromaDBConfig(config) {
|
|
1767
1580
|
const errors = [];
|
|
1768
1581
|
const opts = config.options;
|
|
1769
|
-
if (!opts.
|
|
1582
|
+
if (!opts.baseUrl && !opts.host) {
|
|
1770
1583
|
errors.push({
|
|
1771
|
-
field: "vectorDb.options.
|
|
1772
|
-
message:
|
|
1773
|
-
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",
|
|
1774
1587
|
severity: "error"
|
|
1775
1588
|
});
|
|
1776
1589
|
}
|
|
1777
1590
|
return errors;
|
|
1778
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
|
+
*/
|
|
1779
1597
|
static validateRedisConfig(config) {
|
|
1780
1598
|
const errors = [];
|
|
1781
1599
|
const opts = config.options;
|
|
1782
|
-
|
|
1600
|
+
const hasUrl = Boolean(opts.baseUrl || opts.url);
|
|
1601
|
+
const hasHostPort = Boolean(opts.host && opts.port);
|
|
1602
|
+
if (!hasUrl && !hasHostPort) {
|
|
1783
1603
|
errors.push({
|
|
1784
|
-
field: "vectorDb.options.
|
|
1785
|
-
message: "Redis connection
|
|
1786
|
-
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",
|
|
1787
1607
|
severity: "error"
|
|
1788
1608
|
});
|
|
1789
1609
|
}
|
|
1790
1610
|
return errors;
|
|
1791
1611
|
}
|
|
1612
|
+
/**
|
|
1613
|
+
* Weaviate — accepts baseUrl OR url.
|
|
1614
|
+
* WeaviateProvider reads opts.baseUrl.
|
|
1615
|
+
* Options keys: { baseUrl?: string, url?: string, apiKey?: string }
|
|
1616
|
+
*/
|
|
1792
1617
|
static validateWeaviateConfig(config) {
|
|
1793
1618
|
const errors = [];
|
|
1794
1619
|
const opts = config.options;
|
|
1795
|
-
if (!opts.url) {
|
|
1620
|
+
if (!opts.baseUrl && !opts.url) {
|
|
1796
1621
|
errors.push({
|
|
1797
|
-
field: "vectorDb.options.
|
|
1622
|
+
field: "vectorDb.options.baseUrl",
|
|
1798
1623
|
message: "Weaviate instance URL is required",
|
|
1799
1624
|
suggestion: "Set WEAVIATE_URL environment variable",
|
|
1800
1625
|
severity: "error"
|
|
@@ -1802,6 +1627,10 @@ var ConfigValidator = class {
|
|
|
1802
1627
|
}
|
|
1803
1628
|
return errors;
|
|
1804
1629
|
}
|
|
1630
|
+
/**
|
|
1631
|
+
* Universal REST / custom REST adapter.
|
|
1632
|
+
* Options key: { baseUrl: string }
|
|
1633
|
+
*/
|
|
1805
1634
|
static validateRestConfig(config) {
|
|
1806
1635
|
const errors = [];
|
|
1807
1636
|
const opts = config.options;
|
|
@@ -1909,7 +1738,7 @@ var ConfigValidator = class {
|
|
|
1909
1738
|
errors.push({
|
|
1910
1739
|
field: "embedding.model",
|
|
1911
1740
|
message: "Embedding model name is required",
|
|
1912
|
-
suggestion: 'e.g., "text-embedding-3-small" for OpenAI',
|
|
1741
|
+
suggestion: 'e.g., "text-embedding-3-small" for OpenAI, "nomic-embed-text" for Ollama',
|
|
1913
1742
|
severity: "error"
|
|
1914
1743
|
});
|
|
1915
1744
|
}
|
|
@@ -1924,7 +1753,7 @@ var ConfigValidator = class {
|
|
|
1924
1753
|
if (config.provider === "ollama" && !config.baseUrl) {
|
|
1925
1754
|
errors.push({
|
|
1926
1755
|
field: "embedding.baseUrl",
|
|
1927
|
-
message: "Ollama base URL is required",
|
|
1756
|
+
message: "Ollama base URL is required for embedding",
|
|
1928
1757
|
suggestion: "Set EMBEDDING_BASE_URL environment variable",
|
|
1929
1758
|
severity: "error"
|
|
1930
1759
|
});
|
|
@@ -2101,17 +1930,433 @@ var DocumentChunker = class {
|
|
|
2101
1930
|
}
|
|
2102
1931
|
};
|
|
2103
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
|
+
|
|
2104
2345
|
// src/core/ProviderRegistry.ts
|
|
2105
|
-
init_LLMFactory();
|
|
2106
2346
|
var ProviderRegistry = class {
|
|
2107
2347
|
/**
|
|
2108
|
-
* 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);
|
|
2109
2353
|
*/
|
|
2110
2354
|
static registerVectorProvider(name, providerClass) {
|
|
2111
2355
|
this.vectorProviders[name] = providerClass;
|
|
2112
2356
|
}
|
|
2113
2357
|
/**
|
|
2114
2358
|
* Creates a vector database provider based on the configuration.
|
|
2359
|
+
* Built-in providers are dynamically imported to avoid bundling all SDKs.
|
|
2115
2360
|
*/
|
|
2116
2361
|
static async createVectorProvider(config) {
|
|
2117
2362
|
const { provider } = config;
|
|
@@ -2119,33 +2364,48 @@ var ProviderRegistry = class {
|
|
|
2119
2364
|
return new this.vectorProviders[provider](config);
|
|
2120
2365
|
}
|
|
2121
2366
|
switch (provider) {
|
|
2122
|
-
case "pinecone":
|
|
2367
|
+
case "pinecone": {
|
|
2123
2368
|
const { PineconeProvider: PineconeProvider2 } = await Promise.resolve().then(() => (init_PineconeProvider(), PineconeProvider_exports));
|
|
2124
2369
|
return new PineconeProvider2(config);
|
|
2370
|
+
}
|
|
2125
2371
|
case "pgvector":
|
|
2126
|
-
case "postgresql":
|
|
2372
|
+
case "postgresql": {
|
|
2127
2373
|
const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
|
|
2128
2374
|
return new PostgreSQLProvider2(config);
|
|
2129
|
-
|
|
2375
|
+
}
|
|
2376
|
+
case "mongodb": {
|
|
2130
2377
|
const { MongoDBProvider: MongoDBProvider2 } = await Promise.resolve().then(() => (init_MongoDBProvider(), MongoDBProvider_exports));
|
|
2131
2378
|
return new MongoDBProvider2(config);
|
|
2132
|
-
|
|
2379
|
+
}
|
|
2380
|
+
case "milvus": {
|
|
2133
2381
|
const { MilvusProvider: MilvusProvider2 } = await Promise.resolve().then(() => (init_MilvusProvider(), MilvusProvider_exports));
|
|
2134
2382
|
return new MilvusProvider2(config);
|
|
2135
|
-
|
|
2383
|
+
}
|
|
2384
|
+
case "qdrant": {
|
|
2136
2385
|
const { QdrantProvider: QdrantProvider2 } = await Promise.resolve().then(() => (init_QdrantProvider(), QdrantProvider_exports));
|
|
2137
2386
|
return new QdrantProvider2(config);
|
|
2138
|
-
|
|
2387
|
+
}
|
|
2388
|
+
case "chromadb": {
|
|
2139
2389
|
const { ChromaDBProvider: ChromaDBProvider2 } = await Promise.resolve().then(() => (init_ChromaDBProvider(), ChromaDBProvider_exports));
|
|
2140
2390
|
return new ChromaDBProvider2(config);
|
|
2141
|
-
|
|
2391
|
+
}
|
|
2392
|
+
case "redis": {
|
|
2142
2393
|
const { RedisProvider: RedisProvider2 } = await Promise.resolve().then(() => (init_RedisProvider(), RedisProvider_exports));
|
|
2143
2394
|
return new RedisProvider2(config);
|
|
2144
|
-
|
|
2395
|
+
}
|
|
2396
|
+
case "weaviate": {
|
|
2145
2397
|
const { WeaviateProvider: WeaviateProvider2 } = await Promise.resolve().then(() => (init_WeaviateProvider(), WeaviateProvider_exports));
|
|
2146
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
|
+
}
|
|
2147
2405
|
default:
|
|
2148
|
-
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
|
+
);
|
|
2149
2409
|
}
|
|
2150
2410
|
}
|
|
2151
2411
|
/**
|
|
@@ -2381,6 +2641,89 @@ ${errorMessages}`
|
|
|
2381
2641
|
}
|
|
2382
2642
|
};
|
|
2383
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
|
+
|
|
2384
2727
|
// src/core/Pipeline.ts
|
|
2385
2728
|
var Pipeline = class {
|
|
2386
2729
|
constructor(config) {
|
|
@@ -2395,18 +2738,17 @@ var Pipeline = class {
|
|
|
2395
2738
|
async initialize() {
|
|
2396
2739
|
if (this.initialised) return;
|
|
2397
2740
|
this.vectorDB = await ProviderRegistry.createVectorProvider(this.config.vectorDb);
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
}
|
|
2741
|
+
const { llmProvider, embeddingProvider } = await EmbeddingStrategyResolver.resolve(
|
|
2742
|
+
this.config.llm,
|
|
2743
|
+
this.config.embedding
|
|
2744
|
+
);
|
|
2745
|
+
this.llmProvider = llmProvider;
|
|
2746
|
+
this.embeddingProvider = embeddingProvider;
|
|
2405
2747
|
await this.vectorDB.initialize();
|
|
2406
2748
|
this.initialised = true;
|
|
2407
2749
|
}
|
|
2408
2750
|
/**
|
|
2409
|
-
* Ingest documents with automatic chunking, embedding, and batch
|
|
2751
|
+
* Ingest documents with automatic chunking, embedding, and batch upsert.
|
|
2410
2752
|
* Handles retries for transient failures.
|
|
2411
2753
|
*/
|
|
2412
2754
|
async ingest(documents, namespace) {
|
|
@@ -2419,19 +2761,18 @@ var Pipeline = class {
|
|
|
2419
2761
|
docId: doc.docId,
|
|
2420
2762
|
metadata: doc.metadata
|
|
2421
2763
|
});
|
|
2422
|
-
const
|
|
2764
|
+
const embedBatchOptions = {
|
|
2423
2765
|
batchSize: 50,
|
|
2424
|
-
// Embedding batch size
|
|
2425
2766
|
maxRetries: 3,
|
|
2426
2767
|
initialDelayMs: 100
|
|
2427
2768
|
};
|
|
2428
2769
|
const vectors = await BatchProcessor.mapWithRetry(
|
|
2429
2770
|
chunks.map((c) => c.content),
|
|
2430
2771
|
(text) => this.embeddingProvider.embed(text),
|
|
2431
|
-
|
|
2772
|
+
embedBatchOptions
|
|
2432
2773
|
);
|
|
2433
2774
|
if (vectors.length !== chunks.length) {
|
|
2434
|
-
throw new Error(`Embedding
|
|
2775
|
+
throw new Error(`Embedding mismatch: got ${vectors.length} vectors for ${chunks.length} chunks`);
|
|
2435
2776
|
}
|
|
2436
2777
|
const upsertDocs = chunks.map((chunk, i) => ({
|
|
2437
2778
|
id: chunk.id,
|
|
@@ -2458,10 +2799,7 @@ var Pipeline = class {
|
|
|
2458
2799
|
});
|
|
2459
2800
|
} catch (error) {
|
|
2460
2801
|
console.error(`[Pipeline] Failed to ingest document ${doc.docId}:`, error);
|
|
2461
|
-
results.push({
|
|
2462
|
-
docId: doc.docId,
|
|
2463
|
-
chunksIngested: 0
|
|
2464
|
-
});
|
|
2802
|
+
results.push({ docId: doc.docId, chunksIngested: 0 });
|
|
2465
2803
|
}
|
|
2466
2804
|
}
|
|
2467
2805
|
return results;
|
|
@@ -2491,7 +2829,6 @@ ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
|
2491
2829
|
var ProviderHealthCheck = class {
|
|
2492
2830
|
/**
|
|
2493
2831
|
* Validates vector database configuration before initialization.
|
|
2494
|
-
* Performs connectivity checks and verifies required resources exist.
|
|
2495
2832
|
*/
|
|
2496
2833
|
static async checkVectorProvider(config) {
|
|
2497
2834
|
const timestamp = Date.now();
|
|
@@ -2499,7 +2836,6 @@ var ProviderHealthCheck = class {
|
|
|
2499
2836
|
projectId: "health-check",
|
|
2500
2837
|
vectorDb: config,
|
|
2501
2838
|
llm: { provider: "openai", model: "gpt-4o" },
|
|
2502
|
-
// dummy
|
|
2503
2839
|
embedding: { provider: "openai", model: "text-embedding-3-small" }
|
|
2504
2840
|
});
|
|
2505
2841
|
const vectorDbErrors = configErrors.filter((e) => e.field.startsWith("vectorDb"));
|
|
@@ -2569,10 +2905,7 @@ var ProviderHealthCheck = class {
|
|
|
2569
2905
|
return {
|
|
2570
2906
|
healthy: true,
|
|
2571
2907
|
provider: "pinecone",
|
|
2572
|
-
capabilities: {
|
|
2573
|
-
indexes: indexNames.length,
|
|
2574
|
-
targetIndex: config.indexName
|
|
2575
|
-
},
|
|
2908
|
+
capabilities: { indexes: indexNames.length, targetIndex: config.indexName },
|
|
2576
2909
|
timestamp
|
|
2577
2910
|
};
|
|
2578
2911
|
} catch (error) {
|
|
@@ -2591,9 +2924,7 @@ var ProviderHealthCheck = class {
|
|
|
2591
2924
|
const client = new Client({ connectionString: opts.connectionString });
|
|
2592
2925
|
await client.connect();
|
|
2593
2926
|
const result = await client.query(`
|
|
2594
|
-
SELECT EXISTS(
|
|
2595
|
-
SELECT 1 FROM pg_extension WHERE extname = 'vector'
|
|
2596
|
-
);
|
|
2927
|
+
SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'vector');
|
|
2597
2928
|
`);
|
|
2598
2929
|
const hasVector = result.rows[0].exists;
|
|
2599
2930
|
await client.end();
|
|
@@ -2628,7 +2959,7 @@ var ProviderHealthCheck = class {
|
|
|
2628
2959
|
provider: "mongodb",
|
|
2629
2960
|
capabilities: {
|
|
2630
2961
|
collections: collectionNames.length,
|
|
2631
|
-
targetCollection: hasCollection ? opts.collection : "NOT FOUND"
|
|
2962
|
+
targetCollection: hasCollection ? opts.collection : "NOT FOUND (will be created on first insert)"
|
|
2632
2963
|
},
|
|
2633
2964
|
timestamp
|
|
2634
2965
|
};
|
|
@@ -2641,16 +2972,16 @@ var ProviderHealthCheck = class {
|
|
|
2641
2972
|
};
|
|
2642
2973
|
}
|
|
2643
2974
|
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Milvus health check — uses baseUrl/uri (matching MilvusProvider constructor).
|
|
2977
|
+
*/
|
|
2644
2978
|
static async checkMilvus(config, timestamp) {
|
|
2645
2979
|
const opts = config.options;
|
|
2646
|
-
const
|
|
2647
|
-
const port = opts.port || 19530;
|
|
2980
|
+
const baseUrl = opts.baseUrl || opts.uri || (opts.host ? `http://${opts.host}:${opts.port || 19530}` : "http://localhost:19530");
|
|
2648
2981
|
try {
|
|
2649
2982
|
const controller = new AbortController();
|
|
2650
2983
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
2651
|
-
const response = await fetch(
|
|
2652
|
-
signal: controller.signal
|
|
2653
|
-
});
|
|
2984
|
+
const response = await fetch(`${baseUrl}/v1/health`, { signal: controller.signal });
|
|
2654
2985
|
clearTimeout(timeoutId);
|
|
2655
2986
|
if (!response.ok) {
|
|
2656
2987
|
throw new Error(`Health check returned ${response.status}`);
|
|
@@ -2658,7 +2989,7 @@ var ProviderHealthCheck = class {
|
|
|
2658
2989
|
return {
|
|
2659
2990
|
healthy: true,
|
|
2660
2991
|
provider: "milvus",
|
|
2661
|
-
capabilities: { endpoint:
|
|
2992
|
+
capabilities: { endpoint: baseUrl },
|
|
2662
2993
|
timestamp
|
|
2663
2994
|
};
|
|
2664
2995
|
} catch (error) {
|
|
@@ -2670,17 +3001,18 @@ var ProviderHealthCheck = class {
|
|
|
2670
3001
|
};
|
|
2671
3002
|
}
|
|
2672
3003
|
}
|
|
3004
|
+
/**
|
|
3005
|
+
* Qdrant health check — uses baseUrl (matching QdrantProvider constructor).
|
|
3006
|
+
*/
|
|
2673
3007
|
static async checkQdrant(config, timestamp) {
|
|
2674
3008
|
const opts = config.options;
|
|
2675
|
-
const baseUrl = opts.baseUrl || opts.url || "http://localhost:6333";
|
|
3009
|
+
const baseUrl = (opts.baseUrl || opts.url || "http://localhost:6333").replace(/\/$/, "");
|
|
2676
3010
|
try {
|
|
2677
3011
|
const apiKey = opts.apiKey;
|
|
2678
3012
|
const response = await fetch(`${baseUrl}/`, {
|
|
2679
3013
|
headers: apiKey ? { "api-key": apiKey } : {}
|
|
2680
3014
|
});
|
|
2681
|
-
if (!response.ok) {
|
|
2682
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2683
|
-
}
|
|
3015
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2684
3016
|
const health = await response.json();
|
|
2685
3017
|
return {
|
|
2686
3018
|
healthy: true,
|
|
@@ -2697,19 +3029,19 @@ var ProviderHealthCheck = class {
|
|
|
2697
3029
|
};
|
|
2698
3030
|
}
|
|
2699
3031
|
}
|
|
3032
|
+
/**
|
|
3033
|
+
* ChromaDB health check — uses baseUrl/host (matching ChromaDBProvider constructor).
|
|
3034
|
+
*/
|
|
2700
3035
|
static async checkChromaDB(config, timestamp) {
|
|
2701
3036
|
const opts = config.options;
|
|
2702
|
-
const
|
|
2703
|
-
const port = opts.port || 8e3;
|
|
3037
|
+
const baseUrl = opts.baseUrl || (opts.host ? `http://${opts.host}:${opts.port || 8e3}` : "http://localhost:8000");
|
|
2704
3038
|
try {
|
|
2705
|
-
const response = await fetch(
|
|
2706
|
-
if (!response.ok) {
|
|
2707
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2708
|
-
}
|
|
3039
|
+
const response = await fetch(`${baseUrl}/api/v1/heartbeat`);
|
|
3040
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2709
3041
|
return {
|
|
2710
3042
|
healthy: true,
|
|
2711
3043
|
provider: "chromadb",
|
|
2712
|
-
capabilities: { endpoint:
|
|
3044
|
+
capabilities: { endpoint: baseUrl },
|
|
2713
3045
|
timestamp
|
|
2714
3046
|
};
|
|
2715
3047
|
} catch (error) {
|
|
@@ -2721,38 +3053,43 @@ var ProviderHealthCheck = class {
|
|
|
2721
3053
|
};
|
|
2722
3054
|
}
|
|
2723
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
|
+
*/
|
|
2724
3060
|
static async checkRedis(config, timestamp) {
|
|
2725
3061
|
const opts = config.options;
|
|
2726
|
-
const url = opts.url || `redis://${opts.host}:${opts.port}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
healthy: true,
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
timestamp
|
|
2734
|
-
};
|
|
2735
|
-
} catch (error) {
|
|
2736
|
-
return {
|
|
2737
|
-
healthy: false,
|
|
2738
|
-
provider: "redis",
|
|
2739
|
-
error: `Connection check failed: ${error instanceof Error ? error.message : String(error)}. Ensure Redis is running at ${url}`,
|
|
2740
|
-
timestamp
|
|
2741
|
-
};
|
|
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
|
+
}
|
|
2742
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
|
+
};
|
|
2743
3079
|
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Weaviate health check — uses baseUrl/url (matching WeaviateProvider constructor).
|
|
3082
|
+
*/
|
|
2744
3083
|
static async checkWeaviate(config, timestamp) {
|
|
2745
3084
|
const opts = config.options;
|
|
2746
|
-
const
|
|
3085
|
+
const baseUrl = (opts.baseUrl || opts.url || "http://localhost:8080").replace(/\/$/, "");
|
|
2747
3086
|
try {
|
|
2748
|
-
const response = await fetch(`${
|
|
2749
|
-
if (!response.ok) {
|
|
2750
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2751
|
-
}
|
|
3087
|
+
const response = await fetch(`${baseUrl}/v1/.well-known/ready`);
|
|
3088
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2752
3089
|
return {
|
|
2753
3090
|
healthy: true,
|
|
2754
3091
|
provider: "weaviate",
|
|
2755
|
-
capabilities: { endpoint:
|
|
3092
|
+
capabilities: { endpoint: baseUrl },
|
|
2756
3093
|
timestamp
|
|
2757
3094
|
};
|
|
2758
3095
|
} catch (error) {
|
|
@@ -2768,12 +3105,7 @@ var ProviderHealthCheck = class {
|
|
|
2768
3105
|
const opts = config.options;
|
|
2769
3106
|
const baseUrl = (opts.baseUrl || "").replace(/\/$/, "");
|
|
2770
3107
|
if (!baseUrl) {
|
|
2771
|
-
return {
|
|
2772
|
-
healthy: false,
|
|
2773
|
-
provider: "rest",
|
|
2774
|
-
error: "baseUrl is required",
|
|
2775
|
-
timestamp
|
|
2776
|
-
};
|
|
3108
|
+
return { healthy: false, provider: "rest", error: "baseUrl is required", timestamp };
|
|
2777
3109
|
}
|
|
2778
3110
|
try {
|
|
2779
3111
|
const response = await fetch(`${baseUrl}/health`, {
|
|
@@ -2836,11 +3168,7 @@ var ProviderHealthCheck = class {
|
|
|
2836
3168
|
return {
|
|
2837
3169
|
healthy: true,
|
|
2838
3170
|
provider: "openai",
|
|
2839
|
-
capabilities: {
|
|
2840
|
-
model: config.model,
|
|
2841
|
-
available: hasModel,
|
|
2842
|
-
totalModels: models.data.length
|
|
2843
|
-
},
|
|
3171
|
+
capabilities: { model: config.model, available: hasModel, totalModels: models.data.length },
|
|
2844
3172
|
timestamp
|
|
2845
3173
|
};
|
|
2846
3174
|
} catch (error) {
|
|
@@ -2861,12 +3189,7 @@ var ProviderHealthCheck = class {
|
|
|
2861
3189
|
max_tokens: 10,
|
|
2862
3190
|
messages: [{ role: "user", content: "ping" }]
|
|
2863
3191
|
});
|
|
2864
|
-
return {
|
|
2865
|
-
healthy: true,
|
|
2866
|
-
provider: "anthropic",
|
|
2867
|
-
capabilities: { model: config.model },
|
|
2868
|
-
timestamp
|
|
2869
|
-
};
|
|
3192
|
+
return { healthy: true, provider: "anthropic", capabilities: { model: config.model }, timestamp };
|
|
2870
3193
|
} catch (error) {
|
|
2871
3194
|
return {
|
|
2872
3195
|
healthy: false,
|
|
@@ -2880,20 +3203,14 @@ var ProviderHealthCheck = class {
|
|
|
2880
3203
|
const baseUrl = (config.baseUrl || "http://localhost:11434").replace(/\/$/, "");
|
|
2881
3204
|
try {
|
|
2882
3205
|
const response = await fetch(`${baseUrl}/api/tags`);
|
|
2883
|
-
if (!response.ok) {
|
|
2884
|
-
throw new Error(`Health check returned ${response.status}`);
|
|
2885
|
-
}
|
|
3206
|
+
if (!response.ok) throw new Error(`Health check returned ${response.status}`);
|
|
2886
3207
|
const data = await response.json();
|
|
2887
3208
|
const models = data.models || [];
|
|
2888
3209
|
const hasModel = models.some((m) => m.name === config.model);
|
|
2889
3210
|
return {
|
|
2890
3211
|
healthy: true,
|
|
2891
3212
|
provider: "ollama",
|
|
2892
|
-
capabilities: {
|
|
2893
|
-
model: config.model,
|
|
2894
|
-
available: hasModel,
|
|
2895
|
-
totalModels: models.length
|
|
2896
|
-
},
|
|
3213
|
+
capabilities: { model: config.model, available: hasModel, totalModels: models.length },
|
|
2897
3214
|
timestamp
|
|
2898
3215
|
};
|
|
2899
3216
|
} catch (error) {
|
|
@@ -2910,18 +3227,11 @@ var ProviderHealthCheck = class {
|
|
|
2910
3227
|
const baseUrlRaw = config.baseUrl || ((_a = config.options) == null ? void 0 : _a.baseUrl);
|
|
2911
3228
|
const baseUrl = (typeof baseUrlRaw === "string" ? baseUrlRaw : "").replace(/\/$/, "");
|
|
2912
3229
|
if (!baseUrl) {
|
|
2913
|
-
return {
|
|
2914
|
-
healthy: false,
|
|
2915
|
-
provider: config.provider,
|
|
2916
|
-
error: "baseUrl is required",
|
|
2917
|
-
timestamp
|
|
2918
|
-
};
|
|
3230
|
+
return { healthy: false, provider: config.provider, error: "baseUrl is required", timestamp };
|
|
2919
3231
|
}
|
|
2920
3232
|
try {
|
|
2921
3233
|
const headers = (_b = config.options) == null ? void 0 : _b.headers;
|
|
2922
|
-
const response = await fetch(`${baseUrl}/health`, {
|
|
2923
|
-
headers: headers || void 0
|
|
2924
|
-
});
|
|
3234
|
+
const response = await fetch(`${baseUrl}/health`, { headers: headers || void 0 });
|
|
2925
3235
|
return {
|
|
2926
3236
|
healthy: response.ok,
|
|
2927
3237
|
provider: config.provider,
|
|
@@ -2938,7 +3248,7 @@ var ProviderHealthCheck = class {
|
|
|
2938
3248
|
}
|
|
2939
3249
|
}
|
|
2940
3250
|
/**
|
|
2941
|
-
* Runs comprehensive health checks on all configured providers.
|
|
3251
|
+
* Runs comprehensive health checks on all configured providers in parallel.
|
|
2942
3252
|
*/
|
|
2943
3253
|
static async checkAll(vectorDbConfig, llmConfig, embeddingConfig) {
|
|
2944
3254
|
const [vectorDb, llm, embedding] = await Promise.all([
|
|
@@ -3015,23 +3325,278 @@ var VectorPlugin = class {
|
|
|
3015
3325
|
}
|
|
3016
3326
|
};
|
|
3017
3327
|
|
|
3018
|
-
// src/
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
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
|
+
}
|
|
3035
3600
|
|
|
3036
3601
|
// src/utils/DocumentParser.ts
|
|
3037
3602
|
var DocumentParser = class {
|
|
@@ -3092,7 +3657,20 @@ var DocumentParser = class {
|
|
|
3092
3657
|
}
|
|
3093
3658
|
};
|
|
3094
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
|
+
|
|
3095
3672
|
// src/handlers/index.ts
|
|
3673
|
+
var import_server = require("next/server");
|
|
3096
3674
|
function createChatHandler(config) {
|
|
3097
3675
|
const plugin = new VectorPlugin(config);
|
|
3098
3676
|
return async function POST(req) {
|
|
@@ -3181,23 +3759,36 @@ function createUploadHandler(config) {
|
|
|
3181
3759
|
0 && (module.exports = {
|
|
3182
3760
|
AnthropicProvider,
|
|
3183
3761
|
BaseVectorProvider,
|
|
3762
|
+
BatchProcessor,
|
|
3184
3763
|
ChromaDBProvider,
|
|
3764
|
+
ConfigBuilder,
|
|
3185
3765
|
ConfigResolver,
|
|
3766
|
+
ConfigValidator,
|
|
3186
3767
|
DocumentChunker,
|
|
3768
|
+
DocumentParser,
|
|
3769
|
+
EmbeddingStrategy,
|
|
3770
|
+
EmbeddingStrategyResolver,
|
|
3187
3771
|
LLMFactory,
|
|
3772
|
+
LLM_PROFILES,
|
|
3188
3773
|
MilvusProvider,
|
|
3189
3774
|
MongoDBProvider,
|
|
3190
3775
|
OllamaProvider,
|
|
3191
3776
|
OpenAIProvider,
|
|
3777
|
+
PRESETS,
|
|
3192
3778
|
PineconeProvider,
|
|
3193
3779
|
Pipeline,
|
|
3194
3780
|
PostgreSQLProvider,
|
|
3781
|
+
ProviderHealthCheck,
|
|
3195
3782
|
ProviderRegistry,
|
|
3196
3783
|
QdrantProvider,
|
|
3197
3784
|
RedisProvider,
|
|
3785
|
+
UniversalLLMAdapter,
|
|
3786
|
+
UniversalVectorProvider,
|
|
3787
|
+
VECTOR_PROFILES,
|
|
3198
3788
|
VectorPlugin,
|
|
3199
3789
|
WeaviateProvider,
|
|
3200
3790
|
createChatHandler,
|
|
3791
|
+
createFromPreset,
|
|
3201
3792
|
createHealthHandler,
|
|
3202
3793
|
createIngestHandler,
|
|
3203
3794
|
createUploadHandler,
|