@retrivora-ai/rag-engine 0.2.4 → 0.2.6
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.d.mts +1 -2
- package/dist/server.d.ts +1 -2
- package/dist/server.js +17 -8
- package/dist/server.mjs +17 -8
- package/package.json +1 -1
- package/src/providers/vectordb/MultiTablePostgresProvider.ts +23 -8
package/dist/server.d.mts
CHANGED
|
@@ -720,8 +720,7 @@ declare class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
720
720
|
/**
|
|
721
721
|
* Query all configured tables and merge results, sorted by cosine similarity score.
|
|
722
722
|
*/
|
|
723
|
-
query(vector: number[], topK: number, _namespace?: string,
|
|
724
|
-
_filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
|
723
|
+
query(vector: number[], topK: number, _namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
|
725
724
|
delete(_id: string | number, _namespace?: string): Promise<void>;
|
|
726
725
|
deleteNamespace(_namespace: string): Promise<void>;
|
|
727
726
|
ping(): Promise<boolean>;
|
package/dist/server.d.ts
CHANGED
|
@@ -720,8 +720,7 @@ declare class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
720
720
|
/**
|
|
721
721
|
* Query all configured tables and merge results, sorted by cosine similarity score.
|
|
722
722
|
*/
|
|
723
|
-
query(vector: number[], topK: number, _namespace?: string,
|
|
724
|
-
_filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
|
723
|
+
query(vector: number[], topK: number, _namespace?: string, _filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
|
725
724
|
delete(_id: string | number, _namespace?: string): Promise<void>;
|
|
726
725
|
deleteNamespace(_namespace: string): Promise<void>;
|
|
727
726
|
ping(): Promise<boolean>;
|
package/dist/server.js
CHANGED
|
@@ -3763,7 +3763,7 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
3763
3763
|
* Query all configured tables and merge results, sorted by cosine similarity score.
|
|
3764
3764
|
*/
|
|
3765
3765
|
async query(vector, topK, _namespace, _filter) {
|
|
3766
|
-
var _b, _c
|
|
3766
|
+
var _a, _b, _c;
|
|
3767
3767
|
if (!this.pool) {
|
|
3768
3768
|
throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
|
|
3769
3769
|
}
|
|
@@ -3771,7 +3771,7 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
3771
3771
|
const allResults = [];
|
|
3772
3772
|
console.log(`[MultiTablePostgresProvider] --- Starting Multi-Table Search ---`);
|
|
3773
3773
|
const queryText = _filter == null ? void 0 : _filter.__queryText;
|
|
3774
|
-
|
|
3774
|
+
const queryPromises = this.tables.map(async (table) => {
|
|
3775
3775
|
try {
|
|
3776
3776
|
let sqlQuery = "";
|
|
3777
3777
|
let params = [];
|
|
@@ -3779,8 +3779,8 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
3779
3779
|
sqlQuery = `
|
|
3780
3780
|
SELECT *,
|
|
3781
3781
|
(1 - (embedding <=> $1::vector)) AS vector_score,
|
|
3782
|
-
ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) AS keyword_score,
|
|
3783
|
-
((1 - (embedding <=> $1::vector)) + (ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) * 2.0)) AS hybrid_score
|
|
3782
|
+
COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) AS keyword_score,
|
|
3783
|
+
((1 - (embedding <=> $1::vector)) + (COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) * 2.0)) AS hybrid_score
|
|
3784
3784
|
FROM "${table}" t
|
|
3785
3785
|
ORDER BY hybrid_score DESC
|
|
3786
3786
|
LIMIT 50
|
|
@@ -3802,28 +3802,37 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
3802
3802
|
} else {
|
|
3803
3803
|
console.log(` \u26AA Table "${table}": No relevant matches found.`);
|
|
3804
3804
|
}
|
|
3805
|
+
const tableResults = [];
|
|
3805
3806
|
for (const row of result.rows) {
|
|
3806
|
-
const
|
|
3807
|
+
const _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
|
|
3807
3808
|
delete rest.embedding;
|
|
3809
|
+
delete rest.vector_score;
|
|
3810
|
+
delete rest.keyword_score;
|
|
3808
3811
|
const content = `[TYPE: ${table.replace(/s$/, "").toUpperCase()}]
|
|
3809
3812
|
` + Object.entries(rest).filter(([k, v]) => v !== null && typeof v !== "object" && k !== "id").map(([k, v]) => `${k}: ${v}`).join("\n");
|
|
3810
|
-
|
|
3813
|
+
tableResults.push({
|
|
3811
3814
|
id: `${table}-${id}`,
|
|
3812
3815
|
score: parseFloat(String(hybrid_score)),
|
|
3813
3816
|
content,
|
|
3814
3817
|
metadata: __spreadProps(__spreadValues({}, rest), { source_table: table })
|
|
3815
3818
|
});
|
|
3816
3819
|
}
|
|
3820
|
+
return tableResults;
|
|
3817
3821
|
} catch (err) {
|
|
3818
3822
|
console.error(
|
|
3819
3823
|
`[MultiTablePostgresProvider] Error querying table "${table}":`,
|
|
3820
3824
|
err.message
|
|
3821
3825
|
);
|
|
3826
|
+
return [];
|
|
3822
3827
|
}
|
|
3828
|
+
});
|
|
3829
|
+
const resultsArray = await Promise.all(queryPromises);
|
|
3830
|
+
for (const tableResults of resultsArray) {
|
|
3831
|
+
allResults.push(...tableResults);
|
|
3823
3832
|
}
|
|
3824
3833
|
const resultsByTable = {};
|
|
3825
3834
|
for (const res of allResults) {
|
|
3826
|
-
const table = (
|
|
3835
|
+
const table = (_a = res.metadata) == null ? void 0 : _a.source_table;
|
|
3827
3836
|
if (!resultsByTable[table]) resultsByTable[table] = [];
|
|
3828
3837
|
resultsByTable[table].push(res);
|
|
3829
3838
|
}
|
|
@@ -3835,7 +3844,7 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
3835
3844
|
const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
|
|
3836
3845
|
if (finalSorted.length > 0) {
|
|
3837
3846
|
console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
|
|
3838
|
-
console.log(`[MultiTablePostgresProvider] Final top match from "${(
|
|
3847
|
+
console.log(`[MultiTablePostgresProvider] Final top match from "${(_c = (_b = finalSorted[0].metadata) == null ? void 0 : _b.source_table) != null ? _c : "unknown"}" with score ${finalSorted[0].score.toFixed(4)}`);
|
|
3839
3848
|
}
|
|
3840
3849
|
return finalSorted.slice(0, Math.max(topK, 15));
|
|
3841
3850
|
}
|
package/dist/server.mjs
CHANGED
|
@@ -406,7 +406,7 @@ 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 _a, _b, _c;
|
|
410
410
|
if (!this.pool) {
|
|
411
411
|
throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
|
|
412
412
|
}
|
|
@@ -414,7 +414,7 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
414
414
|
const allResults = [];
|
|
415
415
|
console.log(`[MultiTablePostgresProvider] --- Starting Multi-Table Search ---`);
|
|
416
416
|
const queryText = _filter == null ? void 0 : _filter.__queryText;
|
|
417
|
-
|
|
417
|
+
const queryPromises = this.tables.map(async (table) => {
|
|
418
418
|
try {
|
|
419
419
|
let sqlQuery = "";
|
|
420
420
|
let params = [];
|
|
@@ -422,8 +422,8 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
422
422
|
sqlQuery = `
|
|
423
423
|
SELECT *,
|
|
424
424
|
(1 - (embedding <=> $1::vector)) AS vector_score,
|
|
425
|
-
ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) AS keyword_score,
|
|
426
|
-
((1 - (embedding <=> $1::vector)) + (ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) * 2.0)) AS hybrid_score
|
|
425
|
+
COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) AS keyword_score,
|
|
426
|
+
((1 - (embedding <=> $1::vector)) + (COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) * 2.0)) AS hybrid_score
|
|
427
427
|
FROM "${table}" t
|
|
428
428
|
ORDER BY hybrid_score DESC
|
|
429
429
|
LIMIT 50
|
|
@@ -445,28 +445,37 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
445
445
|
} else {
|
|
446
446
|
console.log(` \u26AA Table "${table}": No relevant matches found.`);
|
|
447
447
|
}
|
|
448
|
+
const tableResults = [];
|
|
448
449
|
for (const row of result.rows) {
|
|
449
|
-
const
|
|
450
|
+
const _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
|
|
450
451
|
delete rest.embedding;
|
|
452
|
+
delete rest.vector_score;
|
|
453
|
+
delete rest.keyword_score;
|
|
451
454
|
const content = `[TYPE: ${table.replace(/s$/, "").toUpperCase()}]
|
|
452
455
|
` + Object.entries(rest).filter(([k, v]) => v !== null && typeof v !== "object" && k !== "id").map(([k, v]) => `${k}: ${v}`).join("\n");
|
|
453
|
-
|
|
456
|
+
tableResults.push({
|
|
454
457
|
id: `${table}-${id}`,
|
|
455
458
|
score: parseFloat(String(hybrid_score)),
|
|
456
459
|
content,
|
|
457
460
|
metadata: __spreadProps(__spreadValues({}, rest), { source_table: table })
|
|
458
461
|
});
|
|
459
462
|
}
|
|
463
|
+
return tableResults;
|
|
460
464
|
} catch (err) {
|
|
461
465
|
console.error(
|
|
462
466
|
`[MultiTablePostgresProvider] Error querying table "${table}":`,
|
|
463
467
|
err.message
|
|
464
468
|
);
|
|
469
|
+
return [];
|
|
465
470
|
}
|
|
471
|
+
});
|
|
472
|
+
const resultsArray = await Promise.all(queryPromises);
|
|
473
|
+
for (const tableResults of resultsArray) {
|
|
474
|
+
allResults.push(...tableResults);
|
|
466
475
|
}
|
|
467
476
|
const resultsByTable = {};
|
|
468
477
|
for (const res of allResults) {
|
|
469
|
-
const table = (
|
|
478
|
+
const table = (_a = res.metadata) == null ? void 0 : _a.source_table;
|
|
470
479
|
if (!resultsByTable[table]) resultsByTable[table] = [];
|
|
471
480
|
resultsByTable[table].push(res);
|
|
472
481
|
}
|
|
@@ -478,7 +487,7 @@ var MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
|
478
487
|
const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
|
|
479
488
|
if (finalSorted.length > 0) {
|
|
480
489
|
console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
|
|
481
|
-
console.log(`[MultiTablePostgresProvider] Final top match from "${(
|
|
490
|
+
console.log(`[MultiTablePostgresProvider] Final top match from "${(_c = (_b = finalSorted[0].metadata) == null ? void 0 : _b.source_table) != null ? _c : "unknown"}" with score ${finalSorted[0].score.toFixed(4)}`);
|
|
482
491
|
}
|
|
483
492
|
return finalSorted.slice(0, Math.max(topK, 15));
|
|
484
493
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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",
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
import { Pool, PoolClient } from 'pg';
|
|
2
5
|
import { BaseVectorProvider } from './BaseVectorProvider';
|
|
3
6
|
import { VectorMatch, UpsertDocument } from '../../types';
|
|
@@ -111,8 +114,8 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
111
114
|
async query(
|
|
112
115
|
vector: number[],
|
|
113
116
|
topK: number,
|
|
114
|
-
_namespace?: string,
|
|
115
|
-
_filter?: Record<string, unknown>
|
|
117
|
+
_namespace?: string,
|
|
118
|
+
_filter?: Record<string, unknown>
|
|
116
119
|
): Promise<VectorMatch[]> {
|
|
117
120
|
if (!this.pool) {
|
|
118
121
|
throw new Error('[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.');
|
|
@@ -125,18 +128,20 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
125
128
|
|
|
126
129
|
const queryText = _filter?.__queryText as string | undefined;
|
|
127
130
|
|
|
128
|
-
|
|
131
|
+
const queryPromises = this.tables.map(async (table) => {
|
|
129
132
|
try {
|
|
130
133
|
let sqlQuery = '';
|
|
131
|
-
let params:
|
|
134
|
+
let params: unknown[] = [];
|
|
132
135
|
|
|
133
136
|
if (queryText) {
|
|
134
137
|
// Actual Hybrid Search: Semantic Vector Score + Full-Text Keyword Rank
|
|
138
|
+
// We convert plainto_tsquery's AND (&) operator to OR (|) so that natural language queries
|
|
139
|
+
// (which contain words like "price", "product" not found in the row text) still match entities like "Router".
|
|
135
140
|
sqlQuery = `
|
|
136
141
|
SELECT *,
|
|
137
142
|
(1 - (embedding <=> $1::vector)) AS vector_score,
|
|
138
|
-
ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) AS keyword_score,
|
|
139
|
-
((1 - (embedding <=> $1::vector)) + (ts_rank(to_tsvector('english', t.*::text), plainto_tsquery('english', $2)) * 2.0)) AS hybrid_score
|
|
143
|
+
COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) AS keyword_score,
|
|
144
|
+
((1 - (embedding <=> $1::vector)) + (COALESCE(ts_rank(to_tsvector('english', t.*::text), NULLIF(REPLACE(plainto_tsquery('english', $2)::text, '&', '|'), '')::tsquery), 0) * 2.0)) AS hybrid_score
|
|
140
145
|
FROM "${table}" t
|
|
141
146
|
ORDER BY hybrid_score DESC
|
|
142
147
|
LIMIT 50
|
|
@@ -162,9 +167,12 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
162
167
|
console.log(` ⚪ Table "${table}": No relevant matches found.`);
|
|
163
168
|
}
|
|
164
169
|
|
|
170
|
+
const tableResults: VectorMatch[] = [];
|
|
165
171
|
for (const row of result.rows) {
|
|
166
|
-
const { hybrid_score,
|
|
172
|
+
const { hybrid_score, id, ...rest } = row as Record<string, unknown>;
|
|
167
173
|
delete rest.embedding;
|
|
174
|
+
delete rest.vector_score;
|
|
175
|
+
delete rest.keyword_score;
|
|
168
176
|
|
|
169
177
|
const content = `[TYPE: ${table.replace(/s$/, '').toUpperCase()}]\n` +
|
|
170
178
|
Object.entries(rest)
|
|
@@ -172,19 +180,26 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
|
|
|
172
180
|
.map(([k, v]) => `${k}: ${v}`)
|
|
173
181
|
.join('\n');
|
|
174
182
|
|
|
175
|
-
|
|
183
|
+
tableResults.push({
|
|
176
184
|
id: `${table}-${id}`,
|
|
177
185
|
score: parseFloat(String(hybrid_score)),
|
|
178
186
|
content,
|
|
179
187
|
metadata: { ...rest, source_table: table },
|
|
180
188
|
});
|
|
181
189
|
}
|
|
190
|
+
return tableResults;
|
|
182
191
|
} catch (err) {
|
|
183
192
|
console.error(
|
|
184
193
|
`[MultiTablePostgresProvider] Error querying table "${table}":`,
|
|
185
194
|
(err as Error).message
|
|
186
195
|
);
|
|
196
|
+
return [];
|
|
187
197
|
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const resultsArray = await Promise.all(queryPromises);
|
|
201
|
+
for (const tableResults of resultsArray) {
|
|
202
|
+
allResults.push(...tableResults);
|
|
188
203
|
}
|
|
189
204
|
|
|
190
205
|
// 1. Group results by table to ensure we take the top ones from each
|