@retrivora-ai/rag-engine 1.0.5 → 1.0.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/{RagConfig-BEmz4hVP.d.mts → RagConfig-BjC6zSTV.d.mts} +4 -0
- package/dist/{RagConfig-BEmz4hVP.d.ts → RagConfig-BjC6zSTV.d.ts} +4 -0
- package/dist/{chunk-MWL4AGQI.mjs → chunk-ZCDJSGUW.mjs} +48 -6
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +48 -6
- package/dist/handlers/index.mjs +1 -1
- package/dist/{index-CSfaCeux.d.ts → index-C3bLmWcR.d.ts} +1 -1
- package/dist/{index-DFSy0CG6.d.mts → index-CU_fQq__.d.mts} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +48 -6
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/config/RagConfig.ts +4 -0
- package/src/core/Pipeline.ts +1 -1
- package/src/core/QueryProcessor.ts +36 -4
|
@@ -244,6 +244,10 @@ interface RAGConfig {
|
|
|
244
244
|
useGraphRetrieval?: boolean;
|
|
245
245
|
/** Whether to perform reranking on retrieved results */
|
|
246
246
|
useReranking?: boolean;
|
|
247
|
+
/** List of metadata fields that are valid for filtering.
|
|
248
|
+
* Used to dynamically extract hints from natural language queries.
|
|
249
|
+
*/
|
|
250
|
+
filterableFields?: string[];
|
|
247
251
|
}
|
|
248
252
|
interface RagConfig {
|
|
249
253
|
/**
|
|
@@ -244,6 +244,10 @@ interface RAGConfig {
|
|
|
244
244
|
useGraphRetrieval?: boolean;
|
|
245
245
|
/** Whether to perform reranking on retrieved results */
|
|
246
246
|
useReranking?: boolean;
|
|
247
|
+
/** List of metadata fields that are valid for filtering.
|
|
248
|
+
* Used to dynamically extract hints from natural language queries.
|
|
249
|
+
*/
|
|
250
|
+
filterableFields?: string[];
|
|
247
251
|
}
|
|
248
252
|
interface RagConfig {
|
|
249
253
|
/**
|
|
@@ -1904,15 +1904,18 @@ var QueryProcessor = class {
|
|
|
1904
1904
|
* Checks if a string is likely a question word or common prompt phrase.
|
|
1905
1905
|
*/
|
|
1906
1906
|
static isLikelyPromptPhrase(value) {
|
|
1907
|
-
return /^(what|which|who|where|when|why|how)\b/i.test(value.trim());
|
|
1907
|
+
return /^(what|which|who|where|when|why|how|the|is|are|was|were|in|on|at|by|for|with|about|a|an|to|of)\b/i.test(value.trim());
|
|
1908
1908
|
}
|
|
1909
1909
|
/**
|
|
1910
1910
|
* Scans a natural language question for potential metadata hints and keywords.
|
|
1911
|
+
* @param question The user's query
|
|
1912
|
+
* @param validFields Optional list of known filterable fields to look for
|
|
1911
1913
|
*/
|
|
1912
|
-
static extractQueryFieldHints(question) {
|
|
1914
|
+
static extractQueryFieldHints(question, validFields = []) {
|
|
1913
1915
|
var _a, _b, _c, _d;
|
|
1914
1916
|
if (!question.trim()) return [];
|
|
1915
1917
|
const hints = /* @__PURE__ */ new Map();
|
|
1918
|
+
const fieldsToSearch = [.../* @__PURE__ */ new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
|
|
1916
1919
|
const addHint = (value, field) => {
|
|
1917
1920
|
const normalizedValue = this.normalizeHintValue(value);
|
|
1918
1921
|
if (!normalizedValue) return;
|
|
@@ -1943,11 +1946,28 @@ var QueryProcessor = class {
|
|
|
1943
1946
|
if (name) addHint(name, "name");
|
|
1944
1947
|
}
|
|
1945
1948
|
}
|
|
1949
|
+
if (fieldsToSearch.length > 0) {
|
|
1950
|
+
for (const field of fieldsToSearch) {
|
|
1951
|
+
const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, "gi");
|
|
1952
|
+
for (const match of question.matchAll(forwardPattern)) {
|
|
1953
|
+
const value = match[1];
|
|
1954
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
1955
|
+
addHint(value, field);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, "gi");
|
|
1959
|
+
for (const match of question.matchAll(reversePattern)) {
|
|
1960
|
+
const value = match[1];
|
|
1961
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
1962
|
+
addHint(value, field);
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1946
1967
|
const universalPatterns = [
|
|
1947
1968
|
{ regex: /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/gi, field: "email", group: 1 },
|
|
1948
1969
|
{ regex: /(\+?\d[\d\-\.\s\(\)]{6,}\d)/g, field: "phone", group: 1 },
|
|
1949
1970
|
{ regex: /(\b\d{4}-\d{2}-\d{2}\b|\b\d{1,2}\/\d{1,2}\/\d{2,4}\b)/g, field: "date", group: 1 },
|
|
1950
|
-
{ regex: /(\$\s?\d{1,3}(?:,\d{3})*(?:\.\d+)?)/g, field: "amount", group: 1 },
|
|
1951
1971
|
{ regex: /\b(ID|id|identifier)[: ]\s*([A-Za-z0-9\-]{3,})\b/gi, field: "id", group: 2 },
|
|
1952
1972
|
{ regex: /"([^"]{2,120})"/g, group: 1 },
|
|
1953
1973
|
{ regex: /'([^']{2,120})'/g, group: 1 }
|
|
@@ -2012,6 +2032,28 @@ var QueryProcessor = class {
|
|
|
2012
2032
|
return filter;
|
|
2013
2033
|
}
|
|
2014
2034
|
};
|
|
2035
|
+
QueryProcessor.COMMON_METADATA_FIELDS = [
|
|
2036
|
+
"category",
|
|
2037
|
+
"type",
|
|
2038
|
+
"brand",
|
|
2039
|
+
"status",
|
|
2040
|
+
"priority",
|
|
2041
|
+
"id",
|
|
2042
|
+
"name",
|
|
2043
|
+
"email",
|
|
2044
|
+
"phone",
|
|
2045
|
+
"price",
|
|
2046
|
+
"rating",
|
|
2047
|
+
"color",
|
|
2048
|
+
"size",
|
|
2049
|
+
"material",
|
|
2050
|
+
"sku",
|
|
2051
|
+
"role",
|
|
2052
|
+
"department",
|
|
2053
|
+
"location",
|
|
2054
|
+
"tag",
|
|
2055
|
+
"label"
|
|
2056
|
+
];
|
|
2015
2057
|
|
|
2016
2058
|
// src/core/Pipeline.ts
|
|
2017
2059
|
var LRUEmbeddingCache = class {
|
|
@@ -2241,7 +2283,7 @@ var Pipeline = class {
|
|
|
2241
2283
|
*/
|
|
2242
2284
|
askStream(_0) {
|
|
2243
2285
|
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
2244
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2286
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2245
2287
|
yield new __await(this.initialize());
|
|
2246
2288
|
const ns = namespace != null ? namespace : this.config.projectId;
|
|
2247
2289
|
const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
|
|
@@ -2251,7 +2293,7 @@ var Pipeline = class {
|
|
|
2251
2293
|
if ((_e = this.config.rag) == null ? void 0 : _e.useQueryTransformation) {
|
|
2252
2294
|
searchQuery = yield new __await(this.rewriteQuery(question, history));
|
|
2253
2295
|
}
|
|
2254
|
-
const hints = QueryProcessor.extractQueryFieldHints(question);
|
|
2296
|
+
const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
|
|
2255
2297
|
const filter = QueryProcessor.buildQueryFilter(question, hints);
|
|
2256
2298
|
const { sources: rawSources, graphData } = yield new __await(this.retrieve(searchQuery, {
|
|
2257
2299
|
namespace: ns,
|
|
@@ -2259,7 +2301,7 @@ var Pipeline = class {
|
|
|
2259
2301
|
filter
|
|
2260
2302
|
}));
|
|
2261
2303
|
let sources = rawSources.filter((m) => m.score >= scoreThreshold);
|
|
2262
|
-
if ((
|
|
2304
|
+
if ((_g = this.config.rag) == null ? void 0 : _g.useReranking) {
|
|
2263
2305
|
sources = yield new __await(this.reranker.rerank(sources, question, topK));
|
|
2264
2306
|
} else {
|
|
2265
2307
|
sources = sources.slice(0, topK);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../RagConfig-
|
|
2
|
-
export { 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-
|
|
1
|
+
import '../RagConfig-BjC6zSTV.mjs';
|
|
2
|
+
export { 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-CU_fQq__.mjs';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../RagConfig-
|
|
2
|
-
export { 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-
|
|
1
|
+
import '../RagConfig-BjC6zSTV.js';
|
|
2
|
+
export { 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-C3bLmWcR.js';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.js
CHANGED
|
@@ -3362,15 +3362,18 @@ var QueryProcessor = class {
|
|
|
3362
3362
|
* Checks if a string is likely a question word or common prompt phrase.
|
|
3363
3363
|
*/
|
|
3364
3364
|
static isLikelyPromptPhrase(value) {
|
|
3365
|
-
return /^(what|which|who|where|when|why|how)\b/i.test(value.trim());
|
|
3365
|
+
return /^(what|which|who|where|when|why|how|the|is|are|was|were|in|on|at|by|for|with|about|a|an|to|of)\b/i.test(value.trim());
|
|
3366
3366
|
}
|
|
3367
3367
|
/**
|
|
3368
3368
|
* Scans a natural language question for potential metadata hints and keywords.
|
|
3369
|
+
* @param question The user's query
|
|
3370
|
+
* @param validFields Optional list of known filterable fields to look for
|
|
3369
3371
|
*/
|
|
3370
|
-
static extractQueryFieldHints(question) {
|
|
3372
|
+
static extractQueryFieldHints(question, validFields = []) {
|
|
3371
3373
|
var _a, _b, _c, _d;
|
|
3372
3374
|
if (!question.trim()) return [];
|
|
3373
3375
|
const hints = /* @__PURE__ */ new Map();
|
|
3376
|
+
const fieldsToSearch = [.../* @__PURE__ */ new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
|
|
3374
3377
|
const addHint = (value, field) => {
|
|
3375
3378
|
const normalizedValue = this.normalizeHintValue(value);
|
|
3376
3379
|
if (!normalizedValue) return;
|
|
@@ -3401,11 +3404,28 @@ var QueryProcessor = class {
|
|
|
3401
3404
|
if (name) addHint(name, "name");
|
|
3402
3405
|
}
|
|
3403
3406
|
}
|
|
3407
|
+
if (fieldsToSearch.length > 0) {
|
|
3408
|
+
for (const field of fieldsToSearch) {
|
|
3409
|
+
const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, "gi");
|
|
3410
|
+
for (const match of question.matchAll(forwardPattern)) {
|
|
3411
|
+
const value = match[1];
|
|
3412
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
3413
|
+
addHint(value, field);
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, "gi");
|
|
3417
|
+
for (const match of question.matchAll(reversePattern)) {
|
|
3418
|
+
const value = match[1];
|
|
3419
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
3420
|
+
addHint(value, field);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3404
3425
|
const universalPatterns = [
|
|
3405
3426
|
{ regex: /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/gi, field: "email", group: 1 },
|
|
3406
3427
|
{ regex: /(\+?\d[\d\-\.\s\(\)]{6,}\d)/g, field: "phone", group: 1 },
|
|
3407
3428
|
{ regex: /(\b\d{4}-\d{2}-\d{2}\b|\b\d{1,2}\/\d{1,2}\/\d{2,4}\b)/g, field: "date", group: 1 },
|
|
3408
|
-
{ regex: /(\$\s?\d{1,3}(?:,\d{3})*(?:\.\d+)?)/g, field: "amount", group: 1 },
|
|
3409
3429
|
{ regex: /\b(ID|id|identifier)[: ]\s*([A-Za-z0-9\-]{3,})\b/gi, field: "id", group: 2 },
|
|
3410
3430
|
{ regex: /"([^"]{2,120})"/g, group: 1 },
|
|
3411
3431
|
{ regex: /'([^']{2,120})'/g, group: 1 }
|
|
@@ -3470,6 +3490,28 @@ var QueryProcessor = class {
|
|
|
3470
3490
|
return filter;
|
|
3471
3491
|
}
|
|
3472
3492
|
};
|
|
3493
|
+
QueryProcessor.COMMON_METADATA_FIELDS = [
|
|
3494
|
+
"category",
|
|
3495
|
+
"type",
|
|
3496
|
+
"brand",
|
|
3497
|
+
"status",
|
|
3498
|
+
"priority",
|
|
3499
|
+
"id",
|
|
3500
|
+
"name",
|
|
3501
|
+
"email",
|
|
3502
|
+
"phone",
|
|
3503
|
+
"price",
|
|
3504
|
+
"rating",
|
|
3505
|
+
"color",
|
|
3506
|
+
"size",
|
|
3507
|
+
"material",
|
|
3508
|
+
"sku",
|
|
3509
|
+
"role",
|
|
3510
|
+
"department",
|
|
3511
|
+
"location",
|
|
3512
|
+
"tag",
|
|
3513
|
+
"label"
|
|
3514
|
+
];
|
|
3473
3515
|
|
|
3474
3516
|
// src/core/Pipeline.ts
|
|
3475
3517
|
var LRUEmbeddingCache = class {
|
|
@@ -3699,7 +3741,7 @@ var Pipeline = class {
|
|
|
3699
3741
|
*/
|
|
3700
3742
|
askStream(_0) {
|
|
3701
3743
|
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
3702
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3744
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3703
3745
|
yield new __await(this.initialize());
|
|
3704
3746
|
const ns = namespace != null ? namespace : this.config.projectId;
|
|
3705
3747
|
const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
|
|
@@ -3709,7 +3751,7 @@ var Pipeline = class {
|
|
|
3709
3751
|
if ((_e = this.config.rag) == null ? void 0 : _e.useQueryTransformation) {
|
|
3710
3752
|
searchQuery = yield new __await(this.rewriteQuery(question, history));
|
|
3711
3753
|
}
|
|
3712
|
-
const hints = QueryProcessor.extractQueryFieldHints(question);
|
|
3754
|
+
const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
|
|
3713
3755
|
const filter = QueryProcessor.buildQueryFilter(question, hints);
|
|
3714
3756
|
const { sources: rawSources, graphData } = yield new __await(this.retrieve(searchQuery, {
|
|
3715
3757
|
namespace: ns,
|
|
@@ -3717,7 +3759,7 @@ var Pipeline = class {
|
|
|
3717
3759
|
filter
|
|
3718
3760
|
}));
|
|
3719
3761
|
let sources = rawSources.filter((m) => m.score >= scoreThreshold);
|
|
3720
|
-
if ((
|
|
3762
|
+
if ((_g = this.config.rag) == null ? void 0 : _g.useReranking) {
|
|
3721
3763
|
sources = yield new __await(this.reranker.rerank(sources, question, topK));
|
|
3722
3764
|
} else {
|
|
3723
3765
|
sources = sources.slice(0, topK);
|
package/dist/handlers/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-
|
|
1
|
+
import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-BjC6zSTV.js';
|
|
2
2
|
import { NextRequest, NextResponse } from 'next/server';
|
|
3
3
|
|
|
4
4
|
interface ValidationError {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-
|
|
1
|
+
import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-BjC6zSTV.mjs';
|
|
2
2
|
import { NextRequest, NextResponse } from 'next/server';
|
|
3
3
|
|
|
4
4
|
interface ValidationError {
|
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-
|
|
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-
|
|
2
|
+
import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-BjC6zSTV.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-BjC6zSTV.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-
|
|
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-
|
|
2
|
+
import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-BjC6zSTV.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-BjC6zSTV.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-
|
|
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-BjC6zSTV.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-
|
|
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-
|
|
3
|
+
import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-CU_fQq__.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-CU_fQq__.mjs';
|
|
5
5
|
import 'next/server';
|
|
6
6
|
|
|
7
7
|
/**
|
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-
|
|
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-BjC6zSTV.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-
|
|
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-
|
|
3
|
+
import { H as HealthCheckResult, I as IProviderValidator, a as IProviderHealthChecker } from './index-C3bLmWcR.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-C3bLmWcR.js';
|
|
5
5
|
import 'next/server';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/server.js
CHANGED
|
@@ -3455,15 +3455,18 @@ var QueryProcessor = class {
|
|
|
3455
3455
|
* Checks if a string is likely a question word or common prompt phrase.
|
|
3456
3456
|
*/
|
|
3457
3457
|
static isLikelyPromptPhrase(value) {
|
|
3458
|
-
return /^(what|which|who|where|when|why|how)\b/i.test(value.trim());
|
|
3458
|
+
return /^(what|which|who|where|when|why|how|the|is|are|was|were|in|on|at|by|for|with|about|a|an|to|of)\b/i.test(value.trim());
|
|
3459
3459
|
}
|
|
3460
3460
|
/**
|
|
3461
3461
|
* Scans a natural language question for potential metadata hints and keywords.
|
|
3462
|
+
* @param question The user's query
|
|
3463
|
+
* @param validFields Optional list of known filterable fields to look for
|
|
3462
3464
|
*/
|
|
3463
|
-
static extractQueryFieldHints(question) {
|
|
3465
|
+
static extractQueryFieldHints(question, validFields = []) {
|
|
3464
3466
|
var _a, _b, _c, _d;
|
|
3465
3467
|
if (!question.trim()) return [];
|
|
3466
3468
|
const hints = /* @__PURE__ */ new Map();
|
|
3469
|
+
const fieldsToSearch = [.../* @__PURE__ */ new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
|
|
3467
3470
|
const addHint = (value, field) => {
|
|
3468
3471
|
const normalizedValue = this.normalizeHintValue(value);
|
|
3469
3472
|
if (!normalizedValue) return;
|
|
@@ -3494,11 +3497,28 @@ var QueryProcessor = class {
|
|
|
3494
3497
|
if (name) addHint(name, "name");
|
|
3495
3498
|
}
|
|
3496
3499
|
}
|
|
3500
|
+
if (fieldsToSearch.length > 0) {
|
|
3501
|
+
for (const field of fieldsToSearch) {
|
|
3502
|
+
const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, "gi");
|
|
3503
|
+
for (const match of question.matchAll(forwardPattern)) {
|
|
3504
|
+
const value = match[1];
|
|
3505
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
3506
|
+
addHint(value, field);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, "gi");
|
|
3510
|
+
for (const match of question.matchAll(reversePattern)) {
|
|
3511
|
+
const value = match[1];
|
|
3512
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
3513
|
+
addHint(value, field);
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3497
3518
|
const universalPatterns = [
|
|
3498
3519
|
{ regex: /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/gi, field: "email", group: 1 },
|
|
3499
3520
|
{ regex: /(\+?\d[\d\-\.\s\(\)]{6,}\d)/g, field: "phone", group: 1 },
|
|
3500
3521
|
{ regex: /(\b\d{4}-\d{2}-\d{2}\b|\b\d{1,2}\/\d{1,2}\/\d{2,4}\b)/g, field: "date", group: 1 },
|
|
3501
|
-
{ regex: /(\$\s?\d{1,3}(?:,\d{3})*(?:\.\d+)?)/g, field: "amount", group: 1 },
|
|
3502
3522
|
{ regex: /\b(ID|id|identifier)[: ]\s*([A-Za-z0-9\-]{3,})\b/gi, field: "id", group: 2 },
|
|
3503
3523
|
{ regex: /"([^"]{2,120})"/g, group: 1 },
|
|
3504
3524
|
{ regex: /'([^']{2,120})'/g, group: 1 }
|
|
@@ -3563,6 +3583,28 @@ var QueryProcessor = class {
|
|
|
3563
3583
|
return filter;
|
|
3564
3584
|
}
|
|
3565
3585
|
};
|
|
3586
|
+
QueryProcessor.COMMON_METADATA_FIELDS = [
|
|
3587
|
+
"category",
|
|
3588
|
+
"type",
|
|
3589
|
+
"brand",
|
|
3590
|
+
"status",
|
|
3591
|
+
"priority",
|
|
3592
|
+
"id",
|
|
3593
|
+
"name",
|
|
3594
|
+
"email",
|
|
3595
|
+
"phone",
|
|
3596
|
+
"price",
|
|
3597
|
+
"rating",
|
|
3598
|
+
"color",
|
|
3599
|
+
"size",
|
|
3600
|
+
"material",
|
|
3601
|
+
"sku",
|
|
3602
|
+
"role",
|
|
3603
|
+
"department",
|
|
3604
|
+
"location",
|
|
3605
|
+
"tag",
|
|
3606
|
+
"label"
|
|
3607
|
+
];
|
|
3566
3608
|
|
|
3567
3609
|
// src/core/Pipeline.ts
|
|
3568
3610
|
var LRUEmbeddingCache = class {
|
|
@@ -3792,7 +3834,7 @@ var Pipeline = class {
|
|
|
3792
3834
|
*/
|
|
3793
3835
|
askStream(_0) {
|
|
3794
3836
|
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
3795
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3837
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3796
3838
|
yield new __await(this.initialize());
|
|
3797
3839
|
const ns = namespace != null ? namespace : this.config.projectId;
|
|
3798
3840
|
const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
|
|
@@ -3802,7 +3844,7 @@ var Pipeline = class {
|
|
|
3802
3844
|
if ((_e = this.config.rag) == null ? void 0 : _e.useQueryTransformation) {
|
|
3803
3845
|
searchQuery = yield new __await(this.rewriteQuery(question, history));
|
|
3804
3846
|
}
|
|
3805
|
-
const hints = QueryProcessor.extractQueryFieldHints(question);
|
|
3847
|
+
const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
|
|
3806
3848
|
const filter = QueryProcessor.buildQueryFilter(question, hints);
|
|
3807
3849
|
const { sources: rawSources, graphData } = yield new __await(this.retrieve(searchQuery, {
|
|
3808
3850
|
namespace: ns,
|
|
@@ -3810,7 +3852,7 @@ var Pipeline = class {
|
|
|
3810
3852
|
filter
|
|
3811
3853
|
}));
|
|
3812
3854
|
let sources = rawSources.filter((m) => m.score >= scoreThreshold);
|
|
3813
|
-
if ((
|
|
3855
|
+
if ((_g = this.config.rag) == null ? void 0 : _g.useReranking) {
|
|
3814
3856
|
sources = yield new __await(this.reranker.rerank(sources, question, topK));
|
|
3815
3857
|
} else {
|
|
3816
3858
|
sources = sources.slice(0, topK);
|
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.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",
|
package/src/config/RagConfig.ts
CHANGED
|
@@ -174,6 +174,10 @@ export interface RAGConfig {
|
|
|
174
174
|
useGraphRetrieval?: boolean;
|
|
175
175
|
/** Whether to perform reranking on retrieved results */
|
|
176
176
|
useReranking?: boolean;
|
|
177
|
+
/** List of metadata fields that are valid for filtering.
|
|
178
|
+
* Used to dynamically extract hints from natural language queries.
|
|
179
|
+
*/
|
|
180
|
+
filterableFields?: string[];
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
// ---------------------------------------------------------------------------
|
package/src/core/Pipeline.ts
CHANGED
|
@@ -315,7 +315,7 @@ export class Pipeline {
|
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
// 2. Parallel Retrieval
|
|
318
|
-
const hints = QueryProcessor.extractQueryFieldHints(question);
|
|
318
|
+
const hints = QueryProcessor.extractQueryFieldHints(question, this.config.rag?.filterableFields);
|
|
319
319
|
const filter = QueryProcessor.buildQueryFilter(question, hints);
|
|
320
320
|
|
|
321
321
|
const { sources: rawSources, graphData } = await this.retrieve(searchQuery, {
|
|
@@ -31,16 +31,25 @@ export class QueryProcessor {
|
|
|
31
31
|
* Checks if a string is likely a question word or common prompt phrase.
|
|
32
32
|
*/
|
|
33
33
|
static isLikelyPromptPhrase(value: string): boolean {
|
|
34
|
-
return /^(what|which|who|where|when|why|how)\b/i.test(value.trim());
|
|
34
|
+
return /^(what|which|who|where|when|why|how|the|is|are|was|were|in|on|at|by|for|with|about|a|an|to|of)\b/i.test(value.trim());
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
private static readonly COMMON_METADATA_FIELDS = [
|
|
38
|
+
'category', 'type', 'brand', 'status', 'priority', 'id', 'name',
|
|
39
|
+
'email', 'phone', 'price', 'rating', 'color', 'size', 'material',
|
|
40
|
+
'sku', 'role', 'department', 'location', 'tag', 'label'
|
|
41
|
+
];
|
|
42
|
+
|
|
37
43
|
/**
|
|
38
44
|
* Scans a natural language question for potential metadata hints and keywords.
|
|
45
|
+
* @param question The user's query
|
|
46
|
+
* @param validFields Optional list of known filterable fields to look for
|
|
39
47
|
*/
|
|
40
|
-
static extractQueryFieldHints(question: string): QueryFieldHint[] {
|
|
48
|
+
static extractQueryFieldHints(question: string, validFields: string[] = []): QueryFieldHint[] {
|
|
41
49
|
if (!question.trim()) return [];
|
|
42
50
|
|
|
43
51
|
const hints = new Map<string, QueryFieldHint>();
|
|
52
|
+
const fieldsToSearch = [...new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
|
|
44
53
|
|
|
45
54
|
const addHint = (value: string, field?: string) => {
|
|
46
55
|
const normalizedValue = this.normalizeHintValue(value);
|
|
@@ -88,12 +97,35 @@ export class QueryProcessor {
|
|
|
88
97
|
}
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
// 4.
|
|
100
|
+
// 4. Dynamic Schema-driven patterns
|
|
101
|
+
// We look for common metadata fields (and any user-defined ones) in natural language.
|
|
102
|
+
if (fieldsToSearch.length > 0) {
|
|
103
|
+
for (const field of fieldsToSearch) {
|
|
104
|
+
// Pattern 1: "[field] is [value]", "[field]: [value]", "[field] of [value]"
|
|
105
|
+
const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, 'gi');
|
|
106
|
+
for (const match of question.matchAll(forwardPattern)) {
|
|
107
|
+
const value = match[1];
|
|
108
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
109
|
+
addHint(value, field);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Pattern 2: "[value] [field]" (e.g. "blue color", "electronics category")
|
|
114
|
+
const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, 'gi');
|
|
115
|
+
for (const match of question.matchAll(reversePattern)) {
|
|
116
|
+
const value = match[1];
|
|
117
|
+
if (value && !this.isLikelyPromptPhrase(value)) {
|
|
118
|
+
addHint(value, field);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 5. Universal patterns (email, phone, etc.)
|
|
92
125
|
const universalPatterns: Array<{ regex: RegExp; field?: string; group?: number }> = [
|
|
93
126
|
{ regex: /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/gi, field: 'email', group: 1 },
|
|
94
127
|
{ regex: /(\+?\d[\d\-\.\s\(\)]{6,}\d)/g, field: 'phone', group: 1 },
|
|
95
128
|
{ regex: /(\b\d{4}-\d{2}-\d{2}\b|\b\d{1,2}\/\d{1,2}\/\d{2,4}\b)/g, field: 'date', group: 1 },
|
|
96
|
-
{ regex: /(\$\s?\d{1,3}(?:,\d{3})*(?:\.\d+)?)/g, field: 'amount', group: 1 },
|
|
97
129
|
{ regex: /\b(ID|id|identifier)[: ]\s*([A-Za-z0-9\-]{3,})\b/gi, field: 'id', group: 2 },
|
|
98
130
|
{ regex: /"([^"]{2,120})"/g, group: 1 },
|
|
99
131
|
{ regex: /'([^']{2,120})'/g, group: 1 },
|