@retrivora-ai/rag-engine 1.9.1 → 1.9.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/{ILLMProvider-BQyKZLnd.d.mts → ILLMProvider-Bw2A28nU.d.mts} +2 -0
- package/dist/{ILLMProvider-BQyKZLnd.d.ts → ILLMProvider-Bw2A28nU.d.ts} +2 -0
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +183 -103
- package/dist/handlers/index.mjs +183 -103
- package/dist/{index-CDftK3qs.d.mts → index-B70ZLkfG.d.mts} +1 -1
- package/dist/{index-A0GqPsaG.d.ts → index-DVu-mkAM.d.ts} +1 -1
- package/dist/index.css +57 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +90 -36
- package/dist/index.mjs +91 -37
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +183 -103
- package/dist/server.mjs +183 -103
- package/package.json +1 -1
- package/src/components/ChatWindow.tsx +24 -14
- package/src/components/MessageBubble.tsx +41 -6
- package/src/components/ProductCard.tsx +4 -4
- package/src/core/Pipeline.ts +52 -25
- package/src/core/QueryProcessor.ts +10 -9
- package/src/handlers/index.ts +31 -8
- package/src/hooks/useRagChat.ts +24 -0
- package/src/providers/vectordb/MultiTablePostgresProvider.ts +36 -4
- package/src/types/chat.ts +2 -0
- package/src/utils/SchemaMapper.ts +6 -4
- package/src/utils/UITransformer.ts +2 -1
- package/src/utils/synonyms.ts +5 -5
package/dist/server.js
CHANGED
|
@@ -540,6 +540,82 @@ var init_PostgreSQLProvider = __esm({
|
|
|
540
540
|
}
|
|
541
541
|
});
|
|
542
542
|
|
|
543
|
+
// src/utils/synonyms.ts
|
|
544
|
+
function resolveMetadataValue(meta, uiKey) {
|
|
545
|
+
var _a;
|
|
546
|
+
const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
|
|
547
|
+
const keys = Object.keys(meta);
|
|
548
|
+
const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
|
|
549
|
+
let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
|
|
550
|
+
if (match !== void 0) return meta[match];
|
|
551
|
+
match = keys.find((k) => synonyms.map((s) => s.toLowerCase()).includes(k.toLowerCase()));
|
|
552
|
+
if (match !== void 0) return meta[match];
|
|
553
|
+
const isBlacklisted = (kl) => {
|
|
554
|
+
return systemKeys.includes(kl) || kl.startsWith("option1") || kl.startsWith("option2") || kl.startsWith("option3");
|
|
555
|
+
};
|
|
556
|
+
match = keys.find((k) => {
|
|
557
|
+
const kl = k.toLowerCase();
|
|
558
|
+
if (isBlacklisted(kl)) return false;
|
|
559
|
+
return kl.includes(uiKey.toLowerCase());
|
|
560
|
+
});
|
|
561
|
+
if (match !== void 0) return meta[match];
|
|
562
|
+
match = keys.find((k) => {
|
|
563
|
+
const kl = k.toLowerCase();
|
|
564
|
+
if (isBlacklisted(kl)) return false;
|
|
565
|
+
return synonyms.some((sk) => kl.includes(sk.toLowerCase()) || sk.toLowerCase().includes(kl));
|
|
566
|
+
});
|
|
567
|
+
return match !== void 0 ? meta[match] : void 0;
|
|
568
|
+
}
|
|
569
|
+
var FIELD_SYNONYMS;
|
|
570
|
+
var init_synonyms = __esm({
|
|
571
|
+
"src/utils/synonyms.ts"() {
|
|
572
|
+
"use strict";
|
|
573
|
+
FIELD_SYNONYMS = {
|
|
574
|
+
name: ["product", "item", "title", "label", "heading", "subject", "product name", "item name"],
|
|
575
|
+
price: ["cost", "amount", "msrp", "price", "rate", "value", "price_usd", "variant price"],
|
|
576
|
+
brand: ["manufacturer", "vendor", "make", "company", "brand_name", "supplier"],
|
|
577
|
+
image: [
|
|
578
|
+
"imageUrl",
|
|
579
|
+
"thumbnail",
|
|
580
|
+
"img",
|
|
581
|
+
"url",
|
|
582
|
+
"photo",
|
|
583
|
+
"picture",
|
|
584
|
+
"media",
|
|
585
|
+
"image_url",
|
|
586
|
+
"main_image",
|
|
587
|
+
"product_image",
|
|
588
|
+
"thumb",
|
|
589
|
+
"image src",
|
|
590
|
+
"variant image"
|
|
591
|
+
],
|
|
592
|
+
stock: [
|
|
593
|
+
"inventory",
|
|
594
|
+
"quantity",
|
|
595
|
+
"count",
|
|
596
|
+
"availability",
|
|
597
|
+
"stock_level",
|
|
598
|
+
"inStock",
|
|
599
|
+
"is_available",
|
|
600
|
+
"in stock",
|
|
601
|
+
"status",
|
|
602
|
+
"variant inventory qty"
|
|
603
|
+
],
|
|
604
|
+
category: [
|
|
605
|
+
"product_category",
|
|
606
|
+
"product category",
|
|
607
|
+
"category_name",
|
|
608
|
+
"category name",
|
|
609
|
+
"department",
|
|
610
|
+
"collection",
|
|
611
|
+
"type"
|
|
612
|
+
],
|
|
613
|
+
description: ["summary", "content", "body", "text", "info", "details", "body (html)", "seo description"],
|
|
614
|
+
link: ["url", "href", "product_url", "page_url", "link"]
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
|
|
543
619
|
// src/providers/vectordb/MultiTablePostgresProvider.ts
|
|
544
620
|
var MultiTablePostgresProvider_exports = {};
|
|
545
621
|
__export(MultiTablePostgresProvider_exports, {
|
|
@@ -551,6 +627,7 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
551
627
|
"use strict";
|
|
552
628
|
import_pg2 = require("pg");
|
|
553
629
|
init_BaseVectorProvider();
|
|
630
|
+
init_synonyms();
|
|
554
631
|
MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
555
632
|
constructor(config) {
|
|
556
633
|
var _a, _b, _c;
|
|
@@ -631,8 +708,13 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
631
708
|
}
|
|
632
709
|
tableName = tableName.replace(/[^a-z0-9_]/gi, "_").toLowerCase() || this.uploadTable;
|
|
633
710
|
const firstMeta = fileDocs[0].metadata || {};
|
|
634
|
-
|
|
635
|
-
|
|
711
|
+
let csvHeaders = [];
|
|
712
|
+
if (Array.isArray(firstMeta.csvHeaders)) {
|
|
713
|
+
csvHeaders = firstMeta.csvHeaders;
|
|
714
|
+
} else {
|
|
715
|
+
const systemKeys = ["fileName", "fileSize", "fileType", "uploadedAt", "dimension", "chunkIndex", "id", "namespace", "content", "metadata", "embedding", "docId", "docid", "chunkId", "chunkid", "csvHeaders", "csvheaders"];
|
|
716
|
+
csvHeaders = Object.keys(firstMeta).filter((k) => !systemKeys.includes(k) && !systemKeys.includes(k.toLowerCase()));
|
|
717
|
+
}
|
|
636
718
|
const columnDefs = csvHeaders.map((h) => `"${h}" TEXT`).join(",\n ");
|
|
637
719
|
const createTableSql = `
|
|
638
720
|
CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
@@ -725,10 +807,26 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
725
807
|
};
|
|
726
808
|
const dynamicKeywordQuery = getDynamicKeywordQuery();
|
|
727
809
|
const tableLimit = Math.max(topK, 50);
|
|
810
|
+
const metadataFilters = _filter == null ? void 0 : _filter.metadata;
|
|
728
811
|
const queryPromises = this.tables.map(async (table) => {
|
|
729
812
|
try {
|
|
730
813
|
let sqlQuery = "";
|
|
731
814
|
let params = [];
|
|
815
|
+
let whereClause = "";
|
|
816
|
+
const filterParams = [];
|
|
817
|
+
if (metadataFilters && Object.keys(metadataFilters).length > 0) {
|
|
818
|
+
const conditions = Object.entries(metadataFilters).map(([key, val]) => {
|
|
819
|
+
var _a3;
|
|
820
|
+
filterParams.push(String(val));
|
|
821
|
+
const baseOffset = queryText && dynamicKeywordQuery ? 2 : 1;
|
|
822
|
+
const paramIdx = baseOffset + filterParams.length;
|
|
823
|
+
const synonyms = (_a3 = FIELD_SYNONYMS[key]) != null ? _a3 : [];
|
|
824
|
+
const keysToCheck = [key, ...synonyms];
|
|
825
|
+
const coalesceExprs = keysToCheck.map((k) => `LOWER(metadata->>'${k}')`);
|
|
826
|
+
return `COALESCE(${coalesceExprs.join(", ")}) = LOWER($${paramIdx})`;
|
|
827
|
+
});
|
|
828
|
+
whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
829
|
+
}
|
|
732
830
|
if (queryText && dynamicKeywordQuery) {
|
|
733
831
|
const hasEntityHints = entityHints.length > 0;
|
|
734
832
|
const exactNameScoreExpr = hasEntityHints ? `+ (
|
|
@@ -745,19 +843,21 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
745
843
|
COALESCE(ts_rank(to_tsvector('english', (to_jsonb(t) - 'embedding')::text), to_tsquery('english', $2)), 0) AS keyword_score,
|
|
746
844
|
((1 - (embedding <=> $1::vector)) + (COALESCE(ts_rank(to_tsvector('english', (to_jsonb(t) - 'embedding')::text), to_tsquery('english', $2)), 0) * 2.0) ${exactNameScoreExpr}) AS hybrid_score
|
|
747
845
|
FROM "${table}" t
|
|
846
|
+
${whereClause}
|
|
748
847
|
ORDER BY hybrid_score DESC
|
|
749
848
|
LIMIT ${tableLimit}
|
|
750
849
|
`;
|
|
751
|
-
params = [vectorLiteral, dynamicKeywordQuery];
|
|
850
|
+
params = [vectorLiteral, dynamicKeywordQuery, ...filterParams];
|
|
752
851
|
} else {
|
|
753
852
|
sqlQuery = `
|
|
754
853
|
SELECT *,
|
|
755
854
|
(1 - (embedding <=> $1::vector)) AS hybrid_score
|
|
756
855
|
FROM "${table}" t
|
|
856
|
+
${whereClause}
|
|
757
857
|
ORDER BY hybrid_score DESC
|
|
758
858
|
LIMIT ${tableLimit}
|
|
759
859
|
`;
|
|
760
|
-
params = [vectorLiteral];
|
|
860
|
+
params = [vectorLiteral, ...filterParams];
|
|
761
861
|
}
|
|
762
862
|
const result = await this.pool.query(sqlQuery, params);
|
|
763
863
|
if (result.rowCount && result.rowCount > 0) {
|
|
@@ -4430,7 +4530,8 @@ var QueryProcessor = class {
|
|
|
4430
4530
|
const fieldValuePatterns = [
|
|
4431
4531
|
new RegExp(`\\b${fieldPattern}\\s*(?:=|:)\\s*["']?${valuePattern}["']?(?=[?.!,]|$)`, "gi"),
|
|
4432
4532
|
new RegExp(`\\b${fieldPattern}\\s+(?:is|are|was|were|equals?|equal to|named|called)\\s+["']?${valuePattern}["']?(?=[?.!,]|$)`, "gi"),
|
|
4433
|
-
new RegExp(`\\bwith\\s+${fieldPattern}\\s+["']?${valuePattern}["']?(?=[?.!,]|$)`, "gi")
|
|
4533
|
+
new RegExp(`\\bwith\\s+${fieldPattern}\\s+["']?${valuePattern}["']?(?=[?.!,]|$)`, "gi"),
|
|
4534
|
+
new RegExp(`\\b(?:under|in|for|from|of)\\s+${fieldPattern}\\s+["']?${valuePattern}["']?(?=[?.!,]|$)`, "gi")
|
|
4434
4535
|
];
|
|
4435
4536
|
for (const pattern of fieldValuePatterns) {
|
|
4436
4537
|
for (const match of question.matchAll(pattern)) {
|
|
@@ -4664,73 +4765,8 @@ var LLMRouter = class {
|
|
|
4664
4765
|
}
|
|
4665
4766
|
};
|
|
4666
4767
|
|
|
4667
|
-
// src/utils/synonyms.ts
|
|
4668
|
-
var FIELD_SYNONYMS = {
|
|
4669
|
-
name: ["product", "item", "title", "label", "heading", "subject", "product name", "item name"],
|
|
4670
|
-
price: ["cost", "amount", "msrp", "price", "rate", "value", "price_usd"],
|
|
4671
|
-
brand: ["manufacturer", "vendor", "make", "company", "brand_name", "supplier"],
|
|
4672
|
-
image: [
|
|
4673
|
-
"imageUrl",
|
|
4674
|
-
"thumbnail",
|
|
4675
|
-
"img",
|
|
4676
|
-
"url",
|
|
4677
|
-
"photo",
|
|
4678
|
-
"picture",
|
|
4679
|
-
"media",
|
|
4680
|
-
"image_url",
|
|
4681
|
-
"main_image",
|
|
4682
|
-
"product_image",
|
|
4683
|
-
"thumb"
|
|
4684
|
-
],
|
|
4685
|
-
stock: [
|
|
4686
|
-
"inventory",
|
|
4687
|
-
"quantity",
|
|
4688
|
-
"count",
|
|
4689
|
-
"availability",
|
|
4690
|
-
"stock_level",
|
|
4691
|
-
"inStock",
|
|
4692
|
-
"is_available",
|
|
4693
|
-
"in stock",
|
|
4694
|
-
"status"
|
|
4695
|
-
],
|
|
4696
|
-
category: [
|
|
4697
|
-
"product_category",
|
|
4698
|
-
"product category",
|
|
4699
|
-
"category_name",
|
|
4700
|
-
"category name",
|
|
4701
|
-
"department",
|
|
4702
|
-
"collection"
|
|
4703
|
-
],
|
|
4704
|
-
description: ["summary", "content", "body", "text", "info", "details"],
|
|
4705
|
-
link: ["url", "href", "product_url", "page_url", "link"]
|
|
4706
|
-
};
|
|
4707
|
-
function resolveMetadataValue(meta, uiKey) {
|
|
4708
|
-
var _a;
|
|
4709
|
-
const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
|
|
4710
|
-
const keys = Object.keys(meta);
|
|
4711
|
-
const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
|
|
4712
|
-
let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
|
|
4713
|
-
if (match !== void 0) return meta[match];
|
|
4714
|
-
match = keys.find((k) => synonyms.map((s) => s.toLowerCase()).includes(k.toLowerCase()));
|
|
4715
|
-
if (match !== void 0) return meta[match];
|
|
4716
|
-
const isBlacklisted = (kl) => {
|
|
4717
|
-
return systemKeys.includes(kl) || kl.startsWith("option1") || kl.startsWith("option2") || kl.startsWith("option3");
|
|
4718
|
-
};
|
|
4719
|
-
match = keys.find((k) => {
|
|
4720
|
-
const kl = k.toLowerCase();
|
|
4721
|
-
if (isBlacklisted(kl)) return false;
|
|
4722
|
-
return kl.includes(uiKey.toLowerCase());
|
|
4723
|
-
});
|
|
4724
|
-
if (match !== void 0) return meta[match];
|
|
4725
|
-
match = keys.find((k) => {
|
|
4726
|
-
const kl = k.toLowerCase();
|
|
4727
|
-
if (isBlacklisted(kl)) return false;
|
|
4728
|
-
return synonyms.some((sk) => kl.includes(sk.toLowerCase()) || sk.toLowerCase().includes(kl));
|
|
4729
|
-
});
|
|
4730
|
-
return match !== void 0 ? meta[match] : void 0;
|
|
4731
|
-
}
|
|
4732
|
-
|
|
4733
4768
|
// src/utils/UITransformer.ts
|
|
4769
|
+
init_synonyms();
|
|
4734
4770
|
var UITransformer = class {
|
|
4735
4771
|
// ─── Public Entry Points ─────────────────────────────────────────────────
|
|
4736
4772
|
/**
|
|
@@ -5027,7 +5063,7 @@ RULES:
|
|
|
5027
5063
|
}
|
|
5028
5064
|
// ─── Transform Helpers ────────────────────────────────────────────────────
|
|
5029
5065
|
static transformToProductCarousel(data, config, trainedSchema) {
|
|
5030
|
-
const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
|
|
5066
|
+
const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
|
|
5031
5067
|
return {
|
|
5032
5068
|
type: "product_carousel",
|
|
5033
5069
|
title: "Recommended Products",
|
|
@@ -5986,14 +6022,16 @@ Given these metadata keys from a database: [${keys.join(", ")}]
|
|
|
5986
6022
|
Identify which keys best correspond to these standard UI properties:
|
|
5987
6023
|
${propertyList}
|
|
5988
6024
|
|
|
5989
|
-
Return ONLY a JSON object where the keys are the UI properties and the values are the matching database keys.
|
|
6025
|
+
Return ONLY a valid JSON object where the keys are the UI properties and the values are the EXACT matching database keys from the list above.
|
|
5990
6026
|
If no good match is found for a property, omit it.
|
|
5991
6027
|
|
|
5992
6028
|
Example:
|
|
5993
6029
|
{
|
|
5994
|
-
"name": "
|
|
5995
|
-
"price": "
|
|
5996
|
-
"brand": "
|
|
6030
|
+
"name": "Title",
|
|
6031
|
+
"price": "Variant Price",
|
|
6032
|
+
"brand": "Vendor",
|
|
6033
|
+
"image": "Image Src",
|
|
6034
|
+
"stock": "Variant Inventory Qty"
|
|
5997
6035
|
}
|
|
5998
6036
|
`;
|
|
5999
6037
|
try {
|
|
@@ -6284,7 +6322,10 @@ var Pipeline = class {
|
|
|
6284
6322
|
upsertBatchOptions
|
|
6285
6323
|
);
|
|
6286
6324
|
if (upsertResult.errors.length > 0) {
|
|
6287
|
-
console.warn(`[Pipeline] Ingestion: ${upsertResult.errors.length} batches failed
|
|
6325
|
+
console.warn(`[Pipeline] Ingestion: ${upsertResult.errors.length} batches failed. Error details:`);
|
|
6326
|
+
upsertResult.errors.forEach((err, idx) => {
|
|
6327
|
+
console.warn(` Batch ${idx + 1} Error: ${err.error.message || String(err.error)}`);
|
|
6328
|
+
});
|
|
6288
6329
|
}
|
|
6289
6330
|
return upsertResult.totalProcessed;
|
|
6290
6331
|
}
|
|
@@ -6399,8 +6440,9 @@ var Pipeline = class {
|
|
|
6399
6440
|
this.embeddingCache.set(cacheKey, queryVector);
|
|
6400
6441
|
}
|
|
6401
6442
|
const graphData = (strategyResult === "graph" || strategyResult === "both") && this.graphDB && ((_j = this.config.rag) == null ? void 0 : _j.useGraphRetrieval) ? yield new __await(this.graphDB.query(searchQuery)) : void 0;
|
|
6443
|
+
const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
|
|
6402
6444
|
const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
|
|
6403
|
-
const wantsExhaustiveList = hasNumericPredicates || /\b(list|all|show|provide|give|get)\b/i.test(question);
|
|
6445
|
+
const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
|
|
6404
6446
|
const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
|
|
6405
6447
|
const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
|
|
6406
6448
|
const retrieveEnd = performance.now();
|
|
@@ -6408,15 +6450,27 @@ var Pipeline = class {
|
|
|
6408
6450
|
const retrieveMs = retrieveEnd - embedStart;
|
|
6409
6451
|
const rerankStart = performance.now();
|
|
6410
6452
|
const structuredSources = this.applyStructuredFilters(rawSources, filter);
|
|
6411
|
-
let
|
|
6453
|
+
let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
|
|
6454
|
+
const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
|
|
6412
6455
|
if (!hasNumericPredicates && ((_k = this.config.rag) == null ? void 0 : _k.useReranking)) {
|
|
6413
|
-
|
|
6456
|
+
fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
|
|
6414
6457
|
} else if (!wantsExhaustiveList) {
|
|
6415
|
-
|
|
6458
|
+
fullSources = fullSources.slice(0, topK);
|
|
6416
6459
|
}
|
|
6417
6460
|
const rerankMs = performance.now() - rerankStart;
|
|
6418
|
-
let context =
|
|
6461
|
+
let context = fullSources.length ? fullSources.map((m, i) => `[Source ${i + 1}]
|
|
6419
6462
|
${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
6463
|
+
let displayCount = 15;
|
|
6464
|
+
if (hasMetadataFilter) {
|
|
6465
|
+
displayCount = fullSources.length;
|
|
6466
|
+
} else {
|
|
6467
|
+
const highlyRelevant = fullSources.filter((m) => m.score >= 0.4);
|
|
6468
|
+
displayCount = Math.max(highlyRelevant.length, topK);
|
|
6469
|
+
if (displayCount > 15) {
|
|
6470
|
+
displayCount = 15;
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
|
|
6420
6474
|
if (graphData && graphData.nodes.length > 0) {
|
|
6421
6475
|
const graphContext = graphData.nodes.map(
|
|
6422
6476
|
(n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
|
|
@@ -6429,7 +6483,18 @@ ${context}`;
|
|
|
6429
6483
|
}
|
|
6430
6484
|
const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
|
|
6431
6485
|
const trainedSchemaPromise = allMetadataKeys.length > 0 ? SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => void 0) : Promise.resolve(void 0);
|
|
6432
|
-
const
|
|
6486
|
+
const uiTransformationPromise = trainedSchemaPromise.then(
|
|
6487
|
+
(trainedSchema) => this.generateUiTransformation(
|
|
6488
|
+
question,
|
|
6489
|
+
sources,
|
|
6490
|
+
trainedSchema,
|
|
6491
|
+
hasNumericPredicates
|
|
6492
|
+
)
|
|
6493
|
+
).catch((uiError) => {
|
|
6494
|
+
console.warn("[Pipeline] UI transformation failed concurrently:", uiError);
|
|
6495
|
+
return UITransformer.transform(question, sources, this.config);
|
|
6496
|
+
});
|
|
6497
|
+
const restrictionSuffix = "\n\n(IMPORTANT: Format your response beautifully using rich Markdown! Use bolding for emphasis, headings (##) for structure, bullet points for lists, and proper line breaks between paragraphs to make it highly readable. However, NEVER generate Markdown tables, HTML figures, or text charts (the UI renders requested charts separately, so NEVER say you cannot create, display, draw, render, or provide a chart/visualization). If listing products, use simple markdown bullet points or comma-separated names. NEVER use plus signs (+) to separate product names, category names, or list items. For product description/detail questions, provide customer-facing prose only and do NOT list internal catalog fields such as Handle, Body (HTML), Vendor, Type, Tags, Published, Option, Variant, SKU, or raw metadata labels. You CAN use numbers for years/counts like 2006 or 5800, but NEVER put a dollar sign ($) before them.)";
|
|
6433
6498
|
const hardenedHistory = [...history];
|
|
6434
6499
|
const userQuestion = { role: "user", content: question + restrictionSuffix };
|
|
6435
6500
|
const messages = [...hardenedHistory, userQuestion];
|
|
@@ -6499,19 +6564,7 @@ ${context}`;
|
|
|
6499
6564
|
tokens,
|
|
6500
6565
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6501
6566
|
};
|
|
6502
|
-
|
|
6503
|
-
try {
|
|
6504
|
-
const trainedSchema = yield new __await(trainedSchemaPromise);
|
|
6505
|
-
uiTransformation = yield new __await(this.generateUiTransformation(
|
|
6506
|
-
question,
|
|
6507
|
-
sources,
|
|
6508
|
-
trainedSchema,
|
|
6509
|
-
hasNumericPredicates
|
|
6510
|
-
));
|
|
6511
|
-
} catch (uiError) {
|
|
6512
|
-
console.warn("[Pipeline] UI transformation failed before metadata yield:", uiError);
|
|
6513
|
-
uiTransformation = UITransformer.transform(question, sources, this.config);
|
|
6514
|
-
}
|
|
6567
|
+
const uiTransformation = yield new __await(uiTransformationPromise);
|
|
6515
6568
|
yield {
|
|
6516
6569
|
reply: "",
|
|
6517
6570
|
sources,
|
|
@@ -7245,15 +7298,24 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7245
7298
|
});
|
|
7246
7299
|
}
|
|
7247
7300
|
const encoder = new TextEncoder();
|
|
7301
|
+
let isActive = true;
|
|
7248
7302
|
const stream = new ReadableStream({
|
|
7249
7303
|
async start(controller) {
|
|
7250
7304
|
var _a;
|
|
7251
|
-
const enqueue = (text) =>
|
|
7305
|
+
const enqueue = (text) => {
|
|
7306
|
+
if (!isActive) return;
|
|
7307
|
+
try {
|
|
7308
|
+
controller.enqueue(encoder.encode(text));
|
|
7309
|
+
} catch (err) {
|
|
7310
|
+
console.warn("[createStreamHandler] Failed to enqueue (stream already closed):", err);
|
|
7311
|
+
}
|
|
7312
|
+
};
|
|
7252
7313
|
try {
|
|
7253
7314
|
const pipelineStream = plugin.chatStream(message, history, namespace);
|
|
7254
7315
|
try {
|
|
7255
7316
|
for (var iter = __forAwait(pipelineStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
7256
7317
|
const chunk = temp.value;
|
|
7318
|
+
if (!isActive) break;
|
|
7257
7319
|
if (typeof chunk === "string") {
|
|
7258
7320
|
enqueue(sseTextFrame(chunk));
|
|
7259
7321
|
} else {
|
|
@@ -7291,12 +7353,27 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7291
7353
|
}
|
|
7292
7354
|
}
|
|
7293
7355
|
} catch (streamError) {
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7356
|
+
if (isActive) {
|
|
7357
|
+
const errorMessage = streamError instanceof Error ? streamError.message : String(streamError);
|
|
7358
|
+
console.error("[createStreamHandler] Stream error:", streamError);
|
|
7359
|
+
try {
|
|
7360
|
+
enqueue(sseErrorFrame(errorMessage));
|
|
7361
|
+
} catch (e) {
|
|
7362
|
+
}
|
|
7363
|
+
}
|
|
7297
7364
|
} finally {
|
|
7298
|
-
|
|
7365
|
+
if (isActive) {
|
|
7366
|
+
isActive = false;
|
|
7367
|
+
try {
|
|
7368
|
+
controller.close();
|
|
7369
|
+
} catch (e) {
|
|
7370
|
+
}
|
|
7371
|
+
}
|
|
7299
7372
|
}
|
|
7373
|
+
},
|
|
7374
|
+
cancel(reason) {
|
|
7375
|
+
isActive = false;
|
|
7376
|
+
console.log("[createStreamHandler] Stream connection closed by client:", reason);
|
|
7300
7377
|
}
|
|
7301
7378
|
});
|
|
7302
7379
|
return new Response(stream, { headers: SSE_HEADERS });
|
|
@@ -7357,6 +7434,7 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7357
7434
|
if (parsed.data && parsed.data.length > 0) {
|
|
7358
7435
|
let i = 0;
|
|
7359
7436
|
let lastRowData = null;
|
|
7437
|
+
const csvCols = Object.keys(parsed.data[0]);
|
|
7360
7438
|
for (const row of parsed.data) {
|
|
7361
7439
|
i++;
|
|
7362
7440
|
const rowData = row;
|
|
@@ -7378,12 +7456,14 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7378
7456
|
documents.push({
|
|
7379
7457
|
docId: `${file.name}-row-${i}`,
|
|
7380
7458
|
content: contentParts.join(", "),
|
|
7381
|
-
metadata: __spreadValues(__spreadValues({
|
|
7459
|
+
metadata: __spreadValues(__spreadProps(__spreadValues({
|
|
7382
7460
|
fileName: file.name,
|
|
7383
7461
|
fileSize: file.size,
|
|
7384
7462
|
fileType: file.type,
|
|
7385
7463
|
uploadedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7386
|
-
}, dimension ? { dimension } : {}),
|
|
7464
|
+
}, dimension ? { dimension } : {}), {
|
|
7465
|
+
csvHeaders: csvCols
|
|
7466
|
+
}), rowData)
|
|
7387
7467
|
});
|
|
7388
7468
|
}
|
|
7389
7469
|
}
|