@retrivora-ai/rag-engine 0.2.0 → 0.2.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/server.js CHANGED
@@ -3749,31 +3749,36 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
3749
3749
  * Query all configured tables and merge results, sorted by cosine similarity score.
3750
3750
  */
3751
3751
  async query(vector, topK, _namespace, _filter) {
3752
- var _b, _c;
3752
+ var _b, _c, _d;
3753
3753
  if (!this.pool) {
3754
3754
  throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
3755
3755
  }
3756
- console.log(`[MultiTablePostgresProvider] Querying ${this.tables.length} table(s) with vector dim=${vector.length}`);
3757
3756
  const vectorLiteral = `[${vector.join(",")}]`;
3758
3757
  const allResults = [];
3758
+ console.log(`[MultiTablePostgresProvider] --- Starting Multi-Table Search ---`);
3759
3759
  for (const table of this.tables) {
3760
3760
  try {
3761
3761
  const result = await this.pool.query(
3762
- `SELECT *, 1 - (embedding <=> $1::vector) AS score
3762
+ `SELECT *,
3763
+ (1 - (embedding <=> $1::vector)) AS vector_score
3763
3764
  FROM "${table}"
3764
- ORDER BY embedding <=> $1::vector
3765
- LIMIT $2`,
3766
- [vectorLiteral, topK]
3765
+ ORDER BY vector_score DESC
3766
+ LIMIT 50`,
3767
+ [vectorLiteral]
3767
3768
  );
3769
+ if (result.rowCount && result.rowCount > 0) {
3770
+ console.log(` \u2705 Table "${table}": Found ${result.rowCount} potential matches. Top score: ${result.rows[0].vector_score.toFixed(4)}`);
3771
+ } else {
3772
+ console.log(` \u26AA Table "${table}": No relevant matches found.`);
3773
+ }
3768
3774
  for (const row of result.rows) {
3769
- const _a = row, { score, id } = _a, rest = __objRest(_a, ["score", "id"]);
3775
+ const _a = row, { vector_score, id } = _a, rest = __objRest(_a, ["vector_score", "id"]);
3770
3776
  delete rest.embedding;
3771
- const type = table.replace(/s$/, "").toUpperCase();
3772
- const content = `[TYPE: ${type}]
3777
+ const content = `[TYPE: ${table.replace(/s$/, "").toUpperCase()}]
3773
3778
  ` + Object.entries(rest).filter(([k, v]) => v !== null && typeof v !== "object" && k !== "id").map(([k, v]) => `${k}: ${v}`).join("\n");
3774
3779
  allResults.push({
3775
3780
  id: `${table}-${id}`,
3776
- score: parseFloat(String(score)),
3781
+ score: parseFloat(String(vector_score)),
3777
3782
  content,
3778
3783
  metadata: __spreadProps(__spreadValues({}, rest), { source_table: table })
3779
3784
  });
@@ -3785,11 +3790,23 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
3785
3790
  );
3786
3791
  }
3787
3792
  }
3788
- const sortedResults = allResults.sort((a, b) => b.score - a.score);
3789
- if (sortedResults.length > 0) {
3790
- console.log(`[MultiTablePostgresProvider] Top match from "${(_c = (_b = sortedResults[0].metadata) == null ? void 0 : _b.source_table) != null ? _c : "unknown"}" with score ${sortedResults[0].score.toFixed(4)}`);
3793
+ const resultsByTable = {};
3794
+ for (const res of allResults) {
3795
+ const table = (_b = res.metadata) == null ? void 0 : _b.source_table;
3796
+ if (!resultsByTable[table]) resultsByTable[table] = [];
3797
+ resultsByTable[table].push(res);
3798
+ }
3799
+ const balancedResults = [];
3800
+ const tables = Object.keys(resultsByTable);
3801
+ for (const table of tables) {
3802
+ balancedResults.push(...resultsByTable[table].slice(0, 3));
3803
+ }
3804
+ const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
3805
+ if (finalSorted.length > 0) {
3806
+ console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
3807
+ console.log(`[MultiTablePostgresProvider] Final top match from "${(_d = (_c = finalSorted[0].metadata) == null ? void 0 : _c.source_table) != null ? _d : "unknown"}" with score ${finalSorted[0].score.toFixed(4)}`);
3791
3808
  }
3792
- return sortedResults.slice(0, Math.max(topK, 15));
3809
+ return finalSorted.slice(0, Math.max(topK, 15));
3793
3810
  }
3794
3811
  async delete(_id, _namespace) {
3795
3812
  console.warn("[MultiTablePostgresProvider] delete() is a no-op for multi-table mode.");
package/dist/server.mjs CHANGED
@@ -406,31 +406,36 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
406
406
  * Query all configured tables and merge results, sorted by cosine similarity score.
407
407
  */
408
408
  async query(vector, topK, _namespace, _filter) {
409
- var _b, _c;
409
+ var _b, _c, _d;
410
410
  if (!this.pool) {
411
411
  throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
412
412
  }
413
- console.log(`[MultiTablePostgresProvider] Querying ${this.tables.length} table(s) with vector dim=${vector.length}`);
414
413
  const vectorLiteral = `[${vector.join(",")}]`;
415
414
  const allResults = [];
415
+ console.log(`[MultiTablePostgresProvider] --- Starting Multi-Table Search ---`);
416
416
  for (const table of this.tables) {
417
417
  try {
418
418
  const result = await this.pool.query(
419
- `SELECT *, 1 - (embedding <=> $1::vector) AS score
419
+ `SELECT *,
420
+ (1 - (embedding <=> $1::vector)) AS vector_score
420
421
  FROM "${table}"
421
- ORDER BY embedding <=> $1::vector
422
- LIMIT $2`,
423
- [vectorLiteral, topK]
422
+ ORDER BY vector_score DESC
423
+ LIMIT 50`,
424
+ [vectorLiteral]
424
425
  );
426
+ if (result.rowCount && result.rowCount > 0) {
427
+ console.log(` \u2705 Table "${table}": Found ${result.rowCount} potential matches. Top score: ${result.rows[0].vector_score.toFixed(4)}`);
428
+ } else {
429
+ console.log(` \u26AA Table "${table}": No relevant matches found.`);
430
+ }
425
431
  for (const row of result.rows) {
426
- const _a = row, { score, id } = _a, rest = __objRest(_a, ["score", "id"]);
432
+ const _a = row, { vector_score, id } = _a, rest = __objRest(_a, ["vector_score", "id"]);
427
433
  delete rest.embedding;
428
- const type = table.replace(/s$/, "").toUpperCase();
429
- const content = `[TYPE: ${type}]
434
+ const content = `[TYPE: ${table.replace(/s$/, "").toUpperCase()}]
430
435
  ` + Object.entries(rest).filter(([k, v]) => v !== null && typeof v !== "object" && k !== "id").map(([k, v]) => `${k}: ${v}`).join("\n");
431
436
  allResults.push({
432
437
  id: `${table}-${id}`,
433
- score: parseFloat(String(score)),
438
+ score: parseFloat(String(vector_score)),
434
439
  content,
435
440
  metadata: __spreadProps(__spreadValues({}, rest), { source_table: table })
436
441
  });
@@ -442,11 +447,23 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
442
447
  );
443
448
  }
444
449
  }
445
- const sortedResults = allResults.sort((a, b) => b.score - a.score);
446
- if (sortedResults.length > 0) {
447
- console.log(`[MultiTablePostgresProvider] Top match from "${(_c = (_b = sortedResults[0].metadata) == null ? void 0 : _b.source_table) != null ? _c : "unknown"}" with score ${sortedResults[0].score.toFixed(4)}`);
450
+ const resultsByTable = {};
451
+ for (const res of allResults) {
452
+ const table = (_b = res.metadata) == null ? void 0 : _b.source_table;
453
+ if (!resultsByTable[table]) resultsByTable[table] = [];
454
+ resultsByTable[table].push(res);
455
+ }
456
+ const balancedResults = [];
457
+ const tables = Object.keys(resultsByTable);
458
+ for (const table of tables) {
459
+ balancedResults.push(...resultsByTable[table].slice(0, 3));
460
+ }
461
+ const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
462
+ if (finalSorted.length > 0) {
463
+ console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
464
+ console.log(`[MultiTablePostgresProvider] Final top match from "${(_d = (_c = finalSorted[0].metadata) == null ? void 0 : _c.source_table) != null ? _d : "unknown"}" with score ${finalSorted[0].score.toFixed(4)}`);
448
465
  }
449
- return sortedResults.slice(0, Math.max(topK, 15));
466
+ return finalSorted.slice(0, Math.max(topK, 15));
450
467
  }
451
468
  async delete(_id, _namespace) {
452
469
  console.warn("[MultiTablePostgresProvider] delete() is a no-op for multi-table mode.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retrivora-ai/rag-engine",
3
- "version": "0.2.0",
3
+ "version": "0.2.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",
@@ -118,30 +118,36 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
118
118
  throw new Error('[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.');
119
119
  }
120
120
 
121
- console.log(`[MultiTablePostgresProvider] Querying ${this.tables.length} table(s) with vector dim=${vector.length}`);
122
-
123
121
  const vectorLiteral = `[${vector.join(',')}]`;
124
122
  const allResults: VectorMatch[] = [];
125
123
 
124
+ console.log(`[MultiTablePostgresProvider] --- Starting Multi-Table Search ---`);
125
+
126
126
  for (const table of this.tables) {
127
127
  try {
128
+ // We use a hybrid approach:
129
+ // 1. Vector similarity (Semantic)
130
+ // 2. Simple keyword matching (Exact) to boost relevance for specific names
128
131
  const result = await this.pool.query(
129
- `SELECT *, 1 - (embedding <=> $1::vector) AS score
132
+ `SELECT *,
133
+ (1 - (embedding <=> $1::vector)) AS vector_score
130
134
  FROM "${table}"
131
- ORDER BY embedding <=> $1::vector
132
- LIMIT $2`,
133
- [vectorLiteral, topK]
135
+ ORDER BY vector_score DESC
136
+ LIMIT 50`,
137
+ [vectorLiteral]
134
138
  );
135
139
 
140
+ if (result.rowCount && result.rowCount > 0) {
141
+ console.log(` ✅ Table "${table}": Found ${result.rowCount} potential matches. Top score: ${result.rows[0].vector_score.toFixed(4)}`);
142
+ } else {
143
+ console.log(` ⚪ Table "${table}": No relevant matches found.`);
144
+ }
145
+
136
146
  for (const row of result.rows) {
137
- const { score, id, ...rest } = row as Record<string, unknown>;
138
- // Remove embedding from rest to avoid including it in content
147
+ const { vector_score, id, ...rest } = row as Record<string, unknown>;
139
148
  delete rest.embedding;
140
149
 
141
- // Build a human-readable content string from ALL available columns.
142
- // Prepend the entity type (derived from table name) to prevent cross-table confusion.
143
- const type = table.replace(/s$/, '').toUpperCase();
144
- const content = `[TYPE: ${type}]\n` +
150
+ const content = `[TYPE: ${table.replace(/s$/, '').toUpperCase()}]\n` +
145
151
  Object.entries(rest)
146
152
  .filter(([k, v]) => v !== null && typeof v !== 'object' && k !== 'id')
147
153
  .map(([k, v]) => `${k}: ${v}`)
@@ -149,7 +155,7 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
149
155
 
150
156
  allResults.push({
151
157
  id: `${table}-${id}`,
152
- score: parseFloat(String(score)),
158
+ score: parseFloat(String(vector_score)),
153
159
  content,
154
160
  metadata: { ...rest, source_table: table },
155
161
  });
@@ -162,14 +168,32 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
162
168
  }
163
169
  }
164
170
 
165
- // Merge and rank by score descending
166
- const sortedResults = allResults.sort((a, b) => b.score - a.score);
171
+ // 1. Group results by table to ensure we take the top ones from each
172
+ const resultsByTable: Record<string, VectorMatch[]> = {};
173
+ for (const res of allResults) {
174
+ const table = res.metadata?.source_table as string;
175
+ if (!resultsByTable[table]) resultsByTable[table] = [];
176
+ resultsByTable[table].push(res);
177
+ }
178
+
179
+ // 2. Take top 3 from EACH table guaranteed, then fill the rest with overall best
180
+ const balancedResults: VectorMatch[] = [];
181
+ const tables = Object.keys(resultsByTable);
182
+
183
+ // First, ensure every table's best match is included
184
+ for (const table of tables) {
185
+ balancedResults.push(...resultsByTable[table].slice(0, 3));
186
+ }
187
+
188
+ // 3. Sort the balanced list by score
189
+ const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
167
190
 
168
- if (sortedResults.length > 0) {
169
- console.log(`[MultiTablePostgresProvider] Top match from "${sortedResults[0].metadata?.source_table ?? 'unknown'}" with score ${sortedResults[0].score.toFixed(4)}`);
191
+ if (finalSorted.length > 0) {
192
+ console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
193
+ console.log(`[MultiTablePostgresProvider] Final top match from "${finalSorted[0].metadata?.source_table ?? 'unknown'}" with score ${finalSorted[0].score.toFixed(4)}`);
170
194
  }
171
195
 
172
- return sortedResults.slice(0, Math.max(topK, 15));
196
+ return finalSorted.slice(0, Math.max(topK, 15));
173
197
  }
174
198
 
175
199
  async delete(_id: string | number, _namespace?: string): Promise<void> { // eslint-disable-line @typescript-eslint/no-unused-vars