@retrivora-ai/rag-engine 1.8.4 → 1.8.5
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/LICENSE.txt +21 -0
- package/dist/{ILLMProvider-BOJFz3Na.d.mts → ILLMProvider-CbUtvWAW.d.mts} +2 -0
- package/dist/{ILLMProvider-BOJFz3Na.d.ts → ILLMProvider-CbUtvWAW.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 +100 -52
- package/dist/handlers/index.mjs +100 -52
- package/dist/{index-BwpcaziY.d.ts → index-DgzcnqZs.d.ts} +1 -1
- package/dist/{index-D3V9Et2M.d.mts → index-c_y_5qdw.d.mts} +1 -1
- package/dist/index.css +27 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -4
- package/dist/index.mjs +18 -4
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +108 -55
- package/dist/server.mjs +108 -55
- package/package.json +1 -1
- package/src/app/globals.css +97 -0
- package/src/components/ChatWidget.tsx +23 -10
- package/src/config/RagConfig.ts +2 -0
- package/src/providers/vectordb/ChromaDBProvider.ts +4 -0
- package/src/providers/vectordb/MultiTablePostgresProvider.ts +18 -5
- package/src/providers/vectordb/PostgreSQLProvider.ts +14 -3
- package/src/providers/vectordb/QdrantProvider.ts +4 -1
- package/src/utils/UITransformer.ts +99 -51
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2026] [Abhinav Alkuchi]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -99,6 +99,8 @@ interface VectorDBConfig {
|
|
|
99
99
|
* - searchFields?: string[] | string // optional override for which columns receive exact-match boosts
|
|
100
100
|
*/
|
|
101
101
|
options: Record<string, unknown>;
|
|
102
|
+
/** Optional distance metric (defaults to cosine if not specified and supported by provider) */
|
|
103
|
+
distanceMetric?: 'cosine' | 'euclidean' | 'dotproduct';
|
|
102
104
|
}
|
|
103
105
|
type GraphDBProvider = typeof GRAPH_DB_PROVIDERS[number];
|
|
104
106
|
interface GraphDBConfig {
|
|
@@ -99,6 +99,8 @@ interface VectorDBConfig {
|
|
|
99
99
|
* - searchFields?: string[] | string // optional override for which columns receive exact-match boosts
|
|
100
100
|
*/
|
|
101
101
|
options: Record<string, unknown>;
|
|
102
|
+
/** Optional distance metric (defaults to cosine if not specified and supported by provider) */
|
|
103
|
+
distanceMetric?: 'cosine' | 'euclidean' | 'dotproduct';
|
|
102
104
|
}
|
|
103
105
|
type GraphDBProvider = typeof GRAPH_DB_PROVIDERS[number];
|
|
104
106
|
interface GraphDBConfig {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../ILLMProvider-
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, l as sseObservabilityFrame, j as sseTextFrame, m as sseUIFrame } from '../index-
|
|
1
|
+
import '../ILLMProvider-CbUtvWAW.mjs';
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, l as sseObservabilityFrame, j as sseTextFrame, m as sseUIFrame } from '../index-c_y_5qdw.mjs';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../ILLMProvider-
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, l as sseObservabilityFrame, j as sseTextFrame, m as sseUIFrame } from '../index-
|
|
1
|
+
import '../ILLMProvider-CbUtvWAW.js';
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, l as sseObservabilityFrame, j as sseTextFrame, m as sseUIFrame } from '../index-DgzcnqZs.js';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.js
CHANGED
|
@@ -374,10 +374,12 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
374
374
|
embedding VECTOR(${this.dimensions})
|
|
375
375
|
)
|
|
376
376
|
`);
|
|
377
|
+
const metric = this.config.distanceMetric || "cosine";
|
|
378
|
+
const indexOps = metric === "euclidean" ? "vector_l2_ops" : metric === "dotproduct" ? "vector_ip_ops" : "vector_cosine_ops";
|
|
377
379
|
await client.query(`
|
|
378
380
|
CREATE INDEX IF NOT EXISTS ${this.uploadTable}_embedding_idx
|
|
379
381
|
ON ${this.uploadTable}
|
|
380
|
-
USING hnsw (embedding
|
|
382
|
+
USING hnsw (embedding ${indexOps})
|
|
381
383
|
`);
|
|
382
384
|
const res = await client.query(`
|
|
383
385
|
SELECT table_name
|
|
@@ -439,10 +441,12 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
439
441
|
)
|
|
440
442
|
`;
|
|
441
443
|
await client.query(createTableSql);
|
|
444
|
+
const metric = this.config.distanceMetric || "cosine";
|
|
445
|
+
const indexOps = metric === "euclidean" ? "vector_l2_ops" : metric === "dotproduct" ? "vector_ip_ops" : "vector_cosine_ops";
|
|
442
446
|
await client.query(`
|
|
443
447
|
CREATE INDEX IF NOT EXISTS "${tableName}_embedding_idx"
|
|
444
448
|
ON "${tableName}"
|
|
445
|
-
USING hnsw (embedding
|
|
449
|
+
USING hnsw (embedding ${indexOps})
|
|
446
450
|
`);
|
|
447
451
|
if (!this.tables.includes(tableName)) {
|
|
448
452
|
this.tables.push(tableName);
|
|
@@ -524,6 +528,8 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
524
528
|
try {
|
|
525
529
|
let sqlQuery = "";
|
|
526
530
|
let params = [];
|
|
531
|
+
const metric = this.config.distanceMetric || "cosine";
|
|
532
|
+
const scoreExpr = metric === "euclidean" ? `1 / (1 + (embedding <-> $1::vector))` : metric === "dotproduct" ? `(embedding <#> $1::vector) * -1` : `1 - (embedding <=> $1::vector)`;
|
|
527
533
|
if (queryText) {
|
|
528
534
|
const hasEntityHints = entityHints.length > 0;
|
|
529
535
|
const exactNameScoreExpr = hasEntityHints ? `+ (
|
|
@@ -536,9 +542,9 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
536
542
|
) * 3.0` : "";
|
|
537
543
|
sqlQuery = `
|
|
538
544
|
SELECT *,
|
|
539
|
-
(
|
|
545
|
+
(${scoreExpr}) AS vector_score,
|
|
540
546
|
COALESCE(ts_rank(to_tsvector('english', (to_jsonb(t) - 'embedding')::text), to_tsquery('english', $2)), 0) AS keyword_score,
|
|
541
|
-
((
|
|
547
|
+
((${scoreExpr}) + (COALESCE(ts_rank(to_tsvector('english', (to_jsonb(t) - 'embedding')::text), to_tsquery('english', $2)), 0) * 2.0) ${exactNameScoreExpr}) AS hybrid_score
|
|
542
548
|
FROM "${table}" t
|
|
543
549
|
ORDER BY hybrid_score DESC
|
|
544
550
|
LIMIT 50
|
|
@@ -547,7 +553,7 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
547
553
|
} else {
|
|
548
554
|
sqlQuery = `
|
|
549
555
|
SELECT *,
|
|
550
|
-
(
|
|
556
|
+
(${scoreExpr}) AS hybrid_score
|
|
551
557
|
FROM "${table}" t
|
|
552
558
|
ORDER BY hybrid_score DESC
|
|
553
559
|
LIMIT 50
|
|
@@ -1021,11 +1027,13 @@ var init_QdrantProvider = __esm({
|
|
|
1021
1027
|
if (import_axios4.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
1022
1028
|
const opts = this.config.options;
|
|
1023
1029
|
const dimensionsForCreate = opts.dimensions || 1536;
|
|
1030
|
+
const metric = this.config.distanceMetric || "cosine";
|
|
1031
|
+
const distance = metric === "euclidean" ? "Euclid" : metric === "dotproduct" ? "Dot" : "Cosine";
|
|
1024
1032
|
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
|
|
1025
1033
|
await this.http.put(`/collections/${this.indexName}`, {
|
|
1026
1034
|
vectors: {
|
|
1027
1035
|
size: dimensionsForCreate,
|
|
1028
|
-
distance
|
|
1036
|
+
distance
|
|
1029
1037
|
}
|
|
1030
1038
|
});
|
|
1031
1039
|
console.log(`[QdrantProvider] \u2705 Created collection "${this.indexName}"`);
|
|
@@ -1203,9 +1211,12 @@ var init_ChromaDBProvider = __esm({
|
|
|
1203
1211
|
console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
|
|
1204
1212
|
} catch (err) {
|
|
1205
1213
|
if (import_axios5.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
|
|
1214
|
+
const metric = this.config.distanceMetric || "cosine";
|
|
1215
|
+
const space = metric === "euclidean" ? "l2" : metric === "dotproduct" ? "ip" : "cosine";
|
|
1206
1216
|
console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
|
|
1207
1217
|
const { data } = await this.http.post("/api/v1/collections", {
|
|
1208
|
-
name: this.indexName
|
|
1218
|
+
name: this.indexName,
|
|
1219
|
+
metadata: { "hnsw:space": space }
|
|
1209
1220
|
});
|
|
1210
1221
|
this.collectionId = data.id;
|
|
1211
1222
|
console.log(`[ChromaDBProvider] \u2705 Created collection "${this.indexName}" (id: ${this.collectionId})`);
|
|
@@ -4165,18 +4176,20 @@ var UITransformer = class {
|
|
|
4165
4176
|
}
|
|
4166
4177
|
const isStockRequest = this.isStockQuery(userQuery);
|
|
4167
4178
|
const filteredData = isStockRequest ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
|
|
4168
|
-
const
|
|
4179
|
+
const groupByField = this.determineGroupByField(userQuery, filteredData);
|
|
4180
|
+
const categories = this.detectCategories(filteredData, groupByField);
|
|
4169
4181
|
const hasProducts = filteredData.some((item) => this.isProductData(item));
|
|
4170
4182
|
const isTimeSeries = filteredData.some((item) => this.isTimeSeriesData(item));
|
|
4171
4183
|
const isTrendQuery = this.isTrendQuery(userQuery);
|
|
4172
4184
|
if (isTrendQuery && isTimeSeries) {
|
|
4173
4185
|
return this.transformToLineChart(filteredData);
|
|
4174
4186
|
}
|
|
4175
|
-
|
|
4187
|
+
const explicitChartRequest = this.isExplicitChartQuery(userQuery);
|
|
4188
|
+
if (hasProducts && !explicitChartRequest && !this.shouldShowCategoryChart(userQuery)) {
|
|
4176
4189
|
return this.transformToProductCarousel(filteredData, config, trainedSchema);
|
|
4177
4190
|
}
|
|
4178
|
-
if (categories.length > 1 && this.shouldShowCategoryChart(userQuery
|
|
4179
|
-
return this.transformToPieChart(filteredData);
|
|
4191
|
+
if (explicitChartRequest || categories.length > 1 && this.shouldShowCategoryChart(userQuery)) {
|
|
4192
|
+
return this.transformToPieChart(filteredData, groupByField);
|
|
4180
4193
|
}
|
|
4181
4194
|
if (hasProducts) {
|
|
4182
4195
|
return this.transformToProductCarousel(filteredData, config, trainedSchema);
|
|
@@ -4201,11 +4214,12 @@ var UITransformer = class {
|
|
|
4201
4214
|
/**
|
|
4202
4215
|
* Transform data to pie chart format
|
|
4203
4216
|
*/
|
|
4204
|
-
static transformToPieChart(data) {
|
|
4205
|
-
|
|
4206
|
-
|
|
4217
|
+
static transformToPieChart(data, groupByField) {
|
|
4218
|
+
let categories = this.detectCategories(data, groupByField);
|
|
4219
|
+
if (categories.length === 0) categories = ["All Data"];
|
|
4220
|
+
const categoryData = this.aggregateByCategory(data, categories, groupByField);
|
|
4207
4221
|
const pieData = Object.entries(categoryData).map(([label, count]) => {
|
|
4208
|
-
const { inStockCount, outOfStockCount } = this.calculateStockCounts(label, data);
|
|
4222
|
+
const { inStockCount, outOfStockCount } = this.calculateStockCounts(label, data, groupByField);
|
|
4209
4223
|
return {
|
|
4210
4224
|
label,
|
|
4211
4225
|
value: count,
|
|
@@ -4215,7 +4229,7 @@ var UITransformer = class {
|
|
|
4215
4229
|
});
|
|
4216
4230
|
return {
|
|
4217
4231
|
type: "pie_chart",
|
|
4218
|
-
title:
|
|
4232
|
+
title: `Distribution by ${groupByField.charAt(0).toUpperCase() + groupByField.slice(1)}`,
|
|
4219
4233
|
description: `Showing breakdown across ${categories.length} categories`,
|
|
4220
4234
|
data: pieData
|
|
4221
4235
|
};
|
|
@@ -4438,10 +4452,11 @@ var UITransformer = class {
|
|
|
4438
4452
|
});
|
|
4439
4453
|
return hasTimeKeyword || hasValidDateValue;
|
|
4440
4454
|
}
|
|
4441
|
-
static
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4455
|
+
static isExplicitChartQuery(query) {
|
|
4456
|
+
const normalized = query.toLowerCase();
|
|
4457
|
+
return normalized.includes("pie chart") || normalized.includes("piechart") || normalized.includes("bar chart") || normalized.includes("barchart") || normalized.includes("radar chart");
|
|
4458
|
+
}
|
|
4459
|
+
static shouldShowCategoryChart(query) {
|
|
4445
4460
|
const normalized = query.toLowerCase();
|
|
4446
4461
|
const chartKeywords = [
|
|
4447
4462
|
"distribution",
|
|
@@ -4454,7 +4469,11 @@ var UITransformer = class {
|
|
|
4454
4469
|
"segmentation",
|
|
4455
4470
|
"split",
|
|
4456
4471
|
"category breakdown",
|
|
4457
|
-
"category distribution"
|
|
4472
|
+
"category distribution",
|
|
4473
|
+
"pie chart",
|
|
4474
|
+
"piechart",
|
|
4475
|
+
"bar chart",
|
|
4476
|
+
"barchart"
|
|
4458
4477
|
];
|
|
4459
4478
|
return chartKeywords.some((keyword) => normalized.includes(keyword));
|
|
4460
4479
|
}
|
|
@@ -4530,44 +4549,67 @@ var UITransformer = class {
|
|
|
4530
4549
|
return null;
|
|
4531
4550
|
}
|
|
4532
4551
|
/**
|
|
4533
|
-
* Helper:
|
|
4552
|
+
* Helper: Dynamically determine what field to group by based on user query
|
|
4553
|
+
*/
|
|
4554
|
+
static determineGroupByField(query, data) {
|
|
4555
|
+
const normalized = query.toLowerCase();
|
|
4556
|
+
const match = normalized.match(/(?:by|across|per|based on)\s+([a-zA-Z]+)/i);
|
|
4557
|
+
let targetField = "category";
|
|
4558
|
+
if (match && match[1]) {
|
|
4559
|
+
let field = match[1].toLowerCase();
|
|
4560
|
+
if (field.endsWith("ies")) field = field.replace(/ies$/, "y");
|
|
4561
|
+
else if (field.endsWith("s") && field !== "status") field = field.slice(0, -1);
|
|
4562
|
+
const stopWords = ["the", "all", "different", "various", "some", "these", "those"];
|
|
4563
|
+
if (!stopWords.includes(field)) {
|
|
4564
|
+
targetField = field;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
const hasTargetField = data.some((d) => d.metadata && d.metadata[targetField] !== void 0);
|
|
4568
|
+
if (!hasTargetField && targetField === "category") {
|
|
4569
|
+
if (data.some((d) => d.metadata && d.metadata["type"] !== void 0)) return "type";
|
|
4570
|
+
if (data.some((d) => d.metadata && d.metadata["brand"] !== void 0)) return "brand";
|
|
4571
|
+
}
|
|
4572
|
+
return targetField;
|
|
4573
|
+
}
|
|
4574
|
+
/**
|
|
4575
|
+
* Helper: Detect grouping values dynamically
|
|
4534
4576
|
*/
|
|
4535
|
-
static detectCategories(data) {
|
|
4577
|
+
static detectCategories(data, groupByField) {
|
|
4536
4578
|
const categories = /* @__PURE__ */ new Set();
|
|
4537
4579
|
data.forEach((item) => {
|
|
4538
4580
|
const meta = item.metadata || {};
|
|
4539
|
-
if (meta
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
));
|
|
4552
|
-
contentCategories.forEach((category) => categories.add(category));
|
|
4553
|
-
const categoryMatch = item.content.match(/(?:Category|Type|Class):\s*([^\n]+)/i);
|
|
4554
|
-
if (categoryMatch) {
|
|
4555
|
-
categories.add(categoryMatch[1].trim());
|
|
4581
|
+
if (meta[groupByField] !== void 0) {
|
|
4582
|
+
const val = meta[groupByField];
|
|
4583
|
+
if (Array.isArray(val)) val.forEach((v) => categories.add(String(v)));
|
|
4584
|
+
else categories.add(String(val));
|
|
4585
|
+
} else if (groupByField === "category") {
|
|
4586
|
+
if (meta.type) categories.add(String(meta.type));
|
|
4587
|
+
if (meta.tag) {
|
|
4588
|
+
const tags = Array.isArray(meta.tag) ? meta.tag : [meta.tag];
|
|
4589
|
+
tags.forEach((t) => categories.add(String(t)));
|
|
4590
|
+
}
|
|
4591
|
+
const categoryMatch = item.content.match(/(?:Category|Type|Class):\s*([^\n]+)/i);
|
|
4592
|
+
if (categoryMatch) categories.add(categoryMatch[1].trim());
|
|
4556
4593
|
}
|
|
4557
4594
|
});
|
|
4558
4595
|
return Array.from(categories);
|
|
4559
4596
|
}
|
|
4560
4597
|
/**
|
|
4561
|
-
* Helper: Aggregate data
|
|
4598
|
+
* Helper: Aggregate data dynamically
|
|
4562
4599
|
*/
|
|
4563
|
-
static aggregateByCategory(data, categories) {
|
|
4600
|
+
static aggregateByCategory(data, categories, groupByField) {
|
|
4564
4601
|
const result = {};
|
|
4565
4602
|
categories.forEach((cat) => {
|
|
4566
4603
|
result[cat] = 0;
|
|
4567
4604
|
});
|
|
4568
4605
|
data.forEach((item) => {
|
|
4569
4606
|
const meta = item.metadata || {};
|
|
4570
|
-
|
|
4607
|
+
let itemCategory = "Other";
|
|
4608
|
+
if (meta[groupByField] !== void 0) {
|
|
4609
|
+
itemCategory = String(meta[groupByField]);
|
|
4610
|
+
} else if (groupByField === "category" && meta.type) {
|
|
4611
|
+
itemCategory = String(meta.type);
|
|
4612
|
+
}
|
|
4571
4613
|
if (Object.prototype.hasOwnProperty.call(result, itemCategory)) {
|
|
4572
4614
|
result[itemCategory]++;
|
|
4573
4615
|
} else {
|
|
@@ -4617,14 +4659,19 @@ var UITransformer = class {
|
|
|
4617
4659
|
});
|
|
4618
4660
|
}
|
|
4619
4661
|
/**
|
|
4620
|
-
* Helper: Calculate stock counts
|
|
4662
|
+
* Helper: Calculate stock counts dynamically
|
|
4621
4663
|
*/
|
|
4622
|
-
static calculateStockCounts(category, data) {
|
|
4664
|
+
static calculateStockCounts(category, data, groupByField) {
|
|
4623
4665
|
let inStock = 0;
|
|
4624
4666
|
let outOfStock = 0;
|
|
4625
4667
|
data.forEach((d) => {
|
|
4626
4668
|
const meta = d.metadata || {};
|
|
4627
|
-
|
|
4669
|
+
let itemCategory = "Other";
|
|
4670
|
+
if (meta[groupByField] !== void 0) {
|
|
4671
|
+
itemCategory = String(meta[groupByField]);
|
|
4672
|
+
} else if (groupByField === "category" && meta.type) {
|
|
4673
|
+
itemCategory = String(meta.type);
|
|
4674
|
+
}
|
|
4628
4675
|
if (itemCategory === category) {
|
|
4629
4676
|
if (this.determineStockStatus(d)) {
|
|
4630
4677
|
inStock++;
|
|
@@ -4749,12 +4796,13 @@ DATA SHAPE per type:
|
|
|
4749
4796
|
- text: { "content": "<prose answer>" }
|
|
4750
4797
|
|
|
4751
4798
|
DECISION RULES (follow strictly):
|
|
4752
|
-
1.
|
|
4753
|
-
2.
|
|
4754
|
-
3.
|
|
4755
|
-
4.
|
|
4756
|
-
5.
|
|
4757
|
-
6.
|
|
4799
|
+
1. IF the user explicitly asks for a "pie chart", "bar chart", or "table", you MUST output that exact type. Do not deviate from their request.
|
|
4800
|
+
2. bar_chart \u2192 comparing quantities across categories (e.g. sales by region, price by product). Use this when there is only ONE value per category.
|
|
4801
|
+
3. line_chart \u2192 trends or changes over time (dates, months, years, sequential events)
|
|
4802
|
+
4. pie_chart \u2192 proportional breakdown or percentage distribution
|
|
4803
|
+
5. radar_chart \u2192 comparing 2 or more products across MULTIPLE attributes.
|
|
4804
|
+
6. table \u2192 multi-field structured records where each item has \u2265 3 attributes
|
|
4805
|
+
7. text \u2192 conversational or free-form answers where no chart adds value
|
|
4758
4806
|
|
|
4759
4807
|
IMPORTANT:
|
|
4760
4808
|
- Aggregate numeric values from the raw data \u2014 do not pass raw object arrays as data.
|