@retrivora-ai/rag-engine 1.1.0 → 1.1.2

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/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-DVovvPmd.mjs';
3
- export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-DVovvPmd.mjs';
2
+ import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-FyMB_UG6.mjs';
3
+ export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-FyMB_UG6.mjs';
4
4
  export { C as Chunk, a as ChunkOptions } from './DocumentChunker-Dh9TvmGG.mjs';
5
5
 
6
6
  interface ChatWidgetProps {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-DVovvPmd.js';
3
- export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-DVovvPmd.js';
2
+ import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-FyMB_UG6.js';
3
+ export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-FyMB_UG6.js';
4
4
  export { C as Chunk, a as ChunkOptions } from './DocumentChunker-Dh9TvmGG.js';
5
5
 
6
6
  interface ChatWidgetProps {
package/dist/server.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { i as VectorDBConfig, L as LLMConfig, c as EmbeddingConfig, g as RagConfig, e as IngestDocument, C as ChatMessage, b as ChatResponse, k as RetrievalResult, h as UpsertDocument, V as VectorMatch, G as GraphDBConfig, l as GraphNode, m as Edge, n as GraphSearchResult, I as ILLMProvider, j as VectorDBProvider, f as LLMProvider, d as EmbeddingProvider, R as RAGConfig, U as UIConfig, a as ChatOptions, E as EmbedOptions } from './RagConfig-DVovvPmd.mjs';
1
+ import { i as VectorDBConfig, L as LLMConfig, c as EmbeddingConfig, g as RagConfig, e as IngestDocument, C as ChatMessage, b as ChatResponse, k as RetrievalResult, h as UpsertDocument, V as VectorMatch, G as GraphDBConfig, l as GraphNode, m as Edge, n as GraphSearchResult, I as ILLMProvider, j as VectorDBProvider, f as LLMProvider, d as EmbeddingProvider, R as RAGConfig, U as UIConfig, a as ChatOptions, E as EmbedOptions } from './RagConfig-FyMB_UG6.mjs';
2
2
  export { C as Chunk, a as ChunkOptions, D as DocumentChunker } from './DocumentChunker-Dh9TvmGG.mjs';
3
- import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-D0_2f-43.mjs';
4
- export { C as ConfigValidator, V as ValidationError, b as VectorPlugin, c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from './index-D0_2f-43.mjs';
3
+ import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-D-lfcqlL.mjs';
4
+ export { C as ConfigValidator, V as ValidationError, b as VectorPlugin, c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from './index-D-lfcqlL.mjs';
5
5
  import 'next/server';
6
6
 
7
7
  /**
@@ -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
  /**
@@ -755,7 +756,7 @@ declare class QdrantProvider extends BaseVectorProvider {
755
756
  upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
756
757
  batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void>;
757
758
  query(vector: number[], topK: number, namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]>;
758
- delete(id: string | number, _namespace?: string): Promise<void>;
759
+ delete(id: string | number): Promise<void>;
759
760
  deleteNamespace(_namespace: string): Promise<void>;
760
761
  ping(): Promise<boolean>;
761
762
  private normalizeId;
@@ -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
@@ -1,7 +1,7 @@
1
- import { i as VectorDBConfig, L as LLMConfig, c as EmbeddingConfig, g as RagConfig, e as IngestDocument, C as ChatMessage, b as ChatResponse, k as RetrievalResult, h as UpsertDocument, V as VectorMatch, G as GraphDBConfig, l as GraphNode, m as Edge, n as GraphSearchResult, I as ILLMProvider, j as VectorDBProvider, f as LLMProvider, d as EmbeddingProvider, R as RAGConfig, U as UIConfig, a as ChatOptions, E as EmbedOptions } from './RagConfig-DVovvPmd.js';
1
+ import { i as VectorDBConfig, L as LLMConfig, c as EmbeddingConfig, g as RagConfig, e as IngestDocument, C as ChatMessage, b as ChatResponse, k as RetrievalResult, h as UpsertDocument, V as VectorMatch, G as GraphDBConfig, l as GraphNode, m as Edge, n as GraphSearchResult, I as ILLMProvider, j as VectorDBProvider, f as LLMProvider, d as EmbeddingProvider, R as RAGConfig, U as UIConfig, a as ChatOptions, E as EmbedOptions } from './RagConfig-FyMB_UG6.js';
2
2
  export { C as Chunk, a as ChunkOptions, D as DocumentChunker } from './DocumentChunker-Dh9TvmGG.js';
3
- import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-CQ0zQ7Zk.js';
4
- export { C as ConfigValidator, V as ValidationError, b as VectorPlugin, c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from './index-CQ0zQ7Zk.js';
3
+ import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-CYgr00ot.js';
4
+ export { C as ConfigValidator, V as ValidationError, b as VectorPlugin, c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from './index-CYgr00ot.js';
5
5
  import 'next/server';
6
6
 
7
7
  /**
@@ -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
  /**
@@ -755,7 +756,7 @@ declare class QdrantProvider extends BaseVectorProvider {
755
756
  upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
756
757
  batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void>;
757
758
  query(vector: number[], topK: number, namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]>;
758
- delete(id: string | number, _namespace?: string): Promise<void>;
759
+ delete(id: string | number): Promise<void>;
759
760
  deleteNamespace(_namespace: string): Promise<void>;
760
761
  ping(): Promise<boolean>;
761
762
  private normalizeId;
@@ -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
- for (const fieldInfo of allFields) {
881
- const [fieldName, schemaType] = fieldInfo.split(":");
882
- await this.ensureIndex(fieldName, schemaType || "keyword");
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.
@@ -1020,7 +1027,7 @@ var init_QdrantProvider = __esm({
1020
1027
  const p = res.payload || {};
1021
1028
  let content = p[this.contentField] || "";
1022
1029
  if (!content) {
1023
- const stringFields = Object.entries(p).filter(([_, v]) => typeof v === "string").map(([k, v]) => ({ key: k, val: v }));
1030
+ const stringFields = Object.entries(p).filter(([, v]) => typeof v === "string").map(([k, v]) => ({ key: k, val: v }));
1024
1031
  if (stringFields.length > 0) {
1025
1032
  const bestMatch = stringFields.sort((a, b) => b.val.length - a.val.length)[0];
1026
1033
  content = bestMatch.val;
@@ -1045,7 +1052,7 @@ var init_QdrantProvider = __esm({
1045
1052
  });
1046
1053
  return results;
1047
1054
  }
1048
- async delete(id, _namespace) {
1055
+ async delete(id) {
1049
1056
  await this.http.post(`/collections/${this.indexName}/points/delete`, {
1050
1057
  points: [this.normalizeId(id)]
1051
1058
  });
@@ -1668,8 +1675,8 @@ var VECTOR_DB_PROVIDERS = [
1668
1675
  "pgvector",
1669
1676
  "postgresql",
1670
1677
  "mongodb",
1671
- "milvus",
1672
1678
  "qdrant",
1679
+ "milvus",
1673
1680
  "chromadb",
1674
1681
  "redis",
1675
1682
  "weaviate",
@@ -1980,6 +1987,56 @@ ${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
+ if (!stream) {
2020
+ throw new Error("[OpenAIProvider] completions.create stream is undefined");
2021
+ }
2022
+ try {
2023
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2024
+ const chunk = temp.value;
2025
+ const content = ((_g = (_f = chunk.choices[0]) == null ? void 0 : _f.delta) == null ? void 0 : _g.content) || "";
2026
+ if (content) yield content;
2027
+ }
2028
+ } catch (temp) {
2029
+ error = [temp];
2030
+ } finally {
2031
+ try {
2032
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2033
+ } finally {
2034
+ if (error)
2035
+ throw error[0];
2036
+ }
2037
+ }
2038
+ });
2039
+ }
1983
2040
  async embed(text, options) {
1984
2041
  const results = await this.batchEmbed([text], options);
1985
2042
  return results[0];
@@ -2085,6 +2142,50 @@ ${context}`;
2085
2142
  const block = response.content[0];
2086
2143
  return block.type === "text" ? block.text : "";
2087
2144
  }
2145
+ chatStream(messages, context, options) {
2146
+ return __asyncGenerator(this, null, function* () {
2147
+ var _a, _b, _c;
2148
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
2149
+
2150
+ Context:
2151
+ ${context}`;
2152
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2153
+
2154
+ Context:
2155
+ ${context}`;
2156
+ const anthropicMessages = messages.map((m) => ({
2157
+ role: m.role === "assistant" ? "assistant" : "user",
2158
+ content: m.content
2159
+ }));
2160
+ const stream = yield new __await(this.client.messages.create({
2161
+ model: this.llmConfig.model,
2162
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
2163
+ system,
2164
+ messages: anthropicMessages,
2165
+ stream: true
2166
+ }));
2167
+ if (!stream) {
2168
+ throw new Error("[AnthropicProvider] messages.create stream is undefined");
2169
+ }
2170
+ try {
2171
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2172
+ const chunk = temp.value;
2173
+ if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
2174
+ yield chunk.delta.text;
2175
+ }
2176
+ }
2177
+ } catch (temp) {
2178
+ error = [temp];
2179
+ } finally {
2180
+ try {
2181
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2182
+ } finally {
2183
+ if (error)
2184
+ throw error[0];
2185
+ }
2186
+ }
2187
+ });
2188
+ }
2088
2189
  async embed(text, options) {
2089
2190
  void text;
2090
2191
  void options;
@@ -2190,7 +2291,7 @@ var OllamaProvider = class {
2190
2291
  }
2191
2292
  chatStream(messages, context, options) {
2192
2293
  return __asyncGenerator(this, null, function* () {
2193
- var _a, _b, _c, _d, _e;
2294
+ var _a, _b, _c, _d, _e, _f;
2194
2295
  const system = this.buildSystemPrompt(context);
2195
2296
  const response = yield new __await(this.http.post("/api/chat", {
2196
2297
  model: this.llmConfig.model,
@@ -2204,11 +2305,19 @@ var OllamaProvider = class {
2204
2305
  ...messages.map((m) => ({ role: m.role, content: m.content }))
2205
2306
  ]
2206
2307
  }, { responseType: "stream" }));
2308
+ let lineBuffer = "";
2309
+ const stream = response.data;
2310
+ if (!stream) {
2311
+ throw new Error("[OllamaProvider] response.data is undefined for stream request. Axios might not support streams in this environment.");
2312
+ }
2207
2313
  try {
2208
- for (var iter = __forAwait(response.data), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2314
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2209
2315
  const chunk = temp.value;
2210
- const lines = chunk.toString().split("\n").filter(Boolean);
2316
+ lineBuffer += chunk.toString();
2317
+ const lines = lineBuffer.split("\n");
2318
+ lineBuffer = lines.pop() || "";
2211
2319
  for (const line of lines) {
2320
+ if (!line.trim()) continue;
2212
2321
  try {
2213
2322
  const json = JSON.parse(line);
2214
2323
  if ((_e = json.message) == null ? void 0 : _e.content) {
@@ -2216,6 +2325,7 @@ var OllamaProvider = class {
2216
2325
  }
2217
2326
  if (json.done) return;
2218
2327
  } catch (e) {
2328
+ console.warn("[OllamaProvider] Failed to parse streaming line:", line);
2219
2329
  }
2220
2330
  }
2221
2331
  }
@@ -2229,6 +2339,13 @@ var OllamaProvider = class {
2229
2339
  throw error[0];
2230
2340
  }
2231
2341
  }
2342
+ if (lineBuffer.trim()) {
2343
+ try {
2344
+ const json = JSON.parse(lineBuffer);
2345
+ if ((_f = json.message) == null ? void 0 : _f.content) yield json.message.content;
2346
+ } catch (e) {
2347
+ }
2348
+ }
2232
2349
  });
2233
2350
  }
2234
2351
  buildSystemPrompt(context) {
@@ -2374,6 +2491,53 @@ ${context}`;
2374
2491
  });
2375
2492
  return (_f = response.text) != null ? _f : "";
2376
2493
  }
2494
+ chatStream(messages, context, options) {
2495
+ return __asyncGenerator(this, null, function* () {
2496
+ var _a, _b, _c, _d, _e, _f;
2497
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
2498
+
2499
+ Context:
2500
+ ${context}`;
2501
+ const systemInstruction = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2502
+
2503
+ Context:
2504
+ ${context}`;
2505
+ const geminiMessages = messages.map((m) => ({
2506
+ role: m.role === "assistant" ? "model" : "user",
2507
+ parts: [{ text: m.content }]
2508
+ }));
2509
+ const result = yield new __await(this.client.models.generateContentStream({
2510
+ model: this.llmConfig.model,
2511
+ contents: geminiMessages,
2512
+ config: {
2513
+ systemInstruction,
2514
+ temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
2515
+ maxOutputTokens: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024,
2516
+ stopSequences: options == null ? void 0 : options.stop
2517
+ }
2518
+ }));
2519
+ const stream = (_f = result == null ? void 0 : result.stream) != null ? _f : result;
2520
+ if (!stream) {
2521
+ throw new Error("[GeminiProvider] generateContentStream returned undefined");
2522
+ }
2523
+ try {
2524
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2525
+ const chunk = temp.value;
2526
+ const text = chunk.text;
2527
+ if (text) yield text;
2528
+ }
2529
+ } catch (temp) {
2530
+ error = [temp];
2531
+ } finally {
2532
+ try {
2533
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2534
+ } finally {
2535
+ if (error)
2536
+ throw error[0];
2537
+ }
2538
+ }
2539
+ });
2540
+ }
2377
2541
  async embed(text, options) {
2378
2542
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2379
2543
  const model = this.sanitizeModel(
@@ -3947,8 +4111,12 @@ ${context}`;
3947
4111
  }
3948
4112
  const messages = [...history, { role: "user", content: question }];
3949
4113
  if (this.llmProvider.chatStream) {
4114
+ const stream = this.llmProvider.chatStream(messages, context);
4115
+ if (!stream) {
4116
+ throw new Error(`[Pipeline] ${this.config.llm.provider} chatStream returned undefined`);
4117
+ }
3950
4118
  try {
3951
- for (var iter = __forAwait(this.llmProvider.chatStream(messages, context)), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
4119
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3952
4120
  const chunk = temp.value;
3953
4121
  yield chunk;
3954
4122
  }
package/dist/server.mjs CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  sseFrame,
41
41
  sseMetaFrame,
42
42
  sseTextFrame
43
- } from "./chunk-G2LVK46T.mjs";
43
+ } from "./chunk-XEWWAHCM.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-65S4BQL2.mjs";
59
+ } from "./chunk-PSFPZXHX.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.0",
3
+ "version": "1.1.2",
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",
@@ -39,18 +39,18 @@ export const VECTOR_DATABASES: ProviderPill[] = [
39
39
  { Icon: Zap, label: 'Pinecone' },
40
40
  { Icon: Database, label: 'PostgreSQL' },
41
41
  { Icon: Layers, label: 'MongoDB' },
42
- { Icon: Search, label: 'Milvus' },
43
42
  { Icon: Box, label: 'Qdrant' },
43
+ { Icon: Search, label: 'Milvus' },
44
44
  { Icon: Package, label: 'ChromaDB' },
45
45
  { Icon: Activity, label: 'Redis' },
46
46
  { Icon: Hexagon, label: 'Weaviate' },
47
47
  ];
48
48
 
49
49
  export const AI_MODELS: ProviderPill[] = [
50
+ { Icon: Rabbit, label: 'Ollama' },
50
51
  { Icon: Sparkles, label: 'OpenAI' },
51
52
  { Icon: Bot, label: 'Anthropic' },
52
53
  { Icon: Brain, label: 'Gemini' },
53
- { Icon: Rabbit, label: 'Ollama' },
54
54
  { Icon: Code, label: 'Copilot' },
55
55
  { Icon: Terminal, label: 'LiteLLM' },
56
56
  ];
@@ -10,8 +10,8 @@ export const VECTOR_DB_PROVIDERS = [
10
10
  'pgvector',
11
11
  'postgresql',
12
12
  'mongodb',
13
- 'milvus',
14
13
  'qdrant',
14
+ 'milvus',
15
15
  'chromadb',
16
16
  'redis',
17
17
  'weaviate',
@@ -350,7 +350,11 @@ export class Pipeline {
350
350
  const messages: ChatMessage[] = [...history, { role: 'user', content: question }];
351
351
 
352
352
  if (this.llmProvider.chatStream) {
353
- for await (const chunk of this.llmProvider.chatStream(messages, context)) {
353
+ const stream = this.llmProvider.chatStream(messages, context);
354
+ if (!stream) {
355
+ throw new Error(`[Pipeline] ${this.config.llm.provider} chatStream returned undefined`);
356
+ }
357
+ for await (const chunk of stream) {
354
358
  yield chunk;
355
359
  }
356
360
  } else {
@@ -98,6 +98,39 @@ 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
+ if (!stream) {
124
+ throw new Error('[AnthropicProvider] messages.create stream is undefined');
125
+ }
126
+
127
+ for await (const chunk of stream) {
128
+ if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {
129
+ yield chunk.delta.text;
130
+ }
131
+ }
132
+ }
133
+
101
134
  async embed(text: string, options?: EmbedOptions): Promise<number[]> {
102
135
  void text;
103
136
  void options;
@@ -130,6 +130,42 @@ 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
+ const stream = ((result as unknown as Record<string, unknown>)?.stream ?? result) as AsyncIterable<{ text?: string }>;
159
+ if (!stream) {
160
+ throw new Error('[GeminiProvider] generateContentStream returned undefined');
161
+ }
162
+
163
+ for await (const chunk of stream) {
164
+ const text = chunk.text;
165
+ if (text) yield text;
166
+ }
167
+ }
168
+
133
169
  async embed(text: string, options?: EmbedOptions): Promise<number[]> {
134
170
  const model = this.sanitizeModel(
135
171
  options?.model ??
@@ -118,9 +118,21 @@ export class OllamaProvider implements ILLMProvider {
118
118
  ],
119
119
  }, { responseType: 'stream' });
120
120
 
121
- for await (const chunk of response.data) {
122
- const lines = chunk.toString().split('\n').filter(Boolean);
121
+ let lineBuffer = '';
122
+ const stream = response.data;
123
+ if (!stream) {
124
+ throw new Error('[OllamaProvider] response.data is undefined for stream request. Axios might not support streams in this environment.');
125
+ }
126
+
127
+ for await (const chunk of stream) {
128
+ lineBuffer += chunk.toString();
129
+ const lines = lineBuffer.split('\n');
130
+
131
+ // Keep the last partial line in the buffer
132
+ lineBuffer = lines.pop() || '';
133
+
123
134
  for (const line of lines) {
135
+ if (!line.trim()) continue;
124
136
  try {
125
137
  const json = JSON.parse(line);
126
138
  if (json.message?.content) {
@@ -128,10 +140,22 @@ export class OllamaProvider implements ILLMProvider {
128
140
  }
129
141
  if (json.done) return;
130
142
  } catch {
131
- // Ignore parsing errors for partial lines
143
+ // If parsing fails, it might be a malformed line or something else
144
+ // But with line buffering, this should be rare
145
+ console.warn('[OllamaProvider] Failed to parse streaming line:', line);
132
146
  }
133
147
  }
134
148
  }
149
+
150
+ // Process anything left in the buffer at the end
151
+ if (lineBuffer.trim()) {
152
+ try {
153
+ const json = JSON.parse(lineBuffer);
154
+ if (json.message?.content) yield json.message.content;
155
+ } catch {
156
+ // Final cleanup
157
+ }
158
+ }
135
159
  }
136
160
 
137
161
  private buildSystemPrompt(context: string): string {
@@ -108,6 +108,45 @@ 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
+ if (!stream) {
142
+ throw new Error('[OpenAIProvider] completions.create stream is undefined');
143
+ }
144
+
145
+ for await (const chunk of stream) {
146
+ const content = chunk.choices[0]?.delta?.content || '';
147
+ if (content) yield content;
148
+ }
149
+ }
111
150
 
112
151
  async embed(text: string, options?: EmbedOptions): Promise<number[]> {
113
152
  const results = await this.batchEmbed([text], options);