@aivue/tabular-intelligence 1.0.0 → 1.1.0
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/README.md +132 -0
- package/dist/composables/useTabularIntelligence.d.ts +13 -1
- package/dist/composables/useTabularIntelligence.d.ts.map +1 -1
- package/dist/core/TabularIntelligence.d.ts +28 -2
- package/dist/core/TabularIntelligence.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +804 -185
- package/dist/index.mjs.map +1 -1
- package/dist/tabular-intelligence.css +1 -0
- package/dist/types/index.d.ts +82 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/qaEngine.d.ts +61 -0
- package/dist/utils/qaEngine.d.ts.map +1 -0
- package/dist/utils/tableExtractor.d.ts +14 -0
- package/dist/utils/tableExtractor.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,18 +1,425 @@
|
|
|
1
|
-
import { ref as
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { ref as C, defineComponent as F, createElementBlock as d, openBlock as p, createElementVNode as m, createCommentVNode as T, withDirectives as Y, withKeys as j, withModifiers as L, vModelText as W, toDisplayString as v, normalizeClass as X, createTextVNode as Z, Fragment as O, renderList as Q, computed as ee } from "vue";
|
|
2
|
+
function I(l, n) {
|
|
3
|
+
if (l.length === 0)
|
|
4
|
+
return { columns: [], rowCount: 0, name: n };
|
|
5
|
+
const a = l[0];
|
|
6
|
+
return {
|
|
7
|
+
columns: Object.keys(a).map((t) => {
|
|
8
|
+
const s = B(l, t);
|
|
9
|
+
return {
|
|
10
|
+
name: t,
|
|
11
|
+
type: s,
|
|
12
|
+
nullable: l.some((r) => r[t] == null)
|
|
13
|
+
};
|
|
14
|
+
}),
|
|
15
|
+
rowCount: l.length,
|
|
16
|
+
name: n
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function B(l, n) {
|
|
20
|
+
const a = l.map((t) => t[n]).filter((t) => t != null);
|
|
21
|
+
if (a.length === 0) return "string";
|
|
22
|
+
if (a.every((t) => typeof t == "number" || !isNaN(Number(t))))
|
|
23
|
+
return "number";
|
|
24
|
+
if (a.every((t) => typeof t == "boolean" || t === "true" || t === "false"))
|
|
25
|
+
return "boolean";
|
|
26
|
+
if (a.every((t) => !isNaN(Date.parse(t))))
|
|
27
|
+
return "date";
|
|
28
|
+
const e = new Set(a);
|
|
29
|
+
return e.size < a.length * 0.5 && e.size < 20 ? "categorical" : "string";
|
|
30
|
+
}
|
|
31
|
+
function H(l, n, a) {
|
|
32
|
+
const e = l.map((o) => o[n]).filter((o) => o != null), t = e.length, s = l.length - t, r = {
|
|
33
|
+
column: n,
|
|
34
|
+
count: t,
|
|
35
|
+
nullCount: s
|
|
36
|
+
};
|
|
37
|
+
if (a === "number") {
|
|
38
|
+
const o = e.map(Number).filter((i) => !isNaN(i));
|
|
39
|
+
if (o.length > 0) {
|
|
40
|
+
const i = [...o].sort((h, w) => h - w), u = o.reduce((h, w) => h + w, 0);
|
|
41
|
+
r.mean = u / o.length, r.median = i[Math.floor(i.length / 2)], r.min = i[0], r.max = i[i.length - 1];
|
|
42
|
+
const g = o.reduce((h, w) => h + Math.pow(w - r.mean, 2), 0) / o.length;
|
|
43
|
+
r.std = Math.sqrt(g), r.percentiles = {
|
|
44
|
+
25: i[Math.floor(i.length * 0.25)],
|
|
45
|
+
50: r.median,
|
|
46
|
+
75: i[Math.floor(i.length * 0.75)],
|
|
47
|
+
90: i[Math.floor(i.length * 0.9)]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
const o = new Set(e);
|
|
52
|
+
r.uniqueValues = o.size;
|
|
53
|
+
const i = {};
|
|
54
|
+
e.forEach((g) => {
|
|
55
|
+
const h = String(g);
|
|
56
|
+
i[h] = (i[h] || 0) + 1;
|
|
57
|
+
});
|
|
58
|
+
const u = Math.max(...Object.values(i));
|
|
59
|
+
r.mode = Object.keys(i).find((g) => i[g] === u);
|
|
60
|
+
}
|
|
61
|
+
return r;
|
|
62
|
+
}
|
|
63
|
+
function te(l, n, a = 0.5) {
|
|
64
|
+
const e = [], t = 1.5 + (1 - a) * 1.5;
|
|
65
|
+
return n.forEach((s) => {
|
|
66
|
+
const r = l.map((A, b) => ({ value: Number(A[s]), idx: b })).filter((A) => !isNaN(A.value));
|
|
67
|
+
if (r.length === 0) return;
|
|
68
|
+
const o = [...r].sort((A, b) => A.value - b.value), i = o[Math.floor(o.length * 0.25)].value, u = o[Math.floor(o.length * 0.75)].value, g = u - i, h = i - t * g, w = u + t * g;
|
|
69
|
+
r.forEach(({ value: A, idx: b }) => {
|
|
70
|
+
if (A < h || A > w) {
|
|
71
|
+
const _ = e.find((x) => x.rowIndex === b), k = A < h ? `${s}: ${A.toFixed(2)} < ${h.toFixed(2)}` : `${s}: ${A.toFixed(2)} > ${w.toFixed(2)}`;
|
|
72
|
+
_ ? (_.reasons.push(k), _.affectedColumns.push(s), _.score = Math.min(1, _.score + 0.2)) : e.push({
|
|
73
|
+
rowIndex: b,
|
|
74
|
+
row: l[b],
|
|
75
|
+
score: 0.7,
|
|
76
|
+
reasons: [k],
|
|
77
|
+
affectedColumns: [s]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}), e.sort((s, r) => r.score - s.score);
|
|
82
|
+
}
|
|
83
|
+
class P {
|
|
84
|
+
constructor(n) {
|
|
4
85
|
this.config = {
|
|
5
|
-
|
|
6
|
-
|
|
86
|
+
maxTokens: 1e3,
|
|
87
|
+
temperature: 0.3,
|
|
88
|
+
...n
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Answer a question about the table data
|
|
93
|
+
*/
|
|
94
|
+
async answerQuestion(n) {
|
|
95
|
+
const a = Date.now();
|
|
96
|
+
try {
|
|
97
|
+
const { question: e, schema: t, data: s = [], sampleSize: r = 100, includeAggregates: o = !0 } = n, i = s.length > r ? this.sampleData(s, r) : s, u = o ? this.calculateAggregates(s, t) : void 0, g = this.buildPrompt(e, t, i, u, s.length), h = await this.callLLM(g);
|
|
98
|
+
return {
|
|
99
|
+
answer: this.parseResponse(h, e, s.length > r),
|
|
100
|
+
processingTime: Date.now() - a
|
|
101
|
+
};
|
|
102
|
+
} catch (e) {
|
|
103
|
+
return console.error("Q&A error:", e), {
|
|
104
|
+
answer: {
|
|
105
|
+
questionId: this.generateId(),
|
|
106
|
+
text: "I encountered an error while processing your question. Please try again.",
|
|
107
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
108
|
+
confidence: 0,
|
|
109
|
+
cannotAnswer: !0,
|
|
110
|
+
reason: e instanceof Error ? e.message : "Unknown error"
|
|
111
|
+
},
|
|
112
|
+
processingTime: Date.now() - a
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Sample data for large datasets
|
|
118
|
+
*/
|
|
119
|
+
sampleData(n, a) {
|
|
120
|
+
if (n.length <= a)
|
|
121
|
+
return n;
|
|
122
|
+
const e = Math.floor(n.length / a), t = [];
|
|
123
|
+
for (let s = 0; s < n.length && t.length < a; s += e)
|
|
124
|
+
t.push(n[s]);
|
|
125
|
+
return t;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Calculate aggregates for numeric columns
|
|
129
|
+
*/
|
|
130
|
+
calculateAggregates(n, a) {
|
|
131
|
+
const e = {};
|
|
132
|
+
for (const t of a.columns)
|
|
133
|
+
if (t.type === "number" && n.length > 0)
|
|
134
|
+
try {
|
|
135
|
+
const s = H(n, t.name, "number");
|
|
136
|
+
e[t.name] = {
|
|
137
|
+
mean: s.mean,
|
|
138
|
+
median: s.median,
|
|
139
|
+
min: s.min,
|
|
140
|
+
max: s.max,
|
|
141
|
+
count: s.count
|
|
142
|
+
};
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
else if (t.type === "categorical" || t.type === "string") {
|
|
146
|
+
const s = n.map((o) => o[t.name]).filter((o) => o != null), r = new Set(s);
|
|
147
|
+
e[t.name] = {
|
|
148
|
+
uniqueCount: r.size,
|
|
149
|
+
totalCount: s.length,
|
|
150
|
+
topValues: this.getTopValues(s, 5)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return e;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get top N most frequent values
|
|
157
|
+
*/
|
|
158
|
+
getTopValues(n, a) {
|
|
159
|
+
const e = /* @__PURE__ */ new Map();
|
|
160
|
+
for (const t of n)
|
|
161
|
+
e.set(t, (e.get(t) || 0) + 1);
|
|
162
|
+
return Array.from(e.entries()).map(([t, s]) => ({ value: t, count: s })).sort((t, s) => s.count - t.count).slice(0, a);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Build prompt for LLM
|
|
166
|
+
*/
|
|
167
|
+
buildPrompt(n, a, e, t, s) {
|
|
168
|
+
const r = s && s > e.length;
|
|
169
|
+
let o = `You are a data analyst assistant. Answer the following question about a table dataset.
|
|
170
|
+
|
|
171
|
+
`;
|
|
172
|
+
o += `**Table Schema:**
|
|
173
|
+
`, o += `Table: ${a.name}
|
|
174
|
+
`, o += `Columns:
|
|
175
|
+
`;
|
|
176
|
+
for (const i of a.columns)
|
|
177
|
+
o += `- ${i.name} (${i.type})
|
|
178
|
+
`;
|
|
179
|
+
return o += `
|
|
180
|
+
`, t && Object.keys(t).length > 0 && (o += `**Summary Statistics:**
|
|
181
|
+
`, o += JSON.stringify(t, null, 2), o += `
|
|
182
|
+
|
|
183
|
+
`), o += `**Sample Data** (${e.length} rows${r ? ` out of ${s} total` : ""}):
|
|
184
|
+
`, o += JSON.stringify(e.slice(0, 10), null, 2), o += `
|
|
185
|
+
|
|
186
|
+
`, o += `**Question:** ${n}
|
|
187
|
+
|
|
188
|
+
`, o += `**Instructions:**
|
|
189
|
+
`, o += `1. Answer ONLY based on the data provided above.
|
|
190
|
+
`, o += `2. If the question cannot be answered from the available data, clearly state "I cannot answer this question from the available data" and explain why.
|
|
191
|
+
`, o += `3. Provide a clear, concise answer.
|
|
192
|
+
`, o += `4. Include specific numbers or examples from the data when relevant.
|
|
193
|
+
`, o += `5. If the answer is based on sampled data, mention that it's an approximation.
|
|
194
|
+
`, o += `6. Format your response as JSON with the following structure:
|
|
195
|
+
`, o += `{
|
|
196
|
+
`, o += ` "answer": "Your answer text here",
|
|
197
|
+
`, o += ` "confidence": 0.0-1.0,
|
|
198
|
+
`, o += ` "cannotAnswer": false,
|
|
199
|
+
`, o += ` "isApproximate": ${r},
|
|
200
|
+
`, o += ` "supportingData": { "key": "value" } // optional
|
|
201
|
+
`, o += `}
|
|
202
|
+
`, o;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Call LLM API
|
|
206
|
+
*/
|
|
207
|
+
async callLLM(n) {
|
|
208
|
+
const { provider: a, apiKey: e, baseUrl: t, model: s, maxTokens: r, temperature: o } = this.config;
|
|
209
|
+
if (a === "openai")
|
|
210
|
+
return this.callOpenAI(n, e, s || "gpt-4-turbo-preview", r, o);
|
|
211
|
+
if (a === "anthropic")
|
|
212
|
+
return this.callAnthropic(n, e, s || "claude-3-5-sonnet-20241022", r, o);
|
|
213
|
+
if (a === "custom" && t)
|
|
214
|
+
return this.callCustomAPI(n, t, e);
|
|
215
|
+
throw new Error(`Unsupported provider: ${a}`);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Call OpenAI API
|
|
219
|
+
*/
|
|
220
|
+
async callOpenAI(n, a, e, t, s) {
|
|
221
|
+
var i, u;
|
|
222
|
+
const r = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: {
|
|
225
|
+
"Content-Type": "application/json",
|
|
226
|
+
Authorization: `Bearer ${a}`
|
|
227
|
+
},
|
|
228
|
+
body: JSON.stringify({
|
|
229
|
+
model: e,
|
|
230
|
+
messages: [{ role: "user", content: n }],
|
|
231
|
+
max_tokens: t,
|
|
232
|
+
temperature: s,
|
|
233
|
+
response_format: { type: "json_object" }
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
if (!r.ok)
|
|
237
|
+
throw new Error(`OpenAI API error: ${r.statusText}`);
|
|
238
|
+
return ((u = (i = (await r.json()).choices[0]) == null ? void 0 : i.message) == null ? void 0 : u.content) || "";
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Call Anthropic API
|
|
242
|
+
*/
|
|
243
|
+
async callAnthropic(n, a, e, t, s) {
|
|
244
|
+
var i;
|
|
245
|
+
const r = await fetch("https://api.anthropic.com/v1/messages", {
|
|
246
|
+
method: "POST",
|
|
247
|
+
headers: {
|
|
248
|
+
"Content-Type": "application/json",
|
|
249
|
+
"x-api-key": a,
|
|
250
|
+
"anthropic-version": "2023-06-01"
|
|
251
|
+
},
|
|
252
|
+
body: JSON.stringify({
|
|
253
|
+
model: e,
|
|
254
|
+
max_tokens: t,
|
|
255
|
+
temperature: s,
|
|
256
|
+
messages: [{ role: "user", content: n }]
|
|
257
|
+
})
|
|
258
|
+
});
|
|
259
|
+
if (!r.ok)
|
|
260
|
+
throw new Error(`Anthropic API error: ${r.statusText}`);
|
|
261
|
+
return ((i = (await r.json()).content[0]) == null ? void 0 : i.text) || "";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Call custom API
|
|
265
|
+
*/
|
|
266
|
+
async callCustomAPI(n, a, e) {
|
|
267
|
+
const t = {
|
|
268
|
+
"Content-Type": "application/json"
|
|
7
269
|
};
|
|
270
|
+
e && (t.Authorization = `Bearer ${e}`);
|
|
271
|
+
const s = await fetch(a, {
|
|
272
|
+
method: "POST",
|
|
273
|
+
headers: t,
|
|
274
|
+
body: JSON.stringify({ prompt: n })
|
|
275
|
+
});
|
|
276
|
+
if (!s.ok)
|
|
277
|
+
throw new Error(`Custom API error: ${s.statusText}`);
|
|
278
|
+
const r = await s.json();
|
|
279
|
+
return r.response || r.answer || JSON.stringify(r);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Parse LLM response
|
|
283
|
+
*/
|
|
284
|
+
parseResponse(n, a, e) {
|
|
285
|
+
try {
|
|
286
|
+
const t = JSON.parse(n);
|
|
287
|
+
return {
|
|
288
|
+
questionId: this.generateId(),
|
|
289
|
+
text: t.answer || t.text || n,
|
|
290
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
291
|
+
confidence: t.confidence || 0.8,
|
|
292
|
+
cannotAnswer: t.cannotAnswer || !1,
|
|
293
|
+
isApproximate: t.isApproximate !== void 0 ? t.isApproximate : e,
|
|
294
|
+
supportingData: t.supportingData,
|
|
295
|
+
reason: t.reason
|
|
296
|
+
};
|
|
297
|
+
} catch {
|
|
298
|
+
return {
|
|
299
|
+
questionId: this.generateId(),
|
|
300
|
+
text: n,
|
|
301
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
302
|
+
confidence: 0.7,
|
|
303
|
+
isApproximate: e
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Generate unique ID
|
|
309
|
+
*/
|
|
310
|
+
generateId() {
|
|
311
|
+
return `qa_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function ne(l = {}) {
|
|
315
|
+
const {
|
|
316
|
+
selector: n = "table",
|
|
317
|
+
includeHeaders: a = !0,
|
|
318
|
+
maxRows: e,
|
|
319
|
+
inferTypes: t = !0,
|
|
320
|
+
skipEmptyRows: s = !0
|
|
321
|
+
} = l, r = document.querySelector(n);
|
|
322
|
+
if (!r || r.tagName !== "TABLE")
|
|
323
|
+
return console.warn(`No table found with selector: ${n}`), null;
|
|
324
|
+
const i = Array.from(r.rows);
|
|
325
|
+
if (i.length === 0)
|
|
326
|
+
return null;
|
|
327
|
+
let u = [], g = 0;
|
|
328
|
+
if (a && i[0]) {
|
|
329
|
+
const b = i[0];
|
|
330
|
+
u = Array.from(b.cells).map((_, k) => {
|
|
331
|
+
var S;
|
|
332
|
+
return ((S = _.textContent) == null ? void 0 : S.trim()) || "" || `Column${k + 1}`;
|
|
333
|
+
}), g = 1;
|
|
334
|
+
} else {
|
|
335
|
+
const b = i[0];
|
|
336
|
+
u = Array.from(b.cells).map((_, k) => `Column${k + 1}`);
|
|
337
|
+
}
|
|
338
|
+
const h = [], w = e ? i.slice(g, g + e) : i.slice(g);
|
|
339
|
+
for (const b of w) {
|
|
340
|
+
const _ = Array.from(b.cells);
|
|
341
|
+
if (s && _.every((x) => {
|
|
342
|
+
var S;
|
|
343
|
+
return !((S = x.textContent) != null && S.trim());
|
|
344
|
+
}))
|
|
345
|
+
continue;
|
|
346
|
+
const k = {};
|
|
347
|
+
_.forEach((x, S) => {
|
|
348
|
+
var M;
|
|
349
|
+
const z = u[S] || `Column${S + 1}`;
|
|
350
|
+
let q = ((M = x.textContent) == null ? void 0 : M.trim()) || "";
|
|
351
|
+
if (t && q) {
|
|
352
|
+
const N = parseFloat(q);
|
|
353
|
+
!isNaN(N) && q === N.toString() && (q = N);
|
|
354
|
+
}
|
|
355
|
+
k[z] = q;
|
|
356
|
+
}), h.push(k);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
schema: t && h.length > 0 ? I(h, "Extracted Table") : ae(u, h.length),
|
|
360
|
+
data: h,
|
|
361
|
+
source: "dom",
|
|
362
|
+
metadata: {
|
|
363
|
+
selector: n,
|
|
364
|
+
rowCount: h.length,
|
|
365
|
+
columnCount: u.length,
|
|
366
|
+
extractedAt: /* @__PURE__ */ new Date()
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function se(l, n, a = {}) {
|
|
371
|
+
const { maxRows: e, inferTypes: t = !0 } = a, s = e ? l.slice(0, e) : l;
|
|
372
|
+
let r;
|
|
373
|
+
return n && n.length > 0 ? r = {
|
|
374
|
+
name: "Vue Data Grid",
|
|
375
|
+
columns: n.map((o) => ({
|
|
376
|
+
name: o.field,
|
|
377
|
+
type: t && s.length > 0 ? B(s, o.field) : "string",
|
|
378
|
+
nullable: !0
|
|
379
|
+
})),
|
|
380
|
+
rowCount: s.length
|
|
381
|
+
} : s.length > 0 ? r = I(s, "Vue Data Grid") : r = { name: "Vue Data Grid", columns: [], rowCount: 0 }, {
|
|
382
|
+
schema: r,
|
|
383
|
+
data: s,
|
|
384
|
+
source: "vue",
|
|
385
|
+
metadata: {
|
|
386
|
+
rowCount: s.length,
|
|
387
|
+
columnCount: r.columns.length,
|
|
388
|
+
extractedAt: /* @__PURE__ */ new Date()
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function ae(l, n = 0) {
|
|
393
|
+
return {
|
|
394
|
+
name: "Extracted Table",
|
|
395
|
+
columns: l.map((a) => ({
|
|
396
|
+
name: a,
|
|
397
|
+
type: "string",
|
|
398
|
+
nullable: !0
|
|
399
|
+
})),
|
|
400
|
+
rowCount: n
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
class oe {
|
|
404
|
+
constructor(n, a) {
|
|
405
|
+
this.config = {
|
|
406
|
+
timeout: 3e4,
|
|
407
|
+
...n
|
|
408
|
+
}, a && (this.qaEngine = new P(a));
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Initialize or update Q&A engine
|
|
412
|
+
*/
|
|
413
|
+
initializeQA(n) {
|
|
414
|
+
this.qaEngine = new P(n);
|
|
8
415
|
}
|
|
9
416
|
/**
|
|
10
417
|
* Generic API call to TFM endpoint
|
|
11
418
|
*/
|
|
12
|
-
async callTFM(
|
|
13
|
-
const
|
|
419
|
+
async callTFM(n) {
|
|
420
|
+
const a = Date.now();
|
|
14
421
|
try {
|
|
15
|
-
const
|
|
422
|
+
const e = await fetch(this.config.baseUrl, {
|
|
16
423
|
method: "POST",
|
|
17
424
|
headers: {
|
|
18
425
|
"Content-Type": "application/json",
|
|
@@ -20,31 +427,31 @@ class N {
|
|
|
20
427
|
...this.config.headers
|
|
21
428
|
},
|
|
22
429
|
body: JSON.stringify({
|
|
23
|
-
...
|
|
430
|
+
...n,
|
|
24
431
|
model: this.config.model
|
|
25
432
|
}),
|
|
26
433
|
signal: AbortSignal.timeout(this.config.timeout || 3e4)
|
|
27
434
|
});
|
|
28
|
-
if (!
|
|
29
|
-
const r = await
|
|
30
|
-
throw new Error(`TFM API error: ${
|
|
435
|
+
if (!e.ok) {
|
|
436
|
+
const r = await e.text();
|
|
437
|
+
throw new Error(`TFM API error: ${e.status} - ${r}`);
|
|
31
438
|
}
|
|
32
|
-
const t = await
|
|
439
|
+
const t = await e.json(), s = Date.now() - a;
|
|
33
440
|
return {
|
|
34
441
|
success: !0,
|
|
35
442
|
result: t.result || t,
|
|
36
443
|
metadata: {
|
|
37
|
-
processingTime:
|
|
444
|
+
processingTime: s,
|
|
38
445
|
model: this.config.model || "unknown",
|
|
39
446
|
version: t.version
|
|
40
447
|
}
|
|
41
448
|
};
|
|
42
|
-
} catch (
|
|
449
|
+
} catch (e) {
|
|
43
450
|
return {
|
|
44
451
|
success: !1,
|
|
45
|
-
error:
|
|
452
|
+
error: e instanceof Error ? e.message : "Unknown error",
|
|
46
453
|
metadata: {
|
|
47
|
-
processingTime: Date.now() -
|
|
454
|
+
processingTime: Date.now() - a,
|
|
48
455
|
model: this.config.model || "unknown"
|
|
49
456
|
}
|
|
50
457
|
};
|
|
@@ -53,255 +460,467 @@ class N {
|
|
|
53
460
|
/**
|
|
54
461
|
* Perform analysis on tabular data
|
|
55
462
|
*/
|
|
56
|
-
async analyze(
|
|
57
|
-
const
|
|
58
|
-
operation:
|
|
59
|
-
data:
|
|
60
|
-
schema:
|
|
61
|
-
parameters:
|
|
62
|
-
},
|
|
63
|
-
if (!
|
|
64
|
-
throw new Error(
|
|
65
|
-
return this.parseAnalysisResult(
|
|
463
|
+
async analyze(n) {
|
|
464
|
+
const a = {
|
|
465
|
+
operation: n.type,
|
|
466
|
+
data: n.data,
|
|
467
|
+
schema: n.schema,
|
|
468
|
+
parameters: n.options
|
|
469
|
+
}, e = await this.callTFM(a);
|
|
470
|
+
if (!e.success)
|
|
471
|
+
throw new Error(e.error || "Analysis failed");
|
|
472
|
+
return this.parseAnalysisResult(n.type, e.result, e.metadata);
|
|
66
473
|
}
|
|
67
474
|
/**
|
|
68
475
|
* Parse TFM response into structured AnalysisResult
|
|
69
476
|
*/
|
|
70
|
-
parseAnalysisResult(
|
|
477
|
+
parseAnalysisResult(n, a, e) {
|
|
71
478
|
const t = {
|
|
72
|
-
type:
|
|
479
|
+
type: n,
|
|
73
480
|
timestamp: /* @__PURE__ */ new Date(),
|
|
74
|
-
summary:
|
|
75
|
-
insights:
|
|
76
|
-
recommendations:
|
|
77
|
-
confidence:
|
|
78
|
-
processingTime:
|
|
481
|
+
summary: a.summary || "",
|
|
482
|
+
insights: a.insights || [],
|
|
483
|
+
recommendations: a.recommendations,
|
|
484
|
+
confidence: a.confidence || 0.8,
|
|
485
|
+
processingTime: e == null ? void 0 : e.processingTime
|
|
79
486
|
};
|
|
80
|
-
switch (
|
|
487
|
+
switch (n) {
|
|
81
488
|
case "descriptive_stats":
|
|
82
489
|
return {
|
|
83
490
|
...t,
|
|
84
|
-
descriptiveStats:
|
|
491
|
+
descriptiveStats: a.stats || a.descriptiveStats
|
|
85
492
|
};
|
|
86
493
|
case "anomaly_detection":
|
|
87
494
|
return {
|
|
88
495
|
...t,
|
|
89
|
-
anomalies:
|
|
496
|
+
anomalies: a.anomalies || []
|
|
90
497
|
};
|
|
91
498
|
case "segmentation":
|
|
92
499
|
case "clustering":
|
|
93
500
|
return {
|
|
94
501
|
...t,
|
|
95
|
-
clusters:
|
|
502
|
+
clusters: a.clusters || []
|
|
96
503
|
};
|
|
97
504
|
case "prediction":
|
|
98
505
|
return {
|
|
99
506
|
...t,
|
|
100
|
-
predictions:
|
|
507
|
+
predictions: a.predictions || a
|
|
101
508
|
};
|
|
102
509
|
case "correlation":
|
|
103
510
|
return {
|
|
104
511
|
...t,
|
|
105
|
-
correlations:
|
|
512
|
+
correlations: a.correlations || a
|
|
513
|
+
};
|
|
514
|
+
case "summary":
|
|
515
|
+
return {
|
|
516
|
+
...t,
|
|
517
|
+
aiSummary: a.summary || a
|
|
518
|
+
};
|
|
519
|
+
case "qa":
|
|
520
|
+
return {
|
|
521
|
+
...t,
|
|
522
|
+
qaAnswer: a.answer || a
|
|
106
523
|
};
|
|
107
524
|
default:
|
|
108
525
|
return t;
|
|
109
526
|
}
|
|
110
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Ask a question about the data (Q&A)
|
|
530
|
+
*/
|
|
531
|
+
async askQuestion(n) {
|
|
532
|
+
if (!this.qaEngine)
|
|
533
|
+
throw new Error("Q&A engine not initialized. Call initializeQA() first.");
|
|
534
|
+
return this.qaEngine.answerQuestion(n);
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Generate AI summary of table data
|
|
538
|
+
*/
|
|
539
|
+
async generateSummary(n, a) {
|
|
540
|
+
const e = {
|
|
541
|
+
type: "summary",
|
|
542
|
+
data: n,
|
|
543
|
+
schema: a
|
|
544
|
+
}, t = await this.analyze(e);
|
|
545
|
+
if (!t.aiSummary)
|
|
546
|
+
throw new Error("Failed to generate summary");
|
|
547
|
+
return t.aiSummary;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Extract table from DOM
|
|
551
|
+
*/
|
|
552
|
+
extractFromDOM(n) {
|
|
553
|
+
return ne(n);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Normalize Vue data grid data
|
|
557
|
+
*/
|
|
558
|
+
normalizeVueData(n, a, e) {
|
|
559
|
+
return se(n, a, e);
|
|
560
|
+
}
|
|
111
561
|
/**
|
|
112
562
|
* Update configuration
|
|
113
563
|
*/
|
|
114
|
-
updateConfig(
|
|
115
|
-
this.config = { ...this.config, ...
|
|
564
|
+
updateConfig(n) {
|
|
565
|
+
this.config = { ...this.config, ...n };
|
|
116
566
|
}
|
|
117
567
|
/**
|
|
118
568
|
* Get current configuration (without sensitive data)
|
|
119
569
|
*/
|
|
120
570
|
getConfig() {
|
|
121
|
-
const { apiKey:
|
|
122
|
-
return
|
|
571
|
+
const { apiKey: n, ...a } = this.config;
|
|
572
|
+
return a;
|
|
123
573
|
}
|
|
124
574
|
}
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
columns: Object.keys(e).map((t) => {
|
|
131
|
-
const i = $(c, t);
|
|
132
|
-
return {
|
|
133
|
-
name: t,
|
|
134
|
-
type: i,
|
|
135
|
-
nullable: c.some((r) => r[t] == null)
|
|
136
|
-
};
|
|
137
|
-
}),
|
|
138
|
-
rowCount: c.length,
|
|
139
|
-
name: s
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function $(c, s) {
|
|
143
|
-
const e = c.map((t) => t[s]).filter((t) => t != null);
|
|
144
|
-
if (e.length === 0) return "string";
|
|
145
|
-
if (e.every((t) => typeof t == "number" || !isNaN(Number(t))))
|
|
146
|
-
return "number";
|
|
147
|
-
if (e.every((t) => typeof t == "boolean" || t === "true" || t === "false"))
|
|
148
|
-
return "boolean";
|
|
149
|
-
if (e.every((t) => !isNaN(Date.parse(t))))
|
|
150
|
-
return "date";
|
|
151
|
-
const n = new Set(e);
|
|
152
|
-
return n.size < e.length * 0.5 && n.size < 20 ? "categorical" : "string";
|
|
153
|
-
}
|
|
154
|
-
function A(c, s, e) {
|
|
155
|
-
const n = c.map((l) => l[s]).filter((l) => l != null), t = n.length, i = c.length - t, r = {
|
|
156
|
-
column: s,
|
|
157
|
-
count: t,
|
|
158
|
-
nullCount: i
|
|
159
|
-
};
|
|
160
|
-
if (e === "number") {
|
|
161
|
-
const l = n.map(Number).filter((o) => !isNaN(o));
|
|
162
|
-
if (l.length > 0) {
|
|
163
|
-
const o = [...l].sort((u, d) => u - d), p = l.reduce((u, d) => u + d, 0);
|
|
164
|
-
r.mean = p / l.length, r.median = o[Math.floor(o.length / 2)], r.min = o[0], r.max = o[o.length - 1];
|
|
165
|
-
const h = l.reduce((u, d) => u + Math.pow(d - r.mean, 2), 0) / l.length;
|
|
166
|
-
r.std = Math.sqrt(h), r.percentiles = {
|
|
167
|
-
25: o[Math.floor(o.length * 0.25)],
|
|
168
|
-
50: r.median,
|
|
169
|
-
75: o[Math.floor(o.length * 0.75)],
|
|
170
|
-
90: o[Math.floor(o.length * 0.9)]
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
const l = new Set(n);
|
|
175
|
-
r.uniqueValues = l.size;
|
|
176
|
-
const o = {};
|
|
177
|
-
n.forEach((h) => {
|
|
178
|
-
const u = String(h);
|
|
179
|
-
o[u] = (o[u] || 0) + 1;
|
|
180
|
-
});
|
|
181
|
-
const p = Math.max(...Object.values(o));
|
|
182
|
-
r.mode = Object.keys(o).find((h) => o[h] === p);
|
|
183
|
-
}
|
|
184
|
-
return r;
|
|
185
|
-
}
|
|
186
|
-
function F(c, s, e = 0.5) {
|
|
187
|
-
const n = [], t = 1.5 + (1 - e) * 1.5;
|
|
188
|
-
return s.forEach((i) => {
|
|
189
|
-
const r = c.map((m, g) => ({ value: Number(m[i]), idx: g })).filter((m) => !isNaN(m.value));
|
|
190
|
-
if (r.length === 0) return;
|
|
191
|
-
const l = [...r].sort((m, g) => m.value - g.value), o = l[Math.floor(l.length * 0.25)].value, p = l[Math.floor(l.length * 0.75)].value, h = p - o, u = o - t * h, d = p + t * h;
|
|
192
|
-
r.forEach(({ value: m, idx: g }) => {
|
|
193
|
-
if (m < u || m > d) {
|
|
194
|
-
const v = n.find((a) => a.rowIndex === g), S = m < u ? `${i}: ${m.toFixed(2)} < ${u.toFixed(2)}` : `${i}: ${m.toFixed(2)} > ${d.toFixed(2)}`;
|
|
195
|
-
v ? (v.reasons.push(S), v.affectedColumns.push(i), v.score = Math.min(1, v.score + 0.2)) : n.push({
|
|
196
|
-
rowIndex: g,
|
|
197
|
-
row: c[g],
|
|
198
|
-
score: 0.7,
|
|
199
|
-
reasons: [S],
|
|
200
|
-
affectedColumns: [i]
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
}), n.sort((i, r) => r.score - i.score);
|
|
205
|
-
}
|
|
206
|
-
function E(c) {
|
|
207
|
-
const s = new N(c.config), e = M(!1), n = M(null), t = M(null), i = c.data || M([]), r = c.schema || M(null), l = c.useLocalFallback !== !1;
|
|
208
|
-
async function o(a, f) {
|
|
209
|
-
e.value = !0, n.value = null;
|
|
575
|
+
function Be(l) {
|
|
576
|
+
const n = new oe(l.config, l.qaConfig), a = C(!1), e = C(null), t = C(null), s = l.data || C([]), r = l.schema || C(null), o = C([]), i = C([]), u = C(null), g = l.maxQuestionHistory || 50, h = l.useLocalFallback !== !1;
|
|
577
|
+
async function w(c, f) {
|
|
578
|
+
a.value = !0, e.value = null;
|
|
210
579
|
try {
|
|
211
580
|
const y = {
|
|
212
|
-
type:
|
|
213
|
-
data:
|
|
581
|
+
type: c,
|
|
582
|
+
data: s.value,
|
|
214
583
|
schema: r.value || void 0,
|
|
215
584
|
options: f
|
|
216
|
-
},
|
|
217
|
-
return t.value =
|
|
585
|
+
}, $ = await n.analyze(y);
|
|
586
|
+
return t.value = $, $;
|
|
218
587
|
} catch (y) {
|
|
219
|
-
if (
|
|
220
|
-
return
|
|
221
|
-
throw
|
|
588
|
+
if (e.value = y instanceof Error ? y : new Error("Analysis failed"), h)
|
|
589
|
+
return A(c, f);
|
|
590
|
+
throw e.value;
|
|
222
591
|
} finally {
|
|
223
|
-
|
|
592
|
+
a.value = !1;
|
|
224
593
|
}
|
|
225
594
|
}
|
|
226
|
-
function
|
|
227
|
-
const y = r.value ||
|
|
228
|
-
switch (
|
|
595
|
+
function A(c, f) {
|
|
596
|
+
const y = r.value || I(s.value);
|
|
597
|
+
switch (c) {
|
|
229
598
|
case "descriptive_stats": {
|
|
230
|
-
const
|
|
231
|
-
(
|
|
599
|
+
const $ = y.columns.map(
|
|
600
|
+
(E) => H(s.value, E.name, E.type)
|
|
232
601
|
);
|
|
233
602
|
return {
|
|
234
|
-
type:
|
|
603
|
+
type: c,
|
|
235
604
|
timestamp: /* @__PURE__ */ new Date(),
|
|
236
|
-
descriptiveStats:
|
|
237
|
-
summary: `Calculated statistics for ${
|
|
605
|
+
descriptiveStats: $,
|
|
606
|
+
summary: `Calculated statistics for ${$.length} columns`,
|
|
238
607
|
insights: [],
|
|
239
608
|
confidence: 0.9
|
|
240
609
|
};
|
|
241
610
|
}
|
|
242
611
|
case "anomaly_detection": {
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
612
|
+
const $ = y.columns.filter((D) => D.type === "number").map((D) => D.name), E = te(
|
|
613
|
+
s.value,
|
|
614
|
+
$,
|
|
246
615
|
f == null ? void 0 : f.sensitivity
|
|
247
616
|
);
|
|
248
617
|
return {
|
|
249
|
-
type:
|
|
618
|
+
type: c,
|
|
250
619
|
timestamp: /* @__PURE__ */ new Date(),
|
|
251
|
-
anomalies:
|
|
252
|
-
summary: `Found ${
|
|
253
|
-
insights:
|
|
620
|
+
anomalies: E,
|
|
621
|
+
summary: `Found ${E.length} anomalies`,
|
|
622
|
+
insights: E.slice(0, 3).map((D) => D.reasons[0]),
|
|
254
623
|
confidence: 0.8
|
|
255
624
|
};
|
|
256
625
|
}
|
|
257
626
|
default:
|
|
258
|
-
throw new Error(`Local analysis not supported for type: ${
|
|
627
|
+
throw new Error(`Local analysis not supported for type: ${c}`);
|
|
259
628
|
}
|
|
260
629
|
}
|
|
261
|
-
async function
|
|
262
|
-
return (await
|
|
630
|
+
async function b() {
|
|
631
|
+
return (await w("descriptive_stats")).descriptiveStats || [];
|
|
263
632
|
}
|
|
264
|
-
async function
|
|
265
|
-
return (await
|
|
633
|
+
async function _(c, f) {
|
|
634
|
+
return (await w("anomaly_detection", { sensitivity: f, features: c })).anomalies || [];
|
|
266
635
|
}
|
|
267
|
-
async function
|
|
268
|
-
return
|
|
636
|
+
async function k(c, f = 3) {
|
|
637
|
+
return w("clustering", { features: c, numClusters: f });
|
|
269
638
|
}
|
|
270
|
-
async function
|
|
271
|
-
return
|
|
639
|
+
async function x(c, f) {
|
|
640
|
+
return w("prediction", { targetColumn: c, ...f });
|
|
272
641
|
}
|
|
273
|
-
function
|
|
274
|
-
|
|
642
|
+
function S(c) {
|
|
643
|
+
n.updateConfig(c);
|
|
275
644
|
}
|
|
276
|
-
function
|
|
277
|
-
|
|
645
|
+
function z(c, f = !0) {
|
|
646
|
+
s.value = c, f && (r.value = I(c));
|
|
278
647
|
}
|
|
279
|
-
function
|
|
280
|
-
|
|
648
|
+
function q() {
|
|
649
|
+
a.value = !1, e.value = null, t.value = null, o.value = [], i.value = [], u.value = null;
|
|
650
|
+
}
|
|
651
|
+
async function M(c, f) {
|
|
652
|
+
a.value = !0, e.value = null;
|
|
653
|
+
try {
|
|
654
|
+
const y = r.value || I(s.value), $ = {
|
|
655
|
+
question: c,
|
|
656
|
+
schema: y,
|
|
657
|
+
data: s.value,
|
|
658
|
+
sampleSize: 100,
|
|
659
|
+
includeAggregates: !0,
|
|
660
|
+
...f
|
|
661
|
+
}, D = (await n.askQuestion($)).answer, G = {
|
|
662
|
+
id: D.questionId,
|
|
663
|
+
text: c,
|
|
664
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
665
|
+
context: {
|
|
666
|
+
tableSchema: y,
|
|
667
|
+
rowCount: s.value.length
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
return o.value.push(G), i.value.push(D), u.value = D, o.value.length > g && (o.value.shift(), i.value.shift()), D;
|
|
671
|
+
} catch (y) {
|
|
672
|
+
throw e.value = y instanceof Error ? y : new Error("Q&A failed"), e.value;
|
|
673
|
+
} finally {
|
|
674
|
+
a.value = !1;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
async function N() {
|
|
678
|
+
a.value = !0, e.value = null;
|
|
679
|
+
try {
|
|
680
|
+
const c = r.value || I(s.value);
|
|
681
|
+
return await n.generateSummary(s.value, c);
|
|
682
|
+
} catch (c) {
|
|
683
|
+
throw e.value = c instanceof Error ? c : new Error("Summary generation failed"), e.value;
|
|
684
|
+
} finally {
|
|
685
|
+
a.value = !1;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
function R() {
|
|
689
|
+
o.value = [], i.value = [], u.value = null;
|
|
690
|
+
}
|
|
691
|
+
function J(c) {
|
|
692
|
+
const f = n.extractFromDOM(c);
|
|
693
|
+
return f && (s.value = f.data, r.value = f.schema), f;
|
|
694
|
+
}
|
|
695
|
+
function K(c, f, y) {
|
|
696
|
+
const $ = n.normalizeVueData(c, f, y);
|
|
697
|
+
s.value = $.data, r.value = $.schema;
|
|
698
|
+
}
|
|
699
|
+
function U(c) {
|
|
700
|
+
n.initializeQA(c);
|
|
281
701
|
}
|
|
282
702
|
return {
|
|
283
|
-
client:
|
|
284
|
-
loading:
|
|
285
|
-
error:
|
|
703
|
+
client: n,
|
|
704
|
+
loading: a,
|
|
705
|
+
error: e,
|
|
286
706
|
lastResult: t,
|
|
287
|
-
data:
|
|
707
|
+
data: s,
|
|
288
708
|
schema: r,
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
709
|
+
questionHistory: o,
|
|
710
|
+
answerHistory: i,
|
|
711
|
+
lastAnswer: u,
|
|
712
|
+
analyze: w,
|
|
713
|
+
getDescriptiveStats: b,
|
|
714
|
+
detectAnomalies: _,
|
|
715
|
+
performClustering: k,
|
|
716
|
+
predict: x,
|
|
717
|
+
askQuestion: M,
|
|
718
|
+
generateSummary: N,
|
|
719
|
+
clearHistory: R,
|
|
720
|
+
extractFromDOM: J,
|
|
721
|
+
loadFromVueGrid: K,
|
|
722
|
+
updateConfig: S,
|
|
723
|
+
initializeQA: U,
|
|
724
|
+
setData: z,
|
|
725
|
+
reset: q
|
|
297
726
|
};
|
|
298
727
|
}
|
|
728
|
+
const re = { class: "ti-question-input" }, ie = { class: "ti-input-wrapper" }, le = ["placeholder", "disabled", "onKeydown"], ce = ["disabled"], ue = { key: 0 }, me = {
|
|
729
|
+
key: 1,
|
|
730
|
+
class: "ti-loading"
|
|
731
|
+
}, de = {
|
|
732
|
+
key: 0,
|
|
733
|
+
class: "ti-hint"
|
|
734
|
+
}, pe = /* @__PURE__ */ F({
|
|
735
|
+
__name: "QuestionInput",
|
|
736
|
+
props: {
|
|
737
|
+
placeholder: { default: "Ask a question about this data..." },
|
|
738
|
+
submitLabel: { default: "Ask" },
|
|
739
|
+
loadingLabel: { default: "Processing..." },
|
|
740
|
+
hint: { default: "Press Enter to submit, Shift+Enter for new line" },
|
|
741
|
+
showHint: { type: Boolean, default: !0 },
|
|
742
|
+
disabled: { type: Boolean, default: !1 },
|
|
743
|
+
loading: { type: Boolean, default: !1 }
|
|
744
|
+
},
|
|
745
|
+
emits: ["submit"],
|
|
746
|
+
setup(l, { emit: n }) {
|
|
747
|
+
const a = l, e = n, t = C("");
|
|
748
|
+
function s() {
|
|
749
|
+
t.value.trim() && !a.disabled && !a.loading && (e("submit", t.value.trim()), t.value = "");
|
|
750
|
+
}
|
|
751
|
+
function r(o) {
|
|
752
|
+
}
|
|
753
|
+
return (o, i) => (p(), d("div", re, [
|
|
754
|
+
m("div", ie, [
|
|
755
|
+
Y(m("textarea", {
|
|
756
|
+
"onUpdate:modelValue": i[0] || (i[0] = (u) => t.value = u),
|
|
757
|
+
placeholder: o.placeholder,
|
|
758
|
+
disabled: o.disabled,
|
|
759
|
+
class: "ti-textarea",
|
|
760
|
+
rows: "2",
|
|
761
|
+
onKeydown: [
|
|
762
|
+
j(L(s, ["exact", "prevent"]), ["enter"]),
|
|
763
|
+
j(L(r, ["shift"]), ["enter"])
|
|
764
|
+
]
|
|
765
|
+
}, null, 40, le), [
|
|
766
|
+
[W, t.value]
|
|
767
|
+
]),
|
|
768
|
+
m("button", {
|
|
769
|
+
disabled: o.disabled || !t.value.trim(),
|
|
770
|
+
class: "ti-submit-btn",
|
|
771
|
+
onClick: s
|
|
772
|
+
}, [
|
|
773
|
+
o.loading ? (p(), d("span", me, v(o.loadingLabel), 1)) : (p(), d("span", ue, v(o.submitLabel), 1))
|
|
774
|
+
], 8, ce)
|
|
775
|
+
]),
|
|
776
|
+
o.showHint ? (p(), d("div", de, v(o.hint), 1)) : T("", !0)
|
|
777
|
+
]));
|
|
778
|
+
}
|
|
779
|
+
}), V = (l, n) => {
|
|
780
|
+
const a = l.__vccOpts || l;
|
|
781
|
+
for (const [e, t] of n)
|
|
782
|
+
a[e] = t;
|
|
783
|
+
return a;
|
|
784
|
+
}, He = /* @__PURE__ */ V(pe, [["__scopeId", "data-v-90db5921"]]), he = { class: "ti-answer-header" }, fe = { class: "ti-answer-icon" }, ge = { key: 0 }, we = { key: 1 }, ye = { class: "ti-answer-meta" }, ve = { class: "ti-confidence" }, be = { class: "ti-timestamp" }, Ae = { class: "ti-answer-text" }, _e = {
|
|
785
|
+
key: 0,
|
|
786
|
+
class: "ti-approximate-notice"
|
|
787
|
+
}, $e = {
|
|
788
|
+
key: 1,
|
|
789
|
+
class: "ti-reason"
|
|
790
|
+
}, ke = {
|
|
791
|
+
key: 2,
|
|
792
|
+
class: "ti-supporting-data"
|
|
793
|
+
}, Se = {
|
|
794
|
+
key: 0,
|
|
795
|
+
class: "ti-supporting-content"
|
|
796
|
+
}, De = {
|
|
797
|
+
key: 0,
|
|
798
|
+
class: "ti-aggregates"
|
|
799
|
+
}, Ce = {
|
|
800
|
+
key: 1,
|
|
801
|
+
class: "ti-rows"
|
|
802
|
+
}, Te = { class: "ti-table-wrapper" }, xe = { class: "ti-table" }, qe = /* @__PURE__ */ F({
|
|
803
|
+
__name: "AnswerDisplay",
|
|
804
|
+
props: {
|
|
805
|
+
answer: {}
|
|
806
|
+
},
|
|
807
|
+
setup(l) {
|
|
808
|
+
const n = C(!1);
|
|
809
|
+
function a(e) {
|
|
810
|
+
return new Date(e).toLocaleTimeString();
|
|
811
|
+
}
|
|
812
|
+
return (e, t) => (p(), d("div", {
|
|
813
|
+
class: X(["ti-answer-display", { "ti-cannot-answer": e.answer.cannotAnswer }])
|
|
814
|
+
}, [
|
|
815
|
+
m("div", he, [
|
|
816
|
+
m("div", fe, [
|
|
817
|
+
e.answer.cannotAnswer ? (p(), d("span", we, "⚠️")) : (p(), d("span", ge, "💡"))
|
|
818
|
+
]),
|
|
819
|
+
m("div", ye, [
|
|
820
|
+
m("div", ve, " Confidence: " + v(Math.round(e.answer.confidence * 100)) + "% ", 1),
|
|
821
|
+
m("div", be, v(a(e.answer.timestamp)), 1)
|
|
822
|
+
])
|
|
823
|
+
]),
|
|
824
|
+
m("div", Ae, v(e.answer.text), 1),
|
|
825
|
+
e.answer.isApproximate ? (p(), d("div", _e, " ℹ️ This answer is based on sampled data and may be approximate. ")) : T("", !0),
|
|
826
|
+
e.answer.reason && e.answer.cannotAnswer ? (p(), d("div", $e, [
|
|
827
|
+
t[1] || (t[1] = m("strong", null, "Reason:", -1)),
|
|
828
|
+
Z(" " + v(e.answer.reason), 1)
|
|
829
|
+
])) : T("", !0),
|
|
830
|
+
e.answer.supportingData ? (p(), d("div", ke, [
|
|
831
|
+
m("button", {
|
|
832
|
+
class: "ti-toggle-btn",
|
|
833
|
+
onClick: t[0] || (t[0] = (s) => n.value = !n.value)
|
|
834
|
+
}, v(n.value ? "▼" : "▶") + " Supporting Data ", 1),
|
|
835
|
+
n.value ? (p(), d("div", Se, [
|
|
836
|
+
e.answer.supportingData.aggregates ? (p(), d("div", De, [
|
|
837
|
+
t[2] || (t[2] = m("h4", null, "Aggregates:", -1)),
|
|
838
|
+
m("pre", null, v(JSON.stringify(e.answer.supportingData.aggregates, null, 2)), 1)
|
|
839
|
+
])) : T("", !0),
|
|
840
|
+
e.answer.supportingData.rows && e.answer.supportingData.rows.length > 0 ? (p(), d("div", Ce, [
|
|
841
|
+
m("h4", null, "Sample Rows (" + v(e.answer.supportingData.rows.length) + "):", 1),
|
|
842
|
+
m("div", Te, [
|
|
843
|
+
m("table", xe, [
|
|
844
|
+
m("thead", null, [
|
|
845
|
+
m("tr", null, [
|
|
846
|
+
(p(!0), d(O, null, Q(Object.keys(e.answer.supportingData.rows[0]), (s, r) => (p(), d("th", { key: r }, v(s), 1))), 128))
|
|
847
|
+
])
|
|
848
|
+
]),
|
|
849
|
+
m("tbody", null, [
|
|
850
|
+
(p(!0), d(O, null, Q(e.answer.supportingData.rows.slice(0, 5), (s, r) => (p(), d("tr", { key: r }, [
|
|
851
|
+
(p(!0), d(O, null, Q(Object.keys(s), (o, i) => (p(), d("td", { key: i }, v(s[o]), 1))), 128))
|
|
852
|
+
]))), 128))
|
|
853
|
+
])
|
|
854
|
+
])
|
|
855
|
+
])
|
|
856
|
+
])) : T("", !0)
|
|
857
|
+
])) : T("", !0)
|
|
858
|
+
])) : T("", !0)
|
|
859
|
+
], 2));
|
|
860
|
+
}
|
|
861
|
+
}), Re = /* @__PURE__ */ V(qe, [["__scopeId", "data-v-d1aaae1d"]]), Ee = { class: "ti-question-history" }, Ie = { class: "ti-history-header" }, Ne = {
|
|
862
|
+
key: 0,
|
|
863
|
+
class: "ti-empty-state"
|
|
864
|
+
}, Me = {
|
|
865
|
+
key: 1,
|
|
866
|
+
class: "ti-history-list"
|
|
867
|
+
}, Oe = ["onClick"], Qe = { class: "ti-question-header" }, ze = { class: "ti-question-number" }, Fe = { class: "ti-question-time" }, Ve = { class: "ti-question-text" }, je = {
|
|
868
|
+
key: 0,
|
|
869
|
+
class: "ti-question-context"
|
|
870
|
+
}, Le = /* @__PURE__ */ F({
|
|
871
|
+
__name: "QuestionHistory",
|
|
872
|
+
props: {
|
|
873
|
+
questions: {}
|
|
874
|
+
},
|
|
875
|
+
emits: ["clear", "select"],
|
|
876
|
+
setup(l, { emit: n }) {
|
|
877
|
+
const a = l, e = ee(() => [...a.questions].reverse());
|
|
878
|
+
function t(s) {
|
|
879
|
+
const r = new Date(s), i = (/* @__PURE__ */ new Date()).getTime() - r.getTime(), u = Math.floor(i / 6e4), g = Math.floor(i / 36e5), h = Math.floor(i / 864e5);
|
|
880
|
+
return u < 1 ? "Just now" : u < 60 ? `${u}m ago` : g < 24 ? `${g}h ago` : `${h}d ago`;
|
|
881
|
+
}
|
|
882
|
+
return (s, r) => (p(), d("div", Ee, [
|
|
883
|
+
m("div", Ie, [
|
|
884
|
+
r[1] || (r[1] = m("h3", null, "Question History", -1)),
|
|
885
|
+
s.questions.length > 0 ? (p(), d("button", {
|
|
886
|
+
key: 0,
|
|
887
|
+
class: "ti-clear-btn",
|
|
888
|
+
onClick: r[0] || (r[0] = (o) => s.$emit("clear"))
|
|
889
|
+
}, " Clear History ")) : T("", !0)
|
|
890
|
+
]),
|
|
891
|
+
s.questions.length === 0 ? (p(), d("div", Ne, r[2] || (r[2] = [
|
|
892
|
+
m("div", { class: "ti-empty-icon" }, "💬", -1),
|
|
893
|
+
m("p", null, "No questions asked yet", -1),
|
|
894
|
+
m("p", { class: "ti-empty-hint" }, "Ask a question about your data to get started", -1)
|
|
895
|
+
]))) : (p(), d("div", Me, [
|
|
896
|
+
(p(!0), d(O, null, Q(e.value, (o, i) => (p(), d("div", {
|
|
897
|
+
key: o.id,
|
|
898
|
+
class: "ti-history-item",
|
|
899
|
+
onClick: (u) => s.$emit("select", o)
|
|
900
|
+
}, [
|
|
901
|
+
m("div", Qe, [
|
|
902
|
+
m("span", ze, "#" + v(s.questions.length - i), 1),
|
|
903
|
+
m("span", Fe, v(t(o.timestamp)), 1)
|
|
904
|
+
]),
|
|
905
|
+
m("div", Ve, v(o.text), 1),
|
|
906
|
+
o.context ? (p(), d("div", je, v(o.context.rowCount) + " rows ", 1)) : T("", !0)
|
|
907
|
+
], 8, Oe))), 128))
|
|
908
|
+
]))
|
|
909
|
+
]));
|
|
910
|
+
}
|
|
911
|
+
}), Je = /* @__PURE__ */ V(Le, [["__scopeId", "data-v-c66393d9"]]);
|
|
299
912
|
export {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
913
|
+
Re as AnswerDisplay,
|
|
914
|
+
P as QAEngine,
|
|
915
|
+
Je as QuestionHistory,
|
|
916
|
+
He as QuestionInput,
|
|
917
|
+
oe as TabularIntelligence,
|
|
918
|
+
H as calculateStats,
|
|
919
|
+
te as detectAnomalies,
|
|
920
|
+
ne as extractFromDOM,
|
|
921
|
+
B as inferColumnType,
|
|
922
|
+
I as inferSchema,
|
|
923
|
+
se as normalizeVueData,
|
|
924
|
+
Be as useTabularIntelligence
|
|
306
925
|
};
|
|
307
926
|
//# sourceMappingURL=index.mjs.map
|