@retrivora-ai/rag-engine 1.1.0 → 1.1.1
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/{QdrantProvider-WWXFX2XF.mjs → QdrantProvider-NMXOULCU.mjs} +1 -1
- package/dist/{chunk-65S4BQL2.mjs → chunk-63HITIWC.mjs} +11 -4
- package/dist/{chunk-G2LVK46T.mjs → chunk-JZ4H7EP6.mjs} +146 -3
- package/dist/handlers/index.js +156 -6
- package/dist/handlers/index.mjs +1 -1
- package/dist/server.d.mts +3 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +156 -6
- package/dist/server.mjs +2 -2
- package/package.json +1 -1
- package/src/llm/providers/AnthropicProvider.ts +29 -0
- package/src/llm/providers/GeminiProvider.ts +31 -0
- package/src/llm/providers/OllamaProvider.ts +21 -2
- package/src/llm/providers/OpenAIProvider.ts +35 -0
- package/src/providers/vectordb/QdrantProvider.ts +13 -4
|
@@ -11,6 +11,7 @@ import crypto from "crypto";
|
|
|
11
11
|
var QdrantProvider = class extends BaseVectorProvider {
|
|
12
12
|
constructor(config) {
|
|
13
13
|
super(config);
|
|
14
|
+
this.schemaDiscovered = false;
|
|
14
15
|
const opts = config.options;
|
|
15
16
|
const baseUrl = opts.baseUrl;
|
|
16
17
|
if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
|
|
@@ -19,12 +20,15 @@ var QdrantProvider = class extends BaseVectorProvider {
|
|
|
19
20
|
this.isFlatPayload = !!opts.flatPayload;
|
|
20
21
|
this.http = axios.create({
|
|
21
22
|
baseURL: baseUrl,
|
|
23
|
+
timeout: 15e3,
|
|
24
|
+
// 15s timeout for vector DB operations
|
|
22
25
|
headers: __spreadValues({
|
|
23
26
|
"Content-Type": "application/json"
|
|
24
27
|
}, opts.apiKey ? { "api-key": opts.apiKey } : {})
|
|
25
28
|
});
|
|
26
29
|
}
|
|
27
30
|
async initialize() {
|
|
31
|
+
if (this.schemaDiscovered) return;
|
|
28
32
|
await this.ping();
|
|
29
33
|
await this.ensureCollection();
|
|
30
34
|
console.log(`[QdrantProvider] \u{1F50D} Discovering schema for collection "${this.indexName}"...`);
|
|
@@ -34,13 +38,16 @@ var QdrantProvider = class extends BaseVectorProvider {
|
|
|
34
38
|
const allFields = [.../* @__PURE__ */ new Set([...discoveredFields, ...configFields])];
|
|
35
39
|
if (allFields.length > 0) {
|
|
36
40
|
console.log(`[QdrantProvider] \u{1F6E0} Ensuring indexes for ${allFields.length} discovered fields...`);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
await Promise.all(
|
|
42
|
+
allFields.map(async (fieldInfo) => {
|
|
43
|
+
const [fieldName, schemaType] = fieldInfo.split(":");
|
|
44
|
+
return this.ensureIndex(fieldName, schemaType || "keyword");
|
|
45
|
+
})
|
|
46
|
+
);
|
|
41
47
|
} else {
|
|
42
48
|
console.log(`[QdrantProvider] \u2139\uFE0F No fields discovered for indexing.`);
|
|
43
49
|
}
|
|
50
|
+
this.schemaDiscovered = true;
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
53
|
* Samples points from the collection to discover available payload fields.
|
|
@@ -333,6 +333,53 @@ ${context}`
|
|
|
333
333
|
});
|
|
334
334
|
return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
|
|
335
335
|
}
|
|
336
|
+
chatStream(messages, context, options) {
|
|
337
|
+
return __asyncGenerator(this, null, function* () {
|
|
338
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
339
|
+
const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
340
|
+
|
|
341
|
+
Context:
|
|
342
|
+
${context}`;
|
|
343
|
+
const systemMessage = {
|
|
344
|
+
role: "system",
|
|
345
|
+
content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
|
|
346
|
+
|
|
347
|
+
Context:
|
|
348
|
+
${context}`
|
|
349
|
+
};
|
|
350
|
+
const formattedMessages = [
|
|
351
|
+
systemMessage,
|
|
352
|
+
...messages.map((m) => ({
|
|
353
|
+
role: m.role,
|
|
354
|
+
content: m.content
|
|
355
|
+
}))
|
|
356
|
+
];
|
|
357
|
+
const stream = yield new __await(this.client.chat.completions.create({
|
|
358
|
+
model: this.llmConfig.model,
|
|
359
|
+
messages: formattedMessages,
|
|
360
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
361
|
+
temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
|
|
362
|
+
stop: options == null ? void 0 : options.stop,
|
|
363
|
+
stream: true
|
|
364
|
+
}));
|
|
365
|
+
try {
|
|
366
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
367
|
+
const chunk = temp.value;
|
|
368
|
+
const content = ((_g = (_f = chunk.choices[0]) == null ? void 0 : _f.delta) == null ? void 0 : _g.content) || "";
|
|
369
|
+
if (content) yield content;
|
|
370
|
+
}
|
|
371
|
+
} catch (temp) {
|
|
372
|
+
error = [temp];
|
|
373
|
+
} finally {
|
|
374
|
+
try {
|
|
375
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
376
|
+
} finally {
|
|
377
|
+
if (error)
|
|
378
|
+
throw error[0];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
336
383
|
async embed(text, options) {
|
|
337
384
|
const results = await this.batchEmbed([text], options);
|
|
338
385
|
return results[0];
|
|
@@ -438,6 +485,47 @@ ${context}`;
|
|
|
438
485
|
const block = response.content[0];
|
|
439
486
|
return block.type === "text" ? block.text : "";
|
|
440
487
|
}
|
|
488
|
+
chatStream(messages, context, options) {
|
|
489
|
+
return __asyncGenerator(this, null, function* () {
|
|
490
|
+
var _a, _b, _c;
|
|
491
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
|
|
492
|
+
|
|
493
|
+
Context:
|
|
494
|
+
${context}`;
|
|
495
|
+
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
496
|
+
|
|
497
|
+
Context:
|
|
498
|
+
${context}`;
|
|
499
|
+
const anthropicMessages = messages.map((m) => ({
|
|
500
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
501
|
+
content: m.content
|
|
502
|
+
}));
|
|
503
|
+
const stream = yield new __await(this.client.messages.create({
|
|
504
|
+
model: this.llmConfig.model,
|
|
505
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
506
|
+
system,
|
|
507
|
+
messages: anthropicMessages,
|
|
508
|
+
stream: true
|
|
509
|
+
}));
|
|
510
|
+
try {
|
|
511
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
512
|
+
const chunk = temp.value;
|
|
513
|
+
if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
|
|
514
|
+
yield chunk.delta.text;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
} catch (temp) {
|
|
518
|
+
error = [temp];
|
|
519
|
+
} finally {
|
|
520
|
+
try {
|
|
521
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
522
|
+
} finally {
|
|
523
|
+
if (error)
|
|
524
|
+
throw error[0];
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
441
529
|
async embed(text, options) {
|
|
442
530
|
void text;
|
|
443
531
|
void options;
|
|
@@ -543,7 +631,7 @@ var OllamaProvider = class {
|
|
|
543
631
|
}
|
|
544
632
|
chatStream(messages, context, options) {
|
|
545
633
|
return __asyncGenerator(this, null, function* () {
|
|
546
|
-
var _a, _b, _c, _d, _e;
|
|
634
|
+
var _a, _b, _c, _d, _e, _f;
|
|
547
635
|
const system = this.buildSystemPrompt(context);
|
|
548
636
|
const response = yield new __await(this.http.post("/api/chat", {
|
|
549
637
|
model: this.llmConfig.model,
|
|
@@ -557,11 +645,15 @@ var OllamaProvider = class {
|
|
|
557
645
|
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
558
646
|
]
|
|
559
647
|
}, { responseType: "stream" }));
|
|
648
|
+
let lineBuffer = "";
|
|
560
649
|
try {
|
|
561
650
|
for (var iter = __forAwait(response.data), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
562
651
|
const chunk = temp.value;
|
|
563
|
-
|
|
652
|
+
lineBuffer += chunk.toString();
|
|
653
|
+
const lines = lineBuffer.split("\n");
|
|
654
|
+
lineBuffer = lines.pop() || "";
|
|
564
655
|
for (const line of lines) {
|
|
656
|
+
if (!line.trim()) continue;
|
|
565
657
|
try {
|
|
566
658
|
const json = JSON.parse(line);
|
|
567
659
|
if ((_e = json.message) == null ? void 0 : _e.content) {
|
|
@@ -569,6 +661,7 @@ var OllamaProvider = class {
|
|
|
569
661
|
}
|
|
570
662
|
if (json.done) return;
|
|
571
663
|
} catch (e) {
|
|
664
|
+
console.warn("[OllamaProvider] Failed to parse streaming line:", line);
|
|
572
665
|
}
|
|
573
666
|
}
|
|
574
667
|
}
|
|
@@ -582,6 +675,13 @@ var OllamaProvider = class {
|
|
|
582
675
|
throw error[0];
|
|
583
676
|
}
|
|
584
677
|
}
|
|
678
|
+
if (lineBuffer.trim()) {
|
|
679
|
+
try {
|
|
680
|
+
const json = JSON.parse(lineBuffer);
|
|
681
|
+
if ((_f = json.message) == null ? void 0 : _f.content) yield json.message.content;
|
|
682
|
+
} catch (e) {
|
|
683
|
+
}
|
|
684
|
+
}
|
|
585
685
|
});
|
|
586
686
|
}
|
|
587
687
|
buildSystemPrompt(context) {
|
|
@@ -727,6 +827,49 @@ ${context}`;
|
|
|
727
827
|
});
|
|
728
828
|
return (_f = response.text) != null ? _f : "";
|
|
729
829
|
}
|
|
830
|
+
chatStream(messages, context, options) {
|
|
831
|
+
return __asyncGenerator(this, null, function* () {
|
|
832
|
+
var _a, _b, _c, _d, _e;
|
|
833
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
834
|
+
|
|
835
|
+
Context:
|
|
836
|
+
${context}`;
|
|
837
|
+
const systemInstruction = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
838
|
+
|
|
839
|
+
Context:
|
|
840
|
+
${context}`;
|
|
841
|
+
const geminiMessages = messages.map((m) => ({
|
|
842
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
843
|
+
parts: [{ text: m.content }]
|
|
844
|
+
}));
|
|
845
|
+
const result = yield new __await(this.client.models.generateContentStream({
|
|
846
|
+
model: this.llmConfig.model,
|
|
847
|
+
contents: geminiMessages,
|
|
848
|
+
config: {
|
|
849
|
+
systemInstruction,
|
|
850
|
+
temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
|
|
851
|
+
maxOutputTokens: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024,
|
|
852
|
+
stopSequences: options == null ? void 0 : options.stop
|
|
853
|
+
}
|
|
854
|
+
}));
|
|
855
|
+
try {
|
|
856
|
+
for (var iter = __forAwait(result.stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
857
|
+
const chunk = temp.value;
|
|
858
|
+
const text = chunk.text;
|
|
859
|
+
if (text) yield text;
|
|
860
|
+
}
|
|
861
|
+
} catch (temp) {
|
|
862
|
+
error = [temp];
|
|
863
|
+
} finally {
|
|
864
|
+
try {
|
|
865
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
866
|
+
} finally {
|
|
867
|
+
if (error)
|
|
868
|
+
throw error[0];
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
}
|
|
730
873
|
async embed(text, options) {
|
|
731
874
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
732
875
|
const model = this.sanitizeModel(
|
|
@@ -1106,7 +1249,7 @@ var ProviderRegistry = class {
|
|
|
1106
1249
|
return MilvusProvider;
|
|
1107
1250
|
}
|
|
1108
1251
|
case "qdrant": {
|
|
1109
|
-
const { QdrantProvider } = await import("./QdrantProvider-
|
|
1252
|
+
const { QdrantProvider } = await import("./QdrantProvider-NMXOULCU.mjs");
|
|
1110
1253
|
return QdrantProvider;
|
|
1111
1254
|
}
|
|
1112
1255
|
case "chromadb": {
|
package/dist/handlers/index.js
CHANGED
|
@@ -842,6 +842,7 @@ var init_QdrantProvider = __esm({
|
|
|
842
842
|
QdrantProvider = class extends BaseVectorProvider {
|
|
843
843
|
constructor(config) {
|
|
844
844
|
super(config);
|
|
845
|
+
this.schemaDiscovered = false;
|
|
845
846
|
const opts = config.options;
|
|
846
847
|
const baseUrl = opts.baseUrl;
|
|
847
848
|
if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
|
|
@@ -850,12 +851,15 @@ var init_QdrantProvider = __esm({
|
|
|
850
851
|
this.isFlatPayload = !!opts.flatPayload;
|
|
851
852
|
this.http = import_axios4.default.create({
|
|
852
853
|
baseURL: baseUrl,
|
|
854
|
+
timeout: 15e3,
|
|
855
|
+
// 15s timeout for vector DB operations
|
|
853
856
|
headers: __spreadValues({
|
|
854
857
|
"Content-Type": "application/json"
|
|
855
858
|
}, opts.apiKey ? { "api-key": opts.apiKey } : {})
|
|
856
859
|
});
|
|
857
860
|
}
|
|
858
861
|
async initialize() {
|
|
862
|
+
if (this.schemaDiscovered) return;
|
|
859
863
|
await this.ping();
|
|
860
864
|
await this.ensureCollection();
|
|
861
865
|
console.log(`[QdrantProvider] \u{1F50D} Discovering schema for collection "${this.indexName}"...`);
|
|
@@ -865,13 +869,16 @@ var init_QdrantProvider = __esm({
|
|
|
865
869
|
const allFields = [.../* @__PURE__ */ new Set([...discoveredFields, ...configFields])];
|
|
866
870
|
if (allFields.length > 0) {
|
|
867
871
|
console.log(`[QdrantProvider] \u{1F6E0} Ensuring indexes for ${allFields.length} discovered fields...`);
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
+
await Promise.all(
|
|
873
|
+
allFields.map(async (fieldInfo) => {
|
|
874
|
+
const [fieldName, schemaType] = fieldInfo.split(":");
|
|
875
|
+
return this.ensureIndex(fieldName, schemaType || "keyword");
|
|
876
|
+
})
|
|
877
|
+
);
|
|
872
878
|
} else {
|
|
873
879
|
console.log(`[QdrantProvider] \u2139\uFE0F No fields discovered for indexing.`);
|
|
874
880
|
}
|
|
881
|
+
this.schemaDiscovered = true;
|
|
875
882
|
}
|
|
876
883
|
/**
|
|
877
884
|
* Samples points from the collection to discover available payload fields.
|
|
@@ -1932,6 +1939,53 @@ ${context}`
|
|
|
1932
1939
|
});
|
|
1933
1940
|
return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
|
|
1934
1941
|
}
|
|
1942
|
+
chatStream(messages, context, options) {
|
|
1943
|
+
return __asyncGenerator(this, null, function* () {
|
|
1944
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1945
|
+
const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
1946
|
+
|
|
1947
|
+
Context:
|
|
1948
|
+
${context}`;
|
|
1949
|
+
const systemMessage = {
|
|
1950
|
+
role: "system",
|
|
1951
|
+
content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
|
|
1952
|
+
|
|
1953
|
+
Context:
|
|
1954
|
+
${context}`
|
|
1955
|
+
};
|
|
1956
|
+
const formattedMessages = [
|
|
1957
|
+
systemMessage,
|
|
1958
|
+
...messages.map((m) => ({
|
|
1959
|
+
role: m.role,
|
|
1960
|
+
content: m.content
|
|
1961
|
+
}))
|
|
1962
|
+
];
|
|
1963
|
+
const stream = yield new __await(this.client.chat.completions.create({
|
|
1964
|
+
model: this.llmConfig.model,
|
|
1965
|
+
messages: formattedMessages,
|
|
1966
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
1967
|
+
temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
|
|
1968
|
+
stop: options == null ? void 0 : options.stop,
|
|
1969
|
+
stream: true
|
|
1970
|
+
}));
|
|
1971
|
+
try {
|
|
1972
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
1973
|
+
const chunk = temp.value;
|
|
1974
|
+
const content = ((_g = (_f = chunk.choices[0]) == null ? void 0 : _f.delta) == null ? void 0 : _g.content) || "";
|
|
1975
|
+
if (content) yield content;
|
|
1976
|
+
}
|
|
1977
|
+
} catch (temp) {
|
|
1978
|
+
error = [temp];
|
|
1979
|
+
} finally {
|
|
1980
|
+
try {
|
|
1981
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
1982
|
+
} finally {
|
|
1983
|
+
if (error)
|
|
1984
|
+
throw error[0];
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1935
1989
|
async embed(text, options) {
|
|
1936
1990
|
const results = await this.batchEmbed([text], options);
|
|
1937
1991
|
return results[0];
|
|
@@ -2037,6 +2091,47 @@ ${context}`;
|
|
|
2037
2091
|
const block = response.content[0];
|
|
2038
2092
|
return block.type === "text" ? block.text : "";
|
|
2039
2093
|
}
|
|
2094
|
+
chatStream(messages, context, options) {
|
|
2095
|
+
return __asyncGenerator(this, null, function* () {
|
|
2096
|
+
var _a, _b, _c;
|
|
2097
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
|
|
2098
|
+
|
|
2099
|
+
Context:
|
|
2100
|
+
${context}`;
|
|
2101
|
+
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2102
|
+
|
|
2103
|
+
Context:
|
|
2104
|
+
${context}`;
|
|
2105
|
+
const anthropicMessages = messages.map((m) => ({
|
|
2106
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
2107
|
+
content: m.content
|
|
2108
|
+
}));
|
|
2109
|
+
const stream = yield new __await(this.client.messages.create({
|
|
2110
|
+
model: this.llmConfig.model,
|
|
2111
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
2112
|
+
system,
|
|
2113
|
+
messages: anthropicMessages,
|
|
2114
|
+
stream: true
|
|
2115
|
+
}));
|
|
2116
|
+
try {
|
|
2117
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2118
|
+
const chunk = temp.value;
|
|
2119
|
+
if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
|
|
2120
|
+
yield chunk.delta.text;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
} catch (temp) {
|
|
2124
|
+
error = [temp];
|
|
2125
|
+
} finally {
|
|
2126
|
+
try {
|
|
2127
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2128
|
+
} finally {
|
|
2129
|
+
if (error)
|
|
2130
|
+
throw error[0];
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
});
|
|
2134
|
+
}
|
|
2040
2135
|
async embed(text, options) {
|
|
2041
2136
|
void text;
|
|
2042
2137
|
void options;
|
|
@@ -2142,7 +2237,7 @@ var OllamaProvider = class {
|
|
|
2142
2237
|
}
|
|
2143
2238
|
chatStream(messages, context, options) {
|
|
2144
2239
|
return __asyncGenerator(this, null, function* () {
|
|
2145
|
-
var _a, _b, _c, _d, _e;
|
|
2240
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2146
2241
|
const system = this.buildSystemPrompt(context);
|
|
2147
2242
|
const response = yield new __await(this.http.post("/api/chat", {
|
|
2148
2243
|
model: this.llmConfig.model,
|
|
@@ -2156,11 +2251,15 @@ var OllamaProvider = class {
|
|
|
2156
2251
|
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
2157
2252
|
]
|
|
2158
2253
|
}, { responseType: "stream" }));
|
|
2254
|
+
let lineBuffer = "";
|
|
2159
2255
|
try {
|
|
2160
2256
|
for (var iter = __forAwait(response.data), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2161
2257
|
const chunk = temp.value;
|
|
2162
|
-
|
|
2258
|
+
lineBuffer += chunk.toString();
|
|
2259
|
+
const lines = lineBuffer.split("\n");
|
|
2260
|
+
lineBuffer = lines.pop() || "";
|
|
2163
2261
|
for (const line of lines) {
|
|
2262
|
+
if (!line.trim()) continue;
|
|
2164
2263
|
try {
|
|
2165
2264
|
const json = JSON.parse(line);
|
|
2166
2265
|
if ((_e = json.message) == null ? void 0 : _e.content) {
|
|
@@ -2168,6 +2267,7 @@ var OllamaProvider = class {
|
|
|
2168
2267
|
}
|
|
2169
2268
|
if (json.done) return;
|
|
2170
2269
|
} catch (e) {
|
|
2270
|
+
console.warn("[OllamaProvider] Failed to parse streaming line:", line);
|
|
2171
2271
|
}
|
|
2172
2272
|
}
|
|
2173
2273
|
}
|
|
@@ -2181,6 +2281,13 @@ var OllamaProvider = class {
|
|
|
2181
2281
|
throw error[0];
|
|
2182
2282
|
}
|
|
2183
2283
|
}
|
|
2284
|
+
if (lineBuffer.trim()) {
|
|
2285
|
+
try {
|
|
2286
|
+
const json = JSON.parse(lineBuffer);
|
|
2287
|
+
if ((_f = json.message) == null ? void 0 : _f.content) yield json.message.content;
|
|
2288
|
+
} catch (e) {
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2184
2291
|
});
|
|
2185
2292
|
}
|
|
2186
2293
|
buildSystemPrompt(context) {
|
|
@@ -2326,6 +2433,49 @@ ${context}`;
|
|
|
2326
2433
|
});
|
|
2327
2434
|
return (_f = response.text) != null ? _f : "";
|
|
2328
2435
|
}
|
|
2436
|
+
chatStream(messages, context, options) {
|
|
2437
|
+
return __asyncGenerator(this, null, function* () {
|
|
2438
|
+
var _a, _b, _c, _d, _e;
|
|
2439
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
2440
|
+
|
|
2441
|
+
Context:
|
|
2442
|
+
${context}`;
|
|
2443
|
+
const systemInstruction = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2444
|
+
|
|
2445
|
+
Context:
|
|
2446
|
+
${context}`;
|
|
2447
|
+
const geminiMessages = messages.map((m) => ({
|
|
2448
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
2449
|
+
parts: [{ text: m.content }]
|
|
2450
|
+
}));
|
|
2451
|
+
const result = yield new __await(this.client.models.generateContentStream({
|
|
2452
|
+
model: this.llmConfig.model,
|
|
2453
|
+
contents: geminiMessages,
|
|
2454
|
+
config: {
|
|
2455
|
+
systemInstruction,
|
|
2456
|
+
temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
|
|
2457
|
+
maxOutputTokens: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024,
|
|
2458
|
+
stopSequences: options == null ? void 0 : options.stop
|
|
2459
|
+
}
|
|
2460
|
+
}));
|
|
2461
|
+
try {
|
|
2462
|
+
for (var iter = __forAwait(result.stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2463
|
+
const chunk = temp.value;
|
|
2464
|
+
const text = chunk.text;
|
|
2465
|
+
if (text) yield text;
|
|
2466
|
+
}
|
|
2467
|
+
} catch (temp) {
|
|
2468
|
+
error = [temp];
|
|
2469
|
+
} finally {
|
|
2470
|
+
try {
|
|
2471
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2472
|
+
} finally {
|
|
2473
|
+
if (error)
|
|
2474
|
+
throw error[0];
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
});
|
|
2478
|
+
}
|
|
2329
2479
|
async embed(text, options) {
|
|
2330
2480
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
2331
2481
|
const model = this.sanitizeModel(
|
package/dist/handlers/index.mjs
CHANGED
package/dist/server.d.mts
CHANGED
|
@@ -738,6 +738,7 @@ declare class QdrantProvider extends BaseVectorProvider {
|
|
|
738
738
|
private contentField;
|
|
739
739
|
private metadataField;
|
|
740
740
|
private isFlatPayload;
|
|
741
|
+
private schemaDiscovered;
|
|
741
742
|
constructor(config: VectorDBConfig);
|
|
742
743
|
initialize(): Promise<void>;
|
|
743
744
|
/**
|
|
@@ -892,6 +893,7 @@ declare class OpenAIProvider implements ILLMProvider {
|
|
|
892
893
|
static getValidator(): IProviderValidator;
|
|
893
894
|
static getHealthChecker(): IProviderHealthChecker;
|
|
894
895
|
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
896
|
+
chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
895
897
|
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
896
898
|
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
897
899
|
ping(): Promise<boolean>;
|
|
@@ -909,6 +911,7 @@ declare class AnthropicProvider implements ILLMProvider {
|
|
|
909
911
|
static getValidator(): IProviderValidator;
|
|
910
912
|
static getHealthChecker(): IProviderHealthChecker;
|
|
911
913
|
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
914
|
+
chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
912
915
|
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
913
916
|
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
914
917
|
ping(): Promise<boolean>;
|
package/dist/server.d.ts
CHANGED
|
@@ -738,6 +738,7 @@ declare class QdrantProvider extends BaseVectorProvider {
|
|
|
738
738
|
private contentField;
|
|
739
739
|
private metadataField;
|
|
740
740
|
private isFlatPayload;
|
|
741
|
+
private schemaDiscovered;
|
|
741
742
|
constructor(config: VectorDBConfig);
|
|
742
743
|
initialize(): Promise<void>;
|
|
743
744
|
/**
|
|
@@ -892,6 +893,7 @@ declare class OpenAIProvider implements ILLMProvider {
|
|
|
892
893
|
static getValidator(): IProviderValidator;
|
|
893
894
|
static getHealthChecker(): IProviderHealthChecker;
|
|
894
895
|
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
896
|
+
chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
895
897
|
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
896
898
|
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
897
899
|
ping(): Promise<boolean>;
|
|
@@ -909,6 +911,7 @@ declare class AnthropicProvider implements ILLMProvider {
|
|
|
909
911
|
static getValidator(): IProviderValidator;
|
|
910
912
|
static getHealthChecker(): IProviderHealthChecker;
|
|
911
913
|
chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
|
|
914
|
+
chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
|
|
912
915
|
embed(text: string, options?: EmbedOptions): Promise<number[]>;
|
|
913
916
|
batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
914
917
|
ping(): Promise<boolean>;
|
package/dist/server.js
CHANGED
|
@@ -854,6 +854,7 @@ var init_QdrantProvider = __esm({
|
|
|
854
854
|
QdrantProvider = class extends BaseVectorProvider {
|
|
855
855
|
constructor(config) {
|
|
856
856
|
super(config);
|
|
857
|
+
this.schemaDiscovered = false;
|
|
857
858
|
const opts = config.options;
|
|
858
859
|
const baseUrl = opts.baseUrl;
|
|
859
860
|
if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
|
|
@@ -862,12 +863,15 @@ var init_QdrantProvider = __esm({
|
|
|
862
863
|
this.isFlatPayload = !!opts.flatPayload;
|
|
863
864
|
this.http = import_axios4.default.create({
|
|
864
865
|
baseURL: baseUrl,
|
|
866
|
+
timeout: 15e3,
|
|
867
|
+
// 15s timeout for vector DB operations
|
|
865
868
|
headers: __spreadValues({
|
|
866
869
|
"Content-Type": "application/json"
|
|
867
870
|
}, opts.apiKey ? { "api-key": opts.apiKey } : {})
|
|
868
871
|
});
|
|
869
872
|
}
|
|
870
873
|
async initialize() {
|
|
874
|
+
if (this.schemaDiscovered) return;
|
|
871
875
|
await this.ping();
|
|
872
876
|
await this.ensureCollection();
|
|
873
877
|
console.log(`[QdrantProvider] \u{1F50D} Discovering schema for collection "${this.indexName}"...`);
|
|
@@ -877,13 +881,16 @@ var init_QdrantProvider = __esm({
|
|
|
877
881
|
const allFields = [.../* @__PURE__ */ new Set([...discoveredFields, ...configFields])];
|
|
878
882
|
if (allFields.length > 0) {
|
|
879
883
|
console.log(`[QdrantProvider] \u{1F6E0} Ensuring indexes for ${allFields.length} discovered fields...`);
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
+
await Promise.all(
|
|
885
|
+
allFields.map(async (fieldInfo) => {
|
|
886
|
+
const [fieldName, schemaType] = fieldInfo.split(":");
|
|
887
|
+
return this.ensureIndex(fieldName, schemaType || "keyword");
|
|
888
|
+
})
|
|
889
|
+
);
|
|
884
890
|
} else {
|
|
885
891
|
console.log(`[QdrantProvider] \u2139\uFE0F No fields discovered for indexing.`);
|
|
886
892
|
}
|
|
893
|
+
this.schemaDiscovered = true;
|
|
887
894
|
}
|
|
888
895
|
/**
|
|
889
896
|
* Samples points from the collection to discover available payload fields.
|
|
@@ -1980,6 +1987,53 @@ ${context}`
|
|
|
1980
1987
|
});
|
|
1981
1988
|
return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
|
|
1982
1989
|
}
|
|
1990
|
+
chatStream(messages, context, options) {
|
|
1991
|
+
return __asyncGenerator(this, null, function* () {
|
|
1992
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1993
|
+
const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
1994
|
+
|
|
1995
|
+
Context:
|
|
1996
|
+
${context}`;
|
|
1997
|
+
const systemMessage = {
|
|
1998
|
+
role: "system",
|
|
1999
|
+
content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
|
|
2000
|
+
|
|
2001
|
+
Context:
|
|
2002
|
+
${context}`
|
|
2003
|
+
};
|
|
2004
|
+
const formattedMessages = [
|
|
2005
|
+
systemMessage,
|
|
2006
|
+
...messages.map((m) => ({
|
|
2007
|
+
role: m.role,
|
|
2008
|
+
content: m.content
|
|
2009
|
+
}))
|
|
2010
|
+
];
|
|
2011
|
+
const stream = yield new __await(this.client.chat.completions.create({
|
|
2012
|
+
model: this.llmConfig.model,
|
|
2013
|
+
messages: formattedMessages,
|
|
2014
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
2015
|
+
temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
|
|
2016
|
+
stop: options == null ? void 0 : options.stop,
|
|
2017
|
+
stream: true
|
|
2018
|
+
}));
|
|
2019
|
+
try {
|
|
2020
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2021
|
+
const chunk = temp.value;
|
|
2022
|
+
const content = ((_g = (_f = chunk.choices[0]) == null ? void 0 : _f.delta) == null ? void 0 : _g.content) || "";
|
|
2023
|
+
if (content) yield content;
|
|
2024
|
+
}
|
|
2025
|
+
} catch (temp) {
|
|
2026
|
+
error = [temp];
|
|
2027
|
+
} finally {
|
|
2028
|
+
try {
|
|
2029
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2030
|
+
} finally {
|
|
2031
|
+
if (error)
|
|
2032
|
+
throw error[0];
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
1983
2037
|
async embed(text, options) {
|
|
1984
2038
|
const results = await this.batchEmbed([text], options);
|
|
1985
2039
|
return results[0];
|
|
@@ -2085,6 +2139,47 @@ ${context}`;
|
|
|
2085
2139
|
const block = response.content[0];
|
|
2086
2140
|
return block.type === "text" ? block.text : "";
|
|
2087
2141
|
}
|
|
2142
|
+
chatStream(messages, context, options) {
|
|
2143
|
+
return __asyncGenerator(this, null, function* () {
|
|
2144
|
+
var _a, _b, _c;
|
|
2145
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
|
|
2146
|
+
|
|
2147
|
+
Context:
|
|
2148
|
+
${context}`;
|
|
2149
|
+
const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2150
|
+
|
|
2151
|
+
Context:
|
|
2152
|
+
${context}`;
|
|
2153
|
+
const anthropicMessages = messages.map((m) => ({
|
|
2154
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
2155
|
+
content: m.content
|
|
2156
|
+
}));
|
|
2157
|
+
const stream = yield new __await(this.client.messages.create({
|
|
2158
|
+
model: this.llmConfig.model,
|
|
2159
|
+
max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
|
|
2160
|
+
system,
|
|
2161
|
+
messages: anthropicMessages,
|
|
2162
|
+
stream: true
|
|
2163
|
+
}));
|
|
2164
|
+
try {
|
|
2165
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2166
|
+
const chunk = temp.value;
|
|
2167
|
+
if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
|
|
2168
|
+
yield chunk.delta.text;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
} catch (temp) {
|
|
2172
|
+
error = [temp];
|
|
2173
|
+
} finally {
|
|
2174
|
+
try {
|
|
2175
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2176
|
+
} finally {
|
|
2177
|
+
if (error)
|
|
2178
|
+
throw error[0];
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2088
2183
|
async embed(text, options) {
|
|
2089
2184
|
void text;
|
|
2090
2185
|
void options;
|
|
@@ -2190,7 +2285,7 @@ var OllamaProvider = class {
|
|
|
2190
2285
|
}
|
|
2191
2286
|
chatStream(messages, context, options) {
|
|
2192
2287
|
return __asyncGenerator(this, null, function* () {
|
|
2193
|
-
var _a, _b, _c, _d, _e;
|
|
2288
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2194
2289
|
const system = this.buildSystemPrompt(context);
|
|
2195
2290
|
const response = yield new __await(this.http.post("/api/chat", {
|
|
2196
2291
|
model: this.llmConfig.model,
|
|
@@ -2204,11 +2299,15 @@ var OllamaProvider = class {
|
|
|
2204
2299
|
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
2205
2300
|
]
|
|
2206
2301
|
}, { responseType: "stream" }));
|
|
2302
|
+
let lineBuffer = "";
|
|
2207
2303
|
try {
|
|
2208
2304
|
for (var iter = __forAwait(response.data), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2209
2305
|
const chunk = temp.value;
|
|
2210
|
-
|
|
2306
|
+
lineBuffer += chunk.toString();
|
|
2307
|
+
const lines = lineBuffer.split("\n");
|
|
2308
|
+
lineBuffer = lines.pop() || "";
|
|
2211
2309
|
for (const line of lines) {
|
|
2310
|
+
if (!line.trim()) continue;
|
|
2212
2311
|
try {
|
|
2213
2312
|
const json = JSON.parse(line);
|
|
2214
2313
|
if ((_e = json.message) == null ? void 0 : _e.content) {
|
|
@@ -2216,6 +2315,7 @@ var OllamaProvider = class {
|
|
|
2216
2315
|
}
|
|
2217
2316
|
if (json.done) return;
|
|
2218
2317
|
} catch (e) {
|
|
2318
|
+
console.warn("[OllamaProvider] Failed to parse streaming line:", line);
|
|
2219
2319
|
}
|
|
2220
2320
|
}
|
|
2221
2321
|
}
|
|
@@ -2229,6 +2329,13 @@ var OllamaProvider = class {
|
|
|
2229
2329
|
throw error[0];
|
|
2230
2330
|
}
|
|
2231
2331
|
}
|
|
2332
|
+
if (lineBuffer.trim()) {
|
|
2333
|
+
try {
|
|
2334
|
+
const json = JSON.parse(lineBuffer);
|
|
2335
|
+
if ((_f = json.message) == null ? void 0 : _f.content) yield json.message.content;
|
|
2336
|
+
} catch (e) {
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2232
2339
|
});
|
|
2233
2340
|
}
|
|
2234
2341
|
buildSystemPrompt(context) {
|
|
@@ -2374,6 +2481,49 @@ ${context}`;
|
|
|
2374
2481
|
});
|
|
2375
2482
|
return (_f = response.text) != null ? _f : "";
|
|
2376
2483
|
}
|
|
2484
|
+
chatStream(messages, context, options) {
|
|
2485
|
+
return __asyncGenerator(this, null, function* () {
|
|
2486
|
+
var _a, _b, _c, _d, _e;
|
|
2487
|
+
const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
|
|
2488
|
+
|
|
2489
|
+
Context:
|
|
2490
|
+
${context}`;
|
|
2491
|
+
const systemInstruction = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
|
|
2492
|
+
|
|
2493
|
+
Context:
|
|
2494
|
+
${context}`;
|
|
2495
|
+
const geminiMessages = messages.map((m) => ({
|
|
2496
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
2497
|
+
parts: [{ text: m.content }]
|
|
2498
|
+
}));
|
|
2499
|
+
const result = yield new __await(this.client.models.generateContentStream({
|
|
2500
|
+
model: this.llmConfig.model,
|
|
2501
|
+
contents: geminiMessages,
|
|
2502
|
+
config: {
|
|
2503
|
+
systemInstruction,
|
|
2504
|
+
temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
|
|
2505
|
+
maxOutputTokens: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024,
|
|
2506
|
+
stopSequences: options == null ? void 0 : options.stop
|
|
2507
|
+
}
|
|
2508
|
+
}));
|
|
2509
|
+
try {
|
|
2510
|
+
for (var iter = __forAwait(result.stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2511
|
+
const chunk = temp.value;
|
|
2512
|
+
const text = chunk.text;
|
|
2513
|
+
if (text) yield text;
|
|
2514
|
+
}
|
|
2515
|
+
} catch (temp) {
|
|
2516
|
+
error = [temp];
|
|
2517
|
+
} finally {
|
|
2518
|
+
try {
|
|
2519
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
2520
|
+
} finally {
|
|
2521
|
+
if (error)
|
|
2522
|
+
throw error[0];
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2377
2527
|
async embed(text, options) {
|
|
2378
2528
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
2379
2529
|
const model = this.sanitizeModel(
|
package/dist/server.mjs
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
sseFrame,
|
|
41
41
|
sseMetaFrame,
|
|
42
42
|
sseTextFrame
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-JZ4H7EP6.mjs";
|
|
44
44
|
import "./chunk-YLTMFW4M.mjs";
|
|
45
45
|
import {
|
|
46
46
|
PineconeProvider
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
} from "./chunk-U55XRW3U.mjs";
|
|
57
57
|
import {
|
|
58
58
|
QdrantProvider
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-63HITIWC.mjs";
|
|
60
60
|
import {
|
|
61
61
|
BaseVectorProvider
|
|
62
62
|
} from "./chunk-IMP6FUCY.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "MIT",
|
|
@@ -98,6 +98,35 @@ export class AnthropicProvider implements ILLMProvider {
|
|
|
98
98
|
return block.type === 'text' ? block.text : '';
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
async *chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string> {
|
|
102
|
+
const systemPrompt =
|
|
103
|
+
this.llmConfig.systemPrompt ??
|
|
104
|
+
`You are a helpful assistant. Use the context below to answer the user's question accurately.\n\nContext:\n${context}`;
|
|
105
|
+
|
|
106
|
+
const system = systemPrompt.includes('{{context}}')
|
|
107
|
+
? systemPrompt.replace('{{context}}', context)
|
|
108
|
+
: `${systemPrompt}\n\nContext:\n${context}`;
|
|
109
|
+
|
|
110
|
+
const anthropicMessages: Anthropic.MessageParam[] = messages.map((m) => ({
|
|
111
|
+
role: m.role === 'assistant' ? 'assistant' : 'user',
|
|
112
|
+
content: m.content,
|
|
113
|
+
}));
|
|
114
|
+
|
|
115
|
+
const stream = await this.client.messages.create({
|
|
116
|
+
model: this.llmConfig.model,
|
|
117
|
+
max_tokens: options?.maxTokens ?? this.llmConfig.maxTokens ?? 1024,
|
|
118
|
+
system,
|
|
119
|
+
messages: anthropicMessages,
|
|
120
|
+
stream: true,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
for await (const chunk of stream) {
|
|
124
|
+
if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {
|
|
125
|
+
yield chunk.delta.text;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
101
130
|
async embed(text: string, options?: EmbedOptions): Promise<number[]> {
|
|
102
131
|
void text;
|
|
103
132
|
void options;
|
|
@@ -130,6 +130,37 @@ export class GeminiProvider implements ILLMProvider {
|
|
|
130
130
|
return response.text ?? '';
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
async *chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string> {
|
|
134
|
+
const systemPrompt =
|
|
135
|
+
this.llmConfig.systemPrompt ??
|
|
136
|
+
`You are a helpful assistant. Answer questions based on the provided context.\n\nContext:\n${context}`;
|
|
137
|
+
|
|
138
|
+
const systemInstruction = systemPrompt.includes('{{context}}')
|
|
139
|
+
? systemPrompt.replace('{{context}}', context)
|
|
140
|
+
: `${systemPrompt}\n\nContext:\n${context}`;
|
|
141
|
+
|
|
142
|
+
const geminiMessages = messages.map((m) => ({
|
|
143
|
+
role: m.role === 'assistant' ? 'model' : 'user',
|
|
144
|
+
parts: [{ text: m.content }],
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
const result = await this.client.models.generateContentStream({
|
|
148
|
+
model: this.llmConfig.model,
|
|
149
|
+
contents: geminiMessages,
|
|
150
|
+
config: {
|
|
151
|
+
systemInstruction,
|
|
152
|
+
temperature: options?.temperature ?? this.llmConfig.temperature ?? 0.7,
|
|
153
|
+
maxOutputTokens: options?.maxTokens ?? this.llmConfig.maxTokens ?? 1024,
|
|
154
|
+
stopSequences: options?.stop,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
for await (const chunk of result.stream) {
|
|
159
|
+
const text = chunk.text;
|
|
160
|
+
if (text) yield text;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
133
164
|
async embed(text: string, options?: EmbedOptions): Promise<number[]> {
|
|
134
165
|
const model = this.sanitizeModel(
|
|
135
166
|
options?.model ??
|
|
@@ -118,9 +118,16 @@ export class OllamaProvider implements ILLMProvider {
|
|
|
118
118
|
],
|
|
119
119
|
}, { responseType: 'stream' });
|
|
120
120
|
|
|
121
|
+
let lineBuffer = '';
|
|
121
122
|
for await (const chunk of response.data) {
|
|
122
|
-
|
|
123
|
+
lineBuffer += chunk.toString();
|
|
124
|
+
const lines = lineBuffer.split('\n');
|
|
125
|
+
|
|
126
|
+
// Keep the last partial line in the buffer
|
|
127
|
+
lineBuffer = lines.pop() || '';
|
|
128
|
+
|
|
123
129
|
for (const line of lines) {
|
|
130
|
+
if (!line.trim()) continue;
|
|
124
131
|
try {
|
|
125
132
|
const json = JSON.parse(line);
|
|
126
133
|
if (json.message?.content) {
|
|
@@ -128,10 +135,22 @@ export class OllamaProvider implements ILLMProvider {
|
|
|
128
135
|
}
|
|
129
136
|
if (json.done) return;
|
|
130
137
|
} catch {
|
|
131
|
-
//
|
|
138
|
+
// If parsing fails, it might be a malformed line or something else
|
|
139
|
+
// But with line buffering, this should be rare
|
|
140
|
+
console.warn('[OllamaProvider] Failed to parse streaming line:', line);
|
|
132
141
|
}
|
|
133
142
|
}
|
|
134
143
|
}
|
|
144
|
+
|
|
145
|
+
// Process anything left in the buffer at the end
|
|
146
|
+
if (lineBuffer.trim()) {
|
|
147
|
+
try {
|
|
148
|
+
const json = JSON.parse(lineBuffer);
|
|
149
|
+
if (json.message?.content) yield json.message.content;
|
|
150
|
+
} catch {
|
|
151
|
+
// Final cleanup
|
|
152
|
+
}
|
|
153
|
+
}
|
|
135
154
|
}
|
|
136
155
|
|
|
137
156
|
private buildSystemPrompt(context: string): string {
|
|
@@ -108,6 +108,41 @@ export class OpenAIProvider implements ILLMProvider {
|
|
|
108
108
|
|
|
109
109
|
return completion.choices[0]?.message?.content ?? '';
|
|
110
110
|
}
|
|
111
|
+
|
|
112
|
+
async *chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string> {
|
|
113
|
+
const systemContent =
|
|
114
|
+
this.llmConfig.systemPrompt ??
|
|
115
|
+
`You are a helpful assistant. Answer questions based on the provided context.\n\nContext:\n${context}`;
|
|
116
|
+
|
|
117
|
+
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam = {
|
|
118
|
+
role: 'system',
|
|
119
|
+
content: systemContent.includes('{{context}}')
|
|
120
|
+
? systemContent.replace('{{context}}', context)
|
|
121
|
+
: `${systemContent}\n\nContext:\n${context}`,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const formattedMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
|
|
125
|
+
systemMessage,
|
|
126
|
+
...messages.map((m) => ({
|
|
127
|
+
role: m.role as 'user' | 'assistant',
|
|
128
|
+
content: m.content,
|
|
129
|
+
})),
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const stream = await this.client.chat.completions.create({
|
|
133
|
+
model: this.llmConfig.model,
|
|
134
|
+
messages: formattedMessages,
|
|
135
|
+
max_tokens: options?.maxTokens ?? this.llmConfig.maxTokens ?? 1024,
|
|
136
|
+
temperature: options?.temperature ?? this.llmConfig.temperature ?? 0.7,
|
|
137
|
+
stop: options?.stop,
|
|
138
|
+
stream: true,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
for await (const chunk of stream) {
|
|
142
|
+
const content = chunk.choices[0]?.delta?.content || '';
|
|
143
|
+
if (content) yield content;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
111
146
|
|
|
112
147
|
async embed(text: string, options?: EmbedOptions): Promise<number[]> {
|
|
113
148
|
const results = await this.batchEmbed([text], options);
|
|
@@ -13,6 +13,7 @@ export class QdrantProvider extends BaseVectorProvider {
|
|
|
13
13
|
private contentField: string;
|
|
14
14
|
private metadataField: string;
|
|
15
15
|
private isFlatPayload: boolean;
|
|
16
|
+
private schemaDiscovered = false;
|
|
16
17
|
|
|
17
18
|
constructor(config: VectorDBConfig) {
|
|
18
19
|
super(config);
|
|
@@ -26,6 +27,7 @@ export class QdrantProvider extends BaseVectorProvider {
|
|
|
26
27
|
|
|
27
28
|
this.http = axios.create({
|
|
28
29
|
baseURL: baseUrl,
|
|
30
|
+
timeout: 15000, // 15s timeout for vector DB operations
|
|
29
31
|
headers: {
|
|
30
32
|
'Content-Type': 'application/json',
|
|
31
33
|
...(opts.apiKey ? { 'api-key': opts.apiKey as string } : {}),
|
|
@@ -34,6 +36,8 @@ export class QdrantProvider extends BaseVectorProvider {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
async initialize(): Promise<void> {
|
|
39
|
+
if (this.schemaDiscovered) return;
|
|
40
|
+
|
|
37
41
|
await this.ping();
|
|
38
42
|
await this.ensureCollection();
|
|
39
43
|
|
|
@@ -49,13 +53,18 @@ export class QdrantProvider extends BaseVectorProvider {
|
|
|
49
53
|
|
|
50
54
|
if (allFields.length > 0) {
|
|
51
55
|
console.log(`[QdrantProvider] 🛠 Ensuring indexes for ${allFields.length} discovered fields...`);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
// Parallelize index creation for much faster startup
|
|
57
|
+
await Promise.all(
|
|
58
|
+
allFields.map(async (fieldInfo) => {
|
|
59
|
+
const [fieldName, schemaType] = fieldInfo.split(':');
|
|
60
|
+
return this.ensureIndex(fieldName, (schemaType as any) || 'keyword');
|
|
61
|
+
})
|
|
62
|
+
);
|
|
56
63
|
} else {
|
|
57
64
|
console.log(`[QdrantProvider] ℹ️ No fields discovered for indexing.`);
|
|
58
65
|
}
|
|
66
|
+
|
|
67
|
+
this.schemaDiscovered = true;
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
/**
|